#内容
今回はRSIとボリンジャーバンドを使ったアルゴリズムを紹介します。
#自己紹介
某理工学部に通う大学2年のfalcon_xです.
大学ではC言語を少しやっているぐらいで、Pythonはほぼ初心者です、、、
Smart Trade社でインターンを始め, QuantX Factoryを使ってアルゴリズムを開発してます。
##What is Smart Trade?
Smart Trade 会社URL:https://smarttrade.co.jp/
ホームページを開くと、こんなページが出てきます。
Smart Tradeとは、株式の売買タイミングを判断する投資アルゴリズムのプラットフォーム企業です。特別なお金持ちではなくても金融サービスを楽しめる、**金融の民主化**を実現するために、アルゴリズム開発プラットフォーム**QuantX Factory**やアルゴリズム売買プラットフォーム**QuantX Store**を提供する会社です。 **QuantX Factory**ではエンジニアを対象に、アルゴリズム開発環境を無償で公開しています。自分が作りたいアルゴリズムをPythonという言語を使ってWeb上で開発することができ、過去の株価の変動を用いて損益等々のバックテストが行えるというものです。またここで開発したアルゴリズムを**QuantX Store**で販売でき、投資家はアルゴリズムを購入することができます。QuantX Factory URL:https://factory.quantx.io/
QuantX Store URL:https://quantx.io/store
またSmart Trade社では、毎週QuantXのアルゴリズムの勉強会をしています。興味のある方はぜひお越しください。
Pythonアルゴリズム勉強会:https://python-algo.connpass.com/
#RSIとボリンジャーバンドを使ったアルゴリズム
RSIとボリンジャーバンドについては下記のサイトがわかりやすいので、詳しく知っりたい方は下記のサイトを参考までにご覧ください!
RSI:https://info.monex.co.jp/technical-analysis/indicators/005.html
ボリンジャーバンド:https://www.jibunbank.co.jp/products/foreign_deposit/chart/help/bollinger_band/
さて、本題に参ります。
今回の買い、売りのサインは以下のように出します。
買いシグナル
RSIが40未満で+2σ線を終値が下回ったとき。
売りシグナル
RSIが70を上回り、-2σを終値が下回ったとき。
##コード
公開コードは以下のリンクになります。
https://factory.quantx.io/developer/f5eec92829294c279499e42894575a18/coding
# ライブラリーのimport
# 必要ライブラリー
import maron
import maron.signalfunc as sf
import maron.execfunc as ef
import pandas as pd
import numpy as np
import talib as ta
ot = maron.OrderType.MARKET_OPEN # シグナルがでた翌日の始値のタイミングでオーダー
# 銘柄、columnsの取得
def initialize(ctx):
# 設定
ctx.logger.debug("initialize() called")
ctx.configure(
channels={ # 銘柄選択
"jp.stock": {
"symbols": [
"jp.stock.3382",
"jp.stock.4063",
"jp.stock.4452",
"jp.stock.4502",
"jp.stock.4503",
"jp.stock.4568",
"jp.stock.6094",
"jp.stock.6501",
"jp.stock.6758",
"jp.stock.6861",
"jp.stock.6954",
"jp.stock.6981",
"jp.stock.7203",
"jp.stock.7267",
"jp.stock.7751",
"jp.stock.7974",
"jp.stock.8031",
"jp.stock.8058",
"jp.stock.8306",
"jp.stock.8316",
"jp.stock.8411",
"jp.stock.8766",
"jp.stock.8802",
"jp.stock.9020",
"jp.stock.9022",
"jp.stock.9432",
"jp.stock.9433",
"jp.stock.9437",
"jp.stock.9984",
],
"columns": [
"close_price", # 終値
"close_price_adj", # 終値(株式分割調整後)
"volume_adj", # 出来高
"txn_volume", # 売買代金
]
}
}
)
# シグナル定義
def _my_signal(data):
cp = data["close_price_adj"].fillna(method='ffill') # 終値の取得
#75日移動平均線の設定
m75 = data["close_price_adj"].fillna(method='ffill').rolling(window=75, center=False).mean()
#rsiの空の入れ物を用意
rsi_S = pd.DataFrame(data=0,columns=[], index=cp.index)
#rsi計算
for (sym,val) in cp.items():
rsi_S[sym] = ta.RSI(cp[sym], timeperiod=26)
#ボリンジャーバンドの空の入れ物を用意
upperband = pd.DataFrame(data=0,columns=[], index=cp.index)
lowerband = pd.DataFrame(data=0,columns=[], index=cp.index)
middleband = pd.DataFrame(data=0,columns=[], index=cp.index)
#ボリンジャーバンドの計算
for (sym,val) in cp.items():
upperband[sym], middleband[sym], lowerband[sym] = ta.BBANDS(cp[sym],
timeperiod=21,
nbdevup=2,
nbdevdn=2,
matype=0)
# 売買シグナルを定義
buy_sig = (rsi_S < 40) & (cp < lowerband)
sell_sig = (rsi_S > 70) & (cp > upperband)
# market_sigという全て0が格納されているデータフレームを作成
market_sig = pd.DataFrame(data=0.0, columns=cp.columns, index=cp.index)
# buy_sigがTrueのとき1.0、sell_sigがTrueのとき-1.0とおく
market_sig[buy_sig == True] = 1.0
market_sig[sell_sig == True] = -1.0
market_sig[(buy_sig == True) & (sell_sig == True)] = 0.0
# ctx.logger.debug(market_sig)
return {
"mavg_75:price": m75,
"rsi_S:g2": rsi_S,
"uband": upperband,
"mband": middleband,
"lband": lowerband,
"market:sig": market_sig,
}
# シグナル登録
ctx.regist_signal("my_signal", _my_signal)
def handle_signals(ctx, date, current):
'''
current: pd.DataFrame
'''
market_sig = current["market:sig"]
done_syms = set([])
# 損切り、利確の設定
for (sym, val) in ctx.portfolio.positions.items():
returns = val["returns"]
if returns < -0.05:
sec = ctx.getSecurity(sym)
sec.order(-val["amount"], comment="損切り(%f)" % returns)
done_syms.add(sym)
elif returns > 0.05:
sec = ctx.getSecurity(sym)
sec.order(-val["amount"], comment="利益確定売(%f)" % returns)
done_syms.add(sym)
# 買いシグナル
buy = market_sig[market_sig > 0.0]
for (sym, val) in buy.items():
if sym in done_syms:
continue
sec = ctx.getSecurity(sym)
sec.order(sec.unit() * 1 ,orderType=ot, comment="SIGNAL BUY")
# ctx.logger.debug("BUY: %s, %f" % (sec.code(), val))
pass
# 売りシグナル
sell = market_sig[market_sig < 0.0]
for (sym, val) in sell.items():
if sym in done_syms:
continue
sec = ctx.getSecurity(sym)
sec.order(sec.unit() * -1,orderType=ot, comment="SIGNAL SELL")
#ctx.logger.debug("SELL: %s, %f" % (sec.code(), val))
pass
α値が低いのが気になりますね、、、
##コード解説
勉強会用に作成した資料が下記のリンク先にあるので、基本的な解説はここでは省略。
今回のコードの重要なところだけ説明していきます。
RSIの計算
rsi_S = pd.DataFrame(data=0,columns=[], index=cp.index)
#rsi計算
for (sym,val) in cp.items():
rsi_S[sym] = ta.RSI(cp[sym], timeperiod=26)
はじめの行は空のデータフレーム設定。
for以下はRSIの計算になっていて、timeperiodには計算に用いる期間の設定。
ボリンジャーバンドの計算
#ボリンジャーバンドの空の入れ物を用意
upperband = pd.DataFrame(data=0,columns=[], index=cp.index)
lowerband = pd.DataFrame(data=0,columns=[], index=cp.index)
middleband = pd.DataFrame(data=0,columns=[], index=cp.index)
#ボリンジャーバンドの計算
for (sym,val) in cp.items():
upperband[sym], middleband[sym], lowerband[sym] = ta.BBANDS(cp[sym],
timeperiod=21,
nbdevup=2,
nbdevdn=2,
matype=0)
上3行は空のデータフレーム設定。
for以下はボリンジャーバンドの計算。
timeperiodは期間、nbdevup、nbdevdnはの値はσ線の値(今回の場合は+2σ, -2σ)。
売買シグナル
# 売買シグナルを定義
buy_sig = (rsi_S < 40) & (cp < lowerband)
sell_sig = (rsi_S > 70) & (cp > upperband)
買いシグナル:
RSIを用いて、売られすぎを判断&ボリンジャーバンドの-2σを株価が下回っている状態
売りシグナル:
RSIを用いて、買われすぎを判断&ボリンジャーバンドの+2σを株価が下回っている状態
今回はここらへんで。
#免責注意事項
本コードを用いた実際のトレードで生じる損害は一切保証しかねますので、ご注意ください。