qis 3.2.8__tar.gz → 3.2.10__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.
- {qis-3.2.8 → qis-3.2.10}/PKG-INFO +1 -1
- {qis-3.2.8 → qis-3.2.10}/pyproject.toml +1 -1
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/multi_portfolio_data.py +55 -11
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/portfolio_data.py +9 -8
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/strategy_benchmark_factsheet.py +44 -21
- {qis-3.2.8 → qis-3.2.10}/LICENSE.txt +0 -0
- {qis-3.2.8 → qis-3.2.10}/README.md +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/best_returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/bootstrap_analysis.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/boxplot_conditional_returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/btc_asset_corr.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/constant_notional.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/constant_weight_portfolios.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/core/perf_bbg_prices.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/core/price_plots.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/core/us_election.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/credit_spreads.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/europe_futures.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/factsheets/multi_assets.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/factsheets/multi_strategy.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/factsheets/pyblogs_reports.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/factsheets/strategy.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/factsheets/strategy_benchmark.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/generate_option_rolls.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/interpolation_infrequent_returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/leveraged_strategies.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/long_short.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/momentum_indices.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/ohlc_vol_analysis.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/overnight_returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/perf_external_assets.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/readme_performances.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/risk_return_frontier.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/rolling_performance.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/seasonality.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/sharpe_vs_sortino.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/simulate_quant_strats.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/test_ewm.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/test_scatter.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/try_pybloqs.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/universe_corrs.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/vix_conditional_returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/vix_spy_by_year.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/vix_tenor_analysis.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/examples/vol_without_weekends.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/file_utils.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/local_path.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/README.md +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/auto_corr.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/corr_cov_matrix.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/ewm.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/ewm_convolution.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/ewm_factors.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/ewm_winsor_outliers.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/pca.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/plot_correlations.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/linear/ra_returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/stats/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/stats/bootstrap.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/stats/ohlc_vol.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/stats/rolling_stats.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/models/stats/test_bootstrap.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/README.md +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/cond_regression.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/config.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/desc_table.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/fx_ops.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/perf_stats.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/regime_classifier.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/returns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/perfstats/timeseries_bfill.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/README.md +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/bars.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/boxplot.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/contour.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/data_timeseries.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/desc_table.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/drawdowns.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/perf_table.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/prices.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/regime_class_table.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/regime_data.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/regime_pdf.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/regime_scatter.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/returns_heatmap.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/derived/returns_scatter.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/errorbar.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/heatmap.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/histogram.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/histplot2d.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/lineplot.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/pie.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/qqplot.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/reports/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/reports/econ_data_single.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/reports/gantt_data_history.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/reports/price_history.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/reports/utils.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/scatter.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/stackplot.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/table.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/time_series.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/plots/utils.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/README.md +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/backtester.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/ewm_portfolio_risk.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/brinson_attribution.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/config.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/multi_assets_factsheet.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/multi_strategy_factsheet.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/strategy_factsheet.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/signal_data.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/strats/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/portfolio/strats/seasonal_strats.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/settings.yaml +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/sql_engine.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/test_data.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/README.md +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/__init__.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/dates.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_agg.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_cut.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_freq.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_groups.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_melt.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_ops.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_str.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_to_scores.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/df_to_weights.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/generic.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/np_ops.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/ols.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/sampling.py +0 -0
- {qis-3.2.8 → qis-3.2.10}/qis/utils/struct_ops.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qis
|
3
|
-
Version: 3.2.
|
3
|
+
Version: 3.2.10
|
4
4
|
Summary: Implementation of visualisation and reporting analytics for Quantitative Investment Strategies
|
5
5
|
License: LICENSE.txt
|
6
6
|
Keywords: quantitative,investing,portfolio optimization,systematic strategies,volatility
|
@@ -192,8 +192,12 @@ class MultiPortfolioData:
|
|
192
192
|
|
193
193
|
def compute_tracking_error_implied_by_covar(self,
|
194
194
|
strategy_idx: int = 0,
|
195
|
-
benchmark_idx: int = 1
|
196
|
-
|
195
|
+
benchmark_idx: int = 1,
|
196
|
+
is_grouped: bool = False,
|
197
|
+
group_data: pd.Series = None,
|
198
|
+
group_order: List[str] = None,
|
199
|
+
total_column: Optional[str] = 'Total'
|
200
|
+
) -> Union[pd.Series, pd.DataFrame]:
|
197
201
|
"""
|
198
202
|
compute Ex ante tracking error =
|
199
203
|
(strategy_weights - strategy_weights) @ covar @ (strategy_weights - strategy_weights).T
|
@@ -208,11 +212,33 @@ class MultiPortfolioData:
|
|
208
212
|
benchmark_weights = benchmark_weights.reindex(index=covar_index, columns=investable_assets).ffill().fillna(0.0)
|
209
213
|
|
210
214
|
weight_diffs = benchmark_weights - strategy_weights
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
215
|
+
if not is_grouped:
|
216
|
+
tracking_error = {}
|
217
|
+
for date, pd_covar in self.covar_dict.items():
|
218
|
+
w = weight_diffs.loc[date]
|
219
|
+
tracking_error[date] = np.sqrt(w @ pd_covar @ w.T)
|
220
|
+
tracking_error = pd.Series(tracking_error, name='Tracking error')
|
221
|
+
else:
|
222
|
+
if group_data is None:
|
223
|
+
group_data = self.portfolio_datas[strategy_idx].group_data
|
224
|
+
if group_order is None:
|
225
|
+
group_order = self.portfolio_datas[strategy_idx].group_order
|
226
|
+
group_dict = dfg.get_group_dict(group_data=group_data,
|
227
|
+
group_order=group_order,
|
228
|
+
total_column=total_column)
|
229
|
+
tracking_error = {key: {} for key in group_dict.keys()}
|
230
|
+
for date, pd_covar in self.covar_dict.items():
|
231
|
+
w = weight_diffs.loc[date]
|
232
|
+
for key, tickers in group_dict.items():
|
233
|
+
w_g = w.loc[tickers]
|
234
|
+
pd_covar_g = pd_covar.loc[tickers, tickers]
|
235
|
+
tracking_error[key][date] = np.sqrt(w_g @ pd_covar_g @ w_g.T)
|
236
|
+
# merge
|
237
|
+
tracking_error_pd = {}
|
238
|
+
for key in group_dict.keys():
|
239
|
+
tracking_error_pd[key] = pd.Series(tracking_error[key], name=key)
|
240
|
+
tracking_error = pd.DataFrame.from_dict(tracking_error_pd, orient='columns')
|
241
|
+
|
216
242
|
return tracking_error
|
217
243
|
|
218
244
|
def compute_tracking_error_table(self,
|
@@ -620,7 +646,7 @@ class MultiPortfolioData:
|
|
620
646
|
**kwargs)
|
621
647
|
if regime_benchmark is not None:
|
622
648
|
self.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark, index=diff.index, regime_params=regime_params)
|
623
|
-
|
649
|
+
|
624
650
|
def get_turnover(self,
|
625
651
|
time_period: TimePeriod = None,
|
626
652
|
turnover_rolling_period: Optional[int] = 12,
|
@@ -637,7 +663,7 @@ class MultiPortfolioData:
|
|
637
663
|
if time_period is not None:
|
638
664
|
turnover = time_period.locate(turnover)
|
639
665
|
return turnover
|
640
|
-
|
666
|
+
|
641
667
|
def plot_turnover(self,
|
642
668
|
regime_benchmark: str = None,
|
643
669
|
time_period: TimePeriod = None,
|
@@ -648,7 +674,7 @@ class MultiPortfolioData:
|
|
648
674
|
is_unit_based_traded_volume: bool = True,
|
649
675
|
ax: plt.Subplot = None,
|
650
676
|
**kwargs) -> None:
|
651
|
-
|
677
|
+
|
652
678
|
turnover = self.get_turnover(turnover_rolling_period=turnover_rolling_period,
|
653
679
|
freq_turnover=freq_turnover,
|
654
680
|
is_unit_based_traded_volume=is_unit_based_traded_volume,
|
@@ -1007,21 +1033,39 @@ class MultiPortfolioData:
|
|
1007
1033
|
def plot_tre_time_series(self,
|
1008
1034
|
strategy_idx: int = 0,
|
1009
1035
|
benchmark_idx: int = 1,
|
1036
|
+
is_grouped: bool = False,
|
1037
|
+
group_data: pd.Series = None,
|
1038
|
+
group_order: List[str] = None,
|
1010
1039
|
regime_benchmark: str = None,
|
1011
1040
|
regime_params: BenchmarkReturnsQuantileRegimeSpecs = REGIME_PARAMS,
|
1012
1041
|
time_period: TimePeriod = None,
|
1013
1042
|
title: Optional[str] = 'Tracking error',
|
1043
|
+
total_column: Optional[str] = 'Total',
|
1014
1044
|
var_format: str = '{:.2%}',
|
1045
|
+
tre_max_clip: Optional[float] = None,
|
1015
1046
|
ax: plt.Subplot = None,
|
1016
1047
|
**kwargs
|
1017
1048
|
) -> None:
|
1018
|
-
tre = self.compute_tracking_error_implied_by_covar(strategy_idx=strategy_idx, benchmark_idx=benchmark_idx
|
1049
|
+
tre = self.compute_tracking_error_implied_by_covar(strategy_idx=strategy_idx, benchmark_idx=benchmark_idx,
|
1050
|
+
is_grouped=is_grouped, group_data=group_data,
|
1051
|
+
group_order=group_order,
|
1052
|
+
total_column=total_column)
|
1053
|
+
if tre_max_clip is not None:
|
1054
|
+
if isinstance(tre, pd.DataFrame): # skip total_column from trimming
|
1055
|
+
tre_columns = tre.columns.to_list()
|
1056
|
+
if total_column in tre:
|
1057
|
+
tre_columns.remove(total_column)
|
1058
|
+
tre[tre_columns] = tre[tre_columns].clip(upper=tre_max_clip)
|
1059
|
+
else:
|
1060
|
+
tre = tre.clip(upper=tre_max_clip)
|
1061
|
+
|
1019
1062
|
if time_period is not None:
|
1020
1063
|
tre = time_period.locate(tre)
|
1021
1064
|
pts.plot_time_series(df=tre,
|
1022
1065
|
var_format=var_format,
|
1023
1066
|
legend_stats=pts.LegendStats.AVG_NONNAN_LAST,
|
1024
1067
|
title=title,
|
1068
|
+
y_limits=(0.0, None),
|
1025
1069
|
ax=ax,
|
1026
1070
|
**kwargs)
|
1027
1071
|
if regime_benchmark is not None:
|
@@ -1484,10 +1484,10 @@ class PortfolioData:
|
|
1484
1484
|
group_data: pd.Series = None,
|
1485
1485
|
group_order: List[str] = None,
|
1486
1486
|
time_period: TimePeriod = None,
|
1487
|
-
|
1487
|
+
turnover_rolling_period: Optional[int] = 260,
|
1488
|
+
freq_turnover: Optional[str] = 'B',
|
1488
1489
|
add_total: bool = True,
|
1489
1490
|
title: str = None,
|
1490
|
-
freq: Optional[str] = None,
|
1491
1491
|
regime_params: BenchmarkReturnsQuantileRegimeSpecs = None,
|
1492
1492
|
ax: plt.Subplot = None,
|
1493
1493
|
**kwargs
|
@@ -1497,19 +1497,20 @@ class PortfolioData:
|
|
1497
1497
|
group_data=group_data,
|
1498
1498
|
group_order=group_order,
|
1499
1499
|
time_period=time_period,
|
1500
|
-
roll_period=
|
1500
|
+
roll_period=turnover_rolling_period,
|
1501
1501
|
add_total=add_total,
|
1502
|
-
freq=
|
1502
|
+
freq=freq_turnover,
|
1503
1503
|
**kwargs)
|
1504
|
-
|
1504
|
+
freq = pd.infer_freq(turnover.index)
|
1505
|
+
turnover_title = title or f"{turnover_rolling_period}-period rolling {freq}-freq Turnover"
|
1505
1506
|
qis.plot_time_series(df=turnover,
|
1506
|
-
var_format='{:,.
|
1507
|
-
|
1507
|
+
var_format='{:,.1%}',
|
1508
|
+
y_limits=(0.0, None),
|
1508
1509
|
legend_stats=qis.LegendStats.AVG_NONNAN_LAST,
|
1509
1510
|
title=turnover_title,
|
1510
1511
|
ax=ax,
|
1511
1512
|
**kwargs)
|
1512
|
-
if regime_benchmark is not None:
|
1513
|
+
if regime_benchmark is not None and self.benchmark_prices is not None:
|
1513
1514
|
self.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark, index=turnover.index,
|
1514
1515
|
regime_params=regime_params)
|
1515
1516
|
|
@@ -513,6 +513,7 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
513
513
|
perf_params: PerfParams = PERF_PARAMS,
|
514
514
|
regime_params: BenchmarkReturnsQuantileRegimeSpecs = REGIME_PARAMS,
|
515
515
|
add_benchmarks_to_navs: bool = True,
|
516
|
+
tre_max_clip: Optional[float] = None,
|
516
517
|
figsize: Tuple[float, float] = (11.7, 8.3),
|
517
518
|
var_format: str = '{:.1%}',
|
518
519
|
add_titles: bool = True,
|
@@ -665,22 +666,6 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
665
666
|
allow_negative=True,
|
666
667
|
**kwargs)
|
667
668
|
|
668
|
-
# tracking error
|
669
|
-
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
670
|
-
figs['tre_time_series'] = fig
|
671
|
-
if add_titles:
|
672
|
-
title = 'Tracking Error'
|
673
|
-
else:
|
674
|
-
title = None
|
675
|
-
multi_portfolio_data.plot_tre_time_series(strategy_idx=strategy_idx,
|
676
|
-
benchmark_idx=benchmark_idx,
|
677
|
-
regime_benchmark=regime_benchmark,
|
678
|
-
regime_params=regime_params,
|
679
|
-
title=title,
|
680
|
-
ax=ax,
|
681
|
-
time_period=time_period,
|
682
|
-
**kwargs)
|
683
|
-
|
684
669
|
# brinson by asset class
|
685
670
|
totals_table, active_total, grouped_allocation_return, grouped_selection_return, grouped_interaction_return = \
|
686
671
|
multi_portfolio_data.compute_brinson_attribution(strategy_idx=strategy_idx,
|
@@ -744,6 +729,42 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
744
729
|
figs['brinson_table_subac'] = qis.plot_brinson_totals_table(totals_table=totals_table, **kwargs)
|
745
730
|
dfs['brinson_table_subac'] = totals_table
|
746
731
|
|
732
|
+
# tracking error
|
733
|
+
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
734
|
+
figs['tre_time_series'] = fig
|
735
|
+
if add_titles:
|
736
|
+
title = 'Tracking Error'
|
737
|
+
else:
|
738
|
+
title = None
|
739
|
+
multi_portfolio_data.plot_tre_time_series(strategy_idx=strategy_idx,
|
740
|
+
benchmark_idx=benchmark_idx,
|
741
|
+
regime_benchmark=regime_benchmark,
|
742
|
+
regime_params=regime_params,
|
743
|
+
title=title,
|
744
|
+
ax=ax,
|
745
|
+
time_period=time_period,
|
746
|
+
**kwargs)
|
747
|
+
|
748
|
+
# group tracking error
|
749
|
+
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
750
|
+
figs['tre_group_time_series'] = fig
|
751
|
+
if add_titles:
|
752
|
+
title = 'Asset Class Tracking Error'
|
753
|
+
else:
|
754
|
+
title = None
|
755
|
+
multi_portfolio_data.plot_tre_time_series(strategy_idx=strategy_idx,
|
756
|
+
benchmark_idx=benchmark_idx,
|
757
|
+
is_grouped=True,
|
758
|
+
group_data=ac_group_data,
|
759
|
+
group_order=ac_group_order,
|
760
|
+
regime_benchmark=regime_benchmark,
|
761
|
+
regime_params=regime_params,
|
762
|
+
tre_max_clip=tre_max_clip,
|
763
|
+
title=title,
|
764
|
+
ax=ax,
|
765
|
+
time_period=time_period,
|
766
|
+
**kwargs)
|
767
|
+
|
747
768
|
# turnover
|
748
769
|
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
749
770
|
figs['joint_turnover'] = fig
|
@@ -751,9 +772,9 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
751
772
|
time_period=time_period,
|
752
773
|
regime_benchmark=regime_benchmark,
|
753
774
|
regime_params=regime_params,
|
754
|
-
#turnover_rolling_period=260,
|
755
|
-
#freq_turnover=None,
|
756
775
|
**kwargs)
|
776
|
+
if not add_titles:
|
777
|
+
ax.title.set_visible(False)
|
757
778
|
# group turnover
|
758
779
|
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
759
780
|
figs['group_turnover'] = fig
|
@@ -765,10 +786,12 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
765
786
|
group_data=turnover_groups,
|
766
787
|
group_order=turnover_order,
|
767
788
|
add_total=False,
|
768
|
-
#turnover_rolling_period=260,
|
769
|
-
#freq_turnover=None,
|
770
789
|
**kwargs)
|
771
|
-
|
790
|
+
if regime_benchmark is not None:
|
791
|
+
multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
|
792
|
+
index=grouped_selection_return.index, regime_params=regime_params)
|
793
|
+
if not add_titles:
|
794
|
+
ax.title.set_visible(False)
|
772
795
|
return figs, dfs
|
773
796
|
|
774
797
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|