tabicl-synthetics-finetuned
TabICL checkpoint (Tabular Foundation Model, in-context learning) fine-tuned for trading-action prediction (Buy / Sell / Hold) on synthetic indices Deriv/Weltrade (Boom, Crash, Volatility, GainX, PainX, FlipX, FX Vol, SFX Vol), intended to serve as the 5th expert inside a multi-expert EARCP ensemble. Trained separately from the Gold+BTC fine-tuning: synthetic indices have statistical properties (artificial jump/volatility processes) very different from real assets.
⚠️ Loading and usage (read before any predict_proba() call)
This checkpoint is an in-context learning model: .fit(X, y) does two things —
(1) gradient fine-tuning of the backbone (preserved by pickle) and (2) encoding of the
provided (X, y) context (_X_encoder_, NOT preserved by pickle.dump()/pickle.load()).
Practical consequence: loading tabicl_finetuned.pkl with pickle.load() succeeds
without error, but calling predict_proba() right after raises NotFittedError
(missing _X_encoder_). You must call .fit() once, with a representative context
set, right after loading — see load_reference.py in this repo for a complete script
and the exact 58-column order.
import pickle
from huggingface_hub import hf_hub_download
ckpt = hf_hub_download("AMFORGE/tabicl-synthetics-finetuned", "tabicl_finetuned.pkl")
scaler = hf_hub_download("AMFORGE/tabicl-synthetics-finetuned", "feature_scaler.pkl")
clf = pickle.load(open(ckpt, "rb"))
scl = pickle.load(open(scaler, "rb"))
# REQUIRED after every load: rebuilds the in-context encoder.
# X_context/y_context: see load_reference.py for the exact 58-column layout.
clf.fit(scl.transform(X_context), y_context)
proba = clf.predict_proba(scl.transform(X_new)) # [p_buy, p_sell, p_hold]
Model details
- Base architecture: TabICL v2, with gradient fine-tuning of the backbone
(
FinetunedTabICLClassifier— seetabicl) - Task: 3-class classification (0=Buy, 1=Sell, 2=Hold)
- Training symbols (28): Boom 500 Index, Boom 1000 Index, Crash 500 Index, Crash 1000 Index, FlipX 3, FlipX 4, FlipX 5, FX Vol 20, FX Vol 40, FX Vol 60, FX Vol 80, FX Vol 99, GainX 400, GainX 600, GainX 800, GainX 1200, PainX 400, PainX 600, PainX 800, PainX 1200, SFX Vol 20, SFX Vol 40, SFX Vol 60, Volatility 10 Index, Volatility 25 Index, Volatility 50 Index, Volatility 75 Index, Volatility 100 Index
- Timeframes used: M1, M5, M15, M30, H1, H4, D1
- Input dimension: 58 (49 base features × 7 timeframes + 9 asset-family one-hot)
- Exact 58-column order: see
load_reference.py(cols 0-48 = 7 features × [M1,M5,M15,M30,H1,H4,D1] in this order; cols 49-57 = asset-family one-hot in the order [boom, crash, volatility, flipx, gainx, painx, fxvol, sfxvol, other]) - Base features per timeframe: close, trend_strength, candle_pattern,
volatility, market_regime, candlestick_pattern, chart_pattern — exact formulas
(windows, thresholds) documented in
load_reference.py - An asset-family one-hot feature (9 categories: boom, crash, volatility, flipx, gainx, painx, fxvol, sfxvol, other) is appended so the model can distinguish the very different statistical regimes of Boom/Crash (jumps), Volatility (constant synthetic volatility), GainX/PainX, FlipX, FX Vol/SFX Vol.
- The scaler (
feature_scaler.pkl) was fit on all 58 columns together (base features + one-hot) — do not refit it separately, do not scale the one-hot block apart. - Labeling: anti-lookahead triple-barrier (TP=2.0×ATR, SL=1.0×ATR, horizon=60 bars of the finest available timeframe)
- Fine-tuning date: 2026-07-01T18:22:36Z
Training data
- Training samples: 34000
- Validation samples: 6000
- Source: MT5 exports (OHLCV per granularity, per symbol). No HuggingFace source (proprietary broker indices, no equivalent public data).
- Some timeframes were deliberately not exported for all symbols (deliberate choice, not a gap); in that case the corresponding features are filled with 0, exactly like the production bot's fallback when a granularity fails to fetch. Train/serve consistency guaranteed.
Results (validation set)
Overall accuracy: 0.6375
| Class | Precision | Recall | F1-score | Support |
|---|---|---|---|---|
| Buy | 0.67 | 0.77 | 0.72 | 2264 |
| Sell | 0.66 | 0.79 | 0.72 | 2291 |
| Hold | 0.42 | 0.18 | 0.26 | 1445 |
Intended use
This checkpoint is designed to serve as the 5th expert in a multi-model trading
ensemble on synthetic indices, where its contribution weight is adjusted dynamically
based on its performance and consistency with the other experts. A context-rebuilding
.fit() is required after every pickle load (see section above and load_reference.py)
— this is not optional, skipping it raises NotFittedError at inference. It is not
intended for standalone trading decisions without human supervision and upstream risk
management.
Limitations
- Synthetic indices are algorithmically generated by the broker (no real underlying asset); their dynamics may change without notice if the broker modifies its generation parameters.
- Some features may be zero for timeframes not exported for a given symbol (see above).
- The pickle does not preserve the in-context encoder (see "Loading and usage"
section) — a context
.fit()is required on every load, in every new process. - TabICL inference cost is higher than a classic gradient-boosting model (XGBoost); evaluate against the target system's latency constraints.
- Not financial advice.