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

感谢大佬分享,关于engine中的cancel_all_condition_orders方法

def cancel_all_condition_orders(self,strategy_name:str):
        """  """
        for order in self.condition_orders.values():
            if order.strategy_name == strategy_name and order.status == CondOrderStatus.WAITING:
                order.status = CondOrderStatus.CANCELLED

                self.call_strategy_func(strategy,strategy.on_condition_order)
                self.event_engine.put(Event(EVENT_CONDITION_ORDER,order))

        return True

其中有策略中on_condition_order的回调,并且未传入参数
正好最近刚应用了您编写的TickFilter(帖子:https://www.vnpy.com/forum/topic/30601-che-di-jie-jue-tickshu-ju-de-guo-lu-wen-ti?page=1)
其中也涉及到该部分的代码,是没有该动作的(self.call_strategy_func(strategy,strategy.on_condition_order)),应该是不需要的吧?

hxxjava wrote:

c787297017 wrote:

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

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

我目前的实盘很不幸还是郑商所没有毫秒数据,simnow前两天恢复之后,我连接simnow的确可以在郑商所合约上得到毫秒标识,然后我就拿对比运行结果去问了国金期货的技术,同样是ctp柜台,为啥simnow有毫秒标识,然后他们给我的回复是“经过咨询上期技术,simnow自己处理过,所以是有的”

目前我只能在TickFilter针对郑商所修改为tick.datetime >= oldtick.datetime,等于的情况也认为是有效tick

另外和您同步一个信息,10:15:00还是15:00:00之后推过来的tick我同样也咨询了国金期货的技术,他们帮忙问了快期那边对于这种非交易时间有效tick的处理方式,回复如下,总结下就是要么抛弃要么强行加回上一分钟

description

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

description

description

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

MTF wrote:

因为速度更快,延时更低
多谢回复,另外米矿的实时分钟数据是不是存在盘中不太准确的问题,好像盘中和盘后下载的有时会有一些差别

vnpy在cta策略实盘时为什么不直接使用米矿的实时分钟数据,而是将交易所返回的tick数据合成分钟?

郭易燔 wrote:

感觉是14:47:00这根甲醇出了问题,14:46:59.035498和14:47:00的时间不对,上一根甲醇也出了这个问题,秒数不对。

针对Normtick的那个甲醇信息,14:46:59.035498是我这条日志的打印时间,14:47:00+08:00是这条tick数据所携带的datetime,那请问为何会导致这种情况呢,如果是因为我的服务器时间和交易所未校准,也算是正常吧?

根本问题不是多品种下tick的datetime在两分钟之间会反复横跳吗?单品种肯定不存在该问题,因为是严格时间序列的

可能存在问题的代码块如下

        if self.last_dt and self.last_dt.minute != tick.datetime.minute:
            for bar in self.bars.values():
                bar.datetime = bar.datetime.replace(second=0, microsecond=0)

            self.on_bars(self.bars)
            self.bars = {}

        bar = self.bars.get(tick.vt_symbol, None)
        if not bar:
            bar = BarData(
                symbol=tick.symbol,
                exchange=tick.exchange,
                interval=Interval.MINUTE,
                datetime=tick.datetime,
                gateway_name=tick.gateway_name,
                open_price=tick.last_price,
                high_price=tick.last_price,
                low_price=tick.last_price,
                close_price=tick.last_price,
                open_interest=tick.open_interest
            )
            self.bars[bar.vt_symbol] = bar
        else:
            bar.high_price = max(bar.high_price, tick.last_price)
            bar.low_price = min(bar.low_price, tick.last_price)
            bar.close_price = tick.last_price
            bar.open_interest = tick.open_interest
            bar.datetime = tick.datetime

        last_tick = self.last_ticks.get(tick.vt_symbol, None)
        if last_tick:
            bar.volume += max(tick.volume - last_tick.volume, 0)
            bar.turnover += max(tick.turnover - last_tick.turnover, 0)

        self.last_ticks[tick.vt_symbol] = tick
        self.last_dt = tick.datetime

其中的基本逻辑为当tick的datetime标识中的minute改变时,就将已经缓存好的self.bars推出(不包含当前tick),并将self.bars清空,当前tick进入self.bars。
在这种逻辑下导致了如下问题,以下截图为实盘打印,使用品种SA209.CZCE、FG209.CZCE、MA209.CZCE

description

截图中开头为@NormTick的是在on_tick首行进行打印,开头为@minbar是在on_bars首行进行打印,可梳理出运行逻辑如下:

  1. 14:47:00的甲醇tick进入到on_tick之后被PortfolioBarGenerator.update_tick认为满足分钟已发生切换的条件(self.last_dt.minute != tick.datetime.minute,46变为47), 所以触发strategy.on_bars将缓存好所有品种的bars全部推出,所以看到了三条开头为@minbar的输出,此时PortfolioBarGenerator缓存的bars被清空并且放入了这条14:47:00的甲醇tick
  2. 下一时刻,14:46:59的纯碱tick进入到on_tick之后,update_tick再次认为满足分钟已发生切换的条件(self.last_dt.minute != tick.datetime.minute,47变为46),所以再次触发strategy.on_bars将缓存的bars(有且仅有14:47:00的甲醇tick)推出,所以看到了1条开头为@minbar的输出
  3. 下一时刻,14:47:00的玻璃tick进入on_tick,update_tick再次认为满足分钟已发生切换的条件(self.last_dt.minute != tick.datetime.minute,46变为47),所以再次触发strategy.on_bars将缓存的bars(有且仅有14:56:59的纯碱tick)推出,所以看到了1条开头为@minbar的输出

在论坛中找到解决类似问题的帖子:https://www.vnpy.com/forum/topic/7028-portfolio-strategy-zhong-on-tick-han-shu-zhong-geng-xin-bars-de-luo-ji-shi-cuo-wu-de-xiu-zheng-ban-de-luo-ji-ru-xia
基本思想为将 self.last_dt.minute != tick.datetime.minute 修改为 self.last_dt.minute < tick.datetime.minute,这样的确可以避免on_bars反复运行,但是在我的例子中会将14:46:59的纯碱tick包裹在14:47的min bar中,虽说数据仍然不准确,但好在没有很离谱(一个min bar实则只包含了一个tick)
目前正在思考更完善的解决方案

还有确定一下,不是说要开五档行情才有毫秒字段吧?普通的二档就可以吧?因为刚刚国金经纪商去问了郑商所是这么答复的

“您好,刚刚问了郑州所负责行情老师,郑州所技术中心组播行情,五档的精度高,有毫秒级的字段,需要收费24w一年;郑商所为每家期货公司转发的席位行情目前精度只到秒级别,精度没有这么高,没有毫秒级别的字段。”

我是怀疑他们没搞清楚。。。

hxxjava wrote:

答复:

问题分析

  1. 目前simnow调试,停止服务。我猜你现在使用的实盘账户在运作策略。所以你才可以继续使用CTP网关行情的。
  2. 你目前应该是连接到你的期货经纪商给提供的连接地址和端口号上的,也就是说,你可能是从你的期货经纪商的行情服务器获取的行情转发。
  3. 行情数据错误可能是两个方面造成的:①期货经纪商的行情转发错误;②本地行情接收成为

解决思路:

  1. 检查期货经纪商的行情使用的CTP版本,看看他们是否对CZCE的品种行情转发的毫秒数是错误的。(需要和你的期货经纪商沟通)
  2. 更换本地的CTP网关版本,最简单的时恢复到vnpy 3.0,订阅一个CZCE的合约,然后在onRtnDepthMarketData()中直接答应data看看。

这样就可以定位到问题了。

还有请问下哪个ctp版本可以获取到郑商所的毫秒数据

经过和经纪商联系,经纪商的落地数据中郑商所就没有tick数据的毫秒标识,所以应该是经纪商的转发问题了,可能他们使用的ctp版本较老吧,只能再去找一个经纪商开户了,各位大佬有没有推荐的经纪商,只要能满足如下就好

  1. 手续费可以调成加1分
  2. 保证金比率可调成跟随交易所
  3. 郑商所tick数据有毫秒标识

我之前使用的国金期货只满足1和2.

hxxjava wrote:

答复:

问题分析

  1. 目前simnow调试,停止服务。我猜你现在使用的实盘账户在运作策略。所以你才可以继续使用CTP网关行情的。
  2. 你目前应该是连接到你的期货经纪商给提供的连接地址和端口号上的,也就是说,你可能是从你的期货经纪商的行情服务器获取的行情转发。
  3. 行情数据错误可能是两个方面造成的:①期货经纪商的行情转发错误;②本地行情接收成为

解决思路:

  1. 检查期货经纪商的行情使用的CTP版本,看看他们是否对CZCE的品种行情转发的毫秒数是错误的。(需要和你的期货经纪商沟通)
  2. 更换本地的CTP网关版本,最简单的时恢复到vnpy 3.0,订阅一个CZCE的合约,然后在onRtnDepthMarketData()中直接答应data看看。

这样就可以定位到问题了。

多谢hxx大佬,我的情况完全符合您问题分析中的1和2,目前我正在联系经纪商确认以及升级ctp网关再次进行测试,感谢耐心回复

MTF wrote:

郑商所合约,行情推送里时间戳不带毫秒信息的,要在业务层自己处理下
大佬可以详细说下吗?业务层是指?多谢了

感谢回复,我仔细检查了我使用的gateway,确定是ctp_gateway,并且我是在实盘时进行的测试,为了进一步定位问题,我将onRtnDepthMarketData中收到的data进行了打印(使用合约:SA209.CZCE)

description

输出内容如下

description

可以看到不知为何UpdateMillisec全部为0,所以才导致了同一秒内的tick数据datetime完全一致的情况,后面推进来的那条就会被当做特殊tick过滤掉。

不知道是否和我使用的vnpy_ctp版本有关系,我目前的版本号为6.5.1.7,hxxjava大神的应该是6.5.1.8以上,目前准备升级再次进行测试,感谢大佬帮我定位问题

在将大佬设计的过滤器布置到实盘环境后,测试发现郑商所品种的tick_data中的datetime未精确到毫秒,所以每秒的两次tick数据datetime标识完全一致,后面的一次会被过滤器认为是无效tick,并且打印了【特别tick =】,上期所和大商所的品种tick数据datetime是精确到毫秒的,所以不存在该问题,过滤器正常运行,请问大佬是怎么处理郑商所这个问题的?

hxxjava wrote:

c787297017 wrote:

请问大佬使用vnpy可以实现期货集合竞价的前4分钟下单吗?
是不是可以在on_start中加一个阻塞,当确定市场已进入集合竞价(时间判定或者事件触发)时,在此处立即下单。

回复:

  1. vnpy可以实现期货集合竞价期间手动下单
  2. 但是目前vnpy中的用户策略模板还没有提供对合约交易状态的感知功能,因此策略无法知道当前时间是否是集合竞价时段。
  3. 在可以收到合约交易状态前提下,在CtaTemplate中增加:合竞价报单、集合竞价撮合和集合竞价结束【连续竞价状态】等状态推送接口,以便推动策略进行委托交易。
  4. 如果策略足够复杂,你还可以考虑集合竞价期间的撤单操作。
  5. 当然4和5两条都需要对目前vnpy的gateway(如CTP网关)、应用引擎(如CtaEngine)和策略模板(如CtaTemplate)进行扩展才能够实现的。

多谢hxx大佬点拨,我准备模仿您实现过的on_auction_tick去尝试下”在CtaTemplate中增加:合竞价报单、集合竞价撮合和集合竞价结束【连续竞价状态】等状态推送接口,以便推动策略进行委托交易“,感觉这样才是正规的解决办法,再次感谢

请问大佬使用vnpy可以实现期货集合竞价的前4分钟下单吗?
是不是可以在on_start中加一个阻塞,当确定市场已进入集合竞价(时间判定或者事件触发)时,在此处立即下单。

多谢大佬解惑

进一步检查发现TtsTdApi.onRtnInstrumentStatus 从未被触发

感谢hxx分享,我模仿您的方法对vnpy_portfoliostrategy和vnpy_tts(gateway)进行了修改,运行起来发现所有的tick都被过滤掉了,检查发现是TickFilter.process_status_event从未被触发过,因此TickFilter.statuses始终为空,这样的话说明EVENT_STATUS从未发生?请问有什么办法能排查某个事件从未发生的原因?

© 2015-2022 微信 18391752892
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

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