Overview
ThePredictionEngine is the heart of the Polymarket Bot’s prediction system. It fuses multiple quantitative signals into a single probability prediction using mathematically sound logit-space transformations.
Key features:
- Black-Scholes binary option probability calculation
- EWMA (Exponentially Weighted Moving Average) volatility estimation
- Multi-timeframe momentum analysis (10s, 30s, 60s)
- Mean-reversion detection
- Platt scaling for probability calibration
- Intelligent abstention when conditions don’t favor prediction
src/engine/predictor.js:37
Constructor
config.engine.
Internal components initialized:
EWMAVolatilityestimator with lambda from configMomentumAnalyzerwith buffer size from configPlattScalerfor probability calibration- Recent outcomes tracker for cold-streak detection
Methods
feedTick()
Ingest a price tick into both the volatility estimator and momentum analyzer.No return value. Updates internal state.
- Updates EWMA volatility estimate
- Adds tick to momentum analyzer’s rolling buffer
- Maintains last 300 ticks (configurable via
config.engine.momentum.bufferSize)
predict()
Produce a combined probability prediction for “Will price be above strike at expiry?” Returns either a full prediction with probability and direction, or an abstention result when the bot has no statistical edge.Prediction result or abstention
Model’s predicted probability of UP outcome (0.01-0.99). Present in both predictions and some abstentions.
Predicted direction based on probability >= 0.5
Current EWMA volatility estimate (per-second σ)
Combined momentum factor (weighted ROC from 10s/30s/60s windows)
Mean-reversion signal strength
Whether Platt scaling was applied (true after 200+ samples)
True when prediction is withheld due to unfavorable conditions
Abstention reason code when abstained=true:
insufficient_data: < minTicks receiveddead_zone: probability too close to 0.5anomalous_regime: volatility spike detectedcold_streak: recent accuracy below threshold
-
Abstention checks (early exit if conditions not met):
- Insufficient data:
tickCount < config.engine.abstention.minTicks(default: 50) - Dead zone:
|baseProb - 0.5| < config.engine.abstention.deadZone(default: 0.10) - Anomalous regime:
sigma > config.engine.abstention.sigmaMultiplier * meanSigma(default: 2.0x) - Cold streak: recent accuracy
< config.engine.abstention.minAccuracy(default: 0.40) over last 20 predictions
- Insufficient data:
- Base probability: Black-Scholes binary call probability using current price, strike, volatility, and time remaining
-
Signal fusion (logit-space combination):
- Convert base probability to log-odds (logit)
- Add weighted momentum adjustment:
logitMomentumWeight * momentumFactor(weight: 150) - Add weighted reversion adjustment:
logitReversionWeight * reversionFactor(weight: 80) - Convert back to probability space via sigmoid
- Near-expiry guard: Skip momentum/reversion adjustments when ≤ 5 seconds remain
- Platt calibration: Apply Platt scaling if 200+ outcomes recorded
- Safety clamp: Final probability clamped to [0.01, 0.99]
recordOutcome()
Record a prediction outcome for cold-streak tracking and Platt calibration. Call this method after each 5-minute interval closes to feed the engine’s learning systems.Whether the prediction was correct (true) or incorrect (false)
The probability that was predicted (0-1). Optional; if omitted, uses the last prediction stored internally.
No return value. Updates internal calibration and accuracy tracking.
- Updates rolling window of recent outcomes (last 20, configurable)
- Feeds Platt scaler with prediction/outcome pair for calibration
- Platt scaler auto-fits after collecting 200+ samples
getRecentAccuracy()
Calculate accuracy over the most recent prediction window.Accuracy ratio in [0, 1]. Returns 1.0 if no outcomes recorded yet.
predict() for cold-streak detection (abstention condition 4).
reset()
Reset all internal state to initial conditions.No return value.
- Resets EWMA volatility estimator
- Clears momentum analyzer buffer
- Clears recent outcomes history
- Creates new Platt scaler instance
- Clears last prediction cache
- Starting a new trading session
- Recovering from data corruption
- Testing/development
resetMomentum()
Reset only the momentum analyzer, preserving volatility state.No return value.
Configuration
The engine reads configuration fromconfig/default.json:
Post-prediction filters (EV and margin checks) are implemented in
src/index.js:154-166 because they require market price data from Polymarket.Internal Components
EWMAVolatility
Exponentially weighted moving average volatility estimator.- Produces per-second volatility (σ) from streaming price ticks
- Uses log returns normalized by time delta
- Maintains rolling history of last 100 σ values for anomaly detection
src/engine/volatility.js:4
MomentumAnalyzer
Multi-timeframe momentum and mean-reversion detector.- Calculates ROC (Rate of Change) over 10s, 30s, 60s windows
- Combines timeframes with weights: 50% (10s) + 30% (30s) + 20% (60s)
- Detects mean-reversion when price deviates >0.3% from 2-minute SMA
src/engine/momentum.js:6
PlattScaler
Logistic calibration for probability predictions.- Auto-activates after collecting 200+ prediction/outcome pairs
- Fits logistic regression:
p_calibrated = sigmoid(A * p_raw + B) - Improves probability calibration over time
src/engine/calibration.js
Usage Patterns
Full Integration Example
See Also
- Data Feeds - ChainlinkFeed, Vatic, and Polymarket APIs
- Interval Tracker - Recording and evaluating predictions
- Data Model - Complete type definitions