Fix exchange API errors: stop cascade BUY failures and stop-loss race condition

- Set available_usdt=0 after BUY fails with "not enough balance" to prevent
  subsequent BUY signals from hitting the exchange in the same cycle
- Add 0.3s delay after canceling stop orders before placing new ones to let
  Bitfinex release locked balance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
kroutony 2026-03-14 03:12:54 +00:00
parent c473a581b0
commit fa148da196

View File

@ -149,6 +149,7 @@ def run_cycle():
logger.info("Cancelled outdated stop %s for %s (amt=%.6f, px=%.6g)",
s["id"], sym, abs(s["amount"]), s["price"])
tracked_stops.pop(sym, None)
time.sleep(0.3) # Wait for Bitfinex to release locked balance
logger.warning("Position %s missing/outdated stop-loss, placing now", sym)
sl = trader.place_stop_loss_order(sym, amount, entry)
@ -345,6 +346,10 @@ def run_cycle():
if result and result.get("status") == "failed":
logger.warning("Order failed at exchange: %s %s%s", action, validated["symbol"], result.get("error", ""))
rejected.append({**validated, "reject_reason": f"交易所錯誤: {result.get('error', 'unknown')}"})
# BUY failed at exchange — mark balance as unreliable to skip remaining BUYs
if action == "BUY" and "not enough" in result.get("error", "").lower():
port["available_usdt"] = 0
logger.info("Marked available_usdt=0 to prevent further BUY attempts this cycle")
continue
if result and result.get("status") in ("filled", "submitted"):
@ -369,9 +374,13 @@ def run_cycle():
if action == "BUY":
# Cancel existing exchange stop orders before placing new one
pos = port.get("positions", {}).get(sym, {})
cancelled_any = False
for s in stop_orders_by_sym.get(sym, []):
trader.cancel_order(s["id"])
cancelled_any = True
logger.info("Cancelled old stop %s for %s (position size changed)", s["id"], sym)
if cancelled_any:
time.sleep(0.3) # Wait for Bitfinex to release locked balance
# Place new stop-loss for TOTAL position amount at new avg entry
total_amount = pos.get("amount", amount)