auto_trade_sys/scripts/clear_cooldown.py
薇薇安 69327a6668 1
2026-02-13 08:27:05 +08:00

147 lines
5.5 KiB
Python
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.

#!/usr/bin/env python3
"""
清理交易冷却时间脚本
用于手动重置某个交易对的“连续亏损冷却”状态。
原理:将该交易对最近一次亏损交易的平仓时间修改为“冷却时间之前”,使其不再触发冷却逻辑。
用法:
python scripts/clear_cooldown.py [symbol]
例如:
python scripts/clear_cooldown.py BTCUSDT # 清理 BTCUSDT 的冷却
python scripts/clear_cooldown.py # 列出当前处于冷却中的交易对
"""
import sys
import os
import time
from datetime import datetime, timedelta
import logging
# Add backend to path
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'backend'))
from database.connection import db
from database.models import Trade, TradingConfig
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def get_cooldown_config(account_id):
"""获取冷却配置"""
try:
enabled = TradingConfig.get_value("SYMBOL_LOSS_COOLDOWN_ENABLED", True, account_id=account_id)
max_losses = int(TradingConfig.get_value("SYMBOL_MAX_CONSECUTIVE_LOSSES", 2, account_id=account_id))
cooldown_sec = int(TradingConfig.get_value("SYMBOL_LOSS_COOLDOWN_SEC", 3600, account_id=account_id))
return enabled, max_losses, cooldown_sec
except Exception as e:
logger.error(f"获取配置失败: {e}")
return True, 2, 3600
def check_cooldown(symbol, account_id, max_losses, cooldown_sec):
"""检查是否处于冷却中"""
recent_trades = Trade.get_all(symbol=symbol, status='closed', account_id=account_id)
# Sort by exit_time desc
recent_trades = sorted(
recent_trades,
key=lambda x: (x.get('exit_time') or x.get('entry_time') or 0),
reverse=True
)[:max_losses + 1]
if not recent_trades:
return False, None, 0
now = int(time.time())
latest_trade = recent_trades[0]
latest_exit_time = latest_trade.get('exit_time') or latest_trade.get('entry_time') or 0
# Check time window
if now - latest_exit_time < cooldown_sec:
consecutive_losses = 0
for trade in recent_trades:
pnl = float(trade.get('pnl', 0) or 0)
exit_reason = str(trade.get('exit_reason', '') or '').lower()
# 2026-02-13 优化手动平仓manual不计入连续亏损
if exit_reason == 'manual' or exit_reason == 'manual_close':
continue
if pnl < 0:
consecutive_losses += 1
else:
break
if consecutive_losses >= max_losses:
remaining = cooldown_sec - (now - latest_exit_time)
return True, latest_trade, remaining
return False, None, 0
def clear_cooldown(symbol, account_id, cooldown_sec):
"""清理冷却(修改平仓时间)"""
is_cooling, latest_trade, remaining = check_cooldown(
symbol, account_id,
*get_cooldown_config(account_id)[1:]
)
if not is_cooling:
logger.info(f"{symbol} 当前未处于冷却状态。")
return
logger.info(f"正在清理 {symbol} 的冷却状态...")
logger.info(f" 当前剩余冷却: {remaining}")
logger.info(f" 最近交易ID: {latest_trade['id']}, 平仓时间: {latest_trade.get('exit_time')}")
# Calculate new exit time: now - cooldown_sec - 60s (buffer)
now = int(time.time())
new_exit_time = now - cooldown_sec - 60
try:
# Update database
sql = "UPDATE trades SET exit_time = %s WHERE id = %s"
db.execute_update(sql, (new_exit_time, latest_trade['id']))
logger.info(f"✅ 已成功清理 {symbol} 的冷却状态!")
logger.info(f" 修改交易 #{latest_trade['id']} 平仓时间 -> {new_exit_time} (当前时间-{cooldown_sec+60}s)")
except Exception as e:
logger.error(f"❌ 更新数据库失败: {e}")
def list_cooldowns(account_id):
"""列出所有处于冷却中的交易对"""
logger.info("正在扫描处于冷却中的交易对...")
enabled, max_losses, cooldown_sec = get_cooldown_config(account_id)
if not enabled:
logger.info("冷却功能未启用 (SYMBOL_LOSS_COOLDOWN_ENABLED=False)")
return
# Get all distinct symbols traded recently?
# Better: Get all symbols from trades in last cooldown_sec + some buffer
# Simplified: Get distinct symbols from trades
sql = "SELECT symbol FROM trades WHERE account_id = %s AND status = 'closed' GROUP BY symbol ORDER BY MAX(id) DESC LIMIT 100"
rows = db.execute_query(sql, (account_id,))
symbols = [r['symbol'] for r in rows]
found = False
for symbol in symbols:
is_cooling, trade, remaining = check_cooldown(symbol, account_id, max_losses, cooldown_sec)
if is_cooling:
found = True
print(f"🔥 {symbol:<10} 冷却剩余: {remaining:>4}s (最近连续亏损)")
if not found:
logger.info("没有发现处于冷却中的交易对。")
def main():
account_id = int(os.getenv("ATS_ACCOUNT_ID") or os.getenv("ACCOUNT_ID") or 1)
if len(sys.argv) > 1:
symbol = sys.argv[1].upper()
clear_cooldown(symbol, account_id, get_cooldown_config(account_id)[2])
else:
list_cooldowns(account_id)
print("\n提示: 使用 python scripts/clear_cooldown.py [SYMBOL] 来清理指定币种的冷却。")
if __name__ == "__main__":
main()