bifitnex-trading/trade_logger.py
kroutony b6bd45b151 Fix SELL P&L calculation, add debug logging, and multiple improvements
- Fix realized_pnl always being 0 on SELL (use amount*price instead of amount_usdt)
- Add debug logging for all-HOLD LLM cycles (log sample HOLD reasons)
- Fix nonce collision in Bitfinex API auth (add counter)
- Fix timezone to UTC+8 in main, trade_logger, sync_cost_basis, check_errors
- Fix stop-loss retry with longer delay after cancel
- Add min order amount check in trader before BUY
- Fix risk_manager to skip positions with amount <= 0
- Cap trade_history to 500 entries to prevent unbounded growth
- Fix greedy regex in LLM response parser
- Reset cost_tracking start dates to null

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 06:23:54 +00:00

46 lines
1.4 KiB
Python

"""Persistent trade history logger — appends every trade to a CSV file."""
import csv
import os
from datetime import datetime, timezone, timedelta
_TZ_UTC8 = timezone(timedelta(hours=8))
import config
TRADE_LOG_FILE = "trade_history.csv"
FIELDS = [
"timestamp", "datetime", "symbol", "name", "action", "amount",
"price", "amount_usdt", "confidence", "reason", "mode", "status",
]
def _ensure_header():
if not os.path.exists(TRADE_LOG_FILE):
with open(TRADE_LOG_FILE, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS)
writer.writeheader()
def log_trade(trade: dict):
"""Append a trade record to the CSV log."""
_ensure_header()
sym = trade.get("symbol", "")
row = {
"timestamp": trade.get("timestamp", ""),
"datetime": datetime.now(_TZ_UTC8).isoformat(timespec="seconds"),
"symbol": sym,
"name": config.SYMBOL_NAMES.get(sym, sym),
"action": trade.get("action", ""),
"amount": trade.get("amount", 0),
"price": trade.get("price", 0),
"amount_usdt": trade.get("amount_usdt", 0),
"confidence": trade.get("confidence", 0),
"reason": trade.get("reason", ""),
"mode": trade.get("mode", ""),
"status": trade.get("status", ""),
}
with open(TRADE_LOG_FILE, "a", newline="") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS)
writer.writerow(row)