
等级: 新手上路
- 注册:
- 2025-2-19
- 曾用名:
|
import backtrader as bt
import datetime
class EnhancedGoldenCross(bt.Strategy):
params = (
('fast', 5),
('slow', 20),
('trend', 200),
('rsi_period', 14),
('rsi_upper', 70),
('atr_period', 14),
('risk_reward', 2),
('pos_size', 0.1),
('vol_filter', 20),
('use_trailing_stop', True),
)
def __init__(self):
# 核心指标
self.fast_ma = bt.indicators.EMA(self.data.close, period=self.p.fast)
self.slow_ma = bt.indicators.EMA(self.data.close, period=self.p.slow)
self.trend_ma = bt.indicators.EMA(self.data.close, period=self.p.trend)
# 辅助指标
self.macd = bt.indicators.MACDHisto(self.data.close)
self.rsi = bt.indicators.RSI(self.data.close, period=self.p.rsi_period)
self.atr = bt.indicators.ATR(self.data, period=self.p.atr_period)
self.vol_ma = bt.indicators.SMA(self.data.volume, period=self.p.vol_filter)
# 交易状态跟踪
self.order = None
self.stop_order = None
self.entry_price = 0
self.max_price = 0
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
self.entry_price = order.executed.price
self.max_price = self.entry_price
# 计算动态止损止盈
stop_loss = self.entry_price - 2 * self.atr[0]
take_profit = self.entry_price + 4 * self.atr[0]
# 创建保护订单
self.stop_order = self.sell(exectype=bt.Order.Stop,
price=stop_loss,
parent=order)
self.take_profit = self.sell(exectype=bt.Order.Limit,
price=take_profit,
parent=order)
elif order.issell():
self.entry_price = 0
self.max_price = 0
# 取消关联订单
if self.stop_order:
self.cancel(self.stop_order)
if self.take_profit:
self.cancel(self.take_profit)
self.order = None
def next(self):
# 跳过非交易时段
if self.data.datetime.time() < datetime.time(9, 30) or \
self.data.datetime.time() > datetime.time(16, 0):
return
# 有未完成订单时跳过
if self.order:
return
# 获取当前账户价值
port_value = self.broker.getvalue()
# 平仓逻辑
if self.position:
# 更新最高价跟踪
self.max_price = max(self.max_price, self.data.close[0])
# 趋势破位平仓
if self.data.close[0] < self.fast_ma[0]:
self.close()
# 动态跟踪止损
if self.p.use_trailing_stop:
trail_stop = self.max_price - 1.5 * self.atr[0]
if trail_stop > self.stop_order.price:
self.cancel(self.stop_order)
self.stop_order = self.sell(exectype=bt.Order.Stop,
price=trail_stop)
# 开仓逻辑
else:
# 核心条件:均线金叉
cross_over = (self.fast_ma[0] > self.slow_ma[0]) and \
(self.fast_ma[-1] <= self.slow_ma[-1])
# 过滤条件
trend_filter = self.data.close[0] > self.trend_ma[0]
momentum_filter = self.macd.histo[0] > 0
volume_filter = self.data.volume[0] > self.vol_ma[0]
volatility_filter = self.atr[0] < 0.03 * self.data.close[0]
rsi_filter = self.rsi[0] < self.p.rsi_upper
if cross_over and trend_filter and momentum_filter and \
volume_filter and volatility_filter and rsi_filter:
# 计算仓位规模
size = (port_value * self.p.pos_size) / self.data.close[0]
self.order = self.buy(size=size)
def stop(self):
self.log('最终组合价值: %.2f' % self.broker.getvalue())
def log(self, txt, dt=None):
dt = dt or self.data.datetime[0]
dt = bt.num2date(dt)
print('%s, %s' % (dt.isoformat(), txt))
if __name__ == '__main__':
cerebro = bt.Cerebro()
# 添加数据
data = bt.feeds.YahooFinanceData(
dataname='AAPL',
fromdate=datetime.datetime(2015, 1, 1),
todate=datetime.datetime(2023, 1, 1),
buffered=True
)
cerebro.adddata(data)
# 策略配置
cerebro.addstrategy(EnhancedGoldenCross)
cerebro.broker.setcash(100000)
cerebro.broker.setcommission(commission=0.0005) # 0.05%手续费
cerebro.broker.set_slippage_perc(0.005) # 0.5%滑点
# 添加分析
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
cerebro.addanalyzer(bt.analyzers.SharpeRatio, riskfreerate=0.0)
# 执行回测
results = cerebro.run()
# 输出结果
strat = results[0]
print('夏普比率:', strat.analyzers.sharperatio.get_analysis()['sharperatio'])
print('最大回撤:', strat.analyzers.drawdown.get_analysis()['max']['drawdown'])
# 绘制图表
cerebro.plot()
|
-
|