May 2026 — Lessons
A long month. The kind where everything you tried to ship surfaced a different lesson than you expected.
What I shipped
- Migrated MT5 MCP server from a DuckDNS subdomain to my own
mt5.ahnafsukri.com. - Stood up Cloudflare Access SSO across the new domain for
openusage.ahnafsukri.com. - Built an autopilot in my trading guard daemon that copies SL/TP from existing positions onto new unmanaged ones.
- Closed a live prop-firm trade green after spending most of the morning underwater on bad entries.
What I learned
A stale .pyc will eat your entire afternoon
I rolled a fix into the rules engine. Restarted the systemd service. Tested. Still broken. Wrote test rules. Still broken. Convinced myself the logic was wrong, started rewriting.
The bug wasn’t the code. Python was loading a March-dated .pyc from __pycache__/ instead of recompiling the May source. Cache invalidation lied. rm -rf __pycache__ + restart = instant fix.
Lesson: when a fix doesn’t deploy and you’ve ruled out obvious things, suspect the bytecode cache before you suspect your understanding.
”Pure scalping mechanics” is a bad place to look for edge
Spent a week building a scalping strategy backtest framework. Tested 18 variants of a layered retest strategy on 3.5 months of XAU M1 data.
Top variant: +154R total. Looked promising.
Then I bootstrapped the results. 29% chance of negative outcome on resampled trades. One single trade contributed +204R of the +154R total — without it, the variant was a loser.
With flat sizing (no layered recovery), the entry edge alone was zero. All the “edge” came from a doubling-sizing mechanism that catches rare 5-layer recoveries.
Lesson: “Positive EV in a small sample” doesn’t mean “edge.” Especially when the positive comes from a fat tail your strategy structurally bets on. Look at concentration before you celebrate totals.
Sniper entries > scaled-in conviction
I held six XAU longs on a live prop account. Average entry around 4478. Price went to 4366 — well past my comfort. I’d scaled in over ~80 points trying to “catch the dip” earlier than the actual dip.
It bounced. I exited green. Lucky.
The disciplined version of that trade: wait for price to actually reach the H4 confluence level (4366), then mass-enter at that level. Same SL position. Same target. Different risk profile: the “I might be wrong” scenario costs 1R not 4R.
I have a demo account where I’d been doing exactly this — hundreds of closed trades, very high win rate, small average. I knew the right pattern. I didn’t apply it to live because the higher-TF setups feel scarce and the urge to enter early grows.
Lesson: the discipline you have on demo is the discipline you need on live. If the higher-TF gives you few setups, the answer is multi-pair coverage, not anticipation.
Domain migration is mostly waiting
Apex of the month’s tedium: switching an old DuckDNS subdomain over to mt5.ahnafsukri.com. Real work: 30 minutes (DNS record, nginx server block, Let’s Encrypt cert). Total elapsed: 4 hours.
Why? Cloudflare API rate-limited the write endpoints unpredictably. DNS propagation in some resolvers takes 5 minutes; some take 5 hours. The --cert-name flag for revoking certificates is different from the -d flag. Each tiny thing costs 10 minutes of context-switching.
Lesson: infrastructure changes always take 5-10x what the actual work suggests. Block real time for them.
What didn’t work
- Trying to add a
mt5.symbol_select()patch via PowerShell regex on a Windows Python file. Broke the file. Restored from backup and used a proper line-by-line script. - First attempt at building the rules engine
close_all_at_4500rule — fetched prices forprice_crossconditions only, notprice_above(the new type I’d added). Cost me real upside on a manual exit while I debugged it.
Next month
- Migrating to Cloudflare Access for SSO across all browser-facing subdomains
- Building TG button-based trade controls (replace 50% of LLM-driven commands)
- Applying the sniper discipline on the next live setup, no exceptions