auto_trade_sys/CONFIG_ARCHITECTURE_VERIFICATION.md
薇薇安 1032295052 a
2026-01-25 09:16:16 +08:00

283 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 配置架构验证文档
## 📋 验证目标
确认:
1.**所有用户下的账户都使用全局策略配置**
2.**普通用户无法通过自己的配置直接影响核心策略参数**
---
## 🏗️ 配置架构设计
### 1. 配置层级
```
┌─────────────────────────────────────────────────────────┐
│ 全局策略账号 (account_id=1, 默认) │
│ - 存储所有核心策略参数 │
│ - 例如ATR_STOP_LOSS_MULTIPLIER, ATR_TAKE_PROFIT_... │
└─────────────────────────────────────────────────────────┘
↓ 读取
┌─────────────────────────────────────────────────────────┐
│ 用户账户 (account_id=2, 3, 4...) │
│ - 存储风险旋钮(每个账户独立) │
│ - 例如MAX_POSITION_PERCENT, AUTO_TRADE_ENABLED... │
└─────────────────────────────────────────────────────────┘
```
### 2. 配置读取逻辑
**位置**`backend/config_manager.py` 的 `get_trading_config()` 方法
```python
def eff_get(key: str, default: Any):
"""
策略核心默认从全局账号读取GLOBAL_STRATEGY_ACCOUNT_ID
风险旋钮:从当前账号读取。
"""
# API key/secret/testnet 永远按账号读取
if key in RISK_KNOBS_KEYS or global_mgr is None:
return self.get(key, default) # 从当前账号读取
try:
# 从全局账号读取
return global_mgr.get(key, default)
except Exception:
return self.get(key, default)
```
**风险旋钮列表**`RISK_KNOBS_KEYS`
- `MIN_MARGIN_USDT`
- `MIN_POSITION_PERCENT`
- `MAX_POSITION_PERCENT`
- `MAX_TOTAL_POSITION_PERCENT`
- `AUTO_TRADE_ENABLED`
- `MAX_OPEN_POSITIONS`
- `MAX_DAILY_ENTRIES`
**核心策略参数**(从全局账号读取):
- `ATR_STOP_LOSS_MULTIPLIER`
- `ATR_TAKE_PROFIT_MULTIPLIER`
- `RISK_REWARD_RATIO`
- `USE_FIXED_RISK_SIZING`
- `FIXED_RISK_PERCENT`
- `USE_DYNAMIC_ATR_MULTIPLIER`
- `MIN_SIGNAL_STRENGTH`
- `SCAN_INTERVAL`
- `TOP_N_SYMBOLS`
- ... 等等所有非风险旋钮的配置
---
## 🔒 权限控制
### 1. 后端API权限控制
**位置**`backend/api/routes/config.py`
#### GET `/api/config` - 获取配置列表
```python
# 普通用户:只展示风险旋钮 + 账号密钥
# 管理员:若当前不是"全局策略账号",同样只展示风险旋钮
is_admin = (user.get("role") or "user") == "admin"
gid = _global_strategy_account_id()
if (not is_admin) or (is_admin and int(account_id) != int(gid)):
allowed = set(USER_RISK_KNOBS) | {"BINANCE_API_KEY", "BINANCE_API_SECRET", "USE_TESTNET"}
result = {k: v for k, v in result.items() if k in allowed}
```
**验证**
- ✅ 普通用户只能看到 `USER_RISK_KNOBS` + API密钥
- ✅ 管理员在非全局策略账号时,也只能看到风险旋钮
- ✅ 只有管理员在全局策略账号时,才能看到所有配置
#### PUT `/api/config/{key}` - 更新单个配置
```python
# 管理员:若不是全局策略账号,则禁止修改策略核心
if (user.get("role") or "user") == "admin":
gid = _global_strategy_account_id()
if int(account_id) != int(gid):
if key not in (USER_RISK_KNOBS | {"BINANCE_API_KEY", "BINANCE_API_SECRET", "USE_TESTNET"}):
raise HTTPException(status_code=403, detail=f"该配置由全局策略账号 #{gid} 统一管理")
# 产品模式:普通用户只能改"风险旋钮"与账号私有密钥/测试网
if (user.get("role") or "user") != "admin":
if key not in (USER_RISK_KNOBS | {"BINANCE_API_KEY", "BINANCE_API_SECRET", "USE_TESTNET"}):
raise HTTPException(status_code=403, detail="该配置由平台统一管理(仅管理员可修改)")
```
**验证**
- ✅ 普通用户尝试修改核心策略参数会返回 403 错误
- ✅ 管理员在非全局策略账号时,也无法修改核心策略参数
- ✅ 只有管理员在全局策略账号时,才能修改核心策略参数
#### POST `/api/config/batch` - 批量更新配置
```python
for item in configs:
# 管理员:若不是全局策略账号,则批量只允许风险旋钮/密钥
if (user.get("role") or "user") == "admin":
gid = _global_strategy_account_id()
if int(account_id) != int(gid):
if item.key not in (USER_RISK_KNOBS | {"BINANCE_API_KEY", "BINANCE_API_SECRET", "USE_TESTNET"}):
errors.append(f"{item.key}: 该配置由全局策略账号 #{gid} 统一管理,请切换账号修改")
continue
# 产品模式:普通用户只能改"风险旋钮"与账号私有密钥/测试网
if (user.get("role") or "user") != "admin":
if item.key not in (USER_RISK_KNOBS | {"BINANCE_API_KEY", "BINANCE_API_SECRET", "USE_TESTNET"}):
errors.append(f"{item.key}: 该配置由平台统一管理(仅管理员可修改)")
continue
```
**验证**
- ✅ 普通用户批量更新时,核心策略参数会被过滤并返回错误
- ✅ 管理员在非全局策略账号时,核心策略参数也会被过滤
---
## ✅ 验证结果
### 1. 所有账户使用全局策略配置 ✅
**验证点**
- `config_manager.py``get_trading_config()` 方法中,所有非风险旋钮的配置都通过 `eff_get()` 从全局账号读取
- 即使普通用户在自己的账户中设置了核心策略参数,也不会生效(因为读取时从全局账号读取)
**代码位置**
- `backend/config_manager.py:509-522`
**结论**:✅ **所有账户都使用全局策略配置**
---
### 2. 普通用户无法修改核心策略参数 ✅
**验证点**
- **前端限制**普通用户在配置页面只能看到风险旋钮通过API过滤
- **后端限制**
- GET `/api/config`:只返回风险旋钮
- PUT `/api/config/{key}`:尝试修改核心参数返回 403
- POST `/api/config/batch`:核心参数被过滤并返回错误
**代码位置**
- `backend/api/routes/config.py:273-280` (GET)
- `backend/api/routes/config.py:645-655` (PUT)
- `backend/api/routes/config.py:765-776` (POST)
**结论**:✅ **普通用户无法通过自己的配置直接影响核心策略参数**
---
## 📊 配置分类总结
### 风险旋钮(每个账户独立)
- `MIN_MARGIN_USDT` - 最小保证金USDT
- `MIN_POSITION_PERCENT` - 最小仓位占比
- `MAX_POSITION_PERCENT` - 最大仓位占比
- `MAX_TOTAL_POSITION_PERCENT` - 总仓位占比上限
- `AUTO_TRADE_ENABLED` - 自动交易开关
- `MAX_OPEN_POSITIONS` - 同时持仓数量上限
- `MAX_DAILY_ENTRIES` - 每日最多开仓次数
### 核心策略参数(全局统一)
- `ATR_STOP_LOSS_MULTIPLIER` - ATR止损倍数
- `ATR_TAKE_PROFIT_MULTIPLIER` - ATR止盈倍数
- `RISK_REWARD_RATIO` - 盈亏比
- `USE_FIXED_RISK_SIZING` - 使用固定风险百分比
- `FIXED_RISK_PERCENT` - 固定风险百分比
- `USE_DYNAMIC_ATR_MULTIPLIER` - 动态ATR倍数
- `MIN_SIGNAL_STRENGTH` - 最小信号强度
- `SCAN_INTERVAL` - 扫描间隔
- `TOP_N_SYMBOLS` - 每次扫描处理的交易对数量
- ... 等等所有非风险旋钮的配置
### 账号私有配置(每个账户独立)
- `BINANCE_API_KEY` - 币安API密钥
- `BINANCE_API_SECRET` - 币安API密钥
- `USE_TESTNET` - 是否使用测试网
---
## 🎯 实际运行验证
### 测试场景1普通用户查看配置
1. 普通用户登录
2. 进入配置页面
3. **预期**:只能看到风险旋钮 + API密钥配置
4. **验证**:前端只显示允许的配置项
### 测试场景2普通用户尝试修改核心策略参数
1. 普通用户登录
2. 尝试通过API修改 `ATR_STOP_LOSS_MULTIPLIER`
3. **预期**:返回 403 错误:"该配置由平台统一管理(仅管理员可修改)"
4. **验证**:后端拒绝修改请求
### 测试场景3管理员在非全局策略账号修改核心策略参数
1. 管理员登录
2. 切换到非全局策略账号(如 account_id=2
3. 尝试修改 `ATR_STOP_LOSS_MULTIPLIER`
4. **预期**:返回 403 错误:"该配置由全局策略账号 #1 统一管理,请切换到该账号修改"
5. **验证**:后端拒绝修改请求
### 测试场景4管理员在全局策略账号修改核心策略参数
1. 管理员登录
2. 切换到全局策略账号account_id=1
3. 修改 `ATR_STOP_LOSS_MULTIPLIER = 2.5`
4. **预期**:修改成功
5. **验证**:所有账户的交易系统都会使用新的值(通过 `config_manager.get_trading_config()` 读取)
---
## 🔍 代码检查清单
- [x] `backend/config_manager.py` - 配置读取逻辑使用全局账号
- [x] `backend/api/routes/config.py` - API权限控制
- [x] `frontend/src/components/ConfigPanel.jsx` - 前端配置页面(依赖后端过滤)
- [x] `frontend/src/components/GlobalConfig.jsx` - 管理员全局配置页面
---
## ✅ 最终结论
1.**所有用户下的账户都使用全局策略配置**
- 通过 `config_manager.get_trading_config()``eff_get()` 函数实现
- 核心策略参数从全局账号account_id=1读取
- 风险旋钮从当前账号读取
2.**普通用户无法通过自己的配置直接影响核心策略参数**
- 前端:只能看到风险旋钮
- 后端:尝试修改核心参数会返回 403 错误
- 即使数据库中有值,读取时也会从全局账号读取
3.**管理员权限控制**
- 管理员在非全局策略账号时,也只能修改风险旋钮
- 只有管理员在全局策略账号时,才能修改核心策略参数
---
## 📝 注意事项
1. **全局策略账号ID**:默认是 `account_id=1`,可通过环境变量 `ATS_GLOBAL_STRATEGY_ACCOUNT_ID` 修改
2. **配置缓存**:配置存储在 Redis 中,修改后需要确保 Redis 缓存已更新
3. **配置生效**:修改全局策略配置后,所有账户的交易系统会在下次 `reload_from_redis()` 时读取新值
4. **风险旋钮的作用**:虽然核心策略参数是全局的,但每个账户可以通过风险旋钮控制:
- 仓位大小MAX_POSITION_PERCENT
- 交易频率MAX_DAILY_ENTRIES
- 同时持仓数量MAX_OPEN_POSITIONS
- 是否启用自动交易AUTO_TRADE_ENABLED
---
## 🎯 建议
1. **定期检查**:定期验证全局策略账号的配置是否正确
2. **配置快照**:在修改全局策略配置前,先导出配置快照作为备份
3. **测试环境**:在测试环境验证配置修改的效果,再应用到生产环境
4. **文档更新**:修改配置后,及时更新相关文档