Skip to content

Fix #219: Use real exchange lot_size (stepSize) and MIN_NOTIONAL for crypto perps - #222

Open
mwaleedta wants to merge 1 commit into
OpenByteInc:mainfrom
mwaleedta:main
Open

Fix #219: Use real exchange lot_size (stepSize) and MIN_NOTIONAL for crypto perps#222
mwaleedta wants to merge 1 commit into
OpenByteInc:mainfrom
mwaleedta:main

Conversation

@mwaleedta

Copy link
Copy Markdown

Summary

Fixes issue #219 where the Strategy V2 engine hardcoded crypto lot size to 1e-8 for all crypto symbols, while real Binance perpetuals use integer coin lots (stepSize = '1' for many perps). This caused sub-lot 'dust' to remain after partial fills due to the per-bar liquidity cap, which then blocked symbol re-entry because position.amount > 0.

Changes

1. CryptoDataSource (backend_api_python/app/data_sources/crypto.py)

  • Added _get_lot_size_and_min_notional() method that fetches stepSize (from precision.amount or limits.amount.min) and MIN_NOTIONAL (from limits.cost.min) from CCXT market data
  • Modified get_kline() to include lot_size and min_notional in each bar via format_kline()

2. Base Data Source (backend_api_python/app/data_sources/base.py)

  • Extended format_kline() to accept optional lot_size and min_notional parameters

3. Strategy V2 Data Portal (backend_api_python/app/services/strategy_v2/data.py)

  • Added min_notional to the bar cache extraction so it's available during execution

4. Strategy V2 Runtime (backend_api_python/app/services/strategy_v2/runtime.py)

  • Updated _lot_size() to use bar.lot_size from exchange data (falls back to 1e-8 for backward compatibility)
  • Added _min_notional() helper to read bar.min_notional
  • Added MIN_NOTIONAL validation in order execution path (rejects orders below exchange minimum)
  • Force sub-lot position residuals to zero (abs(current.amount) <= lot_size) to prevent dust
  • Improved _round_to_lot() precision from 1e-8 to 1e-12

5. Tests (backend_api_python/tests/test_strategy_v2_runtime.py)

  • test_crypto_integer_lot_size_no_dust_on_close: Verifies real lot_size prevents dust on close
  • test_crypto_min_notional_rejection: Verifies MIN_NOTIONAL validation works
  • test_crypto_position_dust_forced_to_zero: Verifies sub-lot residuals are zeroed
  • test_backtest_results_independent_of_initial_capital: Verifies the core fix - backtest results no longer depend on initial capital

Testing

All 1419 existing tests pass + 4 new tests for this fix.

…TIONAL for crypto perps

- Add _get_lot_size_and_min_notional() to CryptoDataSource to fetch exchange
  precision/limits (stepSize and minNotional) from CCXT market data
- Pass lot_size and min_notional through format_kline() into bar data
- Update _lot_size() in runtime to use bar.lot_size from exchange data
- Add _min_notional() helper and validate MIN_NOTIONAL during order execution
- Force sub-lot position residuals to zero to prevent dust blocking re-entry
- Fix precision in _round_to_lot (1e-12 instead of 1e-8)
- Add tests for integer lot sizes, MIN_NOTIONAL rejection, dust elimination,
  and capital-independent backtest results
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant