Line data Source code
1 : /**
2 : * @file position_manager.cpp
3 : * @brief 持仓管理模块实现
4 : */
5 :
6 : #include "app/manager/position_manager.hpp"
7 : #include "storage/store.hpp"
8 : #include <chrono>
9 :
10 : namespace fix40 {
11 :
12 : // =============================================================================
13 : // 构造函数
14 : // =============================================================================
15 :
16 546 : PositionManager::PositionManager()
17 546 : : store_(nullptr)
18 546 : {}
19 :
20 8 : PositionManager::PositionManager(IStore* store)
21 8 : : store_(store)
22 : {
23 8 : if (store_) {
24 : // 启动时从存储恢复持仓状态(用于服务端重启后持仓连续性)。
25 8 : auto positions = store_->loadAllPositions();
26 8 : std::lock_guard<std::mutex> lock(mutex_);
27 8 : positions_.clear();
28 10 : for (const auto& position : positions) {
29 2 : if (!position.accountId.empty() && !position.instrumentId.empty()) {
30 2 : positions_[makeKey(position.accountId, position.instrumentId)] = position;
31 : }
32 : }
33 8 : }
34 8 : }
35 :
36 : // =============================================================================
37 : // 查询方法
38 : // =============================================================================
39 :
40 244 : std::optional<Position> PositionManager::getPosition(const std::string& accountId,
41 : const std::string& instrumentId) const {
42 244 : std::lock_guard<std::mutex> lock(mutex_);
43 :
44 244 : auto it = positions_.find(makeKey(accountId, instrumentId));
45 244 : if (it != positions_.end()) {
46 238 : return it->second;
47 : }
48 6 : return std::nullopt;
49 244 : }
50 :
51 1 : std::vector<Position> PositionManager::getPositionsByAccount(const std::string& accountId) const {
52 1 : std::lock_guard<std::mutex> lock(mutex_);
53 :
54 1 : std::vector<Position> result;
55 4 : for (const auto& pair : positions_) {
56 3 : if (pair.second.accountId == accountId) {
57 2 : result.push_back(pair.second);
58 : }
59 : }
60 2 : return result;
61 1 : }
62 :
63 3 : std::vector<Position> PositionManager::getAllPositions() const {
64 3 : std::lock_guard<std::mutex> lock(mutex_);
65 :
66 3 : std::vector<Position> result;
67 3 : result.reserve(positions_.size());
68 3 : for (const auto& pair : positions_) {
69 0 : result.push_back(pair.second);
70 : }
71 6 : return result;
72 3 : }
73 :
74 3 : bool PositionManager::hasPosition(const std::string& accountId,
75 : const std::string& instrumentId) const {
76 3 : std::lock_guard<std::mutex> lock(mutex_);
77 :
78 3 : auto it = positions_.find(makeKey(accountId, instrumentId));
79 3 : if (it == positions_.end()) {
80 2 : return false;
81 : }
82 1 : return it->second.hasPosition();
83 3 : }
84 :
85 3 : size_t PositionManager::size() const {
86 3 : std::lock_guard<std::mutex> lock(mutex_);
87 6 : return positions_.size();
88 3 : }
89 :
90 : // =============================================================================
91 : // 开仓操作
92 : // =============================================================================
93 :
94 804 : void PositionManager::openPosition(const std::string& accountId,
95 : const std::string& instrumentId,
96 : OrderSide side,
97 : int64_t volume,
98 : double price,
99 : double margin) {
100 804 : std::lock_guard<std::mutex> lock(mutex_);
101 :
102 804 : std::string key = makeKey(accountId, instrumentId);
103 :
104 : // 获取或创建持仓
105 804 : auto it = positions_.find(key);
106 804 : if (it == positions_.end()) {
107 537 : Position pos(accountId, instrumentId);
108 537 : positions_[key] = pos;
109 537 : it = positions_.find(key);
110 537 : }
111 :
112 804 : Position& pos = it->second;
113 :
114 804 : if (side == OrderSide::BUY) {
115 : // 多头开仓
116 : // 新均价 = (原均价 × 原持仓 + 开仓价 × 开仓量) / (原持仓 + 开仓量)
117 687 : double totalCost = pos.longAvgPrice * pos.longPosition + price * volume;
118 687 : int64_t totalVolume = pos.longPosition + volume;
119 :
120 687 : pos.longPosition = totalVolume;
121 687 : pos.longAvgPrice = totalVolume > 0 ? totalCost / totalVolume : 0.0;
122 687 : pos.longMargin += margin;
123 : } else {
124 : // 空头开仓
125 117 : double totalCost = pos.shortAvgPrice * pos.shortPosition + price * volume;
126 117 : int64_t totalVolume = pos.shortPosition + volume;
127 :
128 117 : pos.shortPosition = totalVolume;
129 117 : pos.shortAvgPrice = totalVolume > 0 ? totalCost / totalVolume : 0.0;
130 117 : pos.shortMargin += margin;
131 : }
132 :
133 804 : pos.updateTime = std::chrono::system_clock::now();
134 :
135 : // 持久化
136 804 : persistPosition(pos);
137 804 : }
138 :
139 : // =============================================================================
140 : // 平仓操作
141 : // =============================================================================
142 :
143 217 : double PositionManager::closePosition(const std::string& accountId,
144 : const std::string& instrumentId,
145 : OrderSide side,
146 : int64_t volume,
147 : double price,
148 : int volumeMultiple) {
149 217 : std::lock_guard<std::mutex> lock(mutex_);
150 :
151 217 : std::string key = makeKey(accountId, instrumentId);
152 :
153 217 : auto it = positions_.find(key);
154 217 : if (it == positions_.end()) {
155 0 : return 0.0;
156 : }
157 :
158 217 : Position& pos = it->second;
159 217 : double profit = 0.0;
160 :
161 217 : if (side == OrderSide::SELL) {
162 : // 平多头(卖出平仓)
163 : // 盈亏 = (平仓价 - 持仓均价) × 平仓量 × 合约乘数
164 110 : profit = (price - pos.longAvgPrice) * volume * volumeMultiple;
165 :
166 : // 计算平仓前的持仓量,用于按比例计算保证金释放
167 110 : int64_t originalPosition = pos.longPosition;
168 :
169 : // 减少持仓
170 110 : pos.longPosition -= volume;
171 110 : if (pos.longPosition <= 0) {
172 105 : pos.longPosition = 0;
173 105 : pos.longAvgPrice = 0.0;
174 105 : pos.longProfit = 0.0;
175 105 : pos.longMargin = 0.0;
176 : } else {
177 : // 按比例减少保证金:释放的保证金 = 原保证金 × (平仓量 / 原持仓量)
178 5 : double marginToRelease = pos.longMargin * (static_cast<double>(volume) / originalPosition);
179 5 : pos.longMargin -= marginToRelease;
180 : // 浮动盈亏与持仓量成比例:若当前 longProfit 基于某个最新价计算过,平仓后按剩余仓位缩放,
181 : // 避免出现“持仓量减少但浮动盈亏仍保持旧值”的情况。
182 5 : pos.longProfit *= (static_cast<double>(pos.longPosition) / originalPosition);
183 : }
184 : } else {
185 : // 平空头(买入平仓)
186 : // 盈亏 = (持仓均价 - 平仓价) × 平仓量 × 合约乘数
187 107 : profit = (pos.shortAvgPrice - price) * volume * volumeMultiple;
188 :
189 : // 计算平仓前的持仓量,用于按比例计算保证金释放
190 107 : int64_t originalPosition = pos.shortPosition;
191 :
192 : // 减少持仓
193 107 : pos.shortPosition -= volume;
194 107 : if (pos.shortPosition <= 0) {
195 104 : pos.shortPosition = 0;
196 104 : pos.shortAvgPrice = 0.0;
197 104 : pos.shortProfit = 0.0;
198 104 : pos.shortMargin = 0.0;
199 : } else {
200 : // 按比例减少保证金:释放的保证金 = 原保证金 × (平仓量 / 原持仓量)
201 3 : double marginToRelease = pos.shortMargin * (static_cast<double>(volume) / originalPosition);
202 3 : pos.shortMargin -= marginToRelease;
203 3 : pos.shortProfit *= (static_cast<double>(pos.shortPosition) / originalPosition);
204 : }
205 : }
206 :
207 217 : pos.updateTime = std::chrono::system_clock::now();
208 :
209 : // 持久化
210 217 : persistPosition(pos);
211 :
212 217 : return profit;
213 217 : }
214 :
215 : // =============================================================================
216 : // 盈亏更新
217 : // =============================================================================
218 :
219 1 : void PositionManager::updateAllProfits(const MarketDataSnapshot& snapshot, int volumeMultiple) {
220 1 : std::lock_guard<std::mutex> lock(mutex_);
221 :
222 3 : for (auto& pair : positions_) {
223 2 : if (pair.second.instrumentId == snapshot.instrumentId) {
224 2 : pair.second.updateProfit(snapshot.lastPrice, volumeMultiple);
225 2 : pair.second.updateTime = std::chrono::system_clock::now();
226 : }
227 : }
228 1 : }
229 :
230 105 : double PositionManager::updateProfit(const std::string& accountId,
231 : const std::string& instrumentId,
232 : double lastPrice,
233 : int volumeMultiple) {
234 105 : std::lock_guard<std::mutex> lock(mutex_);
235 :
236 105 : std::string key = makeKey(accountId, instrumentId);
237 :
238 105 : auto it = positions_.find(key);
239 105 : if (it == positions_.end()) {
240 0 : return 0.0;
241 : }
242 :
243 105 : Position& pos = it->second;
244 105 : pos.updateProfit(lastPrice, volumeMultiple);
245 105 : pos.updateTime = std::chrono::system_clock::now();
246 :
247 105 : return pos.getTotalProfit();
248 105 : }
249 :
250 2 : double PositionManager::getTotalProfit(const std::string& accountId) const {
251 2 : std::lock_guard<std::mutex> lock(mutex_);
252 :
253 2 : double total = 0.0;
254 5 : for (const auto& pair : positions_) {
255 3 : if (pair.second.accountId == accountId) {
256 3 : total += pair.second.getTotalProfit();
257 : }
258 : }
259 2 : return total;
260 2 : }
261 :
262 : // =============================================================================
263 : // 清理方法
264 : // =============================================================================
265 :
266 1 : void PositionManager::clear() {
267 1 : std::lock_guard<std::mutex> lock(mutex_);
268 1 : positions_.clear();
269 1 : }
270 :
271 : // =============================================================================
272 : // 私有方法
273 : // =============================================================================
274 :
275 1375 : std::string PositionManager::makeKey(const std::string& accountId,
276 : const std::string& instrumentId) {
277 1375 : return accountId + "_" + instrumentId;
278 : }
279 :
280 1021 : void PositionManager::persistPosition(const Position& position) {
281 1021 : if (!store_) return;
282 : // 注意:此处为 best-effort 持久化。存储失败时不抛异常,以免影响撮合主流程。
283 3 : store_->savePosition(position);
284 : }
285 :
286 : } // namespace fix40
|