Skip to main content

futu_cache/trd_cache/
jp_sub_account.rs

1use std::collections::HashSet;
2
3use super::*;
4
5impl TrdCache {
6    /// Replace JP sub-account id/type mapping after an account-list refresh.
7    pub fn set_jp_sub_account_types<I>(&self, entries: I)
8    where
9        I: IntoIterator<Item = (AccKey, u64, i32)>,
10    {
11        self.jp_sub_account_types.clear();
12        for (acc_id, sub_account_id, jp_acc_type) in entries {
13            self.jp_sub_account_types
14                .insert((acc_id, sub_account_id), jp_acc_type);
15        }
16    }
17
18    /// Resolve backend order `sub_account_id` to public FTAPI `jp_acc_type`.
19    ///
20    /// Account protocol documents JP cash as `sub_account_id=0` and
21    /// `SubAccountType=0`, but account list does not send a cash sub-account
22    /// row. Preserve that convention when backend order rows explicitly carry
23    /// `sub_account_id=0`.
24    #[must_use]
25    pub fn jp_acc_type_for_sub_account(&self, acc_id: AccKey, sub_account_id: u64) -> Option<i32> {
26        if sub_account_id == 0 {
27            return Some(0);
28        }
29        self.jp_sub_account_types
30            .get(&(acc_id, sub_account_id))
31            .map(|entry| *entry.value())
32    }
33
34    /// Resolve public FTAPI `jp_acc_type` back to backend sub-account id.
35    ///
36    /// C++ JP combo trade-write paths call
37    /// `Ndt_Trd_AccItem::GetSubAccIDByType`; this cache side index is populated
38    /// from the same account-list sub-account rows and is used only when a
39    /// backend request must carry `pos_sub_account_id` / `sub_account_id`.
40    #[must_use]
41    pub fn sub_account_for_jp_acc_type(&self, acc_id: AccKey, jp_acc_type: i32) -> Option<u64> {
42        if jp_acc_type == 0 {
43            return Some(0);
44        }
45        self.jp_sub_account_types.iter().find_map(|entry| {
46            let ((entry_acc_id, sub_account_id), entry_type) = (*entry.key(), *entry.value());
47            (entry_acc_id == acc_id && entry_type == jp_acc_type).then_some(sub_account_id)
48        })
49    }
50
51    pub fn jp_sub_account_type_entries_for_accounts(
52        &self,
53        acc_ids: &HashSet<AccKey>,
54    ) -> Vec<(AccKey, u64, i32)> {
55        self.jp_sub_account_types
56            .iter()
57            .filter_map(|entry| {
58                let ((acc_id, sub_account_id), jp_acc_type) = (*entry.key(), *entry.value());
59                acc_ids
60                    .contains(&acc_id)
61                    .then_some((acc_id, sub_account_id, jp_acc_type))
62            })
63            .collect()
64    }
65}