Skip to main content

futu_backend/trade_query/orders/
fill_projection.rs

1//! trade_query/orders/fill_projection — backend fill proto -> OrderFillInfo rows.
2
3use futu_domain_trade_history::admission::{
4    BackendHistoryFillAdmissionFacts, backend_history_fill_is_admissible_like_cpp,
5};
6use futu_domain_trade_history::projection::backend_fills::{
7    BackendTradeReadOrderFillFacts, project_backend_trade_read_order_fill_like_cpp,
8};
9use futu_domain_trade_history::projection::scalars::backend_real_market_to_trd_market_like_cpp;
10
11use crate::proto_internal::odr_sys_cmn;
12
13use super::types::OrderFillInfo;
14
15pub fn order_fill_proto_to_info_with_market_and_jp_acc_type(
16    f: &odr_sys_cmn::OrderFill,
17    trd_market: Option<i32>,
18    jp_acc_type: Option<i32>,
19) -> OrderFillInfo {
20    let projected =
21        project_backend_trade_read_order_fill_like_cpp(BackendTradeReadOrderFillFacts {
22            fill_id_ex: f.id.as_deref(),
23            order_id_ex: f.order_id.as_deref(),
24            side: f.side,
25            market: f.market,
26            code: f.symbol.as_deref(),
27            stock_name: f.stock_name.as_deref(),
28            qty: f.qty.as_deref(),
29            price: f.price.as_deref(),
30            original_qty: f.original_qty.as_deref(),
31            original_price: f.original_price.as_deref(),
32            create_time_micros: f.create_time,
33            update_time_micros: f.update_time,
34            market_id: None,
35            counter_broker_id: f.counter_broker_id.as_deref(),
36            counter_broker_name: f.counter_broker_name.as_deref(),
37            local_counter_broker_name: None,
38            is_cancelled: f.is_cancelled,
39            is_corrected: f.is_corrected,
40            input_source: f.input_source,
41            jp_acc_type,
42        });
43
44    OrderFillInfo {
45        fill_id: projected.fill_id,
46        fill_id_ex: projected.fill_id_ex,
47        order_id: projected.order_id.unwrap_or(0),
48        order_id_ex: projected.order_id_ex.unwrap_or_default(),
49        code: projected.code,
50        name: projected.name,
51        trd_side: projected.trd_side,
52        qty: projected.qty,
53        price: projected.price,
54        create_timestamp: projected.create_timestamp,
55        update_timestamp: projected.update_timestamp,
56        counter_broker_id: projected.counter_broker_id,
57        status: projected.status,
58        trd_market,
59        jp_acc_type: projected.jp_acc_type,
60    }
61}
62
63/// Backend `odr_sys_cmn::OrderFill` -> OpenD cache/API `OrderFillInfo`.
64///
65/// Ref: FutuOpenD/Src/NNProtoCenter/Trade/Deal/NNProto_Trd_DealReal.cpp:13-122.
66/// C++ `UnPackDealItem` drops rows unless `id/side/market/symbol/exchange/
67/// price/qty/create_time` are present, `price/qty` parse as doubles, and the
68/// real-account market passes `IsValidTrdMarket(NN_TrdEnv_Real, market)`.
69///
70/// Simulated deal query is unsupported in C++ (`NNProto_Trd_DealSimulate.cpp:13-67`),
71/// while `NOTICE_TYPE_ORDER_FILL_NTF` also calls `DealReal::UnPackDealList`, so
72/// Rust uses the same real deal row gate for query-cache and direct-push paths.
73pub fn try_order_fill_proto_to_info_like_cpp(f: &odr_sys_cmn::OrderFill) -> Option<OrderFillInfo> {
74    try_order_fill_proto_to_info_with_jp_acc_type_like_cpp(f, None)
75}
76
77pub fn try_order_fill_proto_to_info_with_jp_acc_type_like_cpp(
78    f: &odr_sys_cmn::OrderFill,
79    jp_acc_type: Option<i32>,
80) -> Option<OrderFillInfo> {
81    let trd_market = f.market.map(backend_real_market_to_trd_market_like_cpp);
82    if !backend_history_fill_is_admissible_like_cpp(BackendHistoryFillAdmissionFacts {
83        fill_id: f.id.as_deref(),
84        side: f.side,
85        projected_trd_market: trd_market,
86        symbol: f.symbol.as_deref(),
87        exchange: f.exchange.as_deref(),
88        price: f.price.as_deref(),
89        qty: f.qty.as_deref(),
90        create_time_micros: f.create_time,
91    }) {
92        return None;
93    }
94
95    Some(order_fill_proto_to_info_with_market_and_jp_acc_type(
96        f,
97        trd_market,
98        jp_acc_type,
99    ))
100}