一、前言
双均线策略是最经典的量化交易策略之一。它简单易懂,逻辑清晰,是入门量化交易的最佳实践。本文将完整实现一个双均线策略,并进行模拟交易测试。
二、为什么选择天勤量化(TqSdk)
开发量化交易策略需要一个功能完整的框架。**天勤量化(TqSdk)**是目前国内最适合个人投资者的期货量化平台:
| 模拟交易 | 内置TqSim模拟盘,无需开户即可测试策略 |
| 回测功能 | 支持历史数据回测,验证策略有效性 |
| 实盘对接 | 支持对接实盘账户,一套代码模拟实盘通用 |
| 多账户 | 支持同时管理多个交易账户 |
| 7×24小时 | 支持外盘期货交易时段 |
| 技术指标 | 内置近百个技术指标函数及源码 |
安装方法:
pip install tqsdk
重要提示:建议先使用模拟盘充分测试策略,确认无误后再考虑实盘交易。
三、策略原理
3.1 双均线策略逻辑
双均线策略使用两条不同周期的均线:
- 快线:周期短,反应灵敏(如MA5)
- 慢线:周期长,反应平稳(如MA20)
3.2 交易信号
| 金叉 | 快线从下向上穿越慢线 | 做多 |
| 死叉 | 快线从上向下穿越慢线 | 做空 |
3.3 策略优缺点
| 逻辑简单清晰 | 震荡行情亏损 |
| 能捕捉大趋势 | 信号滞后 |
| 参数少,易优化 | 假信号较多 |
四、策略实现
4.1 完整代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
策略:双均线金叉死叉策略
说明:本代码仅供学习参考,不构成投资建议
"""
from tqsdk import TqApi, TqAuth, TargetPosTask
from tqsdk.tafunc import ma
# 策略参数
SYMBOL = "SHFE.rb2510" # 交易合约(请根据实际情况修改为当前主力合约)
SHORT = 5 # 短周期(快线)
LONG = 20 # 长周期(慢线)
VOLUME = 1 # 交易手数
# 创建API(使用模拟交易,无需实盘账户)
api = TqApi(auth=TqAuth("快期账户", "快期密码"))
# 获取K线数据,数据长度需要大于最长周期
data_length = LONG + 2
klines = api.get_kline_serial(SYMBOL, duration_seconds=60, data_length=data_length)
# 创建目标持仓管理工具
target_pos = TargetPosTask(api, SYMBOL)
print("双均线策略启动")
print(f"合约: {SYMBOL}")
print(f"参数: MA{SHORT} / MA{LONG}")
print("=" * 60)
while True:
api.wait_update()
# 当产生新K线时重新计算均线
if api.is_changing(klines.iloc[–1], "datetime"):
# 使用tafunc.ma计算均线
short_avg = ma(klines["close"], SHORT) # 短周期均线
long_avg = ma(klines["close"], LONG) # 长周期均线
# 获取当前和上一根K线的均线值
current_short = short_avg.iloc[–1]
current_long = long_avg.iloc[–1]
prev_short = short_avg.iloc[–2]
prev_long = long_avg.iloc[–2]
close = klines.iloc[–1]["close"]
# 均线上穿(金叉):做多
if prev_short < prev_long and current_short > current_long:
target_pos.set_target_volume(VOLUME)
print(f"【金叉】做多 | 价格:{close:.0f} | MA{SHORT}:{current_short:.0f} > MA{LONG}:{current_long:.0f}")
# 均线下穿(死叉):做空
if prev_short > prev_long and current_short < current_long:
target_pos.set_target_volume(–VOLUME)
print(f"【死叉】做空 | 价格:{close:.0f} | MA{SHORT}:{current_short:.0f} < MA{LONG}:{current_long:.0f}")
# 打印当前状态
print(f"价格:{close:.0f} | MA{SHORT}:{current_short:.0f} | MA{LONG}:{current_long:.0f}")
4.2 代码解析
| 导入模块 | 直接从tqsdk导入TqApi、TqAuth、TargetPosTask |
| tafunc.ma | 官方提供的移动平均线计算函数,返回pandas.Series |
| duration_seconds | K线周期,60表示1分钟线,86400表示日线 |
| data_length | K线数据长度,需大于最长均线周期 |
| is_changing | 检测数据变化,"datetime"变化表示产生新K线 |
| TargetPosTask | 目标持仓工具,正数做多,负数做空,0平仓 |
4.3 使用tafunc辅助函数
TqSdk提供了专门的crossup和crossdown函数来判断金叉死叉:
from tqsdk import TqApi, TqAuth, TargetPosTask
from tqsdk.tafunc import ma, crossup, crossdown
# … 前面代码省略 …
while True:
api.wait_update()
if api.is_changing(klines.iloc[–1], "datetime"):
short_avg = ma(klines["close"], SHORT)
long_avg = ma(klines["close"], LONG)
# 使用crossup判断金叉
golden_cross = crossup(short_avg, long_avg)
# 使用crossdown判断死叉
dead_cross = crossdown(short_avg, long_avg)
# 判断最新K线是否发生金叉/死叉
if golden_cross.iloc[–1] == 1:
target_pos.set_target_volume(VOLUME)
print("【金叉】做多")
if dead_cross.iloc[–1] == 1:
target_pos.set_target_volume(–VOLUME)
print("【死叉】做空")
五、策略优化
5.1 添加过滤条件
from tqsdk.tafunc import ma
# 只在均线多头排列时做多
def is_bullish_trend(klines):
ma5 = ma(klines["close"], 5).iloc[–1]
ma10 = ma(klines["close"], 10).iloc[–1]
ma20 = ma(klines["close"], 20).iloc[–1]
return ma5 > ma10 > ma20
# 只在均线空头排列时做空
def is_bearish_trend(klines):
ma5 = ma(klines["close"], 5).iloc[–1]
ma10 = ma(klines["close"], 10).iloc[–1]
ma20 = ma(klines["close"], 20).iloc[–1]
return ma5 < ma10 < ma20
# 修改交易逻辑
if prev_short < prev_long and current_short > current_long:
if is_bullish_trend(klines): # 添加过滤
target_pos.set_target_volume(VOLUME)
5.2 添加止损
from tqsdk import TqApi, TqAuth, TargetPosTask
from tqsdk.tafunc import ma
# … 前面代码省略 …
# 获取持仓引用
position = api.get_position(SYMBOL)
STOP_LOSS_POINTS = 30 # 止损点数
while True:
api.wait_update()
# 止损检查
if position.pos_long > 0:
entry = position.open_price_long
close = klines.iloc[–1]["close"]
if close < entry – STOP_LOSS_POINTS:
target_pos.set_target_volume(0)
print(f"【止损】平多仓 | 入场:{entry:.0f} | 现价:{close:.0f}")
if position.pos_short > 0:
entry = position.open_price_short
close = klines.iloc[–1]["close"]
if close > entry + STOP_LOSS_POINTS:
target_pos.set_target_volume(0)
print(f"【止损】平空仓 | 入场:{entry:.0f} | 现价:{close:.0f}")
# 原有的金叉死叉逻辑…
六、参数选择
6.1 常用参数组合
| 激进 | 5 | 10 | 短线交易 |
| 标准 | 5 | 20 | 日内波段 |
| 稳健 | 10 | 30 | 中线交易 |
| 长线 | 20 | 60 | 趋势跟踪 |
6.2 参数选择建议
| 快慢比例 | 慢线周期通常是快线的3-5倍 |
| 根据波动 | 波动大的品种用大周期 |
| 根据成本 | 考虑手续费和滑点 |
七、策略改进思路
7.1 三均线策略
from tqsdk import TqApi, TqAuth, TargetPosTask
from tqsdk.tafunc import ma
# 三均线策略参数
FAST = 5
MID = 10
SLOW = 20
# … API初始化代码省略 …
while True:
api.wait_update()
if api.is_changing(klines.iloc[–1], "datetime"):
ma_fast = ma(klines["close"], FAST).iloc[–1]
ma_mid = ma(klines["close"], MID).iloc[–1]
ma_slow = ma(klines["close"], SLOW).iloc[–1]
# 三线多头排列做多
if ma_fast > ma_mid > ma_slow:
target_pos.set_target_volume(1)
print("多头排列,做多")
# 三线空头排列做空
elif ma_fast < ma_mid < ma_slow:
target_pos.set_target_volume(–1)
print("空头排列,做空")
# 其他情况空仓
else:
target_pos.set_target_volume(0)
print("均线缠绕,空仓观望")
7.2 结合其他指标
TqSdk内置了丰富的技术指标函数:
from tqsdk.ta import ATR, BOLL, MACD, KDJ, RSI
# ATR动态止损
atr = ATR(klines, 14)
stop_loss = atr["atr"].iloc[–1] * 2 # 2倍ATR止损
# 布林带辅助判断
boll = BOLL(klines, 20, 2)
upper = boll["top"].iloc[–1]
lower = boll["bottom"].iloc[–1]
# MACD确认趋势
macd = MACD(klines, 12, 26, 9)
dif = macd["dif"].iloc[–1]
dea = macd["dea"].iloc[–1]
| MACD | 确认趋势方向 |
| RSI | 过滤超买超卖 |
| ATR | 动态止损 |
| BOLL | 判断价格位置 |
| KDJ | 短期超买超卖 |
八、回测验证
TqSdk支持对策略进行历史回测:
from tqsdk import TqApi, TqAuth, TqBacktest, TargetPosTask
from tqsdk.tafunc import ma
from datetime import date
# 创建回测API
api = TqApi(
backtest=TqBacktest(start_dt=date(2024, 1, 1), end_dt=date(2024, 6, 30)),
auth=TqAuth("快期账户", "快期密码")
)
SYMBOL = "SHFE.rb2405"
SHORT, LONG = 5, 20
klines = api.get_kline_serial(SYMBOL, duration_seconds=60, data_length=LONG + 2)
target_pos = TargetPosTask(api, SYMBOL)
account = api.get_account()
try:
while True:
api.wait_update()
if api.is_changing(klines.iloc[–1], "datetime"):
short_avg = ma(klines["close"], SHORT)
long_avg = ma(klines["close"], LONG)
# 金叉做多
if short_avg.iloc[–2] < long_avg.iloc[–2] and short_avg.iloc[–1] > long_avg.iloc[–1]:
target_pos.set_target_volume(1)
# 死叉做空
if short_avg.iloc[–2] > long_avg.iloc[–2] and short_avg.iloc[–1] < long_avg.iloc[–1]:
target_pos.set_target_volume(–1)
except Exception as e:
print(f"回测结束: {e}")
finally:
# 打印回测结果
print(f"期末权益: {account.balance:.2f}")
print(f"盈亏: {account.balance – 1000000:.2f}")
api.close()
九、总结
9.1 策略要点
| 核心信号 | 金叉做多,死叉做空 |
| 适用行情 | 趋势行情 |
| 不适用 | 震荡行情 |
| 优化方向 | 添加过滤条件、止损 |
9.2 TqSdk核心API
| TqApi | 核心接口,连接行情和交易 |
| TqAuth | 账户认证 |
| TargetPosTask | 目标持仓工具,自动处理开平仓 |
| get_kline_serial | 获取K线数据 |
| tafunc.ma | 移动平均线计算 |
| tafunc.crossup/crossdown | 金叉死叉判断 |
| is_changing | 检测数据变化 |
9.3 实盘注意
下一步学习:
- 布林带突破策略
- 海龟交易策略
免责声明:本文仅供学习交流使用,不构成任何投资建议。期货交易有风险,入市需谨慎。
更多资源:
- 天勤量化官网:https://www.shinnytech.com
- GitHub开源地址:https://github.com/shinnytech/tqsdk-python
- 官方文档:https://doc.shinnytech.com/tqsdk/latest


