The fix is a small function that rounds the price to the nearest multiple of SYMBOL_TRADE_TICK_SIZE, then normalises it to the symbol's digits:
- Read SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE).
- price = MathRound(price / tick) * tick.
- Then NormalizeDouble(price, digits).
I also round in the safe direction for stops: down for a long stop, up for a short one, so risk is never larger than planned. Same for lot sizes, rounded down to the volume step.
After the change, zero invalid stop errors in three months. Has anyone else run into tick size issues on CFDs? It seems most EA examples only consider FX.