from tqsdk import TqApi, TqAuth, TqBacktest, TargetPosTask, BacktestFinished
from datetime import date,datetime
from tqsdk.ta import MA # 新增导入
# ====================== 策略参数配置 ======================
# SYMBOL = “KQ.m@SHFE.AL2509” # 氧化铝202509 主连(回测推荐用主连,数据完整)
SYMBOL = “SHFE.ao2606” # 如需直接回测指定合约,取消注释这行,注释上一行
PERIOD = “5min” # 5分钟K线周期
MA_FAST = 5 # 快均线:5日均线
MA_SLOW = 20 # 慢均线:20日均线
# ====================== 回测初始化 ======================
api = TqApi(
auth=TqAuth(“xxx”, “.xxx”), # 必须填写你的信易账号
backtest=TqBacktest(
start_dt=date(2026, 5, 1), # 回测开始日期
end_dt=date(2026, 5, 29) # 回测结束日期
),
web_gui=”http://127.0.0.1:3001″
)
# 获取K线数据
klines = api.get_kline_serial(SYMBOL, duration_seconds=300, data_length=MA_SLOW+2)
# 目标持仓任务(TqSdk标准持仓管理)
target_pos = TargetPosTask(api, SYMBOL)
print(“=” * 50)
print(f”启动回测 | 合约:{SYMBOL} | 周期:{PERIOD} | 均线:{MA_FAST}日 & {MA_SLOW}日”)
print(“=” * 50)
try:
while True:
# 等待行情更新
api.wait_update()
# 仅在新K线生成时计算指标(避免重复计算)
if api.is_changing(klines.iloc[-1], “datetime”):
# 计算均线(使用收盘价)
ma_fast_val = klines.close.rolling(MA_FAST).mean().iloc[-1]
ma_slow_val = klines.close.rolling(MA_SLOW).mean().iloc[-1]
# 上一根K线的均线值(用于判断金叉死叉)
pre_ma_fast = klines.close.rolling(MA_FAST).mean().iloc[-2]
pre_ma_slow = klines.close.rolling(MA_SLOW).mean().iloc[-2]
dt = datetime.fromtimestamp(klines.iloc[-1].datetime / 1000000000)
print(f”时间:{dt} | 5均线:{ma_fast_val:.3f} | 20均线:{ma_slow_val:.3f}”)
# ====================== 交易逻辑 ======================
# 金叉:5日均线上穿20日均线 → 做多
if pre_ma_fast < pre_ma_slow and ma_fast_val > ma_slow_val:
print(“👉 金叉信号 → 开多仓”)
target_pos.set_target_volume(1) # 1手多单
# 死叉:5日均线下穿20日均线 → 做空/平多
elif pre_ma_fast > pre_ma_slow and ma_fast_val < ma_slow_val:
print(“👉 死叉信号 → 平多仓/开空仓”)
target_pos.set_target_volume(0) # 平仓
except BacktestFinished:
# 回测结束,输出统计报告
print(“\n” + “=” * 50)
print(“✅ 回测执行完毕!”)
api.close()