BUILDING AN INSTITUTIONAL-GRADE QUANT TRADING ALGORITHM FROM SCRATCH
Building Mathematical Algorithm Risk System: What It Actually Takes to Build a Quant Trading System From Scratch
1. The question that started it
In mid-2025 I asked myself a simple question: can machine learning actually predict forex price movement?
I had been trading manually since 2023 crypto first, then forex and stocks and I had hit the same wall every retail trader eventually hits: strategies that work until they don’t, mentors selling conviction instead of edge, and no real way to know if what I was doing had any statistical basis at all.
So I went looking for a better answer. What I found, fairly quickly, was that this exact question can a model extract signal from price data is the literal starting point of every systematic trading operation that exists. Jane Street, Jump Trading, Da Vinci , Goldman Sachs; the firms whose names get thrown around as the gold standard all built from some version of this same question, decades of infrastructure ago. That realization is what turned a curiosity into a project: if the question was real, and the answer was knowable, I wanted to actually find it out properly, not by vibes.
2. Losing everything
Partway into building, my laptop failed. I lost most of the data I had gathered, code that hadn’t been committed anywhere yet, and the architecture notes for how the system was supposed to work.
It was a frustrating way to learn a lesson I should have already known: nothing exists until it is backed up somewhere outside the machine in front of you. When I restarted in January 2026, the first real decision wasn’t technical it was procedural. Everything goes to version control immediately. No exceptions, no “I’ll commit it later.” That discipline ended up mattering again, months later, when a second laptop failure happened and that time, the entire project recovered cleanly from GitHub in under an hour.
3. The wrong turn
Early in the rebuild I tried to shortcut the hard part. I went looking for existing GitHub repos, open-source quant tooling, anything that claimed to replicate what real trading firms used hoping I could borrow or adapt infrastructure instead of building from zero.
It didn’t work, and the reason is obvious in hindsight: real quantitative infrastructure isn’t given away. What’s public is either toy code, years out of date, or built for a completely different market and timeframe than the one I needed. Every repo I pulled in turned out to be redundant at best, actively misleading at worst code that looked sophisticated but encoded assumptions that didn’t hold for what I was building.
The pivot was deciding to build from first principles instead: define exactly what the system needed to do, test every component against real data, and accept nothing on the strength of “this looks like what a real firm would use.”
4. Research, done honestly
This is the part most people skip when they talk about building a trading system, and it’s the part that actually matters most.
I tested three separate hypotheses before building anything live, each against a locked, out-of-sample dataset I couldn’t quietly adjust after seeing results:
Can OHLCV technical features (session returns, volatility, momentum indicators) predict next-period direction? Rejected. Negative R² across every time split tested, accuracy barely above a naive majority-class baseline, and even where a backtest showed a positive Sharpe ratio, it underperformed simply holding the asset meaning any apparent edge was noise, not signal.
Can a model predict next-session volatility better than a classical statistical baseline? Rejected. A GARCH-family statistical model beat the machine learning approach on error metrics, and neither model actually explained a meaningful share of real-world variance.
Can macroeconomic data (currency strength, real yields) classify the market’s broader regime? Rejected. The model’s accuracy wasn’t meaningfully better than simply guessing the most common class.
Three rejections in a row might sound like a wasted year. It wasn’t. This is what real research looks like the overwhelming majority of tested ideas should fail, on a locked, honest dataset, specifically so you don’t carry false confidence into live capital. The value isn’t in the hypotheses that worked. It’s in trusting the ones that survived, because you know exactly how hard you tried to kill them first.
5. What survived
None of the three machine learning hypotheses held up. What did work was something much less exotic: a rules-based system, with machine learning relegated to a supporting role (volatility forecasting) rather than the decision-maker.
The architecture that emerged rests on a few principles:
Get Ridge Dela Torjagbo’s stories in your inbox
Join Medium for free to get updates from this writer.
Risk management has final veto power over everything. No signal, however confident, overrides position sizing limits, drawdown protection, or circuit breakers.
Multiple timeframes have to agree before a trade executes. A breakout on a short timeframe gets rejected if the broader trend context disagrees a deliberate trade-off that sacrifices some speed for a meaningful reduction in false signals.
Position sizing is volatility-aware, not fixed. The same dollar risk translates to a different position size depending on current market volatility, computed from a properly time-respecting statistical model not a static lot size.
Every component is independently testable. Each layer of the system signal generation, risk checks, execution can be validated in isolation against historical data before it’s ever allowed near a live account.
6. Bugs that would have been invisible
Building the system surfaced a long list of bugs the kind that don’t show up as crashes, just as quietly wrong numbers you’d never notice unless you went looking.
A few worth naming specifically:
Look-ahead bias in volatility forecasting.
An early version of the volatility model was accidentally using information from the same period it was supposed to be forecasting meaning its backtest results were meaningless, because it was “predicting” something it had already seen. Fixed by rebuilding the model to only ever use a rolling, properly time-ordered window of past data.
Original (leaks future information)
def compute_vol(returns: pd.Series, window: int) -> pd.Series:
return returns.rolling(window=window).std()
# Corrected (strictly causal - shift first)
def compute_vol(returns: pd.Series, window: int) -> pd.Series:
return returns.shift(1).rolling(window=window).std()
The difference looks trivial. In a backtest it produced optimistic volatility forecasts that never survived live data.
Double currency conversion.A backtest on a non-USD-quoted pair showed an obviously impossible return several hundred percent. The root cause: the position-sizing step and the profit-calculation step were each independently converting currency, so the conversion was effectively applied twice. One line of defensive logic, placed in the wrong layer, silently multiplied every result.
The silent double conversion
def size_position(risk_amount: float, price: float, fx_rate: float) -> float:
return risk_amount / (price * fx_rate) # first conversion
def calculate_pnl(size: float, entry: float, exit: float, fx_rate: float) -> float:
return size * (exit - entry) * fx_rate # second conversion
# Correct placement - convert once, at the boundary
def size_position(risk_amount: float, price: float, fx_rate: float) -> float:
return risk_amount / (price * fx_rate)
def calculate_pnl(size: float, entry: float, exit: float) -> float:
return size * (exit - entry) # already in account currency
A dashboard reading from a closed database connection.A monitoring tool built to track live performance was, under certain conditions, silently reusing a database connection that had already been closed meaning it would periodically fail or show stale data with no visible error. The fix required rethinking how database connections were managed across the whole application, not just patching the symptom.
Before — connection could be closed underneath the reader
conn = get_connection()
# … later code closes it
df = pd.read_sql("SELECT * FROM trades", conn) # intermittent failure / stale data
# After - fresh connection every time, context-managed
from contextlib import contextmanager
@contextmanager
def get_fresh_connection():
conn = create_connection()
try:
yield conn
finally:
conn.close()
with get_fresh_connection() as conn:
df = pd.read_sql("SELECT * FROM trades", conn)None of these were exotic mistakes. They were the ordinary, unglamorous kind that live in every real system the difference is whether you go looking for them before they cost you money, or find out after.
7. Where it stands
The system is live now, on a demo account, running a deliberately locked six-week baseline test before any strategy or parameter changes are maderegardless of how any individual session or trade looks along the way. That discipline matters more than it sounds: the easiest way to invalidate a test is to keep tweaking the thing you’re trying to measure.
Alongside the trading system itself, I built a full audit and monitoring layerevery decision, every signal, every risk event logged and independently verifiable, with automated backups that already proved their worth once, surviving a second hardware failure without losing anything.
8. What’s next
The current system is intentionally narrow a single strategy, tuned for a specific kind of market behavior, which means it correctly does nothing when conditions don’t suit it. The next phase is building a second, complementary strategy for the market conditions the first one can’t trade, gated by a regime-detection layer that decides which tool is appropriate for current conditions.
Longer term, the goal hasn’t moved: build the first real quantitative trading firm based in Ghana and West Africa. When I went looking for firms like this in the region, I found almost nothing a couple of firms in South Africa with barely any public information, nothing closer to home, nothing with the kind of transparency and track record that firms like Jane Street or Da Vinci Trading have built over decades. That gap is the actual opportunity. Start small, prove the system survives contact with live markets, and scale only what actually holds up.




