core.test_strikes

Tests for strike generation functions.

Tests the pure functions in f.domains.hedge.core.strikes:

  • generate_strike_universe
  • build_strike_config
  • build_strikes_configuration

Each function has 3 tests covering different scenarios.

EXCEL VERIFICATION GUIDE

For a mathematician to verify these tests in Excel:

  1. Rounding Logic: We use FLOOR.MATH to round prices down to the nearest strike step (usually 100).

    • Formula: =FLOOR.MATH(Price, Step)
  2. Sequence Generation:

    • Start with StartStrike = FLOOR.MATH(P0, Step).
    • Subtract Step recursively until reaching EndStrike.
    • EndStrike = FLOOR.MATH(Pmin, Step) - (Extension * Step).
  3. Configuration Flags:

    • Enabled: Check if strike exists in a list (using MATCH or COUNTIF).
    • Is ATM: Check if strike equals StartStrike.
    • Is Pmin: Check if strike equals FLOOR.MATH(Pmin, Step).
def test_generate_strike_universe_standard():

Test: Standard strike universe generation.

NUMERICAL EXAMPLE

Input: P0 = 3050, Pmin = 2800 strike_step = 100, extension = 2

Calculation: first_strike = floor(3050 / 100) × 100 = 3000 pmin_rounded = floor(2800 / 100) × 100 = 2800 last_strike = 2800 - (2 × 100) = 2600

Strikes: 3000, 2900, 2800, 2700, 2600

Expected: 5 strikes in descending order

EXCEL REPRODUCTION

1. Inputs (Cells A1:B4)

Cell Parameter Value
B1 P0 3050
B2 Pmin 2800
B3 Step 100
B4 Ext 2

2. Calculations (Cells A5:B7)

Cell Name Formula Expectation
B5 First =FLOOR.MATH(B1, B3) 3000
B6 PminRnd =FLOOR.MATH(B2, B3) 2800
B7 Last =B6 - (B4 * B3) 2600

3. Strike List Generation (Column D)

Cell Formula (Drag Down) Result
D1 =B5 3000
D2 =IF(D1-B$3>=B$7, D1-B$3, "") 2900
D3 (drag down formula) 2800
D4 (drag down formula) 2700
D5 (drag down formula) 2600
def test_generate_strike_universe_edge_case():

Test: Edge case where P0 is exactly at a strike.

NUMERICAL EXAMPLE

Input: P0 = 3000 (exactly on strike), Pmin = 2900 strike_step = 100, extension = 1

Calculation: first_strike = floor(3000 / 100) × 100 = 3000 pmin_rounded = floor(2900 / 100) × 100 = 2900 last_strike = 2900 - (1 × 100) = 2800

Strikes: 3000, 2900, 2800

Expected: 3 strikes

def test_generate_strike_universe_large_range():

Test: Large range with many strikes.

NUMERICAL EXAMPLE

Input: P0 = 3050, Pmin = 2200 strike_step = 100, extension = 3

Calculation: first_strike = 3000 pmin_rounded = 2200 last_strike = 2200 - 300 = 1900

Strikes: 3000, 2900, 2800, ..., 2000, 1900 (12 strikes)

Expected: 12 strikes from 3000 to 1900

def test_build_strike_config_enabled():

Test: Build config for enabled strike.

NUMERICAL EXAMPLE

Input: strike = 3000 enabled_strikes = {3000, 2800} first_strike = 3000 pmin_rounded = 2200

Expected: enabled = True (3000 in set) is_atm = True (3000 == first_strike) is_pmin = False (3000 != 2200)

EXCEL REPRODUCTION

1. Inputs (Cells A1:B4)

Cell Parameter Value
B1 Strike 3000
B2 FirstStrike 3000
B3 PminRnd 2200

2. Enabled List (Cells D1:D2)

Cell Value
D1 3000
D2 2800

3. Logic Checks (Cells A5:B7)

Cell Check Formula Result
B5 Enabled =ISNUMBER(MATCH(B1,D1:D2,0)) TRUE
B6 Is ATM =B1=B2 TRUE
B7 Is Pmin =B1=B3 FALSE
def test_build_strike_config_disabled():

Test: Build config for disabled strike.

NUMERICAL EXAMPLE

Input: strike = 2900 enabled_strikes = {3000, 2800} first_strike = 3000 pmin_rounded = 2200

Expected: enabled = False (2900 not in set) is_atm = False (2900 != 3000) is_pmin = False (2900 != 2200)

def test_build_strike_config_pmin():

Test: Build config for strike at Pmin.

NUMERICAL EXAMPLE

Input: strike = 2200 enabled_strikes = {2200} first_strike = 3000 pmin_rounded = 2200

Expected: enabled = True (2200 in set) is_atm = False (2200 != 3000) is_pmin = True (2200 == 2200)

def test_build_strikes_configuration_full():

Test: Build complete strike configuration.

NUMERICAL EXAMPLE

Input: P0 = 3050, Pmin = 2800 enabled = {3000, 2800} strike_step = 100, extension = 1

Expected: 4 configs: 3000 (enabled, ATM), 2900 (disabled), 2800 (enabled, Pmin), 2700 (disabled)

EXCEL REPRODUCTION

Combine the previous techniques to build a full table.

1. Setup (A1:B4)

Cell Param Value
B1 P0 3050
B2 Pmin 2800
B3 Step 100
B4 Ext 1

2. Enabled List (G1:G2)

Cell Value
G1 3000
G2 2800

3. Reference Values (A5:B7)

Cell Name Formula Value
B5 First =FLOOR.MATH(B1, B3) 3000
B6 PminRnd =FLOOR.MATH(B2, B3) 2800
B7 Last =B6 - (B4 * B3) 2700

4. Configuration Table (D1:H6)

Row Strike (D) Enabled? (E) ATM? (F) Pmin? (G)
1 =B5 =ISNUMBER(MATCH(D1,G$1:G$2,0)) =D1=B$5 =D1=B$6
2 =IF(D1-B$3>=B$7, D1-B$3, "") =ISNUMBER(MATCH(D2,G$1:G$2,0)) =D2=B$5 =D2=B$6
3 ... ... ... ...
def test_build_strikes_configuration_empty_enabled():

Test: Configuration with no enabled strikes.

NUMERICAL EXAMPLE

Input: P0 = 3050, Pmin = 2900 enabled = {} (empty set) strike_step = 100, extension = 1

Expected: 3 configs, all with enabled = False

def test_build_strikes_configuration_custom_step():

Test: Configuration with custom strike step.

NUMERICAL EXAMPLE

Input: P0 = 3100, Pmin = 2700 enabled = {3000, 2500} strike_step = 250, extension = 1

Calculation: first_strike = floor(3100 / 250) × 250 = 3000 pmin_rounded = floor(2700 / 250) × 250 = 2500 last_strike = 2500 - 250 = 2250

Strikes: 3000, 2750, 2500, 2250 (4 strikes)

Expected: 4 configs with step of 250