Documentation Index
Fetch the complete documentation index at: https://docs.novosky.app/llms.txt
Use this file to discover all available pages before exploring further.
Model overview
| Model | Type | Algorithm | Output |
|---|---|---|---|
| Signal | Classifier | RF + XGB + LGB (majority vote) | BUY / SELL / HOLD + confidence |
| Position | Classifier | RF + XGB + LGB (majority vote) | HOLD / EXIT / ADD |
| SL/TP | Regressor | LightGBM | SL multiplier, TP multiplier |
| Risk | Regressor | LightGBM | Risk multiplier [0.10, 1.25] |
Signal model
File:ml/ensemble_trainer.py / ml/ensemble_predictor.py
The signal model answers: should we trade this bar?
Architecture
Three independent classifiers trained on the same 62-feature vector with ATR-aware labeling. Majority vote determines the final prediction. When two or more models agree, confidence is that fractionβs vote strength.confidence_threshold (default 0.633), the signal is treated as HOLD.
Training
ml/tune/hyperparams.py). The tuner optimizes a custom objective that balances precision, recall, and drawdown on an OOS validation split.
Inference
Inference priority: calibrated pkl β ONNX β raw pkl After training,calibrate_models() wraps each classifier with CalibratedClassifierCV to produce well-calibrated probability estimates. The calibrated model is used at runtime.
ONNX export (
ml/model_trainer.py) runs after training but before calibration. ONNX cannot wrap CalibratedClassifierCV, so the ONNX fallback is always the uncalibrated version.Model paths
Position model
File:ml/position_trainer.py / ml/position_predictor.py
The position model answers: should we hold, exit early, or add to this open position?
Architecture
Same three-classifier majority-vote ensemble. Trained on labeled historical positions using the same 62-feature vector, but labeling captures in-trade state rather than entry signals. Output classes:- HOLD β keep position open
- EXIT β close now (reversal signal)
- ADD β increase size (continuation signal β currently conservative)
Training
ml/position_labeling.py. Labels are generated from historical trades where early exit would have improved the outcome.
Tuning
Optuna tuning:ml/tune/position.py
Dynamic SL/TP model
File:ml/sltp_trainer.py / ml/sltp_predictor.py
The SL/TP model answers: given current market conditions, what SL and TP distance (in ATR units) maximizes risk-adjusted return?
Architecture
LightGBM regressor. Outputs two values:sl_multiplierβ SL as a multiple of ATRtp_multiplierβ TP as a multiple of ATR
tp_multiplier > sl_multiplier is enforced at inference time (Phase 16 fix β previously a bug allowed tp < sl).
Training
Applied at inference
Risk multiplier model
File:ml/risk_trainer.py / ml/risk_predictor.py
The risk model answers: given the current state of the account, how aggressively should we size this trade?
Architecture
LightGBM regressor. Input: 7 equity-state features. Output: a multiplier in[0.10, 1.25].
Features
These features are fixed. They must stay in sync acrossml/risk_trainer.py, ml/risk_predictor.py, and ml_config.json β risk_model.features.
Training
The Risk model is trained after SLTP models are saved, because its training uses a backtest that requires SL/TP predictions:Kelly-inspired design
The risk multiplier is loosely inspired by Kelly criterion: scale up when the edge is high (low drawdown, high recent win rate) and scale down when conditions deteriorate. The model learns this relationship from labeled historical trade data augmented with account-state features.Model storage
Models are stored differently depending on whether you are using the Python bot or the Go binary.Python bot
| Location | What | Used for |
|---|---|---|
models/ | Metadata JSON + compatibility check | Git-tracked state |
| Hugging Face Hub | All .pkl and .onnx binaries | Distribution to trading machines |
Go binary
All model files are embedded inside the binary at compile time. Customers do not receive amodels/ directory or a Hugging Face Hub connection.
| Embedded file | Format | Go inference |
|---|---|---|
ensemble_rf/xgb/lgb.onnx | ONNX classification | input="X", outputs=["label","probabilities"] |
position_rf/xgb/lgb.onnx | ONNX classification | Same |
risk_lgb.onnx | ONNX regression | input="float_input", output="variable" |
sltp_sl/tp_lgb.onnx | ONNX regression | Same |
*_scaler.json | StandardScaler JSON | Applied before ONNX inference |
*_metadata.json | Feature names | Read at startup β never hardcoded |
Compatibility check (Python bot)
Before go-live after any retrain, verify model compatibility:ModelCompatibilityError at startup.