3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个非常经典的多周期共振策略。在量化交易中,通常的做法是在小周期(如5分钟)上运行策略,同时在代码中获取大周期(如日线)的数据来进行趋势过滤。
# -*- coding: gbk -*-
import pandas as pd
def init(ContextInfo):
"""
初始化函数,设定账户、股票池和参数
"""
# 1. 设置资金账号 (请替换为您自己的资金账号)
ContextInfo.accID = '6000000000'
ContextInfo.set_account(ContextInfo.accID)
# 2. 设置要交易的股票 (示例:平安银行)
ContextInfo.stock_code = '000001.SZ'
ContextInfo.set_universe([ContextInfo.stock_code])
# 3. 策略参数设置
ContextInfo.trade_qty = 1000 # 每次买入数量
ContextInfo.day_ma_len = 20 # 日线趋势均线周期
ContextInfo.min_ma_short = 5 # 5分钟短均线
ContextInfo.min_ma_long = 10 # 5分钟长均线
# 4. 周期设置
ContextInfo.period_day = '1d' # 大周期:日线
ContextInfo.period_min = '5m' # 小周期:5分钟
def get_position(ContextInfo, stock_code):
"""
辅助函数:获取指定股票的持仓数量
"""
# 获取持仓列表
positions = get_trade_detail_data(ContextInfo.accID, 'stock', 'position')
for pos in positions:
# QMT返回的持仓对象中,证券代码通常不带后缀,需要注意匹配
# 这里使用 m_strInstrumentID + '.' + m_strExchangeID 拼接成完整代码
pos_code = pos.m_strInstrumentID + '.' + pos.m_strExchangeID
if pos_code == stock_code:
return pos.m_nVolume
return 0
def handlebar(ContextInfo):
"""
核心逻辑函数,每根K线(5分钟)执行一次
"""
# 获取当前正在处理的股票代码
stock = ContextInfo.stock_code
# ----------------------------------------------------------------
# 第一步:获取日线数据,判断大趋势
# ----------------------------------------------------------------
# 获取足够计算MA20的日线数据,count设大一点防止停牌等导致数据不足
day_data = ContextInfo.get_market_data_ex(
['close'],
[stock],
period=ContextInfo.period_day,
count=ContextInfo.day_ma_len + 5,
dividend_type='front',
subscribe=True
)
if stock not in day_data or len(day_data[stock]) < ContextInfo.day_ma_len:
# 数据不足,跳过
return
df_day = day_data[stock]
# 计算日线 MA20
df_day['ma20'] = df_day['close'].rolling(window=ContextInfo.day_ma_len).mean()
# 获取最新的日线收盘价和均线值
last_day_close = df_day['close'].iloc[-1]
last_day_ma20 = df_day['ma20'].iloc[-1]
# 判断日线趋势:价格在20日均线之上为看涨
is_day_bullish = last_day_close > last_day_ma20
# ----------------------------------------------------------------
# 第二步:获取5分钟数据,判断入场信号
# ----------------------------------------------------------------
min_data = ContextInfo.get_market_data_ex(
['close'],
[stock],
period=ContextInfo.period_min,
count=ContextInfo.min_ma_long + 5,
dividend_type='front',
subscribe=True
)
if stock not in min_data or len(min_data[stock]) < ContextInfo.min_ma_long:
return
df_min = min_data[stock]
# 计算5分钟均线
df_min['ma_short'] = df_min['close'].rolling(window=ContextInfo.min_ma_short).mean()
df_min['ma_long'] = df_min['close'].rolling(window=ContextInfo.min_ma_long).mean()
# 获取当前和上一根K线的均线值(用于判断交叉)
curr_short = df_min['ma_short'].iloc[-1]
curr_long = df_min['ma_long'].iloc[-1]
prev_short = df_min['ma_short'].iloc[-2]
prev_long = df_min['ma_long'].iloc[-2]
# 判断金叉:上一根短线<=长线,且当前短线>长线
is_golden_cross = (prev_short <= prev_long) and (curr_short > curr_long)
# 判断死叉:上一根短线>=长线,且当前短线<长线
is_death_cross = (prev_short >= prev_long) and (curr_short < curr_long)
# 获取最新价格用于下单
current_price = df_min['close'].iloc[-1]
# ----------------------------------------------------------------
# 第三步:交易执行
# ----------------------------------------------------------------
# 获取当前持仓
curr_pos = get_position(ContextInfo, stock)
# 买入逻辑:日线看涨 + 5分钟金叉 + 无持仓
if is_day_bullish and is_golden_cross and curr_pos == 0:
print(f"【买入信号】{stock} 日线看涨(价格:{last_day_close:.2f}>MA20:{last_day_ma20:.2f}), 5分钟金叉")
# 使用 order_shares 下单指定股数
order_shares(stock, ContextInfo.trade_qty, 'fix', current_price, ContextInfo, ContextInfo.accID)
# 卖出逻辑:5分钟死叉 + 有持仓 (这里只看小周期信号平仓,也可加入日线趋势反转平仓)
elif is_death_cross and curr_pos > 0:
print(f"【卖出信号】{stock} 5分钟死叉,执行平仓")
order_shares(stock, -curr_pos, 'fix', current_price, ContextInfo, ContextInfo.accID)
ContextInfo.accID = '6000000000' 修改为您实际的资金账号。get_market_data_ex,这是 QMT 推荐的高效数据接口,支持订阅实时行情。order_shares 进行下单,fix 代表限价单(以当前最新价下单),如果需要市价单可改为 market(注意回测和实盘的区别)。Q: 为什么要在5分钟周期上运行,而不是日线周期?
A: 因为买入信号是基于5分钟均线金叉触发的。如果在日线周期上运行,handlebar 函数每天只会在收盘时调用一次,无法捕捉盘中的5分钟级别信号。
Q: get_market_data_ex 中的 subscribe=True 是什么意思?
A: 这表示订阅数据。在实盘模式下,当有新的行情推送过来时,QMT 会自动更新数据并触发策略计算,保证信号的实时性。
Q: 如何修改“日线看涨”的定义?
A: 您可以修改代码中 is_day_bullish 的计算逻辑。例如,改为“日线 MA5 > 日线 MA10”:
# 计算日线 MA5 和 MA10
df_day['ma5'] = df_day['close'].rolling(window=5).mean()
df_day['ma10'] = df_day['close'].rolling(window=10).mean()
is_day_bullish = df_day['ma5'].iloc[-1] > df_day['ma10'].iloc[-1]