import pandas as pd
# 假设已加载 1H 数据 df_1h
# 示例:把 1H 汇总成 4H
df_4h = df_1h.resample("4H").agg({
"open": "first",
"high": "max",
"low": "min",
"close": "last",
"volume": "sum"
}).dropna()
# 合并 1H + 4H(右对齐)
merged = df_1h.join(df_4h, rsuffix="_4h", how="left").ffill()
merged.tail()
示意图(可在 Notebook 画):
from IPython.display import Markdown
Markdown("""
**Multi-Timeframe Logic**
- Higher TF → 市场趋势方向 (4H)
- Lower TF → 精准入场 (1H)
""")
import backtrader as bt
class MTFStrategy(bt.Strategy):
def __init__(self):
# lower timeframe data0 (1H)
self.data_close = self.datas[0].close
# higher timeframe data1 (4H)
self.data_close_4h = self.datas[1].close
def next(self):
# 过滤条件:4H 趋势向上
trend_up = self.data_close_4h[0] > self.data_close_4h[-1]
# 入场条件:1H 突破
breakout = self.data_close[0] > max(self.data_close[-3:-1])
if trend_up and breakout:
self.buy()
# === 注册数据 ===
cerebro = bt.Cerebro()
data1h = bt.feeds.PandasData(dataname=df_1h)
data4h = bt.feeds.PandasData(dataname=df_4h)
cerebro.adddata(data1h)
cerebro.adddata(data4h)
cerebro.addstrategy(MTFStrategy)
cerebro.run()
# 回测结果
res = cerebro.run()[0]
cerebro.plot()
# 手动计算比较
perf = {
"mtf_pnl": res.broker.getvalue(),
}
print(perf)
时间戳对齐检查:
print(df_1h.index[-5:])
print(df_4h.index[-5:])
import numpy as np
df_1h['volume_surge'] = df_1h['volume'] > df_1h['volume'].rolling(20).mean() * 1.5
df_1h['breakout'] = df_1h['close'] > df_1h['high'].rolling(20).max()
# backtrader 用 indicator 版本(简单示例)
class MTFStrategy(bt.Strategy):
def next(self):
trend_up = self.data_close_4h[0] > self.data_close_4h[-1]
breakout = self.data_close[0] > max(self.data_close[-20:-1])
vol_surge = self.datas[0].volume[0] > bt.indicators.SMA(self.datas[0].volume, 20)[0] * 1.5
if trend_up and breakout and vol_surge:
self.buy()
import random
ORDER_DELAY = 2 # 2 根K线延迟
MISS_PROB = 0.1 # 10% 漏单概率
class DelayStrategy(bt.Strategy):
def next(self):
# 延迟触发
if len(self) >= ORDER_DELAY:
delayed_price = self.data_close[-ORDER_DELAY]
else:
delayed_price = self.data_close[0]
# 漏单
if random.random() < MISS_PROB:
return
# 示例:在突破时用延迟价格入场
breakout = self.data_close[0] > max(self.data_close[-3:-1])
if breakout:
self.buy(price=delayed_price)