💰

【株式投資】Pythonを用いたテクニカル分析とバックテスト

2024/01/07に公開

✅目的

  • pythonと各種ライブラリを使用して株式投資のストラテジの立て方について紹介します。
  • また、古くからおこなわれているテクニカル指標を使ってのアルゴリズムトレードの実現方法について解説します。
  • ストラテジを立てる過程、バックテストについては実際にGoogle Colaboratoryで実施し手法を公開しています。
  • テクニカル指標を用いたストラテジで2022年1月~12月と2023年1月~12月にかけてS&P500を売買した場合どのような結果になるかバックテストを実施します。
  • テクニカル分析による売買戦略が特定の期間や条件下では力を発揮するが、未来予測ができるわけではないことを確認します。
  • 最終的な投資判断は自己責任となりますのでよろしくお願いします。
  • 最大限注意をして、この記事を作成していますが、誤りがありましたらご指摘いただけると幸いです。

📃そもそもテクニカル分析ってなに?

  • 過去の値動きやデータをもとに将来の値動きを予測しようする手法です。
  • ファンダメンタル分析と双璧をなす分析手法で短期的な値動きやトレンドを把握するための分析手法です。
  • 判断基準や指標は千差万別で統計学や時系列分析手法から派生したものもあれば経験則的な点から発展したものも存在します。
  • テクニカル分析の考え方の根底はダウ理論をもとに考案されたものが多いです。
  • 歴史は古く、江戸時代の米相場を予測するために本間宗久(ほんま そうきゅう)がはじめたという説がありますが定かではないようです。

📃処理の流れ

  1. yfinanceライブラリを使用してS&P500の株価を取得します。
  2. 取得した株価をもとにtalibライブラリを使用して単純移動平均を計算します。
  3. 単純移動平均の線をもとにゴールデンクロス/デッドクロスを判定します。
  4. ゴールデンクロス/デッドクロスの判定をもとにロング/ショートを切り替えます。
  5. ショート時は空売りをして利益が発生する想定とします。
  6. 上記、ストラテジで累積収益率がロングオンリーとくらべてどのような成績かを簡易的なバックテストで確認します。

🐍pythonで実行してみる

実行はGoogle Colaboratoryを使用しました。
全処理内容は以下を参照してください。
https://github.com/omizunomitaro/technical_backtest/

実装解説

1. yfinanceライブラリでの株価取得

# yfinanceをインポート
import yfinance as yf
start = '2022-01-01'
end = '2023-12-31'

# 日経平均の株価を5年分 日足で取得
stock_data = yf.download(tickers='^GSPC', interval='1d', start=start, end=end)
stock_data

上記で海外のyahoo financeから株価をdataframeで取得できます。
また、パラメータの指定方法によっては財務情報なでも取得できて便利です。
以下に使いそうなパラメータ指定をまとめました。

yfinanceパラメータ
  • ticker
    取得する銘柄の指定をします。国内株、海外株、インデックスなど複数銘柄を取得できます。
国内株取得

国内株式の取得は株価コードに.Tをつけて株価を取得します。
.Tは東証を表します。

stock_data = yf.download(tickers='9984.T', interval='1d', start=start, end=end)
外国株取得

海外株式は普通にティッカーコードを指定します。

stock_data = yf.download(tickers="AMZN", interval='1d', start=start, end=end)
インデックス

よく使いそうなインデックス指標のtickerコード一覧

コード 内容
VIX指数(恐怖指数) ^VIX
HG=F
SOX(半導体)指数 SOXX
Russel2000 RUT
S&P500 ^GSPC
GLD
ドルインデックス DX-Y.NYB
ドル円 JPY=X
アメリカ5年債 ^FVX
アメリカ10年債 ^TNX
アメリカ30年債 ^TYX
  • interval
    取得するデータ間隔の指定です。有効な間隔は次のとおりです。

    • 「1 分」、「2 分」、「5 分」、「15 分」、「30 分」、「60 分」、「90 分」、「1 時間」、「1 日」、「5 日」、「1 週間」、「1 ヶ月」、「3 ヶ月」
    • “1m”, “2m”, “5m”, “15m”, “30m”, “60m”, “90m”, “1h”, “1d”, “5d”, “1wk”, “1mo”, “3mo”
    # 1年分S&P500株価取得
    stock_data = yf.download(tickers='^GSPC', interval='1d', period='1y')
    stock_data
    
  • start
    データ取得開始日時です。

  • end
     データ取得終了日時です。

  • period

    • 「1 日」、「5 日」、「1 か月」、「3 か月」、「6 か月」、「1 年」、「2 年」、「5 年」、「10 年」、「ytd」、「最大」
    • “1d”, “5d”, “1mo”, “3mo”, “6mo”, “1y”, “2y”, “5y”, “10y”, “ytd”, “max”
  • 財務情報の取得
    以下の方法で個別株の財務情報を取得することもできます。

    #ソフトバンク財務情報取得
    stock_info = yf.Ticker('9984.T')
    stock_info.financials
    
  • 複数銘柄の同時取得

start = '2022-01-01'
end = '2023-12-31'

#amazon/apple/googleの終値を複数取得
stock_data = yf.download(tickers="AMZN AAPL GOOG", interval='1d', start=start, end=end)[Close]

stock_data

2. talibでの単純移動平均計算

# talibをインポートする。
import talib
# テーブルに移動平均線の計算結果の行を追加する。
stock_data["sma_7"] = talib.SMA(stock_data['Adj Close'].values, 7)
stock_data["sma_25"] = talib.SMA(stock_data['Adj Close'].values, 25)

4. ゴールデンクロス/デッドクロスの判定

# numpyをインポート
import numpy as np

# ゴールデンクロス、デッドクロスを判定して、position列を追加する。
stock_data['position'] = np.where(stock_data['sma_7'] > stock_data['sma_25'], 1, -1)

# 移動平均なので前半の数日は平均線を生成できない。nanが含まれる行は集計から除外する。
stock_data.dropna(inplace=True)

stock_data

6. バックテスト

今回のバックテストは以下の条件で行っています。

  • 売買手数料は考慮しません。
  • ショート時は空売りをして利益が発生する想定とします。
対数収益率をもとめる
stock_data['return'] = np.log(stock_data['Adj Close'] / stock_data['Adj Close'].shift(1))
stock_data
売買戦略を適用した場合の収益率をもとめる
stock_data['strategy'] = stock_data['position'].shift(1) * stock_data['return']
バイホールドと単純移動平均戦略で売買した場合の累積合計をもとめる
stock_data[['return', 'strategy']].cumsum().apply(np.exp).plot(figsize=(10, 6))
stock_data[['return', 'strategy']].cumsum()

2022年 S&P500を単純移動平均戦略で売買したらどうなっていたか?

S&P500 2022年1月~2022年12月にかけて

S&P500株価

  • 2022年はインフレ退治のため米国債の利上げを実施しました。
  • その結果、リセッション懸念から投資家心理が悪化しS&P500は下げトレンドでした。
対数収益率合計

対数収益率グラフ

  • retrunはバイホールドした場合の対数収益率合計、strategyは移動平均にあわせて売り買いした場合の対数収益率合計です。
  • この結果をみると移動平均をもとに売買を行ったほうがパフォーマンスがよいことになります。
  • 株価はランダムウォークするため過去の値動きから予測するテクニカル分析は無意味という風潮がありますがいちがいに無意味とも言えないようです。
  • ただし、株価下落時に利益を得ているため、その分信用取引をしてリスクをとっているからバイホールドよりアウトパフォームしてあたりまえという考え方もあるかもしれません。

2023年 S&P500を単純移動平均戦略で売買したらどうなっていたか?

S&P500 2023年1月~2023年12月にかけて

S&P500株価

  • ゆるゆるとインフレが鎮静化するとともにリセッションは起きずソフトランディングするのではないかという期待から株式市場は全体的には好調でした。
  • 年初めは多くのアナリストが債券の年と予想していましたが予想を裏切る形となりました。
対数収益率合計

対数収益率グラフ

  • retrunはバイホールドした場合の対数収益率合計、strategyは移動平均にあわせて売り買いした場合の対数収益率合計です。
  • この結果をみると移動平均をもとに売買を行ったほうがパフォーマンスが悪いことがわかります。
  • 短期的にピンポイントでは売買を繰り返して利益をだすことは可能ですがS&P500のような長期的に右肩上がりの株価の場合、売買を繰り返して利益を生み出すことは難しそうです。

まとめ

  • 株価の取得/テクニカル分析/クロスの判定/バックテストと一通りの流れをpythonを用いて実施しました。
  • 単純移動平均線を用いて売買した場合どうなるかをS&P500で実際に確認しました。
  • テクニカル分析とアルゴリズムトレードが必ず勝てるわけでもないですが、無意味でもないということを確認しました。
  • そのためテクニカル分析は大まかなトレンドを把握するものであって未来予測ができるわけではないことを確認しました。

参考文献

バートン・マルキール.ウォール街のランダム・ウォーカー<原著第12版> 株式投資の不滅の真理.日本経済新聞出版
古城鶴也.テクニカル分析がわかる.日本経済新聞出版
Yves Hilpisch.Pythonからはじめるアルゴリズムトレード(自動売買の基礎と機械学習の本格導入に向けたPythonプログラミング).オライリー・ジャパン

Discussion