今日模拟交易中出现一个换月问题,当它对DCE.p开仓时,它检测到DCE.pg具有相同的前缀,于是错误的对pg平仓。并参考ringo老师的建议,进行了修改。
测试代码如下():
from tqsdk import TqApi, TargetPosTask api = TqApi() #模拟持有old主力合约'SHFE.cu2011' TargetPosTask(api, 'SHFE.cu2011').set_target_volume(1) api.wait_update() api.wait_update() #优先获得(昨仓)持仓列表s_list position = api.get_position() s_list = list(position) print("昨仓列表",s_list) # def close_pos_his(SYMBOL): if SYMBOL not in s_list: #取得主力合约的前缀,用以找到s_list中对应的old合约,C开头的郑商所合约月份为3位数,其它4位数 str = SYMBOL[:-3] if SYMBOL.startswith('C') else SYMBOL[:-4] for x in s_list: if x.startswith(str) and x != SYMBOL and len(x)==len(SYMBOL): position = api.get_position(x) pos_v = position.pos if pos_v: print("持有老合约", pos_v) s_list.remove(x) #将其移除列表,避免重复操作 TargetPosTask(api, x).set_target_volume(0) while True: print("等待平仓......", api.wait_update()) if position.pos == 0: print("平仓完成") break # #取得主连对应的主力合约 quote = api.get_quote('KQ.m@SHFE.cu') SYMBOL = quote.underlying_symbol print("新主力", SYMBOL) #如果新主力SYMBOL不在s_list中,则有两种可能,1主力换月;2未持仓 #始终只用新主力SYMBOL计算交易条件 #…… target_pos = TargetPosTask(api, SYMBOL) #模拟条件成立发出交易信号 try: while True: api.wait_update() if 1: #开仓(新主力合约开仓) target_pos.set_target_volume(-1) close_pos_his(SYMBOL) except KeyboardInterrupt: api.close()
_________________________________________________________________________
__________________这是一条分割线,以下是早先有误的内容____________________________
又临近主力换月,因不久前接触了主连映射,我认为可以利用起来。
当然,我的想法很简单,在新主力合约达到开仓条件后,先平掉老主力合约的仓位。(弊端:如果新主力一直不出开仓信号,将不能平掉老主力)
整个测试过程如下:
from tqsdk import TqApi, TargetPosTask api = TqApi() #模拟持有old主力合约'SHFE.rb2009' TargetPosTask(api, 'SHFE.rb2009').set_target_volume(1) api.wait_update() #优先获得(昨仓)持仓列表list position = api.get_position() list = [x for x in position] print(position) print("昨仓列表",list) #取得主连对应的主力合约 quote = api.get_quote('KQ.m@SHFE.rb') SYMBOL = quote.underlying_symbol print("新主力", SYMBOL) #如果新主力SYMBOL不在list中,则有两种可能,1主力换月;2未持仓 #始终只用新主力SYMBOL计算交易条件 #…… target_pos = TargetPosTask(api, SYMBOL) #模拟条件成立发出交易信号 if 1: if SYMBOL not in list: #取得主力合约的前缀,用以找到list中对应的old合约,C开头的郑商所合约月份为3位数,其它4位数 str = SYMBOL[:-3] if SYMBOL.startswith('C') else SYMBOL[:-4] for x in list: if x.startswith(str): TargetPosTask(api, x).set_target_volume(0) #对新合约执行信号操作 target_pos.set_target_volume(-1) api.wait_update() print(position)
整理一下思路:
- 用get_position()取得持仓列表list
- 用get_quote(‘KQ.m@SHFE.rb’).underlying_symbol取得新主力symbol
- 判断symbol是否包含在list中
- 如果不在,证明换月或空仓。此时提取symbol中的前缀’SHFE.rb’(也可由’KQ.m@SHFE.rb’给定或截取字符串),遍历list中的老合约,并set_target_volume(0)
29 行的api.wait_update() 是不建议单独使用的
target_pos 也不是保证一次api.wait_update() 全部成交到位并收到反馈,所以应该把平仓逻辑放入while True 循环内,然后判断当 position.pos 达到了你设定的目标持仓位再跳出循环
ringo 已回答的问题 2020年8月13日