QMT Python API从零入门:手把手编写你的第一个量化交易策略
引言:什么是自动化交易?
自动化交易,通常也被称为量化交易或程序化交易,其核心在于利用预先编写好的计算机程序,依据设定好的交易规则自动执行买卖操作。这种方法能够有效规避人类情绪中常见的贪婪与恐惧,从而实现严格纪律性的交易执行。同时,它可以同时监控多个交易品种和不同时间周期,极大地提升了交易的执行效率与覆盖范围。在国内众多量化交易平台中,QMT(极速策略交易系统)是一个功能全面且对初学者相对友好的选择。它不仅提供了丰富的历史数据接口和完备的回测系统,还支持使用流行的Python语言来编写交易策略,这显著降低了普通投资者踏入量化交易领域的门槛。
本文将作为一份新手向导,带领你从最基础的概念开始,系统地了解QMT Python API的框架,并逐步完成你的第一个自动化交易策略的编写。无论你是具备一定交易经验但刚接触编程的交易者,还是拥有Python基础希望探索金融应用的投资者,都能通过本指南快速上手。
QMT系统概述
QMT是一款集成度高的专业量化交易终端,它将行情展示、策略开发、历史数据回测、模拟交易以及实盘交易等功能整合在一个平台内。与常规的股票交易软件不同,QMT的核心在于其“策略模型”——用户可以将自己的交易逻辑和想法转化为具体的计算机代码,形成可重复执行的策略模型,进而交由系统自动化运行。
QMT支持多种编程语言进行策略开发,其中Python因其语法简洁、学习曲线平缓以及拥有诸如NumPy、Pandas等强大的数据分析库而成为主流选择。QMT内置的Python环境已经预装了如TA-Lib、SciPy等常用的量化分析库,并且允许用户根据需要自行安装额外的第三方库。更重要的是,QMT提供的Python API是底层高性能C++接口的封装,在获取实时行情数据和下达交易指令时都能保证极快的速度。
Python策略的基本结构
在QMT的框架下,任何一个完整的Python策略都必须包含两个特定函数:init 和 handlebar。这是策略运行的固定入口,两者缺一不可。
# coding:gbk
def init(ContextInfo):
pass
def handlebar(ContextInfo):
pass
1. init 初始化函数
init 函数在整个策略的生命周期中仅会执行一次。通常我们在此函数中完成所有的初始化配置工作,例如:
- 设定需要监控和交易的股票池(标的列表)。
- 配置将要使用的资金账户信息。
- 声明并初始化策略中需要使用的全局变量。
- 设置回测相关的参数,如交易滑点、手续费率等。
即便当前没有任何初始化操作,也必须保留一个空的
init函数以符合框架要求。
2. handlebar 行情处理函数
handlebar 函数是策略逻辑的核心所在,它会在每一根K线周期上被调用执行一次。在回测模式下,系统会从历史数据的第一根K线开始,依次对每一根K线调用一次handlebar。在实时行情模式下,历史K线处理完毕后,每当接收到一个新的tick(分笔成交)数据,系统会更新当前最后一根未结束的K线,并再次调用handlebar函数。这意味着在交易时段内,handlebar会被频繁触发,你可以在这里编写核心的交易逻辑:读取最新的行情数据、计算各类技术指标、根据条件判断买卖点、并最终下达交易指令。
3. ContextInfo 上下文对象
ContextInfo 是一个至关重要的对象,它封装了策略运行时所需的各种环境信息和方法。通过它,你可以访问和控制策略的许多方面,例如:
ContextInfo.barpos:获取当前正在处理的K线的索引位置(从0开始计数)。ContextInfo.is_last_bar():判断当前K线是否为最新的、未结束的K线。ContextInfo.get_market_data():用于获取指定品种和周期的行情数据。ContextInfo.set_universe():用于动态设置或更新策略的股票池。 你还可以在ContextInfo对象上自定义属性,以便在init和handlebar函数之间传递和共享数据。但需要注意,ContextInfo的状态在每次K线切换时会自动“回滚”到上一个时间点的快照,因此若需要保存跨越多根K线的持久化变量,建议使用Python的全局变量或在ContextInfo上谨慎地管理自定义属性。
第一个简单策略:打印“hello world”
让我们遵循QMT的官方示例,编写一个最简单的策略。这个策略仅在初始化时打印一条消息,并在每一根K线被处理时打印另一条消息,同时展示如何获取K线信息。
# coding:gbk
def init(ContextInfo):
print('hello init')
# 在此处可以设置初始股票池,例如获取“上证50”指数的所有成分股
stock_list = ContextInfo.get_stock_list_in_sector("上证50", "")
ContextInfo.set_universe(stock_list)
def handlebar(ContextInfo):
print('hello handlebar')
# 获取当前K线的索引和对应的时间戳
index = ContextInfo.barpos
timetag = ContextInfo.get_bar_timetag(index)
print('当前K线索引:', index, '时间戳:', timetag)
将上述代码复制到QMT策略编辑器中(通过“模型研究”界面新建一个Python模型),然后点击“运行”按钮。你可以在输出窗口中观察到,系统首先打印一次hello init,随后会为每一根历史K线打印一次hello handlebar及其对应的索引和时间信息。这个过程模拟了策略在历史数据上逐根K线运行的情景。
重要提示:在QMT策略编辑器中编写代码时,必须在文件开头指定编码为
#coding:gbk,否则中文字符可能出现乱码问题。
运行机制详解:逐K线运行与信号有效性
深刻理解QMT策略的运行机制是编写正确、可靠策略的关键。官方文档明确指出,QMT的策略模型是由行情数据驱动的,采用逐K线运行的模式。这意味着:
- 当启动策略运行时,系统会从主图时间周期的第一根历史K线开始,依次对每一根K线调用
handlebar函数,一直运行到最新的一根K线。 - 在实时交易盘中,最新的那根K线会随着每一个新tick数据的到来而不断更新(例如价格变动、成交量增加),因此
handlebar函数也会随着每个tick被频繁调用。 - 只有在一根K线已经完全定型、不会再被更新时(即该K线的最后一个tick),在这期间产生的交易信号才会被系统认定为有效信号。有效的买卖指令会在下一根K线的第一个tick时刻被发送至交易所。这个设计旨在避免在单根K线形成过程中,因为价格的瞬时波动而产生大量无效的“噪音”交易信号。
有效信号与无效信号的区分
- 有效信号:在最新且已确定的K线(此时
ContextInfo.is_last_bar()返回True,且这是该K线最后一次被handlebar处理)内部调用交易函数所产生的信号。此类信号会被策略引擎记录,并在下一个交易周期开始时触发实际的委托下单。 - 无效信号:在已经形成的历史K线上调用交易函数,或者在一根尚未结束的最新K线中间过程(非最后一个tick)调用交易函数,通常不会产生实际的委托订单(除非启用了特定的快速交易模式)。
快速交易模式
如果策略需要信号立即触发下单(例如某些高频或抢单策略),可以启用quickTrade参数。例如,在通用的passorder下单函数中:
quickTrade=1:当在非历史K线(即最新的K线)上调用时,立即触发下单。quickTrade=2:无论在任何K线(包括历史K线)上调用,都立即触发下单(此模式需格外谨慎使用,特别是在回测中)。 对于一些特定的函数(如期权组合开仓函数make_option_combination),其默认行为就是立即触发。
充分理解这些运行机制和信号规则,能帮助你更好地控制策略的交易时机,提高信号的有效性,避免在实盘交易中因机制误解而导致不必要的损失。
如何运行你的策略
在QMT平台上运行一个Python策略的流程非常直观:
- 打开QMT客户端中的“模型研究”模块,点击“新建模型”按钮,并选择“Python模型”类型。
- 在打开的策略编辑器窗口中,输入或粘贴你的策略代码。
- 在编辑器右侧的“基本信息”面板中,配置策略的默认运行参数,例如默认的K线周期(如日线)、默认的交易品种(如沪深300指数)。
- 点击编辑器工具栏上的“运行”按钮,策略便会开始在主图K线上执行,所有的运行日志和输出信息将显示在底部的“日志输出”面板中。 如果你在“行情”界面已经打开了某个品种的K线图,在此界面运行策略,策略将自动叠加在该主图上运行。若直接在“模型研究”界面运行,则会使用“基本信息”中设置的默认品种和周期。
回测:验证策略的历史表现
在将策略投入真实资金进行交易之前,进行严格的历史回测是必不可少的一步。回测旨在通过历史数据模拟策略过去的交易表现,从而评估其潜在盈利能力和风险特征。QMT提供了完善的回测功能。
设置回测参数
在策略编辑器的“回测参数”面板中,你可以详细配置回测环境:
- 回测的起止时间范围。
- 策略的初始投入资金。
- 模拟交易的滑点成本(买卖价差影响)。
- 各项交易费用,包括印花税、券商佣金等。
- 业绩比较基准(如某个市场指数),用于对比策略的超额收益。
这些参数同样可以在策略的
init函数中,通过ContextInfo.start、ContextInfo.end、ContextInfo.capital等属性进行动态设置,且代码中的设置优先级高于面板设置。
执行回测分析
点击“回测”按钮,QMT系统将依据你设定的参数,在选定的历史时间区间内,严格按照时间顺序逐K线模拟运行你的策略,并完整记录每一次虚拟的买卖操作。回测结束后,系统会生成一份详细的绩效分析报告,其中包含年化收益率、夏普比率、最大回撤率、胜率、交易次数等关键指标。同时,在主图K线上会用清晰的箭头标记出每一次买入和卖出的点位。
回测是检验策略逻辑有效性的核心工具,但必须清醒认识到:优异的历史回测结果并不等同于未来的盈利保证。回测过程往往无法完全模拟市场滑点、订单冲击成本、流动性限制等所有现实交易中的复杂因素。因此,对回测结果应保持理性分析,并通常需要进行多周期、多品种的稳健性测试。
获取行情数据:get_market_data
在策略开发中,获取准确、及时的行情数据是进行计算和决策的基础。QMT通过ContextInfo.get_market_data函数提供了强大且灵活的数据获取接口。
最基本的应用是获取当前主图品种的最新价格。例如,获取最新收盘价:
def handlebar(ContextInfo):
# 获取当前主图最近一根K线的收盘价(单个数值)
close_price = ContextInfo.get_market_data(['close'], count=1)
print(close_price)
更常见的是获取指定股票在一段时间内的多维度数据。例如,获取平安银行股票最近5个交易日的收盘价和开盘价:
def handlebar(ContextInfo):
data_df = ContextInfo.get_market_data(
fields=['close', 'open'], # 所需数据字段
stock_code=['000001.SZ'], # 股票代码
period='1d', # 数据周期:日线
dividend_type='front', # 复权方式:前复权
count=5 # 获取最近5根K线
)
print(data_df)
该函数根据传入参数的不同,可能返回单个数值、pandas.Series、pandas.DataFrame等不同格式的数据对象,便于直接进行数据分析。熟练掌握get_market_data的用法是策略开发的基石。例如,你可以结合TA-Lib库,利用获取到的价格数据计算MACD、RSI、布林带等技术指标,进而基于这些指标值构建交易信号。
初识交易函数:passorder
虽然在本入门篇中我们不进行真实下单,但提前了解核心的交易函数有助于理解策略的完整闭环。passorder是QMT中最通用、底层的下单函数,支持股票、期货、期权等多种金融品种的交易。
例如,以市场最新价买入100股平安银行股票的代码示例如下:
passorder(23, 1101, '你的资金账号', '000001.SZ', 5, -1, 100, ContextInfo)
关键参数简要说明:
23:交易操作类型编码,此处代表普通股票买入。1101:订单报价方式编码,代表单股票单账户、按股数下单。'你的资金账号':用于交易的资金账号。通常可在init函数中用ContextInfo.set_account()提前设置,也可直接传入。'000001.SZ':标准格式的合约代码。5:价格类型,5代表“最新价”下单。-1:当价格类型为指定价时有效,此处填-1表示忽略。100:委托数量(单位:股)。ContextInfo:策略上下文对象,必须传入。
在实际策略编写中,为了提升代码可读性和易用性,通常会使用QMT封装好的更简洁的高级订单函数,例如order_lots、order_value等。例如,order_lots('000001.SZ', 1, ContextInfo, ‘资金账号’)即表示买入1手(100股)平安银行。
结语:迈向自动化交易的第一步
通过本文的讲解,你已经初步掌握了QMT Python策略的基本框架、核心运行机制,并成功编写和运行了你的第一个策略代码。你学习了如何获取所需的行情数据,也对最终的交易指令函数有了概念性的认识。这一切都为后续开发更复杂、更实用的量化交易策略奠定了坚实的基础。
在接下来的内容中,我们将深入探讨如何构建一个完整的交易策略体系。这包括如何动态管理和筛选股票池、如何高效计算并应用多种技术指标、如何设计并过滤交易信号以提升质量,以及如何进行科学的回测评估与绩效分析。我们还将涉足实战中的关键议题,如资金管理、仓位控制以及风险控制模块的实现。
量化交易的世界既充满挑战也富含机遇,而QMT为我们提供了一个强大且易用的工具入口。真诚建议你立即动手实践,将本文中的示例代码亲自输入编辑器并运行,切身感受程序化交易的逻辑与节奏。请始终牢记:理论认知源于学习,而真正的技能提升源于持续不断的实践与迭代。