我想在以下场景中阐明QuickFIX/J
(FIX 4.2)的行为。此QuickFIX/J
通信涉及两方:
当我登录 A 时,他们会与标记35=A
交换FIX消息。建立连接后,我开始提交订单。然而,可能有一点,我意外断开连接,此时 A 决定为我的所有未结订单发送取消(这是有效的,因为 A 不知道为什么我失败或我会活着回来。)
请注意,此整个取消取消程序仅由 A 启动和处理 - 它是从 A onLogout(...)
启动的方法由其正常的订单管理机制处理。为我的每个未结订单生成一条35=F
条消息,并在每次成功取消时生成ExecutionReport
(35=8
)。
当我恢复活着时,必须以某种方式将这些ExecutionReport
传递给我,以便它知道所有先前的订单已被取消。我的印象是QuickFIX/J
的消息队列实现在没有应用程序级帮助的情况下处理此问题。确保所有QuickFIX
消息都可以传递给对方(http://permalink.gmane.org/gmane.comp.finance.quickfix.devel/169)。
与我的理解相反, A 的ExecutionReport
日志中没有显示QuickFIX
,或我{ strong>当我重新连接时,导致我不知道其先前的订单已被取消。我注意到由于sendRaw(Message message, int num)
中Session
的{{1}}方法的以下源代码,因此未发生日志记录:
QuickFIX/J
在为我断开连接启动的取消生成/**
* Send the message
*
* @param message is the message to send
* @param num is the seq num of the message to send, if 0, the next expected sender seqnum is used.
* @return
*/
private boolean sendRaw(Message message, int num) {
...
} else {
try {
application.toApp(message, sessionID);
} catch (final DoNotSend e) {
return false;
} catch (final Throwable t) {
logApplicationException("toApp()", t);
}
messageString = message.toString();
if (isLoggedOn()) { // happens only if session is connected
result = send(messageString); // logging happens within "send"
}
}
...
}
消息时,会话未登录,因此它从未点击ExecutionReport
和没有记录发生。我相信没有消息排队(基于我在它恢复活动时没有收到任何消息的事实)出于同样的原因。
我们公司基于send(messageString);
保证所有消息都能毫不费力地传递的信念做出了许多实现,但我对上述场景的观察却说不出来。
当会话未登录时,QuickFIX/J
的消息队列在这种情况下的行为如何?它是否应该对消息进行排队,等待会话在将来再次可用时发送,还是在会话结束时停止排队?
答案 0 :(得分:1)
在private boolean sendRaw(Message message, int num)
方法结束时,有以下代码:
if (num == 0) {
final int msgSeqNum = header.getInt(MsgSeqNum.FIELD);
if (persistMessages) {
state.set(msgSeqNum, messageString);
}
state.incrNextSenderMsgSeqNum();
}
如果会话未连接,state.set(msgSeqNum, messageString)
将调用messageStore.set(sequence, message)
实际存储邮件以供稍后传递。
据我所知,所有邮件都会排队,直到会话成功登录。
答案 1 :(得分:0)
这是我的10美分:当QF / J保证基于序列号和间隙填充的活动会话的消息传递...
如果会话丢失,则无法保证任何内容。一旦发现序列号不匹配,您需要做的是将启动器和接受器配置为重新连接时的间隙填充。嗯,您的ResetOnDisconnect标志在配置中说了什么? ResetOnLogout怎么样?
我认为在QF中等待会话的消息“队列”并不存在,因为会话可以迪斯科并且永远不会重新调整意味着QF队列只是保持填充,或者永远是活跃的,这不是QF将要发生的事情能够为每个人提供开箱即用的服务。
如果您有迪斯科舞厅,也不能使用OnLogout将执行报告发送到断开连接的客户端!首先,OnLogout并不总是在每个迪斯科舞厅上调用,其次正如你所说我们进入QF内部并且它找不到发送消息的会话,所以它除外。我不希望QF内部队列为我处理这种情况。再次,保证传递是在连接是UP时...这是一个依赖。但是,我希望在某处记录它。你的日志配置是什么?
我认为您需要查看原因:“当/恢复活着时,必须将这些ExecutionReports传递给/以某种方式,以便它知道所有先前的订单已被取消。” isn'迪斯科的所有订单都被取消了吗?为什么/需要确认?这是给定的,不是吗?这可能是您必须单独编写QF基础的代码。
答案 2 :(得分:0)
阅读this。
有些公司支持35002
消息中的标记LOGON
(取消时取消),并带有可能的值:
了解您的对手方是否支持此功能。我没有检查过QuickFIX支持,但您可以自己手动添加标记,或自定义FIX字典以支持标记。
显然,高频交易员经常使用它。我不熟悉那个行业,因此在评论部分提出了这个问题。