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

> Discover how optionstratlib's barrier.rs handles knock-in and knock-out events using analytical Black-Scholes formulas with direction signs and helper closures.

- Repository: [Joaquin Bejar Garcia/optionstratlib](https://github.com/joaquinbejar/optionstratlib)
- Tags: deep-dive
- Published: 2026-03-04

---

**The `barrier_black_scholes` function in [`src/pricing/barrier.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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:

```rust
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:

```rust
// 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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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.