Line data Source code
1 : /**
2 : * @file instrument.hpp
3 : * @brief 合约信息数据结构
4 : *
5 : * 定义期货合约的静态属性,如保证金率、合约乘数、涨跌停价等。
6 : * 用于交易规则验证和保证金计算。
7 : */
8 :
9 : #pragma once
10 :
11 : #include <string>
12 : #include <cstdint>
13 : #include <cmath>
14 :
15 : namespace fix40 {
16 :
17 : // ============================================================================
18 : // 合约信息结构
19 : // ============================================================================
20 :
21 : /**
22 : * @struct Instrument
23 : * @brief 合约静态信息
24 : *
25 : * 期货合约的基本属性,包含交易规则相关的参数。
26 : * 系统通过此结构进行保证金计算和价格有效性检查。
27 : *
28 : * @par 保证金计算
29 : * 保证金 = 价格 × 数量 × 合约乘数 × 保证金率
30 : *
31 : * @par 使用示例
32 : * @code
33 : * Instrument inst;
34 : * inst.instrumentId = "IF2601";
35 : * inst.exchangeId = "CFFEX";
36 : * inst.volumeMultiple = 300;
37 : * inst.marginRate = 0.12; // 12%
38 : * inst.priceTick = 0.2;
39 : *
40 : * // 计算开仓保证金
41 : * double margin = inst.calculateMargin(4000.0, 2);
42 : * // margin = 4000 * 2 * 300 * 0.12 = 288000
43 : *
44 : * // 检查价格有效性
45 : * bool valid = inst.isPriceValid(4050.0);
46 : * @endcode
47 : */
48 : struct Instrument {
49 : // -------------------------------------------------------------------------
50 : // 标识符
51 : // -------------------------------------------------------------------------
52 : std::string instrumentId; ///< 合约代码(如 "IF2601")
53 : std::string exchangeId; ///< 交易所代码(如 "CFFEX")
54 : std::string productId; ///< 品种代码(如 "IF")
55 :
56 : // -------------------------------------------------------------------------
57 : // 交易参数
58 : // -------------------------------------------------------------------------
59 : double priceTick; ///< 最小变动价位(如 0.2)
60 : int volumeMultiple; ///< 合约乘数(如 300)
61 : double marginRate; ///< 保证金率(如 0.12 表示 12%)
62 :
63 : // -------------------------------------------------------------------------
64 : // 价格限制(从行情更新)
65 : // -------------------------------------------------------------------------
66 : double upperLimitPrice; ///< 涨停价
67 : double lowerLimitPrice; ///< 跌停价
68 : double preSettlementPrice; ///< 昨结算价
69 :
70 : // -------------------------------------------------------------------------
71 : // 构造函数
72 : // -------------------------------------------------------------------------
73 :
74 : /**
75 : * @brief 默认构造函数
76 : *
77 : * 初始化所有数值字段为 0。
78 : */
79 535 : Instrument()
80 1070 : : priceTick(0.0)
81 535 : , volumeMultiple(0)
82 535 : , marginRate(0.0)
83 535 : , upperLimitPrice(0.0)
84 535 : , lowerLimitPrice(0.0)
85 535 : , preSettlementPrice(0.0)
86 535 : {}
87 :
88 : /**
89 : * @brief 带基本参数的构造函数
90 : *
91 : * @param instId 合约代码
92 : * @param exchId 交易所代码
93 : * @param prodId 品种代码
94 : * @param tick 最小变动价位
95 : * @param multiple 合约乘数
96 : * @param margin 保证金率
97 : */
98 764 : Instrument(const std::string& instId, const std::string& exchId,
99 : const std::string& prodId, double tick, int multiple, double margin)
100 764 : : instrumentId(instId)
101 764 : , exchangeId(exchId)
102 764 : , productId(prodId)
103 764 : , priceTick(tick)
104 764 : , volumeMultiple(multiple)
105 764 : , marginRate(margin)
106 764 : , upperLimitPrice(0.0)
107 764 : , lowerLimitPrice(0.0)
108 764 : , preSettlementPrice(0.0)
109 764 : {}
110 :
111 : // -------------------------------------------------------------------------
112 : // 计算方法
113 : // -------------------------------------------------------------------------
114 :
115 : /**
116 : * @brief 计算开仓保证金
117 : *
118 : * 根据价格和数量计算所需的保证金。
119 : *
120 : * @param price 开仓价格
121 : * @param volume 开仓数量(手数)
122 : * @return 所需保证金金额
123 : *
124 : * @par 计算公式
125 : * 保证金 = 价格 × 数量 × 合约乘数 × 保证金率
126 : */
127 420 : double calculateMargin(double price, int64_t volume) const {
128 420 : return price * volume * volumeMultiple * marginRate;
129 : }
130 :
131 : /**
132 : * @brief 检查价格是否在涨跌停范围内
133 : *
134 : * 验证给定价格是否在当日涨跌停价格范围内。
135 : *
136 : * @param price 待检查的价格
137 : * @return 如果价格在有效范围内返回 true
138 : *
139 : * @note 如果涨跌停价格未设置(为0),则认为价格有效
140 : */
141 619 : bool isPriceValid(double price) const {
142 : // 如果涨跌停价格未设置,认为价格有效
143 619 : if (lowerLimitPrice <= 0 && upperLimitPrice <= 0) {
144 1 : return true;
145 : }
146 618 : return price >= lowerLimitPrice && price <= upperLimitPrice;
147 : }
148 :
149 : /**
150 : * @brief 检查价格是否符合最小变动价位
151 : *
152 : * 验证给定价格是否是最小变动价位的整数倍。
153 : *
154 : * @param price 待检查的价格
155 : * @return 如果价格符合最小变动价位返回 true
156 : *
157 : * @note 使用容差比较以处理浮点数精度问题
158 : */
159 6 : bool isPriceTickValid(double price) const {
160 6 : if (priceTick <= 0) {
161 1 : return true;
162 : }
163 5 : double remainder = std::fmod(price, priceTick);
164 : // 使用容差比较
165 5 : return remainder < 1e-9 || (priceTick - remainder) < 1e-9;
166 : }
167 :
168 : /**
169 : * @brief 更新涨跌停价格
170 : *
171 : * 从行情数据更新涨跌停价格。
172 : *
173 : * @param upper 涨停价
174 : * @param lower 跌停价
175 : */
176 732 : void updateLimitPrices(double upper, double lower) {
177 732 : upperLimitPrice = upper;
178 732 : lowerLimitPrice = lower;
179 732 : }
180 :
181 : // -------------------------------------------------------------------------
182 : // 比较操作符(用于测试)
183 : // -------------------------------------------------------------------------
184 :
185 : /**
186 : * @brief 相等比较操作符
187 : *
188 : * 比较两个合约的所有字段是否相等。
189 : *
190 : * @param other 另一个合约
191 : * @return 如果所有字段相等则返回 true
192 : *
193 : * @note 此操作符使用精确比较,适用于序列化/反序列化的 round-trip 测试。
194 : * 如需比较计算结果,请使用带容差的比较方法。
195 : */
196 102 : bool operator==(const Instrument& other) const {
197 203 : return instrumentId == other.instrumentId &&
198 202 : exchangeId == other.exchangeId &&
199 101 : productId == other.productId &&
200 101 : priceTick == other.priceTick &&
201 101 : volumeMultiple == other.volumeMultiple &&
202 101 : marginRate == other.marginRate &&
203 101 : upperLimitPrice == other.upperLimitPrice &&
204 304 : lowerLimitPrice == other.lowerLimitPrice &&
205 203 : preSettlementPrice == other.preSettlementPrice;
206 : }
207 :
208 : /**
209 : * @brief 不等比较操作符
210 : *
211 : * @param other 另一个合约
212 : * @return 如果任意字段不相等则返回 true
213 : */
214 1 : bool operator!=(const Instrument& other) const {
215 1 : return !(*this == other);
216 : }
217 : };
218 :
219 : } // namespace fix40
|