小果QMT与Ptrade策略转换助手
> 作者:小果(微信:xg_quant)
> 版本:1.0.0
> 覆盖平台:迅投 QMT(极速策略交易系统) · 恒生 Ptrade 量化交易终端
> 文档规模:QMT 参考资料 129 篇 + Ptrade 参考资料 80 篇(已按平台合并为 8 个大文档)+ 策略源码 69 个 + 策略示例 24 个
> 文件总数:116 个(满足 ≤200 个文件的数量限制)
> 声明:仅做学习与研究使用,不构成投资建议,注意风险。
一、这个技能解决什么问题
同一个策略思路,写到 QMT 和 Ptrade 上就是两套完全不同的代码:QMT 用 ContextInfo 对象 + passorder(...) 十一参下单,Ptrade 用全局函数 + order(...) 下单;QMT 的 K 线入口叫 handlebar,Ptrade 叫 handle_data;QMT 代码后缀是 .SH/.SZ,Ptrade 是 .SS/.SZ。
本技能把这两套体系逐项对齐,让你能:
| 能力 | 说明 | 落地位置 |
|---|---|---|
| 双向移植 | QMT 策略 → Ptrade 策略,Ptrade 策略 → QMT 策略 | 本文 §七 工作流 |
| API 映射 | 八大类 API 一比一对照(含参数语义差异) | 本文 §四 映射总表 |
| 代码格式转换 | 600000.SH ↔ 600000.SS 等后缀互转 |
本文 §五 + scripts/qmt_ptrade_converter.py |
| 误用检查 | 检出"在 Ptrade 里写 QMT 语法"这类必炸的错 | scripts/validate_strategy.py |
| 避坑指南 | 15 条跨平台高频坑 + 报错对照表 | 本文 §八 / §九 |
| 成品模板 | 两平台可跑的双均线、网格、动量轮动、多因子等 | scripts/、assets/ |
| 全量手册 | 两平台官方函数原型 / 参数 / 返回值(按平台合并为 8 个大文档) | references/QMT/、references/Ptrade/ |
二、双平台总览对照
| 维度 | 迅投 QMT | 恒生 Ptrade |
|---|---|---|
| 运行环境 | 内置 Python 3.6(迅投研终端 / 券商版 QMT) | 云端 Python 策略引擎(券商 Ptrade 终端) |
| 代码入口 | init(ContextInfo) + handlebar(ContextInfo) |
initialize(context) + handle_data(context, data) |
| 上下文 | ContextInfo(C 对象,逐 K 回滚) |
context + g(Python 对象,不回滚) |
| 驱动方式 | 逐 K 线驱动 / 事件驱动 / 定时任务 | handle_data 周期驱动 + run_daily / run_interval 定时 |
| 下单核心 | passorder(opType, orderType, ...) 十一参 |
order(security, amount, limit_price=None) |
| 取数核心 | ContextInfo.get_market_data_ex(...) |
get_price(...) / get_history(...) |
| 文件编码 | 必须 #coding:gbk(或 # coding:gbk) |
UTF-8(带 BOM 亦可) |
| 标的代码 | 600000.SH / 000001.SZ / 510300.SH |
600000.SS / 000001.SZ / 510300.SS |
| 运行模式 | 调试 / 回测 / 模拟信号 / 实盘(界面手动选) | 回测 / 实盘(回测通过后开启实盘) |
| 第三方库 | 白名单制,未开通报 ImportError: Forbidden |
自带常见三方库(见参考文档「支持的三方库」) |
| 本地数据 | 需先 download_history_data 补数据 |
云端统一数据,无需本地补数 |
| API 风格 | 对象方法为主:ContextInfo.xxx() |
全局函数为主:get_xxx() / order() |
> 一句话记忆:QMT 是"对象 + 十一参下单",Ptrade 是"全局函数 + 正负持仓下单"。
三、代码骨架对照(可直接套用)
3.1 QMT 最小可运行骨架
#coding:gbk # 【QMT 必须】第一行声明编码,否则中文报错
import numpy as np
class G: # QMT 禁止在 ContextInfo 上存状态(逐K回滚会丢),用全局类承载
pass
g = G()
def init(ContextInfo):
g.stock = '000001.SZ'
g.accid = '你的资金账号'
ContextInfo.start = '2020-01-01 00:00:00'
ContextInfo.end = '2023-12-31 00:00:00'
ContextInfo.capital = 1000000
def handlebar(ContextInfo):
# 回测:先补本地数据;实盘:subscribe=True 用实时行情
data = ContextInfo.get_market_data_ex(
['close'], [g.stock], period='1d', count=20,
dividend_type='front', subscribe=False)
close = data[g.stock]['close']
if len(close) < 20:
return
ma5, ma20 = close[-5:].mean(), close[-20:].mean()
vol = 100 # 股数(ETF/股票 100 股 = 1 手)
if ma5 > ma20:
passorder(23, 1101, g.accid, g.stock, 5, -1, vol,
'小果策略', 2, '金叉买入', ContextInfo)
else:
passorder(24, 1101, g.accid, g.stock, 5, -1, vol,
'小果策略', 2, '死叉卖出', ContextInfo)
3.2 Ptrade 最小可运行骨架(同一策略的 Ptrade 版)
# -*- coding: utf-8 -*- # Ptrade 用 UTF-8,不需要 gbk
import numpy as np
STOCK = '000001.SZ' # 注意:沪市为 .SS
SHORT = 5
LONG = 20
VOLUME = 100
def initialize(context):
set_universe([STOCK]) # 【Ptrade 必须】设置股票池
set_benchmark('000300.SS') # 基准
set_commission(commission_ratio=0.0003, min_commission=5.0, type='STOCK')
set_slippage(0.002)
g.stock = STOCK
g.hold = False
def handle_data(context, data):
df = get_price(g.stock, frequency='1d', fields=['close'],
count=LONG + 5, fq='pre')
close = df['close'].values
if len(close) < LONG:
return
ma_s, ma_l = close[-SHORT:].mean(), close[-LONG:].mean()
if ma_s > ma_l and not g.hold:
order(g.stock, VOLUME) # 正数买入
g.hold = True
elif ma_s < ma_l and g.hold:
order(g.stock, -context.portfolio.positions[g.stock].enable_amount) # 负数卖出,T+1 用可用持仓
g.hold = False
对照要点:编码行、入口函数名、下单调用方式、股票池设置、后缀格式、卖出数量取 enable_amount(T+1)。
四、核心 API 映射总表(QMT ↔ Ptrade)
4.1 策略生命周期
| 用途 | QMT | Ptrade |
|---|---|---|
| 初始化 | init(ContextInfo)(必写) |
initialize(context)(必写) |
| 主循环 | handlebar(ContextInfo)(必写) |
handle_data(context, data)(必写) |
| 盘前 | 无独立钩子,用定时器 | before_trading_start(context, data) |
| 盘后 | 无独立钩子,用定时器 | after_trading_end(context, data) |
| Tick 级 | handlebar 在实盘每 tick 触发 |
tick_data(context, data) |
| init 后一次性 | after_init(ContextInfo) |
在 initialize 末尾直接执行 |
| 停止清理 | stop(ContextInfo) |
无(用 after_trading_end 兜底) |
| 委托/成交回调 | order_callback / deal_callback |
on_order_response(context, order_list) / on_trade_response(context, trade_list) |
| 状态存储 | 全局类实例 g = G()(禁止挂 ContextInfo) |
全局对象 g.xxx = yyy / context.xxx |
4.2 行情数据获取
| 用途 | QMT | Ptrade |
|---|---|---|
| 取 K 线(核心) | ContextInfo.get_market_data_ex(fields, stock_list, period, start_time, end_time, count, dividend_type, fill_data, subscribe) |
get_price(security, start_date, end_date, frequency, fields, fq, count, is_dict) |
| 取多标的历史 | 同上(stock_list 传列表) |
get_history(count, frequency, field, security_list, fq, include, fill, is_dict) |
| 本地历史 | ContextInfo.get_local_data(...) |
无(云端统一提供) |
| 补/下载数据 | download_history_data(stockcode, period, startTime, endTime[, incrementally=True]) |
无需(数据由平台托管) |
| 快照行情 | ContextInfo.get_full_tick(...) / get_market_data_ex(period='tick') |
get_snapshot(security) |
| 五档盘口 | get_market_data_ex(period='l1') / Lv1 全推 |
get_gear_price(sids) |
| 逐笔/明细 | period='l2transaction' / l2order |
get_individual_entrust() / get_individual_transaction() |
| Tick 方向 | L2 数据字段 | get_tick_direction(...) |
| 板块排序 | get_stock_list_in_sector + 自算 |
get_sort_msg(...) |
| 涨跌停名单 | get_instrument_detail 取 UpStopPrice/DownStopPrice |
get_trend_data() / check_limit() |
4.3 证券 / 财务 / 板块信息
| 用途 | QMT | Ptrade |
|---|---|---|
| 证券名称 | get_stock_name(stockcode) |
get_stock_name(stocks) |
| 合约详情 | get_instrument_detail(stockcode) |
get_stock_info(stocks, field) |
| 涨跌停价 | get_instrument_detail(...)['UpStopPrice'] |
check_limit(security) |
| 复权因子 | get_divid_factors / dividend_type 参数 |
get_stock_exrights(stock_code, date) |
| 指数成分股 | get_stock_list_in_sector('沪深300') |
get_index_stocks(index_code, date) |
| 行业成分股 | get_stock_list_in_sector('行业名') |
get_industry_stocks(industry_code) |
| 板块/所属行业 | get_stock_list_in_sector / 板块函数族 |
get_stock_blocks(stock_code) |
| 全部 A 股 | 全推订阅后过滤 | get_Ashares(date) |
| 财务数据 | get_financial_data(fieldList, stockList, startDate, endDate, report_type) |
get_fundamentals(security, table, fields, date, ...) |
| 原始财报 | get_raw_financial_data(...) |
get_fundamentals(..., merge_type=...) |
| 股本/流通股 | get_total_share() / get_last_volume() |
get_stock_info(fields='total_share') |
| 换手率 | get_turnover_rate(stock_list, startTime, endTime) |
由 get_fundamentals 或行情自算 |
| 交易日历 | get_trading_calendar(market, start, end) / get_trading_dates(...) |
get_trade_days(start, end, count) / get_all_trades_days() |
| ST 状态 | get_st_status(stockcode) / get_his_st_data(...) |
get_stock_status(stocks, query_type='ST') |
| ST/停牌过滤 | 自行比对 | filter_stock_by_status(stocks, filter_type=['ST','HALT','DELISTING']) |
| ETF 列表/信息 | get_etf_info(stockcode) / get_etf_iopv(...) |
get_etf_list() / get_etf_info() / get_etf_stock_list() |
| 可转债 | get_cb_list 类接口 |
get_cb_list() / get_cb_info() |
| 新股新债 | get_ipo_data(type) / get_new_purchase_limit(accid) |
get_ipo_stocks() / ipo_stocks_order(...) |
| 期权 | get_option_detail_data / get_option_list / bsm_price / bsm_iv |
期权相关接口见 references/Ptrade/PTrade_01_API函数手册.txt(22交易相关函数 / 23公共交易函数) |
4.4 交易下单(差异最大,重点看)
| 场景 | QMT | Ptrade |
|---|---|---|
| 综合下单 | passorder(opType, orderType, accountid, orderCode, prType, price, volume, strategyName, quickTrade, userOrderId, ContextInfo) |
order(security, amount, limit_price=None) |
| 买/卖方向 | opType:23 买入、24 卖出(25 组合买、27 融资买、33 担保品买…) |
amount 正数买 / 负数卖 |
| 数量/金额 | orderType:1101 股数、1102 金额、1113 比例 |
数量走 order;金额走 order_value;目标市值 order_target_value |
| 目标持仓 | 需自算差值后 passorder |
order_target(security, amount) |
| 目标市值 | 需自算差值后 passorder |
order_target_value(security, value) |
| 委托价格 | prType:5 最新价、11 指定价、14 对手价(price=-1 表示不限价) |
limit_price:None 市价 / 指定价 |
| 市价单 | prType=5(最新价)或市价枚举 |
order_market(security, amount, market_type, limit_price) |
| 定时器里下单 | quickTrade 必须为 2(立即下单) |
直接调用 order(...) 即可 |
| 逐 K 生效 vs 立即 | quickTrade:0 逐K · 1 最新K立即 · 2 立即下单 |
无此概念(handle_data 内即当根生效) |
| 撤单 | cancel(orderId, accountId, accountType, ContextInfo) |
cancel_order(order_param) / cancel_order_ex(order_param) |
| 算法拆单 | algo_passorder(...) / smart_algo_passorder(..., smartAlgoType='VWAP'/'TWAP', ...) |
order_tick(sid, amount, priceGear) / 拆单类接口 |
| 任务管理 | cancel_task / pause_task / resume_task(taskId) |
委托管理走订单接口 |
| 新股申购 | passorder 特殊 opType / get_new_purchase_limit |
ipo_stocks_order(submarket_type, black_stocks) |
| ETF 篮子 | passorder 组合买入(25)/ 篮子函数 |
etf_basket_order(...) / etf_purchase_redemption(...) |
| 两融 | opType 27/33;get_assure_contract / query_credit_opvolume |
margincash_open/close / marginsec_open/close / margin_trade |
| 期货 | passorder + accountType='FUTURE' |
buy_open / sell_close / sell_open / buy_close |
| 盘后固定价 | passorder 定时 + 指定价 |
after_trading_order(security, amount, entrust_price) / after_trading_cancel_order |
| 转债转股 | 券商接口 | debt_to_stock_order(security, amount) |
> passorder 十一参速记:(操作类型, 下单量类型, 资金账号, 代码, 报价类型, 价格, 数量, 策略名, 快速交易, 备注, ContextInfo)
> 例:passorder(23, 1101, 'acct', '000001.SZ', 5, -1, 100, '小果策略', 2, '买入', ContextInfo)
4.5 账户与查询
| 用途 | QMT | Ptrade |
|---|---|---|
| 资金账户 | get_trade_detail_data(accid, 'STOCK', 'account') → m_dAvailable |
context.portfolio.cash / context.portfolio.total_value |
| 全部持仓 | get_trade_detail_data(accid, 'STOCK', 'position') → m_strInstrumentID / m_nVolume / m_nCanUseVolume |
get_positions() / context.portfolio.positions |
| 单只持仓 | 上述列表过滤 | get_position(security) → total_amount / enable_amount / cost_basis |
| 委托查询 | get_trade_detail_data(accid, 'STOCK', 'order') |
get_orders(security) / get_all_orders(security) |
| 单笔委托 | get_value_by_order_id(orderId, accid, 'STOCK', 'order') |
get_order(order_id) |
| 未成交委托 | 委托列表过滤状态 | get_open_orders(security) |
| 成交查询 | get_trade_detail_data(accid, 'STOCK', 'deal') |
get_trades() |
| 历史成交 | get_history_trade_detail_data(accid, 'STOCK', 'deal', start, end) |
get_deliver(start_date, end_date) |
| 资金流水 | 券商接口 | get_fundjour(start_date, end_date) |
| 中签信息 | 券商接口 | get_lucky_info(start_date, end_date) |
| 账号类型常量 | 'STOCK' 'FUTURE' 'CREDIT' 'FUTURE_OPTION' 'STOCK_OPTION' 'HUGANGTONG' 'SHENGANGTONG' |
由账号/get_business_type() 区分 |
> 命名规律:QMT 里 get_ 开头 = 取客户端内存,query_ 开头 = 向服务端查询(异步,需配合回调)。
4.6 定时任务与回调
| 用途 | QMT | Ptrade |
|---|---|---|
| 注册定时(旧/简) | run_time(funcName, period, startTime),period 如 '5nSecond' / '5nDay' |
run_daily(context, func, time='9:31') |
| 注册定时(新/强) | schedule_run(func, time_point, repeat_times, interval, name) → 返回任务号 |
run_interval(context, func, seconds=10) |
| 取消定时 | cancel_schedule_run(key) |
由 run_* 的返回/重新注册控制 |
| 定时器内下单 | quickTrade 必须传 2,否则信号不落地 |
直接 order(...) |
| 资金账户回调 | account_callback(ContextInfo, accountInfo) |
— |
| 委托回调 | order_callback(ContextInfo, orderInfo) |
on_order_response(context, order_list) |
| 成交回调 | deal_callback(ContextInfo, dealInfo) |
on_trade_response(context, trade_list) |
| 持仓回调 | position_callback(ContextInfo, positionInfo) |
— |
| 任务回调 | task_callback(ContextInfo, taskInfo) |
— |
| 下单异常 | orderError_callback(ContextInfo, orderArgs, errMsg) |
日志 + 订单状态判断 |
| 两融查询回调 | credit_account_callback / credit_opvolume_callback |
— |
| 行情订阅 | ContextInfo.subscribe_quote(code, period, callback) / subscribe_whole_quote(code_list, callback) |
在 initialize 中声明标的即自动订阅 |
| 反订阅 | ContextInfo.unsubscribe_quote(subId) |
— |
4.7 设置 / 工具 / 指标 / 日志
| 用途 | QMT | Ptrade |
|---|---|---|
| 股票池 | 无强制概念(自建列表 + get_stock_list_in_sector) |
set_universe(security_list)(必设) |
| 基准 | ContextInfo.benchmark |
set_benchmark(sids) |
| 初始资金 | ContextInfo.capital |
回测界面设置 |
| 回测区间 | ContextInfo.start / ContextInfo.end(仅 init 生效) |
界面设置 |
| 手续费 | 券商/界面设置 | set_commission(commission_ratio, min_commission, type) |
| 滑点 | 界面设置 | set_slippage(slippage) / set_fixed_slippage(fixedslippage) |
| 成交量限制 | — | set_volume_ratio(volume_ratio) |
| 涨跌停模式 | — | set_limit_mode(limit_mode) |
| 策略参数 | 界面/代码常量 | set_parameters(**kwargs) |
| 日志 | print(...) |
log.debug/info/warning/error/critical(...) |
| 画图 | ContextInfo.paint / draw_text / draw_number / draw_vertline / draw_icon |
平台图表由回测引擎生成 |
| 技术指标现成函数 | 主要靠 xg_tdx_func / 自算 |
get_MACD / get_KDJ / get_RSI / get_CCI |
| 是否交易时段 | ContextInfo.is_last_bar() / 交易时段判断 |
is_trade() |
| 时间戳转换 | timetag_to_datetime(timetag, format) |
原生 datetime |
| 当前周期/进度 | ContextInfo.period / barpos / time_tick_size |
get_frequency() / get_current_kline_count() |
| 邮件/推送 | 券商接口 | send_email(...) / send_qywx(...) |
| 策略自检 | 无 | check_strategy(strategy_content, strategy_path) |
| 资金划转 | 券商接口 | fund_transfer(...) / market_fund_transfer(...) |
| 环境路径 | 本地路径 | get_research_path() / get_trade_name() / get_user_name() |
4.8 数据字典与枚举
委托状态(Ptrade order.status)
| 值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| 含义 | 未报 | 待报 | 已报 | 已报待撤 | 部成待撤 | 部撤 | 已撤 | 部成 | 已成 | 废单 |
QMT orderType(下单量类型):1101 股数/手数 · 1102 金额 · 1113 占总资产比例
QMT prType(报价类型):5 最新价 · 11 指定价(配合 price) · 14 对手价
QMT opType(操作类型):23 股票/ETF/可转债买入 · 24 卖出 · 25 组合买入 · 27 融资买入 · 33 担保品买入(完整枚举见 references/QMT/QMT_01_行情与交易API手册.txt 中的「15枚举常量.txt」与「43变量说明.txt」,以及 references/小果全能大QMT量化交易助手.md 的第四部分「参数枚举值大全」)
五、标的代码格式转换
5.1 后缀对照
| 市场 | QMT(迅投) | Ptrade(恒生) |
|---|---|---|
| 上交所 | 600000.SH |
600000.SS |
| 深交所 | 000001.SZ |
000001.SZ |
| 北交所 | 830779.BJ |
830779.BJ |
| 中金所期货 | IC2311.IF |
IC2311.CFFEX |
| 上期所 | rb2311.SF |
rb2311.SHFE |
| 大商所 | m2311.DF |
m2311.DCE |
| 郑商所 | FG305.ZF |
FG305.CZCE |
| 上能源 | sc2311.INE |
sc2311.INE |
| 广期所 | lc2405.GF |
lc2405.GFEX |
| 上证期权 | 10005334.SHO |
10005334.SS(期权后缀随券商版本) |
> 注:QMT 内部严格区分大小写(rb2401.SF 不能写成 RB2401.SF);部分 Ptrade 版本亦兼容聚宽风格 .XSHG / .XSHE,但推荐统一使用 .SS / .SZ。
5.2 转换规则(可直接用代码实现)
# QMT -> Ptrade
def qmt_to_ptrade(code: str) -> str:
return code.replace('.SH', '.SS').replace('.IF', '.CFFEX') \
.replace('.SF', '.SHFE').replace('.DF', '.DCE') \
.replace('.ZF', '.CZCE').replace('.GF', '.GFEX')
# Ptrade -> QMT
def ptrade_to_qmt(code: str) -> str:
return code.replace('.SS', '.SH').replace('.CFFEX', '.IF') \
.replace('.SHFE', '.SF').replace('.DCE', '.DF') \
.replace('.CZCE', '.ZF').replace('.GFEX', '.GF')
批量转换与整文件改写请直接用 scripts/qmt_ptrade_converter.py:
# 查看文件是 QMT 还是 Ptrade 风格,并列出所有跨平台误用
python scripts/qmt_ptrade_converter.py --check strategy.py
# 只转标的代码后缀(.SH -> .SS 等),原地覆盖前请先备份
python scripts/qmt_ptrade_converter.py --convert-code strategy.py -o strategy_ptrade.py
# 打印 QMT <-> Ptrade API 映射表
python scripts/qmt_ptrade_converter.py --map
六、周期与复权参数对照
| 项目 | QMT | Ptrade |
|---|---|---|
| 日线 | period='1d' / '1d' |
frequency='1d'(部分接口写 'daily') |
| 分钟线 | '1m' '3m' '5m' '15m' '30m' |
'1m' '5m' '15m' '30m' '60m' |
| 小时线 | '1h' |
用 '60m' |
| 周/月/季/半年/年 | '1w' '1mon' '1q' '1hy' '1y' |
以日线合成或见接口文档 |
| 分笔 | 'tick' |
tick_data(context, data) 回调 |
| 不复权 | dividend_type='none' |
fq=None |
| 前复权 | dividend_type='front' |
fq='pre' |
| 后复权 | dividend_type='back' |
fq='post' |
| 前复权(比例) | dividend_type='front_ratio' |
— |
| 后复权(比例) | dividend_type='back_ratio' |
— |
> Ptrade 的 fq='dypre' 表示"上一交易日的前复权价",常用于计算涨跌停/昨收,不是 QMT 的标准枚举,移植时按业务语义处理。
七、双向转换工作流
7.1 QMT → Ptrade(8 步)
- 识别骨架:
init(ContextInfo)→initialize(context);handlebar(ContextInfo)→handle_data(context, data);after_init内容并入initialize末尾。 - 去掉 QMT 专有行:删除
#coding:gbk;把ContextInfo.xxx全部改写为对应全局函数或context.xxx。 - 状态迁移:
g = G()全局类实例上的字段 → 统一迁到g.xxx(Ptrade 已预定义g),不要再挂到context上(回测/实盘会乱)。 - 取数改写:
ContextInfo.get_market_data_ex([...], [...], period=..., count=..., dividend_type=...)→get_price(security, frequency=..., fields=[...], count=..., fq='pre');subscribe=False直接删掉(Ptrade 无需);删除download_history_data(...)。 - 下单改写:
passorder(23, 1101, acc, code, 5, -1, n, name, 2, msg, CI)→order(code, n);opType=24→order(code, -n);orderType=1102→order_value(code, amount);orderType=1113→ 先算股数再order。 - 代码后缀:
.SH → .SS(用 §5.2 规则或--convert-code)。 - 股票池与设置:在
initialize里补set_universe([...])、set_benchmark(...)、set_commission(...)、set_slippage(...)。 - 定时器与回调:
run_time/schedule_run→run_daily/run_interval;order_callback/deal_callback→on_order_response/on_trade_response;定时器里的quickTrade=2不用搬,Ptrade 直接下单即生效。
7.2 Ptrade → QMT(8 步)
- 加编码行:文件首行
#coding:gbk(否则中文注释直接报错)。 - 骨架改写:
initialize(context)→init(ContextInfo);handle_data(context, data)→handlebar(ContextInfo);before_trading_start/after_trading_end→ 用run_time/schedule_run定时器实现。 - 状态迁移:
g.xxx→ 自定义全局类g = G()的字段(QMT 的ContextInfo不可存状态,会被逐 K 回滚清空)。 - 取数改写:
get_price(...)→ContextInfo.get_market_data_ex(...),fq='pre'→dividend_type='front';回测前必须先download_history_data(code, period, start, end)补本地数据,实盘取数加subscribe=True。 - 下单改写:
order(code, n)→passorder(23, 1101, acc, code, 5, -1, n, '策略名', quickTrade, '备注', ContextInfo);order(code, -n)→opType=24;order_target_value(code, v)→ 先查持仓算差值,再用orderType=1102或1101下单。 - 代码后缀:
.SS → .SH。 - 参数替换:窗口期、频率枚举(
'60m' → '1h')、复权枚举按 §六 表替换。删掉set_universe/set_benchmark,改为自建列表 +ContextInfo.benchmark。 - 回测验证:在 QMT 策略编辑器中以「回测模式」跑通,确认无白名单/取数报错后再切「模拟信号」→「实盘」。
7.3 转换后自检清单(逐条打勾)
- [ ] 文件首行编码:QMT 是
#coding:gbk;Ptrade 是 UTF-8(无 gbk 行) - [ ] 入口函数齐全:QMT
init+handlebar;Ptradeinitialize+handle_data - [ ] 无跨平台 API:QMT 文件里无
get_price/set_universe;Ptrade 文件里无ContextInfo/passorder/security. - [ ] 状态全部落在全局
g上,没有挂在ContextInfo/context上 - [ ] 标的后缀已按目标平台改写(
.SH↔.SS等) - [ ] 复权枚举语义一致(QMT
front↔ Ptradepre) - [ ] 卖出数量取"可用持仓"(Ptrade
enable_amount),避免 T+1 废单 - [ ] 数量为 100 的整数倍(股票/ETF)
- [ ] QMT 定时器内
quickTrade=2;Ptrade 定时器内直接下单 - [ ] QMT 回测前已
download_history_data;实盘取数subscribe=True - [ ] 第三方库仅在 QMT 白名单内(
numpy/pandas等默认可用,其余需券商开通) - [ ] 用
python scripts/validate_strategy.py strategy.py跑一遍静态检查
八、跨平台高频坑(15 条)
| # | 坑 | 平台 | 现象 | 正确做法 |
|---|---|---|---|---|
| 1 | ContextInfo 逐 K 回滚 | QMT | 存在 ContextInfo 上的属性下个 tick 就丢了 | 用全局类 g = G() 存状态 |
| 2 | 缺少 #coding:gbk |
QMT | 中文注释/字符串编译报错 | 首行必须写 #coding:gbk |
| 3 | 第三方库白名单 | QMT | ImportError: Forbidden: Module xxx not in whitelist! |
只用白名单库,或联系券商开通 |
| 4 | 编辑器里直接跑下单 | QMT | 下单无反应 | 必须在「模型交易」界面运行 |
| 5 | 定时器下单不生效 | QMT | 定时器里 passorder 无委托 |
quickTrade 传 2(立即下单) |
| 6 | 回测取不到数 | QMT | 数据为空 / K 线全 NaN | 回测前 download_history_data 补数据 |
| 7 | 实盘取数不变 | QMT | 行情永远停留在历史 | get_market_data_ex(..., subscribe=True) |
| 8 | 订阅超限 | QMT | 订阅失败告警 | unsubscribe_quote(subId) 及时释放 |
| 9 | 误用 QMT 对象式 API | Ptrade | name 'security' is not defined |
Ptrade 全是全局函数,禁用 security. / trade. |
| 10 | 忘记 set_universe |
Ptrade | handle_data 拿不到数据 / 股票不在池中 |
initialize 里必须 set_universe([...]) |
| 11 | T+1 卖出超量 | 两平台 | 委托被拒 / 废单 | 卖出数量取 enable_amount(可用持仓) |
| 12 | 数量非 100 整数倍 | 两平台 | 委托被拒 | 股数向下取整到 100 的倍数 |
| 13 | print 当日志 |
Ptrade | 日志面板看不到输出 | 用 log.info(...) |
| 14 | 复权枚举混用 | 两平台 | 指标数值对不上、均线漂移 | QMT front ↔ Ptrade pre,严格按 §六 表 |
| 15 | order_target_value 实盘反复下单 |
Ptrade | 重复买卖、超额买入 | 回测可用,实盘谨慎;如需用需自行去重(记录 g 状态 + 校验持仓) |
九、报错对照速查
| 报错 / 现象 | 所属平台 | 根因 | 解决 |
|---|---|---|---|
SyntaxError: Non-UTF-8 code |
QMT | 少了 #coding:gbk |
首行补编码声明 |
ImportError: Forbidden: Module xxx not in whitelist! |
QMT | 用了非白名单库 | 换白名单库 / 券商开通 |
name 'xxx' is not defined |
Ptrade | 误用 QMT 对象式写法(security. / trade. / get_json) |
改写成 Ptrade 全局函数 |
| 策略不产生任何交易 | Ptrade | 没设股票池 / 回测区间无数据 / 订阅未生效 | set_universe + 检查区间 + 订阅行情 |
股票不在股票池中 |
Ptrade | set_universe 未包含该标的 |
补入 set_universe |
| 下单无反应 | QMT | 在编辑器运行;或 quickTrade 未传 2;或账号未登录 |
切「模型交易」界面、quickTrade=2、检查登录/资金 |
| K 线全为 NaN | QMT | 未下载本地数据 / subscribe 参数反了 |
download_history_data;回测 False、实盘 True |
| 委托被拒 / 废单 | 两平台 | 数量非 100 整数倍、超可用持仓、超出涨跌停 | 数量取整、用 enable_amount、check_limit 校验 |
| 策略状态错乱、条件反复触发 | QMT | 把状态存在 ContextInfo 上被回滚 |
改存全局类 g |
| 回测与实盘结果差异大 | 两平台 | 撮合规则、滑点、手续费未对齐 | Ptrade 用 set_commission/set_slippage;QMT 在界面设置 |
十、内置策略与模板索引
10.1 scripts/(69 个 QMT 实盘/回测成品策略 + 2 个工具脚本)
| 主题 | 文件(节选) |
|---|---|
| 六脉神剑趋势增强族 | 11宽基六脉神剑趋势增强策略回测.py、22五大行六脉神剑趋势增强策略实盘.py、24债券六脉神剑趋势增强策略实盘.py、31全球大类六脉神剑趋势增强策略实盘.py、33行业六脉神剑趋势增强策略实盘.py、8主流基金自定义六脉神剑趋势增强策略策略实盘.py |
| 法码(Fama)趋势族 | 1法玛全天候绝对动量策略回测.py、4法玛全天候绝对动量策略源代码版.py、9法玛全天候趋势回归动量指数风控策略代码版.py、14法码中证A500趋势增强策略代码版.py、17法码全市场可转债趋势增强策略代码版.py |
| 网格与高频 | 1西蒙斯高频日线网格策略实盘.py、16高频分时网格策略实盘.py、21法码日线高频基础网格代码版.py、22法码日线ATR高频基础网格代码版.py、34高频日内算法交易.py、5分钟脉冲.py |
| 指数增强实盘 | 18中证1000趋势增强实盘策略.py、19中证2000趋势增强实盘策略.py、20中证A100趋势增强实盘策略.py、21中证A500趋势增强实盘策略.py、32小市值趋势增强实盘策略.py |
| 可转债 / 债券 / 逆回购 | 11可转债5因子轮动策略.py、12可转债自定义因子纯轮动系统.py、13国债逆回购策略.py、5法码国债逆回购代码版.py |
| 基金 / 全球大类 | 26全市场基金波段趋势增强策略5.py、27全市场基金趋势增强策略.py、6基金同花顺人气六脉神剑趋势增强策略实盘.py、3全球大类低相关性六脉神剑趋势轮动策略实盘.py、30全球外盘六脉神剑增强策略实盘.py |
| 基础示例 | 2上涨买入.py、17止盈止损策略.py、13美林时钟策略回测.py、3索普量化日线T0交易策略.py |
10.2 assets/(Ptrade 策略与实战示例,24 个)
| 类型 | 文件(节选) |
|---|---|
| 完整策略 | 七星高照ETF轮动策略.txt、三马-PT移植版.txt、多因子回归5A策略.txt、小市值.txt、改进版ETF溢价策略修正版.txt、ETF自动套利.txt |
| 西蒙斯/索普移植 | ptrade西蒙斯全球大类资产波段趋势增强策略.txt、pt西蒙斯全天候动量模型.txt、ptrade索普量化全天候动量隔离策略.txt、pt西蒙斯全球外盘波段趋势增强策略.txt |
| 打新与逆回购 | ptrade西蒙斯逆回购.txt、西蒙斯ptrade新股新债申购.txt |
| 策略模板 | strategy_template.py(Ptrade 通用模板骨架) |
| 常见问题 | 常见问题解答.txt(Ptrade 实战踩坑合集) |
10.3 references/ 已合并的平台文档(检索入口)
> 原始教程已按平台合并成 8 个大文档,每个源文件在合并文件内以 【源文件】xxx.txt 独立分节,直接全文检索关键词即可定位。
| 合并文档 | 内含 |
|---|---|
references/QMT/QMT_02_策略模板与多因子示例.txt |
期货日内策略模板、股票均线策略模板、双均线实盘示例(handlebar / subscribe / run_time 三版)、国债逆回购实盘模板、逆回购/还负债/止盈止损示例、多因子标准化+中性化+回归法+选股案例、股票/基金/两融/期权/债券/ETF/组合下单例子、跨品种套利、一键买卖、目标持仓调整 |
references/Ptrade/PTrade_02_策略模板与实战示例.txt |
官方样例 20 篇(双均线、MACD、tick 均线、小市值、指数增强、三因子、AROON、单因子、二八轮动、阳线、猛犸、协整配对、日内、期货双均线、集合竞价追涨停、融资融券双均线、法码全天候动量等)+【仅供学习】系列 15 篇(配对交易、可转债溢价套利、月度调仓财务因子、集合竞价、持久化、不重复买不超额买等)+ 一阳穿三线两融/普通账户 demo |
references/QMT/QMT_01_行情与交易API手册.txt |
行情函数族、K线/历史/本地/全推/Lv1/Lv2/分钟线、实时主推、订阅与反订阅、系统函数、变量说明、枚举常量、交易下单与算法下单(passorder / algo_passorder / VWAP / TWAP)、撤单与任务管理、全部查询函数、财务与合约信息、期货期权数据、板块与指数权重、交易日与复权因子、回调函数、数据下载 |
references/Ptrade/PTrade_01_API函数手册.txt |
设置函数、定时周期性函数、获取信息函数、市场/行情/证券信息、交易相关函数、公共交易函数、融资融券交易与查询、期货交易/查询/设置、技术指标计算函数、其他函数、对象、数据字典 |
references/QMT/QMT_04_入门规范与常见问题.txt |
运行机制对比、变量约定、QMT 首次配置流程、交易客户端链接、各家券商支持 QMT 的情况与资金门槛、常见问题、调用模型、模拟/实盘模式区分、init 中下单、下单无反应排查、数据结果 |
references/Ptrade/PTrade_04_入门规范与常见问题.txt |
使用说明、开始写策略、策略引擎简介、常见问题、支持的三方库、三方库接口变动 |
references/QMT/QMT_03_数据教程与因子库说明.txt |
小果数据教程、小果量化数据使用教程、小果大 QMT 量化助手说明、通达信公式 python 库说明 |
references/Ptrade/PTrade_03_财务与估值数据.txt |
估值数据、资产负债表、利润表、现金流量表、成长能力、盈利能力、每股指标、营运能力、偿债能力 |
10.4 工具脚本(本技能新增)
| 脚本 | 作用 |
|---|---|
scripts/validate_strategy.py |
静态检查:入口函数是否齐全、是否混用跨平台 API、是否误用被禁写法 |
scripts/qmt_ptrade_converter.py |
识别策略所属平台、转换标的代码后缀、打印 API 映射表 |
十一、参考文档全量索引
> 为避免文件数量过多,两平台 199 篇原始教程已按平台合并为 8 个大文档(QMT 4 个 + Ptrade 4 个),
> 每个源文件在合并文档内以 【源文件】原文件名 独立分节,一篇未删、一篇未丢,直接全文检索文件名或关键词即可定位。
> .py / .json 代码与数据文件保持独立存放(合并会破坏可运行性)。
11.1 references/QMT/(迅投 QMT,129 篇原始资料 → 4 个合并文档 + 7 个代码文件)
| 文件 | 篇数 | 内含要点 |
|---|---|---|
QMT_01_行情与交易API手册.txt |
78 篇 | 行情:4行情函数、3/14获取行情数据、13获取历史行情数据、12获取本地行情数据、44获取N分钟周期K线、45获取Lv1、46查询LV2、47用Lv1全推算全市场涨幅、4获取全推、5/6订阅行情与全推、8订阅模型、12/42实时主推、48行情回调处理动态行情、49每1分钟统计涨跌;交易:9交易下单函数、23综合下单函数、51passorder、54passorder算法单、28algo_passorder、32算法拆单、33/39智能算法VWAP、38智能算法TWAP、34撤销委托、37撤单、35任务管理、52集合竞价下单、55投资备注、57快速交易参数、58调整至目标持仓、27order_target_value、50一键买卖、59两融可买标的、4逆回购卖出;查询:10交易查询函数、36账号资金委托记录、37历史交易明细、56获取委托持仓资金、64账户、65持股、66委托、67成交、60两融账号、61直接还款、62查询示例、21期货持仓、22负债合约;信息:15/5获取财务数据、6获取合约信息、16合约详细信息、8涨跌停价、16历史ST状态、19除权除息与复权因子、20指数权重、21板块成份股、22交易日信息、19可交易权证标的、17期货数据、18/7期权信息、23期权合约列表、40期权数据、38新股新债;基础:3系统函数、43变量说明、15枚举常量、14绘图函数、10可视化净值走势、8其他信息函数、11读取其他数据、10调用模型、25is_last_bar、26subscribe_whole_quote算分时均线、6order_callback等回调、1下载历史行情数据、2设置定时器、28新股申购 |
QMT_02_策略模板与多因子示例.txt |
29 篇 | 13期货日内策略模板、14股票均线策略模板、58双均线实盘示例PY、5国债逆回购实盘策略模板、3基于handlebar实盘示例、6基于subscribe实盘示例、7基于run_time实盘示例、2如何实盘运行python策略、17收盘前逆回购示例、18定时还负债示例、53止盈止损示例、49交易实时主推示例、62交易数据查询示例、60两融账号信息示例、61直接还款示例、24股票下单例子、25基金下单例子、26两融下单例子、27期权下单例子、29债券下单例子、30ETF下单例子、31组合交易下单例子、50一键买卖(一篮子下单)、7一篮子买卖、36跨品种套利策略、11多因子数据标准化、12多因子数据中性化、13多因子回归法分析、20多因子选股案例 |
QMT_03_数据教程与因子库说明.txt |
4 篇 | 小果数据教程、小果量化数据使用教程、小果全能大QMT量化助手说明、通达信公式python库说明 |
QMT_04_入门规范与常见问题.txt |
11 篇 | 1运行机制对比、1变量约定、5初次使用QMT的python配置流程、1如何在init函数里下单、3python下单但账号没反应、63常见问题、10调用模型、11区分模拟还是实盘、2数据结果、交易客户端链接、各家券商支持QMT的情况及资金门槛 |
alpha.py xg_factor.py xg_factor_trader.py xg_tdx_func.py xg_quant_backtrader_data.py 因子计算测试.py 因子表.json |
7 个 | 小果因子库与通达信函数库源码、因子表数据(独立保留,可 import) |
11.2 references/Ptrade/(恒生 Ptrade,80 篇原始资料 → 4 个合并文档 + 3 个脚本)
| 文件 | 篇数 | 内含要点 |
|---|---|---|
PTrade_01_API函数手册.txt |
23 篇 | 4设置函数、5定时周期性函数、6获取信息函数、7获取市场信息、8获取行情信息、9获取证券信息、10获取指数成分股、11获取行业成份股、21获取其他信息、22交易相关函数、23公共交易函数、24融资融券交易类函数、25融资融券查询类函数、26期货交易类函数、27期货查询类函数、28期货设置类函数、29技术指标计算函数、30其他函数、31对象、32数据字典、ptrade_api_quickstart.md、strategy_notes.md、通达信公式python库 |
PTrade_02_策略模板与实战示例.txt |
39 篇 | 官方样例:1集合竞价追涨停、2tick级别均线、3双均线、4macd、5融资融券双均线、6盘后逆回购、7固定时间申购新股新债、8小市值日线、9指数增强日线、10三因子日线、11AROON、12单因子日线、13二八轮动、14阳线、15猛犸、16协整配对、18单标的日内、19期货日内、20期货双均线、21法码全天候动量隔离、22法码动量安全摸狗;【仅供学习】系列:低开事件收益率分析、单因子分析、买入阶段管理不重复买不超额买、可转债与正股配对交易、可转债溢价套利、月度调仓财务因子、板块策略开发所需数据、MACD demo 直播、均线买卖策略分享、集合竞价数据/交易 demo、逆回购申购、新股申购、持久化 demo、回测交易兼容20251015;其他:一阳穿三线两融/普通账户 demo、案例分享-金叉买入死叉卖出 |
PTrade_03_财务与估值数据.txt |
9 篇 | 12估值数据、13资产负债表、14利润表、15现金流量表、16成长能力、17盈利能力、18每股指标、19营运能力、20偿债能力 |
PTrade_04_入门规范与常见问题.txt |
6 篇 | 1使用说明、2开始写策略、3策略引擎简介、33常见问题、34支持的三方库、35三方库接口变动 |
dual_ma_strategy.py run_backtest.py utils.py |
3 个 | 双均线完整版源码、回测启动脚本、通用工具函数(独立保留,可 import) |
11.3 两个原技能手册全文(完整保留)
| 文件 | 内容 |
|---|---|
references/小果全能大QMT量化交易助手.md |
原「小果全能大QMT量化交易助手」SKILL.md 全文(约 7000 行:七大分部 + 全函数库 + 枚举大全 + 模板 + 常见问题 + 逐函数原型/参数/示例) |
references/小果量化交易Ptrade全能助手.md |
原「小果量化交易Ptrade全能助手」SKILL.md 全文(约 2500 行:功能概述 + 全量 API 分节 + 数据结构 + 数据字典 + 7 大策略模板 + 风控最佳实践 + 离线校验) |
十二、平台运行步骤
12.1 QMT
- 打开迅投研终端 / 券商 QMT,进入「策略编辑」新建 Python 策略,粘贴代码(首行保留
#coding:gbk)。 - 首次运行先补数据:
download_history_data('000001.SZ', '1d', '20200101', '20231231')。 - 选模式:策略编辑器上方「回测」→ 看回测报告;「运行」→ 调试模式(实时行情,不记信号)。
- 实盘:进入「策略交易」界面 → 选策略文件 → 右侧选「模拟」(只记信号)或「实盘」(真实下单)→ 运行。
- 排查:无委托先查是否在「模型交易」界面运行、
quickTrade是否为 2、账号是否登录。
12.2 Ptrade
- 打开 Ptrade → 「策略研究」→ 新建策略,粘贴代码并保存(Ctrl+S)。
- 回测:设置时间范围与初始资金 → 运行 → 查看评价指标(收益、夏普、最大回撤、胜率、盈亏比)与交易日志。
- 参数优化:调整模块级常量(如
SHORT_WIN/LONG_WIN)。 - 上线前:
filter_stock_by_status(...)过滤 ST/停牌/退市;check_strategy(strategy_path=...)静态自检。 - 实盘:订阅实时行情 → 开启自动执行;日志用
log.info观察。
十三、作者与版本
| 项目 | 内容 |
|---|---|
| 作者 | 小果 |
| 联系方式 | 微信 xg_quant |
| 版本 | 1.0.0 |
| 组成 | 由「小果全能大QMT量化交易助手」+「小果量化交易Ptrade全能助手」两个技能整理合并而成,199 篇教程文档、69 个策略源码、24 个策略示例全部保留,无一删减(教程文档已按平台合并为 8 个大文档) |
| 文件结构 | SKILL.md(本文件)· references/(2 套原手册全文 + QMT 4 个合并文档与 7 个代码文件 + Ptrade 4 个合并文档与 3 个脚本)· scripts/(69 个 QMT 策略 + 2 个转换/校验工具)· assets/(24 个 Ptrade 策略示例) |
| 文件总数 | 116 个(满足 ≤200 个文件的数量限制) |
> 免责声明:本技能所提供的全部代码与文档仅用于学习、研究与技术交流,不构成任何投资建议;实盘前请充分回测与风控,注意风险。