LCOV - code coverage report
Current view: top level - include/fix - fix_message_builder.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.7 % 56 48
Test Date: 2025-12-19 03:13:09 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /**
       2              :  * @file fix_message_builder.hpp
       3              :  * @brief FIX 消息构建辅助函数
       4              :  *
       5              :  * 提供将内部数据结构转换为 FIX 消息的辅助函数。
       6              :  */
       7              : 
       8              : #pragma once
       9              : 
      10              : #include "fix/fix_codec.hpp"
      11              : #include "fix/fix_tags.hpp"
      12              : #include "app/model/order.hpp"
      13              : #include <sstream>
      14              : #include <iomanip>
      15              : #include <ctime>
      16              : 
      17              : namespace fix40 {
      18              : 
      19              : /**
      20              :  * @brief 格式化 UTC 时间为 FIX 格式
      21              :  * @param tp 时间点
      22              :  * @return std::string FIX 格式时间字符串 (YYYYMMDD-HH:MM:SS)
      23              :  */
      24          705 : inline std::string formatTransactTime(std::chrono::system_clock::time_point tp) {
      25          705 :     auto time_t_val = std::chrono::system_clock::to_time_t(tp);
      26              :     std::tm tm_buf;
      27          705 :     gmtime_r(&time_t_val, &tm_buf);
      28              :     
      29          705 :     std::ostringstream oss;
      30          705 :     oss << std::put_time(&tm_buf, "%Y%m%d-%H:%M:%S");
      31         1410 :     return oss.str();
      32          705 : }
      33              : 
      34              : /**
      35              :  * @brief 将 OrderSide 转换为 FIX 字符串
      36              :  */
      37          805 : inline std::string sideToFix(OrderSide side) {
      38         1610 :     return side == OrderSide::BUY ? "1" : "2";
      39              : }
      40              : 
      41              : /**
      42              :  * @brief 将 OrderType 转换为 FIX 字符串
      43              :  */
      44          805 : inline std::string ordTypeToFix(OrderType type) {
      45         1610 :     return type == OrderType::MARKET ? "1" : "2";
      46              : }
      47              : 
      48              : /**
      49              :  * @brief 将 OrderStatus 转换为 FIX 字符串
      50              :  */
      51          805 : inline std::string ordStatusToFix(OrderStatus status) {
      52          805 :     switch (status) {
      53          783 :         case OrderStatus::NEW: return "0";
      54          456 :         case OrderStatus::PARTIALLY_FILLED: return "1";
      55          177 :         case OrderStatus::FILLED: return "2";
      56          483 :         case OrderStatus::CANCELED: return "4";
      57            0 :         case OrderStatus::PENDING_CANCEL: return "6";
      58          516 :         case OrderStatus::REJECTED: return "8";
      59            0 :         case OrderStatus::PENDING_NEW: return "A";  // FIX 4.2+, 但为了兼容
      60            0 :         default: return "0";
      61              :     }
      62              : }
      63              : 
      64              : /**
      65              :  * @brief 将 ExecTransType 转换为 FIX 字符串
      66              :  */
      67          705 : inline std::string execTransTypeToFix(ExecTransType type) {
      68          705 :     switch (type) {
      69         2115 :         case ExecTransType::NEW: return "0";
      70            0 :         case ExecTransType::CANCEL: return "1";
      71            0 :         case ExecTransType::CORRECT: return "2";
      72            0 :         case ExecTransType::STATUS: return "3";
      73            0 :         default: return "0";
      74              :     }
      75              : }
      76              : 
      77              : /**
      78              :  * @brief 将 ExecutionReport 转换为 FIX 消息
      79              :  * @param report ExecutionReport 结构
      80              :  * @return FixMessage FIX 消息对象
      81              :  *
      82              :  * 构建 FIX 4.0 ExecutionReport (MsgType=8) 消息。
      83              :  */
      84          705 : inline FixMessage buildExecutionReport(const ExecutionReport& report) {
      85          705 :     FixMessage msg;
      86              :     
      87              :     // MsgType = 8 (ExecutionReport)
      88          705 :     msg.set(tags::MsgType, "8");
      89              :     
      90              :     // 标识符
      91          705 :     msg.set(tags::OrderID, report.orderID);
      92          705 :     msg.set(tags::ClOrdID, report.clOrdID);
      93          705 :     msg.set(tags::ExecID, report.execID);
      94              :     
      95          705 :     if (!report.origClOrdID.empty()) {
      96          100 :         msg.set(tags::OrigClOrdID, report.origClOrdID);
      97              :     }
      98              :     
      99              :     // 执行信息
     100          705 :     msg.set(tags::ExecTransType, execTransTypeToFix(report.execTransType));
     101          705 :     msg.set(tags::OrdStatus, ordStatusToFix(report.ordStatus));
     102              :     
     103              :     // 订单信息
     104          705 :     msg.set(tags::Symbol, report.symbol);
     105          705 :     msg.set(tags::Side, sideToFix(report.side));
     106          705 :     msg.set(tags::OrderQty, std::to_string(report.orderQty));
     107              :     
     108          705 :     if (report.ordType == OrderType::LIMIT && report.price > 0) {
     109          623 :         msg.set(tags::Price, std::to_string(report.price));
     110              :     }
     111          705 :     msg.set(tags::OrdType, ordTypeToFix(report.ordType));
     112              :     
     113              :     // 成交信息
     114          705 :     msg.set(tags::CumQty, std::to_string(report.cumQty));
     115          705 :     msg.set(tags::AvgPx, std::to_string(report.avgPx));
     116              :     
     117          705 :     if (report.lastShares > 0) {
     118          101 :         msg.set(tags::LastShares, std::to_string(report.lastShares));
     119          101 :         msg.set(tags::LastPx, std::to_string(report.lastPx));
     120              :     }
     121              :     
     122              :     // 剩余数量(FIX 4.0 没有 LeavesQty,但可以通过 OrderQty - CumQty 计算)
     123              :     // 这里我们用 Text 字段传递额外信息
     124              :     
     125              :     // 时间
     126          705 :     msg.set(tags::TransactTime, formatTransactTime(report.transactTime));
     127              :     
     128              :     // 拒绝原因
     129          705 :     if (report.ordStatus == OrderStatus::REJECTED && report.ordRejReason != 0) {
     130          103 :         msg.set(tags::OrdRejReason, std::to_string(report.ordRejReason));
     131              :     }
     132              :     
     133              :     // 文本说明
     134          705 :     if (!report.text.empty()) {
     135          104 :         msg.set(tags::Text, report.text);
     136              :     }
     137              :     
     138          705 :     return msg;
     139            0 : }
     140              : 
     141              : } // namespace fix40
        

Generated by: LCOV version 2.0-1