优化交易的止盈亏损问题

This commit is contained in:
薇薇安 2026-02-04 15:00:12 +08:00
parent 922a8f3820
commit f8eca1ed59
2 changed files with 86 additions and 5 deletions

41
analyze_bad_trades.py Normal file
View File

@ -0,0 +1,41 @@
import json
import sys
def analyze_trades(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as f:
trades = json.load(f)
except Exception as e:
print(f"Error reading file: {e}")
return
print(f"Analyzing {len(trades)} trades...")
tp_losses = []
sync_exits = []
for t in trades:
pnl = t.get('盈亏', 0)
reason = t.get('离场原因', '')
duration = t.get('持仓时长分钟')
if reason == 'take_profit' and pnl < 0:
tp_losses.append(t)
if reason == 'sync' and duration == 0:
sync_exits.append(t)
print("\n[Anomalies 1: Negative PnL with 'take_profit' reason]")
for t in tp_losses:
print(f"ID: {t.get('交易ID')} | Symbol: {t.get('交易对')} | Side: {t.get('方向')} | "
f"Entry: {t.get('入场价')} | Exit: {t.get('出场价')} | "
f"PnL: {t.get('盈亏')} | TP Price: {t.get('止盈价')}")
print("\n[Anomalies 2: Immediate Sync Exits (Duration 0)]")
for t in sync_exits:
print(f"ID: {t.get('交易ID')} | Symbol: {t.get('交易对')} | PnL: {t.get('盈亏')} | "
f"Entry Time: {t.get('入场时间')} | Exit Time: {t.get('平仓时间')}")
if __name__ == "__main__":
analyze_trades('/Users/vivian/work/python/auto_trade_sys/交易记录_2026-02-04T06-46-43.json')

View File

@ -2040,7 +2040,41 @@ class PositionManager:
logger.warning(f"{symbol} [状态同步] ⚠️ 数据库中没有找到open状态的交易记录跳过")
continue
logger.info(f"{symbol} [状态同步] 找到 {len(trades)} 条open状态的交易记录开始更新...")
# 过滤掉刚刚开仓的交易给予60秒的同步缓冲期
# 避免因API延迟导致刚开的仓位被误判为"丢失"从而被错误关闭
import time
now_ts = int(time.time())
recent_trades = []
valid_trades = []
for t in trades:
try:
entry_time = t.get('entry_time')
if entry_time:
# 处理 entry_time 可能是 datetime 对象或时间戳的情况
entry_ts = 0
if hasattr(entry_time, 'timestamp'):
entry_ts = int(entry_time.timestamp())
elif isinstance(entry_time, (int, float)):
entry_ts = int(entry_time)
# 如果是刚刚开仓60秒内跳过同步关闭
if now_ts - entry_ts < 60:
recent_trades.append(t)
continue
except Exception as e:
logger.debug(f"{symbol} [状态同步] 检查开仓时间出错: {e}")
valid_trades.append(t)
if recent_trades:
logger.info(f"{symbol} [状态同步] 发现 {len(recent_trades)} 个刚刚开仓的交易(<60s跳过同步关闭防止误杀")
if not valid_trades:
if not recent_trades:
logger.warning(f"{symbol} [状态同步] 没有符合条件的交易记录需要更新")
continue
logger.info(f"{symbol} [状态同步] 找到 {len(valid_trades)} 条open状态的交易记录开始更新...")
except Exception as get_trades_error:
logger.error(
f"{symbol} [状态同步] ❌ 获取交易记录失败: "
@ -2050,7 +2084,7 @@ class PositionManager:
logger.debug(f"{symbol} [状态同步] 错误详情:\n{traceback.format_exc()}")
continue
for trade in trades:
for trade in valid_trades:
trade_id = trade.get('id')
if not trade_id:
logger.warning(f"{symbol} [状态同步] ⚠️ 交易记录缺少ID字段跳过: {trade}")
@ -3072,7 +3106,11 @@ class PositionManager:
take_profit_1_pct_margin = take_profit_1_pct_margin_config * 100 # 转换为百分比
# 直接比较当前盈亏百分比与第一目标(基于保证金,使用配置值)
if pnl_percent_margin >= take_profit_1_pct_margin:
# ⚠️ 2026-02-04 修复:增加最小盈利检查,防止因配置过低或滑点导致负盈利
# 手续费估算0.05% * 2 = 0.1% 价格变动。10x杠杆下约1%保证金。保留2%作为安全边际。
min_profit_margin = 2.0
if pnl_percent_margin >= take_profit_1_pct_margin and pnl_percent_margin > min_profit_margin:
take_profit_pct_config = config.TRADING_CONFIG.get('TAKE_PROFIT_1_PERCENT', 0.15)
if take_profit_pct_config > 1:
take_profit_pct_config = take_profit_pct_config / 100.0
@ -3135,7 +3173,8 @@ class PositionManager:
remaining_pnl_pct_margin = (remaining_pnl_amount / remaining_margin * 100) if remaining_margin > 0 else 0
# 直接比较剩余仓位盈亏百分比与第二目标(基于保证金)
if remaining_pnl_pct_margin >= take_profit_2_pct_margin:
# ⚠️ 2026-02-04 修复:增加最小盈利检查
if remaining_pnl_pct_margin >= take_profit_2_pct_margin and remaining_pnl_pct_margin > 2.0:
should_close = True
# ⚠️ 2026-01-27优化细分状态区分"第一目标止盈后第二目标止盈"
exit_reason = 'take_profit_partial_then_take_profit'
@ -3182,7 +3221,8 @@ class PositionManager:
)
# 直接比较当前盈亏百分比与止盈目标(基于保证金,使用配置值)
if pnl_percent_margin >= take_profit_pct_margin:
# ⚠️ 2026-02-04 修复:增加最小盈利检查
if pnl_percent_margin >= take_profit_pct_margin and pnl_percent_margin > 2.0:
should_close = True
exit_reason = 'take_profit'