Skip to main content

futu_cache/trd_cache/
order_broker.rs

1use super::*;
2use futu_domain_trade_account::{
3    OrderBrokerActiveOrderFacts, OrderBrokerPruneAction, OrderBrokerPruneFacts,
4    OrderBrokerRecordAction, OrderBrokerRecordFacts, OrderBrokerRehomeAction,
5    OrderBrokerRehomeFacts, plan_order_broker_prune_action, plan_order_broker_record_action,
6    plan_order_broker_rehome_action,
7};
8
9impl TrdCache {
10    pub fn record_order_broker(
11        &self,
12        acc_id: AccKey,
13        order_id_ex: impl AsRef<str>,
14        broker_id: u32,
15    ) {
16        let OrderBrokerRecordAction::Record {
17            normalized_order_id_ex,
18        } = plan_order_broker_record_action(OrderBrokerRecordFacts {
19            order_id_ex: order_id_ex.as_ref(),
20        })
21        else {
22            return;
23        };
24        let order_id_ex = normalized_order_id_ex.to_string();
25        let previous_acc = self
26            .order_broker_accounts
27            .insert(order_id_ex.clone(), acc_id);
28        if let OrderBrokerRehomeAction::RemoveOldAccIndex { old_acc_id } =
29            plan_order_broker_rehome_action(OrderBrokerRehomeFacts {
30                previous_acc,
31                new_acc: acc_id,
32            })
33        {
34            self.remove_order_broker_id_from_acc_index(old_acc_id, &order_id_ex);
35        }
36        self.order_broker_ids_by_acc
37            .entry(acc_id)
38            .or_default()
39            .insert(order_id_ex.clone());
40        self.order_brokers.insert(order_id_ex, broker_id);
41    }
42
43    fn remove_order_broker_id_from_acc_index(&self, acc_id: AccKey, order_id_ex: &str) {
44        let mut remove_bucket = false;
45        if let Some(mut ids) = self.order_broker_ids_by_acc.get_mut(&acc_id) {
46            ids.remove(order_id_ex);
47            remove_bucket = ids.is_empty();
48        }
49        if remove_bucket {
50            self.order_broker_ids_by_acc
51                .remove_if(&acc_id, |_, ids| ids.is_empty());
52        }
53    }
54
55    pub(super) fn prune_order_brokers_for_acc(&self, acc_id: AccKey) {
56        if self.order_brokers.is_empty() {
57            return;
58        }
59
60        let prune_actions = {
61            let orders = self.orders.get(&acc_id);
62            let active_orders = orders
63                .as_ref()
64                .map(|entry| {
65                    entry
66                        .value()
67                        .iter()
68                        .map(|order| OrderBrokerActiveOrderFacts {
69                            order_id_ex: &order.order_id_ex,
70                            backend_order_id: &order.backend_order_id,
71                        })
72                        .collect::<Vec<_>>()
73                })
74                .unwrap_or_default();
75
76            let Some(order_ids) = self.order_broker_ids_by_acc.get(&acc_id) else {
77                return;
78            };
79            order_ids
80                .iter()
81                .map(|order_id_ex| {
82                    let mapping_owner_is_changed_acc = self
83                        .order_broker_accounts
84                        .get(order_id_ex.as_str())
85                        .is_some_and(|entry| *entry.value() == acc_id);
86                    let action = plan_order_broker_prune_action(OrderBrokerPruneFacts {
87                        broker_order_id_ex: order_id_ex,
88                        mapping_owner_is_changed_acc,
89                        active_orders: &active_orders,
90                    });
91                    (order_id_ex.clone(), action)
92                })
93                .filter(|(_, action)| *action != OrderBrokerPruneAction::Keep)
94                .collect::<Vec<_>>()
95        };
96
97        for (order_id_ex, action) in prune_actions {
98            match action {
99                OrderBrokerPruneAction::Keep => {}
100                OrderBrokerPruneAction::RemoveBrokerMappingAndAccIndex => {
101                    self.order_broker_accounts.remove(&order_id_ex);
102                    self.order_brokers.remove(&order_id_ex);
103                    self.remove_order_broker_id_from_acc_index(acc_id, &order_id_ex);
104                }
105                OrderBrokerPruneAction::RemoveAccIndexOnly => {
106                    self.remove_order_broker_id_from_acc_index(acc_id, &order_id_ex);
107                }
108            }
109        }
110    }
111}