Platform development and the bug-fix log, side by side
Around two years: from concept to an autonomous system
Фид Alpaca по умолчанию стоял iex — ОДНА биржа из полутора десятков. Замер по PLTR на пятнадцатиминутках за месяц: iex дал 591 бар и 28.7 млн объёма, полный тейп sip — 818 баров и 426.6 млн. Треть баров отсутствовала вовсе, остальные сложены из одной пятнадцатой сделок: их максимум, минимум и закрытие не отражали рынок. ВСЕ стоковые стратегии были доказаны на этой тени. Вывод «по бумаге эджа нет» оказался выводом о фиде: на полных данных тот же прогон нашёл семь стратегий вместо одной.
Ошибка с фидом прожила месяцы, потому что данные никто не спрашивал, кто они. Теперь перед перебором ряд проверяется на источник, глубину, полноту, разрывы и битые бары — с поправкой на режим торгов, поскольку круглосуточную крипту нельзя мерить меркой шестичасовой американской сессии. Паспорт кладётся рядом со стратегией: через месяц видно, на чём она доказана.
Порог взвода сравнивал пиковую прибыль в фунтах с ПЛАНОВЫМ риском в фунтах, а план расходится с фактом всегда — минимум лота, маржинальный кап, курс котируемой валюты. Все победители нефти выходили ровно на +1.00R при цели 2.9R: победитель стал равен проигравшему, и при винрейте 27% минус был гарантирован арифметикой. R теперь берётся из цен, где валюта и объём не участвуют. Исправлено в четырёх ботах.
Сигнал выхода считался по последнему закрытому бару — тому самому, на котором открылись. Форма бара входа выбивала сделку немедленно: медиана жизни позиции была ПЯТЬ МИНУТ при часовых и дневных стратегиях, три четверти закрывались за четверть часа. Каждое такое закрытие ставило инструмент на паузу, и бот сам себе блокировал повторный вход.
Калибровка случайности копилась через максимум со старым значением: один испорченный замер отравлял инструмент навсегда. По PLTR держалось 11.01, тогда как честный перезамер дал 1.77 — завышено вшестеро, и стратегии резались против числа, которого шум никогда не показывал. Таких ключей было 96 из 652. Перезамер теперь замещает, файл ведёт список замен.
Была зашита ровно 0.7. Если сильное движение попадало в хвост ряда, оно целиком уходило в проверку и раздувало её: у PLTR обучение дало 0.76, а проверка 11.01 — в 16 раз лучше, потому что в неё попал рывок +39% за пять дней. Сдвиг границы разоблачает такие находки за одну команду: настоящая стратегия сдвиг переживает, окно — нет.
Журнал вырос со 129 полей до 224 и подключён ко всем торгующим ботам вместо одного. На входе: тренд, положение в диапазоне, волатильность против собственной истории, время и сессия, состояние счёта и серия. На закрытии: форма пути, доля времени в прибыли, откат после пика, КПД выхода и смена режима под сделкой. Всё считается из свечей, которые бот уже держит.
Сканер читает код — этот слой смотрит на поведение. Десять проверок стоят внутри журнала, через который проходит каждая сделка, поэтому покрыты и боты, которых ещё не написали. Главная: полный стоп ОБЯЗАН давать ровно −1.0R. За первый час работы инварианты поймали живой дефект у четырёх ботов сразу — доля взятого от хода выходила больше единицы, чего быть не может.
Каждый новый класс добавлен по случившемуся на счёте: время свечи через parseFloat (у всех баров выходило число 2026), выдуманная сетка объёма, риск на котируемую валюту, закрытие чужих позиций в цикле по всему счёту, отказ брокера без паузы, флэт в поражениях, частичный фид, данные без паспорта. Из 130 находок настоящими оказались меньше половины — остальные разобраны глазами и признаны ложными.
У исполнителя Saxo профит-выход шёл по ВСЕМ позициям счёта и закрывал любую прибыльную старше десяти минут — независимо от того, кто её открыл. Счёт общий на несколько ботов: так уже гасились чужие сделки по совпадению инструмента. Теперь трогается только своё, чужое пишется в журнал и обходится.
Состав набирался по качеству, а стоимость проверялась ПОСЛЕ — дорогие стратегии занимали места, тут же выпадали на проверке доступности, и слоты стояли пустыми до следующей перезагрузки. Работало восемь из десяти. Теперь стратегия, не влезшая в план риска, пропускается при наборе, а место уходит той, что по карману; запись живёт шесть часов и снимается сама.
У ботов без брокерского идентификатора — симуляторов, крипты, акций — ключ сделки оставался пустым, и запись входа с записью выхода не связывалась. Все разрезы отчёта по сессии, дню недели и режиму молчали. Ключ теперь собирается из бота, инструмента, стратегии и момента открытия.
Проверка 500 закрытых сделок показала, что банился не тот набор: худший донор счёта торговался свободно, а инструмент с положительным результатом был закрыт. Списки переписаны по фактическим числам, а не по памяти.
Инструмент раз в два часа сравнивает, что стратегия обещала на отборе, с тем, что она дала на счёте: пять диагнозов и история расхождения. Вскрыл, что вся прибыль основного исполнителя пришла от двух сделок стратегии, которой в текущем составе уже нет.
Деление прибыли в фунтах на дистанцию в котируемой валюте давало число, лишь похожее на R. Поймано проверкой: полный стоп обязан давать −1.0, а выходило −0.098. Теперь R — это отношение пройденного к риску, без валюты.
Тринадцать страниц переведены полностью. Три ловушки ложной готовности: схема строилась из скрипта и проверку обходила, сама проверялка резала строки на четырёхстах символах и не видела длинные абзацы, а сырые угловые скобки в тексте рвали разбор и давали гибридные фразы.
Пробой с ретестом на 1833 непересекающихся сделках дал математическое ожидание +0.001R ДО издержек. Преимущество над случайным входом таяло с ростом выборки — признак шума, а не находки. Точкой отсчёта должен быть случайный вход, а не безубыточный винрейт.
Ступень «разведка» не кусалась: минимум лота биржи возвращал полный размер, и в журнале стоял £1.00 вместо £0.05. Функция расчёта бюджета не вызывалась нигде.
Real closed trades are taken from the broker and run through the model with their own parameters — the stop and target are read from the trade itself rather than supplied. The tool catches discrepancies nobody suspected: the first run found a bot whose model promised +1.31R while the account delivered +0.05R. The cause came out of the close-reason breakdown — 86% of its trades were extinguished by an outside market order, never reaching either the stop or the target.
Every previous lab measured a single strategy in isolation, but money is lost in the combination. The new one trades the whole set at once on a shared account and tests what had been eyeballed: the number of concurrent positions, the correlation threshold, the daily loss limiter and the pause after a loss. The first measurement showed the correlation limiter costs performance without reducing drawdown.
The bugs found all looked plausible: the code ran, numbers came out, the logs were quiet. Now every step is checked against a physically possible range, a violation is recorded with examples and context, and a strategy with not a single signal in its entire history is flagged as dead. Before an order is sent a single battery of checks runs: size, which side the stop and target are on, the exchange minimum, and whether the risk matches the plan to within an order of magnitude.
Bugs spread by copy-paste — a single profit-locking line lived in nine bots at once. Every known class is now described as a check and run across all the files. On its very first run the scanner found the previous day's loose end: the locking threshold had been made relative in one bot and missed in another.
The stop was rigidly tied to the interval the signal fired on, which made fast timeframes look untradeable. When to enter and how much to weight the trade are different questions: on the same data the old rule left zero survivors out of 47,682 variants, while separating them left ten.
Each strategy's signal was recomputed forty-five times over — once per target/stop pair and per exit mode. Removing the redundancy cut the run from 185 seconds to 33, and the results matched on every deterministic field.
Selection is bound by computation, not the network: an instrument on one interval downloads in two seconds and computes in two hundred. A job queue and a worker module for an outside computer were built. Only candles go out and numbers come back; the job carries no broker keys, so the computing machine cannot open a single trade.
The spread was taken from a single quote and applied to the whole history — at the weekend that meant the Friday close, overstating costs fourfold. It is now the median of the actual spread across the entire sample. A separate measurement by hour of day showed the spread inflates 2.6–5.8× at 21:00 UTC; that hour is excluded from entries everywhere.
Previously the lab modelled only the stop and the target, while the live bot applies a profit lock, a hold limit and a trading window on top of them and pays the spread — hence the systematic gap between backtest and reality. sim-core was built: one module through which every lab must run its trades. It models the whole exit stack, including the rule that a lock only applies from bars later than the one it was set on. Six mechanisms were verified separately on synthetic data.
Every live bot is run through the simulator with ITS OWN real signal and its own settings, sweeping the lock arming point and the hold limit. It produced a non-trivial result immediately: the same profit lock kills the oil trend setup (+0.165R with no lock against +0.009R when armed at 0.8R) and saves Raschke's reversion setup (+0.049R against −0.016R with no lock). There is no general rule — only a measurement per bot.
The fx-home module takes quote-currency-to-pound factors straight from the broker and caches them. Risk, margin and costs are computed in real pounds rather than yen or dollars passed off as pounds. Reconciled against live trades to the penny.
The bots sign their orders through tradeClientExtensions with the bot's tag and the planned hold time, taken from the same source that enforces the hold limit. The positions panel shows an elapsed/planned clock next to the bot icon, in red if the trade outlived its limit. This also made it possible to identify a trade's owner on a shared account and stop the bots closing each other's positions.
A measurement across 23 instruments and three timeframes showed that target reachability matches a random walk, and distant targets are RELIABLY worse than one. An R:R ceiling per timeframe was introduced and the system stopped setting targets the market never reaches.
18 ready filters were run across 7 entry types and 5 timeframes — 395 tests with a multiplicity correction. One combination survived: excluding Sunday and Friday after 18:00. It was rolled into every live bot and confirmed on the real account.
A daily stop is not enough: it does nothing about losing a little every day for many days. GTE3 gained a cap on the whole run — once the accumulated loss exceeds the limit the bot stops for good until released by hand, while open trades are still carried to completion.
The trigger now demands an impulse bar, that the break holds, and a reaction on the retest, with tolerance narrowed to less than the stop. The old version's significant loss disappeared and selectivity rose 2.6×.
The trade exit checked ONLY the last closed bar. If a bar was missed (bot restart, network timeout, downtime) the take or stop from that bar was lost and the trade ran on to a worse exit, creating a false skew towards losses. All bars since entry are now scanned and the first touch wins. Fixed in all 9 bots.
Analysis of live trades exposed the root of the weak win rate: it is not the exits (payoff is a healthy 1.6) but entries AGAINST the trend — buying support in a downtrend, selling resistance in an uptrend, while the trend broke the level and ran the trade over. An EMA50 slope filter was added: in a range we trade both directions, against a strong trend we do not enter.
The signal ensemble only worked on ENTRY (the agreement gate and position size) while the exit was blind to it. Now it is symmetric: if the instrument's whole edge pool has turned against an open position (confidence ≥ 0.45) it is closed at once rather than waiting for the stop. The combo governs both entry and exit.
Candlestick and price patterns were added to the strategy factory: engulfing, harami, pin bar (hammer/star), morning and evening star, MACD cross, price/RSI divergence, NR breakout and the three-bar reversal — plus regime filters (volatility above/below average, candle body strength). 270 → 516 combinations, each passing the null gate and walk-forward to weed out noise and overfitting.
The robust executor weights size by strategy TYPE: trend runners (payoff>1) get full size, while pure mean reversion (which historically cuts winners) has its risk trimmed by 40%. The ensemble learned to classify Gerchik and every new pattern correctly by market regime.
The only market-neutral pairs-arbitrage bot was re-checked through the pairs lab: only gold/silver and EUR/CHF survived walk-forward (PF>1.7). A key flaw was fixed — the spread was computed naively without a beta hedge, which produced false signals (verified: where the beta hedge is silent, the naive z-score was shouting «enter»). It now uses the same beta hedge as the lab and trades the validated pairs on paper until forward-confirmed.
One panel behind the robot button: the OANDA account, every executor (crypto / Kraken / Trading 212 / Alpaca — balance, trades, win rate), the GTE family and the legends, with win rate, payoff, net and on/off switches. It refreshes every 20 seconds. All the statistics in one place.
Unused code was stopped and archived: the greedy trainer daemon was removed (freeing a CPU core) and outdated bots went into the archive. The Trading 212 executor became resilient to API failures — a brief rate blip no longer freezes the bot for a whole tick.
GTE2 (false breakout) and GTE3 (bounce) were moved onto a shared level engine: entry at the level and the STOP right behind it (tight and structural) rather than blindly at an ATR or beyond the bar's wick. It was exactly that crooked stop that killed the R:R and produced a 13–27% win rate. Tight risk with a 3:1 target is now achievable. PAPER — they are gathering statistics under the monitor and will only go live on proof.
A separate monitor (cron, every 15 minutes) breaks down every trade and computes win rate / payoff / expectancy BY INSTRUMENT and BY SETUP, catching crashes, a stale heartbeat, stalls and drawdown. Its very first run exposed a donor (GBP_JPY: 17% win rate, 0.56 payoff). This is the observe → fix → calibrate loop.
The daily stop no longer shuts the bot down for a whole day after a couple of small losses. Each loss step brings a short pause with a re-evaluation, then trading continues. A full stop until tomorrow is reserved for a catastrophic drawdown. The bot works all day instead of standing idle.
A heartbeat was added: you can see it is alive, how many bars were evaluated in the tick, how many signals fired, which positions are open and WHY the bot is not entering (busy / cooldown / no signal). A low-frequency bot used to go silent between rare trades and look dead even while holding positions and working. Plus a cron auto-restart.
The null gate could only judge by the MAXIMUM of the noise (family-wise), which cuts genuine moderate edges along with the noise. A 99th-percentile (FDR) mode was added: softer and more powerful, justified by the second layer of defence (the forward gate finishes off whatever slips through). Separately: equities had no noise thresholds of their own and were judged against the forex one — they are now calibrated on their own noise.
The recipe constructor was expanded (192→270 with Bollinger %B, Stochastic, Williams %R and CCI) and included in the daily sweep. The result: 41 solid edges across 13 instruments instead of 9 across 4. The core is US30 / US2000 / EUR_USD (constructor recipes with PF 5.5–7.6 and up to 2.4 of headroom over noise).
The headroom-over-noise threshold was raised from 0.15 to 0.5: only edges with a REAL separation from randomness go into trading. Raw PF is deceptive — HK33 with PF 8.86 has just 0.84 of headroom while the US30 constructor recipe with PF 7.61 has 2.43. 21 noise-borderline edges out of 41 were discarded. The noise machinery was re-checked: the shuffling is sound, the data is clean (no spikes or broken bars) and it only errs on the safe side.
Confirmed forward winners with fewer than 25 trades used to fall into the gap between the gates (promote only released at 25+, while confirmed was set at 6+). They now trade at micro size with their tp/sl restored — proven edges went into battle, and the very first one (XAU) hit take-profit immediately.
Profit protection moved TO THE BROKER'S SIDE: once peak profit reaches £1 the stop is moved at OANDA, instantly locking at least 50% of the peak. And while profit sits under the server-side stop the trade is NOT cut by a signal but runs to take-profit (in practice all the profit came from take-profits).
A replacement for the failed GTE: it trades ONLY Gerchik setups that passed the walk-forward lab and the forward gate (level, breakout, false breakout, sweep, paranormal bar) with a Gerchik 3:1 exit. PAPER until the statistics confirm it.
The complete method from the books: the engine builds levels (paranormal bar, swing pivots, round numbers), rates their strength by touches and false breaks (floating → fixed at 2 or more) and filters out radioactive zones. Entry only on CONFLUENCE: a quality level plus a trigger on it. PAPER.
Codified and verified by the lab: Gerchik's paranormal bar (range ≥2× the average → levels at its ends, fading the false break) and the five-phase reversal (climax + break of structure + retest). Five-phase plus VWAP on the Dow H1 is a robust edge (PF up to 4.5).
About 18 composable filters (multi-timeframe level and trend, VWAP, volume spike, EMA stack, session, ADX regime, extremum break…). The lab loads the higher timeframe and tick volume and compares the strategy with and without the filter through walk-forward. The result: filters OPEN edges the base strategy never reached (DE30, XAG, WTICO, FR40, the Dow).
Forward winners that the nightly lab stopped selecting (orphans) are now loaded directly on their forward proof at micro size — previously they were never traded at all.
The knowledge base now reads video (mp4/mkv via Whisper transcription) and the fb2/docx/odt/rtf text formats (previously only pdf/djvu/epub). Transcription is niced so it never disturbs the trading bots.
Bots that ground away to nothing on flats and small losses (diluting the win rate) were removed, leaving only proven edges. The email monitoring list was aligned with the live bots, ending the not-running spam about disabled ones.
A library of pure functions: levels as probabilistic objects (P of bounce/break, quality, false breaks), P/L distributions with tails (VaR95/99, skew, kurtosis), market memory (Hurst), signal entropy, fill probability and term structure. Computed on demand, never in the hot loop.
A daemon streams Binance's real order book (depth plus aggressors from the trade feed): book imbalance, who is hitting the market, CVD and the spread. There is a chart widget plus a protective size trim in the bot. Honestly: crypto only — CFDs and FX have no central book in the first place (OTC dealers).
Trade size adapts to regime and tails: a negative expectancy or a fat VaR in the regime means a smaller size. Plus a high-conviction tier (fit ≥ 1.1 → +25%), confirmed by calibration on 6,140 trades.
The Profit Vault (30% of peak profit kept out of trading), a drawdown shield, a volatility dampener and an Anti-Correlation Guard (a cluster of joint losses puts the group risk-off). It only lowers risk under stress and never inflates it on a lucky run (scaling up along the equity curve is chasing noise and was honestly rejected).
Logistic regression on structural features gives a calibrated P(success) for an entry — a probability, not a frequency. The calibration is monotone out of sample and training runs weekly. It is interpretable, not a black box. Honestly: the edge is modest and it does not yet affect live trades — it is waiting for forward proof.
The decision log records every entry with its factors (regime/fit/size) plus the outcome, feeding a high-confidence versus ordinary report, a factor heatmap and post-mortems. Calibrating MIN_FIT on history prevented a mistaken change (one dataset's signal turned out to be noise on three others).
Two new brokers: Kraken (crypto spot, GBP) trades proven edges live, and Alpaca (equities/ETFs) gives an account overview plus a shadow bot. The broker panels were unified.
A dedicated lab mode runs walk-forward on live equity data (Alpaca): 60 robust edges across 19 symbols (AAPL, MSFT, AMZN, BAC, SMH…). Real shares, not ETF proxies.
A daily −6% and weekly −12% stop-loss plus a hard correlation limit and a regime entry gate are now on every executor (previously only OANDA had them).
Every edge is run separately over high-volatility bars and broken down by market regime, so you can see where it holds and where it is fragile.
A strategy factory: from a library of primitives (17 triggers × 8 regime filters) it generates 136 candidate recipes and the lab runs them walk-forward across the whole universe. The engine invents new edges every night — 57 passed selection on the very first run.
Between the lab found it and we trade full size sits a live forward test (data produced after the discovery cannot be fitted). Until an edge proves itself forward it trades micro size; if it fails, it is not taken. This is the defence against over-optimising across thousands of tests.
Trade size = a fixed percentage of equity at risk ÷ the ATR stop. Every trade risks the same amount, the size grows with the account (compounding), and instruments size themselves through live currency conversion.
The lab picks the best ratchet individually: Chandelier, break-even after +1R, Donchian/Turtle, an EMA trail or a fixed target. Profit often comes from the exit rather than the entry — half of the top edges chose a ratchet.
The same edges were proven walk-forward on crypto (43 of them, Binance data, honest taker costs) and are traded directly from statistics rather than by neural-network guesswork. A single account compounds, starting in PAPER until confirmed.
Coded and verified by the lab: IBS, the Fisher Transform, TRIX, Aroon, the Relative Vigor Index, the Schaff Trend Cycle, TD Sequential, the Hull MA, Crabel's NR7 and Connors' Double-7. Whatever failed walk-forward (Coppock, Camarilla, the Ultimate Oscillator) was honestly discarded.
The neural network receives a compressed consensus of every proven edge (by family) and learns to weight them by regime — 60 inputs with Trend/Range/Breakout heads. It stays in the shadows behind the AI gate until an edge is proven forward.
12 more CFD markets in the lab: world indices (Russell, DAX, Nikkei, FTSE, Euro Stoxx), palladium and softs (wheat, corn, sugar, soy) — more markets means more independent edges.
A new bot trading the Gerchik method: entry from a level (BSU-BPU pin bar, bounce, breakout-retest, false breakout) with profit running to target (R:R 2.5:1).
Documented edges added and confirmed by our own lab: Time-Series Momentum (gold), Connors RSI(2) (indices), Dual Thrust (oil), Ichimoku/Parabolic SAR (silver, platinum) and weekend crypto momentum. Whatever did not work (CCI, Heikin-Ashi, Supertrend and others) was filtered out.
A new market-neutral bot: the z-score of the spread between correlated assets (gold/platinum, USD_CAD/USD_CHF). It profits when the spread reverts, regardless of market direction.
Early closing of winning trades was removed — a winner runs to target the way manual trading does. Capital protection moved up to the daily level.
A hard daily loss limit: once breached, everything is closed until tomorrow. A single profit-protection ratchet across the whole bot fleet.
A health monitor every five minutes plus silent-failure capture in every module. An email on any breakage.
Daily snapshots for recovery after a failure, two weeks of log retention, and web log/debug viewing from the account area.
The landing page was split into separate pages (Features, Bots, Strategies, Engine, Flow, Instruments, Security, FAQ, Access) with a shared top menu.
A robot illustration with an even grid of cards around it was added to the Engine section.
Every section now carries current information about the engine: capital tiers, the profit ratchet, weekend protection and the volume breakout.
Removed the repeated stop placement every five minutes at weekends (needless API calls).
The bots increase the number of trades and strategies themselves as the account grows (in £100 tiers). Trade size is fixed — only the count grows.
Before the weekend, profitable positions are closed while losing ones stay open but are protected by a thin stop (extra loss ≤ £0.10).
Buying only on a genuine break of the local high on elevated volume, instead of a random signal.
An interactive map of the whole engine: popups on the blocks and animated data flow.
The OANDA engine started trading gold, silver, the Dow, the S&P 500 and the Nasdaq with the best walk-forward strategies (PF up to 4.93).
Daily profit is locked in steps: give back 10% of the peak and that level becomes a floor, while the bot keeps trading. Profit only moves up.
Trades now run to a real ATR target instead of being cut at spread scale. The spread stopped eating the profit.
Crypto bot: the take/stop ratio was corrected from a hopeless 1:14 to something healthy.
Added S/R bounce, breakout-retest, break of structure (BOS), multi-timeframe entry and a liquidity sweep before the break.
Strategies now pass selection only if they are profitable after spread, slippage AND the overnight swap.
The neural network's accuracy metric was fixed; it only goes live once directional accuracy is proven.
A failure to read the balance no longer shuts trading down by mistake.
A local neural network (trained on 17 books) trades in the shadows and earns the right to real money by proving an edge.
A Saxo account was connected with a SIM ⇄ LIVE switch.
Anti-429 backoff for Trading 212, plus new strategies being run in paper mode before real money.
A crypto predictor plus spot bots on Binance (dip buyer, flow momentum) were connected.
OANDA and IG were connected. Correlation, divergence and lead-lag daemons plus news sentiment analysis were launched.
Per-symbol indicator weights across 7 timeframes (M5–W), retrained on closed trades.
More timeframes and instruments, with levels and chart patterns built automatically.
A TA engine with 18 indicators and 15 technical-analysis components, a strategy library and the first bots (OTC, multi-symbol).
A custom self-learning neural network for market analysis.
The web interface, server infrastructure, the daemon system and its watchdog auto-restart.
The signal engine and daemon infrastructure were rewritten for multi-broker operation.
Parallel trading across many instruments on several timeframes.
Automatic detection of levels, patterns and divergences on the charts.
The first version of the self-learning neural network, retrained on trade outcomes.
Parameter optimisation, entry filters and risk management.
Bots launched on broker demo accounts, running around the clock.
Integration with trading APIs in demo mode.
A historical testing engine and a library of trading strategies.
The first working prototypes plus research into indicators and strategies.
Market data connected and the first signal experiments run.
The idea and concept of an autonomous multi-broker trading system.
transparency: every bug caught is part of the reliability
Фид Alpaca по умолчанию стоял iex — одна биржа из полутора десятков. Замер по PLTR на пятнадцатиминутках за месяц: iex дал 591 бар и 28.7 млн объёма, полный тейп sip — 818 баров и 426.6 млн. Треть баров отсутствовала вовсе, остальные сложены из одной пятнадцатой сделок, поэтому их максимум, минимум и закрытие не отражали рынок. Вывод «по бумаге эджа нет» оказался выводом о фиде: на полных данных тот же прогон нашёл семь стратегий вместо одной.lab
Порог взвода сравнивал пиковую прибыль в фунтах с ПЛАНОВЫМ риском в фунтах, а план расходится с фактом всегда: минимум лота, маржинальный кап, курс котируемой валюты. Все победители нефти выходили на +1.00R при цели 2.9R — победитель стал равен проигравшему, и при винрейте 27% минус был предрешён арифметикой, сколько ни улучшай вход. R теперь считается из цен.ratchet
Сигнал выхода считался по последнему закрытому бару — тому самому, где открылась сделка. Его максимум и минимум включают движение ДО входа, поэтому позицию выбивало тем, чего она не застала. Медиана жизни позиции была пять минут при часовых и дневных стратегиях, три четверти закрывались за четверть часа. Каждое закрытие ставило инструмент на паузу, и бот сам блокировал себе повторный вход.engine
Калибровка копилась через максимум со старым значением: один испорченный замер отравлял инструмент навсегда. По PLTR держалось 11.01, честный перезамер дал 1.77 — завышено вшестеро, и стратегии резались против числа, которого шум никогда не показывал. Раздутых ключей было 96 из 652.lab
Время приходит строкой вида 2026-08-11T00:00:00Z, а разбиралось через parseFloat — тот читает до первого нецифрового символа и возвращает 2026 ОДИНАКОВО для каждой свечи. Любое сравнение по времени было пустым: «свежая ли свеча», «сменился ли бар», «сколько прошло» давали ноль разницы. Жило в трёх демонах месяцами.engine
Демоны намеренно держат последнюю дневную свечу как «сегодня», и для контекста это верно, но в расчёт волатильности она попадала тоже. Рано утром диапазон дня неполный, ATR занижен, дистанция стопа мала, а объём позиции завышен. Ошибка максимальна на открытии суток и тает к вечеру, поэтому в глаза не бросалась.risk
Минимальный объём брался из зашитой в код карты и делился на сто: у золота выходил шаг 0.001 при биржевом минимуме 0.1. Три из пятнадцати открытых бумажных позиций биржа бы не приняла. Статистика считалась на сделках, которых не существует, а по ней решается вывод бота на живые деньги: при подъёме до минимума риск вырос бы вчетверо.statistics
Объём считался делением риска в фунтах на дистанцию стопа в котируемой валюте — размерности разные, поэтому верно выходило только для пар с котировкой в фунтах. Бот думал, что рискует £2.40, а рисковал £0.013. Йеновые сделки составляли 11–16% выборки и входили в статистику почти невесомыми, на долларовых риск занижался на 27%.risk
Профит-выход шёл по ВСЕМ позициям счёта и гасил любую прибыльную старше десяти минут, независимо от того, кто её открыл. Счёт общий на несколько ботов. Заодно вскрылось, что этот выход рубит любого победителя на десятой минуте — та же болезнь, что убивала соотношение прибыли к убытку у нефти.bots
Крипто-исполнитель выдал 695 отказов за пять дней, из них 694 одного вида: «объём 0 меньше минимума». Бот считал размер, которого биржа не принимает, и долбил в неё каждые пять минут — лог забивался, лимиты сети жглись, причина не устранялась.bots
У шести симуляторов ошибка записи глоталась пустым обработчиком. При заполненном диске или слетевших правах бот теряет список открытых сделок и после перезапуска считает, что позиций нет.observability
Зашитая карта знаков отличалась от биржевой на трёх инструментах из девяти. В симуляторе это грубее округляет вход, стоп и цель, а в живом боте такая карта уже отклоняла ордера индексов.bots
Метрика показывала 2.5 и 3.1 при потолке 1.0 — взять больше, чем рынок дал, невозможно. Значит неверно считается либо максимальный ход, либо выход. Число месяцами стояло в отчётах и не вызывало вопросов; поймано новым слоем инвариантов в первый же час его работы, сразу у четырёх ботов.statistics
All four live bots computed risk as «price distance × units» and treated the result as POUNDS. But that is a sum in the QUOTE currency: for USD_JPY, 2 units × 0.371 = 0.74 YEN ≈ £0.004, while the bot thought «risk £0.74». Yen trades came out economically empty (about 190× less risk than planned): they took up slots, paid the spread and closed at exactly ±£0.00–0.01. On USD pairs risk was understated by 1.33× and on CAD by 1.8×. It matched only on EUR_GBP, where the quote currency is the pound. A conversion module using the BROKER's factors (homeConversions) was introduced and reconciled against real trades to the penny.risk
The OANDA account is shared: robust, GTE3, oil and Raschke all work on it. The robust executor matched open trades to strategies BY INSTRUMENT ONLY and, on its own drawdown, liquidated OTHER bots' positions. Recorded: «STOP+RETHINK £−5.09 → closed EVERYTHING» wiped out three GTE3 trades opened a minute earlier plus the oil trade. Analysis showed 7 of oil's 24 trades (−£2.66 of −£3.81, i.e. 70% of its loss) were killed by another bot. The same bot moved other bots' stops with its own profit lock and closed their trades on its own hold limit. Ownership is now determined from the trade's tag, and other bots' trades are left alone in five places in the code.bots
The lock armed at an ABSOLUTE £0.8 against £1 of risk — that is 0.8R — and banked 0.48R against a 3R target. The lock intercepted the trade before it reached target: take-profit hits fell from 26% to 4% and expectancy from +0.165R to +0.009R. It was observable live in the most literal way — across 24 trades the take NEVER fired once and all the profit came from the lock alone. Arming was converted into R of the trade's own risk. Importantly, the measurement on Raschke gave the OPPOSITE result (a 0.8R lock was best, and without a lock it was −0.016R) — there is no general rule, only measurement.ratchet
The backtest knew only the stop and the target, while the live bot has a profit lock, a hold limit, a trading window and the spread on top of them. Hence the systematic gap: the lab promised oil a take-profit 25% of the time and live it was 0 out of 24. A single simulator, sim-core, was built to model the whole exit stack, and six mechanisms were verified separately. The rule: a new exit mechanism goes into the simulator, not just into the bot.lab
Of 395 statistical tests (7 entry types × 18 filters × 5 timeframes) exactly one combination survived the multiplicity correction: excluding Sunday and Friday after 18:00 UTC. The live account confirmed it — inside that window a trade loses £0.587 against £0.174 the rest of the time, three times as much. 3.6% of trades produced 11% of the total loss. The trading-window block was rolled into all five live bots.risk
An analysis of 1,135 live trades: the target was reached in 6.9% of cases and the median winner took 24% of its plan. At a planned R:R above 2.5 the target was reached 2% of the time (286 trades, −£242 — more than half of all stop-outs). A reachability measurement across 23 instruments showed near targets are slightly better than a random walk while distant ones are RELIABLY worse (H4 at a 3R target: −4.2 pp, t=−16.2). An R:R ceiling per timeframe was introduced.engine
In robust the threshold was an absolute £1.0 against a per-trade risk of £0.77 to £2.10. For a large trade that arms at 0.48R and locks about 0.3R against a −1R stop — a payoff below one came out arithmetically, regardless of entry quality. Live trades measured: winners closed by the lock gave +£0.94 and those closed by take-profit +£2.08, while the lock took half of all winners. The threshold was converted into a share of the trade's own risk.ratchet
The lock was set from the bar's high and immediately taken out by the low of THAT SAME bar — for a rising candle the assumption that the high comes before the low is false. Every winner was cut at 0.6× of its first peak: 50 of 81 exits went through the lock at an average of +0.71R, while the take fired three times in the whole history. Because of this the Raschke bot's paper «edge» (+£23, a 65% win rate) turned out to be an artefact. The lock now only applies from bars STRICTLY LATER than the one it was set on.lab
43 IG rejections with the useless reason «UNKNOWN» — it turned out the order was below the minimum. IG's minimums DIFFER: SPX500 = 1.0 £/point, US30 = 0.2, NAS100 = 0.05, forex and metals 0.01, while the bot hard-coded 0.01 for everything. The same on OANDA: JP225 was sent at a size of 0.004 against a 0.01 minimum and gold at 0.16 against a 0.1 step — the exchange would have rejected two of the three open trades. Minimum size, size step and price precision are now requested from the broker, and an instrument that does not fit the risk budget is honestly skipped.risk
A construct of the form `x ? x.list : []` turned an API failure into an empty list. In OANDA-robust that erased live P/L attribution forever (the record was deleted BEFORE the result arrived), and on IG it lifted the concurrent-position limit, which is counted from that very list, letting the bot open beyond the cap on top of what was already there. A network failure is now distinguished from emptiness: the whole tick is skipped.observability
The breakout-plus-retest trigger accepted ANY close beyond the level, including a slow drift, did not require the break to hold, and had a tolerance of 0.3 ATR — wider than the stop, which sits right against the level. Measured: the old trigger produced a significant loss (7,502 trades, expectancy −0.046R, z=−2.85). The strict version demands an impulse bar, that the break holds and a reaction on the retest — the significant loss disappeared (2,887 trades, −0.037R, z=−1.40) with selectivity 2.6 times higher.GTE
Dennis's system is a daily one, but the bot ran it on H1, where a 20-bar breakout means a move over 20 hours, i.e. noise, and a 10-bar exit chopped the trade off before a trend could grow out of it. The channel exit averaged +£0.36 while the 2N stop gave back −£1.93 — the winner took five times less. They were moved to daily System 2 (55-bar entry / 20-bar exit / 1N stop) plus a hold limit, which had been missing entirely.bots
In the IG executor a full position limit aborted the tick BEFORE the heartbeat was written. A bot on real money was silent in the log for six hours straight — the is-it-alive check ran straight into this. A full position book is a normal state, not a reason to disappear: the heartbeat is now written in that case too.observability
The pattern required the word CLOSE right after the emoji and a number with no pound sign, so it matched no live format at all. The panel showed 0 trades for the flagship LIVE bot. It also turned out the oil bot was missing from the watch list entirely — trading real money outside monitoring.observability
In strat-core the functions return different things: ema gives an array while sma and rsiL give a NUMBER at an index. The Bill Williams bot called sma as if it were the array version, got a number, and indexing gave undefined — so AO came out as zero on every bar. The condition «AO greater than zero» was NEVER satisfied: zero signals for the bot's entire lifetime, verified across 5,556 bars. The same trap later broke the RSI generator in the filter lab, silently skipping a third of the measurement.engine
All 26 pgrep patterns in start_daemons.sh lacked a start-of-line anchor, so any command containing the script's name counted as a live daemon. The PID file was taken by an unrelated process while the real daemon forever got already running, exiting. Caught live on the robust executor.observability
The lab counted every signal bar as a separate trade, but consecutive bars are the same move and the measurements are barely independent: n was inflated and statistical significance with it. The Turtle configuration showed +0.123R at z=2.78, while an honest sequential count gave +0.001R at z=0.64 — zero. Every lab was moved to non-overlapping trades with a correction for the number of tests.lab
The per-instrument guard let an instrument through if the strategy was flagged confirmed («we do not touch a proven edge»). USD_CHF (−£46 lifetime, a 19% win rate) kept opening despite its chronic losses. Breaking down the OANDA account: three instruments produced 71% of the total loss (BCO −£58, USD_CHF −£46, XAG −£36). Fix: a hard blacklist of edgeless donors that CANNOT be bypassed by the confirmed status. In fairness, BCO and XAG were unbanned — their win rate is 52–53% and it was the old 4-minute scalp with an inverted payoff that drained them (that daemon is already in shadow); USD_CHF and the mean-reversion knives SPX500/AU200 stay banned (payoff 0.4–0.5, both mechanisms checked and both losing).risk
The stop was placed at 1×ATR or beyond the bar's wick instead of right behind the level. The distance ballooned, the 3× target drifted out of reach, and market noise took the trade out before target → a 13–27% win rate. In Gerchik's method a tight stop works ONLY because it sits right behind the level. Fix: the stop goes right behind the level (structural), so risk is tight and 3:1 is achievable.GTE
A −£1.5 daily stop idled the bot until midnight after three small losses — a bad day was treated as switch it off for good. Fix: each loss step gives a pause with a re-evaluation, then trading continues; a full stop until tomorrow is reserved for a −£8 disaster.GTE
The exit checked TP/SL on the very candle it opened on (look-ahead): the bar's own wick could knock the trade out instantly. Fix: a position is never closed on its entry bar, only on later ones.GTE
Equities had no noise thresholds OF THEIR OWN, so equity edges were compared against the global (forex) threshold of about 5 and almost everything was cut as randomness. Exactly 1 edge survived (XLE) and even that one cannot be traded in the EU on T212 → the account sat idle not because there was nothing to trade but because the system had blinded itself. Fix: separate noise-threshold calibration for equities plus a rerun of the equity lab across the tradeable universe.T212
The fallback threshold (for instruments with no calibration of their own) accumulated as a maximum across runs and grew to 9 when the real maximum is about 5, so everything without its own threshold was judged far too strictly. Fix: the threshold is recomputed from actual values instead of growing forever.engine
A low-frequency bot (about one trade a day on slow daily setups) logged nothing between trades and so looked stopped, even though it held 2 positions and evaluated bars every tick. It also had no auto-restart — it ran by hand for almost 8 days, and had it fallen over nobody would have raised it. Fix: a heartbeat with an idle reason plus a cron watchdog.engine
The oanda-commodity-daemon had been considered disabled since 18.06, but start_daemons.sh kept it alive in LIVE mode with broken logic (a fixed-pip stop and re-entry without cooldown). On 14.07 it shorted a rising WTICO with real orders THREE times in an hour → 3 stops for −£2.84, bypassing every executor guard (it is a separate process). Fix: moved to shadow, and WTICO is traded by the executor with a proper ATR stop.engine
Paper-forward confirms an edge on 6 forward trades while promote only released it into trading at 25 — between them sat a log line saying in probation (micro) that released nothing at all. The upshot: 14 of 15 confirmed edges (+£159 of paper forward) were not traded at all and the account sat at zero. Fix: a middle tier — confirmed edges with 6–24 trades are released at micro size with their tp/sl restored.engine
Profit protection closed at market once every five minutes, but a fast reversal slipped between polls: a +£2.42 peak was banked at +£0.04 (98% given back) and a +£2.34 peak at +£0.49 (79%). Across 57 closes, all the profit came from take-profits (+£14.76 at a 100% win rate) while 29 bot closes cut trades early into a loss. Fix: a server-side stop at the broker locks profit instantly and winners run to take-profit.engine
TP/SL price rounding used a hard-coded map of three indices plus a heuristic. The rest (AU200, FR40, JP225, HK33, DE30, EU50, UK100 — one decimal) got three decimals and the broker rejected the order (precision exceeded). Index edges silently failed to open (FR40 had been rejected since 13.07). Fix: price precision is taken from the exchange (displayPrecision), not from hard-coded values.engine
The size cap assumed FIXED 15× leverage, but HK33's real margin rate is 0.10 (10× leverage). The cap let through a £5,423 position needing £542 of margin on a £373 account → INSUFFICIENT_MARGIN, and the strongest edge (PF 8.86) was not traded. The diagnosis that the account was too small proved wrong — the account carries HK33 up to 1.3 units (£307 of margin). Fix: the cap uses the instrument's REAL margin rate (taken from the exchange) — expensive edges are traded at a smaller size rather than rejected.risk
A rejected order set no pause, so HK33 (unaffordable on margin) hammered the request every five minutes for nothing, spamming the broker's API. Fix: any rejection sets a cooldown, and INSUFFICIENT_MARGIN sets six hours (the account physically cannot carry that instrument until it grows).engine
Equity orders failed with quantity-precision-mismatch — the bot sent a quantity with 6 decimals while T212 requires fewer for many shares (the precision is NOT published in the metadata). AMZN, COST and HD silently failed to open and the account stood still. Fix: a retry with decreasing precision (5→0), and since a precision rejection never fills, a double position is impossible.T212
The gte2 bot (validated Gerchik, PAPER) would not come up — cron failed to hold the process and the log froze for three days. The syntax was fine and it started by hand. It was restarted and works. gtev3's sizing was re-checked and turned out to be correct (risk-driven; the old 200-unit trades in state are legacy from before the 14.07 fix, not a current bug).GTE
The executor's ACTIVE records stored an id but no separate strat field, so the journals wrote US30/undefined on an exit close. Cosmetic — it did not affect trading (the field was only used in log text). Fix: the field was added and the journals are readable.engine
Indices and commodities have daily breaks. The bar after a break opens with a GAP, and to the patterns (sweep_wick/dthrust/phrev/bos) it looks like a powerful breakout or thrust that never happened: the strategies were validated on CONTINUOUS data where no such bar exists. Measured over 1,500 bars: the median gap is 0.16–0.25 ATR (a 1.5 ATR stop is not even touched) but the tail reaches 3.5–4.6 ATR. A gap jumps the stop on 0.27% of bars (about once every 94 days across the portfolio), and the loss is then £13–15 instead of £3.79 — the £18.94 daily limit can absorb that. Fix: a gap guard — a signal on a bar with a gap >0.5 ATR is not taken (it removes 1% of signals and almost no real trades).engine
The «edge size multiplier» (1.0–3.0) was written into the config and read by the bot into SIZE_MULT — but it was applied ONLY in the fixed-size fallback, which had been removed as the source of the 47× risk. The upshot: the user set 3× and got 1×. A control that lies. Fix: the slider works, but under an ABSOLUTE ceiling — per-trade risk cannot exceed 2% of equity no matter how far it is turned up (otherwise riskPct 3% × sizeMult 3 = 9% per trade).risk
The RATCHET-BANK block closed ALL profitable positions on the bot._bankNow flag. The flag was never set anywhere — the code was dead, but it stayed a landmine: one line of `_bankNow=true` and winners get cut mid-move again (which is exactly what produced an average win of £0.49 against an average loss of £0.70). It was deleted: profit taking is handled by THE LAB'S EXITS, tested on history alongside their own strategy.engine
server/exits.js implements 8 exit modes (break-even, Chandelier, Donchian, EMA reversal, RSI reversal, Bollinger target, climax, measured move), and the lab picks the BEST one for each edge and writes it into the `ex` field. But the executor only applied chand/atrtrail (the broker's native trailing) — 7 strategies out of 35. The other 23 traded with a DUMB fixed TP/SL, i.e. NOT the exit the edge was validated with. The code even carried a comment saying «be → client-side break-even (manageOpen)» while the manageOpen function DID NOT EXIST. As a result `be` never moved the stop to break-even after +1R (a position could go from profit into loss), `matrl` never closed on a reversal against the EMA20, and `rsix` never banked on overbought. Fix: manageOpen() on every tick — closing on a reversal signal plus tightening the stop ONLY towards profit (loosening a stop is forbidden).engine
risk-guard.corrBlocked exists and works for crypto, Kraken and T212, but OANDA NEVER CALLED IT ONCE. And its strategy list is almost all indices (US30/SPX500/US2000/UK100/DE30/EU50/JP225/HK33). Measured: US30↔SPX500 = 0.78, US30↔US2000 = 0.77, US30↔XAU = 0.71. With a 6-position limit the bot could open six index longs — that is ONE bet with six times the risk, not diversification. At the moment of discovery US30 and SPX500 were already open. Fix: a correlation limit in OANDA with a threshold stricter than standard (ONE correlated position is enough, not two). It fired immediately: US2000 was blocked.risk
setInterval started a new tick WITHOUT WAITING for the previous one. The tick is heavy (candles for every strategy, the availability gate, the stop guard) and could overrun five minutes. Two parallel ticks means a double entry on one signal, a race on state (save() overwrites itself) and breaching the position limit. Fix: a busy flag, and an overlapping tick is skipped.engine
Risk sizing computed the size for an ATR stop, but if the size rounded below the instrument's precision it fell back to a HARD-CODED size. The fact: XAU's risk size of 0.0095 → rounding → 0 → fallback to 1 → an actual risk of £44.64 instead of £0.94, 47 times over. The trade lost £5.84 in five minutes — two thirds of the day's loss. Fix: if the safe size does not fit the minimum lot, WE DO NOT TRADE. An instrument you cannot buy at the right risk is unaffordable.risk
The same bug through the back door: the over-risk protection sat under `if(factor>0)`. If the quote request failed (timeout, 500) then factor was null, risk sizing was skipped, the size stayed hard-coded, AND THE CHECK STAYED SILENT TOO. One network failure brought the whole bug back. Fix: no conversion rate means no trade.risk
Size was multiplied by edge strength (up to 1.5×) and by ensemble agreement (up to 1.6×), together up to 2.4× the plan: £9.09 instead of £3.79, i.e. 2.4% of the account instead of 1%. There was no ceiling. Fix: a 1.25 multiplier ceiling plus an absolute risk cap of 1.5× base.risk
stopLossOnFill can fail to apply (price moved, stop too close) while the MARKET order still fills. A position with no stop is unlimited loss, and nobody was watching it. Fix: a check right after submission (no stop → force one; if that fails → close) plus a guard on every tick across all open positions.risk
notional = Math.max(MINIMUM, risk size) in t212/crypto/kraken/alpaca: whenever the safe size was below the minimum lot, it took the minimum and silently blew through the risk plan. Fix: the trade is skipped in all four.risk
riskGBP was hard-coded to equity × 2% while OANDA takes riskPct from the shared config (0.5–1%). The very same brain risked differently on different brokers and nobody could see it. Fix: IG moved onto the shared config.risk
The guard threshold is a share of equity. A +£100 deposit lifted it from £7.04 to £15, and EUR_GBP with an accumulated −£9.68 loss automatically came back into trading because its loss was no longer so large. But a loss is a historical fact and a deposit does not undo it. Fix: the threshold has a ratchet — it can only tighten, never loosen.risk
HARD was fixed at £9. On a £378 account risking 1% (£3.79 per trade) trading would have stopped after two or three ordinary stops — on a routine statistical run, not an emergency. The same disease as the ratchet: absolute thresholds become noise as the account grows. Fix: 5R (five stops in a row).risk
GTEv3 and GTE2 used a HARD-CODED size, while a Gerchik stop sits beyond the level, so the distance differs for every setup. Per-trade risk was not controlled at all: a £1.50 daily limit was blown through to −£25.67, seventeen times over. Fix: size is computed FROM the stop, and if it does not fit the minimum lot the trade is skipped.GTE
A hard-coded June Donchian table with PF 1.18 on gold — against a noise threshold of 2.87 for XAU|H1. In other words its advantage was below a coin flip. It never passed the null gate. It was the one that opened that XAU trade with 47× the risk. Disabled pending validation.engine
The lab tested 82,796 combinations and kept those with PF_oos ≥ 1.1 — a threshold set by a human rather than calibrated. A check on shuffled bars: on PURE NOISE the filter found TWICE AS MANY «robust» edges (498 of 84,657 = 0.59%) as on real data (232 of 82,796 = 0.28%), and better ones at that (max pfLow 3.16 against 2.09). That means everything the bots were trading was statistically indistinguishable from randomness. Fix: the NULL GATE — the threshold became the MAXIMUM pfLow that randomness can reach on that instrument and timeframe (a reality check); a strategy must beat the best that chance can do.lab
The profit ratchet worked in ABSOLUTE pounds: ladderStep £0.15, lossBuffer £0.10. On an £88 account that is one or two ticks — profitable positions were closed for every 15 pence of daily profit while losing ones ran to a full ATR stop. The fact across 500 OANDA trades: an average win of £0.49 against an average loss of £0.70, with winners held 86 minutes against 157 for losers. Expectancy was −£0.142 per trade — no edge survives that. Fix: the thresholds were tied to per-trade risk (R = 1% of equity): bank no more often than 3R, with a 1R stop on what has been earned.ratchet
The lab validates edges with a TIME-BASED exit (maxHold bars), but the live engines had none at all: a position waited for TP or SL indefinitely. Hence 157 minutes spent holding losers. A trade thesis has a shelf life. Fix: a hold limit in both robust engines with the same values as the lab (H4 — 24 bars, H1 — 48).engine
T212, crypto (Binance), Alpaca and Kraken all took the last, still-forming bar. The signal flickered inside the interval, entry happened on a random tick, and the lab validated on closed bars — so the bots were executing a different strategy from the one that was tested. On T212 it additionally produced an order at 00:00 UTC with the US market closed → 8 cancellations out of 10. Fix: a shared bars.js module, closed candles only.engine
Every cron executor held a position for exactly 60 bars, hard-coded, on any timeframe, while the lab validates with different values (H4 — 24, M5 — 96). On H4 the bot held 2.5 times longer than had been tested. Fix: one holdMs() table from bars.js.engine
ig-robust-executor is a port of oanda-robust, but the protective layers were lost in porting: no per-instrument guard and no news gate. IG traded BCO/XAG/WTICO/NATGAS daily — the very instruments long blocked on OANDA as chronic donors (−£57/−£36). Over 30 days they gave up about £22 of IG's £27.81 total loss. Fix: risk-guard plus the donor block; strategies loaded went from 12 to 8.IG
The guard blocked a donor at max(£15, 15% of equity) — the floors were written for a large deposit and dominated on a £70 account. Replayed on the live book, the guard would have blocked NOTHING: an instrument with an accumulated −£12.67 (18% of the account!) passed as healthy. Fix: the equity share now leads: max(£2, 8%) / max(£1.5, 3%).risk
A strategy got full size on real money after eight forward trades. Of 16 confirmed edges the median was 10 trades, ONE had 20 or more and none had 30. PF 5.36 over nine trades is not an edge, it is nine coin flips. That is where proven strategies that lose money came from. Fix: a 25-trade threshold, mandatory even for those already released → full size went from 12 strategies to 1.forward gate
An HTTP 200 from the broker means the order was accepted, not filled. The bot recorded the position immediately, T212 then cancelled the order, and the bot went on managing and closing a position that did not exist, with invented P/L. Fix: a real fill is confirmed before anything is recorded.T212
strategy-lab.js wrote its result into the shared strategy_lab_results.json with no options. A single-instrument run would have left the live engines with one instrument instead of the whole universe. Fix: --inst now requires --out, otherwise the run is rejected.lab
The trailing stop for mean-reversion entries was placed ABOVE the entry, producing profitable exits on the same bar (intrabar look-ahead) and PF 854 with pfLow 356. Fix: check the previous bar's stop and cap the stop below price.lab
The single best edge (weekly XAG, PF 3.03) would not parse in the engine because of a name mismatch, so no bot could trade it. The type was added to strat-core.engine
Indices and metals were sized by the FX pattern (600 units) and got margin rejections. Explicit conservative sizes per instrument.risk
US2000, wheat and platinum were rounded to whole units → 0 → fallback. Fix: FX whole units, CFDs 2 decimals.risk
Records without a timestamp had age 0 and were never confirmed. Fallback to the state's own age.AI gate
EDGE_FAM did not include fisher/ibs/trix/rvi/…, so strong edges never claimed a slot. The pattern was widened.engine
The executor looked for forward winners inside today's lab set, but they are orphans the lab had already discarded, so the intersection was empty and proven edges were NEVER traded. Fix: proven edges are loaded directly from their forward proof.engine
parseStrat returned NULL for names like phrev15_vw or bo_retest40_htf, so executors could not load the lab's filtered edges. Fix: filter suffixes are parsed and it fails closed (no context means no entry, protecting live money).engine
29 videos were processed before the Whisper PATH fix and were recorded as done with zero lessons, so they were skipped forever. Fix: the done flag was cleared and the niced pipeline reprocessed them.AI training
The monitor sent a CRIT every hour about bots that had been deliberately switched off (binance, gte, ig-kr) because they had no .DISABLED marker. Fix: the monitoring list was aligned with the live bots and the hang threshold moved from 30 to 90 minutes.observability
The old GTE fired Gerchik setups with no walk-forward validation and no forward gate, giving a 13% win rate and draining the whole paper balance. It was retired and replaced by the validated GTE2/GTEv3.bots
A hold counted as a miss on any move, dragging accuracy down to 8%. Real directional accuracy was 47%. The metric was fixed (holds excluded) and the accuracy gate now uses directional accuracy.AI
The position was closed by the server-side stop but local state still thought it was alive, so it retried the close every 10 seconds forever. Fix: reconciliation via fetchOpenTrades.IG
executeIgTrade without await meant every pair saw free slots at once, giving six correlated shorts. Fix: await plus caps per side and per currency.IG
It logged PROTECTION every 7 minutes (session £0.77 vs a floor of £1.05). Fix: the floor is re-based when it fires.ratchet
The cooloff re-fired every 10 minutes below −£1.5. Fix: _coolFloor — only on each new step down.risk
totalTrades counted flat trades, so the win rate sank. Fix: wins/(wins+losses).statistics
The executor loaded a strategy with PF 6.84 on eight trades. Fix: MIN_OOS_TRADES=20 plus a bootstrap pfLow.lab
ER(i,N) was called instead of ER(cl,i,N) (array first), so tsmom was always zero. The signature was corrected.engine
A wrong argument and no await left amountUSD undefined, so the guard never blocked anything. Fixed the argument, added .ok and await.binance
The bots only logged on trades, so the log went stale and raised a false alert; cron without setsid could not hold them. Fix: a 20-minute heartbeat plus a setsid respawn.observability
A size of 500/1 instead of the IG minimum caused rejections and crashes. Sizes were brought in line with IG (0.01–0.02).IG
Whisper called ffmpeg from PATH (which was not there), so it failed silently. Fix: PATH injected at spawn.AI training
The relevance filter was English-only, so a Russian course yielded zero lessons. A Russian keyword dictionary was added.AI training