1.はじめに
どうも、趣味でデータ分析している猫背なエンジニアです。
今回は、だいぶ前に番外編で中途半端になっていたグランビルの法則を完成させましたので、兆しシリーズとして進めて記録したいと思います。
2. 全体ロジック
■ 概要
前回の記事ではデータ収集ロジックを強化しました。具体的には、ハンドコーディングで収集していた銘柄データをpythonロジック上で銘柄更新と銘柄データ収集するようにしました。
■ システム構成
例のごとくスクリーニング1号機内にグランビルの法則を付与したロジックを追加します。
ロジック的にはすごく簡単で、デッドクロス抽出と同じ方法のものを実装します。1番最初の記事から追っている人はもうお分かりかと思いますが、本スクリーニング1号機の位置付けとしては大きな石をはけるためのふるい部分になると思っても過言でないです。どれだけ、大きな石をはけることができるかが期待です。
3. グランビルの法則実装(スクリーニング1号機)
■ グランビルの法則
「グランビルの法則 (Granville’s Rule)」は、米国の投資アナリスト ジョセフ・E・グランビル が考案した、移動平均線と株価の関係から売買のタイミングを判断する手法です。
基本の考え方としては以下3つからなっています。
1.移動平均線(MA)は株価のトレンドを示す指標。
2.株価とMAの位置関係、そしてMAの傾きから売買シグナルを読み取る。
3.「上昇局面で買い」「下降局面で売り」を4パターンずつ、合計 8つのルール で整理。
■ コーディング
実際にグランビルの法則を実装しました。基本的には番外編で設計した際のソースコードを流用していますが、outputが一部変更になりました。
番外編の際のoutputとしては買いシグナルと売りシグナルをデータフレームに上書きし、データフレームをreturnとして返却していました。しかし、データフレーム自体は不要だったので、その場でスクリーニングして分別しました。
グランビルの法則には説明の通り、合計8パターンがあるのですが、購入フラグとして、「買い①:下から上抜け」と「買い②:押し目」を通過させるロジックにしました。
def screen_granville(df):
df = df.copy()
df['MA'] = df['Close'].rolling(window=25).mean()
df['Granville_Signal'] = np.nan # 新しい列に格納
for i in range(1, len(df)):
price = df['Close'].iloc[i]
prev_price = df['Close'].iloc[i-1]
ma = df['MA'].iloc[i]
prev_ma = df['MA'].iloc[i-1]
# --- 買いシグナル ---
if prev_price < prev_ma and price > ma:
#"買い①: 下から上抜け"
df.at[i, 'Granville_Signal'] = True
elif price > ma and prev_price > prev_ma and price < ma * 1.01:
#"買い②: 押し目"
df.at[i, 'Granville_Signal'] = True
elif prev_ma < ma and price < ma:
#"買い③: 一時的な割り込み"
df.at[i, 'Granville_Signal'] = False
elif price < ma * 0.95:
#"買い④: 乖離しすぎ"
df.at[i, 'Granville_Signal'] = False
# --- 売りシグナル ---
elif prev_price > prev_ma and price < ma:
#"売り⑤: 上から下抜け"
df.at[i, 'Granville_Signal'] = False
elif price < ma and prev_price < prev_ma and price > ma * 0.99:
#"売り⑥: 戻り売り"
df.at[i, 'Granville_Signal'] = False
elif prev_ma > ma and price > ma:
#"売り⑦: 一時的な上抜け"
df.at[i, 'Granville_Signal'] = False
elif price > ma * 1.05:
#"売り⑧: 乖離しすぎ"
df.at[i, 'Granville_Signal'] = False
# --- 買いフラグ管理 ---
Granville_flag = False
for idx, row in df.iterrows():
if row['Granville_Signal'] == True:
Granville_flag = True
return Granville_flag
■ 実行結果
成功はしているもののデッドクロス抽出をした時とあまり変わらない量になっているような気もします。
実際のログも取ってみたので掲載します。デッドクロス抽出で多くはふるいにかけられているみたいですが、グランビルでも数銘柄はふるいにかけられていることがわかりました。
4.おわりに
今回は兆しシリーズのKK-FinancialEaterの1号機にグランビルの法則を追加しました。結果としては、微妙なところではありますが、一応デッドクロスで逃した銘柄をグランビルでキャッチしている感じという結果が出たので、一旦は成功かなと思います。
次回も1号機にロジックを追加していきたいと思っていますが、がっつりスクリーニングしてくれそうなロジックを見つけるには、まだまだ長そうですね....。
📈 兆しシリーズ
■ 原点(KK-Adam)
■ KK-FinancialEater
〇プロトタイプ編
〇収集器強化編
〇番外編
参考文献