Backtrader实现三层滤网策略
1. 三层滤网策略
三层滤网策略是一种综合运用不同时间框架和技术指标进行交易决策的方法,由亚历山大·埃尔德发明。这一策略的核心在于通过三个层次的过滤或测试来评估交易机会,以确保交易的成功率。这三个层次分别关注长期趋势、短期波动以及入场时机,具体如下:
第一层滤网:在大周期(如周线图)中,使用趋势型指标来判断主要趋势的运行方向,这被称为“市场潮汐”或“大周期的趋势”。例如,在周线图上分析趋势,如果趋势向上,则表明市场整体处于上升趋势中。
第二层滤网:在小周期(如日线图)中,使用震荡型指标来识别与主要趋势逆向的次级走势。这被称为“市场波浪”或“小周期的波动”。例如,在日线图上,当周线趋势向上时,日线图上的下跌可以被视为买入机会。
第三层滤网:当第一、二层滤网条件均满足后,关注小周期中的突破型K线作为入场信号。这被称为“盘中突破”或具体的入场时机。例如,当大周期趋势向上且小周期摆荡指标向下时,利用追踪型停止买单捕捉盘中的向上突破作为买入信号。
三层滤网策略通过这种多层次的分析,旨在提高交易决策的准确性和效率。它不仅考虑了市场的长期趋势,还关注了短期波动和具体的入场时机,从而帮助交易者更好地把握市场机会。
2. 实现
(1)代码
class ThreeScreenStrategy(bt.Strategy):
params = (
('middleperiod', 15), # 中期移动平均线周期
('longperiod', 60), # 长期移动平均线周期
('shortperiod', 5), # 短期移动平均线周期
('printlog',False), # 日志输出标志
)
def __init__(self):
self.dataclose = self.data.close
self.order = None
self.printlog = self.p.printlog
# 添加指标
self.sma_long = bt.indicators.SimpleMovingAverage(
self.data.close, period=self.params.longperiod)
self.sma_mid = bt.indicators.SimpleMovingAverage(
self.data.close, period=self.params.middleperiod)
self.sma_short = bt.indicators.SimpleMovingAverage(
self.data.close, period=self.params.shortperiod)
def next(self):
if self.order:
return
# 第一层:长期趋势
if self.dataclose[0] > self.sma_long[0] :
long_term_trend = 'UP'
else:
long_term_trend = 'DOWN'
# 第二层:中期趋势
if self.dataclose[0] > self.sma_mid[0] :
mid_term_trend = 'UP'
else:
mid_term_trend = 'DOWN'
# 第三层:短期买卖信号
if self.dataclose[0] > self.sma_short[0] :
short_term_trend = 'UP'
else :
short_term_trend = 'DOWN'
# 三重条件共同判断,都满足才能执行交易
# 买入
if short_term_trend == 'UP' and long_term_trend == 'UP' and mid_term_trend == 'UP':
if not self.position :
self.buy()
# 卖出
elif short_term_trend == 'DOWN' and long_term_trend == 'DOWN' and mid_term_trend == 'DOWN':
if self.position :
self.sell()
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
self.log(f'BUY EXECUTED Price: {order.executed.price:.2f}, Cost: {order.executed.value:.2f}, Comm {order.executed.comm:.2f}',self.printlog)
elif order.issell():
self.log(f'SELL EXECUTED Price: {order.executed.price:.2f}, Cost: {order.executed.value:.2f}, Comm {order.executed.comm:.2f}',self.printlog)
self.order = None
# 处理和打印交易信息
def notify_trade(self, trade):
if not trade.isclosed:
return
self.log('*' * 30 + '交易结果' + '*' * 30,self.printlog)
self.log(f'本次交易毛利润:{trade.pnl:.2f},扣除交易费用后的净利润:{trade.pnlcomm:.2f}',self.printlog)
if trade.pnlcomm > 0: # 如果净收益大于0,就认为这次交易盈利,否则认为这次交易亏损(同时输出交易编号)
self.log(f'交易获利: {trade.ref}',self.printlog)
else:
self.log(f'交易亏损: {trade.ref}',self.printlog)
self.log(f'交易长度: {trade.barlen}',self.printlog)
self.log('*' * 30 + '*' * 30 ,self.printlog)
def log(self, txt, printlog):
''' Logging function for this strategy'''
if printlog :
dt = self.datas[0].datetime.date(0).isoformat()
print(f'{dt}, {txt}')
if __name__ == '__main__':
# 初始化Cerebro
cerebro = bt.Cerebro()
# 定义回测日期
start_date_str = '2018-01-01'
end_date_str = '2023-12-31'
# 从数据库中取数据
stock_df = get_code('000858.SZ',start_date_str,end_date_str) # 601169.SH 000858.SZ
start_date = datetime.datetime.strptime(start_date_str,'%Y-%m-%d') # 回测开始时间
end_date = datetime.datetime.strptime(end_date_str,'%Y-%m-%d') # 回测结束时间
# 加载策略
cerebro.addstrategy(ThreeScreenStrategy,printlog=True)
# 加载数据
data = bt.feeds.PandasData(dataname=stock_df, fromdate=start_date, todate=end_date)
cerebro.adddata(data)
# 设置初始资金为100000
cerebro.broker.setcash(100000.0)
# 设置佣金为0.0001 万一
cerebro.broker.setcommission(commission=0.0001)
# 每笔交易量
cerebro.addsizer(bt.sizers.FixedSize, stake=100)
# 期初资产
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# 运行策略
cerebro.run()
# 期末资产
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
# 绘制回测结果
cerebro.plot(iplot=False, volume=False)
(2)结果
Starting Portfolio Value: 100000.00
Final Portfolio Value: 119573.10
3. 问题
如何处理虚假信号,横盘波动时,多次发生买入和卖出的信号,造成收益损失的问题 。
可以看出交易长度短的交易,都是横盘波动时产生的虚假信号,造成频繁交易,频繁交易的持股时长都短,都是亏损交易。
对于产生盈利的交易,都是持股时间长的情况。
还存在另外一个情况,如果股票没有明显的波段,大的趋势,比如601169.SH,那么策略就是在波动中不断交易和亏损。
如何识别波动,控制频繁交易,是这个策略重点需要解决的问题。
打印出来交易过程:
Starting Portfolio Value: 100000.00
2018-05-04, BUY EXECUTED Price: 73.55, Cost: 7355.00, Comm 0.74
2018-06-29, SELL EXECUTED Price: 74.00, Cost: 7355.00, Comm 0.74
2018-06-29, ******************************交易结果******************************
2018-06-29, 本次交易毛利润:45.00,扣除交易费用后的净利润:43.52
2018-06-29, 交易获利: 375
2018-06-29, 交易长度: 39
2018-06-29, ************************************************************
2018-09-27, BUY EXECUTED Price: 66.99, Cost: 6699.00, Comm 0.67
2018-10-09, SELL EXECUTED Price: 63.56, Cost: 6699.00, Comm 0.64
2018-10-09, ******************************交易结果******************************
2018-10-09, 本次交易毛利润:-343.00,扣除交易费用后的净利润:-344.31
2018-10-09, 交易亏损: 376
2018-10-09, 交易长度: 3
2018-10-09, ************************************************************
2019-01-16, BUY EXECUTED Price: 52.80, Cost: 5280.00, Comm 0.53
2019-10-21, SELL EXECUTED Price: 127.30, Cost: 5280.00, Comm 1.27
2019-10-21, ******************************交易结果******************************
2019-10-21, 本次交易毛利润:7450.00,扣除交易费用后的净利润:7448.20
2019-10-21, 交易获利: 377
2019-10-21, 交易长度: 182
2019-10-21, ************************************************************
2019-10-29, BUY EXECUTED Price: 131.00, Cost: 13100.00, Comm 1.31
2019-11-25, SELL EXECUTED Price: 128.30, Cost: 13100.00, Comm 1.28
2019-11-25, ******************************交易结果******************************
2019-11-25, 本次交易毛利润:-270.00,扣除交易费用后的净利润:-272.59
2019-11-25, 交易亏损: 378
2019-11-25, 交易长度: 19
2019-11-25, ************************************************************
2019-12-31, BUY EXECUTED Price: 133.00, Cost: 13300.00, Comm 1.33
2020-01-07, SELL EXECUTED Price: 129.50, Cost: 13300.00, Comm 1.29
2020-01-07, ******************************交易结果******************************
2020-01-07, 本次交易毛利润:-350.00,扣除交易费用后的净利润:-352.62
2020-01-07, 交易亏损: 379
2020-01-07, 交易长度: 4
2020-01-07, ************************************************************
2020-01-10, BUY EXECUTED Price: 130.50, Cost: 13050.00, Comm 1.30
2020-01-23, SELL EXECUTED Price: 131.77, Cost: 13050.00, Comm 1.32
2020-01-23, ******************************交易结果******************************
2020-01-23, 本次交易毛利润:127.00,扣除交易费用后的净利润:124.38
2020-01-23, 交易获利: 380
2020-01-23, 交易长度: 9
2020-01-23, ************************************************************
2020-02-21, BUY EXECUTED Price: 130.00, Cost: 13000.00, Comm 1.30
2020-02-27, SELL EXECUTED Price: 124.80, Cost: 13000.00, Comm 1.25
2020-02-27, ******************************交易结果******************************
2020-02-27, 本次交易毛利润:-520.00,扣除交易费用后的净利润:-522.55
2020-02-27, 交易亏损: 381
2020-02-27, 交易长度: 4
2020-02-27, ************************************************************
2020-03-06, BUY EXECUTED Price: 132.00, Cost: 13200.00, Comm 1.32
2020-03-10, SELL EXECUTED Price: 126.30, Cost: 13200.00, Comm 1.26
2020-03-10, ******************************交易结果******************************
2020-03-10, 本次交易毛利润:-570.00,扣除交易费用后的净利润:-572.58
2020-03-10, 交易亏损: 382
2020-03-10, 交易长度: 2
2020-03-10, ************************************************************
2020-03-11, BUY EXECUTED Price: 132.50, Cost: 13250.00, Comm 1.32
2020-03-13, SELL EXECUTED Price: 120.00, Cost: 13250.00, Comm 1.20
2020-03-13, ******************************交易结果******************************
2020-03-13, 本次交易毛利润:-1250.00,扣除交易费用后的净利润:-1252.53
2020-03-13, 交易亏损: 383
2020-03-13, 交易长度: 2
2020-03-13, ************************************************************
2020-04-08, BUY EXECUTED Price: 124.14, Cost: 12414.00, Comm 1.24
2020-09-25, SELL EXECUTED Price: 217.01, Cost: 12414.00, Comm 2.17
2020-09-25, ******************************交易结果******************************
2020-09-25, 本次交易毛利润:9287.00,扣除交易费用后的净利润:9283.59
2020-09-25, 交易获利: 384
2020-09-25, 交易长度: 117
2020-09-25, ************************************************************
2020-10-12, BUY EXECUTED Price: 229.00, Cost: 22900.00, Comm 2.29
2021-02-26, SELL EXECUTED Price: 280.56, Cost: 22900.00, Comm 2.81
2021-02-26, ******************************交易结果******************************
2021-02-26, 本次交易毛利润:5156.00,扣除交易费用后的净利润:5150.90
2021-02-26, 交易获利: 385
2021-02-26, 交易长度: 93
2021-02-26, ************************************************************
2021-04-28, BUY EXECUTED Price: 275.00, Cost: 27500.00, Comm 2.75
2021-05-10, SELL EXECUTED Price: 270.58, Cost: 27500.00, Comm 2.71
2021-05-10, ******************************交易结果******************************
2021-05-10, 本次交易毛利润:-442.00,扣除交易费用后的净利润:-447.46
2021-05-10, 交易亏损: 386
2021-05-10, 交易长度: 5
2021-05-10, ************************************************************
2021-05-17, BUY EXECUTED Price: 288.22, Cost: 28822.00, Comm 2.88
2021-07-05, SELL EXECUTED Price: 284.17, Cost: 28822.00, Comm 2.84
2021-07-05, ******************************交易结果******************************
2021-07-05, 本次交易毛利润:-405.00,扣除交易费用后的净利润:-410.72
2021-07-05, 交易亏损: 387
2021-07-05, 交易长度: 34
2021-07-05, ************************************************************
2021-10-13, BUY EXECUTED Price: 228.37, Cost: 22837.00, Comm 2.28
2021-10-19, SELL EXECUTED Price: 213.00, Cost: 22837.00, Comm 2.13
2021-10-19, ******************************交易结果******************************
2021-10-19, 本次交易毛利润:-1537.00,扣除交易费用后的净利润:-1541.41
2021-10-19, 交易亏损: 388
2021-10-19, 交易长度: 4
2021-10-19, ************************************************************
2021-10-25, BUY EXECUTED Price: 223.00, Cost: 22300.00, Comm 2.23
2021-10-26, SELL EXECUTED Price: 220.36, Cost: 22300.00, Comm 2.20
2021-10-26, ******************************交易结果******************************
2021-10-26, 本次交易毛利润:-264.00,扣除交易费用后的净利润:-268.43
2021-10-26, 交易亏损: 389
2021-10-26, 交易长度: 1
2021-10-26, ************************************************************
2021-11-22, BUY EXECUTED Price: 214.00, Cost: 21400.00, Comm 2.14
2022-01-04, SELL EXECUTED Price: 222.66, Cost: 21400.00, Comm 2.23
2022-01-04, ******************************交易结果******************************
2022-01-04, 本次交易毛利润:866.00,扣除交易费用后的净利润:861.63
2022-01-04, 交易获利: 390
2022-01-04, 交易长度: 30
2022-01-04, ************************************************************
2022-05-31, BUY EXECUTED Price: 166.00, Cost: 16600.00, Comm 1.66
2022-08-03, SELL EXECUTED Price: 175.88, Cost: 16600.00, Comm 1.76
2022-08-03, ******************************交易结果******************************
2022-08-03, 本次交易毛利润:988.00,扣除交易费用后的净利润:984.58
2022-08-03, 交易获利: 391
2022-08-03, 交易长度: 45
2022-08-03, ************************************************************
2022-11-30, BUY EXECUTED Price: 154.80, Cost: 15480.00, Comm 1.55
2023-03-13, SELL EXECUTED Price: 195.00, Cost: 15480.00, Comm 1.95
2023-03-13, ******************************交易结果******************************
2023-03-13, 本次交易毛利润:4020.00,扣除交易费用后的净利润:4016.50
2023-03-13, 交易获利: 392
2023-03-13, 交易长度: 67
2023-03-13, ************************************************************
2023-06-15, BUY EXECUTED Price: 179.21, Cost: 17921.00, Comm 1.79
2023-06-27, SELL EXECUTED Price: 164.17, Cost: 17921.00, Comm 1.64
2023-06-27, ******************************交易结果******************************
2023-06-27, 本次交易毛利润:-1504.00,扣除交易费用后的净利润:-1507.43
2023-06-27, 交易亏损: 393
2023-06-27, 交易长度: 6
2023-06-27, ************************************************************
2023-07-14, BUY EXECUTED Price: 173.60, Cost: 17360.00, Comm 1.74
2023-08-15, SELL EXECUTED Price: 168.61, Cost: 17360.00, Comm 1.69
2023-08-15, ******************************交易结果******************************
2023-08-15, 本次交易毛利润:-499.00,扣除交易费用后的净利润:-502.42
2023-08-15, 交易亏损: 394
2023-08-15, 交易长度: 22
2023-08-15, ************************************************************
2023-11-07, BUY EXECUTED Price: 159.30, Cost: 15930.00, Comm 1.59
2023-11-14, SELL EXECUTED Price: 155.88, Cost: 15930.00, Comm 1.56
2023-11-14, ******************************交易结果******************************
2023-11-14, 本次交易毛利润:-342.00,扣除交易费用后的净利润:-345.15
2023-11-14, 交易亏损: 395
2023-11-14, 交易长度: 5
2023-11-14, ************************************************************
Final Portfolio Value: 119573.10
4. 拓展策略思考
考虑其他的指标,用于控制交易。
实际上可认为是多重交易信号,来判断是否交易,比如短期信号修改为RSI信号。
从策略角度看,三重滤网,可以做成四重,多重滤网,提高交易的稳定性和可靠性,大大降低交易的频率。滤网限制越多,其负面效果就是开仓的概率非常小,甚至整个市场都没有符合交易的标的。
总之一句话,鱼和熊掌不可兼得。
class TripleScreenStrategy(bt.Strategy):
params = (
('fast_ma', 14), # 中期均线
('slow_ma', 56), # 长期均线
('rsi_period', 14), # RSI周期
('rsi_overbought', 70), # RSI超买
('rsi_oversold', 30), # RSI超卖
)
def __init__(self):
# 加载指标
self.fast_ma = btind.SMA(period=self.params.fast_ma)
self.slow_ma = btind.SMA(period=self.params.slow_ma)
self.rsi = btind.RSI(period=self.params.rsi_period)
# 设定买入和卖出条件
self.buy_cond = bt.And(
self.data.close > self.slow_ma, # 长期趋势向上
self.data.close > self.fast_ma # 中期趋势向上
)
self.sell_cond = bt.And(
self.data.close < self.slow_ma, # 长期趋势向下
self.data.close < self.fast_ma # 中期趋势向下
)
def next(self):
if not self.position: # 如果没有持仓
if self.buy_cond[0] and self.rsi[0] < self.params.rsi_oversold : # RSI超卖
self.buy()
elif self.sell_cond[0] and self.rsi[0] > self.params.rsi_overbought : # RSI超买
self.sell()