Line data Source code
1 : /**
2 : * @file risk_manager.cpp
3 : * @brief 风险控制模块实现
4 : *
5 : * 实现订单风控检查功能。
6 : */
7 :
8 : #include "app/manager/risk_manager.hpp"
9 : #include <sstream>
10 :
11 : namespace fix40 {
12 :
13 : // =============================================================================
14 : // 主检查方法
15 : // =============================================================================
16 :
17 10 : CheckResult RiskManager::checkOrder(
18 : const Order& order,
19 : const Account& account,
20 : const Position& position,
21 : const Instrument& instrument,
22 : const MarketDataSnapshot& snapshot,
23 : OffsetFlag offsetFlag
24 : ) const {
25 : // 1. 价格检查(限价单)
26 10 : if (order.ordType == OrderType::LIMIT) {
27 8 : CheckResult priceResult = checkPrice(order, instrument);
28 8 : if (!priceResult.passed) {
29 2 : return priceResult;
30 : }
31 8 : }
32 :
33 : // 2. 资金检查(开仓)
34 8 : if (offsetFlag == OffsetFlag::OPEN) {
35 6 : CheckResult marginResult = checkMargin(order, account, instrument);
36 6 : if (!marginResult.passed) {
37 1 : return marginResult;
38 : }
39 6 : }
40 :
41 : // 3. 持仓检查(平仓)
42 7 : if (offsetFlag == OffsetFlag::CLOSE) {
43 2 : CheckResult positionResult = checkPosition(order, position);
44 2 : if (!positionResult.passed) {
45 1 : return positionResult;
46 : }
47 2 : }
48 :
49 : // 4. 对手盘检查(市价单)
50 6 : if (order.ordType == OrderType::MARKET) {
51 2 : CheckResult counterPartyResult = checkCounterParty(order, snapshot);
52 2 : if (!counterPartyResult.passed) {
53 1 : return counterPartyResult;
54 : }
55 2 : }
56 :
57 5 : return CheckResult::success();
58 : }
59 :
60 : // =============================================================================
61 : // 子检查方法
62 : // =============================================================================
63 :
64 211 : CheckResult RiskManager::checkMargin(
65 : const Order& order,
66 : const Account& account,
67 : const Instrument& instrument
68 : ) const {
69 211 : double requiredMargin = calculateRequiredMargin(order, instrument);
70 :
71 211 : if (account.available < requiredMargin) {
72 103 : std::ostringstream oss;
73 103 : oss << "Insufficient funds: required=" << requiredMargin
74 103 : << ", available=" << account.available;
75 103 : return CheckResult::failure(RejectReason::INSUFFICIENT_FUNDS, oss.str());
76 103 : }
77 :
78 108 : return CheckResult::success();
79 : }
80 :
81 415 : CheckResult RiskManager::checkPrice(
82 : const Order& order,
83 : const Instrument& instrument
84 : ) const {
85 : // 市价单不检查价格
86 415 : if (order.ordType == OrderType::MARKET) {
87 101 : return CheckResult::success();
88 : }
89 :
90 : // 如果涨跌停价格未设置,跳过检查
91 314 : if (instrument.lowerLimitPrice <= 0 && instrument.upperLimitPrice <= 0) {
92 1 : return CheckResult::success();
93 : }
94 :
95 : // 检查价格是否在涨跌停范围内
96 313 : if (!instrument.isPriceValid(order.price)) {
97 204 : std::ostringstream oss;
98 204 : oss << "Price out of limit: price=" << order.price
99 204 : << ", lower=" << instrument.lowerLimitPrice
100 204 : << ", upper=" << instrument.upperLimitPrice;
101 204 : return CheckResult::failure(RejectReason::PRICE_OUT_OF_LIMIT, oss.str());
102 204 : }
103 :
104 109 : return CheckResult::success();
105 : }
106 :
107 508 : CheckResult RiskManager::checkPosition(
108 : const Order& order,
109 : const Position& position
110 : ) const {
111 : // 买单平空头,卖单平多头
112 508 : int64_t availablePosition = 0;
113 :
114 508 : if (order.side == OrderSide::BUY) {
115 : // 买入平仓 = 平空头
116 202 : availablePosition = position.shortPosition;
117 : } else {
118 : // 卖出平仓 = 平多头
119 306 : availablePosition = position.longPosition;
120 : }
121 :
122 508 : if (order.orderQty > availablePosition) {
123 204 : std::ostringstream oss;
124 204 : oss << "Insufficient position: required=" << order.orderQty
125 204 : << ", available=" << availablePosition;
126 204 : return CheckResult::failure(RejectReason::INSUFFICIENT_POSITION, oss.str());
127 204 : }
128 :
129 304 : return CheckResult::success();
130 : }
131 :
132 7 : CheckResult RiskManager::checkCounterParty(
133 : const Order& order,
134 : const MarketDataSnapshot& snapshot
135 : ) const {
136 : // 限价单不检查对手盘
137 7 : if (order.ordType == OrderType::LIMIT) {
138 1 : return CheckResult::success();
139 : }
140 :
141 6 : bool hasCounterParty = false;
142 :
143 6 : if (order.side == OrderSide::BUY) {
144 : // 买单需要有卖盘
145 4 : hasCounterParty = snapshot.hasAsk();
146 : } else {
147 : // 卖单需要有买盘
148 2 : hasCounterParty = snapshot.hasBid();
149 : }
150 :
151 6 : if (!hasCounterParty) {
152 3 : std::string sideStr = (order.side == OrderSide::BUY) ? "ask" : "bid";
153 3 : std::ostringstream oss;
154 3 : oss << "No counter party: no " << sideStr << " available";
155 3 : return CheckResult::failure(RejectReason::NO_COUNTER_PARTY, oss.str());
156 3 : }
157 :
158 3 : return CheckResult::success();
159 : }
160 :
161 : // =============================================================================
162 : // 辅助方法
163 : // =============================================================================
164 :
165 316 : double RiskManager::calculateRequiredMargin(
166 : const Order& order,
167 : const Instrument& instrument
168 : ) const {
169 316 : double price = order.price;
170 :
171 : // 市价单使用涨停价(买单)或跌停价(卖单)计算保证金
172 316 : if (order.ordType == OrderType::MARKET) {
173 6 : if (order.side == OrderSide::BUY) {
174 : // 买单使用涨停价
175 4 : price = instrument.upperLimitPrice;
176 : // 如果涨停价未设置,使用昨结算价
177 4 : if (price <= 0) {
178 0 : price = instrument.preSettlementPrice;
179 : }
180 : } else {
181 : // 卖单使用跌停价
182 2 : price = instrument.lowerLimitPrice;
183 : // 如果跌停价未设置,使用昨结算价
184 2 : if (price <= 0) {
185 0 : price = instrument.preSettlementPrice;
186 : }
187 : }
188 : }
189 :
190 316 : return instrument.calculateMargin(price, order.orderQty);
191 : }
192 :
193 : } // namespace fix40
|