TT Lab
开始
学习 学习路径 课程

资本市场与清结算

订单状态不能是任意值

在 TT Lab 中继续学习

一句话总结

订单报告不是随意的记录,而是状态机的输出,其中的数量有不能被破坏的等式。在故障调查中,“哪里出了问题”的大部分答案,只要用机器检查这两点就能得出。

为什么需要它

一个订单所附带的报告,少则三四行,多则几十行。由人用眼睛一行一行读着去找异常,只有前几笔订单才做得到。收到一整天的量,就有几万行,其中有问题的只有五六笔。所以 FDE 拿到客户数据后,第一件事不是读,而是过滤。

之所以能做出过滤网,是因为这个领域里有规则。FIX 协议 用 OrdStatus 这个字段来表示订单的状态,并规定了 New、PartiallyFilled、Filled、Canceled 这样的名称。字段的含义可以在 Fiximate 中确认。能从哪个状态转到哪个状态,各市场、各券商略有不同(本实验把状态转移表作为数据提供,并把它当作本实验的假设),所以重要的不是背下这张表,而是这张表存在,以及让代码去读这张表。

工作原理

检查分为五路。

第一,被禁止的转移。如果从前一条报告的状态到后一条报告的状态之间的路,在表里没有,就是问题。这里最重要的一类是终态。成交完成、撤销、拒绝、过期这类再也无处可去的状态,如果之后又冒出了什么,那要么是迟到的报告,要么是真正的缺陷。不过,也有表本身就是错的情形。如果声明为终态,却还留着一行从它出去的转移,检查器就会把这条转移当作正常放行。所以一读到表,就先找表自身的矛盾。

第二,数量等式。在存活的订单里,CumQty + LeavesQty == OrderQty。意思是,累计成交与剩余数量相加,等于订单数量。要注意的是,订单结束之后,这个等式并不成立。只成交了一半的订单被撤销,剩下的一半就会消失,余量变成 0。无条件应用等式的检查器,会把正常的撤销全都当成误报报上来。

第三,累计量的单调性。CumQty 不会减少。如果看起来减少了,就是报告颠倒着到达了,或者发生了回退。

第四,超额成交。如果成交数量之和超过订单数量,那就是涉及金钱的事故。不过,同一条报告如果进来两次,合计就会膨胀,看起来像超额成交。所以这项判定必须在去重之后再做一次。

第五,平均价格。AvgPx 必须是到那时为止的成交按数量加权的平均值。如果在这里使用浮点数,最后一位就会晃动,使完好的数据看起来像是有偏差。金额计算用 decimal,并预先确定舍入方式。

接下来还剩最后一个问题。过滤出来的东西里,哪些才是真正的缺陷。如果是同一条报告进来了两次,去重之后异常就会消失。如果是到达顺序颠倒了,按交易所时间重新排序之后就会消失。两者都做了还留下来的,才是真的。如果不把这三路分开,只汇报“30 处异常”,对方就什么也做不了。

在现场相遇的样子

有一次,超额成交的告警每天上报二十条。原因全都一样,重发的成交报告没有去重就被累加了。真正的超额成交并不在这二十条里,真正危险的那一笔,是几个星期之后通过别的途径才发现的。如果过滤网里满是噪声,就没有人会再去看那些告警。

另一件事是等式检查。因为检查器把被撤销的订单全部当作异常上报,每天有几千条告警发出去,结果这项检查被整个关掉了。这是只看数量、不看状态的后果。

第三件事是状态转移表本身。客户给的文档里,成交完成被写成了终态,可是代码读取的表里,却还留着一行从那个状态出去的转移。文档和代码对不上的地方,是以检查器所看的一边为准的。所以拿到新客户的数据时,要先让状态转移表与它自己对照。声明为终态的状态有没有出去的路,有没有哪个状态无论从哪里都到达不了,从起始状态到终态是不是真的有路。这三件事只看数据,几行就能确认,如果在这里发现了问题,后面所有的判定就都不能相信了。

最后,补充一点实务经验。这些检查最好做成可以交给客户的形态。如果在调查时用一次就扔掉,同样的问题三个月后会再次浮现,到时又得从头写起。如果规则放在数据里,让代码去读这份数据,即使市场或券商换了,同样的工具也能照常运转。

下一项实验要做什么

做出状态转移表和十二个订单的成交报告,先找出表自身的矛盾。然后依次检查被禁止的转移、数量等式、累计量倒退、超额成交和平均价格,最后把可以用重复报告和顺序颠倒来解释的,与不能解释的区分开,给出按原因汇总的摘要。其中混有以撤销结束的订单和以拒绝结束的订单,所以如果无条件应用等式,就会当场被卡住。