End-to-end workflow for adding a new predictive signal to the market maker
Step-by-step process for adding a new predictive signal. Follow measurement-before-modeling: define what you're predicting, log it, measure baseline, then build.
Before writing code, answer:
Create a new file in src/market_maker/estimator/:
// src/market_maker/estimator/my_signal.rs
pub struct MySignalEstimator {
// State for online estimation
// Use EWMA, rolling windows, or Bayesian updates
}
impl MySignalEstimator {
pub fn new(config: MySignalConfig) -> Self { ... }
/// Update with new market data. Called on every relevant event.
pub fn update(&mut self, data: &MarketData) { ... }
/// Get current signal value, normalized to a useful range.
/// Document units in the return type or name.
pub fn signal_value(&self) -> f64 { ... }
/// Confidence in the signal (0.0 = no data, 1.0 = fully warmed up)
pub fn confidence(&self) -> f64 { ... }
}
_bps suffix for basis point values_s suffix for seconds#[serde(default)] to any checkpoint fields for backward compatwarmup_observations: usize counterAdd the module to src/market_maker/estimator/mod.rs:
pub mod my_signal;
pub use my_signal::MySignalEstimator;
src/market_maker/strategy/signal_integration.rs is the central hub. Add your signal:
update() in the appropriate update methodcompute_signals() or equivalentIMPORTANT: Only the strategy teammate edits signal_integration.rs in team mode. Others propose changes via messages.
In src/market_maker/calibration/model_gating.rs:
should_use_model() returns trueEnsure your signal's predictions are logged for calibration:
PredictionRecord in checkpoint/prediction systemIn src/market_maker/calibration/:
# Must pass
cargo clippy -- -D warnings
cargo test --lib
# Check signal compiles and integrates
cargo build
estimator/mod.rssignal_integration.rs#[serde(default)]