乐于分享
好东西不私藏

PeopleQuant帮助文档:异常交易防范:频繁报撤单、自成交

PeopleQuant帮助文档:异常交易防范:频繁报撤单、自成交

程序化交易中可能触发监管措施的异常交易主要有大额报撤单、频繁报撤单、自成交。
通过把大单拆成小单来规避大额报单,处理逻辑比较简单,一般在写程序时会自主控制,自己心里清楚就不容易出错。
容易出错的是频繁报撤单和自成交。例如我之前在主力合约换月时,执行平老仓开新仓,但是在平老仓时设置了不成交自动撤单追单的逻辑,根据当前的挂单价判断是否撤单,但对行情变量复制粘贴时出错,导致错误使用了新主力的行情价判断,发出了持续的频繁报撤单,还好期货公司及时提醒,避免了更大的损失。
类似这样的错误,可能经常在程序中发生,复制粘贴错了变量、错误改变了变量的值、多线程下数据读写冲突、对手价下单出现巨大滑点……
但不管什么错误,归根结底,只要不把错误订单发出,或者发出了错误订单及时发现并停止策略执行,才能避免损失。
下面给出利用PeopleQuant进行错误防范的一些应用场景。
1、大单拆分,例如需要下单1000手,拆成小单来完成,基本结构如下:
import random#大单拆分lots = 1000#多头持仓小于目标数量while positons.pos_long < lots: #循环执行直到持仓开完    lot = random.randrange(10100#在10~100之间随机生成下单数量    lot = min(lot, lots - positons.pos_long) #剩余下单数量    #默认按超价1跳下单,排队价偏离1跳后自动撤单,重新追单    r = pqapi.open_close(symbol,"kaiduo",lot,price='超价',n_price_tick=1,order_info='大单拆分')    lots -= r['shoushu']
除了把大单拆分成随机小数量实现随机冰山的效果,还可以加入时间以设定执行多长时间,实现twap算法,或者根据成交量计算拆分的数量实现vwap算法。
2、避免使用对手价或涨跌停、市价下单,避免流动性不足出现巨大滑点,PeopleQuant默认采用超排队价1跳下单,单子排在最前面就可以增加成交概率,还能减少巨大滑点的可能性。当然你也可以指定其他价格下单。
3、当你使用撤单追单逻辑时,需要注意撤单和下单同时满足的可能性,PeopleQuant中的下单函数open_close默认当排队价超过下单价1跳,并且有新的成交价产生时,说明别人的单子排在你前面了并且产生了成交,就自动撤单。为避免你使用不合理的下单价导致撤单条件立即满足,例如我之前用新主力行情下单但持仓是老合约,根据老合约的行情判断撤单。或者你用跌停价买入,默认又按当前排队价计算撤单,就可能下单即撤单,因此,open_close加入了此种场景的判断,当下单的同时满足撤单条件时会直接返回。下单后会提示以下日志:
#跌停价买入,默认价格偏离1跳撤单,预计下单后会立即触发撤单pqapi.open_close("FG610",'kaiduo',1,quote1.LowerLimitPrice,n_price_tick = 1,OrderMemo='')#涨停价卖出,默认价格偏离1跳撤单,预计下单后会立即触发撤单pqapi.open_close("FG610",'kaikong',1,quote1.UpperLimitPrice,n_price_tick = 1,OrderMemo='')'''日志输出:'''2026-04-16 13:57:32.213099 -open_close报单错误,合约:FG610,交易方向:kaiduo,下单价格:1019.0,买入价:1019.0,卖出价:1019.0,当前排队价1108.0,已满足撤单条件:价格偏离1跳,极易触发立即撤单2026-04-16 13:57:32.213810 -open_close报单错误,合约:FG610,交易方向:kaikong,下单价格:1221.0,买入价:1221.0,卖出价:1221.0,当前排队价1110.0,已满足撤单条件:价格偏离1跳,极易触发立即撤单
如果你不是用PeopleQuant而是用其他平台做撤单追单,也可以参考PeopleQuant的下单逻辑来避免因价格错误频繁报撤单。
4、当你用多策略下单时,可能存在同一个合约相反方向同时报单的可能,就存在自成交可能,交易所对自成交监管较严,可能发生3次或5次就会收到监管措施。PeopleQuant加入了自成交预防,通过open_close的avoid_self_trade参数控制,默认开启自成交预防,当对合约下单时,先判断当前账户是否有该合约相反方向,下单价格刚好处在对手盘的挂单,如果再次下单有存在以对手价成交而产生自成交的可能性,就会被拦截。例如当前账户有如下挂单:
挂单价刚好处在买一卖一价上,再以对手价下单时收到下单拦截的日志如下:
2026-04-16 13:54:22.610278 -open_close卖一价1110.0存在未成交的挂单,未成交数量1,有自成交可能,合约:FG610,交易方向:kaiduo,下单价格:1221.0,买入价:1221.0,卖出价:1221.0,下单手数:12026-04-16 13:54:22.610858 -open_close买一价1108.0存在未成交的挂单,未成交数量1,有自成交可能,合约:FG610,交易方向:kaikong,下单价格:1019.0,买入价:1019.0,卖出价:1019.0,下单手数:1
如果你做套利交易,并且是两条腿分别下单,多个策略又可能对同一个合约下单,为避免自成交,以及避免因自成交判断而瘸腿,你可以在下单之前先主动做自成交检查:
#自成交检查kaiping ="kaiduo" #交易方向,买price = quote.AskPrice1 #买入价格direction = 'Sell' if kaiping in ["kaiduo","pingkong"else 'buy'#查询合约相反方向的未成交委托单orders = pqapi.get_symbol_order(symbol,OrderStatus="Alive",Direction=direction)for od in orders:    #如果报单价格处在对手价上    if kaiping in ["kaiduo","pingkong"and price >= od["LimitPrice"] == quote.AskPrice1:        '''买入价格等于对手价,对手价有相反方向未成交挂单,存在自成交可能,则不下单'''
5、设置阈值,根据账户的报撤单统计,判断统计数量在阈值范围内的才执行下单,这个统计是针对整个账户的下单,包括用其他终端的下单,例如:
#报单次数、撤单次数、多空开仓成交总手数、自成交数、信息量、重复报单数   阈值orders_insert,orders_cancel,daylots,self_trade,order_exe,repeat = 4,2,1,1,1,2#获取报撤单、信息量统计orderrisk = pqapi.get_order_risk(symbol)if orderrisk["order_count"] >= orders_insert: print(f"警告,报单笔数已超预警{orderrisk['order_count']} >= {orders_insert}")if orderrisk["cancel_count"] >= orders_cancel: print(f"警告,撤单笔数已超预警{orderrisk['cancel_count']} >= {orders_cancel}")if orderrisk["repeat"] >= repeat: print(f"警告,重复报单笔数已超预警{orderrisk['repeat']} >= {repeat}")
6、在策略中加入策略统计,记录当前策略的报撤单数量,每次调用open_close下单时,其返回值字段day_order表示报单次数(上期所平仓数量可能分成平今、平昨两笔报单),che_count表示撤单次数,策略报撤单根据这两个字段统计,例如:
#策略阈值day_cancel,day_order = 0,0 #初始值pqapi.open_close("FG610",'kaiduo',1,quote.LowerLimitPrice,n_price_tick = 1,OrderMemo='')day_order += r['day_order']day_cancel += r['che_count']
同样可在策略阈值满足的情况下再下单。
7、根据资金风险度和可用资金控制,账户可用资金不包含期权的浮动盈亏,虽然可用资金大于0一般不会触发强平,但可能造成可以继续开仓的假象,期权隐含的风险在到期时会显现出来,所以可用资金不能准确反应账户的风险,加入期权浮动盈亏后的市值权益才能真实反应账户风险,并由市值权益计算的风险度可作为进一步交易的判断。PeopleQuant的Account对象的字段market_balance表示市值权益,market_risk_ratio表示市值风险度,账户的浮动盈float_profit包含期权的浮动盈亏。
以上措施应该能满足大部分交易场景了,欢迎使用PeopleQuant实现量化交易,安装加更新(支持Python3.10以上版本):
pip install -U PeopleQuant
欢迎关注公众号,一起学习量化交易