Заголовок тега 8 добавляется к сообщению FIX, отправляемому получателю

Я новичок в технологии FIX и работаю над приложением FIX. Когда я отправляю сообщение NewOrderSingle, я получаю сообщение об ошибке.

Я использую движок QuickFix в C ++ и создаю новые заказы для отправки. Ниже приведен мой заказ, который я отправил на цель.

8 = FIX.4.2 | 9 = 157 | 35 = D | 34 = 180 | 49 = UTRADE | 52 = 20141030-08: 08: 08,660 | 56 = JFIX42 | 11 = Заказ1 | 15 = USD | 21 = 1 | 38 = 200 | 40 = 2 | 44 = 1 | 47 = А |
54 = 1 | 55 = ZVZZT | 59 = 0 | 60 = 20141030-08: 08: 08 | 100 = ARCA | 10 = 087

На стороне сервера (куда я отправляю заказ) говорится, что тег 8 добавляется после трейлера к вашему сообщению, поэтому мы отправляем отклонение. Сообщение на стороне сервера выглядит так:

8 = FIX.4.2 | 9 = 157 | 35 = D | 34 = 180 | 49 = UTRADE | 52 = 20141030-08: 08: 08,660 | 56 = JFIX42 | 11 = Заказ1 | 15 = USD | 21 = 1 | 38 = 200 | 40 = 2 | 44 = 1 | 47 = А | 54 = 1 | 55 = ZVZZT | 59 = 0 | 60 = 20141030-08: 08: 08 | 100 = ARCA | 10 = 087 | 8 = FIX.4

Может кто-нибудь, пожалуйста, помогите мне определить, в чем проблема?

Это мой базовый класс: —

Fix42Adapter::Fix42Adapter ()
{
}

ErrorCode Fix42Adapter::init( const std::string &configFile )
{
DEBUG_2("Starting fix42adapter with config file", configFile );
_settingsPtr.reset( new FIX::SessionSettings( configFile ) ) ;
_fileStoreFactoryPtr.reset( new FIX::FileStoreFactory( *_settingsPtr ) ) ;
_screenLogFactoryPtr.reset( new FIX::ScreenLogFactory( *_settingsPtr ) ) ;

DEBUG_1( "Setting initiator" ) ;
_initiatorPtr.reset( new FIX::SocketInitiator(
*this, *_fileStoreFactoryPtr, *_settingsPtr ) ) ;
DEBUG_1( "Done Setting initiator" ) ;

return _fixSessionHandler.init( *_settingsPtr ) ;
}

void Fix42Adapter::start ()
{
DEBUG_1("Starting fix42adapter ");
_initiatorPtr->start() ;
}
void Fix42Adapter::stop ()
{
DEBUG_1("Stopping fix42adapter ");
_initiatorPtr->stop() ;
}

void Fix42Adapter::onCreate( const FIX::SessionID& sessionId)
{
DEBUG_2("Created session id ", sessionId);
}

void Fix42Adapter::onLogon( const FIX::SessionID& sessionID )
{
DEBUG_2("Logged on ", sessionID);
}

void Fix42Adapter::onLogout( const FIX::SessionID& sessionID )
{
DEBUG_2("Logged out ", sessionID);
}
void Fix42Adapter::toAdmin( FIX::Message &message, const FIX::SessionID &sessionId )
{
FIX::MsgType lMsgType ;
message.getHeader().getField( lMsgType ) ;
// Logon message
if( lMsgType == FIX::MsgType_Logon )
{
//DEBUG_1("Fix42 Logon called ");
toAdmin( (FIX42::Logon&) message ) ;
}
//Logout message
if( lMsgType == FIX::MsgType_Logout )
{
//DEBUG_1("Fix42 Logout called ");
toAdmin( (FIX42::Logout&) message ) ;
}
//Heartbeat message
if( lMsgType == FIX::MsgType_Heartbeat )
{
//DEBUG_1("Fix42 Heartbeat called ");
toAdmin( (FIX42::Heartbeat&) message ) ;
}
#ifndef NDEBUG
UT::DismantleFix::dismantle( "OUTBOUND To EXCHANGE",
message.toString() ) ;
#endif
}
void Fix42Adapter::fromAdmin( const FIX::Message &message, const FIX::SessionID& )
throw( FIX::FieldNotFound,
FIX::IncorrectDataFormat,
FIX::IncorrectTagValue,
FIX::RejectLogon )
{
#ifndef NDEBUG
UT::DismantleFix::dismantle( "INBOUND From EXCHANGE",
message.toString() ) ;
#endif
}

void Fix42Adapter::toApp(FIX::Message &message, const FIX::SessionID& sessionId)
throw( FIX::DoNotSend )
{
FIX::MsgType lMsgType ;
message.getHeader().getField( lMsgType ) ;

if( lMsgType == FIX::MsgType_NewOrderSingle )
{
toApp( (FIX42::NewOrderSingle&) message ) ;
}
if( lMsgType == FIX::MsgType_OrderCancelRequest )
{
toApp( (FIX42::OrderCancelRequest&) message ) ;
}
if( lMsgType == FIX::MsgType_OrderCancelReplaceRequest )
{
toApp( (FIX42::OrderCancelReplaceRequest&) message ) ;
}
#ifndef NDEBUG
UT::DismantleFix::dismantle( "OUTBOUND TO EXCHANGE",
message.toString() ) ;
#endif
}

void Fix42Adapter::fromApp( const FIX::Message &message,
const FIX::SessionID& sessionID)
throw( FIX::FieldNotFound,
FIX::IncorrectDataFormat,
FIX::IncorrectTagValue,
FIX::UnsupportedMessageType )
{
#ifndef NDEBUG
UT::DismantleFix::dismantle( "INBOUND FROM EXCHANGE",
message.toString() ) ;
#endif
crack( message, sessionID );
}

ErrorCode Fix42Adapter::send( const FIX42::NewOrderSingle &order )
{
FIX42::NewOrderSingle newOrder( order ) ;

return _fixSessionHandler.sendNewOrder( newOrder, order.getHeader() ) ;
}
ErrorCode Fix42Adapter::send( const FIX42::OrderCancelRequest &order )
{
FIX42::OrderCancelRequest cancelRequest( order ) ;

return _fixSessionHandler.sendCancelOrder( cancelRequest,
order.getHeader() ) ;
}

ErrorCode Fix42Adapter::send( const FIX42::OrderCancelReplaceRequest &order )
{
FIX42::OrderCancelReplaceRequest replaceOrder( order );

return _fixSessionHandler.sendReplaceOrder( replaceOrder,
order.getHeader() ) ;
}

void Fix42Adapter::onMessage( const FIX42::ExecutionReport &message,
const FIX::SessionID &sessionId )
{
FIX42::ExecutionReport fixReport( message ) ;

FIX::OnBehalfOfCompID lOnBehalfOfCompID( sessionId.getSenderCompID() );
fixReport.getHeader().set( lOnBehalfOfCompID ) ;

OmsHandler::getInstance().sendToOms( fixReport ) ;
}
void Fix42Adapter::onMessage ( const FIX42::OrderCancelReject &message,
const FIX::SessionID &sessionId )
{
FIX42::OrderCancelReject cancelReject( message ) ;

FIX::OnBehalfOfCompID lOnBehalfOfCompID( sessionId.getSenderCompID() ) ;
cancelReject.getHeader().set( lOnBehalfOfCompID ) ;

OmsHandler::getInstance().sendToOms( cancelReject ) ;
}

void Fix42Adapter::onMessage( const FIX42::BusinessMessageReject &message,
const FIX::SessionID &sessionId )
{
FIX42::BusinessMessageReject reject( message ) ;

FIX::OnBehalfOfCompID lOnBehalfOfCompID( sessionId.getSenderCompID() ) ;
reject.getHeader().set( lOnBehalfOfCompID ) ;

OmsHandler::getInstance().sendToOms( reject ) ;
}

void Fix42Adapter::onMessage( const FIX42::News &, const FIX::SessionID& )
{
ERROR_1( MESSAGE_NOT_HANDLED, "News" ) ;
}

class Fix42Adapter
: public FIX::Application,
public FIX::MessageCracker
{
protected:

Fix42Adapter() ;

public :

ErrorCode init( const std::string &configFile ) ;

void stop ();

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 fromAdmin( const FIX::Message&, const FIX::SessionID& )
throw( FIX::FieldNotFound,
FIX::IncorrectDataFormat,
FIX::IncorrectTagValue,
FIX::RejectLogon );
void toApp( FIX::Message&, const FIX::SessionID& )
throw( FIX::DoNotSend ) ;

void fromApp( const FIX::Message& message,
const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound,
FIX::IncorrectDataFormat,
FIX::IncorrectTagValue,
FIX::UnsupportedMessageType );

ErrorCode send( const FIX42::NewOrderSingle &message ) ;

ErrorCode send( const FIX42::OrderCancelRequest &message ) ;

ErrorCode send( const FIX42::OrderCancelReplaceRequest &message ) ;

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

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

protected :virtual void toAdmin( FIX42::Logon & ) {}virtual void toAdmin( FIX42::Logout & ) {}virtual void toAdmin( FIX42::Heartbeat & ) {}
virtual void toApp( FIX42::NewOrderSingle & ) {}virtual void toApp( FIX42::OrderCancelRequest & ) {}virtual void toApp( FIX42::OrderCancelReplaceRequest & ) {}

private:

boost::shared_ptr< FIX::SessionSettings > _settingsPtr ;
boost::shared_ptr< FIX::FileStoreFactory > _fileStoreFactoryPtr ;
boost::shared_ptr< FIX::ScreenLogFactory > _screenLogFactoryPtr ;
boost::shared_ptr< FIX::SocketInitiator > _initiatorPtr ;

FixSessionHandler _fixSessionHandler ;
};

Это мой производный класс для обработки определенных полей для сервера:

  XyzAdapter::XyzAdapter()
{
}

void XyzAdapter::toAdmin( FIX42::Logon& message )
{
}

void XyzAdapter::toAdmin( FIX42::Logout& message )
{
}

void XyzAdapter::toAdmin( FIX42::Heartbeat& message )
{
}
void XyzAdapter::toApp( FIX42::NewOrderSingle& message )
{
//Removes NOT required fields.
message.removeField ( FIX::FIELD::SymbolSfx ) ;
message.removeField ( FIX::FIELD::SecurityType ) ;
message.removeField ( FIX::FIELD::SettlmntTyp ) ;
message.removeField ( FIX::FIELD::MaxFloor ) ;
message.removeField ( FIX::FIELD::CustomerOrFirm ) ;
message.removeField ( FIX::FIELD::NoTradingSessions ) ;
message.removeField( FIX::FIELD::TradingSessionID );
message.removeField( FIX::FIELD::SecurityExchange );
message.removeField( FIX::FIELD::Account );
message.removeField( FIX::FIELD::SecurityID );

//Removes custom tags.
message.removeField( CUSTOMTAGS::AlgorithmType );
message.removeField( CUSTOMTAGS::ParentOrderId );
message.removeField( CUSTOMTAGS::UserId );
message.removeField( CUSTOMTAGS::ExchCreateTime );
message.removeField( CUSTOMTAGS::ExchModifyTime );
message.removeField( CUSTOMTAGS::ProductType );
message.removeField( CUSTOMTAGS::SquareOff );
message.removeField( CUSTOMTAGS::SeqNum );
message.set( FIX::ClOrdID("Order1") );
message.set( FIX::ExDestination("ARCA") );
message.set( FIX::Symbol("ZVZZT") );
message.set( FIX::Currency("USD") );
message.set( FIX::Rule80A('A') );
message.set( FIX::TimeInForce( FIX::TimeInForce_DAY ) );
}

void XyzAdapter::toApp( FIX42::OrderCancelRequest& message )
{
}

void XyzAdapter::toApp( FIX42::OrderCancelReplaceRequest& message )
{
}

class XyzAdapter : public Fix42Adapter
{
public:
/**
*  @brief Default constructor.
*/
XyzAdapter ();

virtual void toAdmin( FIX42::Logon& ) ;
virtual void toAdmin( FIX42::Logout& ) ;
virtual void toAdmin( FIX42::Heartbeat& ) ;
virtual void toApp( FIX42::NewOrderSingle& ) ;
virtual void toApp( FIX42::OrderCancelRequest& );
virtual void toApp( FIX42::OrderCancelReplaceRequest& ) ;
};

-1

Решение

Что-то не так в расчете размера сообщения. Твое сообщение:

8=FIX.4.2|9=157|35=D|34=180|49=UTRADE|52=20141030-08:08:08.660|56=JFIX42|11=Order1|15=USD|21=1|38=200|40=2|44=1|47=A| 54=1|55=ZVZZT|59=0|60=20141030-08:08:08|100=ARCA|10=087

определяет размер 157 (тег 9, который подсчитывает размер, начинающийся сразу после значения тега 9 и разделителя и вплоть до разделителя непосредственно перед последним тегом 10. Таким образом, тег 9 говорит, что эта часть сообщения:

35=D|34=180|49=UTRADE|52=20141030-08:08:08.660|56=JFIX42|11=Order1|15=USD|21=1|38=200|40=2|44=1|47=A| 54=1|55=ZVZZT|59=0|60=20141030-08:08:08|100=ARCA|

157 байт, тогда как на самом деле это 150. Сервер полагается на это число и, таким образом, читает 157 (что вы предоставляете) + 7 («10 = XXX |», контрольная сумма всегда 3 байта) и заканчивается вашим сообщением плюс 7 байтов из следующего.

0

Другие решения


По вопросам рекламы [email protected]