When Our Trading AI Learned the Wrong Lesson: Debugging a Self-Optimizing System
CapTradeAI tunes its own settings from its own results, separately for every account. So when three unrelated accounts all landed on the same maximum values, that wasn't personalization. It was a bug. This is how we found it, what we fixed, and the fix that briefly made things worse.
A system that adjusts itself can fail in a way that looks like success. The numbers move, the dashboard shows "AI learned" values, everything appears to be working, and yet the system has quietly learned nothing useful. We caught ours because the values looked too alike. Here is the whole story, including the parts where we got it wrong.
How the Agent Learns
CapTradeAI does not run one fixed set of settings. Every account has its own learned values, built from that account's own trade history. Two kinds of settings are learned:
Strategy weights
Each strategy (RSI, Bollinger Bands, grid trading, and others) gets a weight that decides how loudly it votes when the agent weighs signals against each other. A strategy that has been earning its keep for an account gets a louder voice, within a hard range of 0.2 to 2.5.
Risk and timing settings
Around two dozen more: stop-loss and take-profit distances, position sizes, cooldowns between trades, consensus thresholds. Each one moves in small steps toward whatever the recent results favor, and each has a limit it cannot cross.
The promise of this design is personalization: an account whose trades behave differently should end up with different settings. Whether that promise is actually kept is exactly what we set out to test.
The Test That Raised the Question
We have a backtester that replays real historical market data through the agent's decision logic. We used it for a direct A/B comparison: the same three live accounts over the same 21 days, once with each account's learned weights and once without. If the learning works, the learned version should win.
It didn't, at least not clearly. Learned weights helped two of the three accounts and hurt the third. That is not a failure by itself, since a small sample can be noisy, but it was not the clean win the design implies either. So instead of arguing about the statistics, we did something simpler: we looked at the actual stored values.
The tell. The RSI, Bollinger and grid weights on three unrelated accounts were all pinned at the same value, about 2.48, right against the 2.5 ceiling. Meanwhile a weight with no consistent edge, the macro-sentiment weight, showed genuine differences between the accounts. Real personalization looks like the second pattern. The first pattern is a formula hitting the same wall for everyone.
Bug One: A Scale That Was Too Generous
Each strategy's weight comes from a score built from its win rate, its risk-adjusted return and a few other measures. That score is then multiplied by a confidence factor, which rewards strategies with plenty of trades behind them, and finally scaled up to the 0.2 to 2.5 weight range.
The mistake was in the arithmetic of how those pieces stack. The confidence factor can push the score up to 1.5, not 1.0, but the final scaling assumed a maximum of 1.0. So any strategy that was merely solid, not exceptional, already hit the ceiling. Being good enough for the maximum should be hard. In our formula it was routine.
The fix was a one-line change to the scaling so that only genuinely exceptional performance reaches the top of the range. We then deleted the affected stored values so every account would relearn from a clean start.
Bug Two: Every Setting Marching to the Same Wall
Once we knew to look, the same shape showed up almost everywhere. About eleven of the risk and timing settings were also stuck at exactly the same limit on every account we checked, a stop-loss distance, a take-profit distance, a cooldown, a position size multiplier.
The cause was structural. Each of these settings followed the same simple rule: if recent results look good, nudge up by a fixed step, otherwise nudge down, and never cross the limit. That works when the signal reflects one account. But the crypto market spends more than nine-tenths of its time in a quiet, range-bound state, and in that state win rates are driven mostly by the market, not by the account. Every account receives the same signal, takes the same steps in the same direction, and arrives at the same wall.
A fixed step cannot tell "this account genuinely converged here" from "this is where the shared market signal pushes everyone". So rather than patching eleven settings one by one, we changed the rule for all of them at once: the step now shrinks in proportion to how much room is left before the limit. A value in the middle of its range still moves at close to full speed. A value near its limit slows down and approaches it gradually instead of slamming into it.
Relearning From Scratch
After the fixes we reset the affected values and let the agent relearn. A day later the picture had changed in the ways we hoped:
- The strategy weights settled between roughly 1.5 and 2.3, not at the ceiling, and they differed between accounts.
- Values that used to jump to their maximum in a few cycles now stopped short of it.
- The practice (demo) account, which trades differently from the live ones, ended up with a visibly lower grid weight than they did, exactly as it should.
Some values still ended up identical across accounts. That is expected when the underlying signal is shared by the whole market, so we don't treat it as a bug on its own. But it did lead us to the next problem.
Bug Three: Settings That Could Never Build on Themselves
Two of the identical values did not look like convergence. A consensus threshold read exactly 0.223 on every account, and a trailing-stop distance was exactly 1.6% on every account, even though the accounts' win rates ranged from under 40% to over 75%.
The reason was mundane. Three of the learning routines computed their next value starting from the built-in default, not from the account's own saved value. Every cycle they started over from the same base, took one small step and saved the result, so the value never moved more than one step away from where it began, on any account. It looked like learning. It could not accumulate.
Fixing it was easy, and we added tests that check each of these routines builds on the saved value. What happened next is the most useful part of this story.
The Fix That Overcorrected
Within a day of the fix, one of the newly working settings, the maximum portfolio drawdown limit, had dropped from 12% to about 8.5% on three accounts. That limit decides when the agent starts selling to protect capital, so a value that low, arrived at that fast, is exactly what an account owner would want to be told about.
It turned out the old bug had been hiding a second one. The routine that adjusts this limit measured drawdown from the curve of realized profits over the last hundred trades, a small number on a small base, while the limit itself is checked against the value of the whole portfolio. Those are not comparable quantities, so the learning signal almost always said "drawdown is high, tighten". While the routine could not compound, that did no harm. Once we made it work, it ratcheted straight to the floor.
What we did: we switched that learning off. It is now disabled by default, the stored values were deleted, and the limit went back to its configured value. We would only turn it back on with a signal computed from the real portfolio value. Being able to fix something and then catch the side effect the next morning is the point of looking at raw values.
What We Watch Now
We already run a daily AI reviewer that reads every trade the agent made (we describe it in a previous post). It now also reads the raw learned values for every account each day, looking for the four shapes of failure this episode taught us:
A value sitting exactly at its maximum or minimum on more than one account. Real personalization rarely lands on a wall.
A value that keeps updating but stays one small step away from the built-in default, the signature of a routine that restarts from the base every cycle.
Shared values are fine when the market drives them. They become a finding when they also change live behavior, for example a threshold that quietly drifts upward and reduces how often the agent trades.
Values that nothing in the code learns any more but that still appear on a dashboard as "AI learned". We cleaned these up on the parameters page too.
What We Are Honest About
We do not yet know whether the corrected learning makes the agent more profitable. The bugs we fixed made the learned values less meaningful, and removing them makes the values meaningful again, but "meaningful" is not the same as "better returns". That question needs weeks of live data and more backtests, and we will report what we find, including if it turns out the learning adds little for a given account.
Our learning engine is also deliberately conservative: bounded ranges, small steps, and now steps that shrink near their limits. The goal is not to squeeze out a maximum. It is to make sure that when the agent adjusts itself, the adjustment is real, is specific to the account, and cannot run away.
Takeaways
- Identical values are a smell. If systems that should be different converge on the same number, look for the shared cause before believing the result.
- Look at raw values, not only outcomes. Aggregate results hid all three bugs. The stored numbers exposed them in minutes.
- Bounds hide bugs. A hard limit stops a bad value from going somewhere dangerous, but it also stops you from noticing that it tried.
- A fix can unmask the next problem. Check again the next day, and have a way to switch a change off.
The standard is the same as everywhere else in the system: a change has to be better on real data, small enough to understand, and easy to undo. A self-tuning agent earns trust by showing its work and correcting itself in public, not by claiming it never gets things wrong.
Trading cryptocurrencies involves substantial risk of loss. Nothing in this article is financial advice, and past behavior of any system does not guarantee future results.
See What Your Agent Has Learned
Pro accounts can see every learned parameter next to its default and its allowed range on the AI Learning page.