Esc

    The API is under testing and may change before release.

    Load a vol grid

    You'll load an equity's spot and a grid of vols, expiries down the side and strikes across the top, into a market, and price an option on it.

    Before you start

    • helixio installed: see installing.
    • The spot and a grid of lognormal vols: one row per expiry, one column per strike. The program's figures are made up.

    Steps

    1. Build the surface from the grid with FutureOptionVolSurface(close, expiries, strikes, vols, "lognormal").
    2. Pin the spot and the surface under the equity's name with with_equity_spot and with_equity_vols.
    3. Price an option on the name with products.equity_option. To read a vol back off the surface, see equity spots and vols.

    The comments in the program match these steps.

    Rust
    use chrono::NaiveDate;
    use helixrs::{
        AnyInstrument, CollateralSpec, EquityOption, FutureOptionVolSurface, MarketContext,
        OptionKind, QuoteSheet, VolConvention,
    };
    
    type Outcome<T> = Result<T, Box<dyn std::error::Error>>;
    
    /// The close and its SOFR swap quotes, for discounting.
    const SOFR_CLOSE_DATE: (i32, u32, u32) = (2026, 10, 1);
    const USD_SOFR_CLOSE: &[(&str, &str, f64)] = &[
        ("USD-SOFR-OIS", "1M", 0.0391),
        ("USD-SOFR-OIS", "3M", 0.0402),
        ("USD-SOFR-OIS", "1Y", 0.0439),
        ("USD-SOFR-OIS", "2Y", 0.0459),
        ("USD-SOFR-OIS", "3Y", 0.0468),
        ("USD-SOFR-OIS", "4Y", 0.0469),
        ("USD-SOFR-OIS", "5Y", 0.0471),
        ("USD-SOFR-OIS", "7Y", 0.0475),
        ("USD-SOFR-OIS", "10Y", 0.0483),
        ("USD-SOFR-OIS", "15Y", 0.0494),
        ("USD-SOFR-OIS", "20Y", 0.0499),
        ("USD-SOFR-OIS", "30Y", 0.0492),
    ];
    
    /// Your grid's spot. The figures are made up for this guide.
    const SPOT: f64 = 120.0;
    
    fn date((year, month, day): (i32, u32, u32)) -> NaiveDate {
        NaiveDate::from_ymd_opt(year, month, day).expect("a real calendar date")
    }
    
    fn main() -> Outcome<()> {
        let close = date(SOFR_CLOSE_DATE);
        let usd = "USD".parse()?;
        // Your grid: a row of vols per expiry, a column per strike.
        let expiries = vec![date((2027, 4, 1)), date((2027, 10, 1))];
        let strikes = vec![100.0, 120.0, 140.0];
        let vols = vec![vec![0.29, 0.26, 0.24], vec![0.28, 0.25, 0.235]];
    
        // Build the surface from the grid and pin it, with the spot, under the name.
        let surface = FutureOptionVolSurface::new(close, expiries.clone(), strikes, &vols, VolConvention::Lognormal)?;
        let market = MarketContext::as_of(close)
            .with_recipe_quotes(
                &CollateralSpec::Currency(usd),
                &QuoteSheet::from_rows(USD_SOFR_CLOSE.iter().copied())?,
            )?
            .with_equity_spot("ACME", SPOT)?
            .with_equity_vols("ACME", surface);
    
        // Price an at-the-money call on the name off the grid.
        let call = AnyInstrument::EquityOption(Box::new(EquityOption::new(
            "ACME",
            usd,
            OptionKind::Call,
            120.0,
            expiries[1],
            1.0,
        )?));
        let npv = call.npv(&market)?;
        println!("call npv          {npv:.6}");
    
        Ok(())
    }
    Python
    import datetime as dt
    
    import helixio as hlx
    
    # The close and its SOFR swap quotes, for discounting.
    SOFR_CLOSE_DATE = dt.date(2026, 10, 1)
    USD_SOFR_CLOSE = {
        "USD-SOFR-OIS": {
            "1M": 0.0391,
            "3M": 0.0402,
            "1Y": 0.0439,
            "2Y": 0.0459,
            "3Y": 0.0468,
            "4Y": 0.0469,
            "5Y": 0.0471,
            "7Y": 0.0475,
            "10Y": 0.0483,
            "15Y": 0.0494,
            "20Y": 0.0499,
            "30Y": 0.0492,
        },
    }
    
    # Your grid: a row of vols per expiry, a column per strike. The figures are
    # made up for this guide.
    SPOT = 120.0
    EXPIRIES = [dt.date(2027, 4, 1), dt.date(2027, 10, 1)]
    STRIKES = [100.0, 120.0, 140.0]
    VOLS = [[0.29, 0.26, 0.24], [0.28, 0.25, 0.235]]
    
    # Build the surface from the grid and pin it, with the spot, under the name.
    surface = hlx.vols.FutureOptionVolSurface(SOFR_CLOSE_DATE, EXPIRIES, STRIKES, VOLS, "lognormal")
    market = (
        hlx.MarketContext(SOFR_CLOSE_DATE)
        .with_recipe_quotes("USD", USD_SOFR_CLOSE)
        .with_equity_spot("ACME", SPOT)
        .with_equity_vols("ACME", surface)
    )
    
    # Price an at-the-money call on the name off the grid.
    call = hlx.products.equity_option("ACME", "USD", strike=120.0, expiry=EXPIRIES[1], kind="call")
    npv = call.npv(market)
    print(f"call npv          {npv:.6f}")
    call npv          14.412183

    Check it worked

    • The call prices to a value above zero and below the spot.
    • Equity spots and vols, the reference for spots and surfaces.
    • Books carry their market, for pricing a book on it.

    From the 0.0 line at revision bf7f2e2. Every printed number is that revision's own output.