From c481e2b7863c0e9e3fc3913df2b0da6ace161081 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Fri, 11 Mar 2022 09:40:37 +0530 Subject: [PATCH] New test using GBM generated series --- tests/test_fincal2.py | 95 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 tests/test_fincal2.py diff --git a/tests/test_fincal2.py b/tests/test_fincal2.py new file mode 100644 index 0000000..469022d --- /dev/null +++ b/tests/test_fincal2.py @@ -0,0 +1,95 @@ +import datetime +import math +import random + +import pytest +from fincal.exceptions import DateNotFoundError +from fincal.fincal import TimeSeries, create_date_series +from fincal.utils import FincalOptions + + +def create_prices(s0: float, mu: float, sigma: float, num_prices: int) -> list: + """Generates a price following a geometric brownian motion process based on the input of the arguments: + - s0: Asset inital price. + - mu: Interest rate expressed annual terms. + - sigma: Volatility expressed annual terms. + - seed: seed for the random number generator + - num_prices: number of prices to generate + """ + + random.seed(1234) # WARNING! Changing the seed will cause most tests to fail + all_values = [] + for _ in range(num_prices): + s0 *= math.exp( + (mu - 0.5 * sigma**2) * (1.0 / 365.0) + sigma * math.sqrt(1.0 / 365.0) * random.gauss(mu=0, sigma=1) + ) + all_values.append(round(s0, 2)) + + return all_values + + +def create_data(): + """Creates TimeSeries data""" + + dates = create_date_series("2017-01-01", "2020-10-31", "D", skip_weekends=True) + values = create_prices(1000, 0.1, 0.05, 1000) + ts = TimeSeries(dict(zip(dates, values)), frequency="D") + return ts + + +class TestReturns: + def test_returns_calc(self): + ts = create_data() + returns = ts.calculate_returns( + "2020-01-01", annual_compounded_returns=False, interval_type="years", interval_value=1 + ) + assert round(returns[1], 6) == 0.112913 + + returns = ts.calculate_returns( + "2020-04-01", annual_compounded_returns=False, interval_type="months", interval_value=3 + ) + assert round(returns[1], 6) == 0.015908 + + returns = ts.calculate_returns( + "2020-04-01", annual_compounded_returns=True, interval_type="months", interval_value=3 + ) + assert round(returns[1], 6) == 0.065167 + + returns = ts.calculate_returns( + "2020-04-01", annual_compounded_returns=False, interval_type="days", interval_value=90 + ) + assert round(returns[1], 6) == 0.017673 + + returns = ts.calculate_returns( + "2020-04-01", annual_compounded_returns=True, interval_type="days", interval_value=90 + ) + assert round(returns[1], 6) == 0.073632 + + with pytest.raises(DateNotFoundError): + ts.calculate_returns("2020-04-04", interval_type="days", interval_value=90, as_on_match="exact") + with pytest.raises(DateNotFoundError): + ts.calculate_returns("2020-04-04", interval_type="months", interval_value=3, prior_match="exact") + + def test_date_formats(self): + ts = create_data() + FincalOptions.date_format = "%d-%m-%Y" + with pytest.raises(ValueError): + ts.calculate_returns("2020-04-10", annual_compounded_returns=True, interval_type="days", interval_value=90) + + returns1 = ts.calculate_returns("2020-04-01", interval_type="days", interval_value=90, date_format="%Y-%m-%d") + returns2 = ts.calculate_returns("01-04-2020", interval_type="days", interval_value=90) + assert round(returns1[1], 6) == round(returns2[1], 6) == 0.073632 + + FincalOptions.date_format = "%m-%d-%Y" + with pytest.raises(ValueError): + ts.calculate_returns("2020-04-01", annual_compounded_returns=True, interval_type="days", interval_value=90) + + returns1 = ts.calculate_returns("2020-04-01", interval_type="days", interval_value=90, date_format="%Y-%m-%d") + returns2 = ts.calculate_returns("04-01-2020", interval_type="days", interval_value=90) + assert round(returns1[1], 6) == round(returns2[1], 6) == 0.073632 + + def test_limits(self): + ts = create_data() + FincalOptions.date_format = "%Y-%m-%d" + with pytest.raises(DateNotFoundError): + ts.calculate_returns("2020-11-25", interval_type="days", interval_value=90, closest_max_days=10)