投資のためのデータサイエンス

個人の投資活動に役立つデータ分析にまつわる話題を綴ります。

パラボリックSARと順位相関指数を組み合わせたシグナル判定

※結果の見方の記述を修正しました (2024/04/26)

前々回(パラボリックSAR)と前回(順位相関指数RCI)の投稿の指標を組み合わせた取引戦略が、ある書籍に載っていました。今回はこれをPythonで実装してみます。
尚、パラボリックSARについてはta-libを用いたコードに変更しました。RCIについては、別のネット記事のコードで計算結果が一致するものを見つけたので、これで正しいということにしておきます。ここではFXを投資対象とします。


まず、投資対象銘柄のリストを与え、両指標の計算関数を定義します。

# ライブラリのインポート
import yfinance as yf
from datetime import datetime, timedelta
from datetime import date
import pandas as pd
import numpy as np
from pandas_datareader import data as pdr
import matplotlib.pyplot as plt
import mplfinance as mpf
import seaborn
import mplfinance as mpf
import talib as ta
# シグナル判定する通貨ペアのリスト
list_ticker = ['USDJPY=X', 'EURJPY=X', 'GBPJPY=X', 'AUDJPY=X', 'CADJPY=X', 'NZDJPY=X', 'MXNJPY=X', 'CHFJPY=X', 'NOKJPY=X',\
               'EURUSD=X', 'GBPUSD=X', 'AUDUSD=X', 'NZDUSD=X', 'AUDNZD=X', 'EURGBP=X', 'GBPAUD=X']
# パラボリックSARの戦略関数
def parabolic_sar_strategy(data):   
   # パラボリックSARの計算
   data['SAR'] = ta.SAR(data['High'], data['Low'], acceleration=0.02, maximum=0.2)
   # シグナルの生成
   data['Signal'] = 0  # 0 means no signal
   data.loc[data['Close'] > data['SAR'], 'Signal'] = 1  # Buy signal
   data.loc[data['Close'] < data['SAR'], 'Signal'] = -1  # Sell signal
   # ポジションの生成
   data['Position'] = data['Signal'].diff()
   return data
# RCIの計算関数
def rci(close, timeperiod=9):
    rci = np.full_like(close, np.nan)
    rank_period = np.arange(1, timeperiod + 1)
    for i in range(timeperiod - 1, len(close)):
        rank_price = close[i - timeperiod + 1:i + 1]
        rank_price = np.argsort(np.argsort(rank_price)) + 1
        aa = 6 * sum((rank_period - rank_price)**2)
        bb = timeperiod * (timeperiod**2 - 1)
        rci[i] = (1 - aa / bb) * 100
    return rci

そして、銘柄のリストの要素毎にシグナルを判定して、指標毎に別々のデータフレームに格納します。

# リスト内の銘柄毎にシグナルを判定する
df_sar = pd.DataFrame()
df_rci = pd.DataFrame()
end = datetime.today()
start = end - timedelta(days=180)  # 6 months before today
for ticker in list_ticker:
    end = datetime.today()
    start = end - timedelta(days=182)  # 6 months before today
    yf.pdr_override()
    # yahooサイトからデータをダウンロード
    data = pdr.get_data_yahoo(ticker, start, end) # パラボリック計算用
    df = data.copy() # RCI計算用
    # SAR諸指標の計算
    df_parab = parabolic_sar_strategy(data)
    # 順位相関指数(RCI)
    df['RCI'] = rci(data['Close'])  
    df['ticker'] = ticker
    df_parab['ticker'] = ticker  
    # 最終行を付け足す
    df_sar = pd.concat([df_sar,df_parab.tail(1)],axis=0)
    df_rci = pd.concat([df_rci,df.tail(1)],axis=0)

そして、両指標について、シグナルがあるケースに絞り込んで横連結します。

# SARのシグナルがある行に絞り込む
df1 = df_sar.loc[df_sar['Signal']==1]
df2 = df_sar.loc[df_sar['Signal']==-1]
df3 = pd.concat([df1, df2], axis=0)
# RCIがLB以下かUB以上の行に絞り込む
df11 = df_rci[df_rci['RCI'] <= -50]
df12 = df_rci[df_rci['RCI'] >= 50]
df13 = pd.concat([df11, df12], axis=0)
# SARとRCIの結果を横連結する
df4 = df3.reset_index()[['SAR','Signal','Position','ticker']]
df14 = df13.reset_index()[['RCI','ticker']]
df20 = pd.merge(df4, df14, on='ticker', how='right')
df20


ここで注目するケースは、Positon=2.0 (買いシグナルにチェンジ)でかつRCIが下方バンドを割っているケース、又はPosition=-2.0 (売りシグナルにチェンジ)でかつRCIが上方バンドを超えているケースです。実際にはRCIのバンド絶対値を80にすると該当ケースがほとんどないため、ここでは50に設定しています。またSARがチェンジするケースも出現頻度は少ないです。