3.58K 浏览
1

今日模拟交易中出现一个换月问题,当它对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)

整理一下思路:

  1. 用get_position()取得持仓列表list
  2. 用get_quote(‘KQ.m@SHFE.rb’).underlying_symbol取得新主力symbol
  3. 判断symbol是否包含在list中
  4. 如果不在,证明换月或空仓。此时提取symbol中的前缀’SHFE.rb’(也可由’KQ.m@SHFE.rb’给定或截取字符串),遍历list中的老合约,并set_target_volume(0)
Shoe X 更改状态以发布 2020年9月3日
0

29 行的api.wait_update() 是不建议单独使用的

target_pos 也不是保证一次api.wait_update() 全部成交到位并收到反馈,所以应该把平仓逻辑放入while True 循环内,然后判断当 position.pos 达到了你设定的目标持仓位再跳出循环

ringo 已回答的问题 2020年8月13日