You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QuickFIX C++:发送MarketDataRequest后服务器无响应求助

FIX协议与QuickFIX问题排查:发送MarketDataRequest无响应

我是FIX协议与QuickFIX的新手,成功运行QuickFIX官方仓库的tradingclient示例后,自行构建了Initiator类。连接状态正常(能看到指定间隔的心跳包),配置文件与官方示例一致且能正常获取行情,但发送MarketDataRequest后服务器无任何响应,也未抛出异常。以下是我的代码及运行输出:

FIXTrader.h

#pragma once

#include <quickfix/Session.h>
#include <quickfix/MessageCracker.h>
#include <quickfix/Values.h>
#include <quickfix/Mutex.h>

#include <quickfix/fix43/MarketDataRequest.h>

#include <queue>

namespace FIX
{
    class FIXTrader: public Application, MessageCracker
    {
    public:
        virtual ~FIXTrader() {};
        void run();

    private:

        void onCreate(const SessionID&);
        void onLogon(const SessionID&);
        void onLogout(const SessionID&);
        void toAdmin(Message&, const SessionID&);
        void toApp(Message&, const SessionID&)
            throw(DoNotSend);
        void fromAdmin(const Message&, const SessionID&)
            throw(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon);
        void fromApp(const Message&, const SessionID&)
            throw(FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType);

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

        FIX43::MarketDataRequest queryMarketDataRequest43();

        void queryHeader(FIX::Header& header);
    };
}

#pragma comment(lib, "ws2_32.lib")

FIXTrader.cpp相关代码

void FIX::FIXTrader::onMessage
(const FIX43::ExecutionReport&, const FIX::SessionID&) {}
void FIX::FIXTrader::onMessage
(const FIX43::OrderCancelReject&, const FIX::SessionID&) {}
void FIX::FIXTrader::onMessage
(const FIX43::MarketDataRequest&, const FIX::SessionID&)
{
    std::cout << "request success" << std::endl;
}
void FIX::FIXTrader::onMessage
(const FIX43::MarketDataRequestReject&, const FIX::SessionID&)
{
    std::cout << "request rejected" << std::endl;
}


FIX43::MarketDataRequest FIX::FIXTrader::queryMarketDataRequest43()
{
    FIX::MDReqID mdReqID("MARKETDATAID");
    FIX::SubscriptionRequestType subType(FIX::SubscriptionRequestType_SNAPSHOT_PLUS_UPDATES);
    FIX::MarketDepth marketDepth(0);

    FIX43::MarketDataRequest::NoMDEntryTypes marketDataEntryGroup;
    FIX::MDEntryType mdEntryType(FIX::MDEntryType_BID);
    marketDataEntryGroup.set(mdEntryType);

    FIX43::MarketDataRequest::NoRelatedSym symbolGroup;
    FIX::Symbol symbol("EURUSD.x");
    symbolGroup.set(symbol);

    FIX43::MarketDataRequest message(mdReqID, subType, marketDepth);
    message.addGroup(marketDataEntryGroup);
    message.addGroup(symbolGroup);

    queryHeader(message.getHeader());

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

    return message;
}

void FIX::FIXTrader::run()
{
    try
    {
        FIX::Message md = queryMarketDataRequest43();
        std::cout << "Sending marketrequest" << std::endl;
        std::cout << "sendToTarget() => " << FIX::Session::sendToTarget(md) << std::endl;
        std::cout << "Sent marketrequest" << std::endl;
        while (_getwch() != 126);
    }
    catch (std::exception& e)
    {
        std::cout << "Message Not Sent: " << e.what();
    }
}

main函数

#include "FixTrader.h"
#include <quickfix/FileStore.h>
#include <quickfix/FileLog.h>
#include <quickfix/SocketInitiator.h>
#include <quickfix/SessionSettings.h>
#include <quickfix/config.h>

// #include "quickfix/Application.h"

int main(int argc, char** argv)
{
    try
    {
        if (argc < 2) return 1;
        std::string fileName = argv[1];

        FIX::SessionSettings settings(fileName);

        FIX::FIXTrader trader_app;
        FIX::FileStoreFactory storeFactory(settings);
        FIX::FileLogFactory logFactory(settings);
        FIX::SocketInitiator initiator
        (trader_app, storeFactory, settings, logFactory /*optional*/);
        initiator.start();
        trader_app.run();
        initiator.stop();
        return 0;
    }
    catch (FIX::ConfigError& e)
    {
        std::cout << e.what();
        return 1;
    }
}

运行输出

C:\fix_trader\Release>fix_trader.exe configfile.txt
<message>
<header>
<field number="8"><![CDATA[FIX.4.3]]></field>
<field number="35"><![CDATA[V]]></field>
<field number="49"><![CDATA[***]]></field>
<field number="56"><![CDATA[****]]></field>
</header>
<body>
<field number="146"><![CDATA[1]]></field>
<field number="262"><![CDATA[MARKETDATAID]]></field>
<field number="263"><![CDATA[1]]></field>
<field number="264"><![CDATA[0]]></field>
<field number="267"><![CDATA[1]]></field>
<group>
<field number="55"><![CDATA[EURUSD.x]]></field>
</group>
<group>
<field number="269"><![CDATA[0]]></field>
</group>
</body>
<trailer>
</trailer>
</message>
8=FIX.4.3 9=79 35=V 49=*** 56=**** 146=1 55=EURUSD.x 262=MARKETDATAID 263=1 264=0 267=1 269=0 10=223 
Sending marketrequest
OUT: 8=FIX.4.3 9=109 35=V 34=5 49=*** 52=20220924-07:35:58.000 56=**** 146=1 55=EURUSD.x 262=MARKETDATAID 263=1 264=0 267=1 269=0 10=184 
sendToTarget() => 1
Sent marketrequest
fromAdmin: 8=FIX.4.3 9=62 35=A 34=1 49=**** 52=20220924-07:35:58.404 56=*** 98=0 108=30 10=234 
Logon successful! Session ID: FIX.4.3:***->****
fromAdmin: 8=FIX.4.3 9=50 35=0 34=2 49=**** 52=20220924-07:36:28.662 56=*** 10=194 
fromAdmin: 8=FIX.4.3 9=50 35=0 34=3 49=**** 52=20220924-07:36:58.682 56=*** 10=200 
fromAdmin: 8=FIX.4.3 9=50 35=5 34=4 49=**** 52=20220924-07:37:06.188 56=*** 10=201 
Logged out from session: FIX.4.3:***->**** 

问题排查与解决方案

  1. 消息组顺序不符合FIX规范
    从输出的消息结构可以看到,NoRelatedSym(含55字段的组)出现在NoMDEntryTypes(含269字段的组)之前,但FIX 4.3规范要求MarketDataRequest的组顺序是先NoMDEntryTypes,再NoRelatedSym。
    建议移除手动设置Header的queryHeader函数——QuickFIX会自动填充SenderCompID、TargetCompID等必要Header字段,手动修改容易打乱消息内部结构。

  2. 未实现MessageCracker的消息分发逻辑
    你的FIXTrader继承了MessageCracker,但fromApp方法未调用crack方法,导致服务器返回的行情消息无法路由到对应的onMessage处理函数。补充实现:

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

    同时需要添加行情响应消息的处理函数,否则即使收到响应也无法感知:

    void FIX::FIXTrader::onMessage(const FIX43::MarketDataSnapshotFullRefresh&, const FIX::SessionID&)
    {
        std::cout << "Received market data snapshot" << std::endl;
    }
    
    void FIX::FIXTrader::onMessage(const FIX43::MarketDataIncrementalRefresh&, const FIX::SessionID&)
    {
        std::cout << "Received market data incremental update" << std::endl;
    }
    
  3. 发送消息时机过早
    当前代码在Initiator启动后立刻发送请求,此时会话可能未完全建立。建议将请求发送逻辑移到onLogon方法中,确保登录成功后再发送:

    void FIX::FIXTrader::onLogon(const SessionID& sessionID)
    {
        std::cout << "Logon successful! Session ID: " << sessionID << std::endl;
        try
        {
            FIX43::MarketDataRequest md = queryMarketDataRequest43();
            FIX::Session::sendToTarget(md, sessionID);
            std::cout << "Sent marketrequest after logon" << std::endl;
        }
        catch (std::exception& e)
        {
            std::cout << "Message Not Sent: " << e.what();
        }
    }
    

    对应的run函数只保留等待逻辑:

    void FIX::FIXTrader::run()
    {
        while (_getwch() != 126);
    }
    
  4. MDReqID唯一性检查
    部分服务器会拒绝重复的MDReqID请求,建议使用带时间戳的唯一ID,比如:

    FIX::MDReqID mdReqID("MARKETDATAID_" + std::to_string(time(nullptr)));
    

内容的提问来源于stack exchange,提问作者Karthik Sivasubramaniam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:05:34