VeighNa量化社区
你的开源社区量化交易平台
hxxjava's Avatar
Member
离线
419 帖子
声望: 155

守望长城2020-6-11-艾瑞巴蒂 wrote:

测试成功.
反馈一个bug, 在图表最左边(最初始的部分K线图,那个时候macd值还未产生)用鼠标右键缩放的时候,会报错,报错信息如下:
Traceback (most recent call last):
File "C:\Users\lx\Desktop\vnpy2022-9-20-在线可运行K线版 - 副本\vnpy\chart\widget.py", line 217, in _update_y_range
y_range = item.get_y_range(min_ix, max_ix)
File "C:\Users\lx\Desktop\vnpy2022-9-20-在线可运行K线版 - 副本\vnpy\usertools\kx_chart.py", line 428, in get_y_range
max_price = np.nanmax(ndarray)
File "<__array_function__ internals>", line 6, in nanmax
File "C:\vnstudio\lib\site-packages\numpy\lib\nanfunctions.py", line 434, in nanmax
res = np.fmax.reduce(a, axis=axis, out=out, **kwargs)
ValueError: zero-size array to reduction operation fmax which has no identity

答复:
既然发现了问题,动动您发财的手帮大家改一下吧 。。。 :)

守望长城2020-6-11-艾瑞巴蒂 wrote:

还有一个问题请大神解答下, 我自己编写了一个chartItem, 用于显示数据点的, 用的是drawPoint绘制方式, 随着不同数据范围下, drawPoint被拉得老长了, 变成了一个长的柱子, 有没有办法就让它一直显示为一个方形的点, 不要自适应拉长

答复:
这个是不可能的,因为你画的矩形的宽度与高度的单位是不同的,宽度单位是时间(多少个K线),高度是价格,怎么能够一样呢?
如果你硬是想显示为正方形,建议使用PyQtGraph的ScutterItem,可以参考回测界面里的K线图表显示开仓和平仓成交单的方法来显示,那是用上下三角形来表达的,不会因为K线图标的缩放而改变大小。

文韬武略 wrote:

配置的是5

答复:

1、BarGenerator的update_bar_minute_window()有bug

文件D:\ProgramFiles\vnstudio\lib\site-packages\vnpy\trader\utility.py"中BarGenerator的update_bar_minute_window(bar)有bug,这样修改:

    def update_bar_minute_window(self, bar: BarData) -> None:
        """"""
        # If not inited, create window bar object
        if not self.window_bar:
            dt = bar.datetime.replace(second=0, microsecond=0)
            self.window_bar = BarData(
                symbol=bar.symbol,
                exchange=bar.exchange,
                datetime=dt,
                gateway_name=bar.gateway_name,
                open_price=bar.open_price,
                high_price=bar.high_price,
                low_price=bar.low_price
            )
        # Otherwise, update high/low price into window bar
        else:
            self.window_bar.high_price = max(
                self.window_bar.high_price,
                bar.high_price
            )
            self.window_bar.low_price = min(
                self.window_bar.low_price,
                bar.low_price
            )

        # Update close price/volume/turnover into window bar
        self.window_bar.close_price = bar.close_price
        self.window_bar.volume += bar.volume
        self.window_bar.turnover += bar.turnover
        self.window_bar.open_interest = bar.open_interest

        # Check if window bar completed
        if self.on_window_bar and self.window:  # hxxjava add
            if not (bar.datetime.minute + 1) % self.window:
                self.on_window_bar(self.window_bar)
                self.window_bar = None

2、这样修改策略来验证一下是否正确

from vnpy_ctastrategy import (
    CtaTemplate,
    StopOrder,
    TickData,
    BarData,
    TradeData,
    OrderData,
    BarGenerator,
    ArrayManager,
)

# from my_strategies_tool import NewBarGennerator
from vnpy.trader.constant import Interval

class DemoStrategy(CtaTemplate):
    """演示用的简单双均线"""

    # 策略作者
    author = "Smart Trader"

    # 定义参数
    fast_window = 10
    slow_window = 20
    fast_window1 = 10
    slow_window1 = 20
    k=5

    # 定义变量
    fast_ma0 = 0.0
    fast_ma1 = 0.0
    slow_ma0 = 0.0
    slow_ma1 = 0.0

    fast_ma01 = 0.0
    fast_ma11 = 0.0
    slow_ma01 = 0.0
    slow_ma11 = 0.0

    cross_over2=True
    cross_below2=True


    # 添加参数和变量名到对应的列表
    parameters = ["fast_window", "slow_window","k","fast_window", "slow_window"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1","fast_ma01", "fast_ma11", "slow_ma01", "slow_ma11","cross_over2","cross_below2"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        # K线合成器:从Tick合成分钟K线用xzsde
        self.bg = BarGenerator(self.on_bar)
        self.bg15=BarGenerator(self.on_bar,  window=self.k, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE)

        # 时间序列容器:计算技术指标用
        self.am = ArrayManager()
        self.am2=ArrayManager()

        self.bars_num = 0   # hxxjava add
        self.bars15_num = 0  # hxxjava add

    def on_init(self):
        """
        当策略被初始化时调用该函数。
        """
        # 输出个日志信息,下同
        self.write_log("策略初始化")

        # 加载10天的历史数据用于初始化回放
        self.load_bar(10)

    def on_start(self):
        """
        当策略被启动时调用该函数。
        """
        self.write_log("策略启动")

        # 通知图形界面更新(策略最新状态)
        # 不调用该函数则界面不会变化
        self.put_event()

    def on_stop(self):
        """
        当策略被停止时调用该函数。
        """
        self.write_log("策略停止")

        self.put_event()

    def on_tick(self, tick: TickData):
        """
        通过该函数收到Tick推送。
        """
        self.bg.update_tick(tick)
        # self.bg15.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        通过该函数收到新的1分钟K线推送。
        """
        self.bars_num += 1  # hxxjava add

        self.bg.update_bar(bar)
        self.bg15.update_bar(bar)

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        fast_ma1 = am.sma(self.fast_window1, array=True)
        self.fast_ma01 = fast_ma1[-1]     # T时刻数值
        self.fast_ma11 = fast_ma1[-2]     # T-1时刻数值

        # 计算慢速均线
        slow_ma1 = am.sma(self.slow_window1, array=True)
        self.slow_ma01 = slow_ma1[-1]
        self.slow_ma11 = slow_ma1[-2]

        # 判断是否金叉
        self.cross_over2 = (self.fast_ma01 > self.slow_ma01 and
                    self.fast_ma11 < self.slow_ma11)

        # 判断是否死叉
        self.cross_below2 = (self.fast_ma01 < self.slow_ma01 and
                    self.fast_ma11 > self.slow_ma11)


    def on_5min_bar(self, bar: BarData):

        self.bars15_num += 1   # hxxjava add
        print(f"1分钟bar到数量={self.bars_num} k分钟bar到数量={self.bars15_num}")   # hxxjava add

        am2=self.am2

        # 更新K线到时间序列容器中

        am2.update_bar(bar)

        # 若缓存的K线数量尚不够计算技术指标,则直接返回

        if not am2.inited:
            return

        # 计算快速均线
        fast_ma = am2.sma(self.fast_window, array=True)
        self.fast_ma0 = fast_ma[-1]     # T时刻数值
        self.fast_ma1 = fast_ma[-2]     # T-1时刻数值

        # 计算慢速均线
        slow_ma = am2.sma(self.slow_window, array=True)
        self.slow_ma0 = slow_ma[-1]
        self.slow_ma1 = slow_ma[-2]

        # 判断是否金叉
        cross_over = (self.fast_ma0 > self.slow_ma0 and
                    self.fast_ma1 < self.slow_ma1)

        # 判断是否死叉
        cross_below = (self.fast_ma0 < self.slow_ma0 and
                    self.fast_ma1 > self.slow_ma1)

        # 如果发生了金叉
        if cross_over and self.cross_over2:
            # 为了保证成交,在K线收盘价上加5发出限价单
            price = bar.close_price + 5

            # 当前无仓位,则直接开多
            if self.pos == 0:
                self.buy(price, 1)
            # 当前持有空头仓位,则先平空,再开多
            elif self.pos < 0:
                self.cover(price, 1)
                self.buy(price, 1)

        # 如果发生了死叉
        elif cross_below and self.cross_below2:
            price = bar.close_price - 5

            # 当前无仓位,则直接开空
            if self.pos == 0:
                self.short(price, 1)
            # 当前持有空头仓位,则先平多,再开空
            elif self.pos > 0:
                self.sell(price, 1)
                self.short(price, 1)

        self.put_event()

    def on_order(self, order: OrderData):
        """
        通过该函数收到委托状态更新推送。
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        通过该函数收到成交推送。
        """
        # 成交后策略逻辑仓位发生变化,需要通知界面更新。
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        通过该函数收到本地停止单推送。
        """
        pass

3、这是测试结果

1分钟bar的数量=10 k分钟bar的数量=2
2022-08-27 08:56:53 1分钟bar的数量=15 k分钟bar的数量=3
1分钟bar的数量=20 k分钟bar的数量=4
1分钟bar的数量=25 k分钟bar的数量=5
1分钟bar的数量=30 k分钟bar的数量=6
1分钟bar的数量=35 k分钟bar的数量=7
1分钟bar的数量=40 k分钟bar的数量=8
1分钟bar的数量=45 k分钟bar的数量=9
1分钟bar的数量=50 k分钟bar的数量=10
2022-08-27 08:56:53 1分钟bar的数量=55 k分钟bar的数量=11
1分钟bar的数量=60 k分钟bar的数量=12
1分钟bar的数量=65 k分钟bar的数量=13
1分钟bar的数量=70 k分钟bar的数量=14
1分钟bar的数量=75 k分钟bar的数量=15
1分钟bar的数量=80 k分钟bar的数量=16
1分钟bar的数量=85 k分钟bar的数量=17
1分钟bar的数量=90 k分钟bar的数量=18
1分钟bar的数量=95 k分钟bar的数量=19
1分钟bar的数量=100 k分钟bar的数量=20
1分钟bar的数量=105 k分钟bar的数量=21
1分钟bar的数量=110 k分钟bar的数量=22
1分钟bar的数量=115 k分钟bar的数量=23
1分钟bar的数量=120 k分钟bar的数量=24
1分钟bar的数量=125 k分钟bar的数量=25
1分钟bar的数量=130 k分钟bar的数量=26
1分钟bar的数量=135 k分钟bar的数量=27
1分钟bar的数量=140 k分钟bar的数量=28
1分钟bar的数量=145 k分钟bar的数量=29
1分钟bar的数量=150 k分钟bar的数量=30
1分钟bar的数量=155 k分钟bar的数量=31
1分钟bar的数量=160 k分钟bar的数量=32
1分钟bar的数量=165 k分钟bar的数量=33
1分钟bar的数量=170 k分钟bar的数量=34
 。。。 。。。

self.k 配置的时候是多少,不能够是0
错误已经提示了:
···
File "C:\veighna_studio\lib\site-packages\vnpy\trader\utility.py", line 302, in update_bar_minute_window
if not (bar.datetime.minute + 1) % self.window:
ZeroDivisionError: integer division or modulo by zero
···

逆火 wrote:

在add_gateway()中的这个语句跟哪里有联系没看出来,self.tick_filters 这个字典在哪里用到了??
description

  1. self.tick_filters是main_engine的成员,为main_engine中的增加的每个gateway都配备一个TickFilter,目的是为了防止重复创建,如果创建过就不再创建了。
  2. 创建成功的TickFilter自己会接收该gateway的交易状态信息和原始tick
  3. TickFilter接收到gateway的原始tick时,会根据tick对应的交易状态信息进行有效性判断,有效则转发到vnpy系统中,无效的则抛弃。

答复:

1 问题代码修改:

def on_tick(self, tick: TickData):
    """
    通过该函数收到Tick推送。
    """
    self.bg.update_tick(tick)
    # self.bg15.update_tick(tick) # —— 先注释掉这一句

self.bg和self.bg15共用了同一个on_bar()函数,在tick到来的时候on_tick()只要调用周期较小self.bg的update_tick就可以生成1分钟bar了。无需两个都更新tick来得到两个相同的1分钟bar,然后又两次调用on_bar()函数,因为self.bg生成1分钟bar时会调用on_bar()函数,self.bg15也会生成一个相同的1分钟bar,它也会调用on_bar()函数,这不符合你的设计本意,对吧?
先这么改下看看。

感觉你的问题与TickFilter的过滤无关,因为:

  1. y2209-y2211合约是你自己创建的本地价差,它的tick是合成出来的,它只依赖y2209.DCE,y2211.DCE两个合约的tick是否能够被收到
  2. y2209.DCE,y2211.DCE的原始tick是否能够收到,与它们的tick时间戳是否是在它们各自的交易状态是否被正确地收到
  3. 只有ctp网关连接正常,ctp接口连接到的交易所的所有合约的交易状态都会被自动推送给TickFilter
  4. y2209-y2211合约的两个腿y2209.DCE,y2211.DCE会被spread_trading模块分别订阅,它们的tick会首先发送给TickFilter,当它们与当时的交易状态一致时,就会被放行到需要它们的spread_trading模块,之后的过程与vnpy系统以前的出来没有任何差别,最终合成出y2209-y2211合成价差tick。

由此可见:你的问题与TickFilter的过滤无关。

逆火 wrote:

大佬 在用价差策略的时候,状态不对,请教
description

答复:

何以见得就不对呢?请描述错误及现象。

价差交易分两种:

  1. 交易所存在的价差合约,这时候交易价差合约就和CTA策略中的其他一般合约一样交易。TickFilter直接可以过来这种价差合约的tick。
  2. 交易所不存在的价差合约,这时候需要在vnpy的spreadtrading模块中自己创建一个本地价差合约,此时交易价差合约就会被分解为对价差合约的两个或多个腿合约的分别的交易。此时就需要对这些腿都合约进行订阅和过滤。TickFilter在spreadtrading的engine之前起过滤作用的,对spreadtrading合成的价差tick无需任何过滤。

王不同 wrote:

请教,怎么获取一根未完成的k线的指标值

  • 需要在on_tick()中自己对BarGenerator未完成的bar进行特别提取,就是所谓的临时K线。
  • 至于之后指标值的计算和完整K线是一样的,然后和之前历史K线一起参与指标计算。

是的,不需要

逆火 wrote:

交易所推送status的时间是多久一次

答复:

  1. 通常一个品种一个交易日有1个集合竞价时间段,n个连续竞价时间段的话,那么会收到:
    非交易时间状态——1个
    集合竞价开始状态——1个
    集合竞价匹配状态——1个
    第一个连续竞价状态——1个
    第一次休市状态——1个
    第二个连续竞价状态——1个
    第二次休市状态 ——1个
    ...
    第n个连续竞价状态——1个
    交易日收盘状态  ——1个
    所以正常情况下会收到2n+3个交易状态
  2. 如果某个合约盘中因为极端行情导致停盘,延迟一段时间后再次回复交易,则每停盘1次就又会多收到1个停盘交易状态+1个连续交易状态。如果一个交易日如果停盘m次,则整个交易日会收到2n+2m+3个交易状态。
  3. 交易所推送交易状态根据不同品种或合约分别推送的,例如你可能在交易日的晚21:00收到约60多个连续竞价交易状态信息,这其中大部分是品种,也可能还包含一些具体合约的交易状态信息。

逆火 wrote:

请教大佬 tick过滤器的实例化在这里 ,没找到 在哪里调用tick数据的传输路径是什么样的

description

答复

  1. 一个gateway对应一个TickFilter;
  2. 每个gateway实例都包含一个行情MdApi,它的onRtnDeepMarketData()函数都会推送tick数据,调用的是BaseGateway的on_tick()接口;
  3. 本设计对on_tick()的方法进行了改写:
    def on_tick(self, tick: TickData) -> None:
         """
         Tick event push.
         Tick event of a specific vt_symbol is also pushed.
         """
         self.on_event(EVENT_ORIGIN_TICK, tick)  # hxxjava add             
         # if tick.first_time:                     # hxxjava add
         #     return
         # self.on_event(EVENT_TICK, tick)                   
         # self.on_event(EVENT_TICK + tick.vt_symbol, tick)
    这里将EVENT_TICK消息类型替换为新定义的EVENT_ORIGIN_TICK消息。
  4. TickFilter都有注册了EVENT_ORIGIN_TICK消息,并且在其处理函数process_tick_event()中进行原始tick有效性判断和过滤,之后再将有效的tick转发到vnpy系统中供其他应用使用的,下面是TickFilter的tick过滤处理函数,其最后两句与原来的BaseGateway的on_tick()的作用是相同的。

     def process_tick_event(self,event:Event):
         """ 对原始tick进行过滤 """
         tick:TickData = event.data
    
         # 检查tick合约的经验状态是否位有效交易状态
         status:StatusData = self.statuses.get(tick.vt_symbol,None)
         if not status:
             vt_instrument = get_vt_instrument(tick.vt_symbol)
             status = self.statuses.get(vt_instrument,None)
             if not status:
                 # 未收到交易状态,返回
                 return
    
         if status.instrument_status not in VALID_TRADE_STATUSES:
             # 不在有效交易状态,返回
             return
    
         key = (tick.gateway_name,tick.vt_symbol)
         _,oldtick = self.last_ticks.get(key,(None,None))
         valid_tick = False
         if not oldtick:
             # 没有该合约的历史tick
             self.last_ticks[key] = (True,tick)
             valid_tick = True
    
         elif tick.datetime > oldtick.datetime:
             # 
             self.last_ticks[key] = (True,tick)
             valid_tick = True
    
         # else:
         #     print(f"【特别tick = {tick}】")
    
         if valid_tick == True:
             # 如果是有效的tick
             if status.instrument_status != InstrumentStatus.CONTINOUS:
                 # 发送集合竞价tic消息到系统中
                 self.event_engine.put(Event(EVENT_AUCTION_TICK,tick))
                 self.event_engine.put(Event(EVENT_AUCTION_TICK + tick.vt_symbol, tick))  
    
             else:
                 # 发送连续竞价tic消息到系统中
                 self.event_engine.put(Event(EVENT_TICK,tick))
                 self.event_engine.put(Event(EVENT_TICK + tick.vt_symbol, tick))
  5. 一句话:BaseGateway的on_tick()对原始tick进行拦截,转向到TickFilter去进行过滤处理,有效的放行,无效的抛弃。

逆火 wrote:

执行的时候 default_name找不到 请问这个是哪里定义的
description

答复

在vnpy_ctp\gateway\ctp_gateway.py中:

class CtpGateway(BaseGateway):
    """
    vn.py用于对接期货CTP柜台的交易接口。
    """

    default_name: str = "CTP"

    default_setting: Dict[str, str] = {
        "用户名": "",
        "密码": "",
        "经纪商代码": "",
        "交易服务器": "",
        "行情服务器": "",
        "产品名称": "",
        "授权编码": ""
    }

    exchanges: List[str] = list(EXCHANGE_CTP2VT.values())

    def __init__(self, event_engine: EventEngine, gateway_name: str) -> None:
        """构造函数"""
        super().__init__(event_engine, gateway_name)

        self.td_api: "CtpTdApi" = CtpTdApi(self)
        self.md_api: "CtpMdApi" = CtpMdApi(self)

对于10:15:00还是15:00:00之后推过来的tick强行加回上一分钟,倒也是一种处理方法,也可以办到。只是tick的时间戳在休市或收盘之后一分钟后也是存在的,杜绝不完的。而且采用这种方式策略必须考虑处理休市或收盘之后可能发出委托的问题了。
如果生成的K先只是用来显示,不用考虑交易,怎么做都很自由。

c787297017 wrote:

多谢大佬深夜耐心回复,那果断在您的TickFilter的基础上增加时间校验,抛弃掉这些虽然有效但处于交易时间外的tick,以防产生额外的k线

顺便问下:你之前遇到的PTA合约在一秒内收到的tick时间戳均没有秒以下毫秒数的情况,现在还是这样吗?

c787297017 wrote:

description

description

将大神的tick_filter应用到实盘后发现存在如上datetime为10:15:00和15:00:00的tick,首先不知道他们还属于有效tick吗?它们的状态是属于VALID_TRADE_STATUSES的,否则会被tick_filter过滤掉,那可能是什么原因导致的这种情况呢?是否考虑增加时间过滤?

答复:

以国内期货为例:

  1. 通常一个交易日的是由非交易时间段、集合竞价时间段、连续竞价时间段构成,连续竞价时间段之间会有休市时间
  2. 用户只能在VALID_TRADE_STATUSES(集合竞价状态、连续竞价状态)下才能够提交委托
  3. 被接受的委托,经过交易所撮合成功之后才会成交,盘口的价格会因此而发生变化。
  4. 变化的tick行情会被推送到所有用户。
  5. 多数合约会在收市时准时停止tick推送,而然也有部分tick数据延迟数秒乃至20多分钟,且这种延迟没有太多规律可循。有时收市后20多分钟了然后会有因为结算问题而更新的tick推送。

上述过程的第3步是需要时间的,有时也会因为一些结算及审查机制,使得用户在已经收到休市和收盘状态,仍然能够收到tick数据推送。
就是说——用户委托必须是在有效交易时间段内,但行情推送可能会超出连续交易时间段的结束时间!

tickfilter是抛弃这些tick,为什么这么设计?

  1. 如果不抛弃这些tick,你要如何使用这些tick呢?难道你要在15:00之后再生成一个5分钟K线吗?
  2. 假如你使用这些tick来驱动你的策略,同时还生成了交易信号,你的策略是执行委托还是不产生委托呢?
  3. 无论在10:15:00还是15:00:00之后,只要你的策略发生了委托,交易接口一定会返回拒单的,此时你的策略对此又该如何处理呢?
  4. 你可以看看其他世面上的成熟软件,你能够找到历史K线起始时间在休市后吗?答案是:找不到。是它们不会收到这种tick吗?不是,它们一样会收到,只是这些tick也是被丢弃处理了。

综上所述:抛弃这些tick是比较好的做法。

逆火 wrote:

实盘中双边仓位一直在扩大,不明白,,,如果持仓中为多2手 空2手,然后新发指令为多开2手,我的持仓会变成多4手 空2手,为什么持仓不是多2手 空0手

这是期货基本常识,准确的说法:

  1. 因为开始为多开2手 空开2手,然后新发指令为多开2手,因为你从来没有平过仓,当然持仓会变成多4手 空2手;
  2. 如果开始为多开2手 空开2手,然后新发指令为多平2手,持仓会变成多2手 空0手;
  3. 如果开始为多开2手 空开2手,然后新发指令为空平2手,持仓会变成多0手 空2手。

要保证交易信号生成机制与交易执行机制的一致性:

  • 用5分钟K线收盘数据生成的信号,却用后面收到的tick去执行,当然会出现重复单。就算用其他的什么标志去做条件过滤也是防不胜防。
  • 用5分钟K线收盘数据生成的信号,用该K线的收盘价去执行,就不会出现重复单。如果仍然有重复单,就过滤你的交易信号,与执行无关。

zlengine wrote:

目前vnpy返回的持仓数据字段只有一个持仓均价,就是昨日的结算价。
有什么办法获取开仓均价呢?

挨个交易日去查询交易记录不太有效率啊,难道一个仓位如果我已经持仓3个月,要查到3月前的成交记录才能计算获得开仓均价?CTP返回的持仓数据中是否包含这一数据呢?

有没有大神了解的,谢谢

要实现你的需求,需要自己保存交易后返回的TradeData,按照reference进行统计,按照逐笔方式统计出多、空两个方向上的持仓均价。

dmz wrote:

另外想请教大神一个问题

def process_tick_event(self,event:Event):
    """ 对原始tick进行过滤 """
    tick:TickData = event.data

    # 检查tick合约的经验状态是否位有效交易状态
    status:StatusData = self.statuses.get(tick.vt_symbol,None)
    if not status:
        vt_instrument = get_vt_instrument(tick.vt_symbol)
        status = self.statuses.get(vt_instrument,None)
        if not status:
            # 未收到交易状态,返回
            return

这段代码我看了很久,如果我的理解没错的话, 判断一个tick是否有效,是用的上一个该品种的tick的 StatusData, 为什么要这样做呢?为什么不能直接用这个tick的状态信息呢?

答复:

  • 因为历史收到的StatusData可能是一个品种 的,也可能是单独一个合约的。如:一个RB.SHFE当前是连续交易时段,但是RB2210.SHFE可能因为激烈的交易行情,超过当时最大涨跌幅度,停盘了,但是该品种的其他合约却正常交易,此时交易所会单独发送RB2210.SHFE停盘3分钟的StatusData,之后再发送RB2210.SHFE恢复连续交易状态的StatusData。
  • 过滤tick数据的时候,第一步就需要看该合约或品种是否有交易状态数据,如果没有就无法判断,只能直接放弃该tick啦。
© 2015-2022 微信 18391752892
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

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