Problem
Pricesearcher wanted to research statistical arbitrage as another strategy for its FX/CFD trading operation. The approach measures a pair’s spread as a z-score, enters when it moves away from its recent range, and seeks an exit as it reverts. The difficult part is assessing whether that relationship persists, how execution and risk settings affect the result, and what happens when several setups share an account.
Architecture
Research workflows load and resample bar data, rank pairs and feed backtesting tools. Scheduled AWS services run the signal engine against the S3 bar lake, while an on-demand service uses the same engine for historical inputs. MQL5 and Python engines execute configured setups, with trade-level reporting and Slack monitoring closing the review loop.
What I built
- Built data loading, spread features, correlation analysis, mean-reversion tests and monthly/yearly return analysis for pair research.
- Moved scheduled signals to AWS and built the companion on-demand historical service.
- Developed the configurable MQL5 Expert Advisor and worked on the Python bot with MT5 and offline-replay brokers.
- Built an interactive comparison app, batch optimisation, hedged variants and a Monte Carlo risk simulator.
- Developed trade-level reporting and performance alerts.
Engineering decisions
- Pair rankings identify candidates for backtesting rather than treating correlation alone as a trading signal.
- MQL5 pair evaluation waits for both symbols to confirm the same closed bar, avoiding a comparison between completed data on one leg and an unfinished bar on the other.
- Controls limit trades by account, symbol, direction and setup. Engines use per-setup identifiers and separate demo/live configurations.
- The Python engine can use z-score, half-life, correlation, Kalman-filtered hedge ratios and packaged LightGBM models, with minute-based scheduling and stop-loss/take-profit management.
Technologies
Python, MQL5, MetaTrader 5, pandas, LightGBM, Kalman filtering, AWS (Lambda, S3), Pulumi, Docker, Slack.
Results
The work connected pair research to backtests, configurable live MQL5 and Python execution, and reporting on individual setups. It provided a way to compare research results with observed trading behaviour and revisit the assumptions behind a setup.
The risk analysis is conditional on the historical data and execution assumptions. Pair relationships can break down, so the work includes drawdown analysis, exposure limits and live performance review as well as signal selection.