Skip to content

Commit c9c5c87

Browse files
committed
chore: black style
1 parent 3f55d03 commit c9c5c87

File tree

9 files changed

+96
-112
lines changed

9 files changed

+96
-112
lines changed

main.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import matplotlib.pyplot as plt
22

33
import okama as ok
4+
45
# Portfolio WithDrawls
5-
weights = [0.32, 0.31, 0.18, .19]
6-
portf = ok.Portfolio(['RGBITR.INDX', 'RUCBTRNS.INDX', 'MCFTR.INDX', 'GC.COMM'],
7-
ccy="RUB",
8-
weights=weights,
9-
inflation=True,
10-
symbol="retirement_portf.PF",
11-
rebalancing_period='year',
12-
cashflow=-200_000,
13-
initial_amount=39_000_000,
14-
discount_rate=None
15-
)
6+
weights = [0.32, 0.31, 0.18, 0.19]
7+
portf = ok.Portfolio(
8+
["RGBITR.INDX", "RUCBTRNS.INDX", "MCFTR.INDX", "GC.COMM"],
9+
ccy="RUB",
10+
weights=weights,
11+
inflation=True,
12+
symbol="retirement_portf.PF",
13+
rebalancing_period="year",
14+
cashflow=-200_000,
15+
initial_amount=39_000_000,
16+
discount_rate=None,
17+
)
1618

1719
print(portf.discount_rate)
1820
print(portf)
@@ -33,10 +35,7 @@
3335

3436
# Rolling / Expanding Risk
3537

36-
al = ok.AssetList(['DJI.INDX',
37-
'BND.US'
38-
])
39-
al.get_rolling_risk_annual(window=12*20).plot()
38+
al = ok.AssetList(["DJI.INDX", "BND.US"])
39+
al.get_rolling_risk_annual(window=12 * 20).plot()
4040

4141
plt.show()
42-

main_notebook.ipynb

Lines changed: 18 additions & 15 deletions
Large diffs are not rendered by default.

okama/common/helpers/helpers.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ def annualize_return(
4444

4545
@staticmethod
4646
def annualize_risk(
47-
risk: Union[float, pd.Series, pd.DataFrame],
48-
mean_return: Union[float, pd.Series, pd.DataFrame]
47+
risk: Union[float, pd.Series, pd.DataFrame], mean_return: Union[float, pd.Series, pd.DataFrame]
4948
) -> Union[float, pd.Series, pd.DataFrame]:
5049
"""
5150
Annualizes Risk.
@@ -168,11 +167,10 @@ def get_annual_return_ts_from_monthly(
168167
if isinstance(ts, pd.Series):
169168
ts.rename(ror_monthly.name, inplace=True)
170169
return ts
171-
170+
172171
@staticmethod
173172
def get_wealth_indexes(
174-
ror: Union[pd.Series, pd.DataFrame],
175-
initial_amount: float = 1000.
173+
ror: Union[pd.Series, pd.DataFrame], initial_amount: float = 1000.0
176174
) -> Union[pd.Series, pd.DataFrame]:
177175
"""
178176
Returns wealth indexes for a list of assets (or for portfolio).
@@ -189,11 +187,11 @@ def get_wealth_indexes(
189187

190188
@staticmethod
191189
def get_wealth_indexes_with_cashflow(
192-
ror: Union[pd.Series, pd.DataFrame],
190+
ror: Union[pd.Series, pd.DataFrame],
193191
portfolio_symbol: Optional[str],
194192
inflation_symbol: Optional[str],
195193
discount_rate: float,
196-
initial_amount: float = 1000.,
194+
initial_amount: float = 1000.0,
197195
cashflow: float = 0,
198196
) -> Union[pd.Series, pd.DataFrame]:
199197
"""
@@ -222,8 +220,7 @@ def get_wealth_indexes_with_cashflow(
222220
s.iloc[0] = initial_amount # replaces NaN with the first period return
223221
if inflation_symbol:
224222
cum_inflation = Frame.get_wealth_indexes(
225-
ror=ror.loc[:, inflation_symbol],
226-
initial_amount=initial_amount
223+
ror=ror.loc[:, inflation_symbol], initial_amount=initial_amount
227224
)
228225
wealth_index = pd.concat([s, cum_inflation], axis="columns")
229226
else:
@@ -336,7 +333,7 @@ def skewness(ror: Union[pd.DataFrame, pd.Series]) -> Union[pd.Series, float]:
336333
The shape of time series should be at least 12. In the opposite case empty time series is returned.
337334
"""
338335
sk = ror.expanding(min_periods=1).skew()
339-
return sk.iloc[settings._MONTHS_PER_YEAR:]
336+
return sk.iloc[settings._MONTHS_PER_YEAR :]
340337

341338
@staticmethod
342339
def skewness_rolling(ror: Union[pd.DataFrame, pd.Series], window: int = 60) -> Union[pd.Series, float]:
@@ -356,7 +353,7 @@ def kurtosis(ror: Union[pd.Series, pd.DataFrame]):
356353
Kurtosis should be close to zero for normal distribution.
357354
"""
358355
kt = ror.expanding(min_periods=1).kurt()
359-
return kt.iloc[settings._MONTHS_PER_YEAR:]
356+
return kt.iloc[settings._MONTHS_PER_YEAR :]
360357

361358
@staticmethod
362359
def kurtosis_rolling(ror: Union[pd.Series, pd.DataFrame], window: int = 60):
@@ -566,7 +563,7 @@ def tracking_difference_annualized(tracking_diff: pd.DataFrame) -> pd.DataFrame:
566563
y = abs(tracking_diff)
567564
diff = (y + 1.0).pow(pwr, axis=0) - 1.0
568565
diff = np.sign(tracking_diff) * diff
569-
return diff.iloc[settings._MONTHS_PER_YEAR - 1:] # returns for the first 11 months can't be annualized
566+
return diff.iloc[settings._MONTHS_PER_YEAR - 1 :] # returns for the first 11 months can't be annualized
570567

571568
@staticmethod
572569
def tracking_error(ror: pd.DataFrame) -> pd.DataFrame:
@@ -597,7 +594,7 @@ def expanding_cov_cor(ror: pd.DataFrame, fn: str) -> pd.DataFrame:
597594
cov_matrix_ts = getattr(ror.expanding(), fn)()
598595
cov_matrix_ts = cov_matrix_ts.drop(index=ror.columns[1:], level=1).droplevel(1)
599596
cov_matrix_ts.drop(columns=ror.columns[0], inplace=True)
600-
return cov_matrix_ts.iloc[settings._MONTHS_PER_YEAR:]
597+
return cov_matrix_ts.iloc[settings._MONTHS_PER_YEAR :]
601598

602599
@staticmethod
603600
def rolling_cov_cor(ror: pd.DataFrame, window: int = 60, fn: str = "corr") -> pd.DataFrame:
@@ -629,7 +626,7 @@ def beta(ror: pd.DataFrame) -> pd.DataFrame:
629626
raise ValueError("Beta coefficient is not defined for time periods < 1 year")
630627
cov = Index.expanding_cov_cor(ror, fn="cov")
631628
benchmark_var = ror.loc[:, ror.columns[0]].expanding().var()
632-
benchmark_var = benchmark_var.iloc[settings._MONTHS_PER_YEAR:]
629+
benchmark_var = benchmark_var.iloc[settings._MONTHS_PER_YEAR :]
633630
return cov.divide(benchmark_var, axis=0)
634631

635632
@staticmethod

okama/common/make_asset_list.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def __init__(
6767
).values()
6868
if first_date:
6969
self.first_date = max(self.first_date, pd.to_datetime(first_date))
70-
self.assets_ror = self.assets_ror[self.first_date:]
70+
self.assets_ror = self.assets_ror[self.first_date :]
7171
if last_date:
7272
self.last_date = min(self.last_date, pd.to_datetime(last_date))
7373
if inflation:
@@ -81,7 +81,7 @@ def __init__(
8181
# Add inflation to the date range dict
8282
self.assets_first_dates.update({self.inflation: macro.Inflation(self.inflation).first_date})
8383
self.assets_last_dates.update({self.inflation: macro.Inflation(self.inflation).last_date})
84-
self.assets_ror: pd.DataFrame = self.assets_ror[self.first_date: self.last_date]
84+
self.assets_ror: pd.DataFrame = self.assets_ror[self.first_date : self.last_date]
8585
self.period_length: float = round((self.last_date - self.first_date) / np.timedelta64(365, "D"), ndigits=1)
8686
self.pl = settings.PeriodLength(
8787
self.assets_ror.shape[0] // settings._MONTHS_PER_YEAR,
@@ -398,7 +398,7 @@ def plot_assets(
398398
kind: str = "mean",
399399
tickers: Union[str, list] = "tickers",
400400
pct_values: bool = False,
401-
xy_text: tuple = (0, 10)
401+
xy_text: tuple = (0, 10),
402402
) -> plt.axes:
403403
"""
404404
Plot the assets points on the risk-return chart with annotations.
@@ -428,7 +428,7 @@ def plot_assets(
428428
Percents (True)
429429
430430
xy_text : tuple, default (0, 10)
431-
The shift of the annotation text (x, y) from the point.
431+
The shift of the annotation text (x, y) from the point.
432432
433433
Examples
434434
--------

okama/frontier/multi_period.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,9 @@ def gmv_annual_values(self) -> Tuple[float, float]:
332332
>>> frontier.gmv_annual_values
333333
(0.03695845106087943, 0.04418318557516887)
334334
"""
335-
returns = helpers.Rebalance(period=self.rebalancing_period).return_ror_ts(self.gmv_annual_weights, self.assets_ror)
335+
returns = helpers.Rebalance(period=self.rebalancing_period).return_ror_ts(
336+
self.gmv_annual_weights, self.assets_ror
337+
)
336338
return (
337339
helpers.Float.annualize_risk(returns.std(), returns.mean()),
338340
(returns + 1.0).prod() ** (settings._MONTHS_PER_YEAR / returns.shape[0]) - 1.0,

okama/portfolio.py

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __init__(
9595
inflation: bool = True,
9696
weights: Optional[List[float]] = None,
9797
rebalancing_period: str = "month",
98-
initial_amount: float = 1000.,
98+
initial_amount: float = 1000.0,
9999
cashflow: float = 0,
100100
discount_rate: Optional[float] = None,
101101
symbol: str = None,
@@ -2255,11 +2255,11 @@ def plot_forecast(
22552255
return ax
22562256

22572257
def plot_forecast_monte_carlo(
2258-
self,
2259-
distr: str = "norm",
2260-
years: int = 1,
2261-
n: int = 20,
2262-
figsize: Optional[tuple] = None,
2258+
self,
2259+
distr: str = "norm",
2260+
years: int = 1,
2261+
n: int = 20,
2262+
figsize: Optional[tuple] = None,
22632263
) -> None:
22642264
"""
22652265
Plot Monte Carlo simulation for portfolio wealth indexes together with historical wealth index.
@@ -2422,7 +2422,7 @@ def cashflow_pv(self) -> Optional[float]:
24222422
>>> pf.dcf.cashflow_pv
24232423
-3004
24242424
"""
2425-
return self.parent.cashflow / (1. + self.parent.discount_rate) ** self.parent.period_length
2425+
return self.parent.cashflow / (1.0 + self.parent.discount_rate) ** self.parent.period_length
24262426

24272427
@property
24282428
def initial_amount_pv(self) -> Optional[float]:
@@ -2443,13 +2443,11 @@ def initial_amount_pv(self) -> Optional[float]:
24432443
>>> pf.dcf.initial_amount_pv
24442444
73650
24452445
"""
2446-
return self.parent.initial_amount / (1. + self.parent.discount_rate) ** self.parent.period_length
2446+
return self.parent.initial_amount / (1.0 + self.parent.discount_rate) ** self.parent.period_length
24472447

2448-
def _monte_carlo_wealth(self,
2449-
first_value: float = 1000.,
2450-
distr: str = "norm",
2451-
years: int = 1,
2452-
n: int = 100) -> pd.DataFrame:
2448+
def _monte_carlo_wealth(
2449+
self, first_value: float = 1000.0, distr: str = "norm", years: int = 1, n: int = 100
2450+
) -> pd.DataFrame:
24532451
"""
24542452
Generate portfolio wealth indexes with cash flows (withdrawals/contributions) by Monte Carlo simulation.
24552453
@@ -2498,7 +2496,7 @@ def _monte_carlo_wealth(self,
24982496
df = return_ts.apply(
24992497
helpers.Frame.get_wealth_indexes_with_cashflow,
25002498
axis=0,
2501-
args=(None, None, self.parent.discount_rate, first_value, self.parent.cashflow)
2499+
args=(None, None, self.parent.discount_rate, first_value, self.parent.cashflow),
25022500
)
25032501

25042502
def remove_negative_values(s):
@@ -2581,10 +2579,10 @@ def plot_forecast_monte_carlo(
25812579
s2.plot(legend=None)
25822580

25832581
def monte_carlo_survival_period(
2584-
self,
2585-
distr: str = "norm",
2586-
years: int = 1,
2587-
n: int = 20,
2582+
self,
2583+
distr: str = "norm",
2584+
years: int = 1,
2585+
n: int = 20,
25882586
) -> pd.Series:
25892587
"""
25902588
Generate a survival period distribution for a portfolio with cash flows by Monte Carlo simulation.
@@ -2631,12 +2629,7 @@ def monte_carlo_survival_period(
26312629
>> s.quantile(50 / 100)
26322630
2.7
26332631
"""
2634-
s2 = self._monte_carlo_wealth(
2635-
first_value=self.parent.initial_amount,
2636-
distr=distr,
2637-
years=years,
2638-
n=n
2639-
)
2632+
s2 = self._monte_carlo_wealth(first_value=self.parent.initial_amount, distr=distr, years=years, n=n)
26402633
dates: pd.Series = helpers.Frame.get_survival_date(s2)
26412634

26422635
return dates.apply(helpers.Date.get_period_length, args=(self.parent.last_date,))

tests/conftest.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ def portfolio_cashflows_inflation(init_portfolio_values):
167167
@pytest.fixture(scope="package")
168168
def portfolio_cashflows_NO_inflation(init_portfolio_values):
169169
_portfolio_cashflows_NO_inflation = deepcopy(init_portfolio_values)
170-
_portfolio_cashflows_NO_inflation["cashflow"] = -100.
171-
_portfolio_cashflows_NO_inflation["initial_amount"] = 100_000.
170+
_portfolio_cashflows_NO_inflation["cashflow"] = -100.0
171+
_portfolio_cashflows_NO_inflation["initial_amount"] = 100_000.0
172172
_portfolio_cashflows_NO_inflation["inflation"] = False
173173
_portfolio_cashflows_NO_inflation["discount_rate"] = 0.09
174174
return ok.Portfolio(**_portfolio_cashflows_NO_inflation)
@@ -177,8 +177,8 @@ def portfolio_cashflows_NO_inflation(init_portfolio_values):
177177
@pytest.fixture(scope="package")
178178
def portfolio_cashflows_NO_inflation_NO_discount_rate(init_portfolio_values):
179179
_portfolio_cashflows_NO_inflation_NO_discount_rate = deepcopy(init_portfolio_values)
180-
_portfolio_cashflows_NO_inflation_NO_discount_rate["cashflow"] = -100.
181-
_portfolio_cashflows_NO_inflation_NO_discount_rate["initial_amount"] = 100_000.
180+
_portfolio_cashflows_NO_inflation_NO_discount_rate["cashflow"] = -100.0
181+
_portfolio_cashflows_NO_inflation_NO_discount_rate["initial_amount"] = 100_000.0
182182
_portfolio_cashflows_NO_inflation_NO_discount_rate["inflation"] = False
183183
_portfolio_cashflows_NO_inflation_NO_discount_rate["discount_rate"] = None
184184
return ok.Portfolio(**_portfolio_cashflows_NO_inflation_NO_discount_rate)
@@ -211,6 +211,7 @@ def portfolio_short_history(init_portfolio_values):
211211
_portfolio_short_history["first_date"] = "2019-02"
212212
return ok.Portfolio(**_portfolio_short_history)
213213

214+
214215
# Efficient Frontier Single Period
215216
@pytest.fixture(scope="module")
216217
def init_efficient_frontier_values1():

tests/test_asset_list.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,31 +86,35 @@ def test_make_asset_list(self):
8686
assert self.asset_list.assets_ror.columns.name == "Symbols"
8787

8888
def test_calculate_wealth_indexes(self):
89-
assert self.asset_list.wealth_indexes.sum(axis=1)[-1] == approx(
90-
3306.19, rel=1e-2
91-
) # last month indexes sum
89+
assert self.asset_list.wealth_indexes.sum(axis=1)[-1] == approx(3306.19, rel=1e-2) # last month indexes sum
9290

9391
def test_risk(self):
9492
assert self.asset_list.risk_monthly.iloc[-1]["USDRUB.CBR"] == approx(0.0258, rel=1e-2)
9593
assert self.asset_list.risk_monthly.iloc[-1]["MCFTR.INDX"] == approx(0.0264, rel=1e-2)
9694
assert self.asset_list.risk_annual.iloc[-1]["USDRUB.CBR"] == approx(0.0825, rel=1e-2)
9795
assert self.asset_list.risk_annual.iloc[-1]["MCFTR.INDX"] == approx(0.1222, rel=1e-2)
9896

99-
@mark.parametrize("window, expected", [
100-
pytest.param(12, 0.1874, id="12-months"),
101-
pytest.param(6, 0.2205, id="6-months"),
102-
])
97+
@mark.parametrize(
98+
"window, expected",
99+
[
100+
pytest.param(12, 0.1874, id="12-months"),
101+
pytest.param(6, 0.2205, id="6-months"),
102+
],
103+
)
103104
def test_get_rolling_risk_annual(self, window, expected):
104105
result = self.asset_list.get_rolling_risk_annual(window).iloc[-1]
105106
assert result.sum() == approx(expected, abs=1e-2)
106107

107-
@pytest.mark.parametrize("window, exception", [
108-
pytest.param(0, ValueError, id="error-0-months"),
109-
pytest.param(-1, ValueError, id="error-negative-months"),
110-
pytest.param(34, ValueError, id="error - window period is too long"),
111-
pytest.param("twelve", TypeError, id="error-string-input"),
112-
pytest.param(None, TypeError, id="error-none-input"),
113-
])
108+
@pytest.mark.parametrize(
109+
"window, exception",
110+
[
111+
pytest.param(0, ValueError, id="error-0-months"),
112+
pytest.param(-1, ValueError, id="error-negative-months"),
113+
pytest.param(34, ValueError, id="error - window period is too long"),
114+
pytest.param("twelve", TypeError, id="error-string-input"),
115+
pytest.param(None, TypeError, id="error-none-input"),
116+
],
117+
)
114118
def test_get_rolling_risk_annual_error_cases(self, window, exception):
115119
with pytest.raises(exception):
116120
self.spy.get_rolling_risk_annual(window)

0 commit comments

Comments
 (0)