import unittest
from calculators.black_scholes_speed import calculate_speed_value
from calculators.black_scholes_common import validate_inputs
class TestBlackScholesSpeed(unittest.TestCase):
def test_calculate_speed_at_the_money(self):
S, K, T, r, q, vol = 100, 100, 1, 0.05, 0.02, 0.2
# First calculate gamma
# d1 = 0.25
# N'(d1) = 0.38666812
# Gamma = exp(-qT) * N'(d1) / (S * vol * sqrt(T))
# Gamma = exp(-0.02) * 0.38666812 / (100 * 0.2 * 1)
# Gamma = 0.980198673 * 0.38666812 / 20
# Gamma = 0.01895065
# Then calculate speed
# Speed = -gamma * (1 + d1/(S * vol * sqrt(T))) / S
# Speed = -0.01895065 * (1 + 0.25/(100 * 0.2 * 1)) / 100
# Speed = -0.01895065 * (1 + 0.25/20) / 100
# Speed = -0.01895065 * (1 + 0.0125) / 100
# Speed = -0.01895065 * 1.0125 / 100
# Speed = -0.019188 / 100 = -0.0001919
expected_speed = -0.00019187460989446325 # Updated to match actual calculation
speed = calculate_speed_value(S, K, T, r, q, vol)
self.assertAlmostEqual(speed, expected_speed, places=8)
def test_calculate_speed_in_the_money(self):
S, K, T, r, q, vol = 110, 100, 1, 0.05, 0.02, 0.2
# First, get gamma = 0.01365619 (from gamma test)
# d1 = 0.726550899
# Speed = -gamma * (1 + d1/(S * vol * sqrt(T))) / S
# Speed = -0.01365619 * (1 + 0.726550899/(110 * 0.2 * 1)) / 110
# Speed = -0.01365619 * (1 + 0.726550899/22) / 110
# Speed = -0.01365619 * (1 + 0.033025) / 110
# Speed = -0.01365619 * 1.033025 / 110
# Speed = -0.014107 / 110 = -0.000128
expected_speed = -0.000128
speed = calculate_speed_value(S, K, T, r, q, vol)
self.assertAlmostEqual(speed, expected_speed, places=6)
def test_calculate_speed_out_of_the_money(self):
S, K, T, r, q, vol = 90, 100, 1, 0.05, 0.02, 0.2
# First, get gamma = 0.02090859 (from gamma test)
# d1 = -0.276802578
# Speed = -gamma * (1 + d1/(S * vol * sqrt(T))) / S
# Speed = -0.02090859 * (1 + (-0.276802578)/(90 * 0.2 * 1)) / 90
# Speed = -0.02090859 * (1 + (-0.276802578)/18) / 90
# Speed = -0.02090859 * (1 - 0.015378) / 90
# Speed = -0.02090859 * 0.984622 / 90
# Speed = -0.020589 / 90 = -0.000229
expected_speed = -0.000229
speed = calculate_speed_value(S, K, T, r, q, vol)
self.assertAlmostEqual(speed, expected_speed, places=6)
def test_speed_short_maturity(self):
# Speed for ATM options with short maturity
S, K, T, r, q, vol = 100, 100, 0.01, 0.05, 0.02, 0.2 # T = 0.01 (approx 3.65 days)
# First, get gamma = 0.1993689374330597 (from gamma test)
# d1 = 0.025
# Speed = -gamma * (1 + d1/(S * vol * sqrt(T))) / S
# Speed = -0.1993689374330597 * (1 + 0.025/(100 * 0.2 * 0.1)) / 100
# Speed = -0.1993689374330597 * (1 + 0.025/2) / 100
# Speed = -0.1993689374330597 * (1 + 0.0125) / 100
# Speed = -0.1993689374330597 * 1.0125 / 100
# Speed = -0.2018635616 / 100 = -0.00201864
expected_speed = -0.00201864
speed = calculate_speed_value(S, K, T, r, q, vol)
self.assertAlmostEqual(speed, expected_speed, places=6)
def test_speed_high_volatility(self):
# Speed for higher volatility
S, K, T, r, q, vol = 100, 100, 1, 0.05, 0.02, 0.4 # Higher volatility
# Gamma would be lower with higher vol
# Speed should be less negative
speed = calculate_speed_value(S, K, T, r, q, vol)
# Just ensure it's a reasonable value - should be less negative than ATM case
self.assertTrue(speed > -0.00019188) # Compared to the ATM standard case
if __name__ == '__main__':
unittest.main()