株式・FXや仮想通貨の取引の際に、一定のルールを使って売買する事があります。
そのルールで長期間売買したときに利益が出るのか!?
投資を実践する際に一番知りたいことですよね。
もちろん将来の予測は出来ませんが、過去のデーターがあればシミュレートすることが出来ます。
Pythonを使って投資戦略をシミュレートする方法を紹介します。
投資戦略
今回シミュレートする投資戦略は「移動平均線交差戦略」です。
もちろんコードの一部を書き換えれば、その他の投資戦略のシミュレートに応用出来ます。
「移動平均線交差戦略(ゴールデンクロス・デッドクロス)」とは?
移動平均線交差戦略(ゴールデンクロス・デッドクロス)とは、どのような投資戦略なのでしょうか?
移動平均線交差戦略は、短期移動平均線と長期移動平均線が交差したタイミングで、株を売買するトレード手法です。
Pythonコード解説
ここからは、サンプルコードをご覧に入れながら解説を進めます。
損益シミュレート対象銘柄を指定する
損益シミュレート対象銘柄を指定します。
今回のサンプルコードでは、日経平均株価の日足データーを使用します。
1 2 |
#ここでは日経平均株価を指定している Security_code = 'Nikkei 225' |
シミュレートする移動平均の値を登録
短期移動平均線と長期移動平均線の値を登録します。
デフォルト値はそれぞれ 25 と 200 を設定。
※下のコードでは短期移動平均線の値を130にしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#短期移動平均の値を入力' Sma_s = '130' #値が空白ならばデフォルト値の25を設定 if Sma_s == '': Sma_s = int(25) else: Sma_s = int(Sma_s) #長期移動平均の値を入力 Sma_l = '200' #値が空白ならば(デフォルト値)200 if Sma_l == '': Sma_l = int(200) else: Sma_l = int(Sma_l) #登録された値を表示 print('短期:',Sma_s, '長期:',Sma_l) |
短期: 130 長期: 200
必要があれば株価データーを取得する
シミュレート対象のデーターは、時系列の価格情報があれば何でもOKです。
初心者の方が、このブログ記事を見て一緒に作業できるように株価取得の手順もご紹介します。
株価データーの取得先はいつもお世話になっているこちら。 https://www.investing.com/
この、大手金融情報サイトのInvesting.comから経済データを取得する事の出来るPythonライブラリー「investpy」を使用します。
※サーバーへ過度な負担を掛けることの無いよう、連続で長期データーを取得する事などは控えてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#ライブラリーをインポート import investpy from datetime import date # 本日の日付を準備 today = date.today().strftime('%d/%m/%Y') code = Security_code #個別銘柄を取得するならこのコードを使用する #stock_data = investpy.get_stock_historical_data(stock=code, country='japan', from_date='01/01/2000', to_date=today) #株価指数を取得するならこのコードを使用する stock_data = investpy.get_index_historical_data(index=code,country='japan', from_date='01/01/2000',to_date=today) # 取得したデーターを変数 code +_Longest_term_historical_data.csv という名前を付けて保存 # 保存する名前を変数に代入 Save_file_name = f"{code}_Longest_term_historical_data.csv" # 変数に代入された名前を付けて保存 stock_data.to_csv('./data/' + Save_file_name) |
指定された移動平均の値で、シミュレートを実行する
株価データーを読み込んで、シミュレートを進めます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#ライブラリーをインポート import pandas as pd # 指定された銘柄コードのファイル名を作成 Security_code +_Longest_term_historical_data.csv csv_file_name = f"{Security_code}_Longest_term_historical_data.csv" # parse_dates=Trueで、インデックスの列をdatetime型に変換している df = pd.read_csv('./data/' + csv_file_name, header=0, index_col='Date', parse_dates=True) # データーを降順に並び替える df = df.sort_index() df |
2001年1月5日から、2022年8月12日までの日経平均株価データーを取得しています。
データー取得元:https://www.investing.com/
日毎の損益金額を算出
前日終値から当日の終値を引いて、1日毎の損益金額を算出します。
1 2 3 4 |
#日毎の損益金額を算出' df['simple_row_return'] = (df['Close'] - df['Close'].shift(1)) df[['Close', 'simple_row_return']] |
移動平均の値と売買フラグの算出
短期・長期移動平均の値と売買フラグを算出します。
移動平均は、rolling().mean()で簡単に算出する事ができます。
df[‘SMA_S’] = df[‘Close’].rolling(SMA_s).mean()
df[‘SMA_L’] = df[‘Close’].rolling(SMA_l).mean()
売買フラグはこちらのコードで算出します。
# もし、短期移動平均線[‘SMA_S’]が長期移動平均線[‘SMA_L’]よりも大きければ 1 そうで無ければ -1
# np.where( 短期移動平均線[‘SMA_S’] > 長期移動平均線[‘SMA_L’] ならば 1 、 そうで無ければ -1
上記条件をコードに書くと、df[‘Position’] = np.where(df[‘SMA_S’] > df[‘SMA_L’], 1, -1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#ライブラリーをインポート import numpy as np # 移動平均を追加 # 移動平均の値を指定 SMA_s = Sma_s SMA_l = Sma_l print('SMA_s:' ,SMA_s) print('SMA_l:' ,SMA_l) # 移動平均を算出してデーターフレームに書き込む df['SMA_S'] = df['Close'].rolling(SMA_s).mean() df['SMA_L'] = df['Close'].rolling(SMA_l).mean() # 日毎損益の累積(Accumulation)和 df['Accumulation_row_return'] = df['simple_row_return'].cumsum() # 移動平均線交差戦略の売買フラグ設定 # もし、短期移動平均線['SMA_S']が長期移動平均線['SMA_L']よりも大きければ 1 そうで無ければ -1 # np.where( 短期移動平均線['SMA_S'] > 長期移動平均線['SMA_L'] ならば 1 、 そうで無ければ -1 df['Position'] = np.where(df['SMA_S'] > df['SMA_L'], 1, -1) # データフレームの欠損値を含むデーターを削除 df.dropna(inplace=True) # 列を指定してデーターフレームを表示 df[['Close', 'SMA_S', 'SMA_L', 'Position', 'Accumulation_row_return']] |
ベクトル化バックテスト
ベクトル化バックテストを実行します。
「ベクトル化」って何?という方は、こちらのサイトさんの記事がシンプルで参考になると思います。
https://applingo.tokyo/article/6949
■移動平均線交差トレードのルール
短期移動平均線が長期移動平均線より上ならば「買い」
短期移動平均線が長期移動平均線より下ならば「売り」
※移動平均線が交差する事が分かった日の終値で売り買いを入れ替える
※手数料、スリップページ、税金等は考慮しない
■Pythonコードでのフラグ付け
短期移動平均線が長期移動平均線より上ならば「1」
短期移動平均線が長期移動平均線より下ならば「-1」
前日の終値で投資戦略が確定するので、前日shift(1)と日々の損益を掛ける事により投資戦略での損益を算出します。
1 2 3 4 5 6 7 8 |
#移動平均線交差戦略 # もし、短期移動平均線['SMA_S']が長期移動平均線['SMA_L']よりも大きければ 1 そうで無ければ -1 # np.where( 短期移動平均線['SMA_S'] > 長期移動平均線['SMA_L'] ならば 1 、 そうで無ければ -1 #日々の損益にフラグを掛けることにより、戦略での損益を算出する df['Strategy'] = df['Position'].shift(1) * df['simple_row_return'] df[['Close', 'simple_row_return', 'Position', 'Strategy']] |
上の例では、たまたま表示されている範囲ではフラグがすべてマイナス(売り戦略)でした。
投資戦略での損益累積和
投資戦略での損益累積和を算出します。
1 2 3 4 5 |
#移動平均交差トレードの累積和を算出する df['Accumulation_Strategy'] = df['Strategy'].cumsum() #列を指定してデーターフレームを表示 df[['Close', 'simple_row_return', 'Position', 'Strategy', 'Accumulation_Strategy']] |
グラフ表示
損益をグラフ化します。
グラフ描画にplotlyというライブラリーを使用します。
plotlyの解説はこちらの記事をご覧下さい。
plotlyをインポート
plotlyというライブラリーをインポートします。
※事前にplotlyのインストールを済ませておいてください。
1 2 |
# plotlyをインポート import plotly.graph_objects as go |
データーフレームの日付がインデックスだとplotlyで描画されないので、インデックスから外す
この記事で紹介するPythonコードでは、データーフレームの日付がインデックスだとplotlyで描画されません。
Dateインデックスから外します。
1 2 3 4 5 |
# 日付がインデックスだとplotlyで描画されないので、インデックスから外す df_Security_code_ri = df.reset_index() #データーフレームを表示させる df_Security_code_ri |
plotryでグラフ表示
いよいよplotryでグラフ表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#グラフオブジェクトを作成 fig1 = go.Figure() #終値Closeを表示させる fig1.add_traces(go.Scatter(x=df_Security_code_ri['Date'], y=df_Security_code_ri['Close'], name='Close')) # チャートの凡例に移動平均の値を表示させるために、文字列に変換して変数に代入する。 str_SMA_s = str(SMA_s) str_SMA_l = str(SMA_l) # 移動平均線を追加 fig1.add_traces( go.Scatter(x=df_Security_code_ri['Date'], y=df_Security_code_ri['SMA_S'], name='短期移動平均' + str_SMA_s)) fig1.add_traces( go.Scatter(x=df_Security_code_ri['Date'], y=df_Security_code_ri['SMA_L'], name='長期移動平均' + str_SMA_l)) fig1.add_traces( go.Scatter(x=df_Security_code_ri['Date'], y=df_Security_code_ri['Accumulation_row_return'], name='株を持ち続けたときの累積和')) fig1.add_traces( go.Scatter(x=df_Security_code_ri['Date'], y=df_Security_code_ri['Accumulation_Strategy'], name='移動平均クロス戦略での累積和')) # fig10.add_traces(go.Scatter(x=df_Security_code_ri['Date'], y=df_Security_code_ri['Position'], name='売り買いポジション', yaxis='y2')) # チャートのタイトルを表示 fig1.update_layout(title_text=Security_code + ' : 移動平均線クロス戦略・損益の累積和') # スライドバー表示 fig1.update_layout(xaxis_rangeslider_visible=True) #チャートを表示させる fig1.show() |
plotlyでは右側の凡例をクリックすると、表示のオンオフを切り替えることが出来ます。
下のグラフでは、日経平均株価の終値、株を持ち続けたときに得られる損益、移動平均クロス戦略を適応したときの損益を表示しています。
パフォーマンスは、何も考えずに株を持ち続けた方が良い結果となっています。
ご自分で、他の移動平均線の組み合わせを試してみてください。
参考文献
参考にさせていただいた書籍はこちらです。
Pythonによるファイナンス
発行元の O’Reilly japan から書籍の画像をお借りしています。
※アフリエイト契約はしていません。
まとめ
投資戦略をPythonでシミュレートする方法を解説しました。
コードの一部を書き換えることによって、他の投資戦略のシミュレートも可能です。
利益が出来ると思われる戦略が、期待外れだったり。。。
そんな事が投資する前に予測できます。
相場で戦える実力は、相場でしか養えません。
相場で実際に痛い目に会わなければ、真の成長は得られないでしょう。
ただし、投資資産にも限りがあります。
シミュレートは未来の損益を正確に予測することは出来ません。
しかし、大切な投資資産を守る役目は果たしてくれるはずです。
後日、最適な移動平均線の組み合わせを算出するコード解説も行う予定です。
関連動画
この記事を書いた人
あしおゆたか
投資歴21年の個人投資家
机上の理論ではなく、実体験に基づいた記事作りをモットーにしています。
スポーツクラブに毎週2日~3日通い、サウナ後の暴飲暴食が趣味。(現在自粛中)
◇主な投資対象
日本株式
株式ETF(上場投資信託)
日経225先物
日経225先物オプション
◇運営者情報はこちら