当前位置:网站首页>Development of trading system (XIII) -- Analysis of quickfix source code

Development of trading system (XIII) -- Analysis of quickfix source code

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

One 、QuickFIX Source directory

QuickFIX The main contents are as follows :

doc:QuickFIX Description and brief HTML file .
example:QuickFIX The sample program .

spec: Deposit FIX The data dictionary .

UnitTest++: Unit test framework .

test: The test script .
src: Source code directory .

src/C++:C++ Implementation code .

src/python:Python Realization .

src/python2:Python2 Realization .

src/python3:Python3 Realization .

src/ruby:Ruby Realization .

Two 、C++ Realization

1、C++ Implementation profile

QuickFIX Of C++ The implementation code is located in src/C++ Catalog ,C++ The code in the directory is QuickFIX Implementation of the general code , Use FIX Name space , Different FIX The implementation of the protocol is put in C++ Different directories under the directory , And use the corresponding FIX The protocol version namespace is qualified , Such as FIX42 The protocol implementation directory is fix42, Namespace is FIX42.

2、XML analysis

QuickFIX stay pugixml parser On the basis of the encapsulation of PUGIXML_DOMAttributes、PUGIXML_DOMNode、PUGIXML_DOMDocument Three categories , For parsing XML file , Defined in the header file PUGIXML_DOMDocument.h in .

#ifndef FIX_PUGIXMLDOMDOCUMENT_H

#define FIX_PUGIXMLDOMDOCUMENT_H

#include "DOMDocument.h"

#include "Exceptions.h"

#include "pugixml.hpp"

namespace FIX

{

/// XML attribute as represented by pugixml.

class PUGIXML_DOMAttributes : public DOMAttributes

{

public:

PUGIXML_DOMAttributes( pugi::xml_node pNode )

: m_pNode(pNode) {}

bool get( const std::string&, std::string& );

DOMAttributes::map toMap();

private:

pugi::xml_node m_pNode;

};

/// XML node as represented by pugixml.

class PUGIXML_DOMNode : public DOMNode

{

public:

PUGIXML_DOMNode( pugi::xml_node pNode )

: m_pNode(pNode) {}

~PUGIXML_DOMNode() {}

DOMNodePtr getFirstChildNode();

DOMNodePtr getNextSiblingNode();

DOMAttributesPtr getAttributes();

std::string getName();

std::string getText();

private:

pugi::xml_node m_pNode;

};

/// XML document as represented by pugixml.

class PUGIXML_DOMDocument : public DOMDocument

{

public:

PUGIXML_DOMDocument() EXCEPT ( ConfigError );

~PUGIXML_DOMDocument();

bool load( std::istream& );

bool load( const std::string& );

bool xml( std::ostream& );

DOMNodePtr getNode( const std::string& );

private:

pugi::xml_document m_pDoc;

};

}

#endif

Developers just need to care PUGIXML_DOMDocument Class load() function , Used for loading XML file .

3、 Data dictionary parsing

DataDictionary Class is used to parse FIX The data dictionary .

void DataDictionary::readFromURL( const std::string& url )

EXCEPT ( ConfigError )

{

  DOMDocumentPtr pDoc(new PUGIXML_DOMDocument());

  if(!pDoc->load(url))

    throw ConfigError(url + ": Could not parse data dictionary file");

  try

  {

    readFromDocument( pDoc );

  }

  catch( ConfigError& e )

  {

    throw ConfigError( url + ": " + e.what() );

  }

}

void DataDictionary::readFromDocument( const DOMDocumentPtr &pDoc )

EXCEPT ( ConfigError )

{

  // VERSION

  DOMNodePtr pFixNode = pDoc->getNode("/fix");

  if(!pFixNode.get())

    throw ConfigError("Could not parse data dictionary file"

                      ", or no <fix> node found at root");

  DOMAttributesPtr attrs = pFixNode->getAttributes();

  std::string type = "FIX";

  if(attrs->get("type", type))

  {

    if(type != "FIX" && type != "FIXT")

      throw ConfigError("type attribute must be FIX or FIXT");

  }

  std::string major;

  if(!attrs->get("major", major))

    throw ConfigError("major attribute not found on <fix>");

  std::string minor;

  if(!attrs->get("minor", minor))

    throw ConfigError("minor attribute not found on <fix>");

  setVersion(type + "." + major + "." + minor);

  // FIELDS

  DOMNodePtr pFieldsNode = pDoc->getNode("/fix/fields");

  if(!pFieldsNode.get())

    throw ConfigError("<fields> section not found in data dictionary");

  DOMNodePtr pFieldNode = pFieldsNode->getFirstChildNode();

  if(!pFieldNode.get()) throw ConfigError("No fields defined");

  while(pFieldNode.get())

  {

    if(pFieldNode->getName() == "field")

    {

      DOMAttributesPtr attrs = pFieldNode->getAttributes();

      std::string name;

      if(!attrs->get("name", name))

        throw ConfigError("<field> does not have a name attribute");

      std::string number;

      if(!attrs->get("number", number))

        throw ConfigError("<field> " + name + " does not have a number attribute");

      int num = atoi(number.c_str());

      std::string type;

      if(!attrs->get("type", type))

        throw ConfigError("<field> " + name + " does not have a type attribute");

      addField(num);

      addFieldType(num, XMLTypeToType(type));

      addFieldName(num, name);

      DOMNodePtr pFieldValueNode = pFieldNode->getFirstChildNode();

      while(pFieldValueNode.get())

      {

        if(pFieldValueNode->getName() == "value")

        {

          DOMAttributesPtr attrs = pFieldValueNode->getAttributes();

          std::string enumeration;

          if(!attrs->get("enum", enumeration))

            throw ConfigError("<value> does not have enum attribute in field " + name);

          addFieldValue(num, enumeration);

          std::string description;

          if(attrs->get("description", description))

            addValueName(num, enumeration, description);

        }

        RESET_AUTO_PTR(pFieldValueNode, pFieldValueNode->getNextSiblingNode());

      }

    }

    RESET_AUTO_PTR(pFieldNode, pFieldNode->getNextSiblingNode());

  }

  // HEADER

  if( type == "FIXT" || (type == "FIX" && major < "5") )

  {

    DOMNodePtr pHeaderNode = pDoc->getNode("/fix/header");

    if(!pHeaderNode.get())

      throw ConfigError("<header> section not found in data dictionary");

    DOMNodePtr pHeaderFieldNode = pHeaderNode->getFirstChildNode();

    if(!pHeaderFieldNode.get()) throw ConfigError("No header fields defined");

    while(pHeaderFieldNode.get())

    {

      if(pHeaderFieldNode->getName() == "field" || pHeaderFieldNode->getName() == "group" )

      {

        DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();

        std::string name;

        if(!attrs->get("name", name))

          throw ConfigError("<field> does not have a name attribute");

        std::string required = "false";

        attrs->get("required", required);

        addHeaderField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");

      }

      if(pHeaderFieldNode->getName() == "group")

      {

        DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();

        std::string required;

        attrs->get("required", required);

        bool isRequired = (required == "Y" || required == "y");

        addXMLGroup(pDoc.get(), pHeaderFieldNode.get(), "_header_", *this, isRequired);

      }

      RESET_AUTO_PTR(pHeaderFieldNode, pHeaderFieldNode->getNextSiblingNode());

    }

  }

  // TRAILER

    if( type == "FIXT" || (type == "FIX" && major < "5") )

    {

    DOMNodePtr pTrailerNode = pDoc->getNode("/fix/trailer");

    if(!pTrailerNode.get())

      throw ConfigError("<trailer> section not found in data dictionary");

    DOMNodePtr pTrailerFieldNode = pTrailerNode->getFirstChildNode();

    if(!pTrailerFieldNode.get()) throw ConfigError("No trailer fields defined");

    while(pTrailerFieldNode.get())

    {

      if(pTrailerFieldNode->getName() == "field" || pTrailerFieldNode->getName() == "group" )

      {

        DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();

        std::string name;

        if(!attrs->get("name", name))

          throw ConfigError("<field> does not have a name attribute");

        std::string required = "false";

        attrs->get("required", required);

        addTrailerField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");

      }

      if(pTrailerFieldNode->getName() == "group")

      {

        DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();

        std::string required;

        attrs->get("required", required);

        bool isRequired = (required == "Y" || required == "y");

        addXMLGroup(pDoc.get(), pTrailerFieldNode.get(), "_trailer_", *this, isRequired);

      }

      RESET_AUTO_PTR(pTrailerFieldNode, pTrailerFieldNode->getNextSiblingNode());

    }

  }

  // MSGTYPE

  DOMNodePtr pMessagesNode = pDoc->getNode("/fix/messages");

  if(!pMessagesNode.get())

    throw ConfigError("<messages> section not found in data dictionary");

  DOMNodePtr pMessageNode = pMessagesNode->getFirstChildNode();

  if(!pMessageNode.get()) throw ConfigError("No messages defined");

  while(pMessageNode.get())

  {

    if(pMessageNode->getName() == "message")

    {

      DOMAttributesPtr attrs = pMessageNode->getAttributes();

      std::string msgtype;

      if(!attrs->get("msgtype", msgtype))

        throw ConfigError("<message> does not have a msgtype attribute");

      addMsgType(msgtype);

      std::string name;

      if(attrs->get("name", name))

        addValueName( 35, msgtype, name );

      DOMNodePtr pMessageFieldNode = pMessageNode->getFirstChildNode();

      while( pMessageFieldNode.get() )

      {

        if(pMessageFieldNode->getName() == "field"

           || pMessageFieldNode->getName() == "group")

        {

          DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();

          std::string name;

          if(!attrs->get("name", name))

            throw ConfigError("<field> does not have a name attribute");

          int num = lookupXMLFieldNumber(pDoc.get(), name);

          addMsgField(msgtype, num);

          std::string required;

          if(attrs->get("required", required)

             && (required == "Y" || required == "y"))

          {

            addRequiredField(msgtype, num);

          }

        }

        else if(pMessageFieldNode->getName() == "component")

        {

          DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();

          std::string required;

          attrs->get("required", required);

          bool isRequired = (required == "Y" || required == "y");

          addXMLComponentFields(pDoc.get(), pMessageFieldNode.get(),

                                msgtype, *this, isRequired);

        }

        if(pMessageFieldNode->getName() == "group")

        {

          DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();

          std::string required;

          attrs->get("required", required);

          bool isRequired = (required == "Y" || required == "y");

          addXMLGroup(pDoc.get(), pMessageFieldNode.get(), msgtype, *this, isRequired);

        }

        RESET_AUTO_PTR(pMessageFieldNode,

                       pMessageFieldNode->getNextSiblingNode());

      }

    }

    RESET_AUTO_PTR(pMessageNode, pMessageNode->getNextSiblingNode());

  }

}

4、FIX Message parsing

QuickFIX Use in Message Class processing FIX news , stay Message.h as follows :

class Header : public FieldMap

{

  enum {  REQUIRED_FIELDS = 8 };

public:

  Header() : FieldMap( message_order( message_order::header ), REQUIRED_FIELDS )

  {}

  Header(const message_order & order) : FieldMap(order)

  {}

  void addGroup( const FIX::Group& group )

  {  FieldMap::addGroup( group.field(), group ); }

  void replaceGroup( unsigned num, const FIX::Group& group )

  {  FieldMap::replaceGroup( num, group.field(), group ); }

  Group& getGroup( unsigned num, FIX::Group& group ) const EXCEPT ( FieldNotFound )

  {  group.clear();

    return static_cast < Group& >

      ( FieldMap::getGroup( num, group.field(), group ) );

  }

  void removeGroup( unsigned num, const FIX::Group& group )

  {  FieldMap::removeGroup( num, group.field() ); }

  void removeGroup( const FIX::Group& group )

  {  FieldMap::removeGroup( group.field() ); }

  bool hasGroup( const FIX::Group& group ) const

  {  return FieldMap::hasGroup( group.field() ); }

  bool hasGroup( unsigned num, const FIX::Group& group ) const

  {  return FieldMap::hasGroup( num, group.field() ); }

};

class Trailer : public FieldMap

{

  enum {  REQUIRED_FIELDS = 1 };

public:

  Trailer() : FieldMap( message_order( message_order::trailer ), REQUIRED_FIELDS )

  {}

  Trailer(const message_order & order) : FieldMap(order)

  {}

  void addGroup( const FIX::Group& group )

  {  FieldMap::addGroup( group.field(), group ); }

  void replaceGroup( unsigned num, const FIX::Group& group )

  {  FieldMap::replaceGroup( num, group.field(), group ); }

  Group& getGroup( unsigned num, FIX::Group& group ) const EXCEPT ( FieldNotFound )

  {  group.clear();

    return static_cast < Group& >

      ( FieldMap::getGroup( num, group.field(), group ) );

  }

  void removeGroup( unsigned num, const FIX::Group& group )

  {  FieldMap::removeGroup( num, group.field() ); }

  void removeGroup( const FIX::Group& group )

  {  FieldMap::removeGroup( group.field() ); }

  bool hasGroup( const FIX::Group& group ) const

  {  return FieldMap::hasGroup( group.field() ); }

  bool hasGroup( unsigned num, const FIX::Group& group ) const

  {  return FieldMap::hasGroup( num, group.field() ); }

};

/**

 * Base class for all %FIX messages.

 *

 * A message consists of three field maps.  One for the header, the body,

 * and the trailer.

 */

class Message : public FieldMap

{

  friend class DataDictionary;

  friend class Session;

  enum field_type {  header, body, trailer };

public:

  Message();

  /// Construct message with a specified order of fields

  Message( const message_order& hdrOrder, const message_order& trlOrder,  const message_order& order);

  /// Construct a message from a string

  Message( const std::string& string, bool validate = true )

  EXCEPT ( InvalidMessage );

  /// Construct a message from a string using a data dictionary

  Message( const std::string& string, const FIX::DataDictionary& dataDictionary,

           bool validate = true )

  EXCEPT ( InvalidMessage );

  /// Construct a message from a string using a session and application data dictionary

  Message( const std::string& string, const FIX::DataDictionary& sessionDataDictionary,

           const FIX::DataDictionary& applicationDataDictionary, bool validate = true )

  EXCEPT ( InvalidMessage );

  /// Construct a message from a string using a data dictionary

  Message( const message_order& hdrOrder, const message_order& trlOrder,  const message_order& order, const std::string& string, const FIX::DataDictionary& dataDictionary,

           bool validate = true )

  EXCEPT ( InvalidMessage );

  /// Construct a message from a string using a session and application data dictionary

  Message( const message_order& hdrOrder, const message_order& trlOrder,  const message_order& order, const std::string& string, const FIX::DataDictionary& sessionDataDictionary,

           const FIX::DataDictionary& applicationDataDictionary, bool validate = true )

  EXCEPT ( InvalidMessage );

  Message( const Message& copy );

  ~Message();

  /// Set global data dictionary for encoding messages into XML

  static bool InitializeXML( const std::string& string );

  void addGroup( const FIX::Group& group )

  {  FieldMap::addGroup( group.field(), group ); }

  void replaceGroup( unsigned num, const FIX::Group& group )

  {  FieldMap::replaceGroup( num, group.field(), group ); }

  Group& getGroup( unsigned num, FIX::Group& group ) const EXCEPT ( FieldNotFound )

  {  group.clear();

    return static_cast < Group& >

      ( FieldMap::getGroup( num, group.field(), group ) );

  }

  void removeGroup( unsigned num, const FIX::Group& group )

  {  FieldMap::removeGroup( num, group.field() ); }

  void removeGroup( const FIX::Group& group )

  {  FieldMap::removeGroup( group.field() ); }

  bool hasGroup( const FIX::Group& group ) const

  {  return FieldMap::hasGroup( group.field() ); }

  bool hasGroup( unsigned num, const FIX::Group& group ) const

  {  return FieldMap::hasGroup( num, group.field() ); }

protected:

  // Constructor for derived classes

  Message( const BeginString& beginString, const MsgType& msgType );

public:

  /// Get a string representation of the message

  std::string toString( int beginStringField = FIELD::BeginString,

                        int bodyLengthField = FIELD::BodyLength,

                        int checkSumField = FIELD::CheckSum ) const;

  /// Get a string representation without making a copy

  std::string& toString( std::string&,

                         int beginStringField = FIELD::BeginString,

                         int bodyLengthField = FIELD::BodyLength,

                         int checkSumField = FIELD::CheckSum ) const;

  /// Get a XML representation of the message

  std::string toXML() const;

  /// Get a XML representation without making a copy

  std::string& toXML( std::string& ) const;

  /**

   * Add header informations depending on a source message.

   * This can be used to add routing informations like OnBehalfOfCompID

   * and DeliverToCompID to a message.

   */

  void reverseRoute( const Header& );

  /**

   * Set a message based on a string representation

   * This will fill in the fields on the message by parsing out the string

   * that is passed in.  It will return true on success and false

   * on failure.

   */

  void setString( const std::string& string )

  EXCEPT ( InvalidMessage )

  {  setString(string, true); }

  void setString( const std::string& string, bool validate )

  EXCEPT ( InvalidMessage )

  {  setString(string, validate, 0); }

  void setString( const std::string& string,

                  bool validate,

                  const FIX::DataDictionary* pDataDictionary )

  EXCEPT ( InvalidMessage )

  {  setString(string, validate, pDataDictionary, pDataDictionary); }

  void setString( const std::string& string,

                  bool validate,

                  const FIX::DataDictionary* pSessionDataDictionary,

                  const FIX::DataDictionary* pApplicationDataDictionary )

  EXCEPT ( InvalidMessage );

  void setGroup( const std::string& msg, const FieldBase& field,

                 const std::string& string, std::string::size_type& pos,

                 FieldMap& map, const DataDictionary& dataDictionary );

  /**

   * Set a messages header from a string

   * This is an optimization that can be used to get useful information

   * from the header of a FIX string without parsing the whole thing.

   */

  bool setStringHeader( const std::string& string );

  /// Getter for the message header

  const Header& getHeader() const {  return m_header; }

  /// Mutable getter for the message header

  Header& getHeader() {  return m_header; }

  /// Getter for the message trailer

  const Trailer& getTrailer() const {  return m_trailer; }

  /// Mutable getter for the message trailer

  Trailer& getTrailer() {  return m_trailer; }

  bool hasValidStructure(int& tag) const

  {  tag = m_tag;

    return m_validStructure;

  }

  int bodyLength( int beginStringField = FIELD::BeginString,

                  int bodyLengthField = FIELD::BodyLength,

                  int checkSumField = FIELD::CheckSum ) const

  {  return m_header.calculateLength(beginStringField, bodyLengthField, checkSumField)

           + calculateLength(beginStringField, bodyLengthField, checkSumField)

           + m_trailer.calculateLength(beginStringField, bodyLengthField, checkSumField);

  }

  int checkSum( int checkSumField = FIELD::CheckSum ) const

  {  return ( m_header.calculateTotal(checkSumField)

             + calculateTotal(checkSumField)

             + m_trailer.calculateTotal(checkSumField) ) % 256;

  }

  bool isAdmin() const

  {  

    MsgType msgType;

    if( m_header.getFieldIfSet( msgType ) )

      return isAdminMsgType( msgType );

    return false;

  }

  bool isApp() const

  {  

    MsgType msgType;

    if( m_header.getFieldIfSet( msgType ) )

      return !isAdminMsgType( msgType );

    return false;

  }

  bool isEmpty()

  {  return m_header.isEmpty() && FieldMap::isEmpty() && m_trailer.isEmpty(); }

  void clear()

  {

    m_tag = 0;

    m_validStructure = true;

    m_header.clear();

    FieldMap::clear();

    m_trailer.clear();

  }

  static bool isAdminMsgType( const MsgType& msgType )

  {  if ( msgType.getValue().length() != 1 ) return false;

    return strchr

           ( "0A12345",

             msgType.getValue().c_str() [ 0 ] ) != 0;

  }

  static ApplVerID toApplVerID(const BeginString& value)

  {

    if( value == BeginString_FIX40 )

      return ApplVerID(ApplVerID_FIX40);

    if( value == BeginString_FIX41 )

      return ApplVerID(ApplVerID_FIX41);

    if( value == BeginString_FIX42 )

      return ApplVerID(ApplVerID_FIX42);

    if( value == BeginString_FIX43 )

      return ApplVerID(ApplVerID_FIX43);

    if( value == BeginString_FIX44 )

      return ApplVerID(ApplVerID_FIX44);

    if( value == BeginString_FIX50 )

      return ApplVerID(ApplVerID_FIX50);

    if( value == "FIX.5.0SP1" )

      return ApplVerID(ApplVerID_FIX50SP1);

    if( value == "FIX.5.0SP2" )

      return ApplVerID(ApplVerID_FIX50SP2);

    return ApplVerID(ApplVerID(value));

  }

  static BeginString toBeginString( const ApplVerID& applVerID )

  {

    if( applVerID == ApplVerID_FIX40 )

      return BeginString(BeginString_FIX40);

    else if( applVerID == ApplVerID_FIX41 )

      return BeginString(BeginString_FIX41);

    else if( applVerID == ApplVerID_FIX42 )

      return BeginString(BeginString_FIX42);

    else if( applVerID == ApplVerID_FIX43 )

      return BeginString(BeginString_FIX43);

    else if( applVerID == ApplVerID_FIX44 )

      return BeginString(BeginString_FIX44);

    else if( applVerID == ApplVerID_FIX50 )

      return BeginString(BeginString_FIX50);

    else if( applVerID == ApplVerID_FIX50SP1 )

      return BeginString(BeginString_FIX50);

    else if( applVerID == ApplVerID_FIX50SP2 )

      return BeginString(BeginString_FIX50);

    else

      return BeginString("");

  }

  static bool isHeaderField( int field );

  static bool isHeaderField( const FieldBase& field,

                             const DataDictionary* pD = 0 );

  static bool isHeaderField( int field,

                             const DataDictionary* pD );

  static bool isTrailerField( int field );

  static bool isTrailerField( const FieldBase& field,

                              const DataDictionary* pD = 0 );

  static bool isTrailerField( int field,

                              const DataDictionary* pD );

  /// Returns the session ID of the intended recipient

  SessionID getSessionID( const std::string& qualifier = "" ) const

  EXCEPT ( FieldNotFound );

  /// Sets the session ID of the intended recipient

  void setSessionID( const SessionID& sessionID );

#ifdef HAVE_EMX

  void  setSubMessageType(const std::string & subMsgType) {  m_subMsgType.assign(subMsgType); }

  const std::string & getSubMessageType() const {  return m_subMsgType; }

#endif

private:

  FieldBase extractField(

    const std::string& string, std::string::size_type& pos,

    const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,

    const Group* pGroup = 0) const;

  static bool IsDataField(

    int field,

    const DataDictionary* pSessionDD,

    const DataDictionary* pAppDD )

  {

    if( (pSessionDD && pSessionDD->isDataField( field )) ||

        (pAppDD && pAppDD != pSessionDD && pAppDD->isDataField( field )) )

    {

      return true;

    }

    return false;

  }

  void validate() const;

  std::string toXMLFields(const FieldMap& fields, int space) const;

protected:

  mutable Header m_header;

  mutable Trailer m_trailer;

  bool m_validStructure;

  int m_tag;

#ifdef HAVE_EMX

  std::string m_subMsgType;

#endif

  static SmartPtr<DataDictionary> s_dataDictionary;

};

/*! @} */

inline std::ostream& operator <<

( std::ostream& stream, const Message& message )

{

  std::string str;

  stream << message.toString( str );

  return stream;

}

/// Parse the type of a message from a string.

inline MsgType identifyType( const std::string& message )

EXCEPT ( MessageParseError )

{

  std::string::size_type pos = message.find( "\001" "35=" );

  if ( pos == std::string::npos ) throw MessageParseError();

  std::string::size_type startValue = pos + 4;

  std::string::size_type soh = message.find_first_of( '\001', startValue );

  if ( soh == std::string::npos ) throw MessageParseError();

  std::string value = message.substr( startValue, soh - startValue );

  return MsgType( value );

}

Message.h As defined in Message Class inherits from class FieldMap, It's different FIX The protocol version implements Message Base class , And contains 3 individual FiledMap, They are message headers 、 Message body 、 Message tail .

FieldMap Class is Message Class base class , For storing and organizing FIX Message field set , Such as the message header 、 Message body 、 Message tail .

5、 Different FIX Protocol implementation

src/C++ Directory fix40、fix41、fix42、fix43、fix44、fix50、fix50sp1、fix50sp2、fixt11 It's for different FIX Implementation of protocol version , Its code is qualified with different namespace .FIX42 Of Message.h The documents are as follows :

namespace FIX42

{

  class Header : public FIX::Header

  {

  public:

    FIELD_SET(*this, FIX::BeginString);

    FIELD_SET(*this, FIX::BodyLength);

    FIELD_SET(*this, FIX::MsgType);

    FIELD_SET(*this, FIX::SenderCompID);

    FIELD_SET(*this, FIX::TargetCompID);

    FIELD_SET(*this, FIX::OnBehalfOfCompID);

    FIELD_SET(*this, FIX::DeliverToCompID);

    FIELD_SET(*this, FIX::SecureDataLen);

    FIELD_SET(*this, FIX::SecureData);

    FIELD_SET(*this, FIX::MsgSeqNum);

    FIELD_SET(*this, FIX::SenderSubID);

    FIELD_SET(*this, FIX::SenderLocationID);

    FIELD_SET(*this, FIX::TargetSubID);

    FIELD_SET(*this, FIX::TargetLocationID);

    FIELD_SET(*this, FIX::OnBehalfOfSubID);

    FIELD_SET(*this, FIX::OnBehalfOfLocationID);

    FIELD_SET(*this, FIX::DeliverToSubID);

    FIELD_SET(*this, FIX::DeliverToLocationID);

    FIELD_SET(*this, FIX::PossDupFlag);

    FIELD_SET(*this, FIX::PossResend);

    FIELD_SET(*this, FIX::SendingTime);

    FIELD_SET(*this, FIX::OrigSendingTime);

    FIELD_SET(*this, FIX::XmlDataLen);

    FIELD_SET(*this, FIX::XmlData);

    FIELD_SET(*this, FIX::MessageEncoding);

    FIELD_SET(*this, FIX::LastMsgSeqNumProcessed);

    FIELD_SET(*this, FIX::OnBehalfOfSendingTime);

  };

  class Trailer : public FIX::Trailer

  {

  public:

    FIELD_SET(*this, FIX::SignatureLength);

    FIELD_SET(*this, FIX::Signature);

    FIELD_SET(*this, FIX::CheckSum);

  };

  class Message : public FIX::Message

  {

  public:

    Message( const FIX::MsgType& msgtype )

    : FIX::Message(

      FIX::BeginString("FIX.4.2"), msgtype )

     {} 

    Message(const FIX::Message& m) : FIX::Message(m) {}

    Message(const Message& m) : FIX::Message(m) {}

    Header& getHeader() {  return (Header&)m_header; }

    const Header& getHeader() const {  return (Header&)m_header; }

    Trailer& getTrailer() {  return (Trailer&)m_trailer; }

    const Trailer& getTrailer() const {  return (Trailer&)m_trailer; }

  };

}

FIX42 Protocol resolution MessageCracker Class is defined as follows :

namespace FIX42

{

class MessageCracker

{

public:

    virtual ~MessageCracker() {}

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {}

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

    {}

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

    {}

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

    {}

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

    {}

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

    {}

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {}

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

    virtual void onMessage( Heartbeat&, const FIX::SessionID& ) {}

public:

    void crack( const Message& message,

                const FIX::SessionID& sessionID )

    {

        const std::string& msgTypeValue

            = message.getHeader().getField( FIX::FIELD::MsgType );

        if( msgTypeValue == "0" )

            onMessage( (const Heartbeat&)message, sessionID );

        else if( msgTypeValue == "1" )

            onMessage( (const TestRequest&)message, sessionID );

        else if( msgTypeValue == "2" )

            onMessage( (const ResendRequest&)message, sessionID );

        else if( msgTypeValue == "3" )

            onMessage( (const Reject&)message, sessionID );

        else if( msgTypeValue == "4" )

            onMessage( (const SequenceReset&)message, sessionID );

        else if( msgTypeValue == "5" )

            onMessage( (const Logout&)message, sessionID );

        else if( msgTypeValue == "6" )

            onMessage( (const IOI&)message, sessionID );

        else if( msgTypeValue == "7" )

            onMessage( (const Advertisement&)message, sessionID );

        else if( msgTypeValue == "8" )

            onMessage( (const ExecutionReport&)message, sessionID );

        else if( msgTypeValue == "9" )

            onMessage( (const OrderCancelReject&)message, sessionID );

        else if( msgTypeValue == "A" )

            onMessage( (const Logon&)message, sessionID );

        else if( msgTypeValue == "B" )

            onMessage( (const News&)message, sessionID );

        else if( msgTypeValue == "C" )

            onMessage( (const Email&)message, sessionID );

        else if( msgTypeValue == "D" )

            onMessage( (const NewOrderSingle&)message, sessionID );

        else if( msgTypeValue == "E" )

            onMessage( (const NewOrderList&)message, sessionID );

        else if( msgTypeValue == "F" )

            onMessage( (const OrderCancelRequest&)message, sessionID );

        else if( msgTypeValue == "G" )

            onMessage( (const OrderCancelReplaceRequest&)message, sessionID );

        else if( msgTypeValue == "H" )

            onMessage( (const OrderStatusRequest&)message, sessionID );

        else if( msgTypeValue == "J" )

            onMessage( (const Allocation&)message, sessionID );

        else if( msgTypeValue == "K" )

            onMessage( (const ListCancelRequest&)message, sessionID );

        else if( msgTypeValue == "L" )

            onMessage( (const ListExecute&)message, sessionID );

        else if( msgTypeValue == "M" )

            onMessage( (const ListStatusRequest&)message, sessionID );

        else if( msgTypeValue == "N" )

            onMessage( (const ListStatus&)message, sessionID );

        else if( msgTypeValue == "P" )

            onMessage( (const AllocationInstructionAck&)message, sessionID );

        else if( msgTypeValue == "Q" )

            onMessage( (const DontKnowTrade&)message, sessionID );

        else if( msgTypeValue == "R" )

            onMessage( (const QuoteRequest&)message, sessionID );

        else if( msgTypeValue == "S" )

            onMessage( (const Quote&)message, sessionID );

        else if( msgTypeValue == "T" )

            onMessage( (const SettlementInstructions&)message, sessionID );

        else if( msgTypeValue == "V" )

            onMessage( (const MarketDataRequest&)message, sessionID );

        else if( msgTypeValue == "W" )

            onMessage( (const MarketDataSnapshotFullRefresh&)message, sessionID );

        else if( msgTypeValue == "X" )

            onMessage( (const MarketDataIncrementalRefresh&)message, sessionID );

        else if( msgTypeValue == "Y" )

            onMessage( (const MarketDataRequestReject&)message, sessionID );

        else if( msgTypeValue == "Z" )

            onMessage( (const QuoteCancel&)message, sessionID );

        else if( msgTypeValue == "a" )

            onMessage( (const QuoteStatusRequest&)message, sessionID );

        else if( msgTypeValue == "b" )

            onMessage( (const QuoteAcknowledgement&)message, sessionID );

        else if( msgTypeValue == "c" )

            onMessage( (const SecurityDefinitionRequest&)message, sessionID );

        else if( msgTypeValue == "d" )

            onMessage( (const SecurityDefinition&)message, sessionID );

        else if( msgTypeValue == "e" )

            onMessage( (const SecurityStatusRequest&)message, sessionID );

        else if( msgTypeValue == "f" )

            onMessage( (const SecurityStatus&)message, sessionID );

        else if( msgTypeValue == "g" )

            onMessage( (const TradingSessionStatusRequest&)message, sessionID );

        else if( msgTypeValue == "h" )

            onMessage( (const TradingSessionStatus&)message, sessionID );

        else if( msgTypeValue == "i" )

            onMessage( (const MassQuote&)message, sessionID );

        else if( msgTypeValue == "j" )

            onMessage( (const BusinessMessageReject&)message, sessionID );

        else if( msgTypeValue == "k" )

            onMessage( (const BidRequest&)message, sessionID );

        else if( msgTypeValue == "l" )

            onMessage( (const BidResponse&)message, sessionID );

        else if( msgTypeValue == "m" )

            onMessage( (const ListStrikePrice&)message, sessionID );

        else onMessage( message, sessionID );

    }

    void crack( Message& message,

                const FIX::SessionID& sessionID )

    {

        FIX::MsgType msgType;

        message.getHeader().getField(msgType);

        std::string msgTypeValue = msgType.getValue();

        if( msgTypeValue == "0" )

            onMessage( (Heartbeat&)message, sessionID );

        else if( msgTypeValue == "1" )

            onMessage( (TestRequest&)message, sessionID );

        else if( msgTypeValue == "2" )

            onMessage( (ResendRequest&)message, sessionID );

        else if( msgTypeValue == "3" )

            onMessage( (Reject&)message, sessionID );

        else if( msgTypeValue == "4" )

            onMessage( (SequenceReset&)message, sessionID );

        else if( msgTypeValue == "5" )

            onMessage( (Logout&)message, sessionID );

        else if( msgTypeValue == "6" )

            onMessage( (IOI&)message, sessionID );

        else if( msgTypeValue == "7" )

            onMessage( (Advertisement&)message, sessionID );

        else if( msgTypeValue == "8" )

            onMessage( (ExecutionReport&)message, sessionID );

        else if( msgTypeValue == "9" )

            onMessage( (OrderCancelReject&)message, sessionID );

        else if( msgTypeValue == "A" )

            onMessage( (Logon&)message, sessionID );

        else if( msgTypeValue == "B" )

            onMessage( (News&)message, sessionID );

        else if( msgTypeValue == "C" )

            onMessage( (Email&)message, sessionID );

        else if( msgTypeValue == "D" )

            onMessage( (NewOrderSingle&)message, sessionID );

        else if( msgTypeValue == "E" )

            onMessage( (NewOrderList&)message, sessionID );

        else if( msgTypeValue == "F" )

            onMessage( (OrderCancelRequest&)message, sessionID );

        else if( msgTypeValue == "G" )

            onMessage( (OrderCancelReplaceRequest&)message, sessionID );

        else if( msgTypeValue == "H" )

            onMessage( (OrderStatusRequest&)message, sessionID );

        else if( msgTypeValue == "J" )

            onMessage( (Allocation&)message, sessionID );

        else if( msgTypeValue == "K" )

            onMessage( (ListCancelRequest&)message, sessionID );

        else if( msgTypeValue == "L" )

            onMessage( (ListExecute&)message, sessionID );

        else if( msgTypeValue == "M" )

            onMessage( (ListStatusRequest&)message, sessionID );

        else if( msgTypeValue == "N" )

            onMessage( (ListStatus&)message, sessionID );

        else if( msgTypeValue == "P" )

            onMessage( (AllocationInstructionAck&)message, sessionID );

        else if( msgTypeValue == "Q" )

            onMessage( (DontKnowTrade&)message, sessionID );

        else if( msgTypeValue == "R" )

            onMessage( (QuoteRequest&)message, sessionID );

        else if( msgTypeValue == "S" )

            onMessage( (Quote&)message, sessionID );

        else if( msgTypeValue == "T" )

            onMessage( (SettlementInstructions&)message, sessionID );

        else if( msgTypeValue == "V" )

            onMessage( (MarketDataRequest&)message, sessionID );

        else if( msgTypeValue == "W" )

            onMessage( (MarketDataSnapshotFullRefresh&)message, sessionID );

        else if( msgTypeValue == "X" )

            onMessage( (MarketDataIncrementalRefresh&)message, sessionID );

        else if( msgTypeValue == "Y" )

            onMessage( (MarketDataRequestReject&)message, sessionID );

        else if( msgTypeValue == "Z" )

            onMessage( (QuoteCancel&)message, sessionID );

        else if( msgTypeValue == "a" )

            onMessage( (QuoteStatusRequest&)message, sessionID );

        else if( msgTypeValue == "b" )

            onMessage( (QuoteAcknowledgement&)message, sessionID );

        else if( msgTypeValue == "c" )

            onMessage( (SecurityDefinitionRequest&)message, sessionID );

        else if( msgTypeValue == "d" )

            onMessage( (SecurityDefinition&)message, sessionID );

        else if( msgTypeValue == "e" )

            onMessage( (SecurityStatusRequest&)message, sessionID );

        else if( msgTypeValue == "f" )

            onMessage( (SecurityStatus&)message, sessionID );

        else if( msgTypeValue == "g" )

            onMessage( (TradingSessionStatusRequest&)message, sessionID );

        else if( msgTypeValue == "h" )

            onMessage( (TradingSessionStatus&)message, sessionID );

        else if( msgTypeValue == "i" )

            onMessage( (MassQuote&)message, sessionID );

        else if( msgTypeValue == "j" )

            onMessage( (BusinessMessageReject&)message, sessionID );

        else if( msgTypeValue == "k" )

            onMessage( (BidRequest&)message, sessionID );

        else if( msgTypeValue == "l" )

            onMessage( (BidResponse&)message, sessionID );

        else if( msgTypeValue == "m" )

            onMessage( (ListStrikePrice&)message, sessionID );

        else onMessage( message, sessionID );

    }

};

}

6、TCP Socket encapsulation

SocketConnection Class encapsulation TCP Socket Client connection related operations ,IO Operation and use Select,SocketConnection Class is defined as follows :

/// Encapsulates a socket file descriptor (single-threaded).

class SocketConnection : Responder

{

public:

  typedef std::set<SessionID> Sessions;

  SocketConnection( socket_handle s, Sessions sessions, SocketMonitor* pMonitor );

  SocketConnection( SocketInitiator&, const SessionID&, socket_handle, SocketMonitor* );

  virtual ~SocketConnection();

  socket_handle getSocket() const {  return m_socket; }

  Session* getSession() const {  return m_pSession; }

  bool read( SocketConnector& s );

  bool read( SocketAcceptor&, SocketServer& );

  bool processQueue();

  void signal()

  {

    Locker l( m_mutex );

    if( m_sendQueue.size() == 1 )

      m_pMonitor->signal( m_socket );

  }

  void unsignal()

  {

    Locker l( m_mutex );

    if( m_sendQueue.size() == 0 )

      m_pMonitor->unsignal( m_socket );

  }

  void onTimeout();

private:

  typedef std::deque<std::string, ALLOCATOR<std::string> >

    Queue;

  bool isValidSession();

  void readFromSocket() EXCEPT ( SocketRecvFailed );

  bool readMessage( std::string& msg );

  void readMessages( SocketMonitor& s );

  bool send( const std::string& );

  void disconnect();

  socket_handle m_socket;

  char m_buffer[BUFSIZ];

  Parser m_parser;

  Queue m_sendQueue;

  unsigned m_sendLength;

  Sessions m_sessions;

  Session* m_pSession;

  SocketMonitor* m_pMonitor;

  Mutex m_mutex;

  fd_set m_fds;

};

ThreadedSocketConnection Class encapsulates the multithreaded TCP Socket Client connection related operations ,IO Operation and use Select;SSLSocketConnection Class encapsulates support for SSL Of TCP Socket Client connection related operations ,IO Operation and use Select;ThreadedSSLSocketConnection Class encapsulates support for SSL And multithreading support TCP Socket Client connection related operations ,IO Operation and use Select.

SocketConnector Class encapsulation Socket The operation of connecting to the remote server .

SocketMonitor Class encapsulates the pair Socket Listening operations for events connected to a collection .

/// Monitors events on a collection of sockets.

class SocketMonitor

{

public:

    class Strategy;

    SocketMonitor( int timeout = 0 );

    virtual ~SocketMonitor();

    bool addConnect(socket_handle socket );

    bool addRead(socket_handle socket );

    bool addWrite(socket_handle socket );

    bool drop(socket_handle socket );

    void signal(socket_handle socket );

    void unsignal(socket_handle socket );

    void block( Strategy& strategy, bool poll = 0, double timeout = 0.0 );

    size_t numSockets()

    {

        return m_readSockets.size() - 1;

    }

private:

    typedef std::set < socket_handle > Sockets;

    typedef std::queue < socket_handle > Queue;

    void setsockopt();

    bool bind();

    bool listen();

    void buildSet( const Sockets&, fd_set& );

    inline timeval* getTimeval( bool poll, double timeout );

    inline bool sleepIfEmpty( bool poll );

    void processReadSet( Strategy&, fd_set& );

    void processWriteSet( Strategy&, fd_set& );

    void processExceptSet( Strategy&, fd_set& );

    int m_timeout;

    timeval m_timeval;

#ifndef SELECT_DECREMENTS_TIME

    clock_t m_ticks;

#endif

    socket_handle m_signal;

    socket_handle m_interrupt;

    Sockets m_connectSockets;

    Sockets m_readSockets;

    Sockets m_writeSockets;

    Queue m_dropped;

public:

    class Strategy

    {

    public:

        virtual ~Strategy()

        {}

        virtual void onConnect( SocketMonitor&, socket_handle socket ) = 0;

        virtual void onEvent( SocketMonitor&, socket_handle socket ) = 0;

        virtual void onWrite( SocketMonitor&, socket_handle socket ) = 0;

        virtual void onError( SocketMonitor&, socket_handle socket ) = 0;

        virtual void onError( SocketMonitor& ) = 0;

        virtual void onTimeout( SocketMonitor& )

        {}

    }

    ;

};
SocketServer Class encapsulation Socket Related operations implemented by the server ,SocketServer Class is defined as follows :

/// Listens for and accepts incoming socket connections on a port.

class SocketServer

{

public:

  class Strategy;

  SocketServer( int timeout = 0 );

  socket_handle add( int port, bool reuse = false, bool noDelay = false,

           int sendBufSize = 0, int rcvBufSize = 0 ) EXCEPT( SocketException& );

  socket_handle accept(socket_handle socket );

  void close();

  bool block( Strategy& strategy, bool poll = 0, double timeout = 0.0 );

  size_t numConnections() {  return m_monitor.numSockets() - 1; }

  SocketMonitor& getMonitor() {  return m_monitor; }

  int socketToPort(socket_handle socket );

  socket_handle portToSocket( int port );

private:

  typedef std::map<socket_handle, SocketInfo>

    SocketToInfo;

  typedef std::map<int, SocketInfo>

    PortToInfo;

  SocketToInfo m_socketToInfo;  

  PortToInfo m_portToInfo;

  SocketMonitor m_monitor;

public:

  class Strategy

  {

  public:

    virtual ~Strategy() {}

    virtual void onConnect( SocketServer&, socket_handle acceptSocket, socket_handle socket ) = 0;

    virtual void onWrite( SocketServer&, socket_handle socket ) = 0;

    virtual bool onData( SocketServer&, socket_handle socket ) = 0;

    virtual void onDisconnect( SocketServer&, socket_handle socket ) = 0;

    virtual void onError( SocketServer& ) = 0;

    virtual void onTimeout( SocketServer& ) {};

  };

};

7、FIX Session Configuration analysis

SessionSettings Class implements the FIX Session Profile parsing ,SessionSettings.h as follows :

class SessionSettings

{

public:

  SessionSettings() {  m_resolveEnvVars = false; }

  SessionSettings( std::istream& stream, bool resolveEnvVars = false ) EXCEPT ( ConfigError );

  SessionSettings( const std::string& file, bool resolveEnvVars = false ) EXCEPT ( ConfigError );

  /// Check if session setings are present

  const bool has( const SessionID& ) const;

  /// Get a dictionary for a session.

  const Dictionary& get( const SessionID& ) const EXCEPT ( ConfigError );

  /// Set a dictionary for a session

  void set( const SessionID&, Dictionary ) EXCEPT ( ConfigError );

  /// Get global default settings

  const Dictionary& get() const {  return m_defaults; }

  /// Set global default settings

  void set( const Dictionary& defaults ) EXCEPT ( ConfigError );

  /// Number of session settings

  size_t size() const {  return m_settings.size(); }

  typedef std::map < SessionID, Dictionary > Dictionaries;

  std::set < SessionID > getSessions() const;

private:

  void validate( const Dictionary& ) const EXCEPT ( ConfigError );

  Dictionaries m_settings;

  Dictionary m_defaults;

  bool m_resolveEnvVars;  // while reading, replace $var, $(var) and ${var} by environment variable var

  friend std::istream& operator>>( std::istream&, SessionSettings& ) EXCEPT ( ConfigError );

  friend std::ostream& operator<<( std::ostream&, const SessionSettings& );

};

8、FIX Session encapsulation

FIX::Session Provides FIX Session Related operations of , frequently-used sendToTarget The method statement is as follows :

static bool FIX::Session::sendToTarget( Message& message,

                                        const std::string& qualifier = "" )

EXCEPT ( SessionNotFound );

static bool FIX::Session::sendToTarget( Message& message,

                                        const SessionID& sessionID )

EXCEPT ( SessionNotFound );

static bool FIX::Session::sendToTarget( Message&,

                          const SenderCompID& senderCompID,

                          const TargetCompID& targetCompID,

                          const std::string& qualifier = "" )

EXCEPT ( SessionNotFound );

static bool FIX::Session::sendToTarget( Message& message,

                          const std::string& senderCompID,

                          const std::string& targetCompID,

                          const std::string& qualifier = "" )

EXCEPT ( SessionNotFound );

9、SocketInitiator

QuickFIX in ,Initiator The client is based on SocketConnection Client connection implementation ,SocketInitiator Class is defined as follows :

/// Socket implementation of Initiator.

class SocketInitiator : public Initiator, SocketConnector::Strategy

{

public:

  SocketInitiator( Application&, MessageStoreFactory&,

                   const SessionSettings& ) EXCEPT ( ConfigError );

  SocketInitiator( Application&, MessageStoreFactory&,

                   const SessionSettings&, LogFactory& ) EXCEPT ( ConfigError );

  virtual ~SocketInitiator();

private:

  typedef std::map < socket_handle, SocketConnection* > SocketConnections;

  typedef std::map < SessionID, int > SessionToHostNum;

  void onConfigure( const SessionSettings& ) EXCEPT ( ConfigError );

  void onInitialize( const SessionSettings& ) EXCEPT ( RuntimeError );

  void onStart();

  bool onPoll( double timeout );

  void onStop();

  void doConnect( const SessionID&, const Dictionary& d );

  void onConnect( SocketConnector&, socket_handle);

  void onWrite( SocketConnector&, socket_handle);

  bool onData( SocketConnector&, socket_handle);

  void onDisconnect( SocketConnector&, socket_handle);

  void onError( SocketConnector& );

  void onTimeout( SocketConnector& );

  void getHost( const SessionID&, const Dictionary&, std::string&, short&, std::string&, short& );

  SessionSettings m_settings;

  SessionToHostNum m_sessionToHostNum;

  SocketConnector m_connector;

  SocketConnections m_pendingConnections;

  SocketConnections m_connections;

  time_t m_lastConnect;

  int m_reconnectInterval;

  bool m_noDelay;

  int m_sendBufSize;

  int m_rcvBufSize;

};

SSLSocketInitiator It's supporting SSL Of Initiator Client implementation .

ThreadedSocketInitiator It supports multithreading Initiator Client implementation .

ThreadedSSLSocketInitiator It's supporting SSL And multithreaded Initiator Client implementation .

10、SocketAcceptor

QuickFIX in ,Acceptor Server based on SocketServer Realization .SocketAcceptor Class is defined as follows :

/// Socket implementation of Acceptor.

class SocketAcceptor : public Acceptor, SocketServer::Strategy

{

  friend class SocketConnection;

public:

  SocketAcceptor( Application&, MessageStoreFactory&,

                  const SessionSettings& ) EXCEPT ( ConfigError );

  SocketAcceptor( Application&, MessageStoreFactory&,

                  const SessionSettings&, LogFactory& ) EXCEPT ( ConfigError );

  virtual ~SocketAcceptor();

private:

  bool readSettings( const SessionSettings& );

  typedef std::set < SessionID > Sessions;

  typedef std::map < int, Sessions > PortToSessions;

  typedef std::map < socket_handle, SocketConnection* > SocketConnections;

  void onConfigure( const SessionSettings& ) EXCEPT ( ConfigError );

  void onInitialize( const SessionSettings& ) EXCEPT ( RuntimeError );

  void onStart();

  bool onPoll( double timeout );

  void onStop();

  void onConnect( SocketServer&, socket_handle, socket_handle );

  void onWrite( SocketServer&, socket_handle );

  bool onData( SocketServer&, socket_handle );

  void onDisconnect( SocketServer&, socket_handle );

  void onError( SocketServer& );

  void onTimeout( SocketServer& );

  SocketServer* m_pServer;

  PortToSessions m_portToSessions;

  SocketConnections m_connections;

};

SSLSocketAcceptor It's supporting SSL Of Acceptor Application implementation .

ThreadedSocketAcceptor It supports multithreading Acceptor Application implementation .

ThreadedSSLSocketAcceptor It's supporting SSL And multithreaded Acceptor Application implementation .

11、Fix Application

FIX::Application The interface is defined as follows :

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;

};

about FIX application development , In addition to the implementation FIX::Application Interface , It needs to be re implemented FIX::MessageCracker From the concrete FIX The protocol version is inherited from the implementation onMessage Method , Such as FIX42::MessageCracker Some interfaces are as follows :

class MessageCracker

{

public:

    virtual ~MessageCracker() {}

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

    virtual void onMessage( const Heartbeat&, const FIX::SessionID& ){}

    virtual void onMessage( const TestRequest&, const FIX::SessionID& ){}

    virtual void onMessage( const ResendRequest&, const FIX::SessionID& ){}

    virtual void onMessage( const Reject&, const FIX::SessionID& ){}

    virtual void onMessage( const SequenceReset&, const FIX::SessionID& ){}

    virtual void onMessage( const Logout&, const FIX::SessionID& ){}

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

    virtual void onMessage( const Logon&, const FIX::SessionID& ){}

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

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

    {

        throw FIX::UnsupportedMessageType();

    }

    virtual void onMessage( const BusinessMessageReject&, const FIX::SessionID& ){}

    virtual void onMessage( Heartbeat&, const FIX::SessionID& ) {}

    virtual void onMessage( TestRequest&, const FIX::SessionID& ) {}

    virtual void onMessage( ResendRequest&, const FIX::SessionID& ) {}

    virtual void onMessage( Reject&, const FIX::SessionID& ) {}

    virtual void onMessage( SequenceReset&, const FIX::SessionID& ) {}

    virtual void onMessage( Logout&, const FIX::SessionID& ) {}

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

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

    virtual void onMessage( Logon&, const FIX::SessionID& ) {}

    virtual void onMessage( NewOrderSingle&, const FIX::SessionID& ) {}

    virtual void onMessage( OrderCancelRequest&, const FIX::SessionID& ) {}

    virtual void onMessage( OrderStatusRequest&, const FIX::SessionID& ) {}

};

3、 ... and 、 The sample program

1、 Sample program introduction

QuickFIX The sample program is located at quickfix/examples Catalog .

ordermatch:FIX Transaction gateway service , Match the price limit list .

tradeclient : Console Trading Client .

tradeclientgui:Java GUI Trading Client .

executor: Return the transaction return for the received price limit order .

2、ordermatch

ordermatch Examples include IDGenerator、Order、OrderMatcher、Market、ordermatch、Application.

IDGenerator:ID generator

Order: Order class

OrderMatcher: Match the engine

Market: Order book

Application:FIX Application

ordermatch: Program entrance

IDGenerator.h file :

#ifndef IDGENERATOR_H

#define IDGENERATOR_H

#include <string>

#include <sstream>

class IDGenerator

{

public:

  IDGenerator() : m_orderID(0), m_executionID(0) 

  {

    

  }

  std::string genOrderID()

  {

    m_stream.clear();

    m_stream.str("");

    m_stream << ++m_orderID;

    return m_stream.str();

  }

  std::string genExecutionID()

  {

    m_stream.clear();

    m_stream.str("");

    m_stream << ++m_executionID;

    return m_stream.str();

  }

private:

  long m_orderID;

  long m_executionID;

  std::stringstream m_stream;

};

#endif

Order.h file :

#ifndef ORDER_H

#define ORDER_H

#include <string>

#include <iomanip>

#include <ostream>

class Order

{

  friend std::ostream& operator<<( std::ostream&, const Order& );

public:

  enum Side {  buy, sell };

  enum Type {  market, limit };

  Order( const std::string& clientId, const std::string& symbol,

         const std::string& owner, const std::string& target,

         Side side, Type type, double price, long quantity )

: m_clientId( clientId ), m_symbol( symbol ), m_owner( owner ),m_target( target ), 

m_side( side ), m_type( type ), m_price( price ),m_quantity( quantity )

  {

    m_openQuantity = m_quantity;

    m_executedQuantity = 0;

    m_avgExecutedPrice = 0;

    m_lastExecutedPrice = 0;

    m_lastExecutedQuantity = 0;

  }

  const std::string& getClientID() const 

  {  

    return m_clientId; 

  }

  const std::string& getSymbol() const 

  {  

    return m_symbol; 

  }

  const std::string& getOwner() const 

  {  

    return m_owner; 

  }

  const std::string& getTarget() const 

  {  

    return m_target; 

  }

  Side getSide() const 

  {  

    return m_side; 

  }

  Type getType() const 

  {

    return m_type; 

  }

  double getPrice() const 

  {  

    return m_price; 

  }

  long getQuantity() const 

  {  

    return m_quantity; 

  }

  long getOpenQuantity() const 

  {  

    return m_openQuantity; 

  }

  long getExecutedQuantity() const 

  {  

    return m_executedQuantity; 

  }

  double getAvgExecutedPrice() const 

  {  

    return m_avgExecutedPrice; 

  }

  double getLastExecutedPrice() const 

  {  

    return m_lastExecutedPrice; 

  }

  long getLastExecutedQuantity() const 

  {  

    return m_lastExecutedQuantity; 

  }

  bool isFilled() const 

  {  

    return m_quantity == m_executedQuantity; 

  }

  bool isClosed() const 

  {  

    return m_openQuantity == 0; 

  }

  void execute( double price, long quantity )

  {

    m_avgExecutedPrice =

      ( ( quantity * price ) + ( m_avgExecutedPrice * m_executedQuantity ) )

      / ( quantity + m_executedQuantity );

    m_openQuantity -= quantity;

    m_executedQuantity += quantity;

    m_lastExecutedPrice = price;

    m_lastExecutedQuantity = quantity;

  }

  void cancel()

  {

    m_openQuantity = 0;

  }

private:

  std::string m_clientId;//  client ID

  std::string m_symbol;// Ticker

  std::string m_owner;//  Local end

  std::string m_target;//  Target end

  Side m_side;//  Business direction

  Type m_type;//  Order type

  double m_price;//  Commission price

  long m_quantity;//  Number of consignments

  long m_openQuantity;

  long m_executedQuantity;

  double m_avgExecutedPrice;

  double m_lastExecutedPrice;

  long m_lastExecutedQuantity;

};

inline std::ostream& operator<<( std::ostream& ostream, const Order& order )

{

  return ostream

         << "ID: " <<  order.getClientID()

         << " Ticker: " << order.getSymbol()

         << " OWNER: " << order.getOwner()

         << " PRICE: " << order.getPrice()

         << " OPENQUANTITY: " << order.getOpenQuantity();

}

#endif

Market.h file :

#ifndef MARKET_H

#define MARKET_H

#include "Order.h"

#include <map>

#include <queue>

#include <string>

#include <functional>

class Market

{

public:

  //  Insert new order into order queue

  bool insert( const Order& order );

  //  Delete order from order queue

  void erase( const Order& order );

  //  Search for orders

  Order& find( Order::Side side, std::string id );

  //  Make a deal

  bool match( std::queue < Order > & );

  void display() const;

protected:

  void match( Order& bid, Order& ask );

private:

  typedef std::multimap < double, Order, std::greater < double > > BidOrders;//  Check , Descending order

  typedef std::multimap < double, Order, std::less < double > > AskOrders;//  vouchers of sale , Ascending sort

  BidOrders m_bidOrders;//  Order book : Pay line

  AskOrders m_askOrders;//  Order book : Order line

};

#endif

Market.cpp file :

#include "Market.h"

#include <iostream>

bool Market::insert( const Order& order )

{

  //  Check

  if ( order.getSide() == Order::buy )

    m_bidOrders.insert( BidOrders::value_type( order.getPrice(), order ) );

  else

    m_askOrders.insert( AskOrders::value_type( order.getPrice(), order ) );

  return true;

}

void Market::erase( const Order& order )

{

  std::string id = order.getClientID();

  //  Check

  if ( order.getSide() == Order::buy )

  {

    BidOrders::iterator i;

    for ( i = m_bidOrders.begin(); i != m_bidOrders.end(); ++i )

      if ( i->second.getClientID() == id )

      {

        m_bidOrders.erase( i );

        return ;

      }

  }

  //  vouchers of sale

  else if ( order.getSide() == Order::sell )

  {

    AskOrders::iterator i;

    for ( i = m_askOrders.begin(); i != m_askOrders.end(); ++i )

      if ( i->second.getClientID() == id )

      {

        m_askOrders.erase( i );

        return ;

      }

  }

}

bool Market::match( std::queue < Order > & orders )

{

  while ( true )

  {

    if ( !m_bidOrders.size() || !m_askOrders.size() )

      return orders.size() != 0;

    BidOrders::iterator iBid = m_bidOrders.begin();

    AskOrders::iterator iAsk = m_askOrders.begin();

    //  The price of the first tier in the buying queue is greater than or equal to the first tier price in the selling queue

    if ( iBid->second.getPrice() >= iAsk->second.getPrice() )

    {

      Order & bid = iBid->second;

      Order& ask = iAsk->second;

      match( bid, ask );

      orders.push( bid );

      orders.push( ask );

      if ( bid.isClosed() ) 

        m_bidOrders.erase( iBid );

      if ( ask.isClosed() )

        m_askOrders.erase( iAsk );

    }

    else

      return orders.size() != 0;

  }

}

Order& Market::find( Order::Side side, std::string id )

{

  //  Check

  if ( side == Order::buy )

  {

    BidOrders::iterator i;

    for ( i = m_bidOrders.begin(); i != m_bidOrders.end(); ++i )

      if ( i->second.getClientID() == id ) return i->second;

  }

  //  vouchers of sale

  else if ( side == Order::sell )

  {

    AskOrders::iterator i;

    for ( i = m_askOrders.begin(); i != m_askOrders.end(); ++i )

      if ( i->second.getClientID() == id ) return i->second;

  }

  throw std::exception();

}

void Market::match( Order& bid, Order& ask )

{

  double price = ask.getPrice();

  long quantity = 0;

  if ( bid.getOpenQuantity() > ask.getOpenQuantity() )

    quantity = ask.getOpenQuantity();

  else

    quantity = bid.getOpenQuantity();

  bid.execute( price, quantity );

  ask.execute( price, quantity );

}

void Market::display() const

{

  BidOrders::const_iterator iBid;

  AskOrders::const_iterator iAsk;

  std::cout << "BIDS:" << std::endl;

  for ( iBid = m_bidOrders.begin(); iBid != m_bidOrders.end(); ++iBid )

    std::cout << iBid->second << std::endl;

  std::cout << std::endl << std::endl;

  std::cout << "ASKS:" << std::endl;

  for ( iAsk = m_askOrders.begin(); iAsk != m_askOrders.end(); ++iAsk )

    std::cout << iAsk->second << std::endl;

}

OrderMatch.h file :

#ifndef ORDERMATCHER_H

#define ORDERMATCHER_H

#include "Market.h"

#include <map>

#include <iostream>

class OrderMatcher

{

  typedef std::map < std::string, Market > Markets;

public:

  //  Insert order

  bool insert( const Order& order )

  {

    Markets::iterator i = m_markets.find( order.getSymbol() );

    if ( i == m_markets.end() )

      i = m_markets.insert( std::make_pair( order.getSymbol(), Market() ) ).first;

    return i->second.insert( order );

  }

  //  Delete order

  void erase( const Order& order )

  {

    Markets::iterator i = m_markets.find( order.getSymbol() );

    if ( i == m_markets.end() ) 

      return ;

    i->second.erase( order );

  }

  //  Order search

  Order& find(const std::string symbol, Order::Side side, std::string id )

  {

    Markets::iterator i = m_markets.find( symbol );

    if ( i == m_markets.end() ) 

      throw std::exception();

    return i->second.find( side, id );

  }

  //  Make a deal

  bool match( const std::string symbol, std::queue < Order > & orders )

  {

    Markets::iterator i = m_markets.find( symbol );

    if ( i == m_markets.end() ) 

      return false;

    return i->second.match( orders );

  }

  bool match( std::queue < Order > & orders )

  {

    Markets::iterator i;

    for ( i = m_markets.begin(); i != m_markets.end(); ++i )

      i->second.match( orders );

    return orders.size() != 0;

  }

  void display( std::string symbol ) const

  {

    Markets::const_iterator i = m_markets.find( symbol );

    if ( i == m_markets.end() )

      return ;

    i->second.display();

  }

  void display() const

  {

    std::cout << "SYMBOLS:" << std::endl;

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

    Markets::const_iterator i;

    for ( i = m_markets.begin(); i != m_markets.end(); ++i )

    {

      i->second.display();

    }

  }

private:

  Markets m_markets;//  Market wide order book

};

#endif

Application.h file :

#ifndef APPLICATION_H

#define APPLICATION_H

#include "IDGenerator.h"

#include "OrderMatcher.h"

#include "Order.h"

#include <queue>

#include <iostream>

#include "quickfix/Application.h"

#include "quickfix/MessageCracker.h"

#include "quickfix/Values.h"

#include "quickfix/Utility.h"

#include "quickfix/Mutex.h"

#include "quickfix/fix42/NewOrderSingle.h"

#include "quickfix/fix42/OrderCancelRequest.h"

#include "quickfix/fix42/MarketDataRequest.h"

#include "quickfix/fix43/MarketDataRequest.h"

class Application

      : public FIX::Application,

        public FIX::MessageCracker

{

public:

  const OrderMatcher& orderMatcher() 

  {  

    return m_orderMatcher; 

  }

protected:

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

protected:

  // MessageCracker overloads

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

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

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

  void onMessage( const FIX43::MarketDataRequest&, const FIX::SessionID& );

protected:

  //  The order processing

  void processOrder( const Order& );

  //  Cancellation processing

  void processCancel( const std::string& id, const std::string& symbol, Order::Side );

  //  Return on orders

  void updateOrder( const Order&, char status );

  //  Rejection processing

  void rejectOrder( const Order& order )

  {  

    updateOrder( order, FIX::OrdStatus_REJECTED ); 

  }

  //  entrust ACK Return

  void acceptOrder( const Order& order )

  {  

    updateOrder( order, FIX::OrdStatus_NEW );

  }

  //  Transaction return

  void fillOrder( const Order& order )

  {

    updateOrder( order,

                 order.isFilled() ? FIX::OrdStatus_FILLED

                 : FIX::OrdStatus_PARTIALLY_FILLED );

  }

  //  Cancellation returns

  void cancelOrder( const Order& order )

  {  

    updateOrder( order, FIX::OrdStatus_CANCELED ); 

  }

  //  In return

  void rejectOrder( const FIX::SenderCompID&, const FIX::TargetCompID&,

                    const FIX::ClOrdID& clOrdID, const FIX::Symbol& symbol,

                    const FIX::Side& side, const std::string& message );

  //  take FIX The buying and selling direction of the message is converted to the buying and selling direction of the order

  Order::Side convert( const FIX::Side& );

  //  Change the order's buying and selling direction to FIX The direction of buying and selling news

  FIX::Side convert( Order::Side );

  //  take FIX The order type of the message is converted to the type of the order

  Order::Type convert( const FIX::OrdType& );

  //  Convert order type to FIX Order type for

  FIX::OrdType convert( Order::Type );

private:

  OrderMatcher m_orderMatcher;//  Order matching engine

  IDGenerator m_generator;// ID generator

};

#endif

Application.cpp file :

#include "config.h"

#include "Application.h"

#include "quickfix/Session.h"

#include "quickfix/fix42/ExecutionReport.h"

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

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

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 FIX42::NewOrderSingle& message, const FIX::SessionID& )

{

  FIX::SenderCompID senderCompID;

  FIX::TargetCompID targetCompID;

  FIX::ClOrdID clOrdID;

  FIX::Symbol symbol;

  FIX::Side side;

  FIX::OrdType ordType;

  FIX::Price price;

  FIX::OrderQty orderQty;

  FIX::TimeInForce timeInForce( FIX::TimeInForce_DAY );

  message.getHeader().get( senderCompID );

  message.getHeader().get( targetCompID );

  message.get( clOrdID );

  message.get( symbol );

  message.get( side );

  message.get( ordType );

  //  Price limit list

  if ( ordType == FIX::OrdType_LIMIT )

    message.get( price );

  message.get( orderQty );

  message.getFieldIfSet( timeInForce );

  try

  {

    if ( timeInForce != FIX::TimeInForce_DAY )

      throw std::logic_error( "Unsupported TIF, use Day" );

    Order order( clOrdID, symbol, senderCompID, targetCompID,

                 convert( side ), convert( ordType ),

                 price, (long)orderQty );

    //  The order processing

    processOrder( order );

  }

  catch ( std::exception & e )

  {

    //  Rejection processing

    rejectOrder( senderCompID, targetCompID, clOrdID, symbol, side, e.what() );

  }

}

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

{

  FIX::OrigClOrdID origClOrdID;

  FIX::Symbol symbol;

  FIX::Side side;

  message.get( origClOrdID );

  message.get( symbol );

  message.get( side );

  try

  {

    //  Cancellation processing

    processCancel( origClOrdID, symbol, convert( side ) );

  }

  catch ( std::exception& ) {}

}

void Application::onMessage( const FIX42::MarketDataRequest& message, const FIX::SessionID& )

{

  FIX::MDReqID mdReqID;

  FIX::SubscriptionRequestType subscriptionRequestType;

  FIX::MarketDepth marketDepth;

  FIX::NoRelatedSym noRelatedSym;

  FIX42::MarketDataRequest::NoRelatedSym noRelatedSymGroup;

  message.get( mdReqID );

  message.get( subscriptionRequestType );

  if ( subscriptionRequestType != FIX::SubscriptionRequestType_SNAPSHOT )

    EXCEPT( FIX::IncorrectTagValue( subscriptionRequestType.getField() ) );

  message.get( marketDepth );

  message.get( noRelatedSym );

  for ( int i = 1; i <= noRelatedSym; ++i )

  {

    FIX::Symbol symbol;

    message.getGroup( i, noRelatedSymGroup );

    noRelatedSymGroup.get( symbol );

  }

}

void Application::onMessage( const FIX43::MarketDataRequest& message, const FIX::SessionID& )

{

    std::cout << message.toXML() << std::endl;

}

void Application::updateOrder( const Order& order, char status )

{

  FIX::TargetCompID targetCompID( order.getOwner() );

  FIX::SenderCompID senderCompID( order.getTarget() );

  FIX42::ExecutionReport fixOrder

  ( FIX::OrderID ( order.getClientID() ),

    FIX::ExecID ( m_generator.genExecutionID() ),

    FIX::ExecTransType ( FIX::ExecTransType_NEW ),

    FIX::ExecType ( status ),

    FIX::OrdStatus ( status ),

    FIX::Symbol ( order.getSymbol() ),

    FIX::Side ( convert( order.getSide() ) ),

    FIX::LeavesQty ( order.getOpenQuantity() ),

    FIX::CumQty ( order.getExecutedQuantity() ),

    FIX::AvgPx ( order.getAvgExecutedPrice() ) 

  );

  fixOrder.set( FIX::ClOrdID( order.getClientID() ) );

  fixOrder.set( FIX::OrderQty( order.getQuantity() ) );

  if ( status == FIX::OrdStatus_FILLED ||

       status == FIX::OrdStatus_PARTIALLY_FILLED )

  {

    fixOrder.set( FIX::LastShares( order.getLastExecutedQuantity() ) );

    fixOrder.set( FIX::LastPx( order.getLastExecutedPrice() ) );

  }

  try

  {

    FIX::Session::sendToTarget( fixOrder, senderCompID, targetCompID );

  }

  catch ( FIX::SessionNotFound& ) {}

}

void Application::rejectOrder

( const FIX::SenderCompID& sender, const FIX::TargetCompID& target,

  const FIX::ClOrdID& clOrdID, const FIX::Symbol& symbol,

  const FIX::Side& side, const std::string& message )

{

  FIX::TargetCompID targetCompID( sender.getValue() );

  FIX::SenderCompID senderCompID( target.getValue() );

  FIX42::ExecutionReport fixOrder

  ( FIX::OrderID ( clOrdID.getValue() ),

    FIX::ExecID ( m_generator.genExecutionID() ),

    FIX::ExecTransType ( FIX::ExecTransType_NEW ),

    FIX::ExecType ( FIX::ExecType_REJECTED ),

    FIX::OrdStatus ( FIX::ExecType_REJECTED ),

    symbol, side, FIX::LeavesQty( 0 ), FIX::CumQty( 0 ), FIX::AvgPx( 0 ) 

  );

  fixOrder.set( clOrdID );

  fixOrder.set( FIX::Text( message ) );

  try

  {

    FIX::Session::sendToTarget( fixOrder, senderCompID, targetCompID );

  }

  catch ( FIX::SessionNotFound& ) {}

}

void Application::processOrder( const Order& order )

{

  if ( m_orderMatcher.insert( order ) )

  {

    //  Return on order confirmation

    acceptOrder( order );

    std::queue < Order > orders;

    //  Make a deal

    m_orderMatcher.match( order.getSymbol(), orders );

    //  Return on orders

    while ( orders.size() )

    {

      fillOrder( orders.front() );

      orders.pop();

    }

  }

  else

    rejectOrder( order );//  In return

}

void Application::processCancel( const std::string& id,

                                 const std::string& symbol, Order::Side side )

{

  Order & order = m_orderMatcher.find( symbol, side, id );

  order.cancel();

  cancelOrder( order );

  m_orderMatcher.erase( order );

}

Order::Side Application::convert( const FIX::Side& side )

{

  switch ( side )

  {

    case FIX::Side_BUY: 

      return Order::buy;

    case FIX::Side_SELL: 

      return Order::sell;

    default: 

      throw std::logic_error( "Unsupported Side, use buy or sell" );

  }

}

Order::Type Application::convert( const FIX::OrdType& ordType )

{

  switch ( ordType )

  {

    case FIX::OrdType_LIMIT: 

      return Order::limit;

    default: 

      throw std::logic_error( "Unsupported Order Type, use limit" );

  }

}

FIX::Side Application::convert( Order::Side side )

{

  switch ( side )

  {

    case Order::buy: 

      return FIX::Side( FIX::Side_BUY );

    case Order::sell: 

      return FIX::Side( FIX::Side_SELL );

    default: 

      throw std::logic_error( "Unsupported Side, use buy or sell" );

  }

}

FIX::OrdType Application::convert( Order::Type type )

{

  switch ( type )

  {

    case Order::limit:

      return FIX::OrdType( FIX::OrdType_LIMIT );

    default: 

      throw std::logic_error( "Unsupported Order Type, use limit" );

  }

}

ordermatch.cpp file :

#include "config.h"

#include "quickfix/FileStore.h"

#include "quickfix/SocketAcceptor.h"

#include "quickfix/SessionSettings.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 ];

  try

  {

    FIX::SessionSettings settings( file );

    Application application;

    FIX::FileStoreFactory storeFactory( settings );

    FIX::ScreenLogFactory logFactory( settings );

    FIX::SocketAcceptor acceptor( application, storeFactory, settings, logFactory );

    acceptor.start();

    while ( true )

    {

      application.orderMatcher().display();

      std::cout << std::endl;

      sleep(5);

    }

    acceptor.stop();

    return 0;

  }

  catch ( std::exception & e )

  {

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

    return 1;

  }

}

CMakeLists.txt file :

cmake_minimum_required(VERSION 3.10)

project(OrderMatch)

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_COMPILER "g++")

set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")

include_directories(/usr/local/include/quickfix)

link_directories(/usr/local/lib)

link_libraries(quickfix)

add_executable(ordermatch Application.cpp Market.cpp ordermatch.cpp)

Acceptor Session The configuration file :

[DEFAULT]

ConnectionType=acceptor

ReconnectInterval=60

SenderCompID=GATEWAY

FileStorePath=./log

SocketAcceptPort=8088

[SESSION]

BeginString=FIX.4.2

TargetCompID=CLIENT

UseLocalTime=Y

StartTime=00:00:00

EndTime=23:30:00

HeartBtInt=30

SocketReuseAddress=Y

UseDataDictionary=Y

DataDictionary=./FIX42.xml

ResetOnLogon=Y

3、tradeclient

tradeclient yes Initiator application .

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/fix42/NewOrderSingle.h"

#include "quickfix/fix42/ExecutionReport.h"

#include "quickfix/fix42/OrderCancelRequest.h"

#include "quickfix/fix42/OrderCancelReject.h"

#include "quickfix/fix42/OrderCancelReplaceRequest.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();

  void queryMarketDataRequest();

  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 == '4' )

        queryMarketDataRequest();

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

}

void Application::queryMarketDataRequest()

{

  int version = queryVersion();

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

  FIX::Message md;

  switch (version) {

  default:

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

    break;

  }

  FIX::Session::sendToTarget( md );

}

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

  }

}

tradeclient.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>

#include <unistd.h>

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;

  }

}

CMakeLists.txt file :

cmake_minimum_required(VERSION 3.10)

project(tradeclient)

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_COMPILER "g++")

set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")

include_directories(/usr/local/include/quickfix)

link_directories(/usr/local/lib)

link_libraries(quickfix)

add_executable(tradeclient Application.cpp tradeclient.cpp)

Initiator Session The configuration file :

[DEFAULT]

ConnectionType=initiator

ReconnectInterval=60

SenderCompID=CLIENT

FileStorePath=./log

[SESSION]

BeginString=FIX.4.2

TargetCompID=GATEWAY

UseLocalTime=Y

StartTime=00:00:00

EndTime=23:30:00

HeartBtInt=30

SocketConnectPort=8088

SocketConnectHost=192.168.0.102

UseDataDictionary=Y

DataDictionary=./FIX42.xml

原网站

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

随机推荐