Includes: Bitfinex API integration, technical indicators, LLM signal generation, risk management, Slack notifications. Recent fixes: - SELL orders use position value instead of total balance - SELL signals always close full position - Failed orders added to rejected list for Slack reporting - Position/exposure limits auto-cap to remaining room - BUY order minimum raised to 10% of portfolio Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
44 lines
1.3 KiB
Python
44 lines
1.3 KiB
Python
"""Persistent trade history logger — appends every trade to a CSV file."""
|
|
|
|
import csv
|
|
import os
|
|
from datetime import datetime
|
|
|
|
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().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)
|