#はじめに
株の買い時のシグナルとして、ゴールデンクロスというチャート上の現象が存在します。チャート分析の本には大体載っている手法ですが、実際に有効な手法なのでしょうか?本稿では、ゴールデンクロスを定義し、有効な買い時のシグナルか検討します。(注意:あくまで定義した範囲で有効かの議論であり、手法の批判を目的としたものではありません。そのため、参考にした金融に関するサイトのリンクは張っていません。また、プログラム及び分析結果の活用は自己責任でお願いします。)
【実施内容】
- ゴールデンクロスの定義と検出プログラムの作成
- ゴールデンクロスは買い時のシグナルかの検証
#ゴールデンクロスの定義
ゴールデンクロスとは、短期の移動平均が長期の移動平均を上回るときとされています(移動平均に関しては、 [Pythonで投資アルゴリズムを開発してみる 2](http://qiita.com/hiroshimoda/items/6337543ba3eb700d0aaa "移動平均の説明"))を参考にしてください)。まず、毎日の株価を終値に設定しました(正直、「始値」「終値」「高値」「低値」のどれがよいかわかりません)。次に、この平均する期間の長さを設定する必要があります。今回は短期平均を5日、長期平均を25日としました。最後に「上回った日」を前日は長期平均の方が高く、当日は短期平均の方が高い日としました。
#ゴールデンクロスの検出
ゴールデンクロスを検出するプログラムの説明をします。出力結果は以下のようになります。青い線が毎日の株価であり、赤い四角がゴールデンクロスを示しています(視認性向上のため、赤い四角のy値を株価にしています)。
プログラムの順番に説明をしていきます(まとめたソースはgoldencross_detection.pyとして、一番下に置きました)。最初の株価取得に関しては、Pythonで株価取得とローソク足チャート作成を見てください。
import datetime
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import pandas as pd
#期間の設定
start = datetime.datetime(2011, 1, 1)
end = datetime.datetime(2017, 5, 30)
#株価取得
df = web.DataReader('TM', 'google', start, end)
df = df.loc[:, ['Close']]
移動平均の計算には、pandas.rollingを用います。プログラムのとおり、windowsで平均する期間の長さを調整します。当然、平均をとるのは当日を最終日とた期間の平均です。移動平均では用いませんが、center=Trueにすることで、当日を中心日とした平均にすることもできます。
#平均する期間の設定
short_term = 5
long_term = 25
#期間平均の計算
df['av_short'] = df['Close'].rolling(window=short_term).mean()#短期平均
df['av_long'] = df['Close'].rolling(window=long_term).mean()#長期平均
ゴールデンクロスの検出を実施します。プログラムでは、列'golden_flag'にゴールデンクロスの日に当日の株価、当該日以外にNoneをいれています。
#ゴールデンクロスの検出
df['golden_flag'] = 0
current_flag=0
previous_flag=1
for i,price in df.iterrows():
if(price['av_short']>price['av_long']):
current_flag = 1
else:
current_flag = 0
if(current_flag*(1-previous_flag)):
df.loc[i,'golden_flag']=price['av_long']
else:
df.loc[i,'golden_flag']= None
previous_flag = current_flag
#図示
df.plot(style=['-'])
plt.scatter(x= df.index,y = df['golden_flag'],marker='s',color='red')
plt.show()
#ゴールデンクロス後の株価推移
次にゴールデンクロスの後に、株価が上昇しているかを見ていきます。ゴールデンクロス当日の株価を1.0として、1~20日後の株価をプロットしていきます。仮にゴールデンクロスが買い時のシグナルであれば、全体的に株価が上昇していくはずです。プログラム(transition_after_goldencross.py)に関してですが、重複内容が多いので3点だけ説明します。
1、DataFrame.indexに基づいた次の日
datetimeモジュールで日付を1日後に変換するには、"day+1"ではエラーになるので、"day+datetime.timedelta(days=1)"とする必要があります。さらに、次の日に株価が存在しているとは限らないので、DataFrameのindexの入っている次の日を返す関数を下のように作りました。
def GetIndexNextDay(df,day):
for p in range(1,10)://10は適当
if((day+datetime.timedelta(days=p)) in df.index):
next_day = day+datetime.timedelta(days=p)
return next_day
2、ListからDataFrameへ
株価推移をListで保存して、DataFrameに変換後にプロットしました。最初から、DataFrameでできるだろうと思いながらも、なんとなくこういう形にしました。
3、図示の工夫
2011年から2017年のゴールデンクロス全ての推移だけを見てもよくわかないので、平均を計算して、目立つように(赤色)プロットしました。
以上、3つの事項を踏まえた結果が以下になります。黒色の線が各ゴールデンクロス検出の日からの株価の推移です。検出日の株価を1.0としているので、day=0では、全て1.0になっています。赤色の線は全黒色の線の平均です。正直、平均的に上がっているようには見えません。
#終わりに
ゴールデンクロスは、個人的に買い時のシグナルには見えませんでした。ただし、よく見ると多くのサイト、本で偽のゴールデンクロスがあるので注意しなさいと書いていました。見分け方も書いていましたが、感覚的に書かれており、簡単に実装できなさそうので、今回はここで終わりにしておきます。
#参考サイト
pandasのDataFrameのインデックスでの要素参照と代入
https://hydrocul.github.io/wiki/numpy/pandas-dataframe-ref-index.html
matplotlib.markers
http://matplotlib.org/api/markers_api.html#module-matplotlib.markers
Dataframeの代入方法
http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
Pythonで投資アルゴリズムを開発してみる 2
http://qiita.com/hiroshimoda/items/6337543ba3eb700d0aaa
#ソースコード
import datetime
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import pandas as pd
#期間の設定
start = datetime.datetime(2011, 1, 1)
end = datetime.datetime(2017, 5, 30)
#株価取得
df = web.DataReader('TM', 'google', start, end)
df = df.loc[:, ['Close']]
#平均する期間の設定
short_term = 5
long_term = 25
#期間平均の計算
df['av_short'] = df['Close'].rolling(window=short_term).mean()#短期平均
df['av_long'] = df['Close'].rolling(window=long_term).mean()#長期平均
#ゴールデンクロスの検出
df['golden_flag'] = 0
current_flag=0
previous_flag=1
for i,price in df.iterrows():
if(price['av_short']>price['av_long']):
current_flag = 1
else:
current_flag = 0
if(current_flag*(1-previous_flag)):
df.loc[i,'golden_flag']=price['av_long']
else:
df.loc[i,'golden_flag']= None
previous_flag = current_flag
#図示
df.plot(style=['-'])
plt.scatter(x= df.index,y = df['golden_flag'],marker='s',color='red')
plt.show()
import datetime
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import pandas as pd
def GetIndexNextDay(df,day):
for p in range(1,10):
if((day+datetime.timedelta(days=p)) in df.index):
next_day = day+datetime.timedelta(days=p)
return next_day
#株価取得
start = datetime.datetime(2011, 1, 1)#株価取得開始日
end = datetime.datetime(2017, 5, 30)#株価取得終了日
df = web.DataReader('TM', 'google', start, end)
df = df.loc[:, ['Close']]
#期間平均の計算
short_term = 5#短期平均の長さ
long_term = 25#長期平均の長さ
df['av_short'] = df['Close'].rolling(window=short_term).mean()#短期平均の計算
df['av_long'] = df['Close'].rolling(window=long_term).mean()#長期平均の計算
#ゴールデンクロスの検出
golden_day = []
df['golden_flag'] = 0
current_flag=0
previous_flag=1
for i,price in df.iterrows():
if(price['av_short']>price['av_long']):
current_flag = 1
else:
current_flag = 0
if(current_flag*(1-previous_flag)):
df.loc[i,'golden_flag']=price['Close']
golden_day.append(i)
else:
df.loc[i,'golden_flag']= None
previous_flag = current_flag
#推移の保存
transitions = []
for day in golden_day:
day_transition = [df['Close'][day]/df['Close'][day]]
next_day = day
for term in range(1,20):
next_day = GetIndexNextDay(df,next_day)
day_transition.append(df['Close'][next_day]/df['Close'][day])
transitions.append(day_transition)
#図示
df2 = (pd.DataFrame(ss)).T
df_mean = ((df2.T).mean()).T
df2.plot(legend=False,color = 'black')
df_mean.plot(color = 'red',lw=5)
plt.show()