1919
2020
2121def test_long_call_butterfly_raw (multi_strike_data ):
22- """Test long call butterfly returns correct structure and leg types ."""
22+ """Test long call butterfly returns correct structure and calculated values ."""
2323 results = long_call_butterfly (multi_strike_data , raw = True )
2424 assert list (results .columns ) == triple_strike_internal_cols
2525 # All legs should be calls
@@ -29,6 +29,17 @@ def test_long_call_butterfly_raw(multi_strike_data):
2929 # Strikes should be in ascending order with equal width
3030 assert results .iloc [0 ]["strike_leg1" ] < results .iloc [0 ]["strike_leg2" ]
3131 assert results .iloc [0 ]["strike_leg2" ] < results .iloc [0 ]["strike_leg3" ]
32+ # Check calculated values for butterfly at strikes 210, 212.5, 215
33+ # Entry: long 210 call (4.95) + short 2x 212.5 calls (-6.10) + long 215 call (1.55) = 0.40
34+ # Exit: 5.00 + (-5.00) + 0.05 = 0.05
35+ row = results [
36+ (results ["strike_leg1" ] == 210.0 )
37+ & (results ["strike_leg2" ] == 212.5 )
38+ & (results ["strike_leg3" ] == 215.0 )
39+ ].iloc [0 ]
40+ assert round (row ["total_entry_cost" ], 2 ) == 0.40
41+ assert round (row ["total_exit_proceeds" ], 2 ) == 0.05
42+ assert round (row ["pct_change" ], 2 ) == - 0.88
3243
3344
3445def test_long_call_butterfly (multi_strike_data ):
@@ -47,13 +58,25 @@ def test_short_call_butterfly_raw(multi_strike_data):
4758
4859
4960def test_long_put_butterfly_raw (multi_strike_data ):
50- """Test long put butterfly returns correct structure and leg types ."""
61+ """Test long put butterfly returns correct structure and calculated values ."""
5162 results = long_put_butterfly (multi_strike_data , raw = True )
5263 assert list (results .columns ) == triple_strike_internal_cols
5364 # All legs should be puts
5465 assert results .iloc [0 ]["option_type_leg1" ] == "put"
5566 assert results .iloc [0 ]["option_type_leg2" ] == "put"
5667 assert results .iloc [0 ]["option_type_leg3" ] == "put"
68+ # Check calculated values for butterfly at strikes 210, 212.5, 215
69+ # All puts expired worthless since underlying at 215
70+ row = results [
71+ (results ["strike_leg1" ] == 210.0 )
72+ & (results ["strike_leg2" ] == 212.5 )
73+ & (results ["strike_leg3" ] == 215.0 )
74+ ].iloc [0 ]
75+ # Entry: long 210 put (1.45) + short 2x 212.5 puts (-6.10) + long 215 put (5.05) = 0.40
76+ assert round (row ["total_entry_cost" ], 2 ) == 0.40
77+ # Exit: all puts worthless = 0.025 + (-0.05) + 0.025 = 0.0
78+ assert round (row ["total_exit_proceeds" ], 2 ) == 0.0
79+ assert round (row ["pct_change" ], 2 ) == - 1.0
5780
5881
5982def test_long_put_butterfly (multi_strike_data ):
@@ -77,7 +100,7 @@ def test_short_put_butterfly_raw(multi_strike_data):
77100
78101
79102def test_iron_condor_raw (multi_strike_data ):
80- """Test iron condor returns correct structure and leg types ."""
103+ """Test iron condor returns correct structure and calculated values ."""
81104 results = iron_condor (multi_strike_data , raw = True )
82105 assert list (results .columns ) == quadruple_strike_internal_cols
83106 # Leg 1 and 2 should be puts, leg 3 and 4 should be calls
@@ -89,6 +112,19 @@ def test_iron_condor_raw(multi_strike_data):
89112 assert results .iloc [0 ]["strike_leg1" ] < results .iloc [0 ]["strike_leg2" ]
90113 assert results .iloc [0 ]["strike_leg2" ] < results .iloc [0 ]["strike_leg3" ]
91114 assert results .iloc [0 ]["strike_leg3" ] < results .iloc [0 ]["strike_leg4" ]
115+ # Check calculated values for iron condor at strikes 207.5, 210, 215, 217.5
116+ # Underlying moved from 212.5 to 215, staying within the condor range
117+ row = results [
118+ (results ["strike_leg1" ] == 207.5 )
119+ & (results ["strike_leg2" ] == 210.0 )
120+ & (results ["strike_leg3" ] == 215.0 )
121+ & (results ["strike_leg4" ] == 217.5 )
122+ ].iloc [0 ]
123+ # Net credit received at entry (negative cost = credit)
124+ assert round (row ["total_entry_cost" ], 2 ) == - 1.90
125+ # Nearly all options expired worthless, kept most of premium
126+ assert round (row ["total_exit_proceeds" ], 3 ) == - 0.025
127+ assert round (row ["pct_change" ], 2 ) == 0.99
92128
93129
94130def test_iron_condor (multi_strike_data ):
@@ -113,7 +149,7 @@ def test_reverse_iron_condor_raw(multi_strike_data):
113149
114150
115151def test_iron_butterfly_raw (multi_strike_data ):
116- """Test iron butterfly returns correct structure and leg types ."""
152+ """Test iron butterfly returns correct structure and calculated values ."""
117153 results = iron_butterfly (multi_strike_data , raw = True )
118154 assert list (results .columns ) == quadruple_strike_internal_cols
119155 # Leg 1 and 2 should be puts, leg 3 and 4 should be calls
@@ -123,6 +159,19 @@ def test_iron_butterfly_raw(multi_strike_data):
123159 assert results .iloc [0 ]["option_type_leg4" ] == "call"
124160 # Middle legs should share the same strike
125161 assert results .iloc [0 ]["strike_leg2" ] == results .iloc [0 ]["strike_leg3" ]
162+ # Check calculated values for iron butterfly at strikes 207.5, 212.5, 212.5, 217.5
163+ # Middle strike at 212.5 (ATM), wings at 207.5 and 217.5
164+ row = results [
165+ (results ["strike_leg1" ] == 207.5 )
166+ & (results ["strike_leg2" ] == 212.5 )
167+ & (results ["strike_leg3" ] == 212.5 )
168+ & (results ["strike_leg4" ] == 217.5 )
169+ ].iloc [0 ]
170+ # Net credit received at entry
171+ assert round (row ["total_entry_cost" ], 2 ) == - 5.00
172+ # Underlying moved to 215, short straddle lost value
173+ assert round (row ["total_exit_proceeds" ], 3 ) == - 2.475
174+ assert round (row ["pct_change" ], 2 ) == 0.50
126175
127176
128177def test_iron_butterfly (multi_strike_data ):
@@ -149,12 +198,22 @@ def test_reverse_iron_butterfly_raw(multi_strike_data):
149198
150199
151200def test_covered_call_raw (multi_strike_data ):
152- """Test covered call returns correct structure."""
201+ """Test covered call returns correct structure and calculated values ."""
153202 results = covered_call (multi_strike_data , raw = True )
154203 assert list (results .columns ) == double_strike_internal_cols
155204 # Both legs should be calls
156205 assert results .iloc [0 ]["option_type_leg1" ] == "call"
157206 assert results .iloc [0 ]["option_type_leg2" ] == "call"
207+ # Check calculated values for covered call at strikes 212.5, 215
208+ # Long deep ITM call (synthetic stock) + short OTM call
209+ row = results [
210+ (results ["strike_leg1" ] == 212.5 ) & (results ["strike_leg2" ] == 215.0 )
211+ ].iloc [0 ]
212+ # Entry: long 212.5 call (3.05) + short 215 call (-1.55) = 1.50
213+ assert round (row ["total_entry_cost" ], 2 ) == 1.50
214+ # Exit: long call worth 2.50 + short call expired worthless (-0.05) = 2.45
215+ assert round (row ["total_exit_proceeds" ], 2 ) == 2.45
216+ assert round (row ["pct_change" ], 2 ) == 0.63
158217
159218
160219def test_covered_call (multi_strike_data ):
@@ -164,12 +223,24 @@ def test_covered_call(multi_strike_data):
164223
165224
166225def test_protective_put_raw (multi_strike_data ):
167- """Test protective put returns correct structure."""
226+ """Test protective put returns correct structure and calculated values ."""
168227 results = protective_put (multi_strike_data , raw = True )
169228 assert list (results .columns ) == double_strike_internal_cols
170229 # Leg 1 should be call (synthetic stock), leg 2 should be put
171230 assert results .iloc [0 ]["option_type_leg1" ] == "call"
172231 assert results .iloc [0 ]["option_type_leg2" ] == "put"
232+ # Check calculated values for protective put at strikes 207.5, 210
233+ # Long call (synthetic stock) + long put for protection
234+ # Note: strike_leg1 < strike_leg2 due to non-overlapping rule
235+ row = results [
236+ (results ["strike_leg1" ] == 207.5 ) & (results ["strike_leg2" ] == 210.0 )
237+ ].iloc [0 ]
238+ # Entry: long 207.5 call (6.95) + long 210 put (1.45) = 8.40
239+ assert round (row ["total_entry_cost" ], 2 ) == 8.40
240+ # Exit: call worth 7.50 + put expired worthless (0.025) = 7.525
241+ assert round (row ["total_exit_proceeds" ], 3 ) == 7.525
242+ # Small loss due to time decay
243+ assert round (row ["pct_change" ], 2 ) == - 0.10
173244
174245
175246def test_protective_put (multi_strike_data ):
0 commit comments