3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于 MFI (Money Flow Index, 资金流量指标) 的 QMT 量化交易策略。
MFI 指标结合了价格和成交量,用于衡量市场的买卖压力。它通常在 0 到 100 之间波动。
# -*- coding: gbk -*-
import pandas as pd
import numpy as np
import talib
def init(ContextInfo):
"""
初始化函数,策略启动时调用一次
"""
# 1. 设置策略参数
ContextInfo.mfi_period = 14 # MFI 计算周期
ContextInfo.buy_threshold = 20 # 买入阈值 (超卖)
ContextInfo.sell_threshold = 80 # 卖出阈值 (超买)
# 2. 设置股票池 (示例:浦发银行,平安银行)
# 在实际运行时,可以通过界面设置股票池,也可以在这里代码指定
ContextInfo.stock_list = ['600000.SH', '000001.SZ']
ContextInfo.set_universe(ContextInfo.stock_list)
# 3. 设置资金账号 (请替换为您真实的资金账号)
ContextInfo.account_id = 'YOUR_ACCOUNT_ID'
ContextInfo.set_account(ContextInfo.account_id)
# 4. 设置回测参数 (仅回测有效)
ContextInfo.set_slippage(1, 0.002) # 设置滑点
ContextInfo.set_commission(0, [0.0003, 0.0013, 0.0003, 0.0003, 0.0003, 5]) # 设置手续费
def handlebar(ContextInfo):
"""
行情事件函数,每根K线或每个Tick调用一次
"""
# 获取当前设置的股票池
stock_list = ContextInfo.get_universe()
# 获取当前周期 (例如 '1d')
period = ContextInfo.period
# 确保是最后一根K线才下单 (避免历史K线重复下单,实盘中通常需要此判断)
# 如果是回测模式,平台会自动处理,但加上此判断逻辑更严谨
if not ContextInfo.is_last_bar():
# 回测模式下,如果不是最后一根bar,通常由平台驱动循环,这里直接return可能导致回测不执行
# 注意:QMT回测机制中,handlebar会在每一根历史K线上执行。
# 实盘中,通常只在最新的K线(is_last_bar)处理交易。
# 为了兼容回测和实盘,这里不做 return,而是依赖 QMT 的机制。
pass
# 获取历史行情数据
# 我们需要 High, Low, Close, Volume 来计算 MFI
# 多取一些数据以保证指标计算的稳定性,例如取 period * 3
count = ContextInfo.mfi_period * 3
# 使用 get_market_data_ex 获取数据 (推荐使用 ex 接口)
# 返回格式: {code: DataFrame}
market_data = ContextInfo.get_market_data_ex(
['high', 'low', 'close', 'volume'],
stock_list,
period=period,
count=count,
dividend_type='front' # 前复权
)
for stock in stock_list:
# 获取该股票的 DataFrame 数据
if stock not in market_data:
continue
df = market_data[stock]
# 数据长度不足,无法计算指标,跳过
if len(df) < ContextInfo.mfi_period + 1:
continue
# 提取 numpy 数组供 talib 使用
# 注意:talib 需要 float 类型
high_prices = df['high'].values.astype(float)
low_prices = df['low'].values.astype(float)
close_prices = df['close'].values.astype(float)
volumes = df['volume'].values.astype(float)
# --- 计算 MFI 指标 ---
try:
mfi_values = talib.MFI(high_prices, low_prices, close_prices, volumes, timeperiod=ContextInfo.mfi_period)
except Exception as e:
print(f"计算 {stock} MFI 出错: {e}")
continue
# 获取最新的 MFI 值 (数组的最后一个)
# 注意:如果数据包含 NaN,需要处理
current_mfi = mfi_values[-1]
if np.isnan(current_mfi):
continue
# --- 交易逻辑 ---
# 打印日志方便调试
# print(f"代码: {stock}, 时间: {df.index[-1]}, MFI: {current_mfi:.2f}")
# 1. 卖出逻辑:MFI > 80 (超买)
if current_mfi > ContextInfo.sell_threshold:
# 使用 order_target_percent 调整仓位到 0 (即清仓)
# 这种方式比 passorder 更方便,不用自己计算持仓量
order_target_percent(stock, 0, ContextInfo, ContextInfo.account_id)
# print(f"{stock} 触发卖出信号,MFI={current_mfi}")
# 2. 买入逻辑:MFI < 20 (超卖)
elif current_mfi < ContextInfo.buy_threshold:
# 使用 order_target_percent 调整仓位到 10% (示例:每只股票买入总资产的 10%)
# 注意:实际使用时请根据资金管理需求调整比例
target_percent = 0.1
order_target_percent(stock, target_percent, ContextInfo, ContextInfo.account_id)
# print(f"{stock} 触发买入信号,MFI={current_mfi}")
# -*- coding: gbk -*-:
数据获取 (get_market_data_ex):
get_market_data_ex 接口,这是 QMT 推荐的高效数据接口。high, low, close, volume 四个字段来计算 MFI。count 设置为 mfi_period * 3 是为了确保有足够的数据让 talib 计算出有效的指标值(去除前期的 NaN 值)。指标计算 (talib.MFI):
talib 库,直接调用 talib.MFI 比手动编写公式计算效率更高且更准确。float 类型的 numpy 数组。交易执行 (order_target_percent):
order_target_percent(stock, percent, ...) 是一个非常方便的高级函数。0.1 (即 10%)。如果当前没仓位,它会自动买入;如果已有仓位不足 10%,它会补仓。0。如果当前有仓位,它会自动卖出平仓。init 中将 ContextInfo.account_id 替换为您真实的资金账号。init 函数中的 ContextInfo.account_id 为您的实际账号。Q: 为什么使用 order_target_percent 而不是 passorder?
A: passorder 是最底层的下单函数,需要手动计算买卖数量(例如:当前持仓多少?需要卖多少才能清仓?)。而 order_target_percent 封装了这些逻辑,你只需要告诉它“我希望这只股票占我总资产的百分之几”,系统会自动计算并下单,非常适合这种趋势或反转策略。
Q: 如何调整 MFI 的灵敏度?
A: 修改 init 函数中的 ContextInfo.mfi_period。
Q: 实盘交易需要注意什么?
A: 实盘时建议在 handlebar 开头增加 if not ContextInfo.is_last_bar(): return 的判断,确保只在最新的行情数据到来时才进行计算和下单,避免对历史 K 线重复触发交易。同时,请确保已在 QMT 界面登录了交易账号。