#はじめに
今回はHL (HighLow) バンドを用いたアルゴリズムを作ってみました.
HLバンドの詳細については以下の記事を参考にしたのでご覧ください.
簡単に説明すると, HLバンドではある期間の高値の最大値を結んだ線(Highバンド)と, 安値の最小値を結んだ線(Lowバンド), 2本の線の平均線(Middleバンド)を用いています.
では早速本題に移ります.
#HLバンドアルゴリズム
##シグナル
買いシグナル:Middleバンドを終値(cp)が突き抜けたとき
売りシグナル:Middleバンドを終値(cp)が下回ったとき or 終値がHighバンドを突き抜けたとき
シグナルの決定はこちらを参考にしました.
##コード
今回のコードはこちら
#HLバンド
import maron
import maron.signalfunc as sf
import maron.execfunc as ef
import pandas as pd
import talib as ta
import numpy as np
#ot = maron.OrderType.MARKET_CLOSE # シグナルがでた翌日の終値のタイミングでオーダー
ot = maron.OrderType.MARKET_OPEN # シグナルがでた翌日の始値のタイミングでオーダー
#ot = maron.OrderType.LIMIT # 指値によるオーダー
def initialize(ctx):
# 設定
ctx.logger.debug("initialize() called")
ctx.configure(
channels={ # 利用チャンネル
"jp.stock": {
"symbols": [
"jp.stock.2914",
"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", # 終値(株式分割調整後)
"high_price_adj", # 高値(株式分割調整後)
"low_price_adj", # 安値(株式分割調整後)
"volume_adj", # 出来高
"txn_volume", # 売買代金
]
}
}
)
# シグナル定義
def _my_signal(data):
cp = data["close_price_adj"].fillna(method='ffill') #終値取得
hp = data["high_price_adj"].fillna(method='ffill') #高値取得
lp = data["low_price_adj"].fillna(method='ffill') #安値取得
hband = hp.rolling(20).max() #Highバンド設定
lband = lp.rolling(20).min() #Lowバンド設定
mband = (hband - lband)/2 + lband #Middleバンド設定
market_sig = pd.DataFrame(data=0.0, columns=cp.columns, index=cp.index)
buy_sig = ((mband.shift(1) > cp.shift(1)) & (mband < cp))
sell_sig = ((mband > cp) | (cp > hband))
# 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 {
# "hband:g2": hband,
# "lband:g2": lband,
# "mband:g2": mband,
"hband": hband,
"lband": lband,
"mband": mband,
"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.02:
sec = ctx.getSecurity(sym)
sec.order(-val["amount"], comment="損切り(%f)" % returns)
done_syms.add(sym)
elif returns > 0.04:
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
##コード解説
基本的なコードの解説は, 勉強会用に作成した資料が下記のリンク先にあるのでこちらをご覧ください.
今回重要なところを解説していきます.
69~71行目
hband = hp.rolling(20).max() #Highバンド設定
lband = lp.rolling(20).min() #Lowバンド設定
mband = (hband - lband)/2 + lband #Middleバンド設定
ここでは, 各バンドの設定をしています. hbandは過去20日間の高値(cp)の最大値, lbandは過去20日間の安値(lp)の最小値, mbandはhbandとlbandの平均をとっています.
rollingについての詳しいことはこちら
74~75行目
buy_sig = ((mband.shift(1) > cp.shift(1)) & (mband < cp))
sell_sig = ((mband > cp) | (cp > hband))
買いシグナル:mbandを終値(cp)が突き抜けたとき
売りシグナル:mbandを終値(cp)が下回ったとき or 終値がhbandを突き抜けたとき
##バックテスト結果
3年で損益率が17%,,,,
あまり儲かっていませんね.
MaxDrawdown, SharpRatio, αの値を見ても, かなり改善の余地がありそうです.
##感想
HLバンドは一般的には, ブレイクアウト手法で使われることが多く, 大相場(普段と比べて, 株式相場全体が活況に満ちて高騰し, 出来高も大きく膨らんだ相場のこと)でないと失速することが多いため, すべての状況でHLバンドを用いてもあまり良いアルゴリズムはできないことが結果からも言えます.
#免責注意事項
本コードを用いた実際のトレードで生じる損害は一切保証しかねますので、ご注意ください。