20
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Pythonで株価チャートのゴールデンクロスを検出

Posted at

#はじめに
株の買い時のシグナルとして、ゴールデンクロスというチャート上の現象が存在します。チャート分析の本には大体載っている手法ですが、実際に有効な手法なのでしょうか?本稿では、ゴールデンクロスを定義し、有効な買い時のシグナルか検討します。(注意:あくまで定義した範囲で有効かの議論であり、手法の批判を目的としたものではありません。そのため、参考にした金融に関するサイトのリンクは張っていません。また、プログラム及び分析結果の活用は自己責任でお願いします。)
【実施内容】

  • ゴールデンクロスの定義と検出プログラムの作成
  • ゴールデンクロスは買い時のシグナルかの検証

#ゴールデンクロスの定義
 ゴールデンクロスとは、短期の移動平均が長期の移動平均を上回るときとされています(移動平均に関しては、 [Pythonで投資アルゴリズムを開発してみる 2](http://qiita.com/hiroshimoda/items/6337543ba3eb700d0aaa "移動平均の説明"))を参考にしてください)。まず、毎日の株価を終値に設定しました(正直、「始値」「終値」「高値」「低値」のどれがよいかわかりません)。次に、この平均する期間の長さを設定する必要があります。今回は短期平均を5日、長期平均を25日としました。最後に「上回った日」を前日は長期平均の方が高く、当日は短期平均の方が高い日としました。

#ゴールデンクロスの検出
 ゴールデンクロスを検出するプログラムの説明をします。出力結果は以下のようになります。青い線が毎日の株価であり、赤い四角がゴールデンクロスを示しています(視認性向上のため、赤い四角のy値を株価にしています)。
goldencross_detection.png

プログラムの順番に説明をしていきます(まとめたソースは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になっています。赤色の線は全黒色の線の平均です。正直、平均的に上がっているようには見えません。
transition_after_goldencross.png

#終わりに
 ゴールデンクロスは、個人的に買い時のシグナルには見えませんでした。ただし、よく見ると多くのサイト、本で偽のゴールデンクロスがあるので注意しなさいと書いていました。見分け方も書いていましたが、感覚的に書かれており、簡単に実装できなさそうので、今回はここで終わりにしておきます。

#参考サイト
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

#ソースコード

goldencross_detection.py
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()
transition_after_goldencross.py
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()
20
29
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
20
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?