1use futu_cache::trd_cache::CachedOrder;
4use futu_domain_trade_history::projection::backend_orders::{
5 BackendOrderSupFacts, BackendTradeReadOrderFacts, project_backend_trade_read_order_like_cpp,
6};
7use futu_domain_trade_history::projection::combo::{
8 HistoryOrderComboFacts, HistoryOrderComboLegFacts, ProjectedHistoryOrderComboLeg,
9};
10use futu_domain_trade_history::projection::orders::{
11 BackendOrderUnpackFacts, project_backend_order_unpacked_trd_market_like_cpp,
12};
13use futu_domain_trade_order::{OrderWireExtensionFacts, project_order_wire_extensions_like_cpp};
14
15use crate::proto_internal::{odr_sys_cmn, sim_odr_sys_cmn};
16
17pub fn order_proto_to_cached_like_cpp(trd_env: i32, o: &odr_sys_cmn::Order) -> Option<CachedOrder> {
18 order_proto_to_cached_with_jp_acc_type_like_cpp(trd_env, o, None)
19}
20
21pub fn order_proto_to_cached_with_jp_acc_type_like_cpp(
22 trd_env: i32,
23 o: &odr_sys_cmn::Order,
24 jp_acc_type: Option<i32>,
25) -> Option<CachedOrder> {
26 let trd_market = project_backend_order_unpacked_trd_market_like_cpp(BackendOrderUnpackFacts {
27 trd_env,
28 has_order_id: o.order_id.is_some(),
29 has_side: o.side.is_some(),
30 market: o.market,
31 has_symbol: o.symbol.is_some(),
32 has_create_time: o.create_time.is_some(),
33 has_expire_time: o.expire_time.is_some(),
34 has_status: o.status.is_some(),
35 })?;
36 let order_trade_time_type = o.sup.as_ref().and_then(|s| s.order_trade_time_type);
37 let combo = o
38 .multi_leg_info
39 .as_ref()
40 .map(|multi_leg| HistoryOrderComboFacts {
41 backend_strategy_type: multi_leg.strategy_type,
42 legs: multi_leg
43 .leg_infos
44 .iter()
45 .map(|leg| HistoryOrderComboLegFacts {
46 symbol: leg.leg_symbol.as_deref(),
47 exchange: leg.leg_exchange.as_deref(),
48 side: leg.leg_side,
49 ratio_qty: leg.leg_ratio_qty.as_deref(),
50 position_id: leg.position_id.as_deref(),
51 })
52 .collect(),
53 });
54 let sup = o.sup.as_ref();
55 let wire_extensions = project_order_wire_extensions_like_cpp(OrderWireExtensionFacts {
56 cash_order_qty: o.cash_order_qty.as_deref(),
57 has_condition: o.condition.is_some(),
58 portfolio_stock_id: o.portfolio_stock_id,
59 has_margin_trade_info: o.margin_trade_info.is_some(),
60 event_contract_quote_id: o
61 .order_extra
62 .as_ref()
63 .and_then(|extra| extra.quote_id.as_deref()),
64 });
65 let projected = project_backend_trade_read_order_like_cpp(BackendTradeReadOrderFacts {
66 trd_env,
67 sim_option_account: trd_env == 0 && matches!(o.market, Some(7 | 9)),
68 trd_market_ftapi: trd_market,
69 ex_destination: o.exdestination,
70 exchange: o.exchange.as_deref(),
71 order_type_trd_market_ftapi: trd_market,
72 currency: o.currency.map(|c| c as i32),
73 jp_acc_type,
74 app_lang: 0,
75 order_id_ex: o.order_id.as_deref(),
76 side: o.side,
77 order_type: o.r#type,
78 security_type: o.security_type,
79 status: o.status,
80 code: o.symbol.as_deref(),
81 stock_name: o.stock_name.as_deref(),
82 qty: o.qty.as_deref(),
83 price: o.price.as_deref(),
84 create_time_micros: o.create_time,
85 update_time_micros: o.update_time,
86 market_id: o.exchange_code,
87 cum_qty: o.cum_qty.as_deref(),
88 avg_fill_price: o.avg_fill_price.as_deref(),
89 last_err_msg: o.last_err_msg.as_deref(),
90 text: o.text.as_deref(),
91 aux_price: o.aux_price.as_deref(),
92 expire_time_micros: o.expire_time,
93 order_amount: o.order_amount.as_deref(),
94 sup: BackendOrderSupFacts {
95 order_trade_time_type,
96 time_in_force: sup.and_then(|value| value.time_in_force),
97 odr_enable_ba_trade: sup.and_then(|value| value.odr_enable_ba_trade),
98 hk_odr_enable_ba_trade: sup.and_then(|value| value.hk_odr_enable_ba_trade),
99 trail_type: sup.and_then(|value| value.trail_type),
100 trail_percent: sup.and_then(|value| value.trail_percent.as_deref()),
101 trail_price: sup.and_then(|value| value.trail_price.as_deref()),
102 },
103 combo,
104 });
105
106 Some(CachedOrder {
107 order_id: projected.order_id,
108 order_id_ex: projected.order_id_ex,
109 code: projected.code,
110 name: o.stock_name.as_ref().cloned().unwrap_or(projected.name),
113 trd_side: projected.trd_side,
114 order_type: projected.order_type,
115 backend_order_type_raw: o.r#type,
116 lot_type: o.lot_type,
117 order_status: projected.order_status,
118 qty: projected.qty,
119 price: projected.price.unwrap_or(0.0),
120 fill_qty: projected.fill_qty,
121 fill_avg_price: projected.fill_avg_price,
122 create_time: projected.create_time,
123 update_time: projected.update_time,
124 last_err_msg: projected.last_err_msg,
125 sec_market: projected.sec_market,
126 create_timestamp: projected.create_timestamp,
127 update_timestamp: projected.update_timestamp,
128 remark: projected.remark,
129 backend_text: o.text.clone(),
130 time_in_force: projected.time_in_force,
131 fill_outside_rth: projected.fill_outside_rth,
132 aux_price: projected.aux_price,
133 trail_type: projected.trail_type,
134 trail_value: projected.trail_value,
135 trail_spread: projected.trail_spread,
136 currency: projected.currency,
137 trd_market: projected.trd_market,
138 strategy_type: projected.strategy_type,
139 combo_legs: projected
140 .combo_legs
141 .into_iter()
142 .map(combo_leg_data_domain_to_api_like_cpp)
143 .collect(),
144 parent_order_id_ex: o.parent_order_id.clone(),
145 legacy_group_id: o.group_id.clone(),
146 relation_type: o.relation_type,
147 order_group_id: o.order_group_id.clone(),
148 order_group_type_raw: o.group_type,
149 quote_id: wire_extensions
150 .event_contract_quote_id
151 .map(ToOwned::to_owned),
152 backend_order_id: o.order_id.clone().unwrap_or_default(),
153 order_version: o.version.unwrap_or(0) as i32,
154 exchange_code: o.exchange_code.unwrap_or(0) as i32,
155 exchange: o.exchange.clone().unwrap_or_default(),
156 security_type: o.security_type.unwrap_or(0) as i32,
157 session: projected.session,
158 order_trade_time_type,
159 sub_account_id: o.sub_account_id,
160 jp_acc_type: projected.jp_acc_type,
161 is_stub: false,
162 is_local_order: false,
163 stub_inserted_at_ms: 0,
164 is_pending_broker_confirm: false,
165 })
166}
167
168fn combo_leg_data_domain_to_api_like_cpp(
169 leg: ProjectedHistoryOrderComboLeg,
170) -> futu_proto::qot_common::ComboLeg {
171 futu_proto::qot_common::ComboLeg {
172 security: futu_proto::qot_common::Security {
173 market: leg.qot_market,
174 code: leg.code,
175 },
176 side: leg.side,
177 qty_ratio: leg.qty_ratio,
178 position_id: leg.position_id,
179 pred_side: None,
184 }
185}
186
187pub(crate) fn sim_order_proto_to_cached_like_cpp(
188 trd_env: i32,
189 o: &sim_odr_sys_cmn::Order,
190) -> Option<CachedOrder> {
191 let trd_market = project_backend_order_unpacked_trd_market_like_cpp(BackendOrderUnpackFacts {
192 trd_env,
193 has_order_id: o.order_id.is_some(),
194 has_side: o.side.is_some(),
195 market: o.market,
196 has_symbol: o.symbol.is_some(),
197 has_create_time: o.create_time.is_some(),
198 has_expire_time: o.expire_time.is_some(),
199 has_status: o.status.is_some(),
200 })?;
201
202 let order_trade_time_type = o.sup.as_ref().and_then(|s| s.order_trade_time_type);
203 let sup = o.sup.as_ref();
204 let projected = project_backend_trade_read_order_like_cpp(BackendTradeReadOrderFacts {
205 trd_env,
206 sim_option_account: trd_env == 0 && matches!(o.market, Some(7 | 9)),
207 trd_market_ftapi: trd_market,
208 ex_destination: o.exdestination,
209 exchange: o.exchange.as_deref(),
210 order_type_trd_market_ftapi: trd_market,
211 currency: o.currency.map(|c| c as i32),
212 jp_acc_type: o.sub_account.map(|v| v as i32),
213 app_lang: 0,
214 order_id_ex: o.order_id.as_deref(),
215 side: o.side,
216 order_type: o.r#type,
217 security_type: o.security_type,
218 status: o.status,
219 code: o.symbol.as_deref(),
220 stock_name: o.stock_name.as_deref(),
221 qty: o.qty.as_deref(),
222 price: o.price.as_deref(),
223 create_time_micros: o.create_time,
224 update_time_micros: o.update_time,
225 market_id: o.exchange_code,
226 cum_qty: o.cum_qty.as_deref(),
227 avg_fill_price: o.avg_fill_price.as_deref(),
228 last_err_msg: o.last_err_msg.as_deref(),
229 text: o.text.as_deref(),
230 aux_price: o.aux_price.as_deref(),
231 expire_time_micros: o.expire_time,
232 order_amount: o.order_amount.as_deref(),
233 sup: BackendOrderSupFacts {
234 order_trade_time_type,
235 time_in_force: sup.and_then(|value| value.time_in_force),
236 odr_enable_ba_trade: sup.and_then(|value| value.odr_enable_ba_trade),
237 hk_odr_enable_ba_trade: sup.and_then(|value| value.hk_odr_enable_ba_trade),
238 trail_type: sup.and_then(|value| value.trail_type),
239 trail_percent: sup.and_then(|value| value.trail_percent.as_deref()),
240 trail_price: sup.and_then(|value| value.trail_price.as_deref()),
241 },
242 combo: None,
243 });
244
245 Some(CachedOrder {
246 order_id: projected.order_id,
247 order_id_ex: projected.order_id_ex.clone(),
248 code: projected.code,
249 name: projected.name,
250 trd_side: projected.trd_side,
251 order_type: projected.order_type,
252 backend_order_type_raw: o.r#type,
253 lot_type: o.lot_type,
254 order_status: projected.order_status,
255 qty: projected.qty,
256 price: projected.price.unwrap_or(0.0),
257 fill_qty: projected.fill_qty,
258 fill_avg_price: projected.fill_avg_price,
259 create_time: projected.create_time,
260 update_time: projected.update_time,
261 last_err_msg: projected.last_err_msg,
262 sec_market: projected.sec_market,
263 create_timestamp: projected.create_timestamp,
264 update_timestamp: projected.update_timestamp,
265 remark: projected.remark,
266 backend_text: o.text.clone(),
267 time_in_force: projected.time_in_force,
268 fill_outside_rth: projected.fill_outside_rth,
269 aux_price: projected.aux_price,
270 trail_type: projected.trail_type,
271 trail_value: projected.trail_value,
272 trail_spread: projected.trail_spread,
273 currency: projected.currency,
274 trd_market: projected.trd_market,
275 strategy_type: None,
276 combo_legs: Vec::new(),
277 parent_order_id_ex: o.parent_order_id.clone(),
278 legacy_group_id: o.group_id.clone(),
279 relation_type: o.relation_type,
280 order_group_id: o.order_group_id.clone(),
281 order_group_type_raw: o.group_type,
282 quote_id: None,
283 backend_order_id: projected.order_id_ex,
284 order_version: o.version.unwrap_or(0) as i32,
285 exchange_code: o.exchange_code.unwrap_or(0) as i32,
286 exchange: o.exchange.clone().unwrap_or_default(),
287 security_type: o.security_type.unwrap_or(0) as i32,
288 session: projected.session,
289 order_trade_time_type,
290 sub_account_id: None,
291 jp_acc_type: projected.jp_acc_type,
292 is_stub: false,
293 is_local_order: false,
294 stub_inserted_at_ms: 0,
295 is_pending_broker_confirm: false,
296 })
297}