今日模拟交易中出现一个换月问题,当它对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)
samhmen 已回答的问题 2024年11月17日
29 行的api.wait_update() 是不建议单独使用的
target_pos 也不是保证一次api.wait_update() 全部成交到位并收到反馈,所以应该把平仓逻辑放入while True 循环内,然后判断当 position.pos 达到了你设定的目标持仓位再跳出循环
ringo 已回答的问题 2020年8月13日