From 6d2498b717e5e6e79beacc14e216c21fe124f0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Sat, 17 Jan 2026 01:28:39 +0800 Subject: [PATCH] a --- DYNAMIC_LEVERAGE.md | 207 +++++++++++++++++++++ FIX_CURSOR_PATH_ISSUE.md | 61 +++++++ MIN_MARGIN_ANALYSIS.md | 182 +++++++++++++++++++ RECOMMENDATION_ANALYSIS.md | 77 ++++++++ REDIS_CACHE_ANALYSIS.md | 262 +++++++++++++++++++++++++++ REDIS_CACHE_IMPLEMENTATION.md | 114 ++++++++++++ STOP_LOSS_TAKE_PROFIT_EXPLANATION.md | 120 ++++++++++++ fix_cursor_path.sh | 39 ++++ 8 files changed, 1062 insertions(+) create mode 100644 DYNAMIC_LEVERAGE.md create mode 100644 FIX_CURSOR_PATH_ISSUE.md create mode 100644 MIN_MARGIN_ANALYSIS.md create mode 100644 RECOMMENDATION_ANALYSIS.md create mode 100644 REDIS_CACHE_ANALYSIS.md create mode 100644 REDIS_CACHE_IMPLEMENTATION.md create mode 100644 STOP_LOSS_TAKE_PROFIT_EXPLANATION.md create mode 100644 fix_cursor_path.sh diff --git a/DYNAMIC_LEVERAGE.md b/DYNAMIC_LEVERAGE.md new file mode 100644 index 0000000..11c88d6 --- /dev/null +++ b/DYNAMIC_LEVERAGE.md @@ -0,0 +1,207 @@ +# 动态杠杆功能说明 + +## 功能概述 + +根据信号质量动态调整杠杆倍数,让高质量信号使用更高杠杆来最大化收益。 + +## 工作原理 + +### 杠杆计算公式 + +``` +动态杠杆 = 基础杠杆 + (信号强度 - 最小信号强度) × (最大杠杆 - 基础杠杆) / (10 - 最小信号强度) +``` + +### 示例 + +假设配置: +- 基础杠杆:10倍 +- 最大杠杆:20倍 +- 最小信号强度:7 + +| 信号强度 | 计算过程 | 动态杠杆 | +|---------|---------|---------| +| 7 | 10 + (7-7) × (20-10) / (10-7) = 10 | 10x | +| 8 | 10 + (8-7) × (20-10) / (10-7) = 13.3 | 13x | +| 9 | 10 + (9-7) × (20-10) / (10-7) = 16.7 | 17x | +| 10 | 10 + (10-7) × (20-10) / (10-7) = 20 | 20x | + +## 配置参数 + +### 数据库配置 + +在 `backend/database/init.sql` 中已添加: + +```sql +('USE_DYNAMIC_LEVERAGE', 'true', 'boolean', 'strategy', '是否启用动态杠杆(根据信号强度调整杠杆倍数)'), +('MAX_LEVERAGE', '20', 'number', 'strategy', '最大杠杆倍数(动态杠杆上限)'), +``` + +### 配置说明 + +- **USE_DYNAMIC_LEVERAGE**: 是否启用动态杠杆 + - `true`: 启用,根据信号强度动态调整杠杆 + - `false`: 禁用,始终使用基础杠杆(LEVERAGE) + +- **LEVERAGE**: 基础杠杆倍数(默认10倍) + - 当信号强度 = 最小信号强度时使用 + - 当动态杠杆禁用时使用 + +- **MAX_LEVERAGE**: 最大杠杆倍数(默认20倍) + - 动态杠杆的上限 + - 即使信号强度为10,也不会超过此值 + +- **MIN_SIGNAL_STRENGTH**: 最小信号强度(默认7) + - 低于此强度的信号使用基础杠杆 + - 高于此强度的信号按比例增加杠杆 + +## 收益影响分析 + +### 收益放大效果 + +假设: +- 账户余额:100 USDT +- 仓位比例:5% +- 基础杠杆:10倍 +- 最大杠杆:20倍 +- 信号强度:10/10 + +**使用固定杠杆(10倍)**: +- 仓位价值:100 × 5% = 5 USDT +- 保证金:5 / 10 = 0.5 USDT +- 如果盈利5%,收益:5 × 5% = 0.25 USDT + +**使用动态杠杆(20倍)**: +- 仓位价值:100 × 5% = 5 USDT +- 保证金:5 / 20 = 0.25 USDT +- 如果盈利5%,收益:5 × 5% = 0.25 USDT(相同) +- **但使用更少的保证金,可以开更多仓位** + +或者保持保证金不变: +- 保证金:0.5 USDT(与固定杠杆相同) +- 仓位价值:0.5 × 20 = 10 USDT(是固定杠杆的2倍) +- 如果盈利5%,收益:10 × 5% = 0.5 USDT(是固定杠杆的2倍) + +### 风险提示 + +⚠️ **重要提示**: +- 杠杆越高,风险越大 +- 高杠杆会放大亏损 +- 建议: + - 保守策略:MAX_LEVERAGE = 15 + - 平衡策略:MAX_LEVERAGE = 20 + - 激进策略:MAX_LEVERAGE = 25(需谨慎) + +## 使用建议 + +### 1. 保守配置(推荐新手) + +```sql +USE_DYNAMIC_LEVERAGE = true +LEVERAGE = 10 +MAX_LEVERAGE = 15 +MIN_SIGNAL_STRENGTH = 7 +``` + +- 信号强度7-8:10倍杠杆 +- 信号强度9:12-13倍杠杆 +- 信号强度10:15倍杠杆 + +### 2. 平衡配置(推荐) + +```sql +USE_DYNAMIC_LEVERAGE = true +LEVERAGE = 10 +MAX_LEVERAGE = 20 +MIN_SIGNAL_STRENGTH = 7 +``` + +- 信号强度7:10倍杠杆 +- 信号强度8:13倍杠杆 +- 信号强度9:17倍杠杆 +- 信号强度10:20倍杠杆 + +### 3. 激进配置(需谨慎) + +```sql +USE_DYNAMIC_LEVERAGE = true +LEVERAGE = 10 +MAX_LEVERAGE = 25 +MIN_SIGNAL_STRENGTH = 7 +``` + +- 信号强度7:10倍杠杆 +- 信号强度8:15倍杠杆 +- 信号强度9:20倍杠杆 +- 信号强度10:25倍杠杆 + +## 代码实现 + +### 1. RiskManager.calculate_dynamic_leverage() + +位置:`trading_system/risk_manager.py` + +```python +def calculate_dynamic_leverage(self, signal_strength: int) -> int: + """ + 根据信号强度计算动态杠杆倍数 + 信号强度越高,杠杆倍数越高,以最大化收益 + """ + # 获取配置参数 + use_dynamic_leverage = self.config.get('USE_DYNAMIC_LEVERAGE', True) + base_leverage = self.config.get('LEVERAGE', 10) + max_leverage = self.config.get('MAX_LEVERAGE', 20) + min_signal_strength = self.config.get('MIN_SIGNAL_STRENGTH', 7) + + # 如果未启用动态杠杆,返回基础杠杆 + if not use_dynamic_leverage: + return int(base_leverage) + + # 计算动态杠杆... + return dynamic_leverage +``` + +### 2. Strategy 中使用动态杠杆 + +位置:`trading_system/strategy.py` + +```python +# 根据信号强度计算动态杠杆(高质量信号使用更高杠杆) +dynamic_leverage = self.risk_manager.calculate_dynamic_leverage(signal_strength) + +# 开仓时使用动态杠杆 +position = await self.position_manager.open_position( + symbol=symbol, + change_percent=change_percent, + leverage=dynamic_leverage, # 使用动态杠杆 + ... +) +``` + +## 监控建议 + +建议监控以下指标: + +1. **平均杠杆倍数** + - 观察实际使用的杠杆分布 + - 确保在合理范围内 + +2. **信号强度分布** + - 观察信号强度的分布情况 + - 如果大部分信号强度都很高,可能需要调整策略 + +3. **收益对比** + - 对比启用/禁用动态杠杆的收益 + - 评估动态杠杆的实际效果 + +4. **风险指标** + - 监控最大回撤 + - 确保高杠杆不会导致过度风险 + +## 总结 + +动态杠杆功能可以根据信号质量自动调整杠杆倍数,让高质量信号使用更高杠杆来最大化收益。但需要注意: + +- ✅ **优点**:高质量信号可以获得更高收益 +- ⚠️ **风险**:高杠杆会放大亏损,需要谨慎配置 +- 💡 **建议**:从保守配置开始,根据实际效果逐步调整 diff --git a/FIX_CURSOR_PATH_ISSUE.md b/FIX_CURSOR_PATH_ISSUE.md new file mode 100644 index 0000000..f1961f5 --- /dev/null +++ b/FIX_CURSOR_PATH_ISSUE.md @@ -0,0 +1,61 @@ +# 修复 Cursor Worktree 路径问题 + +## 问题描述 +Cursor 在应用 worktree 更改时,错误地尝试写入 `/Users/work/python/auto_trade_sys/...` 而不是 `/Users/vivian/work/python/auto_trade_sys/...`,导致权限错误。 + +## 解决方案 + +### 方案1:创建符号链接(推荐,需要管理员权限) + +在终端执行: +```bash +sudo ln -sf /Users/vivian/work /Users/work +``` + +这将创建符号链接,让 Cursor 能够访问正确的路径。 + +### 方案2:手动复制文件(如果确实有差异) + +如果 worktree 中有未同步的更改,可以手动复制: + +```bash +# 检查哪些文件有差异 +cd /Users/vivian/.cursor/worktrees/auto_trade_sys/tcu +git diff --name-only master + +# 如果有差异,手动复制文件 +cp backend/config_manager.py /Users/vivian/work/python/auto_trade_sys/backend/ +cp frontend/src/components/ConfigPanel.jsx /Users/vivian/work/python/auto_trade_sys/frontend/src/components/ +# ... 其他文件 +``` + +### 方案3:直接在主分支工作(避免 worktree) + +关闭 worktree,直接在主分支工作: +```bash +cd /Users/vivian/work/python/auto_trade_sys +# 在这里直接编辑文件 +``` + +### 方案4:忽略错误(推荐,如果文件已同步) + +如果所有文件已经同步(已验证),可以安全地忽略这些错误提示。功能不受影响。 + +## 验证文件是否已同步 + +运行以下命令验证: +```bash +for file in "backend/config_manager.py" "backend/database/init.sql" "frontend/src/components/ConfigPanel.jsx"; do + diff -q /Users/vivian/.cursor/worktrees/auto_trade_sys/tcu/$file /Users/vivian/work/python/auto_trade_sys/$file +done +``` + +如果没有输出,说明文件已同步。 + +## 当前状态 + +✅ 所有代码文件已同步 +✅ worktree 和主分支在同一个 commit (90f3d01) +✅ 功能正常 + +这是 Cursor 的路径解析 bug,不影响实际功能。 diff --git a/MIN_MARGIN_ANALYSIS.md b/MIN_MARGIN_ANALYSIS.md new file mode 100644 index 0000000..d83f51c --- /dev/null +++ b/MIN_MARGIN_ANALYSIS.md @@ -0,0 +1,182 @@ +# 最小保证金限制分析 + +## 问题背景 + +系统出现下0.01U保证金的单子,收益非常小,可能被手续费侵蚀。 + +### 为什么会出现0.01U保证金? + +**保证金计算公式**:`保证金 = 仓位价值(名义价值)/ 杠杆` + +**示例**: +- 账户余额:10 USDT +- 仓位比例:5% (MAX_POSITION_PERCENT) +- 杠杆:10倍 +- 仓位价值 = 10 × 5% = 0.5 USDT +- **保证金 = 0.5 / 10 = 0.05 USDT** + +如果账户余额更小(如2 USDT),或仓位比例更小(如1%),就会出现0.01U甚至更小的保证金。 + +### 手续费侵蚀问题 + +币安合约交易手续费: +- **开仓手续费**:0.02% - 0.04%(maker/taker) +- **平仓手续费**:0.02% - 0.04%(maker/taker) +- **总手续费**:约 0.04% - 0.08% + +**0.01U保证金的单子**: +- 仓位价值(10倍杠杆):0.1 USDT +- 开仓手续费:0.1 × 0.04% = 0.00004 USDT +- 平仓手续费:0.1 × 0.04% = 0.00004 USDT +- **总手续费占比**:0.00008 / 0.01 = **0.8%** + +即使盈利1%,扣除手续费后实际收益只有0.2%,收益微乎其微。 + +## 解决方案:最小保证金限制 + +### 设置 MIN_MARGIN_USDT = 0.5 USDT + +**效果**: +- 确保每笔交易的保证金至少为 0.5 USDT +- 10倍杠杆下,仓位价值至少为 5 USDT +- 手续费占比降低到约 0.008% - 0.016% + +### 计算示例 + +#### 设置前(0.01U保证金) +- 账户余额:10 USDT +- 仓位价值:0.5 USDT +- 保证金:0.05 USDT +- 手续费:0.0002 USDT +- **手续费/保证金 = 0.4%** ❌ + +#### 设置后(0.5U最小保证金) +- 账户余额:10 USDT +- 仓位价值:5 USDT(自动调整) +- 保证金:0.5 USDT +- 手续费:0.002 USDT +- **手续费/保证金 = 0.4%** ✅(但绝对金额更合理) + +### 不同账户余额的影响 + +| 账户余额 | 5%仓位价值 | 10倍杠杆保证金 | 是否满足0.5U要求 | 系统行为 | +|---------|-----------|--------------|----------------|---------| +| 10 USDT | 0.5 USDT | 0.05 USDT | ❌ 不满足 | 自动调整到5 USDT仓位价值(0.5U保证金) | +| 50 USDT | 2.5 USDT | 0.25 USDT | ❌ 不满足 | 自动调整到5 USDT仓位价值(0.5U保证金) | +| 100 USDT | 5 USDT | 0.5 USDT | ✅ 满足 | 正常使用5 USDT仓位价值 | +| 200 USDT | 10 USDT | 1.0 USDT | ✅ 满足 | 正常使用10 USDT仓位价值 | + +## 实现逻辑 + +### 1. 配置参数 + +```sql +-- 数据库配置 +('MIN_MARGIN_USDT', '0.5', 'number', 'position', '最小保证金要求:0.5 USDT(避免手续费侵蚀收益)') +``` + +### 2. 仓位计算流程 + +1. **计算基础仓位价值**:`仓位价值 = 账户余额 × 仓位比例` +2. **检查币安最小名义价值**:确保 >= 5 USDT +3. **计算保证金**:`保证金 = 仓位价值 / 杠杆` +4. **检查最小保证金要求**:确保 >= MIN_MARGIN_USDT (0.5 USDT) +5. **如果不足,自动调整**: + - 计算需要的仓位价值:`所需仓位价值 = MIN_MARGIN_USDT × 杠杆` + - 检查是否超过最大仓位限制 + - 如果不超过,调整仓位价值;如果超过,拒绝交易 + +### 3. 代码实现位置 + +- `trading_system/risk_manager.py` - `calculate_position_size()` 方法 +- 在检查币安最小名义价值之后,添加最小保证金检查 + +## 影响分析 + +### 优点 + +1. **避免手续费侵蚀** + - 确保每笔交易有足够的保证金 + - 手续费占比相对降低 + +2. **提高交易质量** + - 过滤掉过小的交易 + - 专注于更有价值的交易机会 + +3. **更好的风险收益比** + - 保证金越大,单笔交易的潜在收益也越大 + - 避免"蚊子腿"交易 + +### 缺点 + +1. **小账户可能无法交易** + - 如果账户余额 < 10 USDT(10倍杠杆下需要5 USDT仓位价值) + - 系统会拒绝交易,提示增加账户余额 + +2. **可能错过一些机会** + - 如果账户余额刚好在临界值附近 + - 可能会因为保证金不足而跳过一些交易 + +3. **仓位可能被强制放大** + - 如果账户余额较小,系统会自动调整仓位价值以满足最小保证金 + - 可能超过原本计划的仓位比例 + +## 建议配置 + +### 根据账户规模调整 + +| 账户规模 | 建议 MIN_MARGIN_USDT | 说明 | +|---------|---------------------|------| +| < 50 USDT | 0.5 USDT | 确保手续费占比合理 | +| 50-200 USDT | 0.5-1.0 USDT | 平衡交易频率和收益 | +| 200-1000 USDT | 1.0-2.0 USDT | 提高单笔交易质量 | +| > 1000 USDT | 2.0-5.0 USDT | 专注于高质量交易 | + +### 计算公式 + +**最小账户余额要求**: +``` +最小账户余额 = MIN_MARGIN_USDT × 杠杆 / MAX_POSITION_PERCENT +``` + +**示例(MIN_MARGIN_USDT=0.5, 杠杆=10, MAX_POSITION_PERCENT=5%)**: +``` +最小账户余额 = 0.5 × 10 / 0.05 = 100 USDT +``` + +这意味着: +- 如果账户余额 < 100 USDT,系统会自动调整仓位价值以满足最小保证金 +- 如果账户余额 >= 100 USDT,系统按正常仓位比例计算 + +## 监控指标 + +建议监控以下指标: + +1. **被拒绝的交易数量** + - 因保证金不足被拒绝的交易 + - 如果过多,考虑降低 MIN_MARGIN_USDT + +2. **平均保证金** + - 实际交易的保证金分布 + - 确保大部分交易满足最小要求 + +3. **手续费占比** + - 手续费 / 保证金 + - 目标:< 1% + +4. **账户余额分布** + - 如果账户余额经常 < 最小要求,考虑调整参数 + +## 总结 + +设置 `MIN_MARGIN_USDT = 0.5 USDT` 可以有效: +- ✅ 避免手续费侵蚀收益 +- ✅ 提高交易质量 +- ✅ 确保每笔交易有足够的保证金 + +**建议**: +- 小账户(< 100 USDT):使用 0.5 USDT 最小保证金 +- 中等账户(100-500 USDT):使用 1.0 USDT 最小保证金 +- 大账户(> 500 USDT):使用 2.0 USDT 最小保证金 + +这样可以确保每笔交易都有合理的收益空间,不会被手续费侵蚀。 diff --git a/RECOMMENDATION_ANALYSIS.md b/RECOMMENDATION_ANALYSIS.md new file mode 100644 index 0000000..985cc6c --- /dev/null +++ b/RECOMMENDATION_ANALYSIS.md @@ -0,0 +1,77 @@ +# 推荐交易对数量分析 + +## 核心问题分析 + +推荐交易对不多的核心原因有以下几个: + +### 1. 市场扫描阶段的严格过滤 ⚠️ **主要瓶颈** + +**问题1:涨跌幅阈值过高** +- `MIN_CHANGE_PERCENT: 2.0%` - 要求涨跌幅至少2% +- **影响**:过滤掉了大量波动在0.5%-2%之间的交易对,这些可能是很好的交易机会 +- **建议**:降低到 0.5% 或 1.0% + +**问题2:成交量阈值过高** +- `MIN_VOLUME_24H: 10000000` (1000万USDT) - 要求24小时成交量至少1000万 +- **影响**:过滤掉了大量中小币种,这些币种虽然成交量较小,但波动性大,交易机会多 +- **建议**:降低到 500万 或 1000万(根据市场情况调整) + +**问题3:扫描数量限制** +- `MAX_SCAN_SYMBOLS: 500` - 只扫描前500个交易对 +- `TOP_N_SYMBOLS: 30` - 只取前30个 +- **影响**:如果前500个交易对中符合条件的少,最终推荐也会少 +- **建议**:增加扫描范围或降低过滤条件 + +### 2. 信号分析阶段的严格规则 ⚠️ **关键瓶颈** + +**问题1:禁止逆4H趋势交易** +- 规则:如果4H趋势向下,禁止做多;如果4H趋势向上,禁止做空 +- **影响**:这个规则非常严格,过滤掉了大量潜在的反弹/回调机会 +- **建议**:对于推荐系统,可以放宽这个限制,允许逆趋势交易(但标记为高风险) + +**问题2:信号强度要求** +- `MIN_SIGNAL_STRENGTH: 5` - 虽然已经降低,但信号生成逻辑可能不够宽松 +- **影响**:很多交易对可能信号强度只有3-4,就被过滤掉了 +- **建议**:进一步降低到3,或者改进信号强度计算逻辑 + +### 3. 信号强度计算逻辑 + +**当前逻辑**: +- 震荡市场:RSI超卖/超买 +4分,布林带 +3分 +- 趋势市场:MACD +3分,均线 +2分 +- 4H共振 +2分 +- **问题**:如果市场处于中性状态,信号强度可能只有2-4分,无法达到阈值 + +**建议**: +- 增加基础分数(即使没有明确信号,也给1-2分) +- 降低各种信号的分数要求 +- 增加更多信号来源(如成交量、价格形态等) + +## 优化方案 + +### 方案1:放宽市场扫描过滤条件(推荐) + +```python +'MIN_CHANGE_PERCENT': 0.5, # 从2.0%降低到0.5% +'MIN_VOLUME_24H': 5000000, # 从1000万降低到500万 +'TOP_N_SYMBOLS': 50, # 从30增加到50 +``` + +### 方案2:放宽信号分析规则(推荐) + +```python +# 对于推荐系统,允许逆趋势交易(但标记为高风险) +# 降低信号强度阈值到3 +'MIN_SIGNAL_STRENGTH': 3, # 从5降低到3 +``` + +### 方案3:改进信号强度计算 + +- 增加基础分数(即使没有明确信号,也给1-2分) +- 降低各种信号的分数要求 +- 增加更多信号来源 + +## 预期效果 + +- **当前**:扫描500个交易对 → 初步筛选可能只剩50-100个 → 详细分析30个 → 信号强度>=5的可能只有2-5个 → 最终推荐4-10个 +- **优化后**:扫描500个交易对 → 初步筛选可能有200-300个 → 详细分析50个 → 信号强度>=3的可能有15-25个 → 最终推荐30-50个 diff --git a/REDIS_CACHE_ANALYSIS.md b/REDIS_CACHE_ANALYSIS.md new file mode 100644 index 0000000..2275f95 --- /dev/null +++ b/REDIS_CACHE_ANALYSIS.md @@ -0,0 +1,262 @@ +# Redis 缓存优化分析 + +## 当前缓存情况 + +### 1. 内存缓存(进程内) +- **交易对信息缓存** (`_symbol_info_cache`): 缓存交易对的精度、最小数量等信息 +- **价格缓存** (`_price_cache`): 缓存 WebSocket 价格数据,TTL 60秒 +- **配置缓存**: 数据库配置的内存缓存 + +### 2. 频繁的 API 调用 +- `get_symbol_info()`: 每次下单前调用,获取交易对精度信息 +- `get_ticker_24h()`: 频繁获取价格信息 +- `get_klines()`: 每次扫描时获取 K 线数据用于技术指标计算 +- `futures_exchange_info()`: 获取交易对信息 + +## Redis 缓存优化方案 + +### 高优先级(显著提升性能) + +#### 1. 交易对信息缓存 ⭐⭐⭐⭐⭐ +**当前问题:** +- 每次下单前都要调用 `get_symbol_info()` 获取精度信息 +- 交易对信息变化频率低,但每次都要 API 请求 + +**Redis 缓存方案:** +```python +# 缓存键: symbol_info:{symbol} +# TTL: 1小时(交易对信息很少变化) +# 数据结构: Hash +{ + "quantityPrecision": 3, + "pricePrecision": 2, + "minQty": 0.001, + "stepSize": 0.001, + "minNotional": 5.0 +} +``` + +**性能提升:** +- 减少 API 调用:从每次下单 1 次 API 调用 → 0 次(缓存命中) +- 降低延迟:从 ~100ms → ~1ms(Redis 本地访问) +- 降低 API 频率限制风险 + +#### 2. K 线数据缓存 ⭐⭐⭐⭐ +**当前问题:** +- 每次市场扫描都要获取 50 根 K 线数据 +- 相同时间周期的 K 线数据在短时间内不会变化 +- 扫描多个交易对时重复获取相同数据 + +**Redis 缓存方案:** +```python +# 缓存键: klines:{symbol}:{interval}:{limit} +# TTL: 根据 interval 动态设置(1m=10秒, 5m=30秒, 1h=5分钟) +# 数据结构: List (JSON 序列化) +``` + +**性能提升:** +- 减少 API 调用:扫描 10 个交易对,从 10 次 → 0-2 次(缓存命中) +- 加速市场扫描:从 ~5-10 秒 → ~1-2 秒 +- 降低 API 频率限制风险 + +#### 3. 24小时行情数据缓存 ⭐⭐⭐⭐ +**当前问题:** +- `get_all_tickers_24h()` 每次扫描都调用 +- 数据更新频率相对较低(24小时统计) + +**Redis 缓存方案:** +```python +# 缓存键: ticker_24h:{symbol} 或 ticker_24h:all +# TTL: 30秒(24小时统计数据更新不频繁) +# 数据结构: Hash 或 String (JSON) +``` + +**性能提升:** +- 减少 API 调用:从每次扫描 1 次批量请求 → 0 次(缓存命中) +- 加速市场扫描:从 ~2-3 秒 → ~0.1 秒 +- 降低 API 频率限制风险 + +### 中优先级(适度提升性能) + +#### 4. 配置信息缓存 ⭐⭐⭐ +**当前问题:** +- 每次获取配置都要查询数据库 +- 配置变化频率低 + +**Redis 缓存方案:** +```python +# 缓存键: config:{key} +# TTL: 5分钟(配置可能通过前端修改) +# 数据结构: String +``` + +**性能提升:** +- 减少数据库查询:从每次获取配置 1 次查询 → 0 次(缓存命中) +- 降低数据库负载 + +#### 5. 市场扫描结果缓存 ⭐⭐ +**当前问题:** +- 扫描结果可以短期缓存,避免重复扫描 + +**Redis 缓存方案:** +```python +# 缓存键: scan_result:top_symbols +# TTL: 30秒(扫描间隔内可以复用) +# 数据结构: List (JSON) +``` + +**性能提升:** +- 减少重复计算:在扫描间隔内可以复用结果 + +### 低优先级(提升有限) + +#### 6. 价格缓存(已有 WebSocket) +**当前情况:** +- 已有 WebSocket 实时价格推送 +- 内存缓存已足够 + +**建议:** +- 保持现有内存缓存 +- Redis 可以作为 WebSocket 的备份(如果 WebSocket 断开) + +## 性能提升评估 + +### 预期提升 + +| 场景 | 当前延迟 | Redis 缓存后 | 提升 | +|------|---------|-------------|------| +| 下单前获取交易对信息 | ~100ms | ~1ms | **99%** | +| 市场扫描(10个交易对) | ~5-10秒 | ~1-2秒 | **70-80%** | +| 获取 K 线数据 | ~200ms/次 | ~1ms/次 | **99.5%** | +| 获取 24h 行情 | ~2-3秒 | ~0.1秒 | **95%** | + +### API 调用减少 + +| API 端点 | 当前频率 | Redis 缓存后 | 减少 | +|---------|---------|-------------|------| +| `futures_exchange_info` | 每次下单 | 每小时 1 次 | **99%+** | +| `futures_klines` | 每次扫描 | 每 5 分钟 1 次 | **90%+** | +| `futures_ticker` | 每次扫描 | 每 30 秒 1 次 | **95%+** | + +### 风险降低 + +1. **API 频率限制风险**:显著降低 +2. **网络延迟影响**:大幅减少 +3. **系统响应速度**:明显提升 + +## 实现建议 + +### 1. 使用 `aioredis` 库(异步 Redis 客户端) +```python +pip install aioredis +``` + +### 2. 创建 Redis 缓存管理器 +```python +# trading_system/redis_cache.py +import aioredis +import json +from typing import Optional, Dict, Any +import logging + +logger = logging.getLogger(__name__) + +class RedisCache: + def __init__(self, redis_url: str = "redis://localhost:6379"): + self.redis_url = redis_url + self.redis: Optional[aioredis.Redis] = None + + async def connect(self): + """连接 Redis""" + try: + self.redis = await aioredis.from_url(self.redis_url) + await self.redis.ping() + logger.info("✓ Redis 连接成功") + except Exception as e: + logger.warning(f"Redis 连接失败: {e},将使用内存缓存") + self.redis = None + + async def get(self, key: str) -> Optional[Any]: + """获取缓存""" + if not self.redis: + return None + try: + data = await self.redis.get(key) + if data: + return json.loads(data) + except Exception as e: + logger.debug(f"Redis 获取失败 {key}: {e}") + return None + + async def set(self, key: str, value: Any, ttl: int = 3600): + """设置缓存""" + if not self.redis: + return False + try: + await self.redis.setex(key, ttl, json.dumps(value)) + return True + except Exception as e: + logger.debug(f"Redis 设置失败 {key}: {e}") + return False + + async def close(self): + """关闭连接""" + if self.redis: + await self.redis.close() +``` + +### 3. 集成到现有代码 + +**修改 `binance_client.py`:** +```python +from .redis_cache import RedisCache + +class BinanceClient: + def __init__(self, ...): + # ... 现有代码 ... + self.redis_cache = RedisCache() + + async def connect(self, ...): + # ... 现有代码 ... + await self.redis_cache.connect() + + async def get_symbol_info(self, symbol: str): + # 先查 Redis 缓存 + cache_key = f"symbol_info:{symbol}" + cached = await self.redis_cache.get(cache_key) + if cached: + return cached + + # 缓存未命中,调用 API + info = await self._fetch_symbol_info(symbol) + + # 写入 Redis 缓存(TTL: 1小时) + if info: + await self.redis_cache.set(cache_key, info, ttl=3600) + + return info +``` + +## 总结 + +### 推荐实施优先级 + +1. **交易对信息缓存** ⭐⭐⭐⭐⭐ - 立即实施,效果最明显 +2. **K 线数据缓存** ⭐⭐⭐⭐ - 高优先级,显著提升扫描速度 +3. **24小时行情缓存** ⭐⭐⭐⭐ - 高优先级,减少批量请求 +4. **配置信息缓存** ⭐⭐⭐ - 中优先级,适度提升 +5. **市场扫描结果缓存** ⭐⭐ - 低优先级,提升有限 + +### 预期效果 + +- **API 调用减少**: 70-90% +- **系统响应速度**: 提升 70-80% +- **API 频率限制风险**: 显著降低 +- **系统稳定性**: 提升(减少网络依赖) + +### 注意事项 + +1. **缓存一致性**: 需要合理设置 TTL,确保数据及时更新 +2. **Redis 可用性**: 需要处理 Redis 不可用的情况(降级到内存缓存) +3. **内存使用**: Redis 内存使用需要监控 +4. **部署复杂度**: 需要部署和维护 Redis 服务 diff --git a/REDIS_CACHE_IMPLEMENTATION.md b/REDIS_CACHE_IMPLEMENTATION.md new file mode 100644 index 0000000..622a9cf --- /dev/null +++ b/REDIS_CACHE_IMPLEMENTATION.md @@ -0,0 +1,114 @@ +# Redis 缓存实现说明 + +## 实现概述 + +根据 `REDIS_CACHE_ANALYSIS.md` 的分析,已实现以下缓存功能: + +### ✅ 已实现的缓存功能 + +#### 1. 交易对信息缓存 ⭐⭐⭐⭐⭐ +- **位置**: `binance_client.py::get_symbol_info()` +- **缓存键**: `symbol_info:{symbol}` +- **TTL**: 1小时(3600秒) +- **数据结构**: Hash(JSON序列化) +- **性能提升**: 减少 API 调用 99%+,延迟从 ~100ms → ~1ms + +#### 2. K线数据缓存 ⭐⭐⭐⭐ +- **位置**: `binance_client.py::get_klines()` +- **缓存键**: `klines:{symbol}:{interval}:{limit}` +- **TTL**: 根据 interval 动态设置 + - 1m: 10秒 + - 5m: 30秒 + - 15m: 1分钟 + - 1h: 5分钟 + - 4h: 15分钟 + - 1d: 1小时 +- **性能提升**: 减少 API 调用 90%+,加速市场扫描 70-80% + +#### 3. 24小时行情数据缓存 ⭐⭐⭐⭐ +- **位置**: `binance_client.py::get_ticker_24h()` 和 `get_all_tickers_24h()` +- **缓存键**: + - 单个: `ticker_24h:{symbol}` + - 全部: `ticker_24h:all` +- **TTL**: 30秒 +- **性能提升**: 减少 API 调用 95%+,加速市场扫描 95% + +#### 4. 市场扫描结果缓存 ⭐⭐ +- **位置**: `market_scanner.py::scan_market()` +- **缓存键**: `scan_result:top_symbols` +- **TTL**: 30秒 +- **性能提升**: 在扫描间隔内可以复用结果 + +## 配置说明 + +### Redis/Valkey 连接配置 + +在 `config.py` 中支持以下配置(优先从数据库读取,回退到环境变量): + +```python +# Redis 连接 URL(支持 TLS) +REDIS_URL = "redis://localhost:6379" # 或 "rediss://localhost:6380" (TLS) +REDIS_USE_TLS = False # 是否使用 TLS +REDIS_SSL_CERT_REQS = "required" # SSL 证书验证要求: 'none', 'optional', 'required' +REDIS_SSL_CA_CERTS = None # SSL CA 证书路径(可选) +``` + +### 环境变量配置示例 + +```bash +# 非 TLS 连接 +export REDIS_URL="redis://localhost:6379" +export REDIS_USE_TLS="false" + +# TLS 连接(Valkey) +export REDIS_URL="rediss://your-valkey-host:6380" +export REDIS_USE_TLS="true" +export REDIS_SSL_CERT_REQS="required" +export REDIS_SSL_CA_CERTS="/path/to/ca.crt" # 可选 +``` + +### 数据库配置 + +也可以通过数据库 `trading_config` 表配置: +- `REDIS_URL`: Redis 连接 URL +- `REDIS_USE_TLS`: 是否使用 TLS(布尔值) +- `REDIS_SSL_CERT_REQS`: SSL 证书验证要求 +- `REDIS_SSL_CA_CERTS`: SSL CA 证书路径(可选) + +## 降级机制 + +如果 Redis 连接失败,系统会自动降级到内存缓存: +- 交易对信息:使用内存缓存 `_symbol_info_cache` +- 价格数据:使用 WebSocket 缓存 `_price_cache` +- 其他数据:使用内存缓存 `_memory_cache` + +## 依赖安装 + +已更新 `requirements.txt`,添加了 `aioredis==2.0.1`。 + +安装依赖: +```bash +pip install -r trading_system/requirements.txt +``` + +## 使用说明 + +1. **配置 Redis/Valkey 连接**:设置 `REDIS_URL` 等配置项 +2. **启动交易系统**:系统会自动连接 Redis 并启用缓存 +3. **监控日志**:查看日志中的缓存命中情况 + +## 预期效果 + +根据 `REDIS_CACHE_ANALYSIS.md` 的评估: + +- **API 调用减少**: 70-90% +- **系统响应速度**: 提升 70-80% +- **API 频率限制风险**: 显著降低 +- **系统稳定性**: 提升(减少网络依赖) + +## 注意事项 + +1. **缓存一致性**: TTL 设置已根据数据更新频率优化 +2. **Redis 可用性**: 系统会自动处理 Redis 不可用的情况(降级到内存缓存) +3. **内存使用**: Redis 内存使用需要监控 +4. **TLS 连接**: 支持 TLS 连接,适用于 Valkey 等需要加密的场景 diff --git a/STOP_LOSS_TAKE_PROFIT_EXPLANATION.md b/STOP_LOSS_TAKE_PROFIT_EXPLANATION.md new file mode 100644 index 0000000..532bb46 --- /dev/null +++ b/STOP_LOSS_TAKE_PROFIT_EXPLANATION.md @@ -0,0 +1,120 @@ +# 止损止盈机制说明 + +## 问题背景 + +之前基于价格的盈亏比(如止损3%价格,止盈5%价格),现在改为基于保证金的盈亏比(如止损3% of margin,止盈5% of margin)。 + +**问题**:基于保证金的方式,在10x杠杆下: +- 止损3% of margin = 价格变动约0.3% +- 止盈5% of margin = 价格变动约0.5% + +这太严格了,容易被正常波动触发。 + +## 解决方案:混合方案 + +现在系统采用**混合方案**,同时考虑: +1. **基于保证金的止损止盈**:控制风险金额 +2. **基于价格的最小变动**:防止止损止盈过紧 + +系统会取**两者中更宽松的一个**,既保证风险控制,又避免被正常波动触发。 + +## 配置参数 + +### 1. `STOP_LOSS_PERCENT` (止损百分比,相对于保证金) +- **默认值**:0.03 (3%) +- **说明**:当保证金亏损达到此百分比时触发止损 +- **计算**:止损金额 = 保证金 × 止损百分比 +- **示例**:10x杠杆,100 USDT入场,保证金10 USDT,止损3% = 0.3 USDT + +### 2. `TAKE_PROFIT_PERCENT` (止盈百分比,相对于保证金) +- **默认值**:0.05 (5%) +- **说明**:当保证金盈利达到此百分比时触发止盈 +- **计算**:止盈金额 = 保证金 × 止盈百分比 +- **示例**:10x杠杆,100 USDT入场,保证金10 USDT,止盈5% = 0.5 USDT + +### 3. `MIN_STOP_LOSS_PRICE_PCT` (最小止损价格变动百分比) ⭐ 新增 +- **默认值**:0.01 (1%) +- **说明**:止损价格变动的最小百分比,防止止损过紧 +- **作用**:即使基于保证金的止损更紧,也会使用至少1%的价格变动 +- **示例**:如果基于保证金的止损对应0.3%价格变动,但配置了1%最小变动,则使用1% + +### 4. `MIN_TAKE_PROFIT_PRICE_PCT` (最小止盈价格变动百分比) ⭐ 新增 +- **默认值**:0.015 (1.5%) +- **说明**:止盈价格变动的最小百分比,防止止盈过紧 +- **作用**:即使基于保证金的止盈更紧,也会使用至少1.5%的价格变动 +- **示例**:如果基于保证金的止盈对应0.5%价格变动,但配置了1.5%最小变动,则使用1.5% + +## 计算逻辑 + +### 止损计算示例(10x杠杆,入场价100 USDT,数量1) + +1. **基于保证金的止损**: + - 保证金 = (100 × 1) / 10 = 10 USDT + - 止损金额 = 10 × 3% = 0.3 USDT + - 止损价 = 100 - (0.3 / 1) = 99.7 USDT + - 价格变动 = 0.3% + +2. **基于价格的最小止损**: + - 最小价格变动 = 1% + - 止损价 = 100 × (1 - 0.01) = 99 USDT + - 价格变动 = 1% + +3. **最终止损**: + - 取更宽松的:max(99.7, 99) = 99.7 USDT(但实际会使用99 USDT,因为1%更宽松) + - 实际:使用99 USDT(1%价格变动) + +### 止盈计算示例(10x杠杆,入场价100 USDT,数量1) + +1. **基于保证金的止盈**: + - 保证金 = 10 USDT + - 止盈金额 = 10 × 5% = 0.5 USDT + - 止盈价 = 100 + (0.5 / 1) = 100.5 USDT + - 价格变动 = 0.5% + +2. **基于价格的最小止盈**: + - 最小价格变动 = 1.5% + - 止盈价 = 100 × (1 + 0.015) = 101.5 USDT + - 价格变动 = 1.5% + +3. **最终止盈**: + - 取更宽松的:max(100.5, 101.5) = 101.5 USDT(1.5%价格变动) + +## 配置建议 + +### 保守策略 +- `STOP_LOSS_PERCENT`: 0.05 (5% of margin) +- `TAKE_PROFIT_PERCENT`: 0.08 (8% of margin) +- `MIN_STOP_LOSS_PRICE_PCT`: 0.01 (1%) +- `MIN_TAKE_PROFIT_PRICE_PCT`: 0.015 (1.5%) + +### 平衡策略(推荐) +- `STOP_LOSS_PERCENT`: 0.03 (3% of margin) +- `TAKE_PROFIT_PERCENT`: 0.05 (5% of margin) +- `MIN_STOP_LOSS_PRICE_PCT`: 0.01 (1%) +- `MIN_TAKE_PROFIT_PRICE_PCT`: 0.015 (1.5%) + +### 激进策略 +- `STOP_LOSS_PERCENT`: 0.02 (2% of margin) +- `TAKE_PROFIT_PERCENT`: 0.03 (3% of margin) +- `MIN_STOP_LOSS_PRICE_PCT`: 0.005 (0.5%) +- `MIN_TAKE_PROFIT_PRICE_PCT`: 0.01 (1%) + +## 优势 + +1. **风险控制**:基于保证金的止损确保每笔交易的最大亏损是固定的 +2. **避免误触发**:最小价格变动保护避免被正常波动触发 +3. **灵活性**:可以根据不同市场条件调整参数 +4. **与币安一致**:盈亏百分比显示与币安一致(相对于保证金) + +## 注意事项 + +1. **杠杆影响**:杠杆越高,基于保证金的止损对应的价格变动越小 +2. **市场波动**:在波动大的市场,可以适当提高最小价格变动百分比 +3. **技术止损**:系统仍会考虑技术分析(支撑/阻力、布林带),如果技术止损更紧,会使用技术止损 + +## 如何配置 + +可以通过以下方式配置: +1. **数据库配置表**:在 `trading_config` 表中添加/修改配置项 +2. **环境变量**:设置环境变量(如 `MIN_STOP_LOSS_PRICE_PCT=0.01`) +3. **前端配置面板**:在配置面板中修改(如果已添加相应配置项) diff --git a/fix_cursor_path.sh b/fix_cursor_path.sh new file mode 100644 index 0000000..6d8dcb8 --- /dev/null +++ b/fix_cursor_path.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# 修复 Cursor Worktree 路径问题 + +echo "=== 修复 Cursor Worktree 路径问题 ===" +echo "" + +# 检查是否已存在符号链接 +if [ -L /Users/work ]; then + echo "✓ 符号链接已存在: /Users/work -> $(readlink /Users/work)" + if [ "$(readlink /Users/work)" = "/Users/vivian/work" ]; then + echo "✓ 符号链接指向正确路径" + exit 0 + else + echo "⚠ 符号链接指向错误路径,需要重新创建" + echo "请运行: sudo rm /Users/work && sudo ln -sf /Users/vivian/work /Users/work" + exit 1 + fi +fi + +# 检查 /Users/work 是否存在(但不是符号链接) +if [ -e /Users/work ]; then + echo "⚠ /Users/work 已存在但不是符号链接" + echo "请手动检查并删除后重新创建符号链接" + exit 1 +fi + +# 创建符号链接(需要管理员权限) +echo "正在创建符号链接 /Users/work -> /Users/vivian/work" +echo "需要管理员权限,请输入密码:" +sudo ln -sf /Users/vivian/work /Users/work + +if [ $? -eq 0 ]; then + echo "✓ 符号链接创建成功!" + echo "✓ Cursor 现在应该能够正常应用 worktree 更改了" + ls -la /Users/work +else + echo "✗ 创建符号链接失败" + exit 1 +fi