Yamamotoの日記

Yale SOM MBA、金融工学、技術関係の記事を書きたいです

Quantpedia記事翻訳:Man vs. Machine: Stock Analysis

基本情報

Authors

Sean Cao, Wei Jiang, Junbo L. Wang and Baozhong Yang

Link

papers.ssrn.com quantpedia.com

まえがき

近年、機械学習ベースの取引戦術や市場分析が増えている。しかし、機械が我々に取って代わることは可能なのだろうか?アルゴリズムがbig dataを解釈するより高い能力を持っていることは疑いようもない。しかしながら、市場の常ではあるが、全てが合理的なわけではないのだ。Cao et al.(2021)は、株式市場におけるこのテーマを深く分析した。目標価格と利益予想は重要なポイントで、トレーダーや投資家が活用する数字である。最新の研究では、目標価格の予想能力に関して人間の能力と機械の能力を比較した。全体として、AI-based analysisは人間による分析を凌駕したが、ことはそう単純ではない。AIは多くのデータから学習することができるが、人間がそう簡単に取って代わられることはないだろう。人間の特殊性が価値を持つ場面が多くある。例えば、流動性が低く小さな会社や、アセットライトなビジネスモデルを持つ会社だ。さらに言えば、AIと人間は競合しているというよりは補完しあっている。

要旨・内容

  • 企業財務情報、定性開示情報、マクロ経済情報を学習したAI-analystは、価格予測に関してhuman-analystを凌駕し、超過リターンを生み出した。複雑な企業の分析において、透明性が高く量の多い情報が多次元に渡り手に入る場合はAI-analystの優位性が大きかった。
  • 重要な情報の解釈に制度的な知識(無形資産の内容等)が必要な場合はhuman-analystの方が優れていた。
  • human-analystがalternative dataや企業内AIへのアクセスを手に入れるにつれ、AIの優位性は時間と共に減衰していった。
  • AI-analystとHuman-analystを合わせた分析はAI-analystを大きく凌駕し、機械と人間の融合の可能性を見せた。
    f:id:maxonblog:20210808172104p:plain
    Figre-1

f:id:maxonblog:20210808172129p:plain
Figure-2

f:id:maxonblog:20210808172149p:plain
Figure-3

特筆すべきポイント

  • 使用したAIモデルは次の通り: Elastic-Net, Support Vector Machines, Random Forest, Gradient Boosting, and Long Short-Term Memory Neural Networks
  • Man + Machineのpredictionについては、合成方法の記載なし。

機械学習を使ってお買い得中古物件を探す ~分析編~

前回投稿からはや半年。GRE受験もなんとか終わり、少し時間ができました。

前回はこちら maxonblog.hatenablog.com

今回も、こちらの記事を参考に分析していきます。この記事のようにすぱっと理解できる示唆を出すのは、やはりなかなか難しいですねー。 www.analyze-world.com

今回は、Rを使って分析していきます。昔から使っていることもあり、PythonよりもRの方が統計分析に向いていると思います。僕が大学院で使ってた約10年前から、最近はtidyverseやらggplot2の出現によって書き方が全然変わってしまいましたが、思想・考え方はあまり変わらないように思います。データの形式や設定を意識せず、やりたい分析・処理をやらせてくれるという点で、すごく優れているように感じます。JavaPythonを比べてもそんな感じしますが、PythonとRを比べるとそんな感じがします。

生データの確認

さて、まずは、価格に一番効いてきそうなもの。。。部屋の大きさ(m2)と価格の関係性を確認します。

f:id:maxonblog:20210621213714p:plain
価格 vs 広さ
うーん。広ければ広いほど値段が高くなる。。。?(そらそうだ) 関係性がいまいちピンと来ませんね。広さが大きくなるにつれて価格の分散も大きくなっていくようですので、いわゆる分散不均一なデータということもわかります。

あと、築年数と価格の散布図も見てみます。

f:id:maxonblog:20210621215654p:plain
価格 vs 築年数
うーん。。。なんとも。。。築年数が増える(=古くなる)と、少し価格が安くなるように見える。。。かな?

グルーピングして回帰分析

最近マンションを買った友人から、「地域(区の下:品川区東五反田の"東五反田"部分)によって価格の分布が全然違う」とのコメントをいただいたので、地域ごとにグルーピングして"価格 ~ 広さ + 築年数"で重回帰分析をしてみます。 まずは多重共線性のチェックです。価格と広さに相関が強ければ、多重共線性によってうまいこと線形回帰ができないですからね!

f:id:maxonblog:20210621220304p:plain
広さ vs 築年数
お。いい感じです。

では、以下Rコードを使って、ばばばっと重回帰分析を行います(手抜き)。

result <- temp %>%
    group_nest(location) %>%
    mutate(fit = map(data, ~lm(price ~ size + age, data = .)),
           summary = map(fit, summary),
           DataNum = map_dbl(data, nrow),
           Alpha = map_dbl(fit, ~.$coefficients[1]),
           Beta_1 = map_dbl(fit, ~.$coefficients[2]),
           Beta_2 = map_dbl(fit, ~.$coefficients[3]),
           R2 = map_dbl(summary, ~.$r.squared))

これで、どれくらい説明できたのでしょうか?

f:id:maxonblog:20210621220837p:plain
R2の分布

おおお。結構説明できています。 今度は、データ数が多い順に地域を並べてみます。面倒なのでExcel職人の画像貼り付けで許してください。Beta_1は広さに対する係数、Beta_2は築年数に対する係数です。

f:id:maxonblog:20210621222513p:plain
データ数多い順20地域
きれいな分析結果になりましたねー。件数が多いと説明力も高いです。 南青山とか、1年で341万円も値下がりするんですね。。。恐ろしい。逆に新宿(新宿区新宿)は1年で12万円しか値下がりしないので、長く住むにはいいかもしれませんね(住むところなのか。。。?)。

結論と今後の課題

このデータを使って、地域・広さ・築年数がわかれば、6割程度の精度で価格を予測することができることがわかりました。参考にした記事みたいに、お得物件を提示できればよかったのですが、力付きました。。。 ということで、残課題は以下の通りです。MBA受験が一段落したら続きを書く予定なので、もしこのブログを読んでくれている人がいたら、僕のMBA受験がうまくいくことを祈っていてください。

残課題

  • 外れ値を除去する。10LDKとか変な値を持つデータも入っており、分析に悪影響を与えていそうなので削除しておきたいところ。
  • お得物件を探す。現状の情報でも、不当に安い物件は見つけられそうなので
  • サーバーで定期的にデータを取得し、時系列のデータを作成。割安な物件が出てきたらアラートを出す。
  • 地域差を説明する変数を探す。何らかの要素によって各係数の関係性が規定されていると思われるので、この変数を探す。人口とか港区からの距離とかが考えられるけど、区役所のサイトを探したりとか、地図データを作ったりととても大変。

ほな。

Quantpedia記事翻訳:Measuring Financial Investors Presence in Commodities

quantpedia.com

Authors

Zeno Adams, Solene Collot and Davide Rossi Measuring Financial Investor Presence through Term Structure Anomalies by Zeno Adams, Solene Collot, Davide Rossi :: SSRN

要旨

本稿では、商品先物の期間構造推定からの実データの乖離(=anomalies)を計測することで、financial investorsの存在を証明する。2004年~2014年の間、特に期近の限月についてfinancial investorによる価格の歪みが観測された。この分析手法は、他の方法よりも原油のvolatilityをうまく説明した。

f:id:maxonblog:20210621003031p:plain

特筆すべきポイント

  • Financial Investorsは、個人が購入するETFを商品先物市場に流すプレイヤーと年金基金等の運用者が多いため、Longポジションの傾向を持つ。いずれもIndexを模倣する傾向にあり、巨額のロールオーバーを行う。
  • このロールオーバーのタイミングで、期近のポジションに歪みが発生する。
  • 1ヶ月ごと、12ヶ月先までのポジションを分析対象として、3次自然スプライン補間によって期間構造を再現した。スプライン補間を使うことの利点は、期間構造を連続的に分析できること。
  • ロールオーバーによる乖離が生まれていることから、第一限月には売り圧力がかかり、第二限月には買い圧力がかかると考えられる。実際に、本稿における分析ではその傾向が見られた。青く色づけをした部分がfinancial investorの影響と考えられる。

機械学習を使ってお買い得中古物件を探す~前処理編~

前回はこちら maxonblog.hatenablog.com

前回同様、本日はこちらのサイトにアイデアを頂いて進めていきます。 www.analyze-world.com

データ読み込み&確認

まずはなにはともあれデータの読み込み、確認です。pandas便利ですね。

方法

Pandas:Seriesのattributionである、strを使っていきます。正規表現も使えます。列全体に対して処理を行うことができるので便利です。

  • split(x, expand) xを検索、ヒットしたらxで左右に分ける。expand=Trueとすると、複数列を持つDataFrameとしてくれます。expand=Falseとすると単列の中にすべて入れこまれます。逆に、どういう用途でどうやって使うんだろう。。。
  • replace(x,y) xを検索、yに入れ替えます。xに正規表現を使っています。正規表現()で囲んで使いましょう。
  • contains(x) xを含む行をindex(かな?)のSeriesで返します。DataFrameの列指定に入れ込むことで、xを含む行だけにすることができます。
  • extract(x) 各要素からxを検索して、matchしたものを各要素に返します。Seriesで返ってきます。
  • pandas.to_datetime() 文字列で記述された日付をdatetime型に変換します。
import pandas as pd
import datetime as dt
from pandas import DataFrame 
df = pd.read_csv("./Data/suumoData.csv", encoding="utf-8")
df.head()
name price location station size floor terrace construction
0 シャトレーイン東京・笹塚 770万円 東京都渋谷区笹塚1 京王線「笹塚」徒歩5分 14.52m2(4.39坪)(壁芯) ワンルーム - 1987年3月
1 高幡台住宅 26号棟 780万円 東京都日野市三沢 京王線高幡不動」徒歩11分 48.85m2(14.77坪)(壁芯) 2LDK 6m2 1970年7月
2 ライオンズマンション西日暮里北 880万円 東京都荒川区東尾久2-44-16 日暮里・舎人ライナー「赤土小学校前」徒歩3分 19.6m2(壁芯) 1K 3.36m2 1989年10月
3 ライオンズガーデン町田の丘 900万円 東京都町田市図師町 JR横浜線「町田」バス20分停歩3分 51.87m2(壁芯) 3LDK 7.41m2 1993年9月
4 武蔵小金井フラワーホーム 980万円 東京都小金井市緑町5 JR中央線「武蔵小金井」徒歩12分 26.22m2(壁芯) ワンルーム 7m2 1977年7月

データ整形

路線・駅名・駅までの距離

路線、駅名、徒歩時間を切り分けます。
"歩"、"「"といったところで切れるので、splitで分けた後replaceで不要な文字("」"以降、"分")を削除していきます。他の方法があったかな。最後に大元dfにくっつけることを忘れないようにしましょう。
尚、今更ながら、Jupyterだと、大元のデータを処理してしまうと微調整して再処理するとエラーを吐くので、input用変数とoutput用変数は分けるべきだったようです。
いらないデータはdropで削除し、最後にconcatでもとのデータ(df)にくっつけます。

df_split_1 = df["station"].str.split("歩", expand=True)
df_split_1 = pd.concat([df_split_1[0].str.split("「", expand=True), df_split_1[1]], axis=1)
df_split_1.columns = ["line", "station", "time"]
df_split_1["station"] = df_split_1["station"].str.replace("」(.)", "")  
df_split_1["time"] = df_split_1["time"].str.replace("分", "")
df.drop(['station'], axis=1, inplace=True)  
df = pd.concat((df, df_split_1),axis=1)
df.head()
name price location size floor terrace construction line station time
0 シャトレーイン東京・笹塚 770万円 東京都渋谷区笹塚1 14.52m2(4.39坪)(壁芯) ワンルーム - 1987年3月 京王線 笹塚 5
1 高幡台住宅 26号棟 780万円 東京都日野市三沢 48.85m2(14.77坪)(壁芯) 2LDK 6m2 1970年7月 京王線 高幡不動 11
2 ライオンズマンション西日暮里北 880万円 東京都荒川区東尾久2-44-16 19.6m2(壁芯) 1K 3.36m2 1989年10月 日暮里・舎人ライナー 赤土小学校前 3
3 ライオンズガーデン町田の丘 900万円 東京都町田市図師町 51.87m2(壁芯) 3LDK 7.41m2 1993年9月 JR横浜線 町田ス20分停 3
4 武蔵小金井フラワーホーム 980万円 東京都小金井市緑町5 26.22m2(壁芯) ワンルーム 7m2 1977年7月 JR中央線 武蔵小金井 12

住所を修正。東京23区内のみの分析にする。

本当は23区外も分析の対象外にしたかったのですが、規則性が薄そうで手間がかかりそうだったのでまずは東京23区を対象とすべく、"区"を含む行だけにして処理を進めます。エリアまでほしかったので、区以降の住所の中の地域名をaddressとして残します。
r"([^\d]*)"は、正規表現で数字「以外」を抜き出しています。

df = df[df["location"].str.contains("区")]
temp_1 = df["location"].str.replace("東京都", "").str.split("区", expand=True)
temp_1.columns = ["ku", "address"]
temp_1 = temp_1["address"].str.extract(r"([^\d]*)")
df = pd.concat((df, temp_1), axis=1)
df.head()
name price location size floor terrace construction line station time address
0 シャトレーイン東京・笹塚 770万円 東京都渋谷区笹塚1 14.52m2(4.39坪)(壁芯) ワンルーム - 1987年3月 京王線 笹塚 5 笹塚
2 ライオンズマンション西日暮里北 880万円 東京都荒川区東尾久2-44-16 19.6m2(壁芯) 1K 3.36m2 1989年10月 日暮里・舎人ライナー 赤土小学校前 3 東尾久
8 プレール新中野 1280万円 東京都中野区中央4 17.45m2(5.27坪)(壁芯) 1K 2.5m2 1990年3月 東京メトロ丸ノ内線 新中野 3 中央
9 ニュー荻窪フラワーホーム 1280万円 東京都杉並区桃井3 31.44m2(9.51坪)(壁芯) 1DK 5.51m2 1972年2月 JR中央線 荻窪 18 桃井
10 ライオンズマンション西日暮里北 1380万円 東京都荒川区東尾久2 44.62m2(壁芯) 2DK 11.01m2 1989年10月 日暮里・舎人ライナー 赤土小学校前 3 東尾久

広さのm2以降を削除する

数字として扱いたいので、いらない文字は削除しましょう。

df["size"] = df["size"].replace("m2(.*)", "", regex=True)
df["terrace"] = df["terrace"].replace("m2(.*)", "", regex=True)

価格を使えるデータに整形する

注釈とか幅をもたせたデータ(~、・、※を含むデータ)は削除し、x億円以上の部分は10,000かけて単位をずらして万円とつなげる、その後、intに変換します。

df = df[~df["price"].str.contains("~|〜|・|〜|~|※")]
df_split_1 = pd.DataFrame(df["price"].str.extract('(.*億)').str.replace("億", "").fillna(0).astype(int) * 10000)
df_split_2 = pd.DataFrame(df["price"].str.replace('(.*億)', "").str.replace("万|円", "").str.extract(r"(\d+)").fillna(0).astype(int))
df["price"] = df_split_1 + df_split_2
df.head()
name price location size floor terrace construction line station time address
0 シャトレーイン東京・笹塚 770 東京都渋谷区笹塚1 14.52 ワンルーム - 1987年3月 京王線 笹塚 5 笹塚
2 ライオンズマンション西日暮里北 880 東京都荒川区東尾久2-44-16 19.6 1K 3.36 1989年10月 日暮里・舎人ライナー 赤土小学校前 3 東尾久
8 プレール新中野 1280 東京都中野区中央4 17.45 1K 2.5 1990年3月 東京メトロ丸ノ内線 新中野 3 中央
9 ニュー荻窪フラワーホーム 1280 東京都杉並区桃井3 31.44 1DK 5.51 1972年2月 JR中央線 荻窪 18 桃井
10 ライオンズマンション西日暮里北 1380 東京都荒川区東尾久2 44.62 2DK 11.01 1989年10月 日暮里・舎人ライナー 赤土小学校前 3 東尾久

建築日を使えるデータにする

まずは建築日(完工日?)を日付データに変換します。年月までの情報しかないので、各月の1日に完工したと設定し、日付データとします。
次に、完工日からデータ取得日までの日数のデータとするため、引き算。日付のまま保持するより、int型に変換したほうがよかったかな、と思いはじめました。

df["construction"] = pd.to_datetime(df["construction"] + "1日", format="%Y年%m月%d日")
temp_1 = pd.to_datetime(dt.date.today()) - df["construction"]
temp_1 = temp_1.rename("age")
df = pd.concat((df, temp_1), axis=1)
df.head()
name price location size floor terrace construction line station time address age
0 シャトレーイン東京・笹塚 770 東京都渋谷区笹塚1 14.52 ワンルーム - 1987-03-01 京王線 笹塚 5 笹塚 12401 days
2 ライオンズマンション西日暮里北 880 東京都荒川区東尾久2-44-16 19.6 1K 3.36 1989-10-01 日暮里・舎人ライナー 赤土小学校前 3 東尾久 11456 days
8 プレール新中野 1280 東京都中野区中央4 17.45 1K 2.5 1990-03-01 東京メトロ丸ノ内線 新中野 3 中央 11305 days
9 ニュー荻窪フラワーホーム 1280 東京都杉並区桃井3 31.44 1DK 5.51 1972-02-01 JR中央線 荻窪 18 桃井 17908 days
10 ライオンズマンション西日暮里北 1380 東京都荒川区東尾久2 44.62 2DK 11.01 1989-10-01 日暮里・舎人ライナー 赤土小学校前 3 東尾久 11456 days

Floor(部屋数)の修正

Floor(部屋数)を使えるデータに変換します。ここは割と工夫をした点です。2LDKとか3LDKとかだけでなく、11LDKとか、S(納戸)とか変なデータが多かったので、まずはどういうフレームワークで分析するか考えました。
結論として、Room、Living、Dining、Kitchen、Service、及び部屋数のデータを残すことに。手順は以下の通りです。

  1. 部屋数の数字をextract:2LDKの"2"の部分ですね。
  2. L、D、Kの数を数える。2つLivingがある部屋は、2LLDKという表記になっています。
  3. Sについては、"S"の前だけ抜き出して、その文字列に含む数字をSの数とします。+2S(納戸)とかいう不思議な表記になっているためです。
  4. 最後に、全部の部屋数を足した部屋数列を作成。

ついでに、今日の日付の情報も入れておきましょう。
これらを元のデータにくっつけておしまいです。

df = df.reset_index(drop=True)
temp_1 = pd.Series(df["floor"]).str.replace("(.*ワンルーム)", "1")
rldks: DataFrame = pd.DataFrame([
    temp_1.str.extract(r"(\d\d*)"),
    temp_1.str.count("L"),
    temp_1.str.count("D"),
    temp_1.str.count("K"),
    temp_1.str.extract(r"(\+.*S)").fillna("0").str.extract(r"(\d+)").fillna(1)],
    index=["room", "Living", "Dining", "Kitchen", "Service"]
    ).astype(int).T
temp2 = pd.DataFrame({"No.ofRooms": rldks.sum(axis=1)})
today = pd.Series([dt.date.today() for i in range(len(df))])
df = pd.concat((df, rldks, temp2,today), axis=1)
df.head()
name price location size floor terrace construction line station time ... Service No.ofRooms 0 room Living Dining Kitchen Service No.ofRooms 0
0 シャトレーイン東京・笹塚 770 東京都渋谷区笹塚1 14.52 ワンルーム - 1987-03-01 京王線 笹塚 5 ... 0 1 2021-02-11 1 0 0 0 0 1 2021-02-11
1 ライオンズマンション西日暮里北 880 東京都荒川区東尾久2-44-16 19.6 1K 3.36 1989-10-01 日暮里・舎人ライナー 赤土小学校前 3 ... 0 2 2021-02-11 1 0 0 1 0 2 2021-02-11
2 プレール新中野 1280 東京都中野区中央4 17.45 1K 2.5 1990-03-01 東京メトロ丸ノ内線 新中野 3 ... 0 2 2021-02-11 1 0 0 1 0 2 2021-02-11
3 ニュー荻窪フラワーホーム 1280 東京都杉並区桃井3 31.44 1DK 5.51 1972-02-01 JR中央線 荻窪 18 ... 0 3 2021-02-11 1 0 1 1 0 3 2021-02-11
4 ライオンズマンション西日暮里北 1380 東京都荒川区東尾久2 44.62 2DK 11.01 1989-10-01 日暮里・舎人ライナー 赤土小学校前 3 ... 0 4 2021-02-11 2 0 1 1 0 4 2021-02-11

5 rows × 26 columns

終わり

さて、次は楽しい分析です!Pythonだとデータ分析は難しいのでRでやるかなー。

df.head(5)
df.tail(5)
name price location size floor terrace construction line station time address age room Living Dining Kitchen Service No.ofRooms 0
17970 フォレセーヌ赤坂檜坂 24000 東京都港区赤坂6 88.13 2LDK 8.49 2016-01-01 東京メトロ日比谷線 六本木 6 赤坂 1868 days 2 1 1 1 0 5 2021-02-11
17971 パークコート青山ザ・タワー 25800 東京都港区南青山2 82.79 2LDK - 2017-12-01 東京メトロ銀座線 青山一丁目 3 南青山 1168 days 2 1 1 1 0 5 2021-02-11
17972 パークハウス多摩川 29000 東京都大田区下丸子4 307.68 1LDK 56.4 1993-02-01 東急多摩川線 鵜の木 7 下丸子 10237 days 1 1 1 1 0 4 2021-02-11
17973 ブランズ六本木ザ・レジデンス 30000 東京都港区六本木4 101.97 2LDK 5.22 2019-01-01 都営大江戸線 六本木 3 六本木 772 days 2 1 1 1 0 5 2021-02-11
17974 パークコート乃木坂ザ・タワー 33000 東京都港区南青山1 100.65 2LDK 11.42 2019-02-01 東京メトロ千代田線 乃木坂 2 南青山 741 days 2 1 1 1 0 5 2021-02-11

機械学習を使ってお買い得中古物件を探す~スクレイピング編~

www.analyze-world.com

こちらの記事に着想を得てやってみました.。元記事は賃貸物件を探しますが、僕は中古物件を探しています。 まずはSuumoのサイトからデータを取得します。Suumoのサイトにはスクレイピング禁止とは書いてなかったけど、問題あったら誰か教えて下さい。 巨大なデータになるのでCSVで保存したくない。。。データベースの勉強も必要ですね。

データがとても汚いので、前処理が大変そう。

家電3社・2019Q1決算

最近、わけあってSONYに興味があるので、ひとことコメント

SONY

グループとしてセンサーアンドイメージング(S&II)に力を入れていくことを明確に打ち出した。Third pointの喧嘩を前向きに買いにいく姿勢に笑う。Gaming & Entertainmentでキャッシュを稼ぎ、半導体関連・センサー関連につぎ込んでいく方針。金融分野も大きいが、上記分野に比べると注力は低い。ガバナンスを整えて、安定的にキャッシュを生んでくれるビジネスとして認識している模様。

Panasonic

セグメントごとの純利益が出ておらずわからないが、テレビは純利益が赤字らしい。減損か金融費用か?セグメントごとの純利益非開示もそうだが、この会社は本当に投資家を馬鹿にしている感じがする。売上高「前年比94%の減収」とか言っちゃうし(6%の減収との言い方が多い)。セグメント別のCF計算書も公開しておらず、どこに注力しているかわかりにくい。 イメージとしてはアプライアンス(エアコン)とライフソリューションズ(ライト・スマートホーム)で利益を出して、コネクテッドソリューションズ(メディア・プロセスオートメーション等)に力を入れて行く感じか? オートモーティブは電池の伸びが高いものの、売上高3,774億に対してOPが-100億円。中国自動車市場の悪化や製品サイクルの移行期による販売減をカバーできず、とのこと。 また、ポートフォリオ改革の進捗を見ると、トヨタとの協働等、オートモーティブに力を入れているように見える。EV化に伴う電池需要増の流れに乗ろうとしているな。

SHARP

前年同期比から減収減益。売価ダウンがでかい。スマートライフ、8K(テレビ)、ICT(通信、サービス)の3分野があり、セグメント別の売上高でいうと8Kが一番でかい。180, 260, 96。一方で営業利益は6.2, 6.2, 7.3と同レベル。利益率が高いのでICTにもっと力を入れていく感じか。

総論

これら3社については、自動運転車市場の発展に伴うセンサー、電池、通信の分野に大きく張っている印象。

CAPMは成り立つのか?

まとめ

市場indexから推定した個別株のβは、決定係数が低く信頼性が低い。日本に於いては、市場にある8割の個別株は決定係数が0.33以下。リターンをマーケットに対する超過リスクで説明するというCAPM理論は、少なくとも実証レベルでは成り立ってなさそうだ。

決定係数(R2)の分布

f:id:maxonblog:20190303221143p:plain
決定係数の分布

f:id:maxonblog:20190303221722p:plain
積分

東証1部上場企業の5 years, Monthly βを取ってみた。当社内では、決定係数が0.1未満のβは信頼性が低く、Valuation時のCoE推定には使えないとされているのだが、決定係数のボリュームゾーンは0.1以下で、累積でもほとんどの企業のβの決定係数は0.1未満だ。。。ほとんどのデータの信頼性が低いということになってしまう。。。笑

そもそもCAPMとは

投資家が期待するリターンは、マーケットの(超過)リターンで説明できるとする理論1である。 CAPMの前提2 は結構厳しい。これだけ厳しい前提を置いて初めて、個別株式のリターンをマーケットの超過リターンの一次式によって説明することができる。 * 全投資家はリスク回避的で期待効用の最大化を望む。(効用関数が上に凸、投資家は投資価値の期待値/分散だけを見て投資する) * 投資期間は1期だけ。 * 投資家はポートフォリオを構築可能 * 投資家は無リスク利子率で無制限に借入ができる。 * すべての投資家は同じ情報を持つ。 * 完全市場である。

結論

そもそも完全市場じゃないし、二期間で終わる経済じゃない。投資家は期待値と分散だけで投資内容を決めないし、すべての投資家がポートフォリオが組めるわけではない。そして完全市場じゃない。

こんなに成り立たない前提を持った理論をもとに、数百~数千億円単位の投資の意思決定をするなんて恐ろしいことだと思うが、日本ではこれが一般的なので、市場にはたくさんのミスプライシングがありそうだ。