Add atr_sl_mult and atr_tp_mult parameters to _calc_labels_vectorized
and generate_dataset_vectorized, defaulting to existing constants (1.5,
2.0) for full backward compatibility. Callers (train scripts, backtester)
can now pass symbol-specific multipliers without modifying module-level
constants.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add pagination controls to Trades tab (prev/next, offset support)
- Reset page on symbol change
- Use package-lock.json + npm ci for reproducible UI builds
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
C1: /api/reset에 API key 인증 추가 (DASHBOARD_RESET_KEY 환경변수)
C2: /proc 스캐닝 제거, PID file + SIGHUP 기반 파서 재파싱으로 교체
C3: daily_pnl 업데이트를 trades 테이블에서 재계산하여 idempotent하게 변경
I1: CORS origins를 CORS_ORIGINS 환경변수로 설정 가능하게 변경
I2: offset 파라미터에 ge=0 검증 추가
I3: 매 줄 commit → 파일 단위 배치 commit으로 성능 개선
I4: _pending_candles 크기 제한으로 메모리 누적 방지
I5: bot.log glob 중복 파싱 제거 (sorted(set(...)))
I6: /api/health 에러 메시지에서 내부 경로 미노출
I7: RSI 차트(데이터 없음)를 OI 변화율 차트로 교체
M1: pnlColor 변수 shadowing 수정 (posPnlColor)
M2: 거래 목록에 API total 필드 사용
M3: dashboard/ui/.dockerignore 추가
M4: API Dockerfile Python 3.11→3.12
M5: 테스트 fixture에서 temp DB cleanup 추가
M6: 누락 테스트 9건 추가 (health, daily, reset 인증, offset, pagination)
M7: 파서 SIGTERM graceful shutdown + entrypoint.sh signal forwarding
DB: 양쪽 busy_timeout=5000 + WAL pragma 설정
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
C5: Remove duplicate entry_fee deduction in backtester (balance and net_pnl)
C1: Add SL/TP retry (3x) with emergency market close on final failure
C3: Add _close_lock to prevent PnL double recording between callback and monitor
C8: Add SIGTERM/SIGINT handler with per-symbol order cancellation before exit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- fix(data_stream): add reconnect loop to MultiSymbolStream matching UserDataStream pattern
Prevents bot-wide crash on WebSocket disconnect (#3 Critical)
- fix(data_stream): increase buffer_size 200→300 and preload 200→300
Ensures z-score window (288) has sufficient data (#5 Important)
- fix(bot): sync risk manager when Binance has no position but local state does
Prevents ghost entries in open_positions blocking future trades (#1 Critical)
- fix(ml_filter): add np.nan_to_num for ONNX input to handle NaN features
Prevents all signals being blocked during initial ~2h warmup (#2 Critical)
- fix(bot): replace _close_handled_by_sync with current_trade_side==None guard
Eliminates race window in SYNC PnL double recording (#4 Important)
- feat(bot): add _ensure_sl_tp_orders in _recover_position
Detects and re-places missing SL/TP orders on bot restart (#6 Important)
- feat(exchange): add get_open_orders method for SL/TP verification
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- fix(bot): prevent PnL double recording in _close_and_reenter using asyncio.Event
- fix(bot): prevent SYNC detection PnL duplication with _close_handled_by_sync flag
- fix(notifier): move sync HTTP call to background thread via run_in_executor
- fix(risk_manager): make is_trading_allowed async with lock for thread safety
- fix(exchange): cache exchange info at class level (1 API call for all symbols)
- fix(exchange): use `is not None` instead of truthy check for price/stop_price
- refactor(backtester): extract _calc_trade_stats to eliminate code duplication
- fix(ml_features): apply rolling z-score to OI/funding rate in serving (train-serve skew)
- fix(bot): use config.correlation_symbols instead of hardcoded BTCUSDT/ETHUSDT
- fix(bot): expand OI/funding history deque to 96 for z-score window
- cleanup(config): remove unused stop_loss_pct, take_profit_pct, trailing_stop_pct fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Load trade history from data/trade_history/{symbol}.jsonl
- Show per-symbol: consecutive loss streak vs threshold, recent 15-trade PF
- 2-tier alert: clean numbers for normal, ⚠/🔴 KILLED for danger zone
- Inserted before ML retraining checklist in Discord report
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace full file scan with _tail_lines() that reads from EOF
- Only load max(FAST_KILL=8, SLOW_KILL=15) lines on boot
- Trim in-memory trade history to prevent unbounded growth
- No I/O bottleneck regardless of history file size
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fast Kill: 8 consecutive net losses → block new entries for symbol
- Slow Kill: last 15 trades PF < 0.75 → block new entries for symbol
- Trade history persisted to data/trade_history/{symbol}.jsonl (survives restart)
- Boot-time retrospective check restores kill state from history
- Manual reset via RESET_KILL_SWITCH_{SYMBOL}=True in .env + restart
- Entry blocked, exits (SL/TP/manual) always work normally
- Discord alert on kill switch activation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add payoff_ratio and max_consecutive_losses to backtester summary
- Add compare_symbols.py: per-symbol parameter sweep for candidate evaluation
- Add position_sizing_analysis.py: robust Monte Carlo position sizing
- Fetch historical data for SOL, LINK, AVAX candidates (365 days)
- Update existing symbol data (XRP, TRX, DOGE)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_handle_close was not clearing _current_positions when no matching OPEN
trade was found in DB, causing all subsequent entries for the same
symbol+direction to be silently skipped. Also add PYTHONUNBUFFERED=1
and python -u to make log parser crashes visible in docker logs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The combined summary (PF, MDD, win_rate) was indirectly reconstructed
from per-symbol averages using round(win_rate * n), which introduced
rounding errors. MDD was max() of individual symbol MDDs, ignoring
simultaneous drawdowns across the correlated crypto portfolio.
Now computes all combined metrics directly from the trade list:
- PF: sum(wins) / sum(losses) from actual trade PnLs
- MDD: portfolio equity curve from time-sorted trades
- Win rate: direct count from trade PnLs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Increased ATR_SL_MULT_TRXUSDT from 1.0 to 2.0 and adjusted ADX_THRESHOLD_TRXUSDT from 30 to 25 in README.
- Added new weekly report files in HTML and JSON formats for 2026-03-15, including detailed backtest summaries and trade data for XRPUSDT, TRXUSDT, and DOGEUSDT.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MARKET orders can fill in multiple trades (PARTIALLY_FILLED → FILLED).
Previously only the last fill's rp/commission was captured, causing
under-reported PnL. Now accumulates rp and commission across all
partial fills per order_id and sums them on final FILLED event.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5. Add daily PnL reset loop — UTC midnight auto-reset via
_daily_reset_loop in main.py, prevents stale daily_pnl accumulation
6. Fix set_base_balance race condition — call once in main.py before
spawning bots, instead of each bot calling independently
7. Remove realized_pnl != 0 from close detection — prevents entry
orders with small rp values being misclassified as closes
8. Rename xrp_btc_rs/xrp_eth_rs → primary_btc_rs/primary_eth_rs —
generic column names for multi-symbol support (dataset_builder,
ml_features, and tests updated consistently)
9. Replace asyncio.get_event_loop() → get_running_loop() — fixes
DeprecationWarning on Python 3.10+
10. Parallelize candle preload — asyncio.gather for all symbols
instead of sequential REST calls, ~3x faster startup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Margin ratio calculated on per_symbol_balance instead of total balance
— previously amplified margin reduction by num_symbols factor
2. Replace Algo Order API (algoType=CONDITIONAL) with standard
futures_create_order for SL/TP — algo API is for VP/TWAP, not
conditional orders; SL/TP may have silently failed
3. Fallback PnL (SYNC close) now sums all recent income rows instead
of using only the last entry — prevents daily_pnl corruption in
multi-fill scenarios
4. Explicit state transition in _close_and_reenter — clear local
position state after close order to prevent race with User Data
Stream callback on position count
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nginx caches DNS at startup, so when dashboard-api restarts and gets
a new container IP, the proxy breaks with 502. Use Docker's embedded
DNS resolver (127.0.0.11) with a variable-based proxy_pass to
re-resolve on every request.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add UNIQUE(symbol, entry_time, direction) constraint to trades table
and use INSERT OR IGNORE to skip duplicates. Includes auto-migration
to clean up existing duplicate entries on startup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the position monitor detects a missed close via API fallback, it
now queries Binance futures_income_history to get the real realized PnL
and commission instead of logging zeros. Exit price is estimated from
entry price + PnL/quantity. This ensures the dashboard records accurate
profit data even when WebSocket events are missed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The position monitor now checks Binance API every 5 minutes to verify
the bot's internal state matches the actual position. If the bot thinks
a position is open but Binance shows none, it syncs state and logs a
SYNC close event. This prevents the bot from being stuck in a phantom
position when User Data Stream misses a TP/SL fill event.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added entries to .gitignore for node_modules and dist directories in the dashboard UI.
- Updated log file pattern in log_parser.py to match 'bot*.log' instead of 'bot_*.log'.
- Introduced package-lock.json for the dashboard UI to manage dependencies.
- Updated CLAUDE.md to reflect the status of code review improvements.
- Added new weekly report files in HTML and JSON formats for 2026-03-07.
- Updated binary parquet files for dogeusdt, trxusdt, and xrpusdt with new data.
Changed _init_db() from DROP+CREATE to CREATE IF NOT EXISTS so that
trade history, candle data, and daily PnL survive container restarts.
Previously all tables were dropped on every parser start, losing
historical data if log files had been rotated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /api/symbols endpoint only returned symbols that had a :last_start
key, which requires the log parser to catch the bot start log. If the
dashboard was deployed after the bot started, the start log was already
past the file position and symbols showed as 0. Now extracts symbols
from any colon-prefixed key in bot_status.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parse position monitor logs (5min interval) to update current_price,
unrealized_pnl and unrealized_pnl_pct in bot_status. Position cards
now display USDT amount and percentage, colored green/red. Falls back
to entry/current price calculation if monitor data unavailable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hardcoded round(qty, 1) caused -1111 Precision errors for TRXUSDT and
DOGEUSDT (stepSize=1, requires integers). Now lazily loads quantityPrecision
and pricePrecision from Binance futures_exchange_info per symbol. SL/TP
prices also use symbol-specific precision instead of hardcoded 4 decimals.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_fetch_oi_hist and _fetch_funding_rate had no retry logic, causing
crashes on rate limit (429) or transient errors during weekly report
data collection. Added _get_json_with_retry helper (max 3 attempts,
exponential backoff). Updated code-review docs to reflect completion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
useCallback dependency on `symbols` state caused fetchAll to recreate
on every call (since it sets symbols), triggering useEffect to restart
the interval immediately. Use symbolsRef to break the cycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- #1: OI division by zero — already fixed (prev_oi == 0.0 guard exists)
- #2: cumulative trade count used max() instead of sum(), breaking ML trigger
- #4: fetch_history API calls now retry 3x with exponential backoff
- #5: parquet upsert now deduplicates timestamps before sort
- #6: record_pnl() is now async with Lock for multi-symbol safety
- #8: exit_price=0.0 skips close handling with warning log
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
get_signal() now returns (signal, detail) tuple with long/short scores,
ADX value, volume surge status, and HOLD reason for easier diagnosis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Revised the architecture document to enhance clarity on system overview, trading decision process, and technical stack.
- Updated the README to emphasize the bot's operational guidelines and risk management features.
- Added new sections in the architecture document detailing the trading decision gates and data pipeline flow.
- Improved the table of contents for better navigation and understanding of the bot's architecture.
- Added functionality to fetch live trade data from the dashboard API.
- Implemented weekly report generation that includes backtest results, live trade statistics, and performance trends.
- Enhanced error handling for API requests and improved logging for better traceability.
- Updated tests to cover new features and ensure reliability of the report generation process.