Skip to main content

futu_cache/trd_cache/
order_upsert.rs

1use super::{CachedOrder, TrdCache};
2use futu_domain_trade_account::{
3    BackendOrderIdentityFacts, OrderUpsertAction, OrderUpsertOrderFacts,
4    backend_order_identity_matches_like_cpp, plan_order_upsert_like_cpp,
5};
6
7impl TrdCache {
8    /// Update or insert a single order for push-driven order state.
9    pub fn upsert_order(&self, acc_id: u64, order: CachedOrder) -> bool {
10        let mut entry = self.orders.entry(acc_id).or_default();
11        if let Some(existing) = entry
12            .iter_mut()
13            .find(|existing| Self::order_identity_matches(existing, &order))
14        {
15            match plan_order_upsert_like_cpp(
16                Some(Self::order_upsert_facts(existing)),
17                Self::order_upsert_facts(&order),
18            ) {
19                OrderUpsertAction::ReplaceExisting => {
20                    *existing = order;
21                    true
22                }
23                OrderUpsertAction::IgnoreStaleVersion
24                | OrderUpsertAction::IgnoreAuthoritativeExisting
25                | OrderUpsertAction::IgnoreUnchanged => false,
26                OrderUpsertAction::InsertNew => unreachable!("existing order was already matched"),
27            }
28        } else {
29            match plan_order_upsert_like_cpp(None, Self::order_upsert_facts(&order)) {
30                OrderUpsertAction::InsertNew => {
31                    entry.push(order);
32                    true
33                }
34                OrderUpsertAction::ReplaceExisting
35                | OrderUpsertAction::IgnoreStaleVersion
36                | OrderUpsertAction::IgnoreAuthoritativeExisting
37                | OrderUpsertAction::IgnoreUnchanged => {
38                    unreachable!("missing order should plan an insert")
39                }
40            }
41        }
42    }
43
44    fn order_identity_matches(existing: &CachedOrder, incoming: &CachedOrder) -> bool {
45        backend_order_identity_matches_like_cpp(BackendOrderIdentityFacts {
46            existing_order_id: existing.order_id,
47            existing_backend_order_id: &existing.backend_order_id,
48            existing_order_id_ex: &existing.order_id_ex,
49            incoming_order_id: incoming.order_id,
50            incoming_backend_order_id: &incoming.backend_order_id,
51            incoming_order_id_ex: &incoming.order_id_ex,
52        })
53    }
54
55    fn order_upsert_facts(order: &CachedOrder) -> OrderUpsertOrderFacts<'_> {
56        OrderUpsertOrderFacts {
57            order_version: order.order_version,
58            order_status: order.order_status,
59            price: order.price,
60            qty: order.qty,
61            fill_qty: order.fill_qty,
62            aux_price: order.aux_price,
63            trail_type: order.trail_type,
64            trail_value: order.trail_value,
65            trail_spread: order.trail_spread,
66            is_stub: order.is_stub,
67            is_local_order: order.is_local_order,
68            is_pending_broker_confirm: order.is_pending_broker_confirm,
69            backend_order_id: &order.backend_order_id,
70            order_id_ex: &order.order_id_ex,
71        }
72    }
73}