1.40K 浏览
0

天勤的技术支持,
你好!我是专业版会员用户,现在发现在进行期权回测时;
1)有时候找不到相应的期权合约, 找不到期权合约就会导致无法下单。查找期权我用的函数是api.query_options()
2)但是用其他工具在模拟交易模式验证期权合约其实是存在的, 注意是在期权模拟交易模式下测试,用的函数也是api.query_options()
3) 发现有问题的数据,如回测到2021年5~6月份时,查询DEC.p2111的所有期权,返回数据实值期权合约、平值期权合约和虚值期权合约都是空的; 但是回测到6月18日后,却又可以查得到了相应的期权合约,且下单也是正常的;
4)程序较为庞大不方便都贴出来;
5)请问是因为5~6月上旬期间,DEC.p2111的期权都还没有生效的原因的,还是其他什么原因?

拜托处理下,谢谢!

a. 这是部分代码:

elif TEST_DESTINATION_OPTIONS == 1:  # 如果期权回测模式

    # 先处理空单的平仓: 查询该期货所有的待平仓方向期权; 再逐一平仓
    ls = api.query_options(SYMBOL, option_class="PUT")
    numOfOpt = len(ls)

    for ki in range(0, numOfOpt, 1): #先对空头合约逐个清仓
        SYMBOL_OPTION_P = ls[ki]
        pos_optionP = api.get_position(SYMBOL_OPTION_P)

        # 这两行是调试代码
        if pos_optionP.pos_long  > 0:
            print("pos_long=", pos_optionP.pos_long)

        if pos_optionP.pos_long != 0: #PUT期权的持仓数参数为pos_long
            target_pos_optionP = TargetPosTask(api,SYMBOL_OPTION_P)  # TargetPosTask 是按照目标持仓手数自动调整 账户持仓中某合约的净持仓的工具
            OPERATION_COUNT_P = pos_optionP.pos_long  # 应该是pos_long
            target_pos_optionP.set_target_volume(0)  # 设置目标持仓为正数表示多头,负数表示空头,0表示空仓
            mytrdlog.AddAndLogOneTradeRecord(mode=1, symbol=SYMBOL_OPTION_P, callput=-1,  #空单平仓
                                             direction=2,
                                             nlot=OPERATION_COUNT_P, \
                                             price=klines['close'].iloc[-1],
                                             time=klines['datetime_dt'].iloc[-1],
                                             balance=account["balance"])
    #end of for ki in range(0, numOfOpt, 1)

    #sleep(2) #等待2s等平仓先完成?
    #再处理做多
    #这里不能每次都直接创建一个对象,应先查询有无存在的对象;因为之前可能已经做多买过了.
    ls = api.query_options(SYMBOL, option_class="CALL")
    numOfOpt = len(ls)
    posC_long_total: int = 0
    for ki in range(0, numOfOpt, 1): #先对空头合约逐个清仓
        SYMBOL_OPTION_C = ls[ki]
        pos_optionC = api.get_position(SYMBOL_OPTION_C)
        posC_long_total = posC_long_total+pos_optionC.pos_long
    #end of for ki in range(0, numOfOpt, 1)

    #如果已持仓的合约数量未达到目标值,则继续下单; 但不是简单补仓,而是根据当前价格重新找实值step档的合约下单,
    if posC_long_total < basicInfo.optionCallLotQty[i1]:
        SYMBOL_OPTION_C = GetTheOptionToOperate(api, SYMBOL, direction="CALL",price=klines['close'].iloc[-1], step=6, mode=1)

        #debug code
        #SYMBOL_OPTION_C = "DCE.p2111-C-7200"  #for test only

        if SYMBOL_OPTION_C != "NULL":
            target_pos_optionC = TargetPosTask(api,SYMBOL_OPTION_C)  # TargetPosTask 是按照目标持仓手数自动调整 账户持仓中某合约的净持仓的工具
            OPERATION_COUNT_C = basicInfo.optionCallLotQty[i1] - posC_long_total
            target_pos_optionC.set_target_volume(OPERATION_COUNT_C)  # 设置目标持仓为正数表示多头,负数表示空头,0表示空仓
            mytrdlog.AddAndLogOneTradeRecord(mode=1, symbol=SYMBOL_OPTION_C, callput=1, #多单开仓
                                             direction=1,
                                             nlot=OPERATION_COUNT_C, \
                                             price=klines['close'].iloc[-1],
                                             time=klines['datetime_dt'].iloc[-1],
                                             balance=account["balance"])
        #end of if SYMBOL_OPTION_C != "NULL":
        else:
            print("Cannot find related Symbol_Option")
    #end of  if pos_long_total < OPERATION_COUNT_C:

b) 这是查找查找期权合约的函数的代码:

# 计算找出一个对应的最合适的期权合约
# 新方法
# direction: 合约类型, "CALL", "PUT"
# price: 行权价
# step: 几档, =0 平值合约; > 0, 实值合约,档位为step; < 0,虚值合约,档位为|step|
# mode: 匹配模式: =0, 精确匹配step这一档的合约; =1, 模糊匹配step, 即如果没有step这一档的合约,就尽量找最接近的合约
# 输出结果:self.symOptionCall 或 self.symOptionPut (由direction决定)
def GetTheOptionToOperate(api, symbol1, direction: str, price: float, step: int, mode: int):
    if direction == "CALL":
        in_money_options, at_money_options, out_of_money_options = \
            api.query_all_level_options(symbol1, price, "CALL")
    else:
        in_money_options, at_money_options, out_of_money_options = \
            api.query_all_level_options(symbol1, price, "PUT")

    print("symbol=%s, dirt=%s, price=%.1f, step=%d, mode=%d"%(symbol1,direction,price,step, mode))
    #print("in money option:")
    #print(in_money_options)  # 实值期权列表
    #print("at money option:")
    #print(at_money_options)  # 平值期权列表
    #print("out of money option:")
    #print(out_of_money_options)  # 虚值期权列表

    if step == 0: #找平值合约
        num1 = len(at_money_options)
        if (num1 == 0):
            return "NULL"
        else:
            return at_money_options[0]

    elif step > 0: #找实值合约
        num1 = len(in_money_options)
        if num1 == 0:
            print("No option_symbol available.")
            return "NULL"
        if step > num1: #超范围了,返回"NULL"
            if mode == 0: #精确匹配
                return "NULL"
            elif mode == 1: #模糊匹配
                return in_money_options[0]
        else:
            return in_money_options[num1 - step]
    else:  # 找虚值合约
        step = 0-step
        num1 = len(out_of_money_options)
        if num1 == 0:
            return "NULL"
        if step > num1:  # 超范围了,返回"NULL"
            if mode == 0:  # 精确匹配
                return "NULL"
            elif mode == 1:  # 模糊匹配
                return out_of_money_options[0]
        else:
            return out_of_money_options[num1 - step]
李思恒 已回答的问题 2022年7月8日

补充说明:前面表述有误,查询期权用的函数应该是 api.query_all_level_options()

0

先更新下tqsdk,query函数我记得最新的版本是有回测时的bug修复的,然后如果还有问题你可以加我好友qq532428198

yanfengcun0668 发表新评论 2022年7月8日

感谢李工的大力支持。
查清楚了,DCE.p的期权是个品种,6月18日才上市的,所以6月18日之后才能查询得到相关合约;之前日期查询都是返回空数据。
点个赞!

您正在查看1个答案中的1个,单击此处查看所有答案。