Inside Kwiz Quants: An Institutional Trading Architecture Built in R/Shiny/Rhino
systematic trading architecture, R Shiny Rhino, Kwiz Quants, deflated Sharpe ratio, walk-forward cross-validation, MT5 Strategy Tester, quantitative finance Kenya
Most retail traders pick one strategy and believe in it. Kwiz Quants starts with 52,000 strategy candidates and rejects most of them, by design.
That number is not marketing. It is the cardinality of the universe scanned across four pairs-trading methods (Lead-Lag, Correlation, Cointegration, Kalman Filter) and six single-instrument strategies (MA Crossover, RSI, Bollinger Bands, MACD, Donchian Breakout, Z-Score Mean Reversion), multiplied by pair, timeframe, and parameter sweeps. The system was built in Nairobi, in R, on Shiny, structured around a Rhino-style three-tier separation. The economics matter. The architecture matters more.
Three tiers, one language
The codebase has roughly 127 R source files split across an Engine layer, a Logic layer, and a View layer.
The Engine layer holds strategy-agnostic computation. Pairs-trading signal generators, single-instrument strategies, the bar-by-bar backtester, the walk-forward cross-validation engine, the cache-first data fetcher. No Shiny code lives here. Every function in this layer is callable from a test, a batch job, or the Shiny server.
The Logic layer holds business rules and orchestration. Live signal generation, the background trading loop, the cross-validation pipeline, MAE/MFE-derived stop and target calibration, user and account stores, billing, KYC, agreement signing, the access-control engine, and the Paystack payment integration. It uses Shiny reactives internally but renders nothing.
The View layer holds the 13 Shiny modules that users actually touch. Strategy control, the trading monitor with live positions and equity curves, the backtest runner with fold drilldowns, the admin panel, the account manager, the report generator. The largest single module, strategy control, runs to around 6,800 lines because strategy selection, parameter configuration, signal display, and background trading state are tightly coupled in the user’s workflow. Splitting them would force more cross-module wiring than it would save.
This is the same architectural discipline a serious enterprise R/Shiny project uses. It is the precondition for everything that follows.
The validation pipeline that rejects most candidates
A backtest in R is easy. A defensible backtest is rare.
Kwiz Quants runs every candidate through a six-stage pipeline. Universe generation produces the raw strategy-pair-timeframe combinations. Threshold filtering drops anything that fails basic profitability and trade-count screens. Then comes the part that separates this system from a retail backtest report: dual-layer cross-validation.
The offline layer is a 10-fold walk-forward cross-validation. Each fold is a contiguous random-start window that ends at the latest bar. Inside each fold, parameters are re-optimised on the 70 percent training portion via grid search, and the resulting parameters are evaluated on the held-out 30 percent test portion. Fixed end with random start is deliberate. Rolling windows of equal size overlap by 90 percent with their neighbours and report a more flattering picture than the data supports.
The live layer runs the survivors through the native MT5 Strategy Tester. Signals are written as CSV files into the broker’s MQL5/Files directory. An Expert Advisor named KwizSignalReplay, or KwizSplitTPSignalReplay for the nine-tier version, reads them and executes against the broker’s own tick history with real spreads, real slippage, and accurate stop and target hit detection. A strategy must pass both layers to advance. The R backtest cannot lie about execution costs because the MT5 tester gets the final word.
A six-dimension Composite Robustness Score
Survival in the pipeline is necessary but not sufficient. The final gate is statistical.
Every strategy that makes it through is scored on six dimensions. Trade Sufficiency uses Newey-West HAC-adjusted effective sample size rather than the naive trade count, because autocorrelated returns inflate apparent significance. Win Rate and Payoff Consistency rewards stable rolling win rates and penalises tail-dependent profit distributions where one giant trade carries the average. CV Consistency combines fold hit rate, return coefficient of variation across folds, in-sample to out-of-sample Spearman correlation, and a Probability of Backtest Overfitting computed via the combinatorial symmetric cross-validation method of López de Prado (2018), with up to 500 partitions.
Deflated Performance is the dimension that catches the most fragile strategies. Bailey and López de Prado’s Deflated Sharpe Ratio (2014) computes the expected maximum Sharpe under the null across a universe of N candidates via extreme value theory, then asks whether the observed Sharpe survives that adjustment. When you scan 52,000 candidates, some look great by chance alone. The DSR rejects them.
Structural Fragility checks temporal stability across trade thirds and trade clustering by week. Exit Resilience compares the raw MT5 backtest with no stops to the same backtest with stops applied. If adding stops widens drawdowns or flips return direction, the strategy is fragile under realistic execution.
The weighted Composite Robustness Score classifies each strategy into PROMOTE, LOW SHARPE, CRITICALLY FLAGGED (with sub-tables for inflated Sharpe, negative Kelly, no trades), MONITOR, or QUARANTINE. Only the Promote tier reaches live portfolios. All thresholds are user-adjustable from the dashboard.
Live execution and eight risk gates
A strategy that passes the gate still has to survive live trading. The background trading process spawns as a callr::r_bg subprocess so it runs independently of the Shiny event loop. It polls MT5 for live OHLC and quotes through the kwizmt5 package, which speaks to the MetaSocket Expert Advisor over a raw TCP socket by default and falls back to an HTTP REST bridge when configured.
Every order passes eight gates before it goes to the broker. Position sizing converts risk percent and current equity into lots using the MAE-derived stop distance. The stop is the 95th percentile of winner MAE from the CV trade log. The target is the mean of winner MFE. Split-TP tiering opens up to nine sub-orders for mean-reversion strategies, three for directional ones, with allocation weighted toward the higher-probability low-MFE buckets.
A portfolio-wide risk cap, multi-timeframe filtering, a news exclusion window covering high-impact economic events, cooldowns derived from the trade interval distribution, and a robustness gate that bars anything not in the Promote tier round out the stack. Currency concentration is capped at 40 percent per currency via an HHI computation, so a portfolio cannot quietly become one big EUR position.
Each strategy gets a deterministic six-digit MT5 magic number derived from its key via CRC32 hash. The system filters positions by magic number to isolate per-strategy exposure across multiple concurrent strategies trading the same symbol.
Why this gets built in Nairobi
Kenya has the talent. The gap has never been people. It has been infrastructure access.
A Bloomberg seat at a Johannesburg systematic desk costs in the order of 25,000 dollars per year. A Nairobi quant with the same statistics and engineering training historically had a laptop and a retail MT5 terminal. That gap closes by building the infrastructure, not by buying it.
Kwiz Quants runs on commodity Linux containers. Three Docker services (the Shiny dashboard, the Paystack webhook sidecar, the strategy API), Parquet files for time-series storage via ephemeral DuckDB connections, RDS files for nested configuration, and a SQLite WAL-mode pipeline queue. The deployment footprint fits comfortably on a single mid-range VPS for one team. The validation rigour is the same a London desk would demand. The licensing bill is not.
Honest limits
R is not a low-latency execution environment. Strategies built around sub-second edges belong in C++ on co-located hardware. Kwiz Quants targets holding periods measured in hours and days, where a broker quote feed over a TCP socket is fast enough.
Broker data quality is the other persistent ceiling. Tick history from a retail MT5 broker is not institutional FX data, and any robustness score should be read with that in mind. The Capital Markets Authority has specific requirements for algorithmic trading in Kenya. Anyone deploying systematic strategies, even on a personal account, should read the framework before going live.
The starting question
The interesting question is no longer whether African quants can build institutional-grade trading infrastructure in R. The codebase exists. The architecture exists. The validation discipline exists.
The harder question is what else gets built once the assumption that institutional means imported is finally retired.
Kwiz Computing Technologies builds production R/Shiny and Rhino applications for trading teams and data-intensive businesses across East Africa. For background on why backtest metrics need adjusting before you trust them, see our note on the Deflated Sharpe Ratio. For deployment, see the R Shiny hosting guide.