Releases: enarjord/passivbot
v7.8.4
Changed
- Dual balance routing (raw vs hysteresis-snapped) - Live and orchestrator flows now carry both
balance_raw(raw wallet balance) andbalance(hysteresis-snapped balance). Sizing/order-shaping paths use snapped balance, while risk/accounting paths use raw balance (including realized-loss gate peak/floor checks, TWEL entry/auto-reduce gating, and auto-unstuck allowance calculations). This applies consistently across live and backtest via Rust orchestrator input. - WEL denominator behavior split by mode - Live now uses a hard fixed denominator for per-symbol WEL (
total_wallet_exposure_limit / config.bot.{pside}.n_positions), removing runtime denominator drift from open-position count. Backtests now exposebacktest.dynamic_wel_by_tradability(defaulttrue): when enabled, WEL uses tradability-aware denominator growth (min(n_positions, n_tradable_max)) based on coins with real candles, and does not shrink after delistings; when disabled, backtests use the same fixed denominator as live. - Bulk price fetch for Hyperliquid -
calc_ideal_ordersnow uses a singleallMidsAPI call to get prices for all symbols instead of individualget_current_closecalls per symbol (1 call vs ~70). Falls back to per-symbol fetches for non-Hyperliquid exchanges or on error. - Sequential margin mode setting for Hyperliquid - Margin mode and leverage API calls are now sequential with a small delay instead of being fired in parallel, reducing API burst on coin changes.
Fixed
- Bybit fill-event qty inflation on duplicate pages -
BybitFetchernow deduplicatesfetch_my_tradesrows by exec id before canonicalization/coalescing, preventing duplicate pagination rows from inflating canonicalqty,fees, and close PnL. - Balance peak drift in wrong direction under hysteresis - Peak reconstruction (
balance + (pnl_cumsum_max - pnl_cumsum_last)) previously used hysteresis-snapped balance in some paths. Since snapped balance can stay stale whilepnl_cumsum_lastchanges fill-by-fill, this made reconstructed peak drift down after profits and up after losses. Peak/PnL-accuracy-sensitive paths now use raw balance (balance_raw) consistently. - Pytest Rust-module bootstrap fallback - Test bootstrap now tries the project venv
passivbot_rustpackage before falling back to the lightweight stub when tests are launched outside the venv, reducing false failures from missing/incorrect Rust module resolution. max_ohlcv_fetches_per_minuteignored when forager slots open - The rate limit config was only applied when all position slots were full. With open slots (the common case), all candidate symbols were fetched without rate limiting, causing 429 errors on Hyperliquid.- Hyperliquid positions+balance double fetch -
fetch_positionsandfetch_balancenow share a single API call via a dedup lock instead of making two identicalclearinghouseStaterequests per execution cycle. - Thundering herd on minute boundary -
get_candlesno longer force-refreshes all symbols simultaneously when a new minute boundary crosses. A 1-candle staleness tolerance prevents the TTL override that caused all symbols to fetch at once. - Candle refresh TTLs aligned to 1-minute finalization - Active candle refresh TTL raised from 10s to 60s and EMA close TTL from 30s to 60s, matching the actual 1-minute candle finalization interval.
- Boot stagger for multi-bot setups - Added
boot_stagger_secondsconfig (default 30s for Hyperliquid) to randomize startup delay, preventing simultaneous API bursts when multiple bots share the same IP. - Warmup and refresh fetch pacing - Added configurable
warmup_fetch_delay_ms(default 200ms for Hyperliquid) with delays between individual symbol fetches during warmup, forager refresh, and active candle refresh loops. - Exponential backoff on 429 errors - WebSocket
watch_ordersuses exponential backoff (up to 30s) on rate limit errors. Execution loop backs off 5s onRateLimitExceeded. Hourlyinit_marketscatches rate limits with 10s recovery. - Fill events pagination abort on repeated rate limits -
HyperliquidFetchernow aborts after 5 consecutive rate limit retries with exponential backoff instead of retrying indefinitely. - EMA bundle and active candle sweep abort on rate limit - Both
_load_orchestrator_ema_bundleandupdate_ohlcvs_1m_for_activesskip remaining symbols when the CandlestickManager's global rate limit backoff is active. - Live close-EMA failure handling in orchestrator feed -
_load_orchestrator_ema_bundle()no longer silently drops failed/non-finite close EMA spans. It now fails loudly when no prior EMA exists, and otherwise reuses the last successfully computed close EMA for that exact symbol/span with explicit[ema]warning logs (including reason, age, and consecutive fallback count). - Required 1h log-range EMA handling in orchestrator feed -
_load_orchestrator_ema_bundle()now fails loudly when requiredh1log-range spans (fromentry_volatility_ema_span_hours) are missing or non-finite, instead of deferring to downstream RustMissingEmaerrors. - EMA bundle fetch stability under lock contention - Orchestrator EMA bundle loading now fetches per-symbol spans serially and drains all symbol task outcomes before re-raising, reducing same-symbol candle-lock contention and eliminating unretrieved sibling-task exception noise.
Added
- Fill events doctor tool - Added
src/tools/fill_events_doctor.pyto audit cached fill events and auto-repair known Bybit duplicate-fill anomalies without requiring exchange API calls. Bybit startup now runs doctor by default (can be disabled withPASSIVBOT_FILL_EVENTS_DOCTOR=off).
Full changelog: v7.8.3...v7.8.4
v7.8.3
Added
- Added
live.max_realized_loss_pct(default0.05) to block close orders that would realize losses beyond a peak-balance-relative threshold. This applies to normal closes, WEL/TWEL auto-reduce, and unstuck closes; panic closes remain exempt.
Fixed
- Fixed false-positive stale Rust-extension detection after identical rebuilds.
- Fixed suite base scenario coin fallback to use base approved coins.
- Fixed aggregate-method handling in optimizer scoring and Pareto analysis so configured aggregate modes are respected without double-correcting objectives.
v7.8.2: Candle Interval, Exposure Metrics, and Plotting Fixes
Highlights
- Added configurable backtest candle aggregation via
backtest.candle_interval_minutes(default1). - Added high-exposure duration metrics for long/short (
high_exposure_hours_{mean,max}_{long,short}). - Added
total_wallet_exposure.pngoutput for backtests.
Fixed
- Corrected total wallet exposure metrics for short-only configs by using absolute exposure magnitude.
- Fixed timestamp day bucketing in analysis to avoid phantom first-day samples with aggregated intervals.
- Fixed forager
fills_plotsalignment when using candle intervals > 1m by plotting against the effective backtest candle stream. - Fixed candle-interval test robustness and aggregation alignment behavior across suite/optimizer paths.
Changed
- Updated
configs/template.jsondefaults/bounds/scenarios (includingbtc_collateral_cap,maker_fee_override, and optimize limits).
Notes
- Candle aggregation improves backtest/optimizer speed but loses intra-interval fill ordering granularity.
- No user migration steps required.
Full Changelog: v7.8.1...v7.8.2
v7.7.0: FillEventsManager production + logging improvements
Highlights
FillEventsManager Production Transition
- PnL tracking now uses FillEventsManager exclusively - Legacy
update_pnlspath removed - Fill events include psize/pprice - Each fill annotated with position size and VWAP entry price
- Support for all exchanges: Binance, Bybit, Bitget, GateIO, Hyperliquid, KuCoin, OKX
Comprehensive Logging Improvements (7 rounds of refinement)
Tag Standardization:
[memory],[warmup],[hourly],[fills],[mapping],[candle],[ranking],[mode]
Level Adjustments:
- Routine API/cache messages: INFO → DEBUG
- CCXT API payloads: DEBUG → TRACE
- Strict mode gaps: WARNING → DEBUG
- Persistent gaps: WARNING → INFO
Throttling:
- EMA ranking logs: every 5 minutes
- Mode changes: 2 minutes per symbol
- KucoinFetcher PnL discrepancy: 1 hour with delta-based deduplication
New Features:
- WebSocket reconnection logs explicit
[ws] reconnecting...messages - Health summary includes realized PnL when fills > 0
Bug Fixes
- Bybit: Fixed missing PnL on some close fills - Pagination bug in
_fetch_positions_history()caused records to be skipped when >100 existed
Documentation
- New
docs/ai/log_analysis_prompt.md- comprehensive logging guidelines - New
docs/ai/exchange_api_quirks.md- exchange-specific limitations - New
docs/ai/debugging_case_studies.md- debugging reference
Removed
--shadow-modeCLI flaglive.pnls_manager_shadow_modeconfig option- Legacy pnls methods
Migration Notes
- No action required - FillEventsManager automatically fetches and caches fill data
- Old
{user}_pnls.jsoncache files can be safely deleted after upgrading
Full Changelog: v7.6.2...v7.7.0
v7.6.2: Logging Improvements & Bug Fixes
This release focuses on improving log verbosity, fixing critical candle data issues, and enhancing the overall user experience with better diagnostics.
🔧 Critical Bug Fixes
-
Zero-candle warmup fix: Large warmup spans (>2 days) now properly trigger gap-filling via CCXT even when end_ts touches present. Previously, bots would synthesize thousands of zero-candles for historical gaps instead of fetching real data. First warmup may take longer (one-time backfill), subsequent restarts are fast (~6s vs ~156s).
-
One-way mode entry fix: Disabled sides no longer block entries when using one-way mode. The bot now correctly respects side configuration when choosing initial entry direction.
-
Bybit leverage errors: "Leverage not modified" (110043) and "margin mode not modified" (110026) errors are now handled gracefully instead of logging full tracebacks.
📊 Logging Improvements
-
Structured log prefixes: All log messages now use bracketed category tags for easy filtering:
[config]- Configuration changes[fills]- Fill events and PnL[candle]- Candle synthesis/replacement[bybit],[binance], etc. - Exchange-specific logs
-
Health summary enhancements: Now includes realized PnL sum when fills > 0 (e.g.,
fills=3 (pnl=+12.50)) -
Reduced log spam:
- Zero-candle logs rate-limited to once per minute per symbol
- BybitFetcher residual PnL warnings moved to debug level
- FillEventsManager refresh logs consolidated to single summary line
-
Better timestamps: Zero-candle warnings now include human-readable UTC timestamps showing the exact range synthesized
⚙️ New Configuration Options
-
live.enable_archive_candle_fetch(default: false): Opt-in to use exchange archive data for candle fetching. Disabled by default to avoid timeout issues. Backtester always uses archives regardless of this setting. -
live.warmup_jitter_seconds(default: 30): Random delay before warmup to prevent API rate limit storms when multiple bots start simultaneously. -
live.max_concurrent_api_requests(default: null): Optional global concurrency limit for CCXT API calls. -
backtest.maker_fee_override(default: null): Override maker fees in backtest/optimizer (useful for testing different fee tiers).
🖥️ UI Improvements
-
TWEL clarification: Startup banner now shows "TWEL" (Total Wallet Exposure Limit) instead of "Exposure" to clarify it's a limit, not current exposure. Long+short mode shows both limits (e.g.,
TWEL: L:125% S:85%). -
Dynamic banner width: Startup banner now calculates width dynamically to prevent misaligned borders.
🐛 Other Fixes
-
Windows cache compatibility: folder names now replace
:with_on Windows or whenWINDOWS_COMPATIBILITY=1env var is set (#547, thanks @FelixJongleur42) -
Pareto dashboard: Fixed JavaScript callback errors when switching between tabs (#550, thanks @646826)
📦 Dependencies
- Added
openpyxltorequirements-live.txt(required for Bitget archive XLSX parsing)
⚠️ Upgrade Notes
-
First startup may be slower: The zero-candle fix causes a one-time backfill of historical data. Subsequent restarts will be fast.
-
Windows users: Existing caches will be orphaned and re-downloaded due to the folder naming change.
-
Archive fetching disabled by default: If you relied on archive data for live bots, set
live.enable_archive_candle_fetch: truein your config.
📈 Statistics
- 66 commits since v7.6.1
- 62 files changed
- +9,196 / -2,529 lines
Full changelog: https://github.com/enarjord/passivbot/blob/master/changelog.md
v7.6.0
Passivbot v7.5.7
Passivbot v7.5.7 Release Notes
Highlights
- CCXT upgrade to 4.5.22 for better exchange compatibility, along with KuCoin hedge-mode enforcement and order payload fixes.
- Canonical suite metrics & Pareto revamp ensuring optimizer/backtester share identical outputs, with centralized Pareto logic.
- Cleaner balance/position orchestration: bots fetch balance and positions concurrently, logging once both are fresh.
Detailed Changes
Exchange & Bot Behavior
- Upgraded CCXT to v4.5.22 and added regression tests to detect future CCXT-breaking changes.
- KuCoin bot now enforces hedge mode (when supported), handles exchange refusal gracefully, and sends correct
marginMode/positionSideorder params. - All exchange wrappers now keep
fetch_positions()andfetch_balance()separate; callers can refresh each independently. update_positions_and_balance()gathers balance/positions concurrently, logs position deltas after both complete, and emits a single balance-change event so equity logging always uses fresh positions/uPnL.
Optimization & Backtesting
- Added
pareto_core.pyconsolidating Pareto dominance/crowding logic with extreme-preserving pruning. - Suite runner and optimizer now emit the same canonical suite metrics payload (aggregate stats + per-scenario means).
- ParetoStore delegates to the shared helper so dominance/clustering rules are consistent across CLI tools.
Configuration & Overrides
- Added forward/backward TP grid overrides (PR #532) plus template/normalize fixes when loading live or suite configs.
- Improved parse_overrides behavior and logging for suite enablement.
Documentation
- Expanded docs covering minimum effective cost calculations, trailing grid ratios, and the new changelog policy.
- Documented KuCoin hedge-mode setup so users know what to expect after the CCXT upgrade.
Testing & Tooling
- New KuCoin exchange-config regression tests (hedge/margin/leverage) plus refreshed passivbot balance tests.
- Updated test stubs so
passivbot_rust/CCXT mocks reflect the new fetch/log separation.
What's Changed
Full Changelog: v7.5.4...v7.5.7
Passivbot v7.5.4 – Collateral-Agnostic Metrics, Smarter Overrides, and Split Balance/Position Fetch
Highlights
- Added collateral-agnostic performance metrics (
adg_pnl,mdg_pnl, PnL-based Sharpe/Sortino, with weighted variants) and documented them. - Improved coin overrides UX and safety with new docs, tests, and debug logging.
- Refactored position/balance handling to separate updates and optimize Hyperliquid’s combined fetch.
- Robustified data-sync, fill-events cache layout, and Kucoin open-order pagination.
- Expanded optimizer limit handling with a new
limit_utilsmodule and tighter limit/scoring integration.
Metrics & Analysis
- New metrics:
adg_pnl,mdg_pnl(mean/median daily PnL over end-of-day balance), and PnL-basedsharpe_ratio_pnl/sortino_ratio_pnl, plus weighted versions. - Added
docs/metrics.mdentries clarifying equity vs PnL Sharpe/Sortino semantics. - Types/analysis wiring updated across Rust and Python consumers; optimization weights and config canonicalization recognize the new metrics.
- Added optimizer-side limit utilities (
limit_utils) and integration tests to enforce limit normalization/penalties consistently.
Coin Overrides
- Documented full override behavior (
docs/coin_overrides.md) with inline/file-based examples, allowed fields, path resolution, and pitfalls. - Added debug logs when overrides are initialized and when override values are used.
- Expanded tests to cover path resolution, missing override files, and retention through config formatting.
Exchange & Sync Fixes
- Kucoin:
fetch_open_ordersnow paginates (no more 50-order cap). - Hyperliquid:
fill_events_managernow supports the exchange; fetch positions/balance combined once per cycle. - General: position/balance fetching split for all exchanges (dedicated
fetch_balance/fetch_positions), with balance caching to avoid double-hits on combined endpoints. sync_tar.py: pulling a single file no longer nests an extra directory.- Optimizer: new limit handling pipeline (
limit_utils), enhanced scoring/limits parsing, and additional tests for optimizer limits.
Fill Events
- Cache root now
caches/{exchange}/{user}(wascaches/{exchange}_{user}). - Hyperliquid fetcher path registered; CLI no longer rejects hyperliquid users.
Core Refactors & Safeguards
update_positionsand newupdate_balanceseparated; main loops call both.- Balance caching reuse and rate-limit/network guards added.
- Tests added for balance split and Hyperliquid combined fetch reuse.
- Added optimizer limit integration tests and helper coverage for limit utilities.
Docs
- Added coin override guide and metrics reference updates.
QA/Tests
- New tests: override path handling, balance split behavior, Hyperliquid fetch reuse, Hyperliquid fetcher wiring.
- Optimizer limit integration and limit_utils tests added.
- Existing suite continues to pass on targeted runs (spot-checked new tests).
Full Changelog: v7.5.0...v7.5.4
Passivbot v7.5.0 (TWEL Enforcer)
Passivbot v7.5.0 (TWEL Enforcer)
Highlights
-
Risk controls & TWEL enforcer
- Added
risk_we_excess_allowance_pct,risk_wel_enforcer_threshold, and companion Rust helpers that auto-reduce positions when wallet exposure drifts beyond the buffer. - Implemented TWEL (Total Wallet Exposure Limit) gating in Rust with Python wiring, per-position prioritisation, and optimizer bounds/CLI flags.
- Refined unstuck logic so both live bot and backtester use the same Rust helpers; unstuck can now be disabled by setting a negative threshold.
- Added
-
Optimizer overhaul
- Shared-memory HLCV bundles and per-scenario slicing remove per-worker copies, cutting RAM growth as CPU count increases.
- Streaming evaluator outputs: each candidate logs Pareto updates immediately, duplicate detection got stricter, and starting-config logging/immediate termination handling improved.
- Suite support landed: optimisations can now evaluate multiple scenarios per candidate (with config cleaners, override helpers, and scenario metrics aggregation).
- Added Pareto dashboard (WIP) and metrics-only mode; template configs updated with new suites and defaults.
-
Logging & monitoring
- Order-plan logging is now quiet when unchanged, but includes delta/context details when cancels/creates actually happen; tolerance gating prevents churn.
- Candlestick manager detects sparse exchange feeds once per
(exchange,symbol,tf)and still standardises gaps with synthetic zero-candles. - Balance snapshot/logging knobs moved to
config.logging; log-once helper ensures repeated warnings appear only once per symbol.
-
Config & CLI improvements
- Template config refreshed with new risk knobs, trailing weights, and optimizer bounds;
config_utilstracks transforms and exposes_rawdata. - CLI overrides for optimise bounds now only freeze the key you actually pass (e.g.
-lnp 4pins long positions to 4, leaving other bounds untouched). - Added knobs such as
recv_window_ms,balance_sample_divider,logging.volume_refresh_info_threshold_seconds, and updated docs.
- Template config refreshed with new risk knobs, trailing weights, and optimizer bounds;
-
Backtest & analysis
- Introduced
HlcvsBundleand payload subset helpers; backtest payloads now carry coin metadata in Rust and Python tests cover slicing/validation. - New scoring metrics (
entry_initial_balance_pct_long, drawdown limits, volatility-weighted trailing entries) and renamed config fields to match. - Added scripts/tools (
shared_arrays.py, JSON streamliner, new Pareto utilities) plus doc updates (passivbot_agent_principles.yaml, CONTRIBUTING).
- Introduced
-
Fill events manager (WIP)
- New
src/fill_events_manager.pyadds modular fetchers (Bitget, Bybit, Binance) with caching and enrichment plus a CLI runner and tests. Live bot still uses legacyfetch_pnls; the manager will coexist while it matures.
- New
Thanks to everyone who tested TWEL enforcer, optimiser RAM fixes, and the expanding docs/tooling ecosystem.
What's Changed
- Fix res.get() trying to expanding the objectives in case of seen hash by @TayyabTalha in #526
- V7.5.0 twel enforcer by @TayyabTalha in #527
- V7.5.0 twel enforcer by @enarjord in #531
Full Changelog: v7.4.4...v7.5.0