VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 419
声望: 170

注明:
本贴是继如何解决CTP接口中集合竞价后立即下单被拒的问题 !之后,对交易状态信息进行更为深入地研究,实现了交易状态信息管理器,它可以更为有效地利用合约交易状态信息。

1. 交易状态信息管理器

1.1 功能介绍

主要功能:
1)集中保存所有品种的交易状态到字典
2)保存所有品种的交易状态到字典到json文件
3)从json文件加载已经保存的交易状态到字典
4)定时同步交易状态到字典到json文件
5)提取交易合约的在某个时刻的交易状态

1.2 代码实现

class TradeStatusManager(object):
    """ 
    交易状态管理器。
    主要功能:
    1)集中保存所有品种的交易状态到字典
    2)保存所有品种的交易状态到字典到json文件
    3)从json文件加载已经保存的交易状态到字典
    4)定时同步交易状态到字典到json文件
    5)提取交易合约的在某个时刻的交易状态
    """
    json_file = "trade_status.json"

    def __init__(self,event_engine:EventEngine,interval:int)-> None:
        self.event_engine = event_engine
        self.interval = interval
        self.count = 0
        # {vt_symbol:{trade_segment_sn:StatusData}}
        self.trade_status_map:Dict[str:Dict] = self.load_from_file()
        self.change = False

        self.register_event()

    def register_event(self):
        """ 注册消息事件 """
        self.event_engine.register(EVENT_TIMER,self.on_time_event)

    def load_from_file(self):
        """ 
        从json文件读取交易状态映射
        """
        filepath = get_file_path(self.json_file)
        # print(f"filepath = {filepath}")
        if filepath.exists():
            with open(filepath, mode="r", encoding="UTF-8") as f:
                data = json.load(fp=f,cls=TradeStatusDecoder)
            return data
        else:
            save_json(self.json_file, {})
            return {}

    def sync_to_file(self):
        """ 
        保存交易状态映射到json文件 
        """
        filepath = get_file_path(self.json_file)
        with open(filepath, mode="w+", encoding="UTF-8") as f:
            json.dump(
                self.trade_status_map,fp=f,
                cls=TradeStatusEncoder,
                indent=4,
                ensure_ascii=False
            )

    def on_time_event(self,event:Event):
        self.count += 1
        if self.count > self.interval:
            self.count = 0
            if self.change:
                self.sync_to_file()
                self.change = False
                print(f"已经保存交易状态映射到交易状态映射!")

    def save_status(self,status:StatusData):
        """ 
        保存交易状态映射到交易状态映射 
        """
        vt_symbol = status.vt_symbol
        if vt_symbol not in self.trade_status_map:
            self.trade_status_map[vt_symbol] = {}
        segment_sn_str = f"{status.trading_segment_sn}".rjust(2,'0')
        self.trade_status_map[vt_symbol].update({"current":segment_sn_str})
        self.trade_status_map[vt_symbol].update({segment_sn_str:status})
        next_segment_sn = self._get_next_segment_sn(status.vt_symbol)
        self.trade_status_map[vt_symbol].update({"next":next_segment_sn})
        self.change = True

    def get_status(self,vt_symbol:str):
        """ 
        获得一个datetime所处的交易状态 
        """
        # 构造
        symbol,exchange = extract_vt_symbol(vt_symbol)
        instrument = left_alphas(symbol)
        vt_symbol1 = f"{instrument}.{exchange.value}"

        ret_status = None
        # dt_time = dt.time()
        if vt_symbol1 in self.trade_status_map:
            current = self.trade_status_map[vt_symbol1]['current']
            # for enter_time_str,status in self.trade_status_map[vt_symbol1].items():
            #     enter_time = datetime.strptime(enter_time_str,"%H:%M:%S").time()
            #     if dt_time >= enter_time:
            #         ret_status = status 
            ret_status = self.trade_status_map[vt_symbol1][current]

        return ret_status

    def _get_next_segment_sn(self,vt_symbol:str):
        """ 得到合约的下一交易状态编号 """
        next_key:str = ""
        if vt_symbol in self.trade_status_map:
            instrment_dict = self.trade_status_map[vt_symbol] 
            current_key = instrment_dict['current']
            keys = [key for key in sorted(instrment_dict.keys()) if key not in ["current","next"]]
            if current_key == keys[-1]:
                next_key = keys[0]
            else:
                index = 0
                for key in keys:
                    index += 1
                    if key == current_key:
                        break
                next_key = keys[index]

        return next_key

    def get_current_status(self,vt_symbol:str):
        """ 得到合约的当前交易状态 """
        status:StatusData = None

        symbol,exchange = extract_vt_symbol(vt_symbol)
        instrument = left_alphas(symbol)
        vt_symbol1 = f"{instrument}.{exchange.value}"

        if vt_symbol1 in self.trade_status_map:
            status_dict = self.trade_status_map[vt_symbol1]
            key = status_dict['current']
            status = status_dict[key]

        return status

    def get_next_status(self,vt_symbol:str):
        """ 得到合约的下一交易状态 """
        status:StatusData = None

        symbol,exchange = extract_vt_symbol(vt_symbol)
        instrument = left_alphas(symbol)
        vt_symbol1 = f"{instrument}.{exchange.value}"
        if vt_symbol1 in self.trade_status_map:
            status_dict = self.trade_status_map[vt_symbol1]
            key = status_dict['next']
            status = status_dict[key]

        return status

    def get_tick_status(self,tick:TickData):
        """  
        得到一个tick数据的合约所处交易状态
        """
        status:StatusData = None
        instrument = left_alphas(tick.symbol)
        tick_time = tick.datetime.strftime("%H:%M:%S")
        vt_symbol = f"{instrument}.{tick.exchange.value}"
        if vt_symbol in self.trade_status_map:
            status_dict = self.trade_status_map[vt_symbol]
            curr_key = status_dict["current"]
            next_key = status_dict["next"]
            curr_status:StatusData = status_dict[curr_key]
            next_status:StatusData = status_dict[next_key]
            if curr_status.enter_time < next_status.enter_time:
                if curr_status.enter_time <= tick_time < next_status.enter_time:
                    status = curr_status
                elif next_status.enter_time <= tick_time:
                    status = next_status
            else:
                if curr_status.enter_time <= tick_time:
                    status = curr_status
                elif next_status.enter_time <= tick_time:
                    status = next_status
        return status

2. 交易状态相关类型的编码器

因为TradeStatusManager的trade_status_map字典是一个复杂字典,对其进行json转换需要自定义一个编码器。实现如下:

class TradeStatusEncoder(json.JSONEncoder):
    """
    交易状态相关类型的编码器
    """
    def default(self, obj):
        d = {}
        d['__class__'] = obj.__class__.__name__
        if isinstance(obj,Exchange):
            d['_value_'] = obj.value
        elif isinstance(obj,InstrumentStatus):
            d['_value_'] = obj.value
        elif isinstance(obj,StatusEnterReason):
            d['_value_'] = obj.value
        elif isinstance(obj,StatusData):
            d.update(obj.__dict__)
        else:
            d['__module__'] = obj.__module__
            d.update(obj.__dict__)            
        return d

3. 交易状态相关类型的译码器

与2的原因相同,对把json转换到TradeStatusManager的trade_status_map,需要自定义一个译码器。实现如下:

class TradeStatusDecoder(json.JSONDecoder):
    """
    交易状态相关类型的译码器
    """
    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=self.dict2obj)

    def dict2obj(self, d):
        if '__class__' in d:               
            class_name = d.pop('__class__')
            if class_name == 'Exchange':
                value = d['_value_']
                instance = Exchange(value)
            elif class_name == 'InstrumentStatus':
                value = d['_value_']
                instance = InstrumentStatus(value)
            elif class_name == 'StatusEnterReason':
                value = d['_value_']
                instance = StatusEnterReason(value)
            elif class_name == 'StatusData':
                vt_symbol = d.pop('vt_symbol')
                symbol,exchange = extract_vt_symbol(vt_symbol)
                args = dict((key,value) for key, value in d.items())
                args.update({"symbol":symbol,"exchange":exchange})
                instance = StatusData(**args)
            else:           
                module_name = d.pop('__module__')
                # print(f"!!!! class_name:{class_name} module_name:{module_name}")
                module = __import__(module_name)
                class_ = getattr(module, class_name)
                args = dict((key,value) for key, value in d.items())
                instance = class_(**args)
        else:
            instance = d
        return instance

4. trade_status.json文件

4.1 trade_status.json保存在哪里?

这个文件通常保存在系统的用户目录下的.vntrader目录中。

4.2 trade_status.json的内容

4.2.1 有哪些内容?

这里仅仅展示一部分内容,如果您足够敏感的化,您应该能够立即领悟到这些信息的作用!
它是以合约品种为主键值,以进入时间为次键值的嵌套的字典,字典值为交易状态。
有了它你可以知道某个品种、合约在某个时刻之后处于什么状态。

这些状态包含:

  • NO_TRADING = "非交易"
  • BEFORE_TRADING = "开盘前"
  • AUCTION_ORDERING = "集合竞价报单"
  • AUCTION_MATCH = "集合竞价撮合"
  • AUCTION_BALANCE = "集合竞价价格平衡"
  • CONTINOUS = "连续交易"
  • CLOSE = "收盘"

4.2.2 这些信息有什么用?

有了这个状态信息,你可以:

  1. 过滤非交易接收到的无效数据
  2. 可以知道收到的tick是开盘tick,其包含的last_price就是开盘价
  3. 可以避免在在收到开盘tick时立即执行
  4. 因为这些信息每个交易日似乎重复播放的,你可以利用这些历史接收的交易状态信息,快速作出决策。

4.2.3 内容展示

{
    "TA.CZCE": {
        "19:44:24": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "TA",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "非交易"
            },
            "trading_segment_sn": 4,
            "enter_time": "19:44:24",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "TA",
            "vt_symbol": "TA.CZCE"
        },
        "20:04:29": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "TA",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "非交易"
            },
            "trading_segment_sn": 4,
            "enter_time": "20:04:29",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "TA",
            "vt_symbol": "TA.CZCE"
        },
        "20:55:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "TA",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "集合竞价报单"
            },
            "trading_segment_sn": 7,
            "enter_time": "20:55:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "TA",
            "vt_symbol": "TA.CZCE"
        },
        "20:59:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "TA",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "集合竞价撮合"
            },
            "trading_segment_sn": 9,
            "enter_time": "20:59:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "TA",
            "vt_symbol": "TA.CZCE"
        },
        "21:00:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "TA",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "连续交易"
            },
            "trading_segment_sn": 13,
            "enter_time": "21:00:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "TA",
            "vt_symbol": "TA.CZCE"
        },
        "23:00:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "TA",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "非交易"
            },
            "trading_segment_sn": 15,
            "enter_time": "23:00:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "TA",
            "vt_symbol": "TA.CZCE"
        },
        "current": "23:00:00"
    },
    "OI.CZCE": {
        "19:44:24": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "OI",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "非交易"
            },
            "trading_segment_sn": 4,
            "enter_time": "19:44:24",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "OI",
            "vt_symbol": "OI.CZCE"
        },
        "20:04:29": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "OI",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "非交易"
            },
            "trading_segment_sn": 4,
            "enter_time": "20:04:29",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "OI",
            "vt_symbol": "OI.CZCE"
        },
        "20:55:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "OI",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "集合竞价报单"
            },
            "trading_segment_sn": 7,
            "enter_time": "20:55:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "OI",
            "vt_symbol": "OI.CZCE"
        },
        "20:59:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "OI",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "集合竞价撮合"
            },
            "trading_segment_sn": 9,
            "enter_time": "20:59:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "OI",
            "vt_symbol": "OI.CZCE"
        },
        "21:00:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "OI",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "连续交易"
            },
            "trading_segment_sn": 13,
            "enter_time": "21:00:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "OI",
            "vt_symbol": "OI.CZCE"
        },
        "23:00:00": {
            "__class__": "StatusData",
            "gateway_name": "CTP",
            "symbol": "OI",
            "exchange": {
                "__class__": "Exchange",
                "_value_": "CZCE"
            },
            "settlement_group_id": "00000001",
            "instrument_status": {
                "__class__": "InstrumentStatus",
                "_value_": "非交易"
            },
            "trading_segment_sn": 15,
            "enter_time": "23:00:00",
            "enter_reason": {
                "__class__": "StatusEnterReason",
                "_value_": "自动切换"
            },
            "exchange_inst_id": "OI",
            "vt_symbol": "OI.CZCE"
        },
        "current": "23:00:00"
    },

    ... ... 内容太多,略去

}

5. 交易状态信息管理器的使用

未完待续 ... ...

Administrator
avatar
加入于:
帖子: 4500
声望: 320

感谢分享!给你加个精华

Member
avatar
加入于:
帖子: 13
声望: 0

大佬,StatusEnterReason这个数据类型如何定义的,找遍全网,都没有找到对应的定义,望解答啊,感谢!

Member
avatar
加入于:
帖子: 26
声望: 0

vnpytrader wrote:

大佬,StatusEnterReason这个数据类型如何定义的,找遍全网,都没有找到对应的定义,望解答啊,感谢!

在ThostFtdcUserApiDataType.h中

/////////////////////////////////////////////////////////////////////////
///TFtdcInstStatusEnterReasonType是一个品种进入交易状态原因类型
/////////////////////////////////////////////////////////////////////////
///自动切换
#define THOST_FTDC_IER_Automatic '1'
///手动切换
#define THOST_FTDC_IER_Manual '2'
///熔断
#define THOST_FTDC_IER_Fuse '3'

typedef char TThostFtdcInstStatusEnterReasonType;
Member
avatar
加入于:
帖子: 419
声望: 170

vnpytrader wrote:

大佬,StatusEnterReason这个数据类型如何定义的,找遍全网,都没有找到对应的定义,望解答啊,感谢!

class StatusEnterReason(Enum):
    """
    品种进入交易状态原因类型
    """
    AUTOMATIC = "自动切换"
    MANUAL = "手动切换"
    FUSE = "熔断"
Member
avatar
加入于:
帖子: 26
声望: 0

TradeStatusManager的定义是放在vnpy/trader/utility.py中的吗

Member
avatar
加入于:
帖子: 419
声望: 170

jingsiaosing wrote:

TradeStatusManager的定义是放在vnpy/trader/utility.py中的吗

去我以往的帖子中找,我有分享TradeStatusManager

Member
avatar
加入于:
帖子: 7
声望: 0

def save_status(self,status:StatusData):
"""
保存交易状态映射到交易状态映射
"""
vt_symbol = status.vt_symbol
if vt_symbol not in self.trade_status_map:
self.trade_status_map[vt_symbol] = {}
segment_sn_str = f"{status.trading_segment_sn}".rjust(2,'0')
self.trade_status_map[vt_symbol].update({"current":segment_sn_str})
self.trade_status_map[vt_symbol].update({segment_sn_str:status})
next_segment_sn = self._get_next_segment_sn(status.vt_symbol)
self.trade_status_map[vt_symbol].update({"next":next_segment_sn})
self.change = True
代码有BUG segment_sn_str = f"{status.trading_segment_sn}".rjust(2,'0') 应该改成time_str = status.enter_time 后续的segment_sn_str 也是time_str

Member
avatar
加入于:
帖子: 7
声望: 0

针对换日信息,像AL这种 前一个状态是21:00 后一个状态时 1:00
def get_tick_status(self,tick:TickData):
"""
得到一个tick数据的合约所处交易状态
"""
status:StatusData = None
instrument = left_alphas(tick.symbol)
tick_time = tick.datetime.strftime("%H:%M:%S")
vt_symbol = f"{instrument}.{tick.exchange.value}"
if vt_symbol in self.trade_status_map:
status_dict = self.trade_status_map[vt_symbol]
curr_key = status_dict["current"]
next_key = status_dict["next"]
curr_status:StatusData = status_dict[curr_key]
next_status:StatusData = status_dict[next_key]
if curr_status.enter_time < next_status.enter_time:
if curr_status.enter_time <= tick_time < next_status.enter_time:
status = curr_status
elif next_status.enter_time <= tick_time:
status = next_status
else:
if curr_status.enter_time <= tick_time:
status = curr_status
elif next_status.enter_time > tick_time: #yzj修改
status = curr_status
elif next_status.enter_time <= tick_time:
status = next_status
return status

Member
avatar
加入于:
帖子: 7
声望: 0

get_tick_status也有问题,tick_time = tick.datetime.strftime("%H:%M:%S")直接把毫秒数据忽略了,这怎么能行?我的解决方案是tick_time = str(tick.datetime.time())

Member
avatar
加入于:
帖子: 419
声望: 170

1n wrote:

get_tick_status也有问题,tick_time = tick.datetime.strftime("%H:%M:%S")直接把毫秒数据忽略了,这怎么能行?我的解决方案是tick_time = str(tick.datetime.time())

是的,这样更好。不过tick_time = tick.datetime.strftime("%H:%M:%S")也是没有问题的。

Member
avatar
加入于:
帖子: 7
声望: 0

hxxjava wrote:

1n wrote:

get_tick_status也有问题,tick_time = tick.datetime.strftime("%H:%M:%S")直接把毫秒数据忽略了,这怎么能行?我的解决方案是tick_time = str(tick.datetime.time())

是的,这样更好。不过tick_time = tick.datetime.strftime("%H:%M:%S")也是没有问题的。
针对get_tick_status的问题,我的想法是CZCE会在下午15:00:300,15:00:800也会推过来tick,这个也被归到15:00行情里边去了,不能忽略呀

Member
avatar
加入于:
帖子: 7
声望: 0

hxxjava wrote:

1n wrote:

get_tick_status也有问题,tick_time = tick.datetime.strftime("%H:%M:%S")直接把毫秒数据忽略了,这怎么能行?我的解决方案是tick_time = str(tick.datetime.time())

是的,这样更好。不过tick_time = tick.datetime.strftime("%H:%M:%S")也是没有问题的。
另外您对我前两个回帖怎么看呢

Member
avatar
加入于:
帖子: 11
声望: 0

大佬能解释一下get_tick_status吗?看了几遍都没看懂,主要是不明白里面的current_status和next_status是怎么确定的。多谢啦

Member
avatar
加入于:
帖子: 419
声望: 170

heavywater wrote:

大佬能解释一下get_tick_status吗?看了几遍都没看懂,主要是不明白里面的current_status和next_status是怎么确定的。多谢啦

    def get_tick_status(self,tick:TickData):
        """  
        得到一个tick数据的合约所处交易状态
        """
        status:StatusData = None
        instrument = left_alphas(tick.symbol)                     # 提取tick所属的品种
        tick_time = tick.datetime.strftime("%H:%M:%S")   
        vt_symbol = f"{instrument}.{tick.exchange.value}" # 例如:rb.SHFE,TA.CZCE,因为状态字典是按  "品种.交易所"  为字典键值的
        if vt_symbol in self.trade_status_map:
            status_dict = self.trade_status_map[vt_symbol]
            curr_key = status_dict["current"] # 得到当前交易状态的键值,当前状态是有CTP接口收到状态时更新的,这里只是使用
            next_key = status_dict["next"]    # 得到下一个交易状态的键值,当前状态是有CTP接口收到状态时更新的,这里只是使用,
                                                               # 使用一个完整交易日后,它就是会肯定指向一个有意义的值了
            curr_status:StatusData = status_dict[curr_key]  # 得到当前交易状态
            next_status:StatusData = status_dict[next_key] # 得到下一个交易状态

            if curr_status.enter_time < next_status.enter_time:
                # 交易时间段不跨日
                if curr_status.enter_time <= tick_time < next_status.enter_time:
                    status = curr_status
                elif next_status.enter_time <= tick_time:
                    # 超过了当前时间段和下一时间段的开始时间,并且在下一个交易时间段开始时间之后,认为是找到了
                    # 正确的前提条件是,current和next状态的更是是正常的。 
                    status = next_status
            else:
                # 交易时间段跨日
                if curr_status.enter_time <= tick_time:
                    status = curr_status
                elif next_status.enter_time <= tick_time:
                    status = next_status
        return status
Member
avatar
加入于:
帖子: 7
声望: 0

def save_status(self,status:StatusData):
"""
保存交易状态映射到交易状态映射
"""
vt_symbol = status.vt_symbol
if vt_symbol not in self.trade_status_map:
self.trade_status_map[vt_symbol] = {}
segment_sn_str = f"{status.trading_segment_sn}".rjust(2,'0')
self.trade_status_map[vt_symbol].update({"current":segment_sn_str})
self.trade_status_map[vt_symbol].update({segment_sn_str:status})
next_segment_sn = self._get_next_segment_sn(status.vt_symbol)
self.trade_status_map[vt_symbol].update({"next":next_segment_sn})
self.change = True
代码有BUG segment_sn_str = f"{status.trading_segment_sn}".rjust(2,'0') 应该改成time_str = status.enter_time 后续的segment_sn_str 也是time_str

这样修改才能和您的demo一样,难道不是吗

Member
avatar
加入于:
帖子: 7
声望: 0

1n wrote:

针对换日信息,像AL这种 前一个状态是21:00 后一个状态时 1:00
def get_tick_status(self,tick:TickData):
"""
得到一个tick数据的合约所处交易状态
"""
status:StatusData = None
instrument = left_alphas(tick.symbol)
tick_time = tick.datetime.strftime("%H:%M:%S")
vt_symbol = f"{instrument}.{tick.exchange.value}"
if vt_symbol in self.trade_status_map:
status_dict = self.trade_status_map[vt_symbol]
curr_key = status_dict["current"]
next_key = status_dict["next"]
curr_status:StatusData = status_dict[curr_key]
next_status:StatusData = status_dict[next_key]
if curr_status.enter_time < next_status.enter_time:
if curr_status.enter_time <= tick_time < next_status.enter_time:
status = curr_status
elif next_status.enter_time <= tick_time:
status = next_status
else:
if curr_status.enter_time <= tick_time:
status = curr_status
elif next_status.enter_time > tick_time: #yzj修改
status = curr_status
elif next_status.enter_time <= tick_time:
status = next_status
return status

这个问题也需要解决啊,针对那些夜盘跨日的品种,您觉得呢

Member
avatar
加入于:
帖子: 2
声望: 0

看了一下,有没有可能做成时刻刷新交易所推送过来的交易状态?不用存字典,直接提取当前时点的交易状态就可以了

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】