How Barrier Options Handle Knock-In and Knock-Out Events in optionstratlib's pricing/barrier.rs

The barrier_black_scholes function in src/pricing/barrier.rs implements knock-in and knock-out events through analytical Black-Scholes formulas that use direction signs (_phi for call/put, _eta for barrier direction) and helper closures to calculate activation or deactivation prices based on the underlying asset's interaction with the barrier level.

The optionstratlib repository provides a comprehensive Rust implementation of exotic option pricing, including sophisticated barrier option mechanics. Understanding how barrier options handle knock-in and knock-out events requires examining the analytical engine in src/pricing/barrier.rs, which translates market events into mathematical formulas using the Black-Scholes framework with barrier adjustments.

Understanding Barrier Option Events in optionstratlib

The Four Classic Barrier Types

Barrier options in optionstratlib model four distinct event types that determine when the contract becomes active or void. Down-And-Out and Up-And-Out represent knock-out events where the option expires worthless if the underlying breaches the barrier. Conversely, Down-And-In and Up-And-In represent knock-in events where the option only activates upon barrier breach.

Extracting Barrier Parameters from the Option Contract

The implementation begins by unpacking the OptionType::Barrier variant to extract the specific event parameters. According to lines 18-27 in src/pricing/barrier.rs, the function retrieves the barrier_type, barrier_level, and optional rebate amount. If the provided option is not a barrier type, the function returns a PricingError immediately (lines 28-33), ensuring type safety before mathematical calculations begin.

Mathematical Implementation of Knock-In and Knock-Out Logic

Common Parameters and Early Exit Conditions

Before processing specific barrier events, the function converts market data to Decimal types for precision (lines 36-42). The parameters include spot price (s), strike (k), risk-free rate (r), dividend yield (q), volatility (sigma), and time-to-expiry (t). Early-exit checks handle edge cases where t equals zero or sigma equals zero (lines 43-53), returning intrinsic values or zero to avoid unnecessary computation.

Cost-of-Carry and Derived Constants

The implementation calculates the cost-of-carry b = r - q at line 55, then derives three critical constants reused across all barrier types (lines 57-61):

  • mu – the drift adjustment factor
  • lambda – the exponent used in rebate calculations
  • sigma_sqrt_t – the volatility-time product for d1/d2 calculations

Direction Signs and Barrier Classification

Two sign variables control the mathematical direction of barrier events (lines 70-78):

  • _phi – Distinguishes call options (+1) from put options (-1)
  • _eta – Captures the barrier direction: +1 for Down types (Down-And-In, Down-And-Out) and -1 for Up types (Up-And-In, Up-And-Out)

These signs are multiplied inside helper closures to flip arguments dynamically based on the specific barrier event being priced.

Helper Functions for Analytical Components

The implementation defines six closures (f_a through f_f) that construct the analytical Black-Scholes formulas with barrier adjustments (lines 80-130):

  • f_a and f_b – Calculate vanilla-like call and put components using standard d1/d2 calculations (lines 80-90).
  • f_c and f_d – Implement the "mirror" factor h_s_ratio (barrier/spot ratio) that adjusts for knock-out and knock-in events (lines 92-110).
  • f_e – Calculates the rebate value when the barrier is breached during knock-out events (lines 112-120).
  • f_f – Calculates the rebate value when the barrier is never breached during knock-in events, using the lambda exponent (lines 122-130).

Event-Specific Pricing Logic

Knock-Out Event Calculation

For knock-out barrier options (Down-And-Out and Up-And-Out), the pricing logic follows a subtractive pattern (lines 35-41). The function begins with the vanilla option value (f_a for calls, f_b for puts), then subtracts the barrier-adjusted term (f_c or f_d) that accounts for the probability of barrier breach. If a rebate is specified, the function adds f_e to compensate for the knock-out event.

Knock-In Event Calculation

Knock-in options (Down-And-In and Up-And-In) use activation logic that depends on the relationship between strike and barrier levels (lines 42-50). When the strike price lies above the barrier, the implementation returns the sum of the barrier term (f_c or f_d) and the rebate term f_f. For other strike-barrier relationships, the function composes a mix of vanilla and barrier terms to capture the conditional activation payoff.

Up Barrier Handling

The Up barrier family (Up-And-In and Up-And-Out) mirrors the Down barrier logic with _eta = -1 (lines 52-66). This sign inversion flips the barrier direction in the helper function calculations, ensuring that the "mirror" factor h_s_ratio and the probability calculations correctly model upward barrier breaches while maintaining the same mathematical structure as downward barriers.

Rebate Handling and In-Out Parity

Optional Rebate Calculations

The implementation supports optional rebates that pay out when barrier events occur. For knock-out options, f_e calculates the immediate rebate value when the barrier is breached (lines 112-120). For knock-in options, f_f calculates the rebate paid when the barrier is never breached, using the lambda exponent derived from volatility and cost-of-carry (lines 122-130). When no rebate is specified, these functions return zero, allowing the pricing to proceed without rebate adjustments.

Validating Event Logic Through Parity Tests

The test suite in src/pricing/barrier.rs verifies the correctness of knock-in and knock-out event handling through in-out parity validation (lines 64-84). The test_in_out_parity test confirms that the sum of a knock-in option price and its corresponding knock-out option price equals the vanilla Black-Scholes price. This mathematical relationship ensures that the barrier event logic correctly partitions the probability space between activation and deactivation scenarios.

Practical Code Examples

The following example demonstrates how to construct and price a knock-out barrier option using the barrier_black_scholes function:

use optionstratlib::{Options, pricing::barrier::barrier_black_scholes};
use optionstratlib::model::types::{BarrierType, OptionStyle, OptionType, Side};
use rust_decimal_macros::dec;

// Create a down-and-out call (knock-out when S ≤ 95)
let out_option = Options {
    option_type: OptionType::Barrier {
        barrier_type: BarrierType::DownAndOut,
        barrier_level: 95.0,
        rebate: Some(2.0),               // optional rebate
    },
    side: Side::Long,
    underlying_symbol: "TEST".into(),
    strike_price: pos_or_panic!(100.0),
    expiration_date: ExpirationDate::Days(pos_or_panic!(182.5)),
    implied_volatility: pos_or_panic!(0.25),
    quantity: pos_or_panic!(1.0),
    underlying_price: pos_or_panic!(100.0),
    risk_free_rate: dec!(0.08),
    option_style: OptionStyle::Call,
    dividend_yield: pos_or_panic!(0.04),
    exotic_params: None,
};

let price = barrier_black_scholes(&out_option)?;
println!("Knock-out call price = {}", price);

To demonstrate the knock-in counterpart and verify in-out parity:

// Knock-in counterpart (activates only if barrier is breached)
let in_option = Options {
    option_type: OptionType::Barrier {
        barrier_type: BarrierType::DownAndIn,
        barrier_level: 95.0,
        rebate: None,                     // no rebate
    },
    ..out_option.clone()
};

let in_price = barrier_black_scholes(&in_option)?;
println!("Knock-in call price = {}", in_price);

// Verify in-out parity (should equal vanilla BS price)
let vanilla = {
    let mut v = out_option.clone();
    v.option_type = OptionType::European;
    v
};
let vanilla_price = crate::pricing::black_scholes_model::black_scholes(&vanilla)?;
assert!((price + in_price - vanilla_price).abs() < dec!(0.001));

Summary

  • Barrier event modeling in src/pricing/barrier.rs uses analytical Black-Scholes formulas extended with barrier adjustment terms to calculate knock-in activation and knock-out deactivation prices.
  • Direction signs (_phi for call/put, _eta for up/down barrier direction) dynamically configure the mathematical formulas to handle all four barrier types (Down-And-In, Down-And-Out, Up-And-In, Up-And-Out).
  • Helper closures (f_a through f_f) encapsulate the vanilla option components, mirror factors for barrier adjustments, and rebate calculations, enabling composable pricing logic for complex barrier scenarios.
  • In-out parity validation confirms that the sum of knock-in and knock-out prices equals the vanilla Black-Scholes price, ensuring mathematically consistent event handling.

Frequently Asked Questions

How does the barrier pricing algorithm distinguish between knock-in and knock-out events?

The algorithm uses the _eta sign variable to identify barrier direction and pattern matching on the BarrierType enum to select the appropriate formula structure. For knock-out events (DownAndOut, UpAndOut), the function subtracts the barrier adjustment term from the vanilla price and adds any rebate via the f_e helper (lines 35-41). For knock-in events (DownAndIn, UpAndIn), the function returns either the barrier-only term plus rebate via f_f or a composition of vanilla and barrier terms depending on the strike-barrier relationship (lines 42-50).

What role do the helper closures f_c and f_d play in barrier option pricing?

The f_c and f_d closures implement the "mirror" factor calculations that adjust the standard Black-Scholes formula for barrier events. These helpers compute terms involving the h_s_ratio (barrier level divided by spot price) raised to powers derived from the mu and lambda constants, effectively modeling the probability of the underlying asset hitting the barrier. For knock-out options, these terms are subtracted from the vanilla price; for knock-in options, they represent the primary value component when the strike lies above the barrier.

How does the implementation handle rebates for barrier options?

The code supports optional rebates through two specialized helper closures. The f_e closure calculates the rebate value for knock-out options when the barrier is breached, incorporating the barrier level, risk-free rate, and time to expiry (lines 112-120). The f_f closure calculates the rebate for knock-in options when the barrier is never breached, using the lambda exponent derived from volatility and cost-of-carry parameters (lines 122-130). When no rebate is specified in the OptionType::Barrier construction, these functions return zero, allowing the pricing to proceed without rebate adjustments.

What validation ensures the knock-in and knock-out logic is mathematically correct?

The implementation validates barrier event logic through in-out parity tests located in the test suite of src/pricing/barrier.rs (lines 64-84). These tests verify that the sum of a knock-in option price and its corresponding knock-out option price equals the vanilla Black-Scholes price for the same underlying parameters. This mathematical relationship ensures that the barrier event handling correctly partitions the probability space between activation (knock-in) and deactivation (knock-out) scenarios without overlap or omission.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →