Egis Technical Journal

Date: 23/01/2026
Topic: Binance Futures Integration (Open, Sync, Close Position)


1. Goal of the Day

Integrate real Binance USDⓈ-M Futures trading into Egis so that:

  • Bots can open real positions on Binance
  • Egis stores and controls its own state
  • Positions show live data (price, unrealised PnL)
  • Positions can be closed reliably
  • Accounting (PnL, fees, budget) remains correct and deterministic

Key principle throughout the day:

Binance is the source of market truth.
Egis is the source of accounting truth.
Frontend is display-only.


2. Exchange Architecture (Confirmed Working)

Adapter-based design

  • ExchangeAdapter interface
  • PaperExchangeAdapter
  • BinanceFuturesAdapter
  • ExchangeResolver decides adapter by exchange_key

This allowed adding Binance without touching bot/order logic.


3. Opening a Binance Position (Key Lessons)

Order placement

  • Order is sent via Binance Adapter only
  • Testnet base URL enforced:https://demo-fapi.binance.com
  • Orders are placed before any DB transaction
  • DB writes happen only after Binance success

Quantity calculation (critical)

  • User inputs USD size
  • Binance requires base quantity
  • Formula:raw_qty = size_usd / market_price final_qty = floor(raw_qty to stepSize)
  • Never round up
  • If final_qty < minQty → reject order

Important bug found

  • For BNBUSDT, rounding logic accidentally forced minQty
  • This caused $10 request → ~$17.83 position
  • Fix: reject small orders, never auto-increase quantity

4. Storing Binance Orders (Schema Design)

Based on real Binance response, not assumptions.

Stored as:

  • exchange_orders (cache layer)
  • raw_payload JSON preserved 100%

Core stored fields:

  • exchange_order_id
  • symbol
  • side
  • type
  • status
  • origQty
  • executedQty
  • avgPrice
  • cumQuote
  • updateTime

Raw JSON always kept for future-proofing.


5. Querying Binance Positions (Read-only Sync)

Binance behavior

  • /fapi/v2/positionRisk returns ALL symbols
  • Even zero positions

Egis rule

Only care about positions Egis owns.

So we:

  • Query Egis open positions (exchange_key=binance)
  • Collect symbols
  • Filter Binance response by:
    • positionAmt != 0
    • symbol IN egis_symbols

This logic is reused by:

  • CLI command
  • Bot Detail page backend

6. Precision Rules (Very Important)

Binance returns strings with high precision.

Rules enforced:

  • Never cast to float
  • Never round in backend
  • Store as DECIMAL(30,16) (or similar)
  • Rounding allowed ONLY in UI

Fields affected:

  • positionAmt
  • entryPrice
  • markPrice
  • unRealizedProfit
  • quantities

This fixed multiple hidden bugs.


7. The “Size = 0.02” Bug (Root Cause Found)

What happened

  • UI displayed position_amt (0.02)
  • Instead of size_usd (17.83)

Debugging approach

  • Exposed raw backend JSON
  • Proved backend was correct
  • UI was reading the wrong field

Fix

  • size_usd = capital allocation (Egis truth)
  • position_amt = base quantity (Binance truth)
  • UI must never mix them

8. Closing a Binance Position (Hardest Part)

Multiple failed attempts (important lessons)

❌ reduceOnly with MARKET

  • Binance rejects it
  • Error message misleading

❌ closePosition=true with MARKET

  • Invalid for MARKET
  • Only valid for:
    • STOP_MARKET
    • TAKE_PROFIT_MARKET

✅ Final correct rule (confirmed by working code)

MARKET close MUST use quantity

MARKET close:
- side = SELL (for long)
- type = MARKET
- quantity = abs(positionAmt)
- positionSide = BOTH (or LONG/SHORT in hedge mode)

No:

  • reduceOnly
  • closePosition

This matched the old working production code and finally closed positions successfully.


9. Close Position Accounting

On successful close:

  • Cache Binance close order
  • Calculate realised PnL in backend
  • Apply fee (0.05% per order)
  • Update:
    • position.status = closed
    • exit_price
    • realised_pnl
  • Orders and positions remain auditable

Frontend does zero math.


10. Safety Rules Reinforced

  • All tests use SQLite only
  • If DB is not SQLite → tests fail
  • Binance API never called in tests
  • Adapters always mocked
  • Testnet enforced in local/dev

11. Final State at End of Day

✅ Real Binance Futures orders open correctly
✅ Positions sync live mark price & unrealised PnL
✅ Precision preserved end-to-end
✅ Close position works reliably
✅ Fees and PnL calculated correctly
✅ UI reflects backend truth
✅ Architecture remains clean and extensible


12. Key Takeaway

Binance APIs are strict, misleading, and context-sensitive.
Trust behavior over docs.
Never guess—log, inspect raw JSON, and prove.

This day significantly hardened Egis into a real trading system, not a demo.