- MQL5 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| MQL5 | ||
| README.md | ||
TICC
Toeplitz Inverse Covariance Clustering in native MQL5. Estimates a sparse precision matrix per market regime, so a regime is defined by which symbols are conditionally dependent and at what lag, not by how volatile the market is.
Code for the article Toeplitz Inverse Covariance Clustering in MQL5. The article explains the method and reports the measured results. This repo is the source it describes.
What is here
A correlation matrix over FX majors is mostly the dollar leg showing up five times. Inverting it gives the precision matrix, whose off-diagonal entries are partial correlations: the relationship between two symbols once every other symbol is accounted for. An L1 penalty drives unsupported entries to exact zero, so the estimate reads as a graph instead of a heatmap.
Each bar is stacked into a vector of n symbols over w bars, so the precision
matrix covers lead and lag as well as same-bar structure. The block-Toeplitz
constraint forces the model to be time invariant inside the window. For n = 5 and
w = 5 that collapses 625 matrix entries to 115 free parameters.
The solver is ADMM. The theta step reduces to one scalar quadratic per eigenvalue, so there is no matrix inversion anywhere and the result is positive definite by construction. The Z step averages each Toeplitz group and soft-thresholds it, which is the exact proximal operator, not a projection applied afterwards.
Regimes are fitted by alternating the solver with a Viterbi pass over the whole
label path, penalising switches by beta. Labels are therefore persistent rather
than flipping on single-bar noise.
Linear algebra uses the MQL5 matrix and vector types. ALGLIB is used only to
seed the initial clustering. No Python, no DLLs.
Layout
MQL5/Include/TICC/TICC_Types.mqh config, regime and report structs, file paths
MQL5/Include/TICC/TICC_Math.mqh block-Toeplitz group map, penalty taper, eigen helpers
MQL5/Include/TICC/TICC_GraphLasso.mqh Toeplitz graphical lasso by ADMM
MQL5/Include/TICC/TICC_Engine.mqh k-means seeding, Viterbi assignment, EM loop, persistence
MQL5/Include/TICC/TICC_Data.mqh timestamp alignment, log returns, standardisation
MQL5/Include/TICC/TICC_Live.mqh chart-side causal labelling
MQL5/Scripts/TICC/TICC_SolverTest.mq5 solver checks against a known sparsity pattern
MQL5/Scripts/TICC/TICC_Fit.mq5 fits regimes, model selection, held-out diagnostics
MQL5/Indicators/TICC/TICC_Regime.mq5 non-repainting regime ribbon
MQL5/Indicators/TICC/TICC_GraphPanel.mq5 dependency graph of the active regime
MQL5/Files/TICC/ticc_c_k6_b100.txt fitted model the indicators default to
Copy the folders into your terminal's MQL5 directory and compile.
Running it
Run in this order. Each step assumes the previous one passed.
TICC_SolverTest.mq5on any chart. Needs no market data, takes a few seconds, prints twenty checks. If any fail, stop here.TICC_Fit.mq5withInpSaveModelset to a file name. Put every basket symbol in Market Watch first, since it pulls history for all of them. Writes toMQL5\Files\TICC\, then reloads and verifies the copy reproduces the same labels.TICC_Regime.mq5on a chart,InpModelFileset to that file. The model carries its own basket, so the chart symbol does not have to be one of them.TICC_GraphPanel.mq5on the same chart, same model file, same commit lag.
The shipped model ticc_c_k6_b100.txt lets you skip step 2 and attach the
indicators directly.
Settings behind the shipped model
EURUSD, GBPUSD, USDJPY, AUDUSD, USDCHF on H1, w = 5, K = 6, lambda = 0.01, taper sigma = 2.5, beta = 100, commit lag 5, 120-bar causal rolling standardisation, two-thirds training split.
InpBars counts back from whenever you run it, so refitting on a different day
gives a different window. ALGLIB seeds k-means from MathRand, so set InpSeed
if you want a fit to reproduce.
Non-repainting
The batch fit runs a backward pass and therefore sees the future. The indicators do
not use it. They freeze the fitted regimes and run the recursion forward only,
committing a label once the path behind it can no longer be revised. The cost is
that the label arrives InpCommitLag bars late, so the newest bars stay unpainted.
That gap is real and painting it would be repainting.
Things that cost me time
Four MQL5 behaviours worth knowing, all of which fail silently:
EigenSymmetricDCrejects a matrix that is asymmetric in the last bit. A covariance built asX^T Xalways is, because the two dot products accumulate in different orders. Symmetrise before every call. Hand-built test matrices pass, so this only shows up on real data.- ALGLIB seeds its k-means from
MathRandon first use. Without an explicitMathSranda fit will not reproduce even on identical data. - A convergence test that can never be met turns the iteration cap into a hidden hyperparameter that decides the answer.
- An indicator that latches its recalculation guard before doing the work turns one
early failure into a permanent one. Latch it only after a pass that painted.
Returning
rates_totalwhen nothing was drawn tells everyiCustomcaller that an empty buffer is a finished answer.
References
- Hallac, Vare, Boyd, Leskovec (2017). Toeplitz Inverse Covariance-Based Clustering of Multivariate Time Series Data. KDD 2017.
- Boyd, Parikh, Chu, Peleato, Eckstein (2011). Distributed Optimization and Statistical Learning via the Alternating Direction Method of Multipliers. Foundations and Trends in Machine Learning 3(1).
- Friedman, Hastie, Tibshirani (2008). Sparse Inverse Covariance Estimation with the Graphical Lasso. Biostatistics 9(3).
- Dempster (1972). Covariance Selection. Biometrics 28(1).
Disclaimer
Educational code. Past behaviour of any model or dataset says nothing about future results. Test on your own data and broker conditions before drawing conclusions.