← Back to documentation

Recipes

Practical examples showing how to combine floe functions for real-world use cases.

Calculate Dealer Exposures Using Smoothed IV

import {
  getIVSurfaces,
  calculateGammaVannaCharmExposures,
  OptionChain,
} from "@fullstackcraftllc/floe";

// Assume we have a large array of all options across all expiries for a given symbol
// As well as the spot price, risk-free rate, and dividend yield
// This would typically come from your broker API or market data provider
const spot = 450.50; // Current underlying price
const riskFreeRate = 0.05;   // as decimal (5%)
const dividendYield = 0.02;  // as decimal (2%)
const options = [...]; // array of NormalizedOption

// Bundle everything into an OptionChain
const chain: OptionChain = {
  symbol: 'SPY',
  spot,
  riskFreeRate,
  dividendYield,
  options
};

// Build IV surfaces with smoothing applied
const ivSurfaces = getIVSurfaces('blackscholes', 'totalvariance', chain);

// Calculate dealer gamma, vanna, and charm exposures
const exposures = calculateGammaVannaCharmExposures(chain, ivSurfaces);

// Each expiration now has aggregated exposure metrics
for (const expiry of exposures) {
  console.log(`Expiration: ${new Date(expiry.expiration).toDateString()}`);
  console.log(`  Total Gamma: ${expiry.totalGammaExposure.toLocaleString()}`);
  console.log(`  Total Vanna: ${expiry.totalVannaExposure.toLocaleString()}`);
  console.log(`  Total Charm: ${expiry.totalCharmExposure.toLocaleString()}`);
  console.log(`  Max Gamma Strike: ${expiry.strikeOfMaxGamma}`);
}

Calculate Greeks Based on Market IV

import {
  calculateGreeks,
  calculateImpliedVolatility,
  getTimeToExpirationInYears,
} from "@fullstackcraftllc/floe";

// Market data for an option
const optionData = {
  optionType: 'call' as const,
  strike: 105,
  expirationTimestamp: 1711929600000,  // example expiration date
  marketPrice: 2.50,  // observed market price of the option
};

const spot = 100;
const riskFreeRate = 0.05;   // as decimal (5%)
const dividendYield = 0.02;  // as decimal (2%)

// Calculate time to expiration
const timeToExpiry = getTimeToExpirationInYears(optionData.expirationTimestamp);

// First, calculate the IV from the market price
// calculateImpliedVolatility returns IV as a percentage (e.g., 20.0 for 20%)
const ivPercent = calculateImpliedVolatility(
  optionData.marketPrice,  // price
  spot,                     // spot
  optionData.strike,        // strike
  riskFreeRate,             // riskFreeRate
  dividendYield,            // dividendYield
  timeToExpiry,             // timeToExpiry
  optionData.optionType     // optionType
);

console.log(`Implied Volatility: ${ivPercent.toFixed(2)}%`);

// Then use that IV to calculate the Greeks
// Note: calculateGreeks expects volatility as a decimal (0.20 for 20%)
const greeks = calculateGreeks({
  spot,
  strike: optionData.strike,
  timeToExpiry,
  riskFreeRate,
  volatility: ivPercent / 100,  // Convert percentage to decimal
  optionType: optionData.optionType,
  dividendYield,
});

console.log(`Theoretical Price: $${greeks.price.toFixed(2)}`);
console.log(`Delta: ${greeks.delta.toFixed(4)}`);
console.log(`Gamma: ${greeks.gamma.toFixed(6)}`);
console.log(`Theta: ${greeks.theta.toFixed(4)} per day`);
console.log(`Vega: ${greeks.vega.toFixed(4)} per 1% vol`);

Build a Complete Option Chain Analysis

import {
  blackScholes,
  calculateGreeks,
  calculateImpliedVolatility,
  getTimeToExpirationInYears,
  NormalizedOption,
  OptionChain,
} from "@fullstackcraftllc/floe";

// Simulated market data
const spot = 100;
const riskFreeRate = 0.05;
const dividendYield = 0.01;
const expirationTimestamp = Date.now() + 30 * 24 * 60 * 60 * 1000; // 30 days out
const timeToExpiry = getTimeToExpirationInYears(expirationTimestamp);

// Create a simple option chain
const strikes = [95, 97.5, 100, 102.5, 105];
const marketVols = [0.22, 0.20, 0.18, 0.20, 0.22]; // Volatility smile

const analysis = strikes.map((strike, i) => {
  const vol = marketVols[i];
  
  // Calculate theoretical prices
  const callPrice = blackScholes({
    spot,
    strike,
    timeToExpiry,
    riskFreeRate,
    volatility: vol,
    optionType: 'call',
    dividendYield,
  });
  
  const putPrice = blackScholes({
    spot,
    strike,
    timeToExpiry,
    riskFreeRate,
    volatility: vol,
    optionType: 'put',
    dividendYield,
  });
  
  // Calculate Greeks
  const callGreeks = calculateGreeks({
    spot,
    strike,
    timeToExpiry,
    riskFreeRate,
    volatility: vol,
    optionType: 'call',
    dividendYield,
  });
  
  const putGreeks = calculateGreeks({
    spot,
    strike,
    timeToExpiry,
    riskFreeRate,
    volatility: vol,
    optionType: 'put',
    dividendYield,
  });
  
  return {
    strike,
    vol: `${(vol * 100).toFixed(1)}%`,
    callPrice: callPrice.toFixed(2),
    putPrice: putPrice.toFixed(2),
    callDelta: callGreeks.delta.toFixed(3),
    putDelta: putGreeks.delta.toFixed(3),
    gamma: callGreeks.gamma.toFixed(4),
  };
});

console.table(analysis);

Price Options Across Multiple Expirations

import {
  blackScholes,
  calculateGreeks,
} from "@fullstackcraftllc/floe";

const spot = 100;
const strike = 100;  // ATM
const riskFreeRate = 0.05;
const volatility = 0.20;

// Different expiration periods in years
const expirations = [
  { label: '1 week', years: 7 / 365 },
  { label: '1 month', years: 30 / 365 },
  { label: '3 months', years: 90 / 365 },
  { label: '6 months', years: 180 / 365 },
  { label: '1 year', years: 1 },
];

console.log('ATM Option Analysis by Expiration');
console.log('='.repeat(70));

for (const exp of expirations) {
  const callPrice = blackScholes({
    spot,
    strike,
    timeToExpiry: exp.years,
    riskFreeRate,
    volatility,
    optionType: 'call',
  });
  
  const greeks = calculateGreeks({
    spot,
    strike,
    timeToExpiry: exp.years,
    riskFreeRate,
    volatility,
    optionType: 'call',
  });
  
  console.log(`\n${exp.label}:`);
  console.log(`  Call Price: $${callPrice.toFixed(2)}`);
  console.log(`  Delta: ${greeks.delta.toFixed(3)}`);
  console.log(`  Gamma: ${greeks.gamma.toFixed(4)}`);
  console.log(`  Theta: $${greeks.theta.toFixed(3)} per day`);
  console.log(`  Vega: $${greeks.vega.toFixed(3)} per 1% vol`);
}

Reverse Engineer Strike from Target Delta

import { calculateGreeks } from "@fullstackcraftllc/floe";

// Find a strike with approximately the target delta
function findStrikeForDelta(
  targetDelta: number,
  spot: number,
  timeToExpiry: number,
  volatility: number,
  riskFreeRate: number,
  optionType: 'call' | 'put'
): number {
  // Binary search for the strike
  let low = spot * 0.5;
  let high = spot * 1.5;
  
  for (let i = 0; i < 50; i++) {
    const mid = (low + high) / 2;
    
    const greeks = calculateGreeks({
      spot,
      strike: mid,
      timeToExpiry,
      riskFreeRate,
      volatility,
      optionType,
    });
    
    const delta = Math.abs(greeks.delta);
    
    if (Math.abs(delta - targetDelta) < 0.001) {
      return mid;
    }
    
    if (optionType === 'call') {
      // Higher strike = lower delta for calls
      if (delta > targetDelta) {
        low = mid;
      } else {
        high = mid;
      }
    } else {
      // Higher strike = higher |delta| for puts
      if (delta < targetDelta) {
        low = mid;
      } else {
        high = mid;
      }
    }
  }
  
  return (low + high) / 2;
}

// Example: Find the 25-delta call and put
const spot = 100;
const timeToExpiry = 30 / 365;
const volatility = 0.20;
const riskFreeRate = 0.05;

const call25Strike = findStrikeForDelta(0.25, spot, timeToExpiry, volatility, riskFreeRate, 'call');
const put25Strike = findStrikeForDelta(0.25, spot, timeToExpiry, volatility, riskFreeRate, 'put');

console.log(`25-Delta Call Strike: $${call25Strike.toFixed(2)}`);
console.log(`25-Delta Put Strike: $${put25Strike.toFixed(2)}`);
console.log(`Risk Reversal Width: $${(call25Strike - put25Strike).toFixed(2)}`);