代做视频的网站,电影网站怎么做的,网站活动专题页面设计,wordpress 菜单 数据库一、介绍
fix协议在上篇已经学习了#xff0c;不再介绍。
QuickFIX是一款C实现的开源FIX引擎#xff0c;同时提供Python等多种语言实现#xff0c;具体看quickfix git地址
官网已经介绍如何编译quickfix、配置文件字段含义等等#xff0c;我假设你可以看懂#xff0c;用…
一、介绍
fix协议在上篇已经学习了不再介绍。
QuickFIX是一款C实现的开源FIX引擎同时提供Python等多种语言实现具体看quickfix git地址
官网已经介绍如何编译quickfix、配置文件字段含义等等我假设你可以看懂用的时候查阅即可我就不复制过来了本文是教你快速认识此框架并且用起来。
二、主要类介绍
想了解如何用某个组件先了解他的成员都有哪些。
2.1 Application
若是须要使用QuickFIX开发FIX应用则须要实现FIX::Application接口并重载不一样FIX协议版本的MessageCracker::OnMessage接口如FIX42::MessageCracker。
class Application
{
public:virtual ~Application() {};/// Notification of a session begin createdvirtual void onCreate( const SessionID ) 0;/// Notification of a session successfully logging onvirtual void onLogon( const SessionID ) 0;/// Notification of a session logging off or disconnectingvirtual void onLogout( const SessionID ) 0;/// Notification of admin message being sent to targetvirtual void toAdmin( Message, const SessionID ) 0;/// Notification of app message being sent to targetvirtual void toApp( Message, const SessionID )EXCEPT ( DoNotSend ) 0;/// Notification of admin message being received from targetvirtual void fromAdmin( const Message, const SessionID )EXCEPT ( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon ) 0;/// Notification of app message being received from targetvirtual void fromApp( const Message, const SessionID )EXCEPT ( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType ) 0;
}; onCreate当Fix Session创建时调用。 onLogon当Fix Session登陆成功时调用。 onLogout当Fix Session退出时调用。 fromAdmin当收到一个Admin类型消息时调用。 fromApp当收到一个不属于Admin 类型消息时调用。 toAdmin当发送一个admin类型消息调用。 toApp当发送一个非admin(业务类型)消息调用。
admin一般是服务提供方app是客户端
对于支持交易业务的FIX Initiator应用通常重写4个基本消息OnMessage(NewOrderSingle、OnMessage(CancelRequest)、 OnMessage(ExecutionReport)、 OnMessage(CancelReject)用于做委托、撤单、执行回包和对撤单拒绝等4项业务。
更全面的介绍是这样的入门选手可以先不了解这么详细 onCreate当quickfix创建新会话时调用。会话一旦创建将应用程序的整个生命周期内保持存在。不管对方是否连接到会话会话都存在。一旦创建了会话就可以开始向它发送消息。如果没有人登录则消息将在与对方建立连接时发送。onLogon当建立连接并完成FIX登录过程(双方交换有效的登录消息)时调用该函数。onLogout当某个 FIX 会话不再在线时进行通知这可能发生在正常的注销交换过程中或者由于强制终止或网络连接丢失。toAdmin使您可以了解从FIX引擎发送到交易方的管理消息。这通常对应用程序没有用处但它可以让你进行与管理消息相关的日志记录。注意FIX::Message 不是常量这允许你在发送管理消息之前向其添加字段。toApp正在发送给对手方的应用程序消息时进行的回调。如果在这个函数中抛出一个 DoNotSend 异常应用程序将不会发送消息。这可用于取消重新发送一些不必要的消息比如与当前市场不再相关的订单。注意FIX::Message 不是常量这允许你在发送管理消息之前向其添加字段。 抛出 DoNotSend 异常并将消息的 PossDupFlag 设置为 truea sequence reset will be sent in place of the message.序列号将被重置为这个要发送的消息的序列号抛出 DoNotSend 异常并将消息的 PossDupFlag 设置为 false不会发送消息。fromAdmin当管理消息从交易方发送到 FIX 引擎时通知您。这对于对登录消息(如验证密码)进行额外的验证非常有用。在函数中抛出 RejectLogon 异常将断开对方的连接。fromApp接收应用程序级请求。如果您的应用程序是一个卖方OMS您将从函数中获得的新订单请求如果你是买方你会在这里拿到你的执行报告。 如果抛出 FieldNotFound 异常对方将收到一个 Reject消息表示缺少一个条件要求的字段。当试图检索丢失的字段时Message 类将抛出此异常因此很少需要显式地抛出。如果抛出 UnsupportedMessageType 异常对方将收到一个 Reject消息通知他们您的应用程序无法处理这些类型的消息。如果字段包含您不支持的值也会抛出 IncorrectTagValue。如果应用程序在多个会话之间共享资源则必须同步这些资源可以用SynchronizedApplication 类来自动同步应用程序中的所有函数调用各种 MessageCracker 类可用于将通用消息结构解析为特定的 FIX 消息。
2.2 SynchronizedApplication
与Application 的区别通过 Mutex 在回调的时候保证这一次只有一个线程访问应用程序的代码这样对性能有影响。
/**
* This is a special implementation of the Application interface that takes
* in another Application interface and synchronizes all of its callbacks. This
* will guarantee that only one thread will access the applications code at a time.
*
* This class is a great convenience for writing applications where you
* dont want to worry about synchronization. There is of course a tradeoff
* in that you may be synchronizing more than you need to. There is also a very
* minor performance penalty due to the extra virtual table lookup.
*/
class SynchronizedApplication : public Application
{
public:SynchronizedApplication( Application app ) : m_app( app ) {}void onCreate( const SessionID sessionID ){ Locker l( m_mutex ); app().onCreate( sessionID ); }void onLogon( const SessionID sessionID ){ Locker l( m_mutex ); app().onLogon( sessionID ); }void onLogout( const SessionID sessionID ){ Locker l( m_mutex ); app().onLogout( sessionID ); }void toAdmin( Message message, const SessionID sessionID ){ Locker l( m_mutex ); app().toAdmin( message, sessionID ); }void toApp( Message message, const SessionID sessionID )throw( DoNotSend ){ Locker l( m_mutex ); app().toApp( message, sessionID ); }void fromAdmin( const Message message, const SessionID sessionID )throw( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon ){ Locker l( m_mutex ); app().fromAdmin( message, sessionID ); }void fromApp( const Message message, const SessionID sessionID )throw( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType ){ Locker l( m_mutex ); app().fromApp( message, sessionID ); }Mutex m_mutex;Application app() { return m_app; }Application m_app;
};
2.3. FIX::NullApplication实现
FIX::NullApplication 主要用于不想要实现所有回调接口的场景中可以继承该类。
class NullApplication : public Application
{void onCreate( const SessionID ) {}void onLogon( const SessionID ) {}void onLogout( const SessionID ) {}void toAdmin( Message, const SessionID ) {}void toApp( Message, const SessionID ) EXCEPT ( DoNotSend ) {}void fromAdmin( const Message, const SessionID )EXCEPT ( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon ) {}void fromApp( const Message, const SessionID )EXCEPT ( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType ) {}
}; 2.4 SessionSettings
FIX配置使用FIX::SessionSettings读取FIX Session配置文件并传递给QuickFIX框架。
一个FIX应用能够管理多个FIX Session每一个Session能够采用相同的FIX协议版本也能够采用不一样的版本。即便采用的是相同的FIX协议版本不一样FIX Session间也能够有FIX协议细节的差别经过绑定FIX Session与FIX协议字典的方式来实现即在Session配置文件中[Session]配置项中使用DataDictionary选项指定相应FIX字典文件来实现。
FIX::SessionSettings settings(sessionConfig.ini);
应用如何实现的管理多session看Initiator/Acceptor源码可以明白 class{
typedef std::set SessionID SessionIDs;typedef std::map SessionID, int SessionState;typedef std::map SessionID, Session* Sessions;Sessions m_sessions;SessionIDs m_sessionIDs;SessionState m_sessionState;
...
} 三个map记录id、状态、具体对象。
2.5 FileStoreFactory
QuickFIX提供了存储消息到文件的类FIX::FileStoreFactory。消息文件存储的路径在Session配置中指定。具体配置下文提到。
FIX::FileStoreFactory storeFactory(settings);
2.4 MessageStoreFactory
QuickFIX提供了给Fix Session持久化类型(如文件存储、数据存储存储内容包括状态、建立时间、消息及其本身维护的发送序列号和接收序列号等。 如果开发者要自定义持久化方式也可以自己实现MessageStoreFactory而且自定义一种MessageStore的ide。
/*** This interface must be implemented to create a MessageStore.*/
class MessageStoreFactory
{
public:virtual ~MessageStoreFactory() {}virtual MessageStore* create( const SessionID ) 0;virtual void destroy( MessageStore* ) 0;
};
2.5 FIX::FileLogFactory
QuickFIX提供了存储全部日志事件到文件的类FIX::FileLogFactory。
2.6 FIX::Message
QuickFIX中定义了不一样FIX协议版本消息的基类FIX::Message用于定义FIX消息的通用结构不一样的FIX消息版本的消息定义在不一样的FIX命名空间内定义如FIX42::Message。FIX::MessageCracker则继承了全部不一样FIX协议版本的MessageCracker类接收消息后生成具体FIX协议Message对象实现对消息进行处理。
2.7 FIX::Acceptor FIX::Acceptor用于创建和管理本Acceptor的Session。
具体Session的TCP连接管理、数据读写由具体的SocketAcceptor、SSLSocketAcceptor、ThreadedSocketAcceptor、ThreadedSSLSocketAcceptor实现。
FIX::Acceptor* acceptor new FIX::SocketAcceptor(application, storeFactory, settings, logFactory); 2.8 FIX::Initiator FIX::Initiator用于创建和管理本Initiator支持的Session。
具体Session的TCP连接管理、数据读写由具体的SocketInitiator、SSLSocketInitiator、ThreadedSocketInitiator、ThreadedSSLSocketInitiator实现。
FIX::Initiator * initiator new FIX::SocketInitiator(application, storeFactory, settings, logFactory);
三、创建应用
我们根据第二章的内容创建一个应用主体见2.1
.h
#ifndef EXECUTOR_APPLICATION_H
#define EXECUTOR_APPLICATION_H#include quickfix/Application.h
#include quickfix/MessageCracker.h
#include quickfix/Values.h
#include quickfix/Utility.h
#include quickfix/Mutex.h#include quickfix/fix40/NewOrderSingle.h
#include quickfix/fix41/NewOrderSingle.h
#include quickfix/fix42/NewOrderSingle.h
#include quickfix/fix43/NewOrderSingle.h
#include quickfix/fix44/NewOrderSingle.h
#include quickfix/fix50/NewOrderSingle.hclass Application
: public FIX::Application, public FIX::MessageCracker
{
public:Application() : m_orderID(0), m_execID(0) {}// Application overloadsvoid onCreate( const FIX::SessionID );void onLogon( const FIX::SessionID sessionID );void onLogout( const FIX::SessionID sessionID );void toAdmin( FIX::Message, const FIX::SessionID );void toApp( FIX::Message, const FIX::SessionID )EXCEPT( FIX::DoNotSend );void fromAdmin( const FIX::Message, const FIX::SessionID )EXCEPT( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::RejectLogon );void fromApp( const FIX::Message message, const FIX::SessionID sessionID )EXCEPT( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType );// MessageCracker overloadsvoid onMessage( const FIX40::NewOrderSingle, const FIX::SessionID );void onMessage( const FIX41::NewOrderSingle, const FIX::SessionID );void onMessage( const FIX42::NewOrderSingle, const FIX::SessionID );void onMessage( const FIX43::NewOrderSingle, const FIX::SessionID );void onMessage( const FIX44::NewOrderSingle, const FIX::SessionID );void onMessage( const FIX50::NewOrderSingle, const FIX::SessionID );std::string genOrderID() {std::stringstream stream;stream m_orderID;return stream.str();}std::string genExecID() {std::stringstream stream;stream m_execID;return stream.str();}
private:int m_orderID, m_execID;
};#endif
.cpp
#include quickfix/config.h#include Application.h
#include quickfix/Session.h#include quickfix/fix40/ExecutionReport.h
#include quickfix/fix41/ExecutionReport.h
#include quickfix/fix42/ExecutionReport.h
#include quickfix/fix43/ExecutionReport.h
#include quickfix/fix44/ExecutionReport.h
#include quickfix/fix50/ExecutionReport.hvoid Application::onCreate( const FIX::SessionID sessionID ) {}
void Application::onLogon( const FIX::SessionID sessionID ) {}
void Application::onLogout( const FIX::SessionID sessionID ) {}
void Application::toAdmin( FIX::Message message,const FIX::SessionID sessionID ) {}
void Application::toApp( FIX::Message message,const FIX::SessionID sessionID )
EXCEPT( FIX::DoNotSend ) {}void Application::fromAdmin( const FIX::Message message,const FIX::SessionID sessionID )
EXCEPT( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::RejectLogon ) {}void Application::fromApp( const FIX::Message message,const FIX::SessionID sessionID )
EXCEPT( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType )
{ crack( message, sessionID ); }void Application::onMessage( const FIX40::NewOrderSingle message,const FIX::SessionID sessionID )
{FIX::Symbol symbol;FIX::Side side;FIX::OrdType ordType;FIX::OrderQty orderQty;FIX::Price price;FIX::ClOrdID clOrdID;FIX::Account account;message.get( ordType );if ( ordType ! FIX::OrdType_LIMIT )throw FIX::IncorrectTagValue( ordType.getField() );message.get( symbol );message.get( side );message.get( orderQty );message.get( price );message.get( clOrdID );FIX40::ExecutionReport executionReport FIX40::ExecutionReport( FIX::OrderID( genOrderID() ),FIX::ExecID( genExecID() ),FIX::ExecTransType( FIX::ExecTransType_NEW ),FIX::OrdStatus( FIX::OrdStatus_FILLED ),symbol,side,orderQty,FIX::LastShares( orderQty ),FIX::LastPx( price ),FIX::CumQty( orderQty ),FIX::AvgPx( price ) );executionReport.set( clOrdID );if( message.isSet(account) )executionReport.setField( message.get(account) );try{FIX::Session::sendToTarget( executionReport, sessionID );}catch ( FIX::SessionNotFound ) {}
}
代码很简单唯一可能值得注意的两点
1、一般情况下对于FIX应用开发除了实现FIX::Application接口还需要重新实现FIX::MessageCracker从具体FIX协议版本实现继承来的onMessage方法所以我们一般这么写
class FIXApplication: public FIX::Application, public FIX::MessageCracker
2、crack接口他根据message类型匹配到你实现的具体onMessage接口上。 void crack( const Message message,const SessionID sessionID ){const FIX::BeginString beginString FIELD_GET_REF( message.getHeader(), BeginString );crack( message, sessionID, beginString );}void crack( const Message message,const SessionID sessionID,const BeginString beginString ){if ( beginString BeginString_FIX40 )((FIX40::MessageCracker)(*this)).crack((const FIX40::Message) message, sessionID);else if ( beginString BeginString_FIX41 )((FIX41::MessageCracker)(*this)).crack((const FIX41::Message) message, sessionID);else if ( beginString BeginString_FIX42 )((FIX42::MessageCracker)(*this)).crack((const FIX42::Message) message, sessionID);else if ( beginString BeginString_FIX43 )((FIX43::MessageCracker)(*this)).crack((const FIX43::Message) message, sessionID);else if ( beginString BeginString_FIX44 )((FIX44::MessageCracker)(*this)).crack((const FIX44::Message) message, sessionID);else if ( beginString BeginString_FIXT11 ){if( message.isAdmin() ){((FIXT11::MessageCracker)(*this)).crack((const FIXT11::Message) message, sessionID);}else{
}}}
四、发送方
Acceptor也可以称作为 Server就是服务端。客户端从各地发来交易或者行情请求后由这些服务器端接收并进一步送给决策端进行验证、决策并由此服务器返回相应的结果。大概的回复可能是这样的
行情请求35V——行情报价回复35W新建订单35D——订单回复358撤销订单35F——订单回复358或者拒绝359
搭建一个服务端非常的简单只需要两个类一个类负责初始化、启动和关停服务见2.7 FIX::Acceptor另一个类负责服务即收发消息见2.1 Application。
在第三章我们已经实现了收发消息的类接下来我们实现Acceptor万里长征就走完了一大半。
1创建FIX Session配置对象FIX::SessionSettings settings(sessionFile); 2创建FIX应用Application application; 3创建日志工厂LogFactory logFactory(settings); 4创建消息存储文件工厂FIX::FileStoreFactory storeFactory(settings); 5创建Acceptor服务端acceptor new FIX::SocketAcceptor ( application, storeFactory, settings, logFactory ); 6启动acceptor-start();
#include config.h
#include quickfix/FileStore.h
#include quickfix/SocketAcceptor.h
#include quickfix/Log.h
#include quickfix/SessionSettings.h
#include Application.h
#include string
#include iostream
#include fstreamint main( int argc, char** argv )
{if ( argc 2 ){std::cout usage: argv[ 0 ] FILE. std::endl;return 0;}std::string file argv[ 1 ];FIX::Acceptor * acceptor 0;try{FIX::SessionSettings settings( file );Application application;FIX::FileStoreFactory storeFactory( settings );FIX::ScreenLogFactory logFactory( settings );acceptor new FIX::SocketAcceptor ( application, storeFactory, settings, logFactory );acceptor-start();// dosomething wait();acceptor-stop();delete acceptor;return 0;}catch ( std::exception e ){std::cout e.what() std::endl;delete acceptor;return 1;}
}
五、接收方
Initiator也可以称作为 Client就是分散在各个地方的交易机客户端。业务员在上面操作以后客户端会向服务器发送请求。请求多种多样基本常用的有行情请求35V新建订单35D撤销订单35F。
搭建Initiator和服务端基本一样不过多解释。当然买方卖方的application逻辑肯定不一样这里只是给你一个代码框架希望你注意
#include config.h
#include quickfix/FileStore.h
#include quickfix/SocketInitiator.h
#include quickfix/SessionSettings.h
#include quickfix/Log.h
#include Application.h
#include string
#include iostream
#include fstreamint main( int argc, char** argv )
{if ( argc 2 ){std::cout usage: argv[ 0 ] FILE. std::endl;return 0;}std::string file argv[ 1 ];FIX::Initiator * initiator 0;try{FIX::SessionSettings settings( file );Application application;FIX::FileStoreFactory storeFactory( settings );FIX::ScreenLogFactory logFactory( settings );initiator new FIX::SocketInitiator( application, storeFactory, settings, logFactory );initiator-start();application.run();initiator-stop();delete initiator;return 0;}catch ( std::exception e ){std::cout e.what();delete initiator;return 1;}
} 六、进一步的操作
通过上文我们已经了解了quickfix大概的代码框架是什么样子的接下来认识一些进一步的操作以便我们可以把这个小demo真的做成一个功能。 6.1 配置文件
配置文件简化来讲有两个一个是程序调用的properties另一个是传输时候的字典相当于“密码本”。
先看一下文件内容
6.1.1 quickfix.properties
#quickfix-server.properties
[default]
# 这些字段接的改成你的设置
FileStorePathfileStore
SocketConnectHostXXX.XXX.XXX.XXX
SocketConnectPortXXXXX
TargetCompIDQUICKFIX_ACCEPTOR# 以下字段可以不改
ConnectionTypeinitiator
HeartBtInt30
ReconnectInterval10
FileLogPathlog
UseDataDictionaryN
DataDictionarysrc/main/resources/FIX44.modified.xml
ContinueInitializationOnErrorY
BeginStringFIX.4.4
StartTime00:00:00
EndTime23:00:00
ResetOnLogonY
ResetSeqNumFlagY
MaxMessagesInResendRequest1[session]
SenderCompIDQUICKFIX_INITIATOR1[session]
SenderCompIDQUICKFIX_INITIATOR2能看到配置被分为3大类开头的[default]然后是两个[session]。
session的意思是你作为发送方时不一定发给一个人。或者你作为接收方时不一定只接收一个人的信息。每个session下面配了不同的SenderCompID意思就是可能会有很多Sender给我发消息因此我要根据不同的SenderComID来区别不同的发送方。这个名字可以随便起只要保证收发双方一致。
其他公用的部分可以放在[default]里面其中
FileStorePath是存储消息和事件的文件夹确保一定要有写的权限SocketConnectHost和SocketConnectPort 是你Accepter的IP地址和端口TargetCompID 是你发的消息由谁来接收和SenderCompID对应ConnectionType是你扮演的角色有initiator和acceptor两种HeartBtInt是心跳间隔。
更多配置直接查阅官网。
讲到这里我害怕你还是不会写两边的配置所以我复制一份
[default]
# 这些字段记得改成你的设置
FileStorePathfileStore
SocketConnectHost***
SocketConnectPort***
TargetCompIDQUICKFIX_ACCEPTOR# 以下字段可以不改
ConnectionTypeinitiator
HeartBtInt30
ReconnectInterval10
FileLogPathlog
UseDataDictionaryN
DataDictionarysrc/main/resources/FIX44.modified.xml
ContinueInitializationOnErrorY
BeginStringFIX.4.4
StartTime00:00:00
EndTime23:00:00
ResetOnLogonY
ResetSeqNumFlagY
MaxMessagesInResendRequest1[session]
SenderCompIDQUICKFIX_INITIATOR1[session]
SenderCompIDQUICKFIX_INITIATOR2
#quickfix-server.properties
[default]
# 这些字段记得改成你的设置
FileStorePathfileStore
SocketAcceptAddress***
SocketAcceptPort***
SenderCompIDQUICKFIX_ACCEPTOR# 以下字段可以不改
ConnectionTypeacceptor
HeartBtInt30
#ReconnectInterval10
FileLogPathlog
DataDictionarysrc/main/resources/FIX44.modified.xml
ContinueInitializationOnErrorY
BeginStringFIX.4.4
StartTime00:00:00
EndTime23:00:00
ResetOnLogonY
ResetSeqNumFlagY
MaxMessagesInResendRequest1
SocketReuseAddressY
UseDataDictionaryY[session]
TargetCompIDQUICKFIX_INITIATOR1[session]
TargetCompIDQUICKFIX_INITIATOR2
6.1.2 FIX44.modified.xml
在实际业务中我们会对字典进行一定修改比如让某些字段从“必须有”到“可以有”增减某些消息里面的某些字段甚至定义自己的新消息。在这个时候我们就可以在原有FIX44.xml的基础上维护我们自己的“密码本”取个名字FIX44.modified.xml。
每一个消息都在message的标签内
nameMarketDataRequestReject 表示名字msgtypeY 表示他的类别在传输的时候会表现为“35Y”msgcatapp 表示他是App层的传输。另外一个是Adminfield nameMDReqID requiredN 表示这个消息有个字段叫MDReqID并且在传输的时候不是必须的。如果一个字段定义为requiredY但是实际没有传那么这条消息就会被自动拒收并返回“353”的消息高速对方group nameNoAltMDSource 表示里面有个重复组即一个消息中可能多次出现同一个字段比如我在查询行情的时候可能查询多个产品的行情那么这可以“重复”的字段就必须定义在重复组里。
更多信息查阅官网 6.2 官网需要查看的东西
我还希望你可以查看官网的第三章和第四章这可以帮助你学习quickfix的各种细节用法包括如何收发消息、重复组的使用、自定义字段使用、他们自带的一套测试框架等等 七、常见的错误解答qa
第一条消息由Initiator 发出但是在Acceptor端没有看到接收的痕迹。
可能是Initiator端在发送第一条消息的时候过快以至于抢在了登录之前。
SessionNotFound
一般都是你配置错误导致找不到session我们前期讲过一个Session由3个基本要素构成消息头、发送方、接收方。任何一方有错误都会导致上述的SessionNotFound问题。
比如最常见的错误是Properties 文件中IP地址和端口不对或被占用
toApp 接口中抛出 DoNoSend 异常会对序列号造成影响吗
Application::toApp() 接口的回调发生在序列号递增Session::persist()之前所以不会对序列号造成影响。
SendingTime Accuracy Problem
因为收发双方的时间不对应根据Fix协议默认双方时差在30s以上时就会爆出这种时钟不同步的问题。
解决办法1配置你的机器使时间一致。
解决办法2通过设置properties文件配置CheckLatencyN这样就不会去做时钟同步检查。 Logout is Called
在建立链接的时候立即收到Logout is Called的消息除此之外没有其他提示。
如果不是网络问题那就是对方拒绝了跟你的通信但出于安全考虑又不想暴露原因就会抛出这么一个消息。
可能的原因有
没有使用SSL链接方式Logon时候对方需求在消息中包含用户名和密码但你没有写SenderCompID没配好是对方不能识别或者没有记录在案的ID。