掘金社区

关于回调次序的再讨论Pinned highlighted

GloryYan 发表在问题反馈 2019-02-18 09:58:06

问题反馈
135
5
0

终端版本:3.x
编程语言:C#

@喜羊羊

1. 建议新增一个申请订单ID的函数

去年我曾发帖反映回测和实盘两种模式在下单后回调次序不一致的问题, 后来 @喜羊羊说明了要解决这一问题的困难之处, 问题也就搁置下来了。
这段时间我对这一问题又进行了认真思考,发现这一问题其实有另一个思路可以解决。
事实上,回调次序不一致只是表面上的问题,而根本的问题是前端程序何时能得到一个能唯一表示订单的ID(我认为其实就是现在的"clOrdId").
由于两种模式次序不同,造成有时是下单返回最先得到,有时是第一次订单变化时最先得到。这给前端程序的编写造成了很大的麻烦,并且很容易导致回调订单和实际下单对应不起来。

因此我建议:

	增加一个函数,专门用于申请订单ID(clOrdId),下单前先调用该函数获得新的clOrdId;
	下单函数(各种Order...函数)增加一个可选参数"string clOrdId = null";
	为了保持兼容性,当该参数为null时,后台还是和以前一样分配一个新的clOrdId;
	如果该参数不为null,则后台检查该参数的合法性,如合法,则使用该参数作为clOrdId,否则终止下单返回错误码;
	检查该参数的合法性也可以简化处理,只需检查是否为最后颁发的尚未使用的clOrdId即可。

这样,前端程序在下单前就已经有了clOrdId,不管各种回调在什么时间到达,只需识别clOrdId就可区分属于哪个订单,非常清晰。如果解决了先有clOrdId,回调次序不一致的问题可以留待以后慢慢解决。我认为这样做比一次性解决回调次序问题更简单可行。

2. 请补齐回调数据包中的 没有值字段

回测和实盘两种模式下,回调数据包中什么字段有值,什么字段没有值,也是不一致的。这一点我在去年发帖时提到过,但没有详细说明。现在具体列出来:

a.回测模式:

下单返回:	Order.updatedAt 没有值
订单变化事件:	Order.updatedAt 没有值
执行回报事件:	ExecRpt.createdAt 没有值
		ExecRpt.commission 没有值
		ExecRpt.cot 没有值

a.实盘模式:

订单变化事件:	Order.commission 没有值

也许开发人员认为这些没有值的字段本身这个场景下是没有意义的,比如回测模式下订单变化一共就回调一次,有了createdAt就可以了,完全不需要updatedAt。这种想法在功能逻辑上当然是没有问题的,但势必造成两种模型无法统一编程,应当努力避免。

评论: 5
  • 非常感谢您的意见

    2019-02-19 11:27:10
  • 其中有一些没有太明白,现在的下单,不论哪种模式都是会返回cl_ord_id的,实盘立刻返回的订单结构为空,后续随着成交逐步填充,回测也有cl_ord_id,但是内容是一次性填充好的,不知道是否这样理解的

    2019-02-19 11:31:10
  • @喜羊羊

    看来我没有表达得很清楚。的确两种模式都会返回cl_ord_id,但返回的时机不一样。举例来说:
    假设我连续下了2个单,我给它们起名为"订单01"、"订单02"。现在,我已经下完单,剩下的就是等着下单返回以及各种事件,来判断我这些订单完成到哪一步了。
    这时问题就来了,如果是实盘模式,就比较好办。因为我每下一单,下单函数(OderXXX)会在事件到达之前立即返回(我不清楚会不会有例外?),这时我就得到了cl_ord_id。也就是说,我已经知道"订单01"的cl_ord_id是什么,"订单02"的cl_ord_id是什么。当事件到达时,我只需根据回调数据包里的cl_ord_id,可以很容易地判断出这次回调是"订单01"的还是"订单02"的。
    相反,如果是回测模式,就比较麻烦了。我每下一单,下单函数并不立即返回,而是首先触发事件。也就是说,当事件到达时,我还不知道"订单01"、"订单02"的cl_ord_id是什么,当然也就不可能根据回调数据包里的cl_ord_id,来判断出这次回调是"订单01"的还是"订单02"的,而只能用别的替代方法。比如通过下单顺序、证券代码、委托量、下单时间等等因素来判断这次回调到底属于"订单01"的还是"订单02"。
    也许替代方法是可行的,但一定不是"好的"方法,甚至可能是不可靠的方法,是应当避免的。因此我提出了两个建议方案:
    **方案1:修改回测模式的下单回调顺序,使之与实盘模式相同。**这实际上是上次发帖的建议,您已经解释了暂时难于实现。
    **方案2:下单前申请(或称颁发)cl_ord_id,下单时作为参数传给后台。**这就是我这次发帖的建议。这个方案实现起来也比较容易。
    我认为方案2从根本上避免了cl_ord_id和下单回调次序的关联性,即使将来统一了实盘和回测模式的顺序,也建议保留下单前申请cl_ord_id的做法。


    另外反馈一下以前发现的一些小问题:
    HistoryTicksN/HistoryBarsN函数,symbols为逗号分隔的多个代码时返回0条数据(帮助文档中允许多个代码)
    注:允许一次查询多个代码是有必要的,这样比一个一个循环查询节省时间,这在盘中非常重要。

    Subscribe函数:frequency = "tick", unsubscribePrevious = true时返回-1。

    再提两个有关数据的小建议,不知跟您提是否合适:
    一是分红配股数据最好能提前查询到,最好是公告日就能查到,至少是比除息日提前几天能查到。因为分红配股在策略中处理起来还是很麻烦的,如果能提前知道那天是股权登记日和除息日,就可以提前决定避开还是做特殊处理。
    二是"tick"频度回测好像只有3、4个月的数据,这实在是太短了,建议提供前两年的回测数据,至少是前一年的数据;

    2019-02-20 10:59:05
  • @gloryyan
    1 明白您的意思了,回测事件顺序和实盘不一致,导致订单跟踪有问题,这其实是回测机制的深层问题(下单后多久返回成交),回测这一块我们并不打算小修补,而是在机制上大幅完善
    2 history_n一次查询多个标的,在目前的规划中,完成还需等待
    3 分红派送是可以查到未来的信息的,交易所公布后我们就会收录进来

    2019-02-20 18:16:59
  • @喜羊羊
    非常感谢您的回复! 虽然我认为这样的"小修补"化很小的代价解决眼前的大问题, 是值得的, 但你们有自己的产品规划和开发计划, 我表示理解和尊重.

    关于分红送配信息的发布时间, 确实是我孤陋寡闻了. 把endDate参数设成未来的日期就可以查到未来信息了.
    再次感谢!

    2019-02-21 15:40:19

Looks like your connection to 掘金量化社区 - 量化交易者的策略交流学习社区 was lost, please wait while we try to reconnect.