This commit is contained in:
薇薇安 2026-02-14 23:39:19 +08:00
parent 0a9377f5ac
commit 7df054f638
4 changed files with 148 additions and 6 deletions

View File

@ -37,3 +37,14 @@ else:
4. **错误提示**日志里「分析超时10秒」多是因为当时已被限频/封禁导致请求挂起或失败,解封后一般会恢复。
解封后若仍偶发 -1003可先等 12 分钟再跑,或临时增大 `SCAN_INTERVAL` 再观察。
---
## 获取持仓/成交超时TimeoutError
若日志出现「获取持仓信息最终失败 (已重试 7 次): TimeoutError」或「获取成交记录失败 XXX (已重试 5 次): TimeoutError」
1. **网络/限频**:与 -1003 类似,可能是当时网络抖动或请求排队,重试已用 60 秒超时 × 多轮;过几分钟通常恢复。
2. **适当拉长只读超时**(可选):在运行交易进程的环境里设置环境变量
`READ_ONLY_REQUEST_TIMEOUT=90`(默认 60 秒),只读接口(持仓、成交、交易对信息)单次等待时间会变长,**不影响下单/止损止盈的快速失败**。
3. **本次已做**:获取交易对信息(如 ENAUSDT增加 60 秒超时 + 3 次重试;获取成交记录后几次重试间隔改为 2 秒;开仓失败时会打出完整异常与堆栈,便于排查。

View File

@ -0,0 +1,109 @@
# 交易表现分析 2026-02-14
## 一、数据概览
### 1. 20 点之后入场且已平仓(晚间段)
- **14 笔**,总盈亏 **-1.91 USDT**,胜率 **28.6%**4 盈 8 亏 2 平)
- 平仓类型:自动止损 5 笔(-2.01)、同步平仓 4 笔(-0.75)、手动平仓 4 笔(+1.03)、移动止损 1 笔(-0.17
- **特征**20:00~20:28 集中开仓多为「MACD金叉 + RSI超买 反向做空」HYPEUSDT BUY 一笔 -1.31 止损(顺势多)。晚间段胜率、盈亏均差于全天,需单独关注。
### 2. 21 点之后平仓订单
- **仅 1 笔**XPLUSDT BUY入场 22:17自动止损盈亏 **-0.26 USDT**
- 样本太少,与 20 点段合并为「晚间段」一起看改进即可。
### 3. 全量已平仓96 笔)
| 平仓类型 | 笔数 | 总盈亏 (USDT) |
|--------------------|------|----------------|
| 自动平仓(止损) | 32 | **-13.68** |
| 手动平仓 | 28 | +15.99 |
| 同步平仓 | 17 | -1.93 |
| 自动平仓(止盈) | 11 | -4.04 |
| 自动平仓(移动止损)| 8 | +3.48 |
- **总盈亏**:约 +0.08 USDT几乎打平
- **胜率**36.8%BUY 36.4%SELL 36.5%
- **主要问题**止损笔数多32 笔)、亏损集中(-13.68);止盈 11 笔合计仍为负(-4.04),说明止盈单里存在“先盈后亏”或手续费侵蚀。
### 4. 当前持仓(持仓记录 16 个)
- **合计浮盈/亏****-5.46 USDT**
- 多数为 SELL部分 BUYHYPEUSDT、KITEUSDT、CLOUSDT浮亏。
---
## 二、亏损单特征(入场原因 Top
1. **MACD死叉 + 价格在EMA20之下**3 笔)—— 顺势做空在震荡/反弹里被扫。
2. **RSI超买反向做空**(多笔,如 RSI 69.7~79.5 ≥65—— “上升趋势 + RSI超买反空”在强趋势中容易连续止损。
3. **sync_recovered**2 笔)—— 补建仓后被动平仓,需确认是否为系统单、价格是否合理。
结论:**止损占比高、胜率偏低**,与“逆势/震荡中开仓”和“RSI 反向在趋势中触发”关联大。
---
## 三、可落地的改进建议
### 1. RSI 反向:只在 4H 中性时做(优先)
- **现状**`RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H = False`上升趋势里也会“RSI 超买反空”,易被趋势继续拉高打止损。
- **建议**:改为 **True**,仅在 4H 为中性时允许 RSI 超买反空/超卖反多,减少趋势中逆势单。
- **配置项**:全局配置 → 策略参数 → `RSI 反向仅允许 4H 中性` 设为 **是**
### 2. 提高开仓信号门槛(减少低质量单)
- **现状**`MIN_SIGNAL_STRENGTH = 8`,止损 32 笔说明仍有不少“可做可不做”的单子。
- **建议**:提高到 **9**,只做最强信号,减少笔数、提高单笔质量。
- **配置项**:全局配置 → `MIN_SIGNAL_STRENGTH` 设为 **9**
### 3. 止损略放宽(给波动留空间)
- **现状**`ATR_STOP_LOSS_MULTIPLIER = 3.0`32 笔止损 -13.68 可能包含“刚打止损就反向”的噪音。
- **建议**:试 **3.2 或 3.5**,单笔亏损略大但减少“被洗出”次数,观察 1~2 天胜率与总盈亏再微调。
- **配置项**:全局配置 → 风险控制 → `ATR 止损倍数` 设为 **3.2****3.5**
### 4. 止盈与第一目标(观察即可)
- 11 笔止盈总盈亏为负,可能原因:部分止盈后剩余仓位被止损、或手续费。建议先观察,若持续出现可再考虑:
- 略提高 `TAKE_PROFIT_1_PERCENT`(如 25%~30%),让更多单在“第一目标”就了结一部分利润;
- 或检查移动止损与止盈的衔接,避免“先触发移动止损再被扫”。
### 5. 同步平仓 17 笔 -1.93
- 确认是否为“系统单 + 币安已平”的同步;若是,可接受。若包含非系统单误同步,需在同步逻辑里继续用 `SYSTEM_ORDER_ID_PREFIX` 等严格区分。
---
## 四、晚间段20 点之后)改进方案
20 点之后 14 笔、胜率 28.6%、总盈亏 -1.91,明显弱于全天,可做**针对性收紧**
### 方案 A通用收紧优先不改代码
- 沿用第三节的 **RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H = True**、**MIN_SIGNAL_STRENGTH = 9**、**ATR_STOP_LOSS_MULTIPLIER = 3.2~3.5**。
- 晚间大量是「RSI 超买反空」被扫,限制为 4H 中性才反向 + 只做强度 9+,会自然减少 20 点后的低质量开仓。
### 方案 B晚间提高信号门槛需加配置
- 若希望**仅晚间更严**,可增加配置项,例如:
- `EVENING_HOURS_START` / `EVENING_HOURS_END`(如 20、24 表示 20:00~24:00 北京时间);
- `EVENING_MIN_SIGNAL_STRENGTH`(如 9 或 10该时段内仅当信号强度 ≥ 该值才开仓。
- 实现方式:在 `strategy.py` 开仓前根据当前北京时间是否落在晚间区间,动态用 `max(MIN_SIGNAL_STRENGTH, EVENING_MIN_SIGNAL_STRENGTH)` 做过滤。
- 未加该配置前,用方案 A 即可。
### 方案 C晚间少开或不开 RSI 反向(折中)
- 在现有「RSI 反向仅 4H 中性」基础上,若仍发现晚间 RSI 反向单亏损多,可再加一条:**20:00~24:00 不允许 RSI 反向开仓**(只做顺势单)。需在策略里按当前小时判断并跳过 RSI 反向逻辑。
**建议执行顺序**:先做 **方案 A**(三档全局参数),观察 1~2 天;若晚间段仍偏弱,再考虑加 **方案 B**(晚间信号门槛)或 **方案 C**(晚间关闭 RSI 反向)。
---
## 五、建议的配置调整汇总(可直接在全局配置里改)
| 配置项 | 当前建议 | 说明 |
|--------|----------|------|
| RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H | **True** | 仅 4H 中性时 RSI 反向,减少趋势中摸顶/抄底 |
| MIN_SIGNAL_STRENGTH | **9** | 只做最强信号,减少止损笔数 |
| ATR_STOP_LOSS_MULTIPLIER | **3.2****3.5** | 略放宽止损,减少噪音止损 |
改完后**清除全局缓存 + 重启所有账号交易**,让配置生效;观察 1~2 天再微调。
---
## 六、关于“晚间没有明显盈利”
- **20 点之后** 14 笔、胜率 28.6%、总盈亏 -1.91明显差于全天36.8%、+0.08)。
- 晚间集中出现「RSI 超买反向做空」+ 多笔同步平仓/止损,说明该时段要么少做、要么只做更高置信度信号。
- 优先做 **第四节 方案 A**RSI 仅 4H 中性 + 信号强度 9 + 止损 3.2~3.5),观察全时段与晚间是否一起改善;若晚间仍弱,再考虑 **方案 B晚间信号门槛****方案 C晚间关闭 RSI 反向)**

View File

@ -865,8 +865,9 @@ class BinanceClient:
isinstance(e, BinanceAPIException) and (e.code == -1021 or str(e.code).startswith('5'))
)
if is_retryable and attempt < retries - 1:
logger.warning(f"获取成交记录失败 {symbol} (第 {attempt + 1}/{retries} 次): {_format_exception(e)}1秒后重试...")
await asyncio.sleep(1)
wait = 2 if attempt >= 2 else 1 # 后几次多等 1 秒,给网络恢复时间
logger.warning(f"获取成交记录失败 {symbol} (第 {attempt + 1}/{retries} 次): {_format_exception(e)}{wait}秒后重试...")
await asyncio.sleep(wait)
continue
break
except Exception as e:
@ -913,9 +914,29 @@ class BinanceClient:
self._symbol_info_cache[symbol] = cached
return cached
# 3. 缓存未命中,调用 API
# 3. 缓存未命中,调用 API加超时与重试避免网络抖动导致开仓前获取交易对信息失败
read_timeout = getattr(config, 'READ_ONLY_REQUEST_TIMEOUT', 60)
last_err = None
for attempt in range(3):
try:
exchange_info = await asyncio.wait_for(
self.client.futures_exchange_info(),
timeout=read_timeout
)
break
except (asyncio.TimeoutError, BinanceAPIException, OSError) as e:
last_err = e
if attempt < 2:
logger.warning(f"获取 exchange_info 失败 (第 {attempt + 1}/3 次): {_format_exception(e)}1秒后重试...")
await asyncio.sleep(1)
continue
logger.error(f"获取 {symbol} 交易对信息失败 (已重试 3 次): {_format_exception(e)}")
return None
except Exception as e:
logger.error(f"获取 {symbol} 交易对信息失败: {_format_exception(e)}")
return None
try:
exchange_info = await self.client.futures_exchange_info()
for s in exchange_info['symbols']:
if s['symbol'] == symbol:
# 提取数量/价格精度信息
@ -975,7 +996,7 @@ class BinanceClient:
logger.warning(f"未找到交易对 {symbol} 的信息")
return None
except Exception as e:
logger.error(f"获取 {symbol} 交易对信息失败: {e}")
logger.error(f"获取 {symbol} 交易对信息失败: {_format_exception(e)}")
return None
def _adjust_quantity_precision(self, quantity: float, symbol_info: Dict) -> float:

View File

@ -805,7 +805,8 @@ class PositionManager:
return None
except Exception as e:
logger.error(f"开仓失败 {symbol}: {e}")
err_msg = str(e).strip() if str(e) else f"{type(e).__name__}(无详情)"
logger.error(f"开仓失败 {symbol}: {err_msg}", exc_info=True)
return None
async def close_position(self, symbol: str, reason: str = 'manual') -> bool: