3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT 平台中,要测试不同的参数组合(如均线周期)以找到最优解,通常不需要编写复杂的循环代码来反复运行回测。QMT 客户端内置了**参数优化(Optimization)**功能,可以直接在界面上设置参数的范围和步长,系统会自动遍历所有组合并给出绩效对比。
以下是实现参数优化的具体步骤和代码示例。
下面是一个基于双均线策略的完整代码示例。在这个例子中,SHORT_PERIOD(短期均线)和 LONG_PERIOD(长期均线)就是需要优化的参数。
# -*- coding: gbk -*-
import pandas as pd
import numpy as np
# ==============================================================================
# 策略参数定义 (供参数优化面板调用)
# 在QMT界面的【参数设置】面板中,可以设置这些变量的 最小值、最大值 和 步长
# 例如:SHORT_PERIOD 最小5,最大20,步长5; LONG_PERIOD 最小30,最大60,步长10
# ==============================================================================
SHORT_PERIOD = 5 # 短期均线周期默认值
LONG_PERIOD = 20 # 长期均线周期默认值
def init(ContextInfo):
# 设置账号 (请替换为您的实际账号)
ContextInfo.accid = '6000000000'
ContextInfo.set_account(ContextInfo.accid)
# 设置股票池 (示例使用 沪深300 ETF)
ContextInfo.set_universe(['510300.SH'])
# 设置回测参数 (仅回测模式有效)
ContextInfo.set_commission(0, [0.0001, 0.0001, 0.0003, 0.0003, 0, 5]) # 设置费率
ContextInfo.capital = 1000000 # 初始资金
def handlebar(ContextInfo):
# 获取当前K线位置
index = ContextInfo.barpos
# 获取当前图表的股票代码
stock_code = ContextInfo.get_universe()[0]
# 获取历史行情数据
# 注意:获取的数据长度要足够计算长期均线,这里取 LONG_PERIOD + 5 根
# period='1d' 表示日线,根据实际运行周期调整
data = ContextInfo.get_market_data_ex(
['close'],
[stock_code],
period='1d',
count=LONG_PERIOD + 5,
dividend_type='front'
)
# 如果数据获取失败或长度不足,直接返回
if stock_code not in data or len(data[stock_code]) < LONG_PERIOD:
return
# 提取收盘价序列
close_prices = data[stock_code]['close']
# 计算均线
# 使用 pandas 的 rolling().mean() 计算移动平均
ma_short = close_prices.rolling(window=SHORT_PERIOD).mean()
ma_long = close_prices.rolling(window=LONG_PERIOD).mean()
# 获取最新的均线值 (当前K线) 和 上一根K线的均线值
# iloc[-1] 为最新值,iloc[-2] 为上一个值
current_short = ma_short.iloc[-1]
current_long = ma_long.iloc[-1]
prev_short = ma_short.iloc[-2]
prev_long = ma_long.iloc[-2]
# 获取当前持仓
positions = get_trade_detail_data(ContextInfo.accid, 'stock', 'position')
current_vol = 0
for pos in positions:
if pos.m_strInstrumentID + '.' + pos.m_strExchangeID == stock_code:
current_vol = pos.m_nVolume
break
# ==========================================================================
# 交易逻辑:金叉买入,死叉卖出
# ==========================================================================
# 金叉:短期均线上穿长期均线
is_golden_cross = (prev_short <= prev_long) and (current_short > current_long)
# 死叉:短期均线下穿长期均线
is_death_cross = (prev_short >= prev_long) and (current_short < current_long)
# 执行交易
if is_golden_cross and current_vol == 0:
# 全仓买入
print(f"产生金叉信号: 短期{SHORT_PERIOD} > 长期{LONG_PERIOD},买入")
order_target_percent(stock_code, 1.0, "fix", close_prices.iloc[-1], ContextInfo, ContextInfo.accid)
elif is_death_cross and current_vol > 0:
# 清仓卖出
print(f"产生死叉信号: 短期{SHORT_PERIOD} < 长期{LONG_PERIOD},卖出")
order_target_percent(stock_code, 0.0, "fix", close_prices.iloc[-1], ContextInfo, ContextInfo.accid)
SHORT_PERIOD 和 LONG_PERIOD 并显示在列表中。SHORT_PERIOD,设置:
LONG_PERIOD,设置:
Q: 为什么我在参数面板里看不到我的变量?
A: 确保变量是在函数外部(全局作用域)定义的,并且赋了初始值(如 MA = 5)。如果变量定义在 init 或 handlebar 函数内部,QMT 无法将其识别为可调节参数。
Q: 步长(Step)是什么意思?
A: 步长决定了参数遍历的密度。例如范围是 10 到 20,步长为 2,则测试的参数为 10, 12, 14, 16, 18, 20。步长越小,测试的组合越多,计算时间越长。
Q: 优化结果中的“夏普比率”高好还是低好?
A: 夏普比率(Sharpe Ratio)越高越好。它代表了策略在承担单位风险下获得的超额回报。通常在选择参数时,不仅要看收益率,还要看夏普比率和最大回撤,以防止过拟合。