Construct, rank,
explain.
FerroSpread is the spread analytics and optimization engine behind Spread Foundry and MeridianScope. It constructs, ranks, and explains options spreads at retail-scale throughput and professional-grade rigor — a pure-Rust engine on the live IV surface from FerroRisk.
Capabilities
From IV surface to ranked candidates
FerroSpread is the analytical substrate behind every spread screen, every ranked list, and every explained recommendation that ships in the MorphIQ Labs spread products. Three stages, each with a clear contract.
Spread construction
Multi-leg spread construction across the standard taxonomy plus custom-leg builds, over the live IV surface from FerroRisk.
- Verticals — call/put debit/credit
- Butterflies — long, short, iron, broken-wing
- Condors — iron, regular
- Calendars and diagonals
- Custom multi-leg combinations
- Per-leg ratio support
Ranked candidates
Configurable ranking surface across the full constructed candidate set — risk-reward, probability of profit, expected return, capital efficiency, breakeven distance.
- Risk / reward ratio
- Probability of profit (theoretical)
- Expected return at expiry
- Capital efficiency (return per BPR)
- Breakeven distance from spot
- Liquidity-aware filtering
Explainable output
Every ranked candidate carries an explanation payload — why it ranks where it does, which inputs dominated the score, which sensitivities matter most. Required by the professional surface; equally available to retail.
- Score component breakdown
- Dominant Greek sensitivities
- Liquidity and pricing-confidence flags
- Comparable candidates and tradeoffs
- Designed for human decision audit
Architecture
Inputs in, ranked candidates out
FerroSpread sits between the live data + analytics layer (FerroFeed, FerroRisk, FerroWave) and the application layer (Spread Foundry, MeridianScope). Four stages, each typed at the boundary.
Inputs
Live pricing inputs from FerroFeed, the IV surface and Greeks from FerroRisk, regime overlays from FerroWave. Inputs typed at the boundary — no implicit normalization.
Construct
Multi-leg construction over the IV surface. Per-leg constraints — delta limits, theta limits, capital limits — applied at construction time, not after ranking.
Rank
Configurable scoring surface applied across the full candidate set in one pass. Liquidity-aware filtering before scoring keeps thinly-traded combos out of the ranked output.
Explain
Every output candidate carries an explanation payload. Score components, dominant Greeks, liquidity flags, comparable candidates — for human decision audit.
Use Cases
Five workflows on Construct → Rank → Explain
Each card below is a short snippet against the ferro_spread public API — a typed ChainSnapshot in, ranked and explained SpreadCandidates out. Every card maps to a real, in-production workflow behind Spread Foundry and MeridianScope.
Build a bull call debit from one chain
The simplest construction path: a typed ChainSnapshot in, a vector of SpreadCandidate out. Configure target delta, DTE band, and wing width via SpreadBuilder; the engine enumerates strike pairs, prunes infeasible combinations against the bid-ask grid, and prices each candidate on the FerroRisk parametric surface.
use ferro_spread::{ChainSnapshot, SpreadBuilder, SpreadStrategy}; let chain = ChainSnapshot::from_enriched(quote_snapshot)?; let policy = SpreadBuilder::default() .strategy(SpreadStrategy::BullCallDebit) .dte_range(21..=45) .target_delta(0.30) .min_wing_pts(5.0) .max_wing_pts(20.0); let candidates: Vec<SpreadCandidate> = policy.construct(&chain)?; // Each candidate carries legs, debit, max profit, // max loss, breakeven, and a typed PricingTrace // pointing back at the FerroRisk surface fit.
Compose an iron condor for a high-IV regime
Premium-selling structures need a different policy than directional debits. Gate condor construction on an IV-rank floor, choose a target probability-of-profit, and fix wing widths in dollars or in delta-space. The engine returns a typed IronCondorCandidate with both legs of both wings priced consistently on the same parametric smile.
use ferro_spread::{SpreadBuilder, SpreadStrategy}; let policy = SpreadBuilder::default() .strategy(SpreadStrategy::IronCondor) .iv_rank_floor(0.65) // regime gate .target_pop(0.70) // 70% probability .wing_width_pts(10.0) // $-space wings .short_strike_delta(0.16); // ~1σ tails let condors = policy.construct(&chain)?; // Empty Vec when iv_rank < floor — no condors in low-vol // regimes. Embed the gate, not in caller code.
Rank candidates by expected value under constraints
Construction emits everything that's feasible. Rankerimposes the trader's priorities: rank by expected value, capital efficiency, Sharpe-adjacent score, or a custom composite — with hard constraints on capital, PoP floor, max-loss ceiling, days-to-expiry window. Output is a sorted Vec<RankedCandidate> with the rank, the metric, and the constraint trace.
use ferro_spread::{Ranker, RankingMetric}; let ranker = Ranker::default() .by(RankingMetric::ExpectedValue) .constrain(RankingMetric::CapitalRequired, 0.0..=1_000.0) .constrain(RankingMetric::ProbabilityOfProfit, 0.60..) .constrain(RankingMetric::MaxLoss, ..=500.0); let ranked = ranker.rank(&candidates); for r in ranked.iter().take(10) { println!("{} → EV={:.2}, PoP={:.0}%", r.candidate.label, r.ev, r.pop * 100.0); }
Run the universe overnight, 8 strategies × 500 names
UniverseScreener composes the construct/rank pipeline across a watchlist or full universe. Embarrassingly parallel — one chain per name, one chain per worker. Output is a typed report with the top-K per strategy, the top-K overall, and a per-name explainability index so you can audit why each name made or missed the cut.
use ferro_spread::{UniverseScreener, ScreenerReport}; let screener = UniverseScreener::new() .universe(&watchlist_500) .strategies(&[ SpreadStrategy::BullCallDebit, SpreadStrategy::BearPutDebit, SpreadStrategy::IronCondor, SpreadStrategy::ShortStrangle, SpreadStrategy::BullPutCredit, SpreadStrategy::BearCallCredit, SpreadStrategy::CallCalendar, SpreadStrategy::PutCalendar, ]) .ranker(&ranker) .top_k(10); let report: ScreenerReport = screener.run().await?;
Audit any candidate with a typed explanation
Explainer::explain returns a typed payload that decomposes the rank into a score breakdown (which terms drove the rank?), the dominant Greeks (where does the risk live?), the comparable candidates (what else was nearly chosen?), and the assumptions trail (IV source, model, fit quality). The same payload powers the human-facing UI in Spread Foundry and the auditor view in MeridianScope.
use ferro_spread::{Explainer, Explanation, ScoreContribution}; let exp: Explanation = Explainer::explain( &candidate, &ranker)?; // Score breakdown — per-metric contribution for ScoreContribution {{ metric, contribution }} in &exp.breakdown {{ // metric: EV / PoP / CapitalEfficiency / Sharpe-adjacent // contribution: signed f64 in score units }} // Where the risk lives let (top_greek, top_value) = exp.dominant_greek(); // Sibling candidates within Δrank ≤ 2 for sibling in &exp.comparables {{ /* … */ }} // Audit trail: IV source, model, surface FitQuality let assumptions = &exp.assumptions;
Where It Ships
Inside two products
FerroSpread does not ship as a standalone consumer product. It ships inside Spread Foundry and MeridianScope — the application brands that do face the user. The endorsement line stays attribution-style: Powered by FerroSpread, FerroRisk, and FerroWave.
Code Quality
Suite-shared correctness
FerroSpread inherits its mathematical correctness story from the Ferro suite. Pricing comes from FerroRisk, regime overlays from FerroWave, live data from FerroFeed — each on its own release-gated codebase.
Pricing correctness, by FerroRisk
Pricing, IV, and Greeks come from FerroRisk — the same release-gated code that ships as a standalone pricing engine. FerroSpread does not invent its own pricing path, and inconsistencies between spread P&L and per-leg Greeks are a release-gate failure.
Suite-shared evaluation
FerroSpread reuses FerroRisk for pricing and Greeks, FerroWave for regime overlays, and FerroFeed for live data. Cross-suite consistency is the implementation, not an aspiration.
Tested ranking explanations
The explanation payload is tested. Score components must reconcile with the rank; dominant-Greek attribution must match the analytic Greeks; comparables must cover the candidate's neighborhood. Black-box ranking is a feature gap, not a feature.
Foundations
Built from first principles
FerroSpread does not reinvent pricing or hide its scoring. It composes the Ferro suite's release-gated engines into one construct → rank → explain path, typed end to end.
Pricing from FerroRisk, not reinvented
Every leg is priced on the FerroRisk parametric IV surface — the same release-gated engine that ships standalone. Spread P&L and per-leg Greeks share one evaluation path, so an inconsistency between them is a release-gate failure, not a rounding note.
Construct, then rank, then explain
Feasibility is enforced at construction — per-leg delta, theta, and capital limits — the full candidate set is scored in a single pass, and every output carries an explanation. Black-box ranking is a feature gap, not a feature.
Typed at every boundary
A ChainSnapshot in, ranked and explained SpreadCandidates out. Constraints, scores, and the pricing trace are typed values — no implicit normalization, no hidden mutable state between stages.
Deterministic and parallel
The construct/rank pipeline is embarrassingly parallel — one chain per name, one chain per worker — and deterministic: the same inputs always produce the same ranking, so a screen is reproducible and auditable.
Conventions
No surprises in the contract
The units and assumptions behind a ranked candidate are stated on the surface, so a reader of the output can reproduce the numbers without reading the source.
Pricing conventions from FerroRisk
Time in years, continuously-compounded rates, per-calendar-day theta, raw vega — FerroSpread inherits FerroRisk's stated conventions rather than re-deriving them, so a leg priced here matches the same leg priced directly.
Probabilities are model-based
Probability of profit and expected value are theoretical — computed from the parametric surface and the chosen pricing model, not empirical frequencies. The model and surface FitQuality travel with every candidate.
Capital and risk, defined
Max loss, capital required (BPR), and capital efficiency (return per BPR) are defined on the surface, stated at the call site, and reported per candidate — not left to the caller to reconstruct.
Explanations reconcile with the rank
The explanation payload is tested: score components must reconcile with the rank, dominant-Greek attribution must match the analytic Greeks, and comparables must cover the candidate's neighborhood.
In the Ferro Suite
Sibling engines
FerroSpread is one engine in a six-engine suite. Each engine has a scoped marketing surface and artifact boundary — crate, embedded engine, service, or primitive — under the shared Ferro brand and schematic visual register.
FerroMatch
Deterministic order matching engine in pure Rust. Price-time priority, crash recovery, Apache 2.0 open core.
ferromatch.morphiqlabs.com →FerroWave
Wavelet transforms for quantitative finance. DWT, MODWT, SWT, WPT, CWT, EMD, and complex wavelets.
ferrowave.morphiqlabs.com →FerroRisk
Options pricing, IV, and full first- and second-order Greeks. BSM, Black-76, Bjerksund-Stensland. Dual-licensed Apache 2.0 / MIT.
ferrorisk.morphiqlabs.com →FerroFeed
Multi-venue crypto market data normalizer. Binance, Bybit, Coinbase, Kraken — books, trades, funding rates. MIT.
ferrofeed.morphiqlabs.com →FerroReplay
Deterministic clock, replay, and journal primitives for engines that need reproducible time and state evolution.
ferroreplay.morphiqlabs.com →Talk to us
FerroSpread is the engine line for the MorphIQ Labs spread products. It ships inside Spread Foundry and MeridianScope today, with a future standalone artifact as a separate migration decision. Reach out for design-partner discussion or integration guidance on the products it powers.
hello@morphiqlabs.comTell us about your use case
- Whether you want the embedded surface (Spread Foundry / MeridianScope) or design-partner access to the engine
- Spread strategies and ranking criteria you care about
- Workload shape — single chain, full universe, batch vs streaming
- Integration timeline and existing infrastructure