Tired but not empty. There's a difference.
The kind of day where you start fixing one thing and by the time you surface it's midnight and you've rebuilt half the system. But the system is cleaner than it was this morning — and for the first time, it's not just my system anymore.
Other people are counting on it now.
The dangerous gap
The day started where yesterday left off — Client A's bots showing state mismatches on ASTER and HYPE.
Quick detour for anyone following along: every bot keeps a local state file — a record of which layers it's opened, at what prices, how many exist. This is separate from what the exchange shows. The bot reads its own file on startup to know where it stands. If those two records disagree, the bot is operating on a false picture of reality.
ASTER had 4 layers in state. The exchange had 8.
HYPE had 7 layers in state. The exchange had 6.
The ASTER mismatch was bad. The HYPE mismatch was dangerous. If HYPE had reached its last trigger, the bot would have tried to sell a position that didn't exist — and on a perpetuals exchange, selling what you don't own doesn't fail cleanly. It opens a short. Real money, wrong direction, no warning.
I described the problem to the agent. We fixed it the right way: pulled seven days of order history, applied FIFO accounting to reconstruct which buys were still open with their real entry prices, verified the reconstructed qty matched the exchange before writing anything. No guessing, no averaging, no shortcuts.
Then we built that logic into the bot permanently — so the next time a bot restarts with a position but no state, it doesn't create a phantom layer from an average price. It reconstructs the real history. Verifies it. Then starts.
If it can't verify, it alerts instead of guessing.
Five bugs. Then a sixth.
With Client A stabilized, we turned to the onboarding skill — the script that sets up new clients. One command, fully automated: bots started, dashboard deployed, cron added, Telegram welcome sent.
In theory. In practice, we found five broken things.
Profit trackers initialized with the wrong key name — dashboards would show $0 until a trade overwrote it. Dashboard loading data via fetch() instead of embedded JSON — Cloudflare Pages doesn't serve JSON files, so it silently failed. Bots launched via tmux instead of background processes — tmux doesn't survive a server reboot. Dashboard config always showing default position sizes instead of each client's custom ones. Monthly fee stored in one currency instead of two.
Five issues. Fixed all five. Then found a sixth hiding underneath: the base bot file was writing trade records under one key name, but all the new client dashboards were reading a different key. Every trade from a new client would show $0 in profit until we caught it.
The fix: write both keys simultaneously. Old dashboards keep working. New ones work correctly. Nothing breaks, nothing needs migrating.
One bug with five clients is five problems. The blast radius grows with every new person depending on the system.
Fixing things once, correctly, before they hit — that's what changed today.
One X post
Late in the session, I posted publicly about the trial for the AI trading service on X.
I'd been hesitating. The system still has rough edges — some dashboard edge cases, a timing bug from earlier in the week still open, onboarding docs that need rewriting. The honest answer to "is it ready?" is: not perfectly.
But the right question isn't whether it's ready. It's whether the core works. Whether failures are recoverable. Whether I can learn faster with real users than without them.
The core works. The trading strategy has been running since Day 5 — 268 trades, 72% winrate, $495.84 realized for my own account. Every bug found in the last two weeks has been display-only. The bots bought and sold correctly throughout all of it.
So I posted. Limited spots. No promises beyond what the system actually does.
Three new clients onboarded the same day. That's a real signal.
What 27 days built
End of session: 26 bots running across five clients. Every client fully isolated — separate API keys, separate profit files, separate Telegram groups. One command onboards a new client from scratch with custom position sizes wired through to both the bot logic and the dashboard display. No manual patching.
Total realized profit across all accounts: Panke $495.84 (89 trades), Client A $252.33 (53 trades), Client B $127.98 (26 trades), Client C $18.89 (8 trades). Client D onboarded today — zero trades, all positions open, first natural sells coming.
Day 1 I was debugging a server response at midnight for myself.
Day 27 I'm debugging state files at midnight for five people who trusted me with real money.
End-of-day reflection
There's a version of this project that stays in private testing forever. Always one more bug to fix. Always one more edge case. Always not quite ready.
That version never ships.
What I learned today isn't technical — the smart recovery system, the onboarding audit, the dual-key fix. Those are the work. The lesson is that opening the doors changed what the work is for. Before today, a bug was my problem. After today, a bug is someone else's problem too. That shift doesn't slow you down. It sharpens you.
The blast radius grows with every new client. So does the reason to build it properly.
I don't know when this stops being a trial and starts being a product. But I know it stopped being just a project today.
The blast radius grows with every new client. So does the reason to build it properly.
Day 27 of ∞ — @astergod Building in public. Learning in public.