my-github-tests 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- my_github_tests-0.1.0/PKG-INFO +22 -0
- my_github_tests-0.1.0/README.md +3 -0
- my_github_tests-0.1.0/data/__init__.py +0 -0
- my_github_tests-0.1.0/data/mac_portfolio_optimizer.zip +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/__init__.py +22 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/core/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/core/backtester_optimiser.py +295 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/core/current_portfolio_optimiser.py +279 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__pycache__/__init__.cpython-311.pyc +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__pycache__/__init__.cpython-312.pyc +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__pycache__/excel_loader.cpython-311.pyc +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__pycache__/excel_loader.cpython-312.pyc +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__pycache__/mac_universe.cpython-311.pyc +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/__pycache__/mac_universe.cpython-312.pyc +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/db_loader.py +257 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/excel_loader.py +374 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/forecast_returns.py +96 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/data/mac_universe.py +419 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/local_path.py +50 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/fetch_prod_specs.py +67 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/futures_risk_model.py +497 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/prod_covar_specs.py +45 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/reporting.py +93 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/run_current_portfolio.py +115 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/mac_prod/run_funds_backtest.py +345 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/check_corrs.py +37 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/factor_returns.py +36 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/funds_alpha.py +79 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/funds_universe.py +167 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/index_universe.py +382 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/universe.py +59 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/old_data/universe_report.py +74 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/optimise_prod_portfolio.py +66 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/apac/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/apac/run_jp_bespoke_mandate.py +130 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/apac/run_range_saa.py +47 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/apac/run_saa_backtest.py +155 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/apac/set_risk_budget_for_range_saa.py +198 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/estimate_ar.py +261 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/paper/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/paper/article_figures.py +419 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/paper/cross_sharpe.py +43 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/paper/run_backtest_for_article.py +209 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/paper/slides_figures.py +97 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/paper/vol_check.py +115 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/returns_unsmoothing.py +259 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/risk_budget_factors.py +238 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/__init__.py +0 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/cma_backtester.py +330 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/cma_saa_optimiser.py +310 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/cma_saa_optimiser_old.py +312 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/implied_returns.py +185 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/saa_excel_loader.py +207 -0
- my_github_tests-0.1.0/mac_portfolio_optimizer/research/saa/saa_universe.py +58 -0
- my_github_tests-0.1.0/my_github_tests.egg-info/PKG-INFO +22 -0
- my_github_tests-0.1.0/my_github_tests.egg-info/SOURCES.txt +62 -0
- my_github_tests-0.1.0/my_github_tests.egg-info/dependency_links.txt +1 -0
- my_github_tests-0.1.0/my_github_tests.egg-info/top_level.txt +3 -0
- my_github_tests-0.1.0/pyproject.toml +158 -0
- my_github_tests-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: my-github-tests
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: my github tests
|
|
5
|
+
Author-email: AA SS <your.email@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ArturSepp/my_private_github
|
|
8
|
+
Project-URL: Repository, https://github.com/ArturSepp/my_private_github
|
|
9
|
+
Project-URL: Issues, https://github.com/ArturSepp/my_private_github/issues
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# my_private_github
|
|
21
|
+
repo for my private projects
|
|
22
|
+
ISQ objectives and deliverables for 2025
|
|
File without changes
|
|
Binary file
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from mac_portfolio_optimizer.data.mac_universe import (SUB_ASSET_CLASS_DEFINITIONS,
|
|
2
|
+
MacUniverseData,
|
|
3
|
+
UniverseColumns,
|
|
4
|
+
RISK_FACTORS, SaaPortfolio, TaaPortfolio,
|
|
5
|
+
MacRangeConstraints,
|
|
6
|
+
SaaRangeConstraints,
|
|
7
|
+
AssetClasses,
|
|
8
|
+
RiskModel)
|
|
9
|
+
|
|
10
|
+
from mac_portfolio_optimizer.data.excel_loader import (load_mac_portfolio_universe,
|
|
11
|
+
load_universe_returns_from_sheet_data)
|
|
12
|
+
|
|
13
|
+
from mac_portfolio_optimizer.core.backtester_optimiser import (backtest_saa_taa_portfolios,
|
|
14
|
+
backtest_saa_risk_budget_portfolio,
|
|
15
|
+
range_backtest_lasso_portfolio_with_alphas,
|
|
16
|
+
tre_range_backtest_lasso_portfolio_with_alphas)
|
|
17
|
+
|
|
18
|
+
from mac_portfolio_optimizer.core.current_portfolio_optimiser import run_current_saa_portfolio, run_current_saa_taa_portfolios
|
|
19
|
+
|
|
20
|
+
from mac_portfolio_optimizer.mac_prod.reporting import generate_report
|
|
21
|
+
|
|
22
|
+
from mac_portfolio_optimizer.mac_prod.fetch_prod_specs import get_prod_covar_estimator, get_meta_params
|
|
File without changes
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""
|
|
2
|
+
implementation of optimisers for current portfolio and time series backtest
|
|
3
|
+
"""
|
|
4
|
+
# packages
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import qis as qis
|
|
7
|
+
from typing import Optional, Union, Tuple, Dict
|
|
8
|
+
from optimalportfolios import (rolling_risk_budgeting,
|
|
9
|
+
rolling_maximise_alpha_over_tre,
|
|
10
|
+
CovarEstimator,
|
|
11
|
+
compute_joint_alphas,
|
|
12
|
+
AlphasData,
|
|
13
|
+
Constraints,
|
|
14
|
+
EstimatedRollingCovarData)
|
|
15
|
+
|
|
16
|
+
from mac_portfolio_optimizer import MacUniverseData
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def backtest_benchmarked_taa_portfolio(benchmark_rolling_weights: pd.DataFrame,
|
|
20
|
+
taa_alphas: pd.DataFrame,
|
|
21
|
+
covar_dict: Dict[pd.Timestamp, pd.DataFrame],
|
|
22
|
+
joint_prices: pd.DataFrame,
|
|
23
|
+
taa_constraints: Constraints,
|
|
24
|
+
joint_rebalancing_freq: pd.Series,
|
|
25
|
+
time_period: qis.TimePeriod = qis.TimePeriod('31Dec2003', None),
|
|
26
|
+
is_apply_tre_utility_objective: bool = False
|
|
27
|
+
) -> pd.DataFrame:
|
|
28
|
+
"""
|
|
29
|
+
wrapper for TAA optimisation given benchmark weights and alphas solve tre constraint optimisation
|
|
30
|
+
covar_dict is computed covariance for joint assets
|
|
31
|
+
"""
|
|
32
|
+
joint_assets = joint_prices.columns
|
|
33
|
+
# generate rebalancing indicators
|
|
34
|
+
taa_rebalancing_indicators = qis.create_rebalancing_indicators_from_freqs(rebalancing_freqs=joint_rebalancing_freq,
|
|
35
|
+
time_period=time_period,
|
|
36
|
+
tickers=joint_assets)
|
|
37
|
+
# align alphas
|
|
38
|
+
taa_alphas = taa_alphas.reindex(index=list(covar_dict.keys()), method='ffill').ffill()
|
|
39
|
+
alphas_joint = taa_alphas.reindex(columns=joint_assets).fillna(0.0)
|
|
40
|
+
# reindex at covar frequency and joint prices columns
|
|
41
|
+
benchmark_rolling_weights = benchmark_rolling_weights.reindex(index=list(covar_dict.keys()), method='ffill').ffill()
|
|
42
|
+
benchmark_rolling_weights = benchmark_rolling_weights.reindex(columns=joint_assets).fillna(0.0)
|
|
43
|
+
taa_rolling_weights = rolling_maximise_alpha_over_tre(prices=joint_prices,
|
|
44
|
+
alphas=alphas_joint,
|
|
45
|
+
constraints0=taa_constraints,
|
|
46
|
+
benchmark_weights=benchmark_rolling_weights,
|
|
47
|
+
covar_dict=covar_dict,
|
|
48
|
+
time_period=time_period,
|
|
49
|
+
rebalancing_indicators=taa_rebalancing_indicators,
|
|
50
|
+
apply_total_to_good_ratio=False,
|
|
51
|
+
is_apply_tre_utility_objective=is_apply_tre_utility_objective)
|
|
52
|
+
return taa_rolling_weights
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def backtest_saa_risk_budget_portfolio(universe_data: MacUniverseData,
|
|
56
|
+
covar_estimator: CovarEstimator = None,
|
|
57
|
+
saa_taa_covar: Dict[pd.Timestamp, pd.DataFrame] = None,
|
|
58
|
+
time_period: qis.TimePeriod = qis.TimePeriod('31Dec2003', None),
|
|
59
|
+
saa_rebalancing_freq: str = 'QE',
|
|
60
|
+
saa_constraints: Constraints = None,
|
|
61
|
+
management_fee: float = 0.0,
|
|
62
|
+
apply_unsmoothing_for_pe: bool = True,
|
|
63
|
+
**kwargs
|
|
64
|
+
) -> Tuple[pd.DataFrame, qis.PortfolioData]:
|
|
65
|
+
"""
|
|
66
|
+
implementation for computing saa risk budget portfolio
|
|
67
|
+
use QE or YE for saa_rebalancing_freq
|
|
68
|
+
saa_taa_covar can be passed or calculated on the fly
|
|
69
|
+
"""
|
|
70
|
+
saa_rebalancing_schedule = qis.generate_dates_schedule(time_period=time_period, freq=saa_rebalancing_freq)
|
|
71
|
+
saa_risk_prices = universe_data.get_saa_prices(apply_unsmoothing_for_pe=apply_unsmoothing_for_pe)
|
|
72
|
+
|
|
73
|
+
if saa_taa_covar is not None:
|
|
74
|
+
saa_assets = universe_data.saa_prices.columns
|
|
75
|
+
saa_pd_covars = {}
|
|
76
|
+
for date in saa_rebalancing_schedule:
|
|
77
|
+
saa_pd_covars[date] = saa_taa_covar[date].loc[saa_assets, saa_assets]
|
|
78
|
+
else:
|
|
79
|
+
# it is important that returns frequency is saa_rebalancing_freq otherwise we cannot compute proper returns of PE and PD
|
|
80
|
+
# estimate covar at rebalancing schedule
|
|
81
|
+
if covar_estimator is None:
|
|
82
|
+
raise ValueError(f"must pass covar_estimator")
|
|
83
|
+
covar_estimator.rebalancing_freq = saa_rebalancing_freq
|
|
84
|
+
rolling_covar_data = covar_estimator.fit_rolling_covars(prices=saa_risk_prices,
|
|
85
|
+
risk_factor_prices=universe_data.get_risk_factors(),
|
|
86
|
+
time_period=time_period)
|
|
87
|
+
covar_dict = rolling_covar_data.y_covars
|
|
88
|
+
# set saa rebalancing freq
|
|
89
|
+
saa_pd_covars = {}
|
|
90
|
+
for date in saa_rebalancing_schedule:
|
|
91
|
+
saa_pd_covars[date] = covar_dict[date]
|
|
92
|
+
|
|
93
|
+
# generate rebalancing indicators
|
|
94
|
+
saa_rebalancing_indicators = qis.create_rebalancing_indicators_from_freqs(rebalancing_freqs=saa_rebalancing_freq,
|
|
95
|
+
time_period=time_period,
|
|
96
|
+
tickers=universe_data.saa_prices.columns.to_list())
|
|
97
|
+
|
|
98
|
+
if saa_constraints is None:
|
|
99
|
+
saa_constraints = universe_data.get_saa_constraints()
|
|
100
|
+
saa_rolling_weights = rolling_risk_budgeting(prices=saa_risk_prices,
|
|
101
|
+
time_period=time_period,
|
|
102
|
+
covar_dict=saa_pd_covars,
|
|
103
|
+
risk_budget=universe_data.get_saa_risk_budget(),
|
|
104
|
+
constraints0=saa_constraints,
|
|
105
|
+
rebalancing_indicators=saa_rebalancing_indicators,
|
|
106
|
+
apply_total_to_good_ratio=False) # nb
|
|
107
|
+
|
|
108
|
+
saa_portfolio_data = qis.backtest_model_portfolio(prices=universe_data.get_saa_prices(),
|
|
109
|
+
weights=saa_rolling_weights,
|
|
110
|
+
management_fee=management_fee,
|
|
111
|
+
ticker='SAA')
|
|
112
|
+
saa_portfolio_data.covar_dict = saa_pd_covars
|
|
113
|
+
return saa_rolling_weights, saa_portfolio_data
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def backtest_saa_taa_portfolios(universe_data: MacUniverseData,
|
|
117
|
+
covar_estimator: CovarEstimator,
|
|
118
|
+
time_period: qis.TimePeriod = qis.TimePeriod('31Dec2003', None),
|
|
119
|
+
is_joint_saa_taa_covar: bool = True,
|
|
120
|
+
saa_rebalancing_freq: str = 'QE',
|
|
121
|
+
global_tracking_err_vol_constraint: Optional[float] = None,
|
|
122
|
+
group_tracking_err_vol_constraint: Optional[pd.Series] = None,
|
|
123
|
+
global_max_turnover_constraint: Optional[float] = None,
|
|
124
|
+
group_max_turnover_constraint: Optional[pd.Series] = None,
|
|
125
|
+
management_fee: float = 0.0,
|
|
126
|
+
is_saa_benchmark_for_betas: bool = False,
|
|
127
|
+
rebalancing_costs: float = 0.0,
|
|
128
|
+
apply_unsmoothing_for_pe: bool = True,
|
|
129
|
+
) -> Tuple[qis.MultiPortfolioData, AlphasData, EstimatedRollingCovarData]:
|
|
130
|
+
"""
|
|
131
|
+
wrapper for computing saa portfolio and saa-benchmarked taa portfolio
|
|
132
|
+
"""
|
|
133
|
+
# 1. estimate covar
|
|
134
|
+
taa_covar_data = covar_estimator.fit_rolling_covars(risk_factor_prices=universe_data.get_risk_factors(),
|
|
135
|
+
prices=universe_data.get_joint_prices(apply_unsmoothing_for_pe=apply_unsmoothing_for_pe),
|
|
136
|
+
time_period=time_period)
|
|
137
|
+
covar_dict = taa_covar_data.y_covars
|
|
138
|
+
|
|
139
|
+
if is_joint_saa_taa_covar:
|
|
140
|
+
saa_taa_covar = covar_dict
|
|
141
|
+
else:
|
|
142
|
+
saa_taa_covar = None
|
|
143
|
+
|
|
144
|
+
# 2. run saa
|
|
145
|
+
saa_rolling_weights, saa_portfolio_data = backtest_saa_risk_budget_portfolio(universe_data=universe_data,
|
|
146
|
+
saa_taa_covar=saa_taa_covar,
|
|
147
|
+
time_period=time_period,
|
|
148
|
+
covar_estimator=covar_estimator,
|
|
149
|
+
saa_rebalancing_freq=saa_rebalancing_freq,
|
|
150
|
+
management_fee=management_fee,
|
|
151
|
+
apply_unsmoothing_for_pe=apply_unsmoothing_for_pe)
|
|
152
|
+
|
|
153
|
+
# 3. compute alphas
|
|
154
|
+
if is_saa_benchmark_for_betas:
|
|
155
|
+
benchmark_price = saa_portfolio_data.get_portfolio_nav()
|
|
156
|
+
else:
|
|
157
|
+
benchmark_price = universe_data.benchmarks.iloc[:, 0]
|
|
158
|
+
group_data, _ = universe_data.get_joint_sub_ac_group_data()
|
|
159
|
+
group_data_alphas, _ = universe_data.get_joint_ac_group_data()
|
|
160
|
+
# compute alpha using reported prices
|
|
161
|
+
taa_prices = universe_data.get_taa_prices(apply_unsmoothing_for_pe=apply_unsmoothing_for_pe)
|
|
162
|
+
manager_alphas = compute_joint_alphas(prices=taa_prices,
|
|
163
|
+
benchmark_price=benchmark_price,
|
|
164
|
+
risk_factors_prices=universe_data.get_risk_factors(),
|
|
165
|
+
alpha_beta_type=universe_data.get_alpha_beta_type(),
|
|
166
|
+
rebalancing_freq=universe_data.get_joint_rebalancing_freqs(),
|
|
167
|
+
estimated_betas=taa_covar_data.asset_last_betas_t,
|
|
168
|
+
group_data_alphas=universe_data.get_taa_asset_class_data(is_merge_alts_with_equity=True),
|
|
169
|
+
return_annualisation_freq_dict=universe_data.return_annualisation_freq_dict)
|
|
170
|
+
|
|
171
|
+
# 4. run tre portfolio
|
|
172
|
+
taa_constraints = universe_data.get_taa_constraints(
|
|
173
|
+
global_tracking_err_vol_constraint=global_tracking_err_vol_constraint,
|
|
174
|
+
group_tracking_err_vol_constraint=group_tracking_err_vol_constraint,
|
|
175
|
+
global_max_turnover_constraint=global_max_turnover_constraint,
|
|
176
|
+
group_max_turnover_constraint=group_max_turnover_constraint)
|
|
177
|
+
|
|
178
|
+
taa_rolling_weights = backtest_benchmarked_taa_portfolio(benchmark_rolling_weights=saa_rolling_weights,
|
|
179
|
+
taa_alphas=manager_alphas.alpha_scores,
|
|
180
|
+
joint_prices=universe_data.get_joint_prices(),
|
|
181
|
+
joint_rebalancing_freq=universe_data.get_joint_rebalancing_freqs(),
|
|
182
|
+
covar_dict=covar_dict,
|
|
183
|
+
time_period=time_period,
|
|
184
|
+
taa_constraints=taa_constraints)
|
|
185
|
+
prices = universe_data.get_joint_prices()
|
|
186
|
+
taa_portfolio_data = qis.backtest_model_portfolio(prices=prices,
|
|
187
|
+
weights=taa_rolling_weights,
|
|
188
|
+
management_fee=management_fee,
|
|
189
|
+
rebalancing_costs=rebalancing_costs,
|
|
190
|
+
ticker='TAA')
|
|
191
|
+
multi_portfolio_data = qis.MultiPortfolioData(portfolio_datas=[taa_portfolio_data, saa_portfolio_data],
|
|
192
|
+
benchmark_prices=universe_data.benchmarks,
|
|
193
|
+
covar_dict=covar_dict)
|
|
194
|
+
group_data, group_order = universe_data.get_joint_sub_ac_group_data()
|
|
195
|
+
[x.set_group_data(group_data=group_data, group_order=group_order) for x in multi_portfolio_data.portfolio_datas]
|
|
196
|
+
return multi_portfolio_data, manager_alphas, taa_covar_data
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def range_backtest_lasso_portfolio_with_alphas(universe_data: MacUniverseData,
|
|
200
|
+
covar_estimator: CovarEstimator,
|
|
201
|
+
time_period: qis.TimePeriod = qis.TimePeriod('31Dec2003', None),
|
|
202
|
+
is_joint_saa_taa_covar: bool = True,
|
|
203
|
+
saa_rebalancing_freq: Union[str, pd.Series] = 'QE',
|
|
204
|
+
global_tracking_err_vol_constraint: Optional[float] = None,
|
|
205
|
+
group_tracking_err_vol_constraint: Optional[pd.Series] = None,
|
|
206
|
+
global_max_turnover_constraint: Optional[float] = None,
|
|
207
|
+
group_max_turnover_constraint: Optional[pd.Series] = None,
|
|
208
|
+
management_fee: float = 0.0,
|
|
209
|
+
is_saa_benchmark_for_betas: bool = False,
|
|
210
|
+
rebalancing_costs: float = 0.0,
|
|
211
|
+
) -> (qis.MultiPortfolioData, qis.MultiPortfolioData):
|
|
212
|
+
|
|
213
|
+
spans = [24] # span, squeeze_factor
|
|
214
|
+
# reg_lambdas = [1e-4, 1e-5, 1e-6, 1e-7, 1e-8]
|
|
215
|
+
reg_lambdas = [1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 0.0]
|
|
216
|
+
# reg_lambdas = [5.0*1e-5, 5.0*1e-6, 5.0*1e-7]
|
|
217
|
+
# reg_lambdas = [5.0 * 1e-4, 1e-4, 5.0 * 1e-5, 1e-5, 5.0 * 1e-6, 1e-6]
|
|
218
|
+
squeeze_factors = [0.0]
|
|
219
|
+
|
|
220
|
+
saa_portfolio_datas = []
|
|
221
|
+
taa_portfolio_datas = []
|
|
222
|
+
for span in spans:
|
|
223
|
+
for squeeze_factor in squeeze_factors:
|
|
224
|
+
for reg_lambda in reg_lambdas:
|
|
225
|
+
ticker = f"span={span:0.0f}, lambda={reg_lambda:0.0e}, sqze={squeeze_factor:0.2f}"
|
|
226
|
+
covar_estimator.lasso_model.reg_lambda = reg_lambda
|
|
227
|
+
covar_estimator.lasso_model.span = span
|
|
228
|
+
covar_estimator.span_freq_dict = {'ME': span, 'QE': span / 4}
|
|
229
|
+
multi_portfolio_data, _, _ = backtest_saa_taa_portfolios(universe_data=universe_data,
|
|
230
|
+
time_period=time_period,
|
|
231
|
+
covar_estimator=covar_estimator,
|
|
232
|
+
is_joint_saa_taa_covar=is_joint_saa_taa_covar,
|
|
233
|
+
saa_rebalancing_freq=saa_rebalancing_freq,
|
|
234
|
+
is_saa_benchmark_for_betas=is_saa_benchmark_for_betas,
|
|
235
|
+
global_tracking_err_vol_constraint=global_tracking_err_vol_constraint,
|
|
236
|
+
group_tracking_err_vol_constraint=group_tracking_err_vol_constraint,
|
|
237
|
+
global_max_turnover_constraint=global_max_turnover_constraint,
|
|
238
|
+
group_max_turnover_constraint=group_max_turnover_constraint,
|
|
239
|
+
rebalancing_costs=rebalancing_costs,
|
|
240
|
+
management_fee=management_fee)
|
|
241
|
+
saa_portfolio_datas.append(multi_portfolio_data.portfolio_datas[1].set_ticker(ticker))
|
|
242
|
+
taa_portfolio_datas.append(multi_portfolio_data.portfolio_datas[0].set_ticker(ticker))
|
|
243
|
+
|
|
244
|
+
saa_multi_portfolio_data = qis.MultiPortfolioData(portfolio_datas=saa_portfolio_datas,
|
|
245
|
+
benchmark_prices=universe_data.benchmarks.iloc[:, 0])
|
|
246
|
+
taa_multi_portfolio_data = qis.MultiPortfolioData(portfolio_datas=taa_portfolio_datas,
|
|
247
|
+
benchmark_prices=universe_data.benchmarks.iloc[:, 0])
|
|
248
|
+
return saa_multi_portfolio_data, taa_multi_portfolio_data
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def tre_range_backtest_lasso_portfolio_with_alphas(universe_data: MacUniverseData,
|
|
252
|
+
covar_estimator: CovarEstimator,
|
|
253
|
+
time_period: qis.TimePeriod = qis.TimePeriod('31Dec2003', None),
|
|
254
|
+
saa_rebalancing_freq: str = 'QE',
|
|
255
|
+
management_fee: float = 0.0,
|
|
256
|
+
is_saa_benchmark_for_betas: bool = False,
|
|
257
|
+
rebalancing_costs: float = 0.0,
|
|
258
|
+
is_grouped_constaints: bool = True
|
|
259
|
+
) -> (qis.MultiPortfolioData, qis.MultiPortfolioData):
|
|
260
|
+
|
|
261
|
+
tracking_err_vol_constraints = [0.025]
|
|
262
|
+
turnover_constraints = [0.125, 0.25, 0.5]
|
|
263
|
+
|
|
264
|
+
saa_portfolio_datas = []
|
|
265
|
+
taa_portfolio_datas = []
|
|
266
|
+
for tracking_err_vol_constraint in tracking_err_vol_constraints:
|
|
267
|
+
for turnover_constraint in turnover_constraints:
|
|
268
|
+
if is_grouped_constaints:
|
|
269
|
+
ticker = f"group_tre_vol={tracking_err_vol_constraint:0.2%}, turnover={turnover_constraint:0.2%}"
|
|
270
|
+
group_tracking_err_vol_constraint = universe_data.set_group_uniform_tracking_error_constraint(tracking_err_vol_constraint=tracking_err_vol_constraint)
|
|
271
|
+
global_tracking_err_vol_constraint = None
|
|
272
|
+
else:
|
|
273
|
+
ticker = f"global_tre_vol={tracking_err_vol_constraint:0.2%}, turnover={turnover_constraint:0.2%}"
|
|
274
|
+
global_tracking_err_vol_constraint = tracking_err_vol_constraint
|
|
275
|
+
group_tracking_err_vol_constraint = None
|
|
276
|
+
|
|
277
|
+
multi_portfolio_data, _, _ = backtest_saa_taa_portfolios(universe_data=universe_data,
|
|
278
|
+
time_period=time_period,
|
|
279
|
+
covar_estimator=covar_estimator,
|
|
280
|
+
saa_rebalancing_freq=saa_rebalancing_freq,
|
|
281
|
+
global_tracking_err_vol_constraint=global_tracking_err_vol_constraint,
|
|
282
|
+
group_tracking_err_vol_constraint=group_tracking_err_vol_constraint,
|
|
283
|
+
global_max_turnover_constraint=turnover_constraint,
|
|
284
|
+
group_max_turnover_constraint=None,
|
|
285
|
+
management_fee=management_fee,
|
|
286
|
+
is_saa_benchmark_for_betas=is_saa_benchmark_for_betas,
|
|
287
|
+
rebalancing_costs=rebalancing_costs)
|
|
288
|
+
saa_portfolio_datas.append(multi_portfolio_data.portfolio_datas[1].set_ticker(ticker))
|
|
289
|
+
taa_portfolio_datas.append(multi_portfolio_data.portfolio_datas[0].set_ticker(ticker))
|
|
290
|
+
|
|
291
|
+
saa_multi_portfolio_data = qis.MultiPortfolioData(portfolio_datas=saa_portfolio_datas,
|
|
292
|
+
benchmark_prices=universe_data.benchmarks.iloc[:, 0])
|
|
293
|
+
taa_multi_portfolio_data = qis.MultiPortfolioData(portfolio_datas=taa_portfolio_datas,
|
|
294
|
+
benchmark_prices=universe_data.benchmarks.iloc[:, 0])
|
|
295
|
+
return saa_multi_portfolio_data, taa_multi_portfolio_data
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""
|
|
2
|
+
optimisation engine for the current portfolio
|
|
3
|
+
"""
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
import seaborn as sns
|
|
8
|
+
import qis as qis
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import Dict, Any, Tuple, Optional
|
|
11
|
+
from optimalportfolios import (CovarEstimator,
|
|
12
|
+
EstimatedCurrentCovarData,
|
|
13
|
+
EstimatedRollingCovarData,
|
|
14
|
+
wrapper_risk_budgeting,
|
|
15
|
+
compute_joint_alphas,
|
|
16
|
+
wrapper_maximise_alpha_over_tre)
|
|
17
|
+
|
|
18
|
+
from mac_portfolio_optimizer import MacUniverseData, backtest_saa_risk_budget_portfolio
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class SaaTaaPortfolios:
|
|
23
|
+
"""
|
|
24
|
+
output of current saa and taa portfolios
|
|
25
|
+
"""
|
|
26
|
+
saa_valuation_date: pd.Timestamp
|
|
27
|
+
taa_valuation_date: pd.Timestamp
|
|
28
|
+
taa_df: pd.DataFrame
|
|
29
|
+
taa_covar: pd.DataFrame
|
|
30
|
+
saa_df: pd.DataFrame
|
|
31
|
+
saa_covar: pd.DataFrame
|
|
32
|
+
universe_data: MacUniverseData
|
|
33
|
+
taa_rolling_covar_data: EstimatedRollingCovarData
|
|
34
|
+
saa_current_covar_data: Optional[EstimatedCurrentCovarData]
|
|
35
|
+
|
|
36
|
+
taa_corr: pd.DataFrame = None
|
|
37
|
+
saa_corr: pd.DataFrame = None
|
|
38
|
+
|
|
39
|
+
def __post_init__(self):
|
|
40
|
+
self.taa_corr = qis.covar_to_corr(covar=self.taa_covar)
|
|
41
|
+
self.saa_corr = qis.covar_to_corr(covar=self.saa_covar)
|
|
42
|
+
|
|
43
|
+
def get_output_dict(self,
|
|
44
|
+
period_2y: qis.TimePeriod = qis.TimePeriod('31Dec2022', '31Dec2024'),
|
|
45
|
+
period_5y: qis.TimePeriod = qis.TimePeriod('31Dec2019', '31Dec2024'),
|
|
46
|
+
saa_kwargs: Dict[str, Any] = dict(perf_params=qis.PerfParams(freq='QE'), alpha_an_factor=4.0),
|
|
47
|
+
taa_kwargs: Dict[str, Any] = dict(perf_params=qis.PerfParams(freq='QE'), alpha_an_factor=4.0)
|
|
48
|
+
) -> Dict[str, pd.DataFrame]:
|
|
49
|
+
"""
|
|
50
|
+
produce outputs dfs
|
|
51
|
+
"""
|
|
52
|
+
taa_df = self.taa_df.copy()
|
|
53
|
+
saa_df = self.saa_df.copy()
|
|
54
|
+
|
|
55
|
+
saa_prices = pd.concat([self.universe_data.benchmarks, self.universe_data.saa_prices], axis=1)
|
|
56
|
+
saa_perf_2y = qis.get_ra_perf_benchmark_columns(prices=period_2y.locate(saa_prices),
|
|
57
|
+
benchmark=self.universe_data.benchmarks.columns[0],
|
|
58
|
+
is_convert_to_str=False,
|
|
59
|
+
**saa_kwargs)
|
|
60
|
+
saa_perf_5y = qis.get_ra_perf_benchmark_columns(prices=period_5y.locate(saa_prices),
|
|
61
|
+
benchmark=self.universe_data.benchmarks.columns[0],
|
|
62
|
+
is_convert_to_str=False,
|
|
63
|
+
**saa_kwargs)
|
|
64
|
+
|
|
65
|
+
taa_prices = pd.concat([self.universe_data.benchmarks, self.universe_data.taa_prices], axis=1)
|
|
66
|
+
taa_perf_2y = qis.get_ra_perf_benchmark_columns(prices=period_2y.locate(taa_prices),
|
|
67
|
+
benchmark=self.universe_data.benchmarks.columns[0],
|
|
68
|
+
is_convert_to_str=False,
|
|
69
|
+
**taa_kwargs)
|
|
70
|
+
taa_perf_5y = qis.get_ra_perf_benchmark_columns(prices=period_5y.locate(taa_prices),
|
|
71
|
+
benchmark=self.universe_data.benchmarks.columns[0],
|
|
72
|
+
is_convert_to_str=False,
|
|
73
|
+
**taa_kwargs)
|
|
74
|
+
|
|
75
|
+
# betas
|
|
76
|
+
taa_betas = self.taa_rolling_covar_data.asset_last_betas_t[self.taa_valuation_date].T.loc[taa_df.index]
|
|
77
|
+
saa_betas = self.taa_rolling_covar_data.asset_last_betas_t[self.saa_valuation_date].T.loc[saa_df.index]
|
|
78
|
+
|
|
79
|
+
# taa r2
|
|
80
|
+
taa_df['r2'] = self.taa_rolling_covar_data.r2_pd[taa_df.index].iloc[-1, :]
|
|
81
|
+
|
|
82
|
+
# add betas
|
|
83
|
+
taa_df = pd.concat([taa_df, taa_betas], axis=1)
|
|
84
|
+
|
|
85
|
+
# taa vols
|
|
86
|
+
ewma_vol = qis.compute_ewm_vol(data=qis.to_returns(prices=taa_prices, is_log_returns=True),
|
|
87
|
+
mean_adj_type=qis.MeanAdjType.EWMA, span=24, annualization_factor=12)
|
|
88
|
+
taa_df['lasso-vol'] = np.sqrt(np.diag(self.taa_covar)) # todo
|
|
89
|
+
taa_df['ewm-vol'] = ewma_vol.iloc[-1, :]
|
|
90
|
+
taa_df['vol 2y'] = taa_perf_2y['Vol'].loc[taa_df.index]
|
|
91
|
+
|
|
92
|
+
# merge with universe taa data
|
|
93
|
+
taa_universe_df = self.universe_data.taa_universe_df.copy()
|
|
94
|
+
if 'Current Max' in taa_universe_df.columns: # remove level 2 attributions
|
|
95
|
+
col_index = taa_universe_df.columns.get_loc('Current Max')
|
|
96
|
+
columns_to_keep = taa_universe_df.columns[:col_index + 1]
|
|
97
|
+
taa_universe_df = taa_universe_df[columns_to_keep]
|
|
98
|
+
|
|
99
|
+
taa_df = pd.concat([taa_universe_df, taa_df, ], axis=1)
|
|
100
|
+
# saa r2 and vols
|
|
101
|
+
saa_df['r2'] = self.taa_rolling_covar_data.r2_pd[saa_df.index].iloc[-1, :]
|
|
102
|
+
saa_df['lasso-vol'] = np.sqrt(np.diag(self.saa_covar))
|
|
103
|
+
saa_df['vol 5y'] = saa_perf_5y['Vol'].loc[saa_df.index]
|
|
104
|
+
|
|
105
|
+
data = dict(taa_df=taa_df,
|
|
106
|
+
saa_df=saa_df,
|
|
107
|
+
taa_perf_2y=taa_perf_2y,
|
|
108
|
+
taa_perf_5y=taa_perf_5y,
|
|
109
|
+
saa_perf_2y=saa_perf_2y,
|
|
110
|
+
saa_perf_5y=saa_perf_5y,
|
|
111
|
+
taa_corr=self.taa_corr,
|
|
112
|
+
saa_corr=self.saa_corr,
|
|
113
|
+
taa_betas=taa_betas,
|
|
114
|
+
saa_betas=saa_betas)
|
|
115
|
+
return data
|
|
116
|
+
|
|
117
|
+
def plot_taa_corr(self, **kwargs) -> plt.Subplot:
|
|
118
|
+
df = self.taa_corr
|
|
119
|
+
with sns.axes_style('darkgrid'):
|
|
120
|
+
width, height = qis.get_df_table_size(df=df)
|
|
121
|
+
fig, ax = plt.subplots(1, 1, figsize=(width, width), constrained_layout=True)
|
|
122
|
+
qis.plot_heatmap(df=df,
|
|
123
|
+
var_format='{:.2f}',
|
|
124
|
+
cmap='PiYG',
|
|
125
|
+
ax=ax,
|
|
126
|
+
**kwargs)
|
|
127
|
+
return fig
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def run_current_saa_portfolio(universe_data: MacUniverseData,
|
|
131
|
+
covar_estimator: CovarEstimator,
|
|
132
|
+
saa_pd_covar: pd.DataFrame = None,
|
|
133
|
+
saa_valuation_date: pd.Timestamp = pd.Timestamp('31Dec2024'),
|
|
134
|
+
saa_rebalancing_indicators: pd.Series = None # for PE
|
|
135
|
+
) -> Tuple[pd.DataFrame, pd.DataFrame, Optional[EstimatedCurrentCovarData]]:
|
|
136
|
+
"""
|
|
137
|
+
use QE or YE for saa_rebalancing_freq
|
|
138
|
+
"""
|
|
139
|
+
if saa_pd_covar is None:
|
|
140
|
+
saa_covar_data = covar_estimator.fit_current_covars(
|
|
141
|
+
risk_factor_prices=universe_data.get_risk_factors().loc[:saa_valuation_date, :],
|
|
142
|
+
prices=universe_data.get_joint_prices().loc[:saa_valuation_date, :])
|
|
143
|
+
saa_pd_covar = saa_covar_data.y_covar
|
|
144
|
+
else:
|
|
145
|
+
saa_covar_data = None
|
|
146
|
+
|
|
147
|
+
saa_outputs = wrapper_risk_budgeting(pd_covar=saa_pd_covar,
|
|
148
|
+
constraints0=universe_data.get_saa_constraints(),
|
|
149
|
+
weights_0=None,
|
|
150
|
+
risk_budget=universe_data.get_saa_risk_budget(),
|
|
151
|
+
rebalancing_indicators=saa_rebalancing_indicators,
|
|
152
|
+
apply_total_to_good_ratio=False,
|
|
153
|
+
detailed_output=True)
|
|
154
|
+
return saa_outputs, saa_pd_covar, saa_covar_data
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def run_current_saa_taa_portfolios(universe_data: MacUniverseData,
|
|
158
|
+
covar_estimator: CovarEstimator,
|
|
159
|
+
saa_valuation_date: pd.Timestamp = pd.Timestamp('31Dec2024'),
|
|
160
|
+
taa_valuation_date: pd.Timestamp = pd.Timestamp('28Feb2024'),
|
|
161
|
+
time_period: qis.TimePeriod = qis.TimePeriod('31Dec2003', None),
|
|
162
|
+
saa_rebalancing_freq: str = 'QE',
|
|
163
|
+
taa_weights_0: pd.Series = None,
|
|
164
|
+
is_joint_saa_taa_covar: bool = True,
|
|
165
|
+
taa_rebalancing_indicators: pd.Series = None,
|
|
166
|
+
global_tracking_err_vol_constraint: Optional[float] = None,
|
|
167
|
+
group_tracking_err_vol_constraint: Optional[pd.Series] = None,
|
|
168
|
+
global_max_turnover_constraint: float = None,
|
|
169
|
+
group_max_turnover_constraint: Optional[pd.Series] = None,
|
|
170
|
+
is_saa_benchmark_for_betas: bool = True,
|
|
171
|
+
use_current_min_max: bool = True
|
|
172
|
+
) -> SaaTaaPortfolios:
|
|
173
|
+
"""
|
|
174
|
+
optimisation of the current saa_taa portfolio
|
|
175
|
+
taa_weights_0 are provided in universe_data
|
|
176
|
+
taa_weights_0 = universe_data.get_taa_current_weights()
|
|
177
|
+
"""
|
|
178
|
+
# 1. estimate rolling covar for taa and betas
|
|
179
|
+
# we need betas time series to estiate alphas
|
|
180
|
+
risk_factor_prices = universe_data.get_risk_factors().loc[:taa_valuation_date, :]
|
|
181
|
+
taa_rolling_covar_data = covar_estimator.fit_rolling_covars(risk_factor_prices=risk_factor_prices,
|
|
182
|
+
prices=universe_data.get_joint_prices().loc[:taa_valuation_date, :],
|
|
183
|
+
time_period=time_period)
|
|
184
|
+
if is_joint_saa_taa_covar:
|
|
185
|
+
saa_taa_covar = taa_rolling_covar_data.y_covars
|
|
186
|
+
if saa_valuation_date not in saa_taa_covar.keys():
|
|
187
|
+
raise KeyError(f"{saa_valuation_date} not in {saa_taa_covar.keys()}")
|
|
188
|
+
saa_assets = universe_data.saa_prices.columns
|
|
189
|
+
saa_pd_covar = saa_taa_covar[saa_valuation_date].loc[saa_assets, saa_assets]
|
|
190
|
+
else:
|
|
191
|
+
raise NotImplementedError
|
|
192
|
+
|
|
193
|
+
# construct saa portfolio: we need saa portfolio weights for benchmark calculation and low beta characteristics
|
|
194
|
+
saa_rebalancing_indicators = qis.create_rebalancing_indicators_from_freqs(rebalancing_freqs=saa_rebalancing_freq,
|
|
195
|
+
time_period=time_period,
|
|
196
|
+
tickers=universe_data.saa_prices.columns.to_list())
|
|
197
|
+
saa_rolling_weights, saa_portfolio_data = backtest_saa_risk_budget_portfolio(universe_data=universe_data,
|
|
198
|
+
saa_taa_covar=saa_taa_covar,
|
|
199
|
+
time_period=time_period,
|
|
200
|
+
covar_estimator=covar_estimator,
|
|
201
|
+
saa_rebalancing_freq=saa_rebalancing_freq,
|
|
202
|
+
management_fee=0.0)
|
|
203
|
+
# to do: use saa_rolling_weights
|
|
204
|
+
saa_df, saa_pd_covar, saa_current_covar_data = run_current_saa_portfolio(universe_data=universe_data,
|
|
205
|
+
covar_estimator=covar_estimator,
|
|
206
|
+
saa_pd_covar=saa_pd_covar,
|
|
207
|
+
saa_valuation_date=saa_valuation_date,
|
|
208
|
+
saa_rebalancing_indicators=saa_rebalancing_indicators.loc[saa_valuation_date, :])
|
|
209
|
+
rebalancing_freq = universe_data.get_joint_rebalancing_freqs()
|
|
210
|
+
|
|
211
|
+
current_saa_weights = saa_df['weights']
|
|
212
|
+
saa_df = saa_df.rename({'weights': 'SAA weight'}, axis=1)
|
|
213
|
+
|
|
214
|
+
# 2. compute alphas
|
|
215
|
+
if is_saa_benchmark_for_betas:
|
|
216
|
+
benchmark_price = saa_portfolio_data.get_portfolio_nav()
|
|
217
|
+
else:
|
|
218
|
+
benchmark_price = universe_data.benchmarks.iloc[:, 0]
|
|
219
|
+
|
|
220
|
+
joint_alphas = compute_joint_alphas(prices=universe_data.taa_prices,
|
|
221
|
+
benchmark_price=benchmark_price,
|
|
222
|
+
risk_factors_prices=universe_data.get_risk_factors(),
|
|
223
|
+
alpha_beta_type=universe_data.get_alpha_beta_type(),
|
|
224
|
+
rebalancing_freq=rebalancing_freq,
|
|
225
|
+
estimated_betas=taa_rolling_covar_data.asset_last_betas_t,
|
|
226
|
+
group_data_alphas=universe_data.get_taa_asset_class_data(is_merge_alts_with_equity=True),
|
|
227
|
+
return_annualisation_freq_dict=universe_data.return_annualisation_freq_dict)
|
|
228
|
+
|
|
229
|
+
# 3. run tre portfolio
|
|
230
|
+
if taa_weights_0 is None:
|
|
231
|
+
taa_weights_0 = universe_data.get_taa_current_weights()
|
|
232
|
+
taa_constraints = universe_data.get_taa_constraints(use_current_min_max=use_current_min_max,
|
|
233
|
+
global_tracking_err_vol_constraint=global_tracking_err_vol_constraint,
|
|
234
|
+
group_tracking_err_vol_constraint=group_tracking_err_vol_constraint,
|
|
235
|
+
global_max_turnover_constraint=global_max_turnover_constraint,
|
|
236
|
+
group_max_turnover_constraint=group_max_turnover_constraint)
|
|
237
|
+
|
|
238
|
+
# extend alphas and weights
|
|
239
|
+
taa_assets = universe_data.taa_prices.columns.to_list()
|
|
240
|
+
taa_covar = taa_rolling_covar_data.y_covars[taa_valuation_date].loc[taa_assets, taa_assets]
|
|
241
|
+
if taa_rebalancing_indicators is not None:
|
|
242
|
+
rebalancing_indicators = taa_rebalancing_indicators.reindex(index=taa_assets).fillna(0)
|
|
243
|
+
else:
|
|
244
|
+
rebalancing_indicators = pd.Series(1, index=taa_assets)
|
|
245
|
+
current_taa_weights = wrapper_maximise_alpha_over_tre(pd_covar=taa_covar,
|
|
246
|
+
alphas=joint_alphas.alpha_scores.loc[taa_valuation_date, :],
|
|
247
|
+
constraints0=taa_constraints,
|
|
248
|
+
benchmark_weights=current_saa_weights,
|
|
249
|
+
weights_0=taa_weights_0,
|
|
250
|
+
rebalancing_indicators=rebalancing_indicators,
|
|
251
|
+
apply_total_to_good_ratio=False,
|
|
252
|
+
detailed_output=True)
|
|
253
|
+
|
|
254
|
+
taa_weights = current_taa_weights['weights'].loc[taa_assets].rename('Taa Weights')
|
|
255
|
+
# do few round rounding to converge to weights with 2 decimals
|
|
256
|
+
for n in np.arange(5):
|
|
257
|
+
taa_weights = taa_weights / np.nansum(taa_weights)
|
|
258
|
+
taa_weights = taa_weights.round(decimals=4)
|
|
259
|
+
|
|
260
|
+
if taa_weights_0 is not None:
|
|
261
|
+
taa_weights0 = taa_weights_0.loc[universe_data.taa_prices.columns].rename('Given Taa Weights')
|
|
262
|
+
else:
|
|
263
|
+
taa_weights0 = pd.Series(0.0, index=universe_data.taa_prices.columns).rename('Given Taa Weights')
|
|
264
|
+
|
|
265
|
+
taa_rebalancing_indicator = rebalancing_indicators.rename('Is Rebalanced')
|
|
266
|
+
delta = taa_weights.subtract(taa_weights0).rename('Delta weights')
|
|
267
|
+
alphas = joint_alphas.get_alphas_snapshot(date=taa_valuation_date)
|
|
268
|
+
risk_contribs = current_taa_weights['asset_rc_ratio'].loc[taa_assets].rename('Risk Contribution')
|
|
269
|
+
taa_df = pd.concat([taa_rebalancing_indicator, taa_weights0, taa_weights, delta, risk_contribs, alphas], axis=1)
|
|
270
|
+
saa_taa_portfolios = SaaTaaPortfolios(saa_valuation_date=saa_valuation_date,
|
|
271
|
+
taa_valuation_date=taa_valuation_date,
|
|
272
|
+
taa_df=taa_df,
|
|
273
|
+
saa_df=saa_df,
|
|
274
|
+
taa_covar=taa_covar,
|
|
275
|
+
saa_covar=saa_pd_covar,
|
|
276
|
+
universe_data=universe_data,
|
|
277
|
+
taa_rolling_covar_data=taa_rolling_covar_data,
|
|
278
|
+
saa_current_covar_data=saa_current_covar_data)
|
|
279
|
+
return saa_taa_portfolios
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|