def test_increment(self): self.assertEqual(Day(2000, 1, 1) + 1, Day(2000, 1, 2)) self.assertEqual(Day(2000, 2, 28) + 2, Day(2000, 3, 1)) self.assertEqual(Day(2000, 2, 28) + timedelta(2), Day(2000, 3, 1)) self.assertEqual(Day(2000, 2, 28) - 2, Day(2000, 2, 26)) self.assertEqual(Day(2000, 2, 28) - 0, Day(2000, 2, 28))
def test_deep_itm_american_put_worth_intrinsic(self): F = 100.0 K = 150.0 sigma = 0.05 market_day = Day(2018, 1, 1) r = 0.2 option = OptionInstrument(K, OptionRight.PUT, Day(2018, 6, 1), ExerciseStyle.AMERICAN) european_value = option.european_value(market_day, F, sigma, r) intrinsic = option.intrinsic(F) cn_value = option.cn_value(market_day, F, sigma, r) self.assertAlmostEqual(cn_value, intrinsic, delta=0.01) self.assertLess(european_value, intrinsic)
def __init__(self, start_day, end_day): if start_day is None or end_day is None: raise TypeError("Cannot create Days Object from value None") logger.debug("creating days from " + str(start_day) + " and " + str(end_day)) if isinstance(start_day, DaysEnum): self.start_day = Day(start_day) if isinstance(end_day, DaysEnum): self.end_day = Day(end_day) self.start_day = start_day self.end_day = end_day
def __init__(self, a_CasesPerDay): # We need to create a day object for every # entry in our a_CasesPerDay self.d_CaseHistory = {} # We also need to closely monitor the active cases, individually self.d_ActiveCases = {} # We will store these cases in the dictionary above # This way we can access a day's historys by Province.d_CaseHistory[day-1] print(f"Day # \t\tNew Cases\t\tActive Cases\t\tOperation Zone") print("--------------------- Confirmed Govt Data -------------------") for self.i_Cursor in range(0, len(a_CasesPerDay)): # The day will inherit a lot from the province o_Day = Day(i_DayNumber=self.i_Cursor, i_NewCases=a_CasesPerDay[self.i_Cursor], d_ActiveCases=self.d_ActiveCases, d_PreviousData=self.d_CaseHistory) self.d_ActiveCases = o_Day.d_ActiveCases self.d_CaseHistory[f"day-{self.i_Cursor}"] = o_Day print(self.d_CaseHistory[f"day-{self.i_Cursor}"]) # End of interpolation ---------------------------------------------------------- # Mark when our confirmed data ends --------------------------------------------- self.i_InputSignalEndIdx = self.i_Cursor+1 print("--------------------- Extrapolated Data -------------------") for self.i_Cursor in range(self.i_InputSignalEndIdx, self.i_InputSignalEndIdx + 10): # Here we are predicting 10 days ahead o_Day = self.ProjectNextDay() self.d_CaseHistory[f"day-{self.i_Cursor}"] = o_Day print(self.d_CaseHistory[f"day-{self.i_Cursor}"])
def test_european_close_to_black_scholes(self): rng = PimpedRandom() for _ in range(10): seed = np.random.randint(0, 100 * 1000) rng.seed(seed) market_day = Day(2018, 1, 1) option = random_option(rng, ex_style=ExerciseStyle.EUROPEAN) sigma = rng.random() * 0.5 fwd_price = rng.uniform(option.strike - 1.0, option.strike + 1.0) r = 0.1 * rng.random() numeric_value = option.cn_value(market_day, fwd_price, sigma, r) def bs_value(s): return option.european_value(market_day, fwd_price, s, r) analytic_value = bs_value(sigma) tol = max( bs_value(sigma + 0.01) - analytic_value, 0.01, analytic_value * 0.01) self.assertAlmostEqual(numeric_value, analytic_value, delta=tol, msg=f"Seed was {seed}")
def random_option(rng: PimpedRandom, strike: float = None, right: OptionRight = None, expiry: Day = None, ex_style: ExerciseStyle = None): return OptionInstrument(strike or 80.0 + rng.random() * 20, right or rng.enum_choice(OptionRight), expiry or Day(2018, 1, 2) + rng.randint(1, 100), ex_style or rng.enum_choice(ExerciseStyle))
def test_intrinsic(self): rng = PimpedRandom() for _ in range(100): seed = np.random.randint(0, 100 * 1000) rng.seed(seed) option = random_option(rng, ex_style=ExerciseStyle.EUROPEAN) market_day = Day(2018, 1, 1) fwd_price = option.strike + rng.uniform(-2.0, 2.0) self.assertAlmostEqual(option.european_value(market_day, fwd_price, sigma=1e-5, r=0.0), option.intrinsic(fwd_price), delta=1e-3, msg=f"Seed was {seed}")
def __iter__(self): # if end_day is None: # return [start_day] week = list(DaysEnum) start_index = week.index(self.start_day) end_index = week.index(self.end_day) if end_index < start_index: # if the end day is sooner in the week than the start end_index += start_index days = [] for x in range(start_index, end_index+1): #ensure the indices wrap around to the beginning of the week day_index = x % 7 days.append(Day(week[day_index])) return iter(days)
def test_american_worth_at_least_intrinsic(self): rng = PimpedRandom() for _ in range(5): seed = np.random.randint(0, 100 * 1000) rng.seed(seed) market_day = Day(2018, 1, 1) option = random_option(rng, ex_style=ExerciseStyle.AMERICAN) fwd_price = rng.uniform(option.strike - 1.0, option.strike + 1.0) sigma = rng.random() * 0.5 r = 0.1 * rng.random() numeric_value = option.cn_value(market_day, fwd_price, sigma, r) intrinsic_value = option.intrinsic(fwd_price) self.assertGreaterEqual(numeric_value, intrinsic_value, msg=f"Seesd was {seed}")
def test_mc_value_close_to_bs(self): rng = PimpedRandom() for _ in range(5): seed = np.random.randint(0, 100 * 1000) rng.seed(seed) market_day = Day(2018, 1, 1) option = random_option(rng, ex_style=ExerciseStyle.EUROPEAN) fwd_price = rng.uniform(option.strike - 1.0, option.strike + 1.0) sigma = rng.random() * 0.5 r = 0.1 * rng.random() mc_value = option.mc_european_value(market_day, fwd_price, sigma, r) bs_value = option.european_value(market_day, fwd_price, sigma, r) self.assertAlmostEqual(mc_value, bs_value, delta=0.1, msg=f"Seesd was {seed}")
def test_time_since(self): d1 = Day(2001, 1, 1) d2 = d1 + 10 self.assertAlmostEqual(d2.time_since(d1), 10.0 / 365.25, 1e03)
def ProjectNextDay(self): i_ProjectedNewCases = self.ProjectNewCases() o_Day = Day(i_DayNumber=self.i_Cursor, i_NewCases=i_ProjectedNewCases, d_ActiveCases=self.d_ActiveCases, d_PreviousData=self.d_CaseHistory) return o_Day