futucli/cmd/trade_ext/
hints.rs1use futu_core::error::FutuError;
2
3pub(crate) fn translate_trade_ret_msg(ret_msg: &str) -> Option<String> {
14 let m = ret_msg.trim();
16
17 if m.contains("请重新解锁交易") || m.contains("请先解锁交易") || m.contains("未解锁交易")
19 {
20 return Some(
21 "建议: futucli unlock-trade --pwd <md5(交易密码)> \
22 (写路径需先解锁;2FA 账户用 --totp <6位数字>)"
23 .to_string(),
24 );
25 }
26
27 if m.contains("余额不足") || m.contains("可用资金") || m.contains("资金不足") {
29 return Some(
30 "建议: futucli funds --acc-id <ID> --env real 查看可用资金;\
31 下单 qty × price 需 ≤ 可用资金(含手续费 buffer)"
32 .to_string(),
33 );
34 }
35
36 if m.contains("交易未启用") || m.contains("交易未开通") || m.contains("未开通交易")
38 {
39 return Some(
40 "建议: futu-opend 启动时需走完 unlock-trade 流程;\
41 或 daemon 起得太新还没拿到 cipher,等 30s 重试"
42 .to_string(),
43 );
44 }
45
46 if m.contains("代码不存在")
48 || m.contains("标的代码错误")
49 || m.contains("代码错误")
50 || m.contains("证券不存在")
51 || m.contains("无效代码")
52 || m.contains("找不到证券")
53 {
54 return Some(
55 "建议: 检查 prefix (HK./US./SH./SZ.) 是否正确;\
56 用 `futucli static-info --code <CODE> --market <MK>` 验证代码存在"
57 .to_string(),
58 );
59 }
60
61 if m.contains("市场已休市") || m.contains("非交易时段") || m.contains("休市") {
63 return Some(
64 "建议: 用 `futucli market-state --market <MK>` 确认当前 trading hours;\
65 盘前 / 盘后单需明确 session 字段"
66 .to_string(),
67 );
68 }
69
70 if m.contains("最小变动")
72 || m.contains("最小交易单位")
73 || m.contains("交易单位")
74 || m.contains("整手")
75 || m.contains("不符合最小")
76 {
77 return Some(
78 "建议: HK 股票按手(lot size)整数倍下单(如 700 至少 100 股);\
79 用 `futucli static-info --code <CODE>` 查 lot_size"
80 .to_string(),
81 );
82 }
83
84 if m.contains("价格超出") || m.contains("涨跌停") || m.contains("价格不在") {
85 return Some(
86 "建议: 价格需在涨跌停范围内;用 `futucli snapshot --code <CODE>` \
87 查 highest_price / lowest_price 边界"
88 .to_string(),
89 );
90 }
91
92 if m.contains("持仓不足") || m.contains("可卖") || m.contains("持仓数量") {
94 return Some(
95 "建议: futucli positions --acc-id <ID> --env real 查可卖数量;\
96 T+1 / 港股交收 settled qty 才可卖出"
97 .to_string(),
98 );
99 }
100
101 None
103}
104
105pub(crate) fn emit_trade_hint_if_known(err: &anyhow::Error) {
114 if let Some(FutuError::ServerError { ret_type: _, msg }) = err.downcast_ref::<FutuError>()
116 && let Some(hint) = translate_trade_ret_msg(msg)
117 {
118 eprintln!("💡 Hint: {hint}");
119 }
120}