futu_cache/
trd_cache.rs

1// 交易数据缓存
2
3use dashmap::DashMap;
4
5/// 账户 key: acc_id
6pub type AccKey = u64;
7
8/// 缓存的账户信息
9#[derive(Debug, Clone)]
10pub struct CachedTrdAcc {
11    pub acc_id: u64,
12    pub trd_env: i32,
13    pub trd_market_auth_list: Vec<i32>,
14    pub acc_type: Option<i32>,
15    pub card_num: Option<String>,
16    pub security_firm: Option<i32>,
17    pub sim_acc_type: Option<i32>,
18    pub uni_card_num: Option<String>,
19    pub acc_status: Option<i32>,
20    pub acc_role: Option<i32>,
21    pub jp_acc_type: Vec<i32>,
22    // --- 以下为审计补全的字段 ---
23    /// 账户所有者 UID
24    pub owner_uid: Option<u64>,
25    /// 账户操作者 UID
26    pub opr_uid: Option<u64>,
27    /// 混合状态 (C++ enAccState / MixedState)
28    pub mixed_state: Option<i32>,
29    /// IRA 类型 (CA: TFSA=1, RRSP=2, SRRSP=3)
30    pub ira_type: Option<i32>,
31    /// 授权状态 (GrantState)
32    pub grant_state: Option<i32>,
33    /// 口座类型 (JP: Cash=1, Margin=2, Derivative=3)
34    pub kouza_type: Option<i32>,
35    /// 交易市场 (Account.market, 单个值)
36    pub trd_market: Option<i32>,
37    /// 关联账户 ID (基金账户绑定)
38    pub association_acc_id: Option<u64>,
39    /// 综合账户子账户标志 (0=非子账户)
40    pub acc_flag: Option<i32>,
41    /// 原始顺序索引 (用于保持后端返回的自然顺序)
42    pub order_index: usize,
43    /// C++ 排序 key: (BrokerID << 48) | (TrdMkt << 32) | IntraAccID
44    pub sort_key: u64,
45}
46
47/// 缓存的资金 (对齐 C++ Ndt_Trd_AccFund 全字段)
48#[derive(Debug, Clone, Default)]
49pub struct CachedFunds {
50    pub power: f64,                      // 最大做多购买力
51    pub total_assets: f64,               // 资产净值
52    pub cash: f64,                       // 现金
53    pub market_val: f64,                 // 证券市值
54    pub frozen_cash: f64,                // 冻结资金
55    pub debt_cash: f64,                  // 欠款金额
56    pub avl_withdrawal_cash: f64,        // 可提金额
57    pub currency: Option<i32>,           // 货币类型
58    pub available_funds: Option<f64>,    // 可用资金 (期货)
59    pub unrealized_pl: Option<f64>,      // 未实现盈亏 (期货)
60    pub realized_pl: Option<f64>,        // 已实现盈亏 (期货)
61    pub risk_level: Option<i32>,         // 风险等级
62    pub initial_margin: Option<f64>,     // 初始保证金
63    pub maintenance_margin: Option<f64>, // 维持保证金
64    pub max_power_short: Option<f64>,    // 最大做空购买力
65    pub net_cash_power: Option<f64>,     // 现金购买力
66    pub long_mv: Option<f64>,            // 多头市值
67    pub short_mv: Option<f64>,           // 空头市值
68    pub pending_asset: Option<f64>,      // 在途资产
69    pub max_withdrawal: Option<f64>,     // 最大可提
70    pub risk_status: Option<i32>,        // 风险状态码
71    pub margin_call_margin: Option<f64>, // margin call 保证金
72    pub securities_assets: Option<f64>,  // 证券资产
73    pub fund_assets: Option<f64>,        // 基金资产
74    pub bond_assets: Option<f64>,        // 债券资产
75    /// 分币种现金信息: (currency, cash, avl_withdrawal, net_cash_power)
76    pub cash_info_list: Vec<CachedCashInfo>,
77    /// 分市场资产信息: (trd_market, assets)
78    pub market_info_list: Vec<CachedMarketInfo>,
79}
80
81/// 分币种现金信息
82#[derive(Debug, Clone, Default)]
83pub struct CachedCashInfo {
84    pub currency: i32,
85    pub cash: f64,
86    pub available_balance: f64,
87    pub net_cash_power: f64,
88}
89
90/// 分市场资产信息
91#[derive(Debug, Clone, Default)]
92pub struct CachedMarketInfo {
93    pub trd_market: i32,
94    pub assets: f64,
95}
96
97/// 缓存的持仓 (对齐 C++ Ndt_Trd_AccPosition 全字段)
98#[derive(Debug, Clone, Default)]
99pub struct CachedPosition {
100    pub position_id: u64,
101    pub position_side: i32, // 0=多仓, 1=空仓
102    pub code: String,
103    pub name: String,
104    pub qty: f64,
105    pub can_sell_qty: f64,
106    pub price: f64,                      // 当前价
107    pub cost_price: f64,                 // 摊薄成本价
108    pub val: f64,                        // 市值
109    pub pl_val: f64,                     // 盈亏金额
110    pub pl_ratio: Option<f64>,           // 盈亏比例
111    pub sec_market: Option<i32>,         // 证券市场
112    pub td_pl_val: Option<f64>,          // 今日盈亏
113    pub td_trd_val: Option<f64>,         // 今日成交额
114    pub td_buy_val: Option<f64>,         // 今日买入金额
115    pub td_buy_qty: Option<f64>,         // 今日买入数量
116    pub td_sell_val: Option<f64>,        // 今日卖出金额
117    pub td_sell_qty: Option<f64>,        // 今日卖出数量
118    pub unrealized_pl: Option<f64>,      // 未实现盈亏 (期货)
119    pub realized_pl: Option<f64>,        // 已实现盈亏 (期货)
120    pub currency: Option<i32>,           // 货币
121    pub trd_market: Option<i32>,         // 交易市场
122    pub diluted_cost_price: Option<f64>, // 摊薄成本
123    pub average_cost_price: Option<f64>, // 平均成本
124    pub average_pl_ratio: Option<f64>,   // 平均盈亏比例
125}
126
127/// 缓存的订单 (对齐 C++ Ndt_Trd_Order 全字段)
128#[derive(Debug, Clone, Default)]
129pub struct CachedOrder {
130    pub order_id: u64,
131    pub order_id_ex: String, // 服务端订单 ID 字符串
132    pub code: String,
133    pub name: String,
134    pub trd_side: i32,
135    pub order_type: i32,
136    pub order_status: i32,
137    pub qty: f64,
138    pub price: f64,
139    pub fill_qty: f64,
140    pub fill_avg_price: f64,
141    pub create_time: String,
142    pub update_time: String,
143    pub last_err_msg: Option<String>,   // 最后错误信息
144    pub sec_market: Option<i32>,        // 证券市场
145    pub create_timestamp: Option<f64>,  // 创建时间戳
146    pub update_timestamp: Option<f64>,  // 更新时间戳
147    pub remark: Option<String>,         // 备注
148    pub time_in_force: Option<i32>,     // 有效期类型
149    pub fill_outside_rth: Option<bool>, // 是否允许盘前盘后成交
150    pub aux_price: Option<f64>,         // 触发价格
151    pub trail_type: Option<i32>,        // 跟踪类型
152    pub trail_value: Option<f64>,       // 跟踪值
153    pub trail_spread: Option<f64>,      // 跟踪价差
154    pub currency: Option<i32>,          // 货币
155    pub trd_market: Option<i32>,        // 交易市场
156}
157
158/// 交易数据缓存
159pub struct TrdCache {
160    /// 账户列表
161    pub accounts: DashMap<AccKey, CachedTrdAcc>,
162    /// 资金: acc_id → funds
163    pub funds: DashMap<AccKey, CachedFunds>,
164    /// 持仓: acc_id → Vec<position>
165    pub positions: DashMap<AccKey, Vec<CachedPosition>>,
166    /// 当日订单: acc_id → Vec<order>
167    pub orders: DashMap<AccKey, Vec<CachedOrder>>,
168    /// 交易 cipher: acc_id → cipher bytes (解锁后获得)
169    pub ciphers: DashMap<AccKey, Vec<u8>>,
170}
171
172impl TrdCache {
173    pub fn get_cipher(&self, acc_id: u64) -> Option<Vec<u8>> {
174        self.ciphers.get(&acc_id).map(|v| v.clone())
175    }
176
177    pub fn set_cipher(&self, acc_id: u64, cipher: Vec<u8>) {
178        self.ciphers.insert(acc_id, cipher);
179    }
180
181    pub fn new() -> Self {
182        Self {
183            accounts: DashMap::new(),
184            funds: DashMap::new(),
185            positions: DashMap::new(),
186            orders: DashMap::new(),
187            ciphers: DashMap::new(),
188        }
189    }
190
191    pub fn set_accounts(&self, accounts: Vec<CachedTrdAcc>) {
192        self.accounts.clear();
193        for (idx, mut acc) in accounts.into_iter().enumerate() {
194            acc.order_index = idx;
195            self.accounts.insert(acc.acc_id, acc);
196        }
197    }
198
199    pub fn get_accounts(&self) -> Vec<CachedTrdAcc> {
200        self.accounts.iter().map(|e| e.value().clone()).collect()
201    }
202
203    pub fn update_funds(&self, acc_id: u64, funds: CachedFunds) {
204        self.funds.insert(acc_id, funds);
205    }
206
207    pub fn update_positions(&self, acc_id: u64, positions: Vec<CachedPosition>) {
208        self.positions.insert(acc_id, positions);
209    }
210
211    pub fn update_orders(&self, acc_id: u64, orders: Vec<CachedOrder>) {
212        self.orders.insert(acc_id, orders);
213    }
214
215    /// 更新单个订单(推送场景)
216    pub fn upsert_order(&self, acc_id: u64, order: CachedOrder) {
217        let mut entry = self.orders.entry(acc_id).or_default();
218        if let Some(existing) = entry.iter_mut().find(|o| o.order_id == order.order_id) {
219            *existing = order;
220        } else {
221            entry.push(order);
222        }
223    }
224}
225
226impl Default for TrdCache {
227    fn default() -> Self {
228        Self::new()
229    }
230}