3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个关于**日内跳空缺口回补(Gap Filling)**策略的实现方案。
缺口回补策略基于“均值回归”的思想。当市场开盘价格显著偏离前一交易日的收盘价(形成缺口)时,价格往往有动力向昨收价回归,以“回补”这个缺口。
# -*- coding: gbk -*-
import pandas as pd
import time
def init(ContextInfo):
# ================= 策略参数设置 =================
# 交易账号 (请修改为您的实际账号)
ContextInfo.account_id = '6000000000'
# 账号类型:'STOCK'股票, 'FUTURE'期货
ContextInfo.account_type = 'STOCK'
# 策略运行标的 (示例:平安银行)
ContextInfo.stock_code = '000001.SZ'
# 缺口阈值 (例如 1% = 0.01)
ContextInfo.gap_threshold = 0.01
# 止损阈值 (例如亏损 2% 止损)
ContextInfo.stop_loss_pct = 0.02
# 单笔交易数量
ContextInfo.trade_volume = 100
# ================= 状态变量 =================
# 标记今日是否已经开仓
ContextInfo.has_opened = False
# 记录开仓价格
ContextInfo.open_trade_price = 0.0
# 记录目标回补价格(即昨收价)
ContextInfo.target_price = 0.0
# 设置股票池
ContextInfo.set_universe([ContextInfo.stock_code])
# 绑定账号
ContextInfo.set_account(ContextInfo.account_id)
print("策略初始化完成:日内缺口回补策略")
def handlebar(ContextInfo):
# 获取当前K线的时间
index = ContextInfo.barpos
timetag = ContextInfo.get_bar_timetag(index)
# 将时间戳转换为 datetime 对象以便提取小时和分钟
bar_time_str = timetag_to_datetime(timetag, '%H%M%S')
bar_time_int = int(bar_time_str)
# 获取当前最新价格
current_price = ContextInfo.get_market_data(['close'], stock_code=[ContextInfo.stock_code], period='1d', count=1, dividend_type='follow')
# 注意:get_market_data 返回的是 pandas Series/DataFrame,需要取值
if isinstance(current_price, (pd.Series, pd.DataFrame)) and not current_price.empty:
# 这里取的是当前bar的收盘价作为最新价
last_price = ContextInfo.get_market_data(['close'], stock_code=[ContextInfo.stock_code], period='1m', count=1, dividend_type='follow')
if isinstance(last_price, pd.DataFrame):
current_price = last_price.iloc[-1]['close']
else:
return # 数据获取失败
else:
return
# ================= 1. 开盘检测缺口 (09:30 - 09:35) =================
# 每天只开仓一次
if not ContextInfo.has_opened and 93000 <= bar_time_int <= 93500:
# 获取日线数据:取最近2根日线(今天和昨天)
# index 0 是昨天,index 1 是今天(包含今天的开盘价)
daily_data = ContextInfo.get_market_data_ex(
['open', 'close', 'preClose'],
[ContextInfo.stock_code],
period='1d',
count=1,
dividend_type='follow'
)
if ContextInfo.stock_code in daily_data:
df_daily = daily_data[ContextInfo.stock_code]
if not df_daily.empty:
# 获取今日开盘价
today_open = df_daily.iloc[-1]['open']
# 获取昨日收盘价 (preClose 字段通常比取上一根K线close更准确)
yesterday_close = df_daily.iloc[-1]['preClose']
ContextInfo.target_price = yesterday_close
# 计算缺口幅度
gap_pct = (today_open - yesterday_close) / yesterday_close
# --- 策略逻辑:跳空低开 (Gap Down) 买入 ---
if gap_pct < -ContextInfo.gap_threshold:
print(f"检测到跳空低开: 开盘{today_open}, 昨收{yesterday_close}, 幅度{gap_pct:.2%}")
# 执行买入
passorder(23, 1101, ContextInfo.account_id, ContextInfo.stock_code, 5, -1, ContextInfo.trade_volume, ContextInfo)
ContextInfo.has_opened = True
ContextInfo.open_trade_price = current_price
print(f"买入开仓: 价格 {current_price}, 数量 {ContextInfo.trade_volume}")
# ================= 2. 盘中监控 (止盈/止损) =================
if ContextInfo.has_opened:
# 止盈条件:价格回升到昨日收盘价(缺口回补)
if current_price >= ContextInfo.target_price:
print(f"缺口回补成功: 当前价{current_price} >= 昨收{ContextInfo.target_price}")
close_position(ContextInfo)
# 止损条件:价格继续下跌超过止损线
elif current_price <= ContextInfo.open_trade_price * (1 - ContextInfo.stop_loss_pct):
print(f"触发止损: 当前价{current_price}, 成本{ContextInfo.open_trade_price}")
close_position(ContextInfo)
# ================= 3. 尾盘强制平仓 (14:55) =================
if ContextInfo.has_opened and bar_time_int >= 145500:
print("尾盘强制平仓")
close_position(ContextInfo)
# ================= 4. 收盘重置状态 (15:00 后) =================
# 如果是回测,可能需要手动重置;实盘中第二天init会重新运行,或者在这里判断日期变化
if bar_time_int >= 150000:
ContextInfo.has_opened = False
def close_position(ContextInfo):
"""
平仓函数
"""
# 卖出平仓 (股票卖出操作码 24)
passorder(24, 1101, ContextInfo.account_id, ContextInfo.stock_code, 5, -1, ContextInfo.trade_volume, ContextInfo)
print(f"执行平仓: {ContextInfo.stock_code}")
# 重置开仓状态,防止今日再次开仓
ContextInfo.has_opened = False
# 标记为今日已完成交易,避免重复开仓(如果需要严格控制)
# 在此简单逻辑中,has_opened = False 会导致如果还在9:35之前可能再次开仓,
# 实际应用中建议增加一个 ContextInfo.traded_today 变量来控制一天只做一次。
数据获取 (get_market_data_ex):
period='1d' 获取日线数据。这是因为我们需要准确的“今日开盘价”和“昨日收盘价”。preClose 字段是交易所提供的昨收价,比自己去取上一根K线的 close 更稳健(处理了除权除息等情况)。时间控制:
timetag_to_datetime 用于将毫秒时间戳转换为易读的格式(如 093000)。09:30 到 09:35 之间,确保是针对开盘缺口的交易。14:55,确保在收盘前平掉仓位(如果是T+0品种)。交易逻辑:
gap_pct < -阈值。逻辑是市场反应过度,预期反弹。执行买入。current_price >= yesterday_close 时,说明缺口已补,任务完成,平仓。下单函数 (passorder):
23: 股票买入。24: 股票卖出。1101: 单股、单账号、普通、股/手方式下单。5: 最新价报价(也可以用 14 对手价以保证成交)。ContextInfo.account_id 修改为你自己的实盘或模拟盘账号。ContextInfo.stock_code 修改为你想交易的股票或ETF代码。Q: 为什么我回测时没有交易?
A:
1% (0.01) 缺口的行情。ContextInfo.stock_code 是否在你的数据下载范围内。handlebar,一天只运行一次,无法实现日内平仓。Q: 如何做空(跳空高开卖出)?
A:
如果是期货,将买入代码改为 opType=3 (开空),平仓改为 opType=4 (平昨) 或 5 (平今)。
如果是股票,你需要持有底仓。在开仓逻辑中,判断 gap_pct > 阈值,然后执行 passorder(24, ...) 卖出;在止盈逻辑(价格跌回昨收)时,执行 passorder(23, ...) 买回。
Q: get_market_data 和 get_market_data_ex 有什么区别?
A: get_market_data_ex 是新版接口,返回的数据结构更清晰(通常是 Dict of DataFrames),且支持订阅逻辑,建议优先使用。代码中混用了两者是为了展示不同场景,核心逻辑依赖 ex 接口获取日线数据。