3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
Hans123 是一种经典的日内突破策略。其核心逻辑是在开盘后的一段时间内(如开盘前30分钟)建立一个高低点区间,当价格突破该区间的上轨时做多,跌破下轨时做空,并在收盘前平仓。
以下是在 QMT 平台上实现该策略的详细代码和说明。
本代码以**股指期货(IF)**为例,因为 Hans123 是典型的 T+0 策略。如果您用于股票,请注意 A 股的 T+1 限制(当日买入无法当日卖出)。
# -*- coding: gbk -*-
import pandas as pd
import time
def init(ContextInfo):
"""
策略初始化函数
"""
# 1. 设定交易标的 (此处以沪深300主力合约为例,实盘请修改为具体合约代码)
ContextInfo.asset = 'IF00.IF'
# 2. 设定账户 (请修改为您的资金账号)
ContextInfo.account_id = 'YOUR_ACCOUNT_ID'
ContextInfo.account_type = 'FUTURE' # FUTURE: 期货, STOCK: 股票
# 3. 策略参数设置
ContextInfo.setup_time_end = "10:00:00" # 突破区间建立结束时间
ContextInfo.close_time = "14:55:00" # 尾盘平仓时间
ContextInfo.trade_qty = 1 # 每次交易手数
# 4. 全局变量初始化
ContextInfo.day_high = -1 # 当日区间最高价
ContextInfo.day_low = 999999 # 当日区间最低价
ContextInfo.current_date = '' # 当前日期记录
ContextInfo.trade_triggered = False # 当日是否已开仓标记
# 5. 设定运行周期 (建议使用 1分钟 或 5分钟 线)
# 注意:在界面上运行策略时,请选择相应的周期
def handlebar(ContextInfo):
"""
K线周期运行函数
"""
# 获取当前K线位置
index = ContextInfo.barpos
# 获取当前时间
timetag = ContextInfo.get_bar_timetag(index)
# 将时间戳转换为日期和时间字符串
current_dt_str = timetag_to_datetime(timetag, '%Y%m%d %H:%M:%S')
current_date = current_dt_str[0:8]
current_time = current_dt_str[9:]
# --- 1. 新的一天,重置变量 ---
if ContextInfo.current_date != current_date:
ContextInfo.current_date = current_date
ContextInfo.day_high = -1
ContextInfo.day_low = 999999
ContextInfo.trade_triggered = False
print(f"New Day: {current_date}, Reset parameters.")
# 获取最新行情数据 (开高低收)
# 使用 get_market_data_ex 获取数据更高效
data_dict = ContextInfo.get_market_data_ex(
['open', 'high', 'low', 'close'],
[ContextInfo.asset],
period=ContextInfo.period,
count=1,
subscribe=True
)
if ContextInfo.asset not in data_dict:
return
df = data_dict[ContextInfo.asset]
if df.empty:
return
# 获取当前K线的最高、最低、收盘价
current_high = df.iloc[-1]['high']
current_low = df.iloc[-1]['low']
current_close = df.iloc[-1]['close']
# --- 2. 建立突破区间 (开盘 - 10:00) ---
if current_time <= ContextInfo.setup_time_end:
# 更新区间最高价
if current_high > ContextInfo.day_high:
ContextInfo.day_high = current_high
# 更新区间最低价
if current_low < ContextInfo.day_low:
ContextInfo.day_low = current_low
# 在图表上画出区间线 (仅供回测观察)
ContextInfo.paint('Setup_High', ContextInfo.day_high, -1, 0)
ContextInfo.paint('Setup_Low', ContextInfo.day_low, -1, 0)
# --- 3. 交易阶段 (10:00 - 14:55) ---
elif current_time < ContextInfo.close_time:
# 绘制延续的区间线
ContextInfo.paint('Setup_High', ContextInfo.day_high, -1, 0)
ContextInfo.paint('Setup_Low', ContextInfo.day_low, -1, 0)
# 如果今日尚未交易,检查突破信号
if not ContextInfo.trade_triggered:
# 向上突破
if current_close > ContextInfo.day_high:
print(f"Breakout UP: Price {current_close} > High {ContextInfo.day_high}")
# 期货开多 (23:买入, 1101:单股/手)
# 注意:期货开仓通常用 buy_open,这里演示通用 passorder
# opType: 23(买入/开多), 24(卖出/开空) - 股票逻辑
# 期货逻辑: 0(开多), 3(开空)
# 这里使用期货专用函数 buy_open 更加清晰
buy_open(ContextInfo.asset, ContextInfo.trade_qty, "LATEST", current_close, ContextInfo, ContextInfo.account_id)
ContextInfo.trade_triggered = True
# 向下突破
elif current_close < ContextInfo.day_low:
print(f"Breakout DOWN: Price {current_close} < Low {ContextInfo.day_low}")
# 期货开空
sell_open(ContextInfo.asset, ContextInfo.trade_qty, "LATEST", current_close, ContextInfo, ContextInfo.account_id)
ContextInfo.trade_triggered = True
# --- 止损逻辑 (可选) ---
# 如果持多仓,价格跌破下轨,止损平仓
# 如果持空仓,价格突破上轨,止损平仓
# 此处需要获取持仓信息,为简化代码,此处略过复杂持仓判断,仅展示核心逻辑
# --- 4. 尾盘平仓 (14:55 以后) ---
else:
# 获取当前持仓
positions = get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
for pos in positions:
if pos.m_strInstrumentID == ContextInfo.asset:
# 如果有多单,平多
if pos.m_nVolume > 0 and pos.m_nDirection == 48: # 48代表多头
print(f"Closing Long Position at {current_time}")
sell_close_tdayfirst(ContextInfo.asset, pos.m_nVolume, "LATEST", current_close, ContextInfo, ContextInfo.account_id)
# 如果有空单,平空
elif pos.m_nVolume > 0 and pos.m_nDirection == 49: # 49代表空头
print(f"Closing Short Position at {current_time}")
buy_close_tdayfirst(ContextInfo.asset, pos.m_nVolume, "LATEST", current_close, ContextInfo, ContextInfo.account_id)
时间处理:
get_bar_timetag 返回的是毫秒级时间戳。timetag_to_datetime 转换为字符串(如 '10:00:00'),方便进行字符串比较来判断当前处于哪个交易阶段(建立区间、交易、平仓)。数据获取 (get_market_data_ex):
count=1 表示只取最新的一根 K 线数据,用于实时判断。状态管理:
ContextInfo.day_high 和 day_low 用于存储当天的关键点位。ContextInfo.current_date 用于检测日期变更,确保第二天开盘时重置策略状态。交易函数:
buy_open (买入开仓) 和 sell_open (卖出开仓),这是针对期货的便捷函数。sell_close_tdayfirst (卖出平仓,平今优先),适合日内交易,优先平掉当天的仓位以节省手续费(针对某些品种)。ContextInfo.account_id 设置正确。Q: 如何修改止损逻辑?
A: 在“交易阶段”的代码块中,可以使用 get_trade_detail_data 获取当前持仓成本。如果 (现价 - 成本) / 成本 < -0.01 (亏损1%),则触发平仓函数。
Q: 为什么使用 get_market_data_ex 而不是 get_market_data?
A: get_market_data_ex 是 QMT 的新版接口,返回 Pandas 格式,处理数据更方便,且支持订阅模式,效率更高。
Q: 如何在股票上做空?
A: 在 A 股市场,普通账户无法直接做空。如果是信用账户(融资融券),可以使用 passorder 函数配合 opType=28 (融券卖出) 来实现做空逻辑。