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.

3 stages
Construct · Rank · Explain
2 products
Spread Foundry · MeridianScope
8 strategies
Standard taxonomy + custom legs

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.

C

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
R

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
E

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

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.

1

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.

2

Construct

Multi-leg construction over the IV surface. Per-leg constraints — delta limits, theta limits, capital limits — applied at construction time, not after ranking.

3

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.

4

Explain

Every output candidate carries an explanation payload. Score components, dominant Greeks, liquidity flags, comparable candidates — for human decision audit.

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.

01 · Construct

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.
Read the full guide →
Construct · BullCallDebit · 30Δ · 21–45 DTE
02 · Construct

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.
Read the full guide →
Construct · IronCondor · IV-rank ≥ 0.65 · 70% PoP
03 · Rank

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);
}
Read the full guide →
Rank · EV · capital ≤ $1k · PoP ≥ 60% · max-loss ≤ $500
04 · Screen

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?;
Read the full guide →
Screen · 500 names × 8 strategies · top-10 per strategy
05 · Explain

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;
Read the full guide →
Explain · #1 IronCondor 95/105/115/120 · 4 sources

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.

retail
Spread Foundry
Retail Screens
FerroSpread powers Spread Foundry's spread-construction screens — retail-scale throughput, retail-friendly defaults, sharp UX, opinionated workflows.
pro
MeridianScope
Professional Workflows
FerroSpread powers MeridianScope's spread analytics with the full explanation payload that professional workflows require — validated, controlled, auditable.
atlas
RangeAtlas
Discovery Workspace
RangeAtlas — the named workspace inside MeridianScope where FerroSpread output is mapped to ranked, explainable opportunities for professional discovery.

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.

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.

01

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.

02

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.

03

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.

04

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.

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.

P

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.

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.com

Tell 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