This time, I made an algorithm using the HL (HighLow) band. For details on the HL band, please refer to the following article.
How to read and use HL bands [Technical indicators / trends]
Briefly, in the HL band, the line connecting the maximum value of the high price for a certain period (High band), the line connecting the minimum value of the low price (Low band), and the average line of the two lines (Middle band) I am using it.
Let's move on to the main subject.
Buy signal: When the closing price (cp) breaks through the Middle band Sell signal: When the closing price (cp) falls below the Middle band or when the closing price breaks through the High band
I referred to here to determine the signal.
This code is here
#HL band
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 #Order at the timing of the closing price the day after the signal is issued
ot = maron.OrderType.MARKET_OPEN #Order at the timing of the opening price the day after the signal is issued
#ot = maron.OrderType.LIMIT #Limit order
def initialize(ctx):
#Setting
ctx.logger.debug("initialize() called")
ctx.configure(
channels={ #Channel used
"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", #closing price
"close_price_adj", #closing price(After stock split adjustment)
"high_price_adj", #High price(After stock split adjustment)
"low_price_adj", #Low price(After stock split adjustment)
"volume_adj", #Volume
"txn_volume", #Trading price
]
}
}
)
#Signal definition
def _my_signal(data):
cp = data["close_price_adj"].fillna(method='ffill') #Get closing price
hp = data["high_price_adj"].fillna(method='ffill') #Get high
lp = data["low_price_adj"].fillna(method='ffill') #Get low price
hband = hp.rolling(20).max() #High band setting
lband = lp.rolling(20).min() #Low band setting
mband = (hband - lband)/2 + lband #Middle band setting
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_1 when sig is True.0、sell_When sig is True-1.Set to 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,
}
#Signal registration
ctx.regist_signal("my_signal", _my_signal)
def handle_signals(ctx, date, current):
'''
current: pd.DataFrame
'''
market_sig = current["market:sig"]
done_syms = set([])
#Loss cut, profit setting
for (sym, val) in ctx.portfolio.positions.items():
returns = val["returns"]
if returns < -0.02:
sec = ctx.getSecurity(sym)
sec.order(-val["amount"], comment="Loss cut(%f)" % returns)
done_syms.add(sym)
elif returns > 0.04:
sec = ctx.getSecurity(sym)
sec.order(-val["amount"], comment="Profit-taking sale(%f)" % returns)
done_syms.add(sym)
#Buy signal
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 signal
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
For the explanation of the basic code, please see here because the material created for the study session is at the link below.
I will explain the important points this time.
** Lines 69-71 **
hband = hp.rolling(20).max() #High band setting
lband = lp.rolling(20).min() #Low band setting
mband = (hband - lband)/2 + lband #Middle band setting
Here, each band is set. Hband is the maximum value of the high price (cp) in the last 20 days, lband is the minimum value of the low price (lp) in the last 20 days, and mband is the average of hband and lband. Masu.
For more information about rolling, click here [https://pandas.pydata.org/pandas-docs/version/0.25.3/reference/api/pandas.core.window.Rolling.min.html)
** Lines 74-75 **
buy_sig = ((mband.shift(1) > cp.shift(1)) & (mband < cp))
sell_sig = ((mband > cp) | (cp > hband))
Buy signal: When the closing price (cp) breaks through mband Sell signal: When the closing price (cp) falls below mband or when the closing price breaks through hband
Profit and loss ratio is 17% in 3 years ,,,,
It's not very profitable.
Looking at the values of MaxDrawdown, SharpRatio, and α, there seems to be considerable room for improvement.
The HL band is generally used in the breakout method, and it will stall unless it is a big market (a market where the entire stock market is booming and soaring compared to usual, and the trading volume is also greatly expanded). The results also show that using the HL band does not provide a very good algorithm in all situations, as it is often the case.
Please note that we cannot guarantee any damage caused by actual trading using this code.
Recommended Posts