Line data Source code
1 : /**
2 : * @file position.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 Position
23 : * @brief 合约持仓
24 : *
25 : * 用户在某个合约上的持仓信息,分为多头和空头两个方向。
26 : * 系统通过此结构追踪用户的头寸和盈亏状态。
27 : *
28 : * @par 盈亏计算
29 : * - 多头浮动盈亏 = (最新价 - 多头均价) × 多头持仓量 × 合约乘数
30 : * - 空头浮动盈亏 = (空头均价 - 最新价) × 空头持仓量 × 合约乘数
31 : *
32 : * @par 使用示例
33 : * @code
34 : * Position pos;
35 : * pos.accountId = "user001";
36 : * pos.instrumentId = "IF2601";
37 : * pos.longPosition = 2;
38 : * pos.longAvgPrice = 4000.0;
39 : *
40 : * // 更新浮动盈亏(假设最新价4050,合约乘数300)
41 : * pos.updateProfit(4050.0, 300);
42 : * // 多头盈亏 = (4050 - 4000) * 2 * 300 = 30000
43 : * @endcode
44 : */
45 : struct Position {
46 : // -------------------------------------------------------------------------
47 : // 标识符
48 : // -------------------------------------------------------------------------
49 : std::string accountId; ///< 账户ID
50 : std::string instrumentId; ///< 合约代码(如 "IF2601")
51 :
52 : // -------------------------------------------------------------------------
53 : // 多头持仓
54 : // -------------------------------------------------------------------------
55 : int64_t longPosition; ///< 多头持仓量(手数)
56 : double longAvgPrice; ///< 多头持仓均价
57 : double longProfit; ///< 多头浮动盈亏
58 : double longMargin; ///< 多头占用保证金
59 :
60 : // -------------------------------------------------------------------------
61 : // 空头持仓
62 : // -------------------------------------------------------------------------
63 : int64_t shortPosition; ///< 空头持仓量(手数)
64 : double shortAvgPrice; ///< 空头持仓均价
65 : double shortProfit; ///< 空头浮动盈亏
66 : double shortMargin; ///< 空头占用保证金
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 1868 : Position()
83 3736 : : longPosition(0)
84 1868 : , longAvgPrice(0.0)
85 1868 : , longProfit(0.0)
86 1868 : , longMargin(0.0)
87 1868 : , shortPosition(0)
88 1868 : , shortAvgPrice(0.0)
89 1868 : , shortProfit(0.0)
90 1868 : , shortMargin(0.0)
91 1868 : , updateTime(std::chrono::system_clock::now())
92 1868 : {}
93 :
94 : /**
95 : * @brief 带标识符的构造函数
96 : *
97 : * @param accId 账户ID
98 : * @param instId 合约代码
99 : */
100 1073 : Position(const std::string& accId, const std::string& instId)
101 1073 : : accountId(accId)
102 1073 : , instrumentId(instId)
103 1073 : , longPosition(0)
104 1073 : , longAvgPrice(0.0)
105 1073 : , longProfit(0.0)
106 1073 : , longMargin(0.0)
107 1073 : , shortPosition(0)
108 1073 : , shortAvgPrice(0.0)
109 1073 : , shortProfit(0.0)
110 1073 : , shortMargin(0.0)
111 1073 : , updateTime(std::chrono::system_clock::now())
112 1073 : {}
113 :
114 : // -------------------------------------------------------------------------
115 : // 计算方法
116 : // -------------------------------------------------------------------------
117 :
118 : /**
119 : * @brief 更新浮动盈亏
120 : *
121 : * 根据最新价格重新计算多头和空头的浮动盈亏。
122 : *
123 : * @param lastPrice 最新价格
124 : * @param volumeMultiple 合约乘数
125 : *
126 : * @par 计算公式
127 : * - 多头盈亏 = (最新价 - 多头均价) × 多头持仓量 × 合约乘数
128 : * - 空头盈亏 = (空头均价 - 最新价) × 空头持仓量 × 合约乘数
129 : */
130 312 : void updateProfit(double lastPrice, int volumeMultiple) {
131 312 : longProfit = (lastPrice - longAvgPrice) * longPosition * volumeMultiple;
132 312 : shortProfit = (shortAvgPrice - lastPrice) * shortPosition * volumeMultiple;
133 312 : }
134 :
135 : /**
136 : * @brief 获取总浮动盈亏
137 : *
138 : * @return 多头盈亏 + 空头盈亏
139 : */
140 210 : double getTotalProfit() const {
141 210 : return longProfit + shortProfit;
142 : }
143 :
144 : /**
145 : * @brief 获取总持仓量
146 : *
147 : * @return 多头持仓 + 空头持仓
148 : */
149 101 : int64_t getTotalPosition() const {
150 101 : return longPosition + shortPosition;
151 : }
152 :
153 : /**
154 : * @brief 获取总占用保证金
155 : *
156 : * @return 多头保证金 + 空头保证金
157 : */
158 1 : double getTotalMargin() const {
159 1 : return longMargin + shortMargin;
160 : }
161 :
162 : /**
163 : * @brief 检查是否有持仓
164 : *
165 : * @return 如果有任意方向的持仓返回 true
166 : */
167 102 : bool hasPosition() const {
168 102 : return longPosition > 0 || shortPosition > 0;
169 : }
170 :
171 : /**
172 : * @brief 获取净持仓
173 : *
174 : * @return 多头持仓 - 空头持仓(正数表示净多,负数表示净空)
175 : */
176 101 : int64_t getNetPosition() const {
177 101 : return longPosition - shortPosition;
178 : }
179 :
180 : // -------------------------------------------------------------------------
181 : // 比较操作符(用于测试)
182 : // -------------------------------------------------------------------------
183 :
184 : /**
185 : * @brief 相等比较操作符
186 : *
187 : * 比较两个持仓的所有字段是否相等(不包括时间戳)。
188 : * 主要用于属性测试中的 round-trip 验证。
189 : *
190 : * @param other 另一个持仓
191 : * @return 如果所有字段相等则返回 true
192 : *
193 : * @note 此操作符使用精确比较,适用于序列化/反序列化的 round-trip 测试。
194 : * 如需比较计算结果,请使用带容差的比较方法。
195 : */
196 104 : bool operator==(const Position& other) const {
197 207 : return accountId == other.accountId &&
198 103 : instrumentId == other.instrumentId &&
199 103 : longPosition == other.longPosition &&
200 103 : longAvgPrice == other.longAvgPrice &&
201 103 : longProfit == other.longProfit &&
202 103 : longMargin == other.longMargin &&
203 103 : shortPosition == other.shortPosition &&
204 103 : shortAvgPrice == other.shortAvgPrice &&
205 310 : shortProfit == other.shortProfit &&
206 207 : shortMargin == other.shortMargin;
207 : }
208 :
209 : /**
210 : * @brief 不等比较操作符
211 : *
212 : * @param other 另一个持仓
213 : * @return 如果任意字段不相等则返回 true
214 : */
215 1 : bool operator!=(const Position& other) const {
216 1 : return !(*this == other);
217 : }
218 : };
219 :
220 : } // namespace fix40
|