Line data Source code
1 : /**
2 : * @file instrument_manager.hpp
3 : * @brief 合约信息管理模块
4 : *
5 : * 提供合约信息的加载、查询和更新功能。
6 : * 支持从配置文件加载合约静态信息,并从行情更新涨跌停价格。
7 : */
8 :
9 : #pragma once
10 :
11 : #include <string>
12 : #include <unordered_map>
13 : #include <optional>
14 : #include <mutex>
15 : #include <vector>
16 : #include "app/model/instrument.hpp"
17 :
18 : namespace fix40 {
19 :
20 : /**
21 : * @class InstrumentManager
22 : * @brief 合约信息管理器
23 : *
24 : * 负责合约信息的加载、查询和更新操作。
25 : * 系统启动时从配置文件加载合约静态信息,运行时从行情更新涨跌停价格。
26 : *
27 : * @par 线程安全
28 : * 所有公共方法都是线程安全的,使用互斥锁保护内部数据。
29 : *
30 : * @par 使用示例
31 : * @code
32 : * InstrumentManager mgr;
33 : *
34 : * // 从配置文件加载合约
35 : * mgr.loadFromConfig("config/instruments.json");
36 : *
37 : * // 查询合约信息
38 : * const Instrument* inst = mgr.getInstrument("IF2601");
39 : * if (inst) {
40 : * double margin = inst->calculateMargin(4000.0, 2);
41 : * }
42 : *
43 : * // 从行情更新涨跌停价格
44 : * mgr.updateLimitPrices("IF2601", 4400.0, 3600.0);
45 : * @endcode
46 : */
47 : class InstrumentManager {
48 : public:
49 : // -------------------------------------------------------------------------
50 : // 构造函数
51 : // -------------------------------------------------------------------------
52 :
53 : /**
54 : * @brief 默认构造函数
55 : */
56 38 : InstrumentManager() = default;
57 :
58 : /**
59 : * @brief 析构函数
60 : */
61 38 : ~InstrumentManager() = default;
62 :
63 : // 禁用拷贝
64 : InstrumentManager(const InstrumentManager&) = delete;
65 : InstrumentManager& operator=(const InstrumentManager&) = delete;
66 :
67 : // -------------------------------------------------------------------------
68 : // 加载方法
69 : // -------------------------------------------------------------------------
70 :
71 : /**
72 : * @brief 从配置文件加载合约信息
73 : *
74 : * 解析JSON格式的配置文件,加载合约静态信息。
75 : *
76 : * @param configPath 配置文件路径
77 : * @return 加载成功返回 true,失败返回 false
78 : *
79 : * @par 配置文件格式
80 : * @code
81 : * {
82 : * "instruments": [
83 : * {
84 : * "instrumentId": "IF2601",
85 : * "exchangeId": "CFFEX",
86 : * "productId": "IF",
87 : * "priceTick": 0.2,
88 : * "volumeMultiple": 300,
89 : * "marginRate": 0.12
90 : * }
91 : * ]
92 : * }
93 : * @endcode
94 : */
95 : bool loadFromConfig(const std::string& configPath);
96 :
97 : /**
98 : * @brief 添加单个合约
99 : *
100 : * 手动添加合约信息,主要用于测试。
101 : *
102 : * @param instrument 合约信息
103 : *
104 : * @note 如果合约ID已存在,将覆盖原有合约信息,不会发出警告。
105 : * 这是设计意图,允许更新合约参数(如保证金率变化)。
106 : */
107 : void addInstrument(const Instrument& instrument);
108 :
109 : /**
110 : * @brief 批量添加合约
111 : *
112 : * @param instruments 合约列表
113 : *
114 : * @note 如果合约ID已存在,将覆盖原有合约信息,不会发出警告。
115 : */
116 : void addInstruments(const std::vector<Instrument>& instruments);
117 :
118 : // -------------------------------------------------------------------------
119 : // 查询方法
120 : // -------------------------------------------------------------------------
121 :
122 : /**
123 : * @brief 获取合约信息
124 : *
125 : * @param instrumentId 合约代码
126 : * @return 合约信息指针,不存在时返回 nullptr
127 : *
128 : * @note 返回的指针在下次修改操作前有效
129 : */
130 : const Instrument* getInstrument(const std::string& instrumentId) const;
131 :
132 : /**
133 : * @brief 获取合约信息(可选类型)
134 : *
135 : * @param instrumentId 合约代码
136 : * @return 合约信息的副本,不存在时返回 std::nullopt
137 : */
138 : std::optional<Instrument> getInstrumentCopy(const std::string& instrumentId) const;
139 :
140 : /**
141 : * @brief 检查合约是否存在
142 : *
143 : * @param instrumentId 合约代码
144 : * @return 存在返回 true
145 : */
146 : bool hasInstrument(const std::string& instrumentId) const;
147 :
148 : /**
149 : * @brief 获取所有合约代码
150 : *
151 : * @return 合约代码列表
152 : */
153 : std::vector<std::string> getAllInstrumentIds() const;
154 :
155 : /**
156 : * @brief 获取合约数量
157 : *
158 : * @return 已加载的合约数量
159 : */
160 : size_t size() const;
161 :
162 : /**
163 : * @brief 按前缀搜索合约
164 : *
165 : * 用于实现合约代码的自动补全功能。
166 : *
167 : * @param prefix 合约代码前缀(如 "IF")
168 : * @param limit 返回结果数量上限(默认 10)
169 : * @return 匹配的合约代码列表(按字母排序)
170 : *
171 : * @par 使用示例
172 : * @code
173 : * auto results = mgr.searchByPrefix("IF", 5);
174 : * // 可能返回: ["IF2501", "IF2502", "IF2503", "IF2506", "IF2509"]
175 : * @endcode
176 : */
177 : std::vector<std::string> searchByPrefix(const std::string& prefix, size_t limit = 10) const;
178 :
179 : /**
180 : * @brief 按品种获取所有合约
181 : *
182 : * @param productId 品种代码(如 "IF")
183 : * @return 该品种的所有合约代码列表
184 : */
185 : std::vector<std::string> getInstrumentsByProduct(const std::string& productId) const;
186 :
187 : /**
188 : * @brief 按交易所获取所有合约
189 : *
190 : * @param exchangeId 交易所代码(如 "CFFEX")
191 : * @return 该交易所的所有合约代码列表
192 : */
193 : std::vector<std::string> getInstrumentsByExchange(const std::string& exchangeId) const;
194 :
195 : // -------------------------------------------------------------------------
196 : // 更新方法
197 : // -------------------------------------------------------------------------
198 :
199 : /**
200 : * @brief 更新涨跌停价格
201 : *
202 : * 从行情数据更新合约的涨跌停价格。
203 : *
204 : * @param instrumentId 合约代码
205 : * @param upperLimit 涨停价
206 : * @param lowerLimit 跌停价
207 : * @return 更新成功返回 true,合约不存在返回 false
208 : */
209 : bool updateLimitPrices(const std::string& instrumentId,
210 : double upperLimit, double lowerLimit);
211 :
212 : /**
213 : * @brief 更新昨结算价
214 : *
215 : * @param instrumentId 合约代码
216 : * @param preSettlementPrice 昨结算价
217 : * @return 更新成功返回 true,合约不存在返回 false
218 : */
219 : bool updatePreSettlementPrice(const std::string& instrumentId,
220 : double preSettlementPrice);
221 :
222 : // -------------------------------------------------------------------------
223 : // 清理方法
224 : // -------------------------------------------------------------------------
225 :
226 : /**
227 : * @brief 清空所有合约
228 : */
229 : void clear();
230 :
231 : private:
232 : /// 合约映射表:instrumentId -> Instrument
233 : std::unordered_map<std::string, Instrument> instruments_;
234 :
235 : /// 互斥锁,保护 instruments_
236 : mutable std::mutex mutex_;
237 : };
238 :
239 : } // namespace fix40
|