All insightsENGINEERING · Architecture · 3 MIN READ

Build log: how execution accumulated constraints

Five changes to the core over six weeks, with one thing in common — none of them widened what the algorithm could do. Every one narrowed it.

Six weeks of changes to the core. Laid out together, a pattern appears: almost none of them gave the algorithm more freedom. They took it away.

A veto on the trade

The chain used to be simple: the strategy sees a signal, the strategy opens a trade.

A separate service now sits between them. The signal goes not to the exchange but to an arbiter module, which receives market context and returns two values: a direction and a confidence. If the direction agrees with the signal and confidence clears a threshold, the trade goes through. In every other case the signal is dropped.

Ordinary algorithms are greedy — they see a pattern and want to trade it. This added a cold judge that filters noise and refuses to trade where conditions are worse than the model assumed.

Risk grows only where probability is proven

Crowds raise risk on emotion: doubling size after a run of stops to win it back, or after an accidental profit while euphoric. The expected value of that behaviour points one way.

The capital management block was rewritten: base risk per setup is fixed. A multiplier engages only when a specific asset shows a rising win rate and its historical risk-to-reward stays above a threshold — then risk on the next trade in that ticker is raised.

Extra capital goes only where book density and liquidity have already demonstrated predictability. When an asset's maths breaks, the multiplier is withdrawn.

Refusing to trade what cannot be traded

A run across the top 50 assets to build the trading whitelist produced a hard split.

Assets with clear structure and a dense book produce a reliable result — even at a win rate near 31% the system finishes ahead on honest risk-to-reward. Retail favourites and memecoins burn capital: win rate falls to 10–13% and drawdown goes through the floor.

The reason is simple. The code trades market-maker logic and liquidity zones. Coins driven by an emotional crowd and headlines are chaotic noise: squeezes, slippage, unpredictable exit liquidity.

We did not rewrite the architecture so the bot could learn to trade chaos. When the maths does not work on an asset, the asset leaves the pool — the strategy is not bent to fit it.

Hitting the hardware ceiling

One CPU and 512 MB were enough for the core. As the book-evaluation logic grew, the infrastructure started to choke: the bot could not finish the maths across the whole pool and began missing valid setups.

There were two ways out: cut the asset pool to reduce load, which means accepting the loss; or add capacity and rewrite the data handling.

We took the second. The fork itself matters less than the habit of noticing it: degradation under load does not announce itself with an error in the logs. It shows up as trades that quietly never happened.

What looks like chaos and is calibration

When the system moved into actively harvesting inefficiencies with a dynamic trailing stop, from the outside it looked like overtrading: a stream of small trades.

Underneath it was calibration — probing liquidity density and fitting weights to current volatility, with the trailing logic acting as the risk limit.

There is a practical lesson beyond trading in that: in an automated system, behaviour and intent look different from the outside. Watch the risk metrics, not the event count.

The common denominator

Five changes, and not one made the algorithm smarter in the sense of "able to do more". Every one narrowed the space of permitted actions: a veto on trades, a ceiling on risk, refusing assets, refusing to lose setups to resource limits, a limiter on the trailing logic.

Reliable automation does not come from widening what a system can do. It comes from carefully placed refusals.

Related reading