2025.01.10

13F filingで大口投資家の動きを分析してみる

はじめに

グループ研究開発本部・AI研究開発室のS.Sです。
前回・前々回とChatGPTに金融データ分析を行わせる記事を書いてきているので、今回もその関連で13F filingを通して米国株の保有状況を分析し、大口の機関投資家の動きを追ってみたいと思います。
今回の記事では手動の分析がメインとなります。

13F filingとは?

  • 誰が提出するのか?
    • SEC登録の投資運用会社で、少なくとも1億ドル以上の資産を管理している機関投資家が対象
  • 何を報告するのか?
    • 保有株式の詳細(発行体、銘柄、保有株数)
      • アメリカの株式や一部の外国株式、オプション、ETF(上場投資信託)などが対象
    • 銘柄の市場価値
  • 提出期限
    • 四半期ごとに提出が義務付けられており、四半期終了から45日以内に提出される

分析対象の選定

今回は運用規模が大きくヘッジファンドとして有名なRenaissance Technologiesの保有株式を分析してみることにします。(wikipediaより引用)

データの取得

13F filingの情報は公式にはEDGARデータベースで過去まで遡って取得することができますが、分析がしやすいフォーマットに加工するまでが大変なので、加工済みのデータをcsv形式で配布しているサイト13f.infoからデータを取得します。

今回のスコープは傾向を把握するための簡単な分析なので、データ期間は約2年(2013 4Q ~ 2015 4Q)とします。

例えばReneissanceの2014 1Qの保有リストトップは以下のようになっています。
大抵の場合は幅広い銘柄に分散して投資をしていることがほとんどです。

環境セットアップ

分析の前に今回取得した保有状況データと株価データをデータフレームに読み込んでおきます。

import pandas as pd
import numpy as np

df_stock = pd.read_csv("./stock_sp500_20220623.csv")
df_const = pd.read_csv("./constituents_csv.csv")
df_stock["Date"] = df_stock["Date"].pipe(pd.to_datetime)

df_stock_1d = df_stock.set_index(["Date"]).pct_change()


df_13f = pd.concat([pd.read_csv(fn).assign(Date=pd.Series([fn]).str.extract("Q(\d+) (\d+)")\
.pipe(lambda df: pd.to_datetime(df.iloc[0, 1], format="%Y") + pd.offsets.QuarterEnd(int(df.iloc[0, 0])))) for fn in sorted(glob.glob("Renaissance*.csv"))])\
.assign(Date=lambda x: x["Date"] + pd.offsets.QuarterEnd(-1))\
.sort_values(["Date"])

検証1 大口投資家と同一タイミングで取引した場合

13F filingは前Qの保有状況がQ末から約45日後に公表されますが、保有銘柄が事前にわかっていた場合のパフォーマンスをまずは見てみましょう。
分析を簡単にするために、以下のようなコードを実行して、保有額でTOP25の銘柄だけをLongした場合のパフォーマンスをチェックします。

df_sel = df_13f.assign(holding_pct=lambda x: x["%"].str.extract("([0-9.]+)%").squeeze())\
.assign(rk=lambda x: x.groupby(["Date"])["holding_pct"].rank(ascending=False, method="first"))\
.loc[lambda x: x["rk"] <= 25]

qs.reports.full(df_stock_1d.stack().rename("ret")\
.rename_axis(["Date", "col"]).reset_index()\
.pipe(lambda df: pd.merge_asof(df, df_sel.assign(col=lambda x: x["Sym"].str.lower()), on="Date", by="col", tolerance=pd.Timedelta("90 days")))\
.dropna(subset=["Sym"])\
.groupby(["Date"])["ret"].mean())

結果は次のようになりました。
株式インデックスのパフォーマンスも比較的良かった時期ではありますが、保有銘柄と同一の取引をした場合は安定性の指標であるSharpe Ratioが高い値を示しています。

検証2 大口投資家の保有情報公表後に遅れて同一銘柄を取引した場合

それでは保有銘柄の状況が公表されてから、後追いで同一銘柄を取引した場合のパフォーマンスはどうなるでしょうか。
以下のようなコードで試算を行うことができます。

qs.reports.full(df_stock_1d.stack().rename("ret")\
.rename_axis(["Date", "col"]).reset_index()\
.pipe(lambda df: pd.merge_asof(df, df_sel.assign(col=lambda x: x["Sym"].str.lower(), Date=lambda x: x["Date"] + pd.offsets.QuarterEnd(1) + pd.offsets.Day(45)), on="Date", by="col", tolerance=pd.Timedelta("90 days")))\
.dropna(subset=["Sym"])\
.groupby(["Date"])["ret"].mean())

こちらもそこそこの数字となっており、機関投資家の取引している銘柄を参考に取引するという戦略も悪くはなさそうです。

まとめ

13F filingを通して大口投資家の動きを追ってみると、公表タイミングの遅れを差し引いても判断材料として多少は参考になりそうなことがわかりました。
今回は2年間のみでの簡単な検証なので確たることは言えませんが、機関投資家がどのような基準で銘柄を選んだのかまで含めて保有銘柄を分析していくことで、投資戦略を考えるヒントにはなりそうです。

最後に

グループ研究開発本部 AI研究開発室では、データサイエンティスト/機械学習エンジニアを募集しています。ビッグデータの解析業務などAI研究開発室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。皆さんのご応募をお待ちしています。

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ

関連記事