Skip to content

Commit

Permalink
test: update tests for PortfolioDCF
Browse files Browse the repository at this point in the history
  • Loading branch information
chilango74 committed Oct 8, 2024
1 parent 070d892 commit 3cfb425
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 96 deletions.
92 changes: 57 additions & 35 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def _init_asset_list(request, portfolio_short_history, portfolio_dividends, asse
@pytest.fixture(scope="package")
def init_portfolio_values():
return dict(
assets=["RGBITR.INDX", "MCFTR.INDX"],
assets=["RGBITR.INDX", "MCFTR.INDX"], # index values are better as they are not changing (adjusted_close)
ccy="RUB",
first_date="2015-01",
last_date="2020-01",
Expand Down Expand Up @@ -153,40 +153,62 @@ def portfolio_dividends(init_portfolio_values):


# DCF Scenarios
# @pytest.fixture(scope="package")
# def portfolio_cashflows_inflation(init_portfolio_values):
# _portfolio_cashflows_inflation = deepcopy(init_portfolio_values)
# _portfolio_cashflows_inflation["cashflow"] = -100
# _portfolio_cashflows_inflation["initial_amount"] = 100_000
# return ok.Portfolio(**_portfolio_cashflows_inflation)
#
#
# @pytest.fixture(scope="package")
# def portfolio_cashflows_NO_inflation(init_portfolio_values):
# _portfolio_cashflows_NO_inflation = deepcopy(init_portfolio_values)
# _portfolio_cashflows_NO_inflation["cashflow"] = -100.0
# _portfolio_cashflows_NO_inflation["initial_amount"] = 100_000.0
# _portfolio_cashflows_NO_inflation["inflation"] = False
# _portfolio_cashflows_NO_inflation["discount_rate"] = 0.09
# return ok.Portfolio(**_portfolio_cashflows_NO_inflation)
#
#
# @pytest.fixture(scope="package")
# def portfolio_cashflows_NO_inflation_NO_discount_rate(init_portfolio_values):
# _portfolio_cashflows_NO_inflation_NO_discount_rate = deepcopy(init_portfolio_values)
# _portfolio_cashflows_NO_inflation_NO_discount_rate["cashflow"] = -100.0
# _portfolio_cashflows_NO_inflation_NO_discount_rate["initial_amount"] = 100_000.0
# _portfolio_cashflows_NO_inflation_NO_discount_rate["inflation"] = False
# _portfolio_cashflows_NO_inflation_NO_discount_rate["discount_rate"] = None
# return ok.Portfolio(**_portfolio_cashflows_NO_inflation_NO_discount_rate)
#
#
# @pytest.fixture(scope="package")
# def portfolio_cashflows_inflation_large_cf(init_portfolio_values):
# _portfolio_cashflows_inflation_large_cf = deepcopy(init_portfolio_values)
# _portfolio_cashflows_inflation_large_cf["cashflow"] = -2000
# _portfolio_cashflows_inflation_large_cf["initial_amount"] = 100_000
# return ok.Portfolio(**_portfolio_cashflows_inflation_large_cf)
@pytest.fixture(scope="package")
def init_portfolio_dcf(init_portfolio_values):
_portfolio_values = deepcopy(init_portfolio_values)
_portfolio_dcf_values = dict(
discount_rate = None,
use_discounted_values = True,
)
return [_portfolio_values, _portfolio_dcf_values]


@pytest.fixture(scope="package")
def init_mc():
return dict(
distribution="t",
period=10,
number=100
)

@pytest.fixture(scope="package")
def portfolio_dcf(init_portfolio_dcf):
pf = ok.Portfolio(**init_portfolio_dcf[0])
pf_dcf = ok.PortfolioDCF(pf, **init_portfolio_dcf[1])
return pf_dcf


@pytest.fixture(scope="package")
def portfolio_dcf_no_inflation(init_portfolio_dcf):
values_list = deepcopy(init_portfolio_dcf)
values_list[0]["inflation"] = False
# Create Portfolio
pf = ok.Portfolio(**values_list[0])
pf_dcf = ok.PortfolioDCF(pf, **values_list[1])
return pf_dcf

@pytest.fixture(scope="package")
def portfolio_dcf_discount_rate(init_portfolio_dcf):
values_list = deepcopy(init_portfolio_dcf)
values_list[1]["discount_rate"] = 0.08
# Create Portfolio
pf = ok.Portfolio(**values_list[0])
pf_dcf = ok.PortfolioDCF(pf, **values_list[1])
return pf_dcf

@pytest.fixture(scope="package")
def portfolio_dcf_indexation(init_portfolio_dcf, init_mc):
pf = ok.Portfolio(**init_portfolio_dcf[0])
pf_dcf = ok.PortfolioDCF(pf, **init_portfolio_dcf[1])
pf_dcf.set_mc_parameters(**init_mc)
# Cash Flow
ind = ok.IndexationStrategy(pf) # create IndexationStrategy linked to the portfolio
ind.initial_investment = 10_000 # add initial investments size
ind.frequency = "year" # set cash flow frequency
ind.amount = -1_500 # set withdrawal size
ind.indexation = "inflation"
pf_dcf.cashflow_parameters = ind
return pf_dcf


# Macro
Expand Down
68 changes: 7 additions & 61 deletions tests/test_cash_flow.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,14 @@
import numpy as np
import pandas as pd
import pytest
from pytest import approx
from pytest import mark
from numpy.testing import assert_array_equal, assert_allclose
from pandas.testing import assert_series_equal, assert_frame_equal

import okama as ok
from okama.common.error import LongRollingWindowLengthError, RollingWindowLengthBelowOneYearError
from okama.settings import DEFAULT_DISCOUNT_RATE

from tests import conftest

# DCF Methods
def test_dcf_discount_rate(
portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation, portfolio_cashflows_NO_inflation_NO_discount_rate
):
assert portfolio_cashflows_inflation.discount_rate == approx(0.0554, abs=1e-3) # average inflation
assert portfolio_cashflows_NO_inflation.discount_rate == approx(0.09, abs=1e-3) # defined discount rate
assert portfolio_cashflows_NO_inflation_NO_discount_rate.discount_rate == approx(0.05, abs=1e-3) # default rate
def test_dcf_discount_rate(portfolio_dcf, portfolio_dcf_no_inflation, portfolio_dcf_discount_rate):
assert portfolio_dcf.discount_rate == approx(0.05548, rel=1e-2) # average inflation
assert portfolio_dcf_no_inflation.discount_rate == DEFAULT_DISCOUNT_RATE # no inflation
assert portfolio_dcf_discount_rate.discount_rate == approx(0.08, abs=1e-3) # defined discount_rate


def test_dcf_wealth_index(portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation):
assert portfolio_cashflows_inflation.dcf.wealth_index.iloc[-1, 0] == approx(179950.30, rel=1e-2)
assert portfolio_cashflows_inflation.dcf.wealth_index.iloc[-1, 1] == approx(100050.78, rel=1e-2)
assert portfolio_cashflows_NO_inflation.dcf.wealth_index.iloc[-1, 0] == approx(152642.54, rel=1e-2)
def test_initial_investment_pv(portfolio_dcf_indexation):
assert portfolio_dcf_indexation.initial_investment_pv == approx(7633.93, rel=1e-2)


def test_dcf_survival_date(portfolio_cashflows_inflation):
assert portfolio_cashflows_inflation.dcf.survival_date_hist == pd.to_datetime("2020-01-31")


def test_dcf_cashflow_pv(portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation_NO_discount_rate):
assert portfolio_cashflows_inflation.dcf.cashflow_pv == approx(-76.33, rel=1e-2)
assert portfolio_cashflows_NO_inflation_NO_discount_rate.dcf.cashflow_pv == approx(-78.35, rel=1e-2)


def test_dcf_initial_amount_pv(portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation_NO_discount_rate):
assert portfolio_cashflows_inflation.dcf.initial_amount_pv == approx(76339.31, rel=1e-2)
assert portfolio_cashflows_NO_inflation_NO_discount_rate.dcf.initial_amount_pv == approx(78352.61, rel=1e-2)


def test_dcf_survival_period(portfolio_cashflows_inflation):
assert portfolio_cashflows_inflation.dcf.survival_period_hist == approx(5.1, rel=1e-2)


@mark.parametrize(
"distribution, expected",
[("norm", 93899.64), ("lognorm", 92155.15), ("t", 93123.36)],
)
def test_dcf_monte_carlo_wealth(portfolio_cashflows_inflation_large_cf, distribution, expected):
result = portfolio_cashflows_inflation_large_cf.dcf.monte_carlo_wealth(
first_value=100_000, distr=distribution, years=1, n=100
)
assert result.iloc[-1].mean() == approx(expected, rel=1e-1)


@mark.parametrize(
"distribution, expected",
[("norm", 6.2), ("lognorm", 6.2), ("t", 5.9)],
)
def test_dcf_monte_carlo_survival_period(portfolio_cashflows_inflation_large_cf, distribution, expected):
result = portfolio_cashflows_inflation_large_cf.dcf.monte_carlo_survival_period(distr=distribution, years=25, n=100)
assert result.mean() == approx(expected, rel=1e-1)


def test_find_the_largest_withdrawals_size():
assert False

0 comments on commit 3cfb425

Please sign in to comment.