Edited at

移動平均とRSIを組み合わせたアルゴリズム #QuantX

More than 1 year has passed since last update.


移動平均+RSI

先日,RSIのアルゴリズムQuantXで書いてみましたが,今回はRSIに移動平均を組み合わせたアルゴリズムを書いてみます.

ストラテジーの基本方針は,

1. 複数の移動平均を使う

2. 移動平均をみて,上昇トレンドであるかどうか確認

3. 全移動平均よりも今日のロウソク足の位置が上にあることを確認

4. 短期移動平均>中期移動平均>長期移動平均という位置関係にあるか確認

5. 上記の条件が揃っている間はロングポジションを保持

6. ただし,RSIが90に入るような事があれば,ポジション解消

7. もしくは,RSIが60を切った場合は,ポジション解消

ここで,「移動平均をみて,上昇トレンドであるかどうか確認」をどのように表現するか考えてみます.図は日経平均株価の2017年10月頃のチャートに,5日25日75日の移動平均をプロットした図です.

上記図より,上昇トレンドとは,3つの移動平均線が前日よりも高い位置にあること,と定義することにします.よってここでは,移動平均の前日比が3日連続ポジティブであるという事を上昇トレンドであるという判断に使いたいと思います.


シグナル

上記1から5の条件が揃っている間は買い持ち.


手仕舞い

上記6,7が発生した時


コード

import numpy as np 

import talib as ta

def initialize(ctx):
# 設定
ctx.ma_shortterm = 5
ctx.ma_midterm = 25
ctx.ma_longterm = 75

ctx.target = 0.10
ctx.period = 5
ctx.codes = [1605, 1925, 2503, 4519, 4911, 6301, 6752, 7741, 8001 ]
ctx.symbol_list = ["jp.stock.{}".format(code) for code in ctx.codes]

ctx.configure(
channels={ # 利用チャンネル
"jp.stock": {
"symbols":ctx.symbol_list,
"columns": ["open_price_adj", # 始値(株式分割調整後)
"close_price_adj", # 終値(株式分割調整後)
]}})

def _MYSIGNAL(data):

df_open = data["open_price_adj"].fillna(method='ffill')
df_close = data["close_price_adj"].fillna(method='ffill')

# 移動平均
df_sma_short = df_close.rolling(window=ctx.ma_shortterm).mean()
df_sma_middle = df_close.rolling(window=ctx.ma_midterm).mean()
df_sma_long = df_close.rolling(window=ctx.ma_longterm).mean()

# 移動平均の前日比が3日連続ポジティブであるかどうか
# memo 参照
df_sma_short_uptrend = df_sma_short.pct_change().rolling(window=3,).min() > 0
df_sma_middle_uptrend = df_sma_middle.pct_change().rolling(window=3,).min() > 0
df_sma_long_uptrend = df_sma_long.pct_change().rolling(window=3,).min() > 0
df_uptrend = df_sma_short_uptrend & df_sma_middle_uptrend & df_sma_long_uptrend

# 全移動平均よりも今日のロウソク足の位置が上にあることを確認
# つまり,始値も終値も移動平均線より上に位置していることを確認

df_upper_than_ma = (df_open > df_sma_short) & (df_open > df_sma_middle) & (df_open > df_sma_long) & (df_close > df_sma_short) & (df_close > df_sma_middle) & (df_close > df_sma_long)

# 短期移動平均>中期移動平均>長期移動平均という位置関係にあるか確認
df_ma_posion = (df_sma_short > df_sma_middle) & (df_sma_middle > df_sma_long)

# RSI>90 もしくは RSI<60 であればポジションクローズ
df_rsi = df_close.apply(lambda s: ta.RSI(s.values.astype(np.double), timeperiod=ctx.period),axis=0)
df_position_close_condition = (df_rsi > 90) | (df_rsi < 60)

# 買いシグナル
buy_sig = df_uptrend & df_upper_than_ma & df_ma_posion
sell_sig = df_position_close_condition

return {

"buy:sig": buy_sig,
"sell:sig": sell_sig,

}

# シグナル登録
ctx.regist_signal("MYSIGNAL", _MYSIGNAL)

def handle_signals(ctx, date, current):
df = current.copy()

# 買いシグナル
df_long = df[df["buy:sig"]]
if not df_long.empty:
for (sym, val) in df_long.iterrows():
sec = ctx.getSecurity(sym)
msg = "買いシグナル"
sec.order_target_percent(ctx.target, comment= msg)

# 売り(ポジションクローズ)シグナル
df_sell = df[df["sell:sig"]]
if not df_sell.empty:
for (sym, val) in df_sell.iterrows():
sec = ctx.getSecurity(sym)
msg = "売りシグナル"
sec.order_target_percent(0, comment= msg)


結果

2018-08-06-13:23:40.jpg


memo


移動平均の前日比が3日連続ポジティブであるかどうか

これを確認するために,過去三日間の前日比で1番小さい値がポジティブであるという確認を行いました.

df_sma_short.pct_change().rolling(window=3,).min() > 0


感想


  • 今まで書いたアルゴリズムの中で今のところ一番いいですね.

  • 銘柄は前回の記事で使った銘柄をそのまま使っているだけなので,このあたりは工夫の余地はあると思います.

  • その他,移動平均の期間,RSIの閾値など,色々試してみる価値はありそうですね.

  • RSIといえば, @kozzy さんのQuantX 上で RSI による売買アルゴリズムを開発する が分かりやすいのでオススメです.ぜひご一読下さい.

  • 甲子園始まりましたね.自分の出身地と関係ない高校同士の試合の時は,公立高校もしくは地方の学校を応援するタイプです.


免責注意事項


  • このコードに基づき投資した結果、損害が発生しても,一切責任を持ちません.

  • このコードが正しく機能する保証は一切致しません.
    このアルゴリズムを勧めているわけではありません.あくまで QuantX / Python のサンプルコードとして掲載しているだけです.