前面介绍了如何利用迅投miniQMT实现同花顺自选股的盘中实时监控方法,本文和大家一起分享如何利用迅投miniQMT在实盘中实现大单拆单批量下单。
特别提示:本文只从技术层面介绍如何实现大单拆单进行批量下单,不对读者的实际盈亏负责。进行实盘下单前,请务必检查好各参数!
本专栏文章:
使用迅投miniQMT实时监控同花顺自选股,实现自动交易
使用python获取同花顺免费版和同花顺远航版自选股数据用于量化交易
使用python将选股策略选股结果自动更新同花顺【远航版】自选股
使用python将选股策略选股结果自动更新同花顺【免费版】自选股
迅投miniQMT实盘大单拆单批量下单方法的实现
进行实盘交易时,避免对市场造成太大冲击或者隐藏实际交易意图,有时可能需要将一个大单分成多个小单逐步执行,这时就需要进行大单拆单,且保证拆单后的每单买卖数量符合交易所交易规则。
对大单进行拆单,难点在于如何进行拆单,且保证拆单后的每单数量符合交易所交易规则。
比如,想买入某股票1000股,分拆成3次买入,怎么拆分呢?如果用1000除以3的话,每单333.33,显然不符合交易规则。
再如,想买入某科创板股票400股,分拆成4次,每次100股,这也不符合上交所关于科创板股票的交易规则。
那该如何处理呢?
本文的拆分思路是,在确保每次下单的数量符合交易所的最小交易单位的前提下(为简化起见,本文只是平均拆单,随机拆单方法后续介绍),将余数加到最后一个订单上。
计算每单数量:
base_quantity = total_quantity // order_nums
# 余数处理
remainder = total_quantity % (order_nums * min_trading_unit)
# 调整数量符合最小交易单位
adjusted_quantity = (base_quantity // min_trading_unit) * min_trading_unit
if adjusted_quantity == 0:
raise ValueError("拆单后单笔数量小于最小交易单位")
处理余数
for i in range(order_nums):
# 计算当次委托量(最后一笔加上余数)
order_volume = adjusted_quantity
if i == order_nums - 1:
order_volume += remainder
1.参数校验:检查买卖方向、数量有效性等基础参数
2.智能拆单:
自动计算基础委托量
最后一单自动处理余数
保证每笔委托符合最小交易单位
3.异常处理:捕获下单异常并继续执行后续委托
4.日志输出:实时显示下单进度,可通过参数关闭
说明:
1.本文未对下单结果进行跟踪,如有需要,请自行修改;
2.如需市价委托,请自行增加交易时间的判断。
def split_order(xt_trader, account, stock_code, price, total_quantity, order_type, price_type='limit', order_nums=5, interval=3, min_trading_unit=100, strategy_name='', order_remark='', is_log=True):
pass
参数: xt_trader (str): XtQuantTrader对象 account (str): StockAccount对象 stock_code (str): 股票代码 (e.g. '600519.SH') price (float): 委托价格 (市价单可设为0) total_quantity (int): 总委托数量 order_type (str): 买卖方向 ('buy'/'sell') price_type (str): 订单类型 ('limit'限价单/'market'市价单) order_nums (int): 拆单次数 (默认5次) interval (int): 下单间隔(秒) (默认3秒) min_trading_unit (int): 最小交易单位 (默认100,科创板200) is_log (bool): 是否打印执行日志 返回: list: 生成的订单ID列表
if __name__ == '__main__':
# init_xttrader()函数详见https://blog.csdn.net/tzzqn2008/article/details/145634836
xt_trader, acc = init_xttrader()
orders = split_order(
xt_trader=xt_trader,
account=acc,
stock_code='300382.SZ',
price=19.99,
total_quantity=300,
order_type='sell',
price_type='limit',
order_nums=3,
interval=1,
min_trading_unit=100
)
结果如下图所示:
其中:init_xttrader()函数是生成XtQuantTrader对象和StockAccount对象,详见《使用迅投miniQMT实时监控同花顺自选股,实现自动交易》
import time
import re
from xtquant import xtconstant
from utils.func import init_xttrader
import random
def split_order(xt_trader, account, stock_code, price, total_quantity, order_type, price_type='limit', order_nums=5, interval=3, min_trading_unit=100, strategy_name='', order_remark='', is_log=True):
"""
拆单下单函数 - 将大单拆分为多个符合规则的小单
参数:
xt_trader (str): XtQuantTrader对象
account (str): StockAccount对象
stock_code (str): 股票代码 (e.g. '600519.SH')
price (float): 委托价格 (市价单可设为0)
total_quantity (int): 总委托数量
order_type (str): 买卖方向 ('buy'/'sell')
price_type (str): 订单类型 ('limit'限价单/'market'市价单)
order_nums (int): 拆单次数 (默认5次)
interval (int): 下单间隔(秒) (默认3秒)
min_trading_unit (int): 最小交易单位 (默认100)
is_log (bool): 是否打印执行日志
返回:
list: 生成的订单ID列表
"""
# 参数校验
if not re.match(r'([0-9]{6})(.SH)$|([0-9]{6})(.SZ)|([0-9]{6})(.BJ)$', stock_code):
raise ValueError("股票代码不正确,请确保股票代码带市场编码,如600001.SH")
if str.upper(order_type) not in ['BUY', 'SELL']:
raise ValueError("买卖方向错误,应为'BUY'或'SELL'")
if str.upper(price_type) not in ['LIMIT', 'MARKET']:
raise ValueError("买卖方向错误,应为'BUY'或'SELL'")
if total_quantity <= 0:
raise ValueError("委托数量必须大于0")
if str.startswith(stock_code, '688'):
min_trading_unit = 200
# 计算基础手数
base_quantity = total_quantity // order_nums
# 余数处理
remainder = total_quantity % (order_nums * min_trading_unit)
# 调整数量符合最小交易单位
adjusted_quantity = (base_quantity // min_trading_unit) * min_trading_unit
if adjusted_quantity == 0:
raise ValueError("拆单后单笔数量小于最小交易单位")
# 转换order_type为miniQMT的order_type
order_type = xtconstant.STOCK_BUY if str.upper(order_type) == 'BUY' else xtconstant.STOCK_SELL
# 如果是市价委托,将price设置为0
price = price if str.upper(price_type) == 'LIMIT' else 0
# 转换price_type为miniQMT的price_type
price_type = xtconstant.FIX_PRICE if str.upper(price_type) == 'LIMIT' else xtconstant.LATEST_PRICE
# 设置strategy_name
if strategy_name == '':
strategy_name = 'spit_strategy'
# 设置order_remark
if order_remark == '':
order_remark = [f"spit_strategy_{j + 1}" for j in range(order_nums)]
orders = []
try:
for i in range(order_nums):
# 计算当次委托量(最后一笔加上余数)
order_volume = adjusted_quantity
if i == order_nums - 1:
order_volume += remainder
# 生成实盘委托
# 实盘打开下一行注释,请务必检查好相关参数。打开注释代表实盘盈亏自负!
# order_id = xt_trader.order_stock(account, stock_code, order_type, order_volume, price_type, price, strategy_name, order_remark[i])
if order_id:
orders.append(order_id)
if is_log:
print(f"[{time.strftime('%H:%M:%S')}] 已发送【{'买' if order_type == 23 else '卖'}】单 #{i + 1}: "
f"{order_volume}股 @ {price if price else '市价'} 订单ID:{order_id} 策略名:{strategy_name} 订单备注:{order_remark[i]}")
else:
if is_log:
print(f"第 {i + 1}/{order_nums} 次下单失败")
# 等待间隔
if i < order_nums - 1:
time.sleep(interval)
except Exception as e:
print(f"下单异常: {str(e)}")
return orders
return orders
if __name__ == '__main__':
xt_trader, acc = init_xttrader()
orders = split_order(
xt_trader=xt_trader,
account=acc,
stock_code='300382.SZ',
price=19.99,
total_quantity=300,
order_type='sell',
price_type='limit',
order_nums=3,
interval=0,
min_trading_unit=100
)
print('*' * 50)
print(orders)
码字不易,原创更不易,如您觉得本文对您有帮助,麻烦动动您富贵的小手,点赞、收藏、关注、订阅!!!