优化交易的止盈亏损问题
This commit is contained in:
parent
922a8f3820
commit
f8eca1ed59
41
analyze_bad_trades.py
Normal file
41
analyze_bad_trades.py
Normal 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')
|
||||||
|
|
@ -2040,7 +2040,41 @@ class PositionManager:
|
||||||
logger.warning(f"{symbol} [状态同步] ⚠️ 数据库中没有找到open状态的交易记录,跳过")
|
logger.warning(f"{symbol} [状态同步] ⚠️ 数据库中没有找到open状态的交易记录,跳过")
|
||||||
continue
|
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:
|
except Exception as get_trades_error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{symbol} [状态同步] ❌ 获取交易记录失败: "
|
f"{symbol} [状态同步] ❌ 获取交易记录失败: "
|
||||||
|
|
@ -2050,7 +2084,7 @@ class PositionManager:
|
||||||
logger.debug(f"{symbol} [状态同步] 错误详情:\n{traceback.format_exc()}")
|
logger.debug(f"{symbol} [状态同步] 错误详情:\n{traceback.format_exc()}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for trade in trades:
|
for trade in valid_trades:
|
||||||
trade_id = trade.get('id')
|
trade_id = trade.get('id')
|
||||||
if not trade_id:
|
if not trade_id:
|
||||||
logger.warning(f"{symbol} [状态同步] ⚠️ 交易记录缺少ID字段,跳过: {trade}")
|
logger.warning(f"{symbol} [状态同步] ⚠️ 交易记录缺少ID字段,跳过: {trade}")
|
||||||
|
|
@ -3072,7 +3106,11 @@ class PositionManager:
|
||||||
take_profit_1_pct_margin = take_profit_1_pct_margin_config * 100 # 转换为百分比
|
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)
|
take_profit_pct_config = config.TRADING_CONFIG.get('TAKE_PROFIT_1_PERCENT', 0.15)
|
||||||
if take_profit_pct_config > 1:
|
if take_profit_pct_config > 1:
|
||||||
take_profit_pct_config = take_profit_pct_config / 100.0
|
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
|
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
|
should_close = True
|
||||||
# ⚠️ 2026-01-27优化:细分状态,区分"第一目标止盈后第二目标止盈"
|
# ⚠️ 2026-01-27优化:细分状态,区分"第一目标止盈后第二目标止盈"
|
||||||
exit_reason = 'take_profit_partial_then_take_profit'
|
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
|
should_close = True
|
||||||
exit_reason = 'take_profit'
|
exit_reason = 'take_profit'
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user