Line data Source code
1 : /**
2 : * @file market_data_snapshot.hpp
3 : * @brief 行情快照数据结构
4 : *
5 : * 定义用于撮合判断的行情快照数据结构,包含买卖盘口信息。
6 : * 撮合引擎使用此结构判断订单是否可以成交。
7 : */
8 :
9 : #pragma once
10 :
11 : #include <string>
12 : #include <cstdint>
13 : #include <chrono>
14 :
15 : namespace fix40 {
16 :
17 : // ============================================================================
18 : // 行情快照结构
19 : // ============================================================================
20 :
21 : /**
22 : * @struct MarketDataSnapshot
23 : * @brief 合约行情快照
24 : *
25 : * 存储合约的实时行情数据,用于撮合引擎判断订单成交条件。
26 : * 数据来源于 CTP 行情推送,经过转换后存储在此结构中。
27 : *
28 : * @par 撮合规则
29 : * - 买单成交条件:买价 >= 卖一价(askPrice1)
30 : * - 卖单成交条件:卖价 <= 买一价(bidPrice1)
31 : *
32 : * @par 使用示例
33 : * @code
34 : * MarketDataSnapshot snapshot;
35 : * snapshot.instrumentId = "IF2601";
36 : * snapshot.lastPrice = 4000.0;
37 : * snapshot.bidPrice1 = 3999.8;
38 : * snapshot.bidVolume1 = 100;
39 : * snapshot.askPrice1 = 4000.2;
40 : * snapshot.askVolume1 = 50;
41 : *
42 : * if (snapshot.isValid()) {
43 : * // 可以用于撮合判断
44 : * }
45 : * @endcode
46 : */
47 : struct MarketDataSnapshot {
48 : // -------------------------------------------------------------------------
49 : // 标识符
50 : // -------------------------------------------------------------------------
51 : std::string instrumentId; ///< 合约代码(如 "IF2601")
52 :
53 : // -------------------------------------------------------------------------
54 : // 价格信息
55 : // -------------------------------------------------------------------------
56 : double lastPrice; ///< 最新价
57 : double bidPrice1; ///< 买一价(最高买价)
58 : int32_t bidVolume1; ///< 买一量
59 : double askPrice1; ///< 卖一价(最低卖价)
60 : int32_t askVolume1; ///< 卖一量
61 :
62 : // -------------------------------------------------------------------------
63 : // 涨跌停价格
64 : // -------------------------------------------------------------------------
65 : double upperLimitPrice; ///< 涨停价
66 : double lowerLimitPrice; ///< 跌停价
67 :
68 : // -------------------------------------------------------------------------
69 : // 时间戳
70 : // -------------------------------------------------------------------------
71 : std::chrono::system_clock::time_point updateTime; ///< 行情更新时间
72 :
73 : // -------------------------------------------------------------------------
74 : // 构造函数
75 : // -------------------------------------------------------------------------
76 :
77 : /**
78 : * @brief 默认构造函数
79 : *
80 : * 初始化所有数值字段为 0,时间戳为当前时间。
81 : */
82 412 : MarketDataSnapshot()
83 824 : : lastPrice(0.0)
84 412 : , bidPrice1(0.0)
85 412 : , bidVolume1(0)
86 412 : , askPrice1(0.0)
87 412 : , askVolume1(0)
88 412 : , upperLimitPrice(0.0)
89 412 : , lowerLimitPrice(0.0)
90 412 : , updateTime(std::chrono::system_clock::now())
91 412 : {}
92 :
93 : /**
94 : * @brief 带合约代码的构造函数
95 : *
96 : * @param instId 合约代码
97 : */
98 523 : explicit MarketDataSnapshot(const std::string& instId)
99 523 : : instrumentId(instId)
100 523 : , lastPrice(0.0)
101 523 : , bidPrice1(0.0)
102 523 : , bidVolume1(0)
103 523 : , askPrice1(0.0)
104 523 : , askVolume1(0)
105 523 : , upperLimitPrice(0.0)
106 523 : , lowerLimitPrice(0.0)
107 523 : , updateTime(std::chrono::system_clock::now())
108 523 : {}
109 :
110 : // -------------------------------------------------------------------------
111 : // 验证方法
112 : // -------------------------------------------------------------------------
113 :
114 : /**
115 : * @brief 检查行情是否有效
116 : *
117 : * 行情有效的条件是买一价或卖一价大于 0。
118 : * 无效行情不能用于撮合判断。
119 : *
120 : * @return 如果行情有效返回 true
121 : *
122 : * @note 价格为 0 或负数视为无效行情(未初始化或数据异常)
123 : */
124 100 : bool isValid() const {
125 100 : return bidPrice1 > 0 || askPrice1 > 0;
126 : }
127 :
128 : /**
129 : * @brief 检查是否有买盘
130 : *
131 : * @return 如果买一价和买一量都大于 0 返回 true
132 : */
133 408 : bool hasBid() const {
134 408 : return bidPrice1 > 0 && bidVolume1 > 0;
135 : }
136 :
137 : /**
138 : * @brief 检查是否有卖盘
139 : *
140 : * @return 如果卖一价和卖一量都大于 0 返回 true
141 : */
142 416 : bool hasAsk() const {
143 416 : return askPrice1 > 0 && askVolume1 > 0;
144 : }
145 :
146 : /**
147 : * @brief 获取买卖价差
148 : *
149 : * @return 卖一价 - 买一价,如果任一价格无效则返回 0
150 : *
151 : * @note 正常情况下价差应为正数(卖一价 > 买一价)。
152 : * 如果返回负值,表示出现"crossed quotes"异常行情,
153 : * 调用方应检查数据有效性。
154 : */
155 100 : double getSpread() const {
156 100 : if (bidPrice1 > 0 && askPrice1 > 0) {
157 100 : return askPrice1 - bidPrice1;
158 : }
159 0 : return 0.0;
160 : }
161 :
162 : /**
163 : * @brief 获取中间价
164 : *
165 : * @return (买一价 + 卖一价) / 2,如果任一价格无效则返回最新价
166 : */
167 100 : double getMidPrice() const {
168 100 : if (bidPrice1 > 0 && askPrice1 > 0) {
169 100 : return (bidPrice1 + askPrice1) / 2.0;
170 : }
171 0 : return lastPrice;
172 : }
173 :
174 : // -------------------------------------------------------------------------
175 : // 比较操作符(用于测试)
176 : // -------------------------------------------------------------------------
177 :
178 : /**
179 : * @brief 相等比较操作符
180 : *
181 : * 比较两个行情快照的所有字段是否相等(不包括时间戳)。
182 : *
183 : * @param other 另一个行情快照
184 : * @return 如果所有字段相等则返回 true
185 : *
186 : * @note 此操作符使用精确比较,适用于序列化/反序列化的 round-trip 测试。
187 : * 如需比较计算结果,请使用带容差的比较方法。
188 : */
189 : bool operator==(const MarketDataSnapshot& other) const {
190 : return instrumentId == other.instrumentId &&
191 : lastPrice == other.lastPrice &&
192 : bidPrice1 == other.bidPrice1 &&
193 : bidVolume1 == other.bidVolume1 &&
194 : askPrice1 == other.askPrice1 &&
195 : askVolume1 == other.askVolume1 &&
196 : upperLimitPrice == other.upperLimitPrice &&
197 : lowerLimitPrice == other.lowerLimitPrice;
198 : }
199 :
200 : /**
201 : * @brief 不等比较操作符
202 : *
203 : * @param other 另一个行情快照
204 : * @return 如果任意字段不相等则返回 true
205 : */
206 : bool operator!=(const MarketDataSnapshot& other) const {
207 : return !(*this == other);
208 : }
209 : };
210 :
211 : } // namespace fix40
|