LoginSignup
4
3

More than 5 years have passed since last update.

RSIのアルゴリズム #QuantX

Last updated at Posted at 2018-08-02

RSI

今回はRSIを使ったアルゴリズムを QuantXで書いてみたいと思います.
RSI(相対力指数)は最も有名なオシレーター系の指標と言えるのではないでしょうか.

計算式は簡単で,

RSI = \frac{過去n日間で上昇した値幅}{過去n日間で上昇した値幅+過去n日間で下落した値幅} \times 100 \\

です.
過去何日分を見るか,というのがキモになりますが,よく使われるのは14日間のようです.
今回は短めに5日間にしてみます.

シグナル

RSIが30%以下になったら買い,70%以上で売り

手仕舞い

売りシグナルがでたタイミング

コード

import numpy as np 
import talib as ta 
import pandas as pd 


def initialize(ctx):
    # 設定
    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": ["close_price_adj",    # 終値(株式分割調整後) 
          ]}})

    def _RSI(data):

      df_close = data["close_price_adj"].fillna(method='ffill')
      # memo 参照
      df_rsi = df_close.apply(lambda s: ta.RSI(s.values.astype(np.double), timeperiod=ctx.period),axis=0)

      buy_sig = df_rsi < 30.0 
      sell_sig = df_rsi > 70.0 

      return {
        "rsi": df_rsi,
        "buy:sig": buy_sig, 
        "sell:sig": sell_sig, 

        }

    # シグナル登録
    ctx.regist_signal("RSI", _RSI)

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-02_19.jpg

memo

apply

今回は,pandas.DataFrame.applyを使って各銘柄のRSIを算出しました.

どういう仕組みか,簡単に説明します.
まずは説明のために、いくつかの銘柄について、乱数で過去100日分の株価を作ります.

import pandas as pd 
import numpy as np 
import talib as ta 

inputs = {
    'Toyota': np.random.randint(80, 100, size=100), 
    'Nissan': np.random.randint(50, 100, size=100), 
    'JAL': np.random.randint(40, 60, size=100), 
    'ANA': np.random.randint(50, 100, size=100), 
    'JT': np.random.randint(150, 200, size=100), 
}

df_close = pd.DataFrame(inputs)

df_close のデータはこのような構造になります.QuantX上でも全く同じ構造です.(ただしコラム名は文字列ではなく銘柄オブジェクト)

2018-08-02_16.jpg

このデータフレームの各コラム,ANA, JAL, JT, Nissan, Toyota それぞれの Series データに ta.RSI を適用させて,その結果をDataFrameで返すのが apply です.

df_rsi = df_close.apply(lambda s: ta.RSI(s.values.astype(np.double), timeperiod=5)) 

df_rsi は,このようなデータになります.

2018-08-02_17.jpg

lambda

apply の引数に無名関数 lambda を使いました.
上記の lambda s: ta.RSI(s.values.astype(np.double), timeperiod=5)

def hoge (s)
    return ta.RSI(s.values.astype(np.double), timeperiod=5)

と全く同じ意味になります.

apply を使用しない

applyを使わずに書くとすると,このようなコードが考えられます.

d =dict()
for s in df_close.columns:
  d[s] = ta.RSI(df_close[s].values.astype(np.double), timeperiod=5)
#df_rsi = pd.DataFrame(d) 
df_rsi = pd.DataFrame(d, index = df_close.index) 

個人的な趣味ですが,1行で終わるところを4行も書くのは好みではないので, apply を使いました.

感想

免責注意事項

  • このコードに基づき投資した結果、損害が発生しても,一切責任を持ちません.
  • このコードが正しく機能する保証は一切致しません.
  • このアルゴリズムを勧めているわけではありません.あくまで QuantX / Python のサンプルコードとして掲載しているだけです.
4
3
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
4
3