当前位置:网站首页>Development of trading system (XI) -- Introduction to quickfix

Development of trading system (XI) -- Introduction to quickfix

2022-06-25 04:02:00 Tianshan old demon

One 、QuickFIX brief introduction

1、QuickFIX brief introduction

QuickFIX Is a C++ Open source implementation FIX engine , At the same time provide Python、Ruby Language implementation .

QuickFIX Official website :

http://www.quickfixengine.org
Github Address :

https://github.com/quickfix/quickfix

2、QuickFIX compile

Compilation options configuration :

configure

compile :

make

Check :

make check

install :

sudo make install

Two 、FIX Application mode

1、FIX Introduction to application mode

FIX Applications include initiator and acceptor Two modes .

initiator yes TCP The initiator of the connection ,acceptor yes TCP Connect listener . standard FIX application ( Such as CTS FIX gateway ) Can support at the same time initiator and acceptor Two modes , You can initiate a connection , You can also accept connection requests .
Development FIX When applied , You need to make sure FIX Application mode , Then choose the corresponding QuickFIX Class object .

initiator Mode FIX Applications can use SocketInitiator、SSLSocketInitiator、ThreadedSocketInitiator、ThreadedSSLSocketInitiator establish FIX Initiator application .

acceptor Mode FIX Applications can use SocketAcceptor、SSLSocketAcceptor、ThreadedSocketAcceptor、ThreadedSSLSocketAcceptor establish FIX Acceptor application .

2、FIX signal communication

FIX The application business is realized through initiator And acceptor Build a FIX Session And exchange messages .FIX Business messages have a series of predefined types and formats , The current standard message types are 5、60 individual , The letter covers the transaction 、 The market 、 Settlement and other aspects of investment management .FIX Application development is basically about FIX Message programming .

Fix Session Can be made up of one or more Fix Connection composition , namely Fix Session Can log in multiple times .Fix Session Several important signs are usually used to distinguish , Such as Fix Version number string ( Such as :FIX.4.2), sender ID, The receiver ID,Fix Session Every time a message is sent , The message header BeginString、SenderCompID、TargetCompID Will be assigned . When the message passes FIX When the connection reaches the peer , The peer can find the local side according to the ID in the message header Fix Session To process messages .

FIX The communication parties include Initiator and Acceptor, They will maintain each other 2 Incremental serial numbers ( Send message serial number – Add... For each message sent 1, Receive message sequence number – Add... For each message received 1).
(1) Communication is first and foremost by Initiator Start to initiate TCP Connection request , Acceptor Receive network connection request , establish TCP Connect .
(2)Initiator Initiate login message request .
(3)Acceptor After receiving the login request , After a series of message checks , After being qualified , Return to login confirmation .

(4)Initiator After receiving the login confirmation , After a series of message checks , After being qualified , The two sides FIX Session Successful connection .
(5)Initiator and Acceptor Exchange messages .
(6)Initiator and Acceptor Either party sends an exit message .

3、FIX Session To configure

QuickFix in initiator or acceptor Will maintain multiple Fix Session.QuickFix Use in BeginString(Fix Version number )、SenderCompID、TargetCompID A combination of Session,Session Identification is used to distinguish other different Session.

Session The configuration file contains [DEFAULT] and [SESSION] Two kinds of segmentation ,[SESSION] The subsection represents QuickFix Define a Session,[DEFAULT] Express all Session Configuration items used by default , If not provided QuickFix The required configuration ,QuickFix Will throw out ConfigError abnormal , Indicates that the configuration is missing or the format is incorrect .

If [DEFAULT] and [SESSION] All partitions contain the same configuration items , be [SESSION] The configuration items of the partition will overwrite [DEFAULT] Partition the corresponding configuration items .

QuickFix The configuration file sessions.ini as follows :

[DEFAULT]

ConnectionType=initiator

ReconnectInterval=60

FileLogPath=log

FileStorePath=store

StartTime=00:00:00

EndTime=23:59:59

HeartBtInt=30

ResetOnDisconnect=Y

ResetOnLogout=Y

ResetOnLogon=Y

[SESSION]

BeginString=FIX.4.2

SenderCompID=CLIENT

TargetCompID=SERVER

SocketConnectPort=6666

SocketConnectHost=127.0.0.1

DataDictionary=FIX42.xml

3、 ... and 、QuickFIX Core class

1、FIX::Application

FIX The application needs to implement FIX::Application Interface :

class Application

{

public:

  virtual ~Application() {};

  /// Notification of a session begin created

  virtual void onCreate( const SessionID& ) = 0;

  /// Notification of a session successfully logging on

  virtual void onLogon( const SessionID& ) = 0;

  /// Notification of a session logging off or disconnecting

  virtual void onLogout( const SessionID& ) = 0;

  /// Notification of admin message being sent to target

  virtual void toAdmin( Message&, const SessionID& ) = 0;

  /// Notification of app message being sent to target

  virtual void toApp( Message&, const SessionID& )

  EXCEPT ( DoNotSend ) = 0;

  /// Notification of admin message being received from target

  virtual void fromAdmin( const Message&, const SessionID& )

  EXCEPT ( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon ) = 0;

  /// Notification of app message being received from target

  virtual void fromApp( const Message&, const SessionID& )

  EXCEPT ( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType ) = 0;

};

onCreate: When one Fix Session Call .

onLogon: When one Fix Session When the login succeeds, call .

onLogout: When one Fix Session Call... On exit .

fromAdmin: When you receive a message , After a series of checks , After being qualified , Belong to Admin Called on type .

fromApp: When you receive a message , After a series of checks , After being qualified , Do not belong to Admin Call when type .

toAdmin: When sending a admin Type message call .

toApp: When sending a non admin( Business types ) Message call .

If needed QuickFIX Development FIX application , You need to achieve FIX::Application Interface , And reload different FIX Protocol version MessageCracker::OnMessage Interface , Such as FIX42::MessageCracker.

FIX Businesses are handled asynchronously , The basic object of business processing is message .OnMessage Is the message receiving callback function , There are multiple overloaded versions , Developers only need to overload one FIX Version can .

For those who support trading business FIX Initiator application , Usually you have to rewrite 4 A basic message , namely OnMessage(NewOrderSingle)、OnMessage(CancelRequest)、 OnMessage(ExecutionReport)、 OnMessage(CancelReject), They are used separately for delegation 、 cancel the order 、 Execution return ( Including the rejection of entrustment ) And rejection of cancellation, etc 4 Business .

#include "quickfix/Application.h"

#include "quickfix/MessageCracker.h"

class FIXApplication: public FIX::Application, public FIX::MessageCracker

{

public:

    /**************************************************

     *  reimplementation from Application

     * ***********************************************/

    /// Notification of a session begin created

    virtual void onCreate( const SessionID& )

    {

    }

    /// Notification of a session successfully logging on

    virtual void onLogon( const SessionID& )

    {

    }

    /// Notification of a session logging off or disconnecting

    virtual void onLogout( const SessionID& )

    {

    }

    /// Notification of admin message being sent to target

    virtual void toAdmin( Message&, const SessionID& )

    {

    }

    /// Notification of app message being sent to target

    void fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )

    throw( FIX::FieldNotFound&, FIX::IncorrectDataFormat&, FIX::IncorrectTagValue&,

           FIX::UnsupportedMessageType& )

    {

        crack(message, sessionID);

    }

    /// Notification of admin message being received from target

    virtual void fromAdmin( const Message&, const SessionID& )

    throw ( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue,

            FIX::RejectLogon )

    {

    }

    /// Notification of app message being received from target

    virtual void fromApp( const Message&, const SessionID& )

    throw ( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue,

            FIX::UnsupportedMessageType )

    {

    }

    /**************************************************

     *  reimplementation from FIX42::MessageCracker

     * ***********************************************/

    virtual void onMessage( const FIX42::NewOrderSingle& message, const FIX::SessionID& )

    {

    }

    virtual void onMessage( const FIX42::OrderCancelRequest& message, const FIX::SessionID& )

    {

    }

    virtual void onMessage( ExecutionReport&, const FIX::SessionID& )

    {

    }

    virtual void onMessage( OrderCancelReject&, const FIX::SessionID& )

    {

    }

};

2、FIX::SessionSettings

FIX Application configuration uses FIX::SessionSettings Read FIX Session Configure the file and pass it to QuickFIX frame . One FIX Applications can manage multiple FIX Session, Every Session The same... Can be used FIX Protocol version , You can also use different versions . Even if the same FIX Protocol version , Different FIX Session There can also be FIX Differences in agreement details , By binding FIX Session And FIX Protocol dictionary , That is to say Session In profile [Session] Used in configuration items DataDictionary Option specifies the corresponding FIX Dictionary file .

FIX::SessionSettings settings("sessionConfig.ini");

3、FIX::FileStoreFactory

QuickFIX Provides classes for storing messages to files FIX::FileLogFactory. The path of message file storage is Session Specified in configuration .

FIX::FileStoreFactory storeFactory(settings);

4、FIX::MessageStoreFactory

QuickFIX Provide for Fix Session Persistence type ( Such as file storage 、 data storage , The stored contents include status 、 Creation time 、 The message and its own maintained sending sequence number and receiving sequence number ).

If the developer wants to customize the persistence method , You can define yourself MessageStoreFactory Realization , And customize one MessageStore.

5、FIX::FileLogFactory

QuickFIX Provides a class that stores all log events to a file FIX::FileLogFactory.

6、FIX::ScreenLogFactory

QuickFIX A class that displays all message events to standard output is provided in ScreenLogFactory.

FIX::ScreenLogFactory logFactory(settings);

7、FIX::Message

QuickFIX Different... Are defined in FIX Base class for protocol version messages FIX::Message, Used for definition FIX The general structure of messages , Different FIX Message versions of messages are defined in different FIX Namespace , Such as FIX42::Message.FIX::MessageCracker Inherited all the differences FIX Protocol version MessageCracker class , After receiving the message, a specific message is generated FIX agreement Message Object implementation handles messages .

8、FIX::Session

Whether it's FIX Initiator Application or FIX Acceptor application , stay Fix Session On initialization , That is to say FIX::SessionFactory establish Fix Session Will check after Fix Session Time range . If Fix Session Start is not valid for the day Session, Will reset Fix Session Send serial number and receive serial number of .(FIX Specify a Fix Session Generally not more than 24 Hours ).

FIX::Session Some interfaces are defined as follows :

class Session

{

public:

  static bool sendToTarget( Message& message,

                            const std::string& qualifier = "" )

  EXCEPT ( SessionNotFound );

  static bool sendToTarget( Message& message,

                            const SessionID& sessionID )

  EXCEPT ( SessionNotFound );

  static bool sendToTarget( Message&,

                            const SenderCompID& senderCompID,

                            const TargetCompID& targetCompID,

                            const std::string& qualifier = "" )

  EXCEPT ( SessionNotFound );

  static bool sendToTarget( Message& message,

                            const std::string& senderCompID,

                            const std::string& targetCompID,

                            const std::string& qualifier = "" )

  EXCEPT ( SessionNotFound );

  bool send( Message& );

  void next();

  void next( const UtcTimeStamp& timeStamp );

  void next( const std::string&, const UtcTimeStamp& timeStamp, bool queued = false );

  void next( const Message&, const UtcTimeStamp& timeStamp, bool queued = false );

};

next() Method is a method that runs regularly , It is mainly used to detect whether a heartbeat message needs to be sent , Whether it is necessary to send TEST news , Need to disconnect , Whether it is necessary to produce LOGON(Initiator).

next( const Message&) Method for processing Session received FIX news .

9、FIX::Acceptor

FIX::Acceptor For from Session Configuration file reads information to create and manage this Acceptor Supported by FIX Session, Specifically FIX Session Of TCP Connection management 、 Data reading and writing are performed by specific SocketAcceptor、SSLSocketAcceptor、ThreadedSocketAcceptor、ThreadedSSLSocketAcceptor Realization .

FIX::Acceptor* acceptor = new FIX::SocketAcceptor(application, storeFactory, settings, logFactory);

10、FIX::Initiator

FIX::Initiator For from Session Configuration file reads information to create and manage this Initiator Supported by FIX Session, Specifically FIX Session Of TCP Connection management 、 Data reading and writing are performed by specific SocketInitiator、SSLSocketInitiator、ThreadedSocketInitiator、ThreadedSSLSocketInitiator Realization .

FIX::Initiator * initiator = new FIX::SocketInitiator(application, storeFactory, settings, logFactory);

Four 、FIX Acceptor application development

1、FIX Acceptor Application Introduction

FIX Acceptor Applications are usually used for FIX gateway , Deployed on the seller's side .

2、FIX Acceptor Application creation

(1) establish FIX Session Configuration object

FIX::SessionSettings settings(sessionFile);

(2) establish FIX application :

Application application;

Create a log factory :

LogFactory logFactory(settings);

Create a message store file factory :

FIX::FileStoreFactory storeFactory(settings);

establish Acceptor Server side :

FIX::Acceptor* acceptor = new SocketAcceptor(application, storeFactory, settings, logFactory);

start-up SocketAcceptor:

acceptor->start();

3、FIX Acceptor Application example

Executor The example demonstrates how to receive an order request and return a transaction receipt FIX Acceptor application .

Application.h file :

#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.h"

class Application

: public FIX::Application, public FIX::MessageCracker

{

public:

  Application() : m_orderID(0), m_execID(0) {}

  // Application overloads

  void 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 overloads

  void 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

Application.cpp file :

#include "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.h"

void 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& ) {}

}

void Application::onMessage( const FIX41::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 );

  FIX41::ExecutionReport executionReport = FIX41::ExecutionReport

      ( FIX::OrderID( genOrderID() ),

        FIX::ExecID( genExecID() ),

        FIX::ExecTransType( FIX::ExecTransType_NEW ),

        FIX::ExecType( FIX::ExecType_FILL ),

        FIX::OrdStatus( FIX::OrdStatus_FILLED ),

        symbol,

        side,

        orderQty,

        FIX::LastShares( orderQty ),

        FIX::LastPx( price ),

        FIX::LeavesQty( 0 ),

        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& ) {}

}

void Application::onMessage( const FIX42::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 );

  FIX42::ExecutionReport executionReport = FIX42::ExecutionReport

      ( FIX::OrderID( genOrderID() ),

        FIX::ExecID( genExecID() ),

        FIX::ExecTransType( FIX::ExecTransType_NEW ),

        FIX::ExecType( FIX::ExecType_FILL ),

        FIX::OrdStatus( FIX::OrdStatus_FILLED ),

        symbol,

        side,

        FIX::LeavesQty( 0 ),

        FIX::CumQty( orderQty ),

        FIX::AvgPx( price ) );

  executionReport.set( clOrdID );

  executionReport.set( orderQty );

  executionReport.set( FIX::LastShares( orderQty ) );

  executionReport.set( FIX::LastPx( price ) );

  if( message.isSet(account) )

    executionReport.setField( message.get(account) );

  try

  {

    FIX::Session::sendToTarget( executionReport, sessionID );

  }

  catch ( FIX::SessionNotFound& ) {}

}

void Application::onMessage( const FIX43::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 );

  FIX43::ExecutionReport executionReport = FIX43::ExecutionReport

      ( FIX::OrderID( genOrderID() ),

        FIX::ExecID( genExecID() ),

        FIX::ExecType( FIX::ExecType_FILL ),

        FIX::OrdStatus( FIX::OrdStatus_FILLED ),

        side,

        FIX::LeavesQty( 0 ),

        FIX::CumQty( orderQty ),

        FIX::AvgPx( price ) );

  executionReport.set( clOrdID );

  executionReport.set( symbol );

  executionReport.set( orderQty );

  executionReport.set( FIX::LastQty( orderQty ) );

  executionReport.set( FIX::LastPx( price ) );

  if( message.isSet(account) )

    executionReport.setField( message.get(account) );

  try

  {

    FIX::Session::sendToTarget( executionReport, sessionID );

  }

  catch ( FIX::SessionNotFound& ) {}

}

void Application::onMessage( const FIX44::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 );

  FIX44::ExecutionReport executionReport = FIX44::ExecutionReport

      ( FIX::OrderID( genOrderID() ),

        FIX::ExecID( genExecID() ),

        FIX::ExecType( FIX::ExecType_TRADE ),

        FIX::OrdStatus( FIX::OrdStatus_FILLED ),

        side,

        FIX::LeavesQty( 0 ),

        FIX::CumQty( orderQty ),

        FIX::AvgPx( price ) );

  executionReport.set( clOrdID );

  executionReport.set( symbol );

  executionReport.set( orderQty );

  executionReport.set( FIX::LastQty( orderQty ) );

  executionReport.set( FIX::LastPx( price ) );

  if( message.isSet(account) )

    executionReport.setField( message.get(account) );

  try

  {

    FIX::Session::sendToTarget( executionReport, sessionID );

  }

  catch ( FIX::SessionNotFound& ) {}

}

void Application::onMessage( const FIX50::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 );

  FIX50::ExecutionReport executionReport = FIX50::ExecutionReport

      ( FIX::OrderID( genOrderID() ),

        FIX::ExecID( genExecID() ),

        FIX::ExecType( FIX::ExecType_TRADE ),

        FIX::OrdStatus( FIX::OrdStatus_FILLED ),

        side,

        FIX::LeavesQty( 0 ),

        FIX::CumQty( orderQty ) );

  

  executionReport.set( clOrdID );

  executionReport.set( symbol );

  executionReport.set( orderQty );

  executionReport.set( FIX::LastQty( orderQty ) );

  executionReport.set( FIX::LastPx( price ) );

  executionReport.set( FIX::AvgPx( price ) );

  if( message.isSet(account) )

    executionReport.setField( message.get(account) );

  try

  {

    FIX::Session::sendToTarget( executionReport, sessionID );

  }

  catch ( FIX::SessionNotFound& ) {}

}

main.cpp file :

#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 <fstream>

void wait()

{

  std::cout << "Type Ctrl-C to quit" << std::endl;

  while(true)

  {

    FIX::process_sleep(1);

  }

}

int 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();

    wait();

    acceptor->stop();

    delete acceptor;

    return 0;

  }

  catch ( std::exception & e )

  {

    std::cout << e.what() << std::endl;

    delete acceptor;

    return 1;

  }

}

5、 ... and 、FIX Initiator application development

1、FIX Initiator Application Introduction

FIX Initiator Applications are usually used for trading clients , Deployed on the buyer's side .

2、FIX Initiator Application creation

(1) establish FIX Session Configuration object

FIX::SessionSettings settings(sessionFile);

(2) establish FIX application :

Application application;

Create a log factory :

LogFactory logFactory(settings);

Create a message store file factory :

FIX::FileStoreFactory storeFactory(settings);

establish Acceptor Server side :

FIX::Initiator* client= new SocketInitiator(application, storeFactory,settings, logFactory);

start-up SocketInitiator:

client->start();

3、FIX Initiator Application example

tradeclient Trading Client

Application.h file :

#ifndef TRADECLIENT_APPLICATION_H

#define TRADECLIENT_APPLICATION_H

#include "quickfix/Application.h"

#include "quickfix/MessageCracker.h"

#include "quickfix/Values.h"

#include "quickfix/Mutex.h"

#include "quickfix/fix40/NewOrderSingle.h"

#include "quickfix/fix40/ExecutionReport.h"

#include "quickfix/fix40/OrderCancelRequest.h"

#include "quickfix/fix40/OrderCancelReject.h"

#include "quickfix/fix40/OrderCancelReplaceRequest.h"

#include "quickfix/fix41/NewOrderSingle.h"

#include "quickfix/fix41/ExecutionReport.h"

#include "quickfix/fix41/OrderCancelRequest.h"

#include "quickfix/fix41/OrderCancelReject.h"

#include "quickfix/fix41/OrderCancelReplaceRequest.h"

#include "quickfix/fix42/NewOrderSingle.h"

#include "quickfix/fix42/ExecutionReport.h"

#include "quickfix/fix42/OrderCancelRequest.h"

#include "quickfix/fix42/OrderCancelReject.h"

#include "quickfix/fix42/OrderCancelReplaceRequest.h"

#include "quickfix/fix43/NewOrderSingle.h"

#include "quickfix/fix43/ExecutionReport.h"

#include "quickfix/fix43/OrderCancelRequest.h"

#include "quickfix/fix43/OrderCancelReject.h"

#include "quickfix/fix43/OrderCancelReplaceRequest.h"

#include "quickfix/fix43/MarketDataRequest.h"

#include "quickfix/fix44/NewOrderSingle.h"

#include "quickfix/fix44/ExecutionReport.h"

#include "quickfix/fix44/OrderCancelRequest.h"

#include "quickfix/fix44/OrderCancelReject.h"

#include "quickfix/fix44/OrderCancelReplaceRequest.h"

#include "quickfix/fix44/MarketDataRequest.h"

#include "quickfix/fix50/NewOrderSingle.h"

#include "quickfix/fix50/ExecutionReport.h"

#include "quickfix/fix50/OrderCancelRequest.h"

#include "quickfix/fix50/OrderCancelReject.h"

#include "quickfix/fix50/OrderCancelReplaceRequest.h"

#include "quickfix/fix50/MarketDataRequest.h"

#include <queue>

class Application :

      public FIX::Application,

      public FIX::MessageCracker

{

public:

  void run();

private:

  void 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 );

  void onMessage( const FIX42::ExecutionReport&, const FIX::SessionID& );

  void onMessage( const FIX42::OrderCancelReject&, const FIX::SessionID& );

  void queryEnterOrder();

  void queryCancelOrder();

  void queryReplaceOrder();

  FIX42::NewOrderSingle queryNewOrderSingle42();

  FIX42::OrderCancelRequest queryOrderCancelRequest42();

  FIX42::OrderCancelReplaceRequest queryCancelReplaceRequest42();

  void queryHeader( FIX::Header& header );

  char queryAction();

  int queryVersion();

  bool queryConfirm( const std::string& query );

  FIX::SenderCompID querySenderCompID();

  FIX::TargetCompID queryTargetCompID();

  FIX::TargetSubID queryTargetSubID();

  FIX::ClOrdID queryClOrdID();

  FIX::OrigClOrdID queryOrigClOrdID();

  FIX::Symbol querySymbol();

  FIX::Side querySide();

  FIX::OrderQty queryOrderQty();

  FIX::OrdType queryOrdType();

  FIX::Price queryPrice();

  FIX::StopPx queryStopPx();

  FIX::TimeInForce queryTimeInForce();

};

#endif

Application.cpp file :

#include "config.h"

#include "Application.h"

#include "quickfix/Session.h"

#include <iostream>

void Application::onLogon( const FIX::SessionID& sessionID )

{

  std::cout << std::endl << "Logon - " << sessionID << std::endl;

}

void Application::onLogout( const FIX::SessionID& sessionID )

{

  std::cout << std::endl << "Logout - " << sessionID << std::endl;

}

void Application::fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )

EXCEPT( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType )

{

  crack( message, sessionID );

  std::cout << std::endl << "IN: " << message << std::endl;

}

void Application::toApp( FIX::Message& message, const FIX::SessionID& sessionID )

EXCEPT( FIX::DoNotSend )

{

  try

  {

    FIX::PossDupFlag possDupFlag;

    message.getHeader().getField( possDupFlag );

    if ( possDupFlag ) throw FIX::DoNotSend();

  }

  catch ( FIX::FieldNotFound& ) {}

  std::cout << std::endl

  << "OUT: " << message << std::endl;

}

void Application::onMessage

( const FIX42::ExecutionReport&, const FIX::SessionID& ) {}

void Application::onMessage

( const FIX42::OrderCancelReject&, const FIX::SessionID& ) {}

void Application::run()

{

  while ( true )

  {

    try

    {

      char action = queryAction();

      if ( action == '1' )

        queryEnterOrder();

      else if ( action == '2' )

        queryCancelOrder();

      else if ( action == '3' )

        queryReplaceOrder();

      else if ( action == '5' )

        break;

    }

    catch ( std::exception & e )

    {

      std::cout << "Message Not Sent: " << e.what();

    }

  }

}

void Application::queryEnterOrder()

{

  int version = queryVersion();

  std::cout << "\nNewOrderSingle\n";

  FIX::Message order;

  switch ( version ) {

  case 42:

    order = queryNewOrderSingle42();

    break;

  default:

    std::cerr << "No test for version " << version << std::endl;

    break;

  }

  if ( queryConfirm( "Send order" ) )

    FIX::Session::sendToTarget( order );

}

void Application::queryCancelOrder()

{

  int version = queryVersion();

  std::cout << "\nOrderCancelRequest\n";

  FIX::Message cancel;

  switch ( version ) {

  case 42:

    cancel = queryOrderCancelRequest42();

    break;

  default:

    std::cerr << "No test for version " << version << std::endl;

    break;

  }

  if ( queryConfirm( "Send cancel" ) )

    FIX::Session::sendToTarget( cancel );

}

void Application::queryReplaceOrder()

{

  int version = queryVersion();

  std::cout << "\nCancelReplaceRequest\n";

  FIX::Message replace;

  switch ( version ) {

  case 42:

    replace = queryCancelReplaceRequest42();

    break;

  default:

    std::cerr << "No test for version " << version << std::endl;

    break;

  }

  if ( queryConfirm( "Send replace" ) )

    FIX::Session::sendToTarget( replace );

}

FIX42::NewOrderSingle Application::queryNewOrderSingle42()

{

  FIX::OrdType ordType;

  FIX42::NewOrderSingle newOrderSingle(

    queryClOrdID(), FIX::HandlInst( '1' ), querySymbol(), querySide(),

    FIX::TransactTime(), ordType = queryOrdType() );

  newOrderSingle.set( queryOrderQty() );

  newOrderSingle.set( queryTimeInForce() );

  if ( ordType == FIX::OrdType_LIMIT || ordType == FIX::OrdType_STOP_LIMIT )

    newOrderSingle.set( queryPrice() );

  if ( ordType == FIX::OrdType_STOP || ordType == FIX::OrdType_STOP_LIMIT )

    newOrderSingle.set( queryStopPx() );

  queryHeader( newOrderSingle.getHeader() );

  return newOrderSingle;

}

FIX42::OrderCancelRequest Application::queryOrderCancelRequest42()

{

  FIX42::OrderCancelRequest orderCancelRequest( queryOrigClOrdID(),

      queryClOrdID(), querySymbol(), querySide(), FIX::TransactTime() );

  orderCancelRequest.set( queryOrderQty() );

  queryHeader( orderCancelRequest.getHeader() );

  return orderCancelRequest;

}

FIX42::OrderCancelReplaceRequest Application::queryCancelReplaceRequest42()

{

  FIX42::OrderCancelReplaceRequest cancelReplaceRequest(

    queryOrigClOrdID(), queryClOrdID(), FIX::HandlInst( '1' ),

    querySymbol(), querySide(), FIX::TransactTime(), queryOrdType() );

  if ( queryConfirm( "New price" ) )

    cancelReplaceRequest.set( queryPrice() );

  if ( queryConfirm( "New quantity" ) )

    cancelReplaceRequest.set( queryOrderQty() );

  queryHeader( cancelReplaceRequest.getHeader() );

  return cancelReplaceRequest;

}

void Application::queryHeader( FIX::Header& header )

{

  header.setField( querySenderCompID() );

  header.setField( queryTargetCompID() );

  if ( queryConfirm( "Use a TargetSubID" ) )

    header.setField( queryTargetSubID() );

}

char Application::queryAction()

{

  char value;

  std::cout << std::endl

  << "1) Enter Order" << std::endl

  << "2) Cancel Order" << std::endl

  << "3) Replace Order" << std::endl

  << "4) Market data test" << std::endl

  << "5) Quit" << std::endl

  << "Action: ";

  std::cin >> value;

  switch ( value )

  {

    case '1': case '2': case '3': case '4': case '5': break;

    default: throw std::exception();

  }

  return value;

}

int Application::queryVersion()

{

  char value;

  std::cout << std::endl

  << "1) FIX.4.0" << std::endl

  << "2) FIX.4.1" << std::endl

  << "3) FIX.4.2" << std::endl

  << "4) FIX.4.3" << std::endl

  << "5) FIX.4.4" << std::endl

  << "6) FIXT.1.1 (FIX.5.0)" << std::endl

  << "BeginString: ";

  std::cin >> value;

  switch ( value )

  {

    case '1': return 40;

    case '2': return 41;

    case '3': return 42;

    case '4': return 43;

    case '5': return 44;

    case '6': return 50;

    default: throw std::exception();

  }

}

bool Application::queryConfirm( const std::string& query )

{

  std::string value;

  std::cout << std::endl << query << "?: ";

  std::cin >> value;

  return toupper( *value.c_str() ) == 'Y';

}

FIX::SenderCompID Application::querySenderCompID()

{

  std::string value;

  std::cout << std::endl << "SenderCompID: ";

  std::cin >> value;

  return FIX::SenderCompID( value );

}

FIX::TargetCompID Application::queryTargetCompID()

{

  std::string value;

  std::cout << std::endl << "TargetCompID: ";

  std::cin >> value;

  return FIX::TargetCompID( value );

}

FIX::TargetSubID Application::queryTargetSubID()

{

  std::string value;

  std::cout << std::endl << "TargetSubID: ";

  std::cin >> value;

  return FIX::TargetSubID( value );

}

FIX::ClOrdID Application::queryClOrdID()

{

  std::string value;

  std::cout << std::endl << "ClOrdID: ";

  std::cin >> value;

  return FIX::ClOrdID( value );

}

FIX::OrigClOrdID Application::queryOrigClOrdID()

{

  std::string value;

  std::cout << std::endl << "OrigClOrdID: ";

  std::cin >> value;

  return FIX::OrigClOrdID( value );

}

FIX::Symbol Application::querySymbol()

{

  std::string value;

  std::cout << std::endl << "Symbol: ";

  std::cin >> value;

  return FIX::Symbol( value );

}

FIX::Side Application::querySide()

{

  char value;

  std::cout << std::endl

  << "1) Buy" << std::endl

  << "2) Sell" << std::endl

  << "3) Sell Short" << std::endl

  << "4) Sell Short Exempt" << std::endl

  << "5) Cross" << std::endl

  << "6) Cross Short" << std::endl

  << "7) Cross Short Exempt" << std::endl

  << "Side: ";

  std::cin >> value;

  switch ( value )

  {

    case '1': return FIX::Side( FIX::Side_BUY );

    case '2': return FIX::Side( FIX::Side_SELL );

    case '3': return FIX::Side( FIX::Side_SELL_SHORT );

    case '4': return FIX::Side( FIX::Side_SELL_SHORT_EXEMPT );

    case '5': return FIX::Side( FIX::Side_CROSS );

    case '6': return FIX::Side( FIX::Side_CROSS_SHORT );

    case '7': return FIX::Side( 'A' );

    default: throw std::exception();

  }

}

FIX::OrderQty Application::queryOrderQty()

{

  long value;

  std::cout << std::endl << "OrderQty: ";

  std::cin >> value;

  return FIX::OrderQty( value );

}

FIX::OrdType Application::queryOrdType()

{

  char value;

  std::cout << std::endl

  << "1) Market" << std::endl

  << "2) Limit" << std::endl

  << "3) Stop" << std::endl

  << "4) Stop Limit" << std::endl

  << "OrdType: ";

  std::cin >> value;

  switch ( value )

  {

    case '1': return FIX::OrdType( FIX::OrdType_MARKET );

    case '2': return FIX::OrdType( FIX::OrdType_LIMIT );

    case '3': return FIX::OrdType( FIX::OrdType_STOP );

    case '4': return FIX::OrdType( FIX::OrdType_STOP_LIMIT );

    default: throw std::exception();

  }

}

FIX::Price Application::queryPrice()

{

  double value;

  std::cout << std::endl << "Price: ";

  std::cin >> value;

  return FIX::Price( value );

}

FIX::StopPx Application::queryStopPx()

{

  double value;

  std::cout << std::endl << "StopPx: ";

  std::cin >> value;

  return FIX::StopPx( value );

}

FIX::TimeInForce Application::queryTimeInForce()

{

  char value;

  std::cout << std::endl

  << "1) Day" << std::endl

  << "2) IOC" << std::endl

  << "3) OPG" << std::endl

  << "4) GTC" << std::endl

  << "5) GTX" << std::endl

  << "TimeInForce: ";

  std::cin >> value;

  switch ( value )

  {

    case '1': return FIX::TimeInForce( FIX::TimeInForce_DAY );

    case '2': return FIX::TimeInForce( FIX::TimeInForce_IMMEDIATE_OR_CANCEL );

    case '3': return FIX::TimeInForce( FIX::TimeInForce_AT_THE_OPENING );

    case '4': return FIX::TimeInForce( FIX::TimeInForce_GOOD_TILL_CANCEL );

    case '5': return FIX::TimeInForce( FIX::TimeInForce_GOOD_TILL_CROSSING );

    default: throw std::exception();

  }

}

main.cpp file :

#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 <fstream>

int 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;

  }

}

原网站

版权声明
本文为[Tianshan old demon]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202210536403260.html