Line data Source code
1 : /**
2 : * @file risk_manager.hpp
3 : * @brief 风险控制模块
4 : *
5 : * 提供订单风控检查功能,包括资金检查、价格检查、持仓检查等。
6 : * 在订单提交到撮合引擎之前进行风险验证。
7 : */
8 :
9 : #pragma once
10 :
11 : #include <string>
12 : #include <cstdint>
13 : #include "app/model/order.hpp"
14 : #include "app/model/account.hpp"
15 : #include "app/model/position.hpp"
16 : #include "app/model/instrument.hpp"
17 : #include "app/model/market_data_snapshot.hpp"
18 :
19 : namespace fix40 {
20 :
21 : // ============================================================================
22 : // 拒绝原因代码
23 : // ============================================================================
24 :
25 : /**
26 : * @enum RejectReason
27 : * @brief 订单拒绝原因代码
28 : *
29 : * 定义风控检查失败时的拒绝原因代码,与设计文档中的错误处理表对应。
30 : */
31 : enum class RejectReason {
32 : NONE = 0, ///< 无错误(检查通过)
33 : INSTRUMENT_NOT_FOUND = 1, ///< 合约不存在
34 : INSUFFICIENT_FUNDS = 2, ///< 资金不足
35 : PRICE_OUT_OF_LIMIT = 3, ///< 价格超限(超出涨跌停)
36 : INSUFFICIENT_POSITION = 4, ///< 持仓不足(平仓数量超过持仓)
37 : NO_COUNTER_PARTY = 5, ///< 无对手盘(市价单)
38 : ORDER_NOT_FOUND = 6 ///< 订单不存在(撤单时)
39 : };
40 :
41 : // ============================================================================
42 : // 检查结果结构
43 : // ============================================================================
44 :
45 : /**
46 : * @struct CheckResult
47 : * @brief 风控检查结果
48 : *
49 : * 包含检查是否通过、拒绝原因代码和拒绝原因文本。
50 : */
51 : struct CheckResult {
52 : bool passed; ///< 检查是否通过
53 : RejectReason rejectReason; ///< 拒绝原因代码
54 : std::string rejectText; ///< 拒绝原因文本
55 :
56 : /**
57 : * @brief 默认构造函数(检查通过)
58 : */
59 632 : CheckResult()
60 632 : : passed(true)
61 632 : , rejectReason(RejectReason::NONE)
62 632 : {}
63 :
64 : /**
65 : * @brief 构造失败结果
66 : *
67 : * @param reason 拒绝原因代码
68 : * @param text 拒绝原因文本
69 : */
70 514 : CheckResult(RejectReason reason, const std::string& text)
71 514 : : passed(false)
72 514 : , rejectReason(reason)
73 514 : , rejectText(text)
74 514 : {}
75 :
76 : /**
77 : * @brief 创建成功结果
78 : *
79 : * @return 检查通过的结果
80 : */
81 632 : static CheckResult success() {
82 632 : return CheckResult();
83 : }
84 :
85 : /**
86 : * @brief 创建失败结果
87 : *
88 : * @param reason 拒绝原因代码
89 : * @param text 拒绝原因文本
90 : * @return 检查失败的结果
91 : */
92 514 : static CheckResult failure(RejectReason reason, const std::string& text) {
93 514 : return CheckResult(reason, text);
94 : }
95 : };
96 :
97 : // ============================================================================
98 : // 开平标志
99 : // ============================================================================
100 :
101 : /**
102 : * @enum OffsetFlag
103 : * @brief 开平标志
104 : *
105 : * 用于区分开仓和平仓订单。
106 : */
107 : enum class OffsetFlag {
108 : OPEN = 0, ///< 开仓
109 : CLOSE = 1 ///< 平仓
110 : };
111 :
112 : // ============================================================================
113 : // 风控管理器
114 : // ============================================================================
115 :
116 : /**
117 : * @class RiskManager
118 : * @brief 风险控制模块
119 : *
120 : * 负责订单提交前的风险检查,包括:
121 : * - 资金检查:验证可用资金是否足够支付保证金
122 : * - 价格检查:验证限价单价格是否在涨跌停范围内
123 : * - 持仓检查:验证平仓数量是否超过持仓
124 : *
125 : * @par 使用示例
126 : * @code
127 : * RiskManager riskMgr;
128 : *
129 : * Order order;
130 : * order.symbol = "IF2601";
131 : * order.side = OrderSide::BUY;
132 : * order.ordType = OrderType::LIMIT;
133 : * order.price = 4000.0;
134 : * order.orderQty = 2;
135 : *
136 : * Account account("user001", 1000000.0);
137 : * Position position("user001", "IF2601");
138 : * Instrument instrument("IF2601", "CFFEX", "IF", 0.2, 300, 0.12);
139 : * instrument.updateLimitPrices(4200.0, 3800.0);
140 : * MarketDataSnapshot snapshot("IF2601");
141 : * snapshot.askPrice1 = 4000.2;
142 : *
143 : * CheckResult result = riskMgr.checkOrder(order, account, position, instrument, snapshot, OffsetFlag::OPEN);
144 : * if (result.passed) {
145 : * // 提交到撮合引擎
146 : * } else {
147 : * // 拒绝订单,返回 result.rejectText
148 : * }
149 : * @endcode
150 : *
151 : * @par 线程安全
152 : * 所有公共方法都是线程安全的(无状态类)。
153 : */
154 : class RiskManager {
155 : public:
156 : // -------------------------------------------------------------------------
157 : // 构造函数
158 : // -------------------------------------------------------------------------
159 :
160 : /**
161 : * @brief 默认构造函数
162 : */
163 : RiskManager() = default;
164 :
165 : // -------------------------------------------------------------------------
166 : // 主检查方法
167 : // -------------------------------------------------------------------------
168 :
169 : /**
170 : * @brief 订单风控检查
171 : *
172 : * 对订单进行完整的风控检查,包括资金、价格、持仓等。
173 : *
174 : * @param order 待检查的订单
175 : * @param account 账户信息
176 : * @param position 持仓信息
177 : * @param instrument 合约信息
178 : * @param snapshot 行情快照
179 : * @param offsetFlag 开平标志
180 : * @return 检查结果
181 : *
182 : * @par 检查顺序
183 : * 1. 价格检查(限价单)
184 : * 2. 资金检查(开仓)
185 : * 3. 持仓检查(平仓)
186 : * 4. 对手盘检查(市价单)
187 : */
188 : CheckResult checkOrder(
189 : const Order& order,
190 : const Account& account,
191 : const Position& position,
192 : const Instrument& instrument,
193 : const MarketDataSnapshot& snapshot,
194 : OffsetFlag offsetFlag
195 : ) const;
196 :
197 : // -------------------------------------------------------------------------
198 : // 子检查方法(公开以便单独测试)
199 : // -------------------------------------------------------------------------
200 :
201 : /**
202 : * @brief 检查可用资金是否足够
203 : *
204 : * 验证账户可用资金是否足够支付开仓所需的保证金。
205 : *
206 : * @param order 订单信息
207 : * @param account 账户信息
208 : * @param instrument 合约信息
209 : * @return 检查结果
210 : *
211 : * @par 计算公式
212 : * 所需保证金 = 价格 × 数量 × 合约乘数 × 保证金率
213 : *
214 : * @note 市价单使用涨停价(买单)或跌停价(卖单)计算保证金
215 : */
216 : CheckResult checkMargin(
217 : const Order& order,
218 : const Account& account,
219 : const Instrument& instrument
220 : ) const;
221 :
222 : /**
223 : * @brief 检查价格是否在涨跌停范围内
224 : *
225 : * 验证限价单的价格是否在当日涨跌停价格范围内。
226 : *
227 : * @param order 订单信息
228 : * @param instrument 合约信息
229 : * @return 检查结果
230 : *
231 : * @note 市价单不进行价格检查
232 : */
233 : CheckResult checkPrice(
234 : const Order& order,
235 : const Instrument& instrument
236 : ) const;
237 :
238 : /**
239 : * @brief 检查平仓数量是否超过持仓
240 : *
241 : * 验证平仓订单的数量是否超过当前持仓数量。
242 : *
243 : * @param order 订单信息
244 : * @param position 持仓信息
245 : * @return 检查结果
246 : *
247 : * @note 买单平空头持仓,卖单平多头持仓
248 : */
249 : CheckResult checkPosition(
250 : const Order& order,
251 : const Position& position
252 : ) const;
253 :
254 : /**
255 : * @brief 检查市价单是否有对手盘
256 : *
257 : * 验证市价单是否有可成交的对手盘。
258 : *
259 : * @param order 订单信息
260 : * @param snapshot 行情快照
261 : * @return 检查结果
262 : *
263 : * @note 买单需要有卖盘,卖单需要有买盘
264 : */
265 : CheckResult checkCounterParty(
266 : const Order& order,
267 : const MarketDataSnapshot& snapshot
268 : ) const;
269 :
270 : // -------------------------------------------------------------------------
271 : // 辅助方法
272 : // -------------------------------------------------------------------------
273 :
274 : /**
275 : * @brief 计算订单所需保证金
276 : *
277 : * @param order 订单信息
278 : * @param instrument 合约信息
279 : * @return 所需保证金金额
280 : *
281 : * @note 市价单使用涨停价(买单)或跌停价(卖单)计算
282 : */
283 : double calculateRequiredMargin(
284 : const Order& order,
285 : const Instrument& instrument
286 : ) const;
287 : };
288 :
289 : } // namespace fix40
|