3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于 QMT 平台 API 编写的内外盘成交量比率交易策略。
该策略的核心逻辑是利用**外盘(主动买入)和内盘(主动卖出)**的成交量差异来判断市场情绪:
ContextInfo.get_bvol() 获取外盘成交量,使用 ContextInfo.get_svol() 获取内盘成交量。threshold(阈值)参数,防止在多空力量均衡时频繁交易。# -*- coding: gbk -*-
import time
def init(ContextInfo):
"""
策略初始化函数
"""
# 1. 设置资金账号 (请替换为您真实的资金账号)
ContextInfo.account_id = 'YOUR_ACCOUNT_ID'
ContextInfo.account_type = 'STOCK' # 账号类型:'STOCK'股票, 'FUTURE'期货
ContextInfo.set_account(ContextInfo.account_id)
# 2. 设置股票池 (示例:平安银行)
ContextInfo.stock_code = '000001.SZ'
ContextInfo.set_universe([ContextInfo.stock_code])
# 3. 策略参数设置
ContextInfo.threshold = 0.1 # 阈值 10%,即外盘比内盘多10%才买入
ContextInfo.trade_vol = 100 # 每次交易股数
print("策略初始化完成,监控标的: {}".format(ContextInfo.stock_code))
def get_position(ContextInfo, stock_code):
"""
获取指定股票的持仓数量
"""
try:
# 获取持仓对象列表
pos_list = get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
for pos in pos_list:
if pos.m_strInstrumentID + '.' + pos.m_strExchangeID == stock_code:
return pos.m_nVolume
return 0
except Exception as e:
print("获取持仓失败: {}".format(e))
return 0
def handlebar(ContextInfo):
"""
K线/行情驱动函数
"""
# 仅在最后一根K线(实时行情)或回测的当前步运行逻辑
# 注意:get_bvol/get_svol 通常在实时行情中有效,回测历史数据可能需要特定数据源支持
if not ContextInfo.is_last_bar():
return
stock_code = ContextInfo.stock_code
# 1. 获取内外盘数据
# 注意:API返回的是字符串,需要转换为浮点数
try:
bvol_str = ContextInfo.get_bvol(stock_code) # 外盘(主动买入)
svol_str = ContextInfo.get_svol(stock_code) # 内盘(主动卖出)
# 数据有效性检查
if bvol_str == '' or svol_str == '':
return
bvol = float(bvol_str)
svol = float(svol_str)
if svol == 0: # 防止除以0
return
except Exception as e:
print("获取内外盘数据异常: {}".format(e))
return
# 2. 获取当前持仓
current_pos = get_position(ContextInfo, stock_code)
# 3. 计算多空比率
# 避免除零错误,如果内盘极小,视为极端多头
ratio = bvol / svol if svol > 0 else 999
# 4. 交易逻辑
# --- 买入逻辑 ---
# 外盘明显大于内盘 (例如:外盘是内盘的 1.1 倍以上)
if bvol > svol * (1 + ContextInfo.threshold):
if current_pos == 0:
print("【买入信号】外盘: {:.0f}, 内盘: {:.0f}, 比例: {:.2f}".format(bvol, svol, ratio))
# 使用 order_shares 指定股数下单
order_shares(stock_code, ContextInfo.trade_vol, 'fix', -1, ContextInfo, ContextInfo.account_id)
# 'fix', -1 代表使用最新价下单 (具体行为取决于交易设置,通常等同于对手价或最新价)
# --- 卖出逻辑 ---
# 内盘明显大于外盘 (例如:内盘是外盘的 1.1 倍以上)
elif svol > bvol * (1 + ContextInfo.threshold):
if current_pos > 0:
print("【卖出信号】外盘: {:.0f}, 内盘: {:.0f}, 比例: {:.2f}".format(bvol, svol, ratio))
# 卖出全部持仓或指定数量
order_shares(stock_code, -current_pos, 'fix', -1, ContextInfo, ContextInfo.account_id)
# 打印调试信息 (可选)
# print("监控中 - {} - 外盘:{:.0f} 内盘:{:.0f}".format(stock_code, bvol, svol))
get_bvol 和 get_svol 接口返回的是 字符串 (String) 类型,直接比较会报错,必须使用 float() 进行转换。'fix', -1,这在 QMT 中通常表示以最新价或对手价下单(取决于客户端的交易设置)。如果需要更激进的成交,可以使用 'COMPETE'(对手价)或 'MARKET'(市价)。get_trade_detail_data 来获取真实的账户持仓,这是比维护本地变量更稳健的方法。Q: 为什么 get_bvol 返回的是字符串?
A: 这是 QMT 底层 C++ 接口透传的设计,为了保证大数值的精度或兼容性,Python 层接收到的是字符串,使用前务必转换。
Q: 这个策略适合什么周期运行?
A: 建议在 分时 (Tick) 或 1分钟/5分钟 周期下运行。因为内外盘数据是盘中实时变化的,高频监控能更敏锐地捕捉资金流向。
Q: 如何增加止损逻辑?
A: 可以在 handlebar 中获取持仓成本 (pos.m_dOpenPrice) 和最新价 (ContextInfo.get_market_data(['close']...)),计算浮动盈亏比例,当亏损超过一定比例(如 -5%)时强制触发卖出逻辑。