1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

トレンドスキャン法を使ってみよう【アセットマネージャーのためのファイナンス機械学習】

Last updated at Posted at 2025-03-12

トレンドスキャン法について

トレンドスキャン法は「アセットマネージャーのためのファイナンス機械学習 第5章: 金融データのラベリング」で紹介されているラベリング手法です。

株価等の時系列が下降トレンド、無トレンド、上昇トレンドのいずれかに応じて{-1, 0, 1}を付与したラベルを作成するというアイデアです。

def ols_t_value(close):
    # 線形トレンドのt値を計算する
    x = np.ones((close.shape[0], 2))
    x[:, 1] = np.arange(close.shape[0])
    ols = sm1.OLS(close, x).fit()
    return ols.tvalues[1]

このコードは株価終値を時系列のインデックスで、OLS回帰したときのt値を求めています。(関数名など一部変更しています。)

例えばこのようなデータを用意して

import yfinance as yf

data = yf.Ticker('SPY')
spy = data.histry(period='1y')
close = spy['Close'].iloc[-20].to_numpy()

print(ols_t_value(close))

上記のように実行すると、t値が出力されます。

このコードでは20日分の終値のt値を出力していますが、期間を変えれば結果も変わります。そこで、t値の絶対値が大きくなる期間を探索するために、期間を可変するコードを考えます。

def get_bins_from_trend(molecule, close, span):
    """
    線形トレンドのt値の符号からラベルを作成
    入力:
    - molecule: ラベル付けしたい観測値のインデックス
    - close: 終値(時系列)
    - span: 探索する期間の範囲[開始, 終了+1, 間隔]
    出力: 
    - t1: 発見されたトレンドの終了時点
    - t_val: 推定トレンド回帰係数のt値
    - bin: トレンドの符号
    """
    out = pd.DataFrame(index=molecule, columns=['t1', 't_val', 'bin'])
    hrzns = range(*span)

    for dt0 in molecule:
        df0 = pd.Series(dtype=float)

        for horizon in hrzns:
            dt1 = dt0 + pd.Timedelta(days=horizon)
            if dt1 > close.index[-1]:
                break
            df_segment = close.loc[dt0:dt1]
            t_val = ols_t_value(df_segment.values)
            df0.loc[dt1] = t_val

        if not df0.empty:
            t1 = df0.abs().idxmax()
            out.loc[dt0, ['t1', 't_val', 'bin']] = [t1, df0[t1], np.sign(df0[t1])]

    out['t1'] = pd.to_datetime(out['t1'])
    out['bin'] = pd.to_numeric(out['bin'], downcast='signed')

    return out.dropna(subset=['bin'])

※コードは変更しています。元のコードは書籍を参考にしてください。

t値の絶対値が最も高くなる期間を探索して、①探索期間、②t値、③トレンドの符号、の3つ列を含んだデータフレームを返します。このデータがルックフォワード期間の中で最も有意なトレンドを示しており、予測モデルのターゲットとなります。

先ほどyfinanceで取得したSPYのデータで試してみましょう。

close = spy['Close']

bins_df = get_bins_from_trend(close.index, close, [3,10,1])

image.png

bins_dfの中身は元データのインデックス(datetime)を維持したまま、ルックフォワードのトレンド情報が入っています。

plt.scatter(bins_df.index, close.loc[bins_df.index],
            c=bins_df['bin'], cmap='viridis')
plt.colorbar()
plt.title('Trend Labelling')
plt.xlabel('Time Index')
plt.ylabel('Close')
plt.show()

image.png

これで各終値時点でのルックフォワード期間のトレンドがラベリングできました。

書籍と同様にt値も可視化してみましょう。

plt.scatter(bins_df.index, close.loc[bins_df.index],
            c=bins_df['t_val'], cmap='viridis')
plt.colorbar()
plt.title('t-value')
plt.xlabel('Time Index')
plt.ylabel('Price')
plt.show()

image.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?