Skip to content

Commit 3cfb425

Browse files
committed
test: update tests for PortfolioDCF
1 parent 070d892 commit 3cfb425

File tree

2 files changed

+64
-96
lines changed

2 files changed

+64
-96
lines changed

tests/conftest.py

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def _init_asset_list(request, portfolio_short_history, portfolio_dividends, asse
101101
@pytest.fixture(scope="package")
102102
def init_portfolio_values():
103103
return dict(
104-
assets=["RGBITR.INDX", "MCFTR.INDX"],
104+
assets=["RGBITR.INDX", "MCFTR.INDX"], # index values are better as they are not changing (adjusted_close)
105105
ccy="RUB",
106106
first_date="2015-01",
107107
last_date="2020-01",
@@ -153,40 +153,62 @@ def portfolio_dividends(init_portfolio_values):
153153

154154

155155
# DCF Scenarios
156-
# @pytest.fixture(scope="package")
157-
# def portfolio_cashflows_inflation(init_portfolio_values):
158-
# _portfolio_cashflows_inflation = deepcopy(init_portfolio_values)
159-
# _portfolio_cashflows_inflation["cashflow"] = -100
160-
# _portfolio_cashflows_inflation["initial_amount"] = 100_000
161-
# return ok.Portfolio(**_portfolio_cashflows_inflation)
162-
#
163-
#
164-
# @pytest.fixture(scope="package")
165-
# def portfolio_cashflows_NO_inflation(init_portfolio_values):
166-
# _portfolio_cashflows_NO_inflation = deepcopy(init_portfolio_values)
167-
# _portfolio_cashflows_NO_inflation["cashflow"] = -100.0
168-
# _portfolio_cashflows_NO_inflation["initial_amount"] = 100_000.0
169-
# _portfolio_cashflows_NO_inflation["inflation"] = False
170-
# _portfolio_cashflows_NO_inflation["discount_rate"] = 0.09
171-
# return ok.Portfolio(**_portfolio_cashflows_NO_inflation)
172-
#
173-
#
174-
# @pytest.fixture(scope="package")
175-
# def portfolio_cashflows_NO_inflation_NO_discount_rate(init_portfolio_values):
176-
# _portfolio_cashflows_NO_inflation_NO_discount_rate = deepcopy(init_portfolio_values)
177-
# _portfolio_cashflows_NO_inflation_NO_discount_rate["cashflow"] = -100.0
178-
# _portfolio_cashflows_NO_inflation_NO_discount_rate["initial_amount"] = 100_000.0
179-
# _portfolio_cashflows_NO_inflation_NO_discount_rate["inflation"] = False
180-
# _portfolio_cashflows_NO_inflation_NO_discount_rate["discount_rate"] = None
181-
# return ok.Portfolio(**_portfolio_cashflows_NO_inflation_NO_discount_rate)
182-
#
183-
#
184-
# @pytest.fixture(scope="package")
185-
# def portfolio_cashflows_inflation_large_cf(init_portfolio_values):
186-
# _portfolio_cashflows_inflation_large_cf = deepcopy(init_portfolio_values)
187-
# _portfolio_cashflows_inflation_large_cf["cashflow"] = -2000
188-
# _portfolio_cashflows_inflation_large_cf["initial_amount"] = 100_000
189-
# return ok.Portfolio(**_portfolio_cashflows_inflation_large_cf)
156+
@pytest.fixture(scope="package")
157+
def init_portfolio_dcf(init_portfolio_values):
158+
_portfolio_values = deepcopy(init_portfolio_values)
159+
_portfolio_dcf_values = dict(
160+
discount_rate = None,
161+
use_discounted_values = True,
162+
)
163+
return [_portfolio_values, _portfolio_dcf_values]
164+
165+
166+
@pytest.fixture(scope="package")
167+
def init_mc():
168+
return dict(
169+
distribution="t",
170+
period=10,
171+
number=100
172+
)
173+
174+
@pytest.fixture(scope="package")
175+
def portfolio_dcf(init_portfolio_dcf):
176+
pf = ok.Portfolio(**init_portfolio_dcf[0])
177+
pf_dcf = ok.PortfolioDCF(pf, **init_portfolio_dcf[1])
178+
return pf_dcf
179+
180+
181+
@pytest.fixture(scope="package")
182+
def portfolio_dcf_no_inflation(init_portfolio_dcf):
183+
values_list = deepcopy(init_portfolio_dcf)
184+
values_list[0]["inflation"] = False
185+
# Create Portfolio
186+
pf = ok.Portfolio(**values_list[0])
187+
pf_dcf = ok.PortfolioDCF(pf, **values_list[1])
188+
return pf_dcf
189+
190+
@pytest.fixture(scope="package")
191+
def portfolio_dcf_discount_rate(init_portfolio_dcf):
192+
values_list = deepcopy(init_portfolio_dcf)
193+
values_list[1]["discount_rate"] = 0.08
194+
# Create Portfolio
195+
pf = ok.Portfolio(**values_list[0])
196+
pf_dcf = ok.PortfolioDCF(pf, **values_list[1])
197+
return pf_dcf
198+
199+
@pytest.fixture(scope="package")
200+
def portfolio_dcf_indexation(init_portfolio_dcf, init_mc):
201+
pf = ok.Portfolio(**init_portfolio_dcf[0])
202+
pf_dcf = ok.PortfolioDCF(pf, **init_portfolio_dcf[1])
203+
pf_dcf.set_mc_parameters(**init_mc)
204+
# Cash Flow
205+
ind = ok.IndexationStrategy(pf) # create IndexationStrategy linked to the portfolio
206+
ind.initial_investment = 10_000 # add initial investments size
207+
ind.frequency = "year" # set cash flow frequency
208+
ind.amount = -1_500 # set withdrawal size
209+
ind.indexation = "inflation"
210+
pf_dcf.cashflow_parameters = ind
211+
return pf_dcf
190212

191213

192214
# Macro

tests/test_cash_flow.py

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,14 @@
1-
import numpy as np
2-
import pandas as pd
3-
import pytest
41
from pytest import approx
5-
from pytest import mark
6-
from numpy.testing import assert_array_equal, assert_allclose
7-
from pandas.testing import assert_series_equal, assert_frame_equal
82

9-
import okama as ok
10-
from okama.common.error import LongRollingWindowLengthError, RollingWindowLengthBelowOneYearError
3+
from okama.settings import DEFAULT_DISCOUNT_RATE
114

12-
from tests import conftest
135

14-
# DCF Methods
15-
def test_dcf_discount_rate(
16-
portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation, portfolio_cashflows_NO_inflation_NO_discount_rate
17-
):
18-
assert portfolio_cashflows_inflation.discount_rate == approx(0.0554, abs=1e-3) # average inflation
19-
assert portfolio_cashflows_NO_inflation.discount_rate == approx(0.09, abs=1e-3) # defined discount rate
20-
assert portfolio_cashflows_NO_inflation_NO_discount_rate.discount_rate == approx(0.05, abs=1e-3) # default rate
6+
def test_dcf_discount_rate(portfolio_dcf, portfolio_dcf_no_inflation, portfolio_dcf_discount_rate):
7+
assert portfolio_dcf.discount_rate == approx(0.05548, rel=1e-2) # average inflation
8+
assert portfolio_dcf_no_inflation.discount_rate == DEFAULT_DISCOUNT_RATE # no inflation
9+
assert portfolio_dcf_discount_rate.discount_rate == approx(0.08, abs=1e-3) # defined discount_rate
2110

2211

23-
def test_dcf_wealth_index(portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation):
24-
assert portfolio_cashflows_inflation.dcf.wealth_index.iloc[-1, 0] == approx(179950.30, rel=1e-2)
25-
assert portfolio_cashflows_inflation.dcf.wealth_index.iloc[-1, 1] == approx(100050.78, rel=1e-2)
26-
assert portfolio_cashflows_NO_inflation.dcf.wealth_index.iloc[-1, 0] == approx(152642.54, rel=1e-2)
12+
def test_initial_investment_pv(portfolio_dcf_indexation):
13+
assert portfolio_dcf_indexation.initial_investment_pv == approx(7633.93, rel=1e-2)
2714

28-
29-
def test_dcf_survival_date(portfolio_cashflows_inflation):
30-
assert portfolio_cashflows_inflation.dcf.survival_date_hist == pd.to_datetime("2020-01-31")
31-
32-
33-
def test_dcf_cashflow_pv(portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation_NO_discount_rate):
34-
assert portfolio_cashflows_inflation.dcf.cashflow_pv == approx(-76.33, rel=1e-2)
35-
assert portfolio_cashflows_NO_inflation_NO_discount_rate.dcf.cashflow_pv == approx(-78.35, rel=1e-2)
36-
37-
38-
def test_dcf_initial_amount_pv(portfolio_cashflows_inflation, portfolio_cashflows_NO_inflation_NO_discount_rate):
39-
assert portfolio_cashflows_inflation.dcf.initial_amount_pv == approx(76339.31, rel=1e-2)
40-
assert portfolio_cashflows_NO_inflation_NO_discount_rate.dcf.initial_amount_pv == approx(78352.61, rel=1e-2)
41-
42-
43-
def test_dcf_survival_period(portfolio_cashflows_inflation):
44-
assert portfolio_cashflows_inflation.dcf.survival_period_hist == approx(5.1, rel=1e-2)
45-
46-
47-
@mark.parametrize(
48-
"distribution, expected",
49-
[("norm", 93899.64), ("lognorm", 92155.15), ("t", 93123.36)],
50-
)
51-
def test_dcf_monte_carlo_wealth(portfolio_cashflows_inflation_large_cf, distribution, expected):
52-
result = portfolio_cashflows_inflation_large_cf.dcf.monte_carlo_wealth(
53-
first_value=100_000, distr=distribution, years=1, n=100
54-
)
55-
assert result.iloc[-1].mean() == approx(expected, rel=1e-1)
56-
57-
58-
@mark.parametrize(
59-
"distribution, expected",
60-
[("norm", 6.2), ("lognorm", 6.2), ("t", 5.9)],
61-
)
62-
def test_dcf_monte_carlo_survival_period(portfolio_cashflows_inflation_large_cf, distribution, expected):
63-
result = portfolio_cashflows_inflation_large_cf.dcf.monte_carlo_survival_period(distr=distribution, years=25, n=100)
64-
assert result.mean() == approx(expected, rel=1e-1)
65-
66-
67-
def test_find_the_largest_withdrawals_size():
68-
assert False

0 commit comments

Comments
 (0)