Topic: Funding fees, invariants, and making the system honest
Today was one of those days where the system didn’t “break” loudly — it failed silently. And that’s always the more dangerous kind.
What I worked on
1. Funding fee pipeline (deep dive)
I focused heavily on the funding fee collector, because Admin metrics were clearly wrong:
- Funding fees stopped appearing after 2026-02-02 08:00 UTC
- Admin showed 0 despite positions being open and Binance UI showing fees
I built an audit command that answered hard questions instead of guessing:
- When was the last funding fee actually recorded?
- How many 8h funding windows are missing?
- Which bots and symbols were affected?
- Were positions open (including closed ones now) during those windows?
This immediately gave clarity:
- Scheduler was still running.
- Commands exited cleanly.
- Positions (open + closed) were correctly selected.
- But no new funding rows were written.
That shifted the investigation from “logic bug” to data-source mismatch.
2. Closed positions are now first-class citizens
I fixed the funding sync logic so it no longer only considers currently open positions.
Instead, positions are selected by time overlap:
- opened_at < window_end
- closed_at IS NULL OR closed_at > window_start
The logs now explicitly prove that closed positions are included per window, with sample IDs.
This removed a huge blind spot in historical funding accounting.
3. Proved the bug is not in Egis core logic
With detailed logs (run_id, windows, position counts, fetched rows), I could say with confidence:
- ❌ Not a DB issue
- ❌ Not a timezone bug
- ❌ Not a duration / lifecycle bug
- ❌ Not a negative-fee filter bug
- ❌ Not deleted-bot exclusion
The system was honest — it said:
“Bots synced, positions selected, but API returned no new funding records.”
That honesty is a win.
4. Found the real problem: Binance API usage
Incremental mode revealed a critical clue:
- Binance API does return funding fees
- But only old ones (duplicated at 2026-02-02 08:00 UTC)
- Range mode never fetched beyond that
This strongly pointed to:
- Cursor (last_synced_at) still clamping requests
- Or incorrect Binance endpoint / params / pagination
You then confirmed something important:
Binance UI clearly shows funding fees on 2026-02-05
That was the final nail — Egis was asking Binance wrong, not Binance lacking data.
5. Anchored on a known-good solution (Samir)
Instead of continuing to guess, I decided to stop reinventing.
There is already a working Binance funding fee implementation in another project (Samir).
So the plan is now clear and grounded:
- Read that implementation line by line
- Match endpoint, params, pagination, time units, and behavior
- Port that logic into Egis
- Make range mode ignore cursors when explicitly requested
This is a shift from “debugging” to aligning with a proven reference.
6. Admin UX & structure improvements (parallel work)
While deep in backend work, I also cleaned up Admin UX and navigation:
- Grouped menus logically:
- Trading → Positions, Fees, Signal Hooks
- Insights → Strategy Report, Execution Quality, Average Metrics
- Sidebar now behaves like a proper accordion:
- One group open at a time
- Sub-menus align cleanly and share background with main menu
- Dashboard cards are now consistently linkable
- Fees and money values are formatted everywhere as $0.00
- Average Metrics page gained:
- Proper daily averages
- shadcn date picker
- Presets: 7 / 30 / 90 days
All of this reinforces the same theme: calm, honest, explainable Admin UX.
What I learned
- “No data” is a signal, not a failureIf the system can prove it tried correctly, silence becomes actionable information.
- Audit commands are more valuable than fixesThe audit command paid for itself immediately. It turned uncertainty into facts.
- Never fight an exchange API blindBinance APIs are full of edge cases (account type, incomeType, pagination, cursors).If you already have a working implementation — reuse it.
- Cursors must never override explicit intentIf a user says “sync this date”, the system must obey — cursors are helpers, not masters.
- Correctness beats speedIt’s slower to build proof and logs, but it prevents weeks of phantom bugs later.
Status at end of day
- Egis core logic is sound
- Funding fee bug is isolated to Binance API integration
- Next step is mechanical and safe: follow the Samir solution
- Admin UI is cleaner, calmer, and more truthful than before
Today wasn’t about adding features —
it was about making the system incapable of lying.
And that’s real progress.
