qis 3.0.7__tar.gz → 3.0.9__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.0.7 → qis-3.0.9}/PKG-INFO +1 -1
- {qis-3.0.7 → qis-3.0.9}/pyproject.toml +1 -1
- {qis-3.0.7 → qis-3.0.9}/qis/plots/scatter.py +1 -1
- {qis-3.0.7 → qis-3.0.9}/qis/plots/time_series.py +20 -19
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/multi_portfolio_data.py +2 -1
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/brinson_attribution.py +1 -1
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_benchmark_factsheet.py +46 -12
- {qis-3.0.7 → qis-3.0.9}/LICENSE.txt +0 -0
- {qis-3.0.7 → qis-3.0.9}/README.md +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/best_returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/bond_futures_portfolio.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/bootstrap_analysis.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/boxplot_conditional_returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/btc_asset_corr.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/constant_notional.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/constant_weight_portfolios.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/core/perf_bbg_prices.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/core/price_plots.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/core/us_election.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/credit_spreads.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/credit_trackers.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/europe_futures.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/multi_assets.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/multi_strategy.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/pyblogs_reports.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/strategy.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/strategy_benchmark.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/generate_option_rolls.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/interpolation_infrequent_returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/leveraged_strategies.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/long_short.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/momentum_indices.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/oakmark_analysis.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/ohlc_vol_analysis.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/overnight_returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/perf_external_assets.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/perp_pricing.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/readme_performances.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/risk_return_frontier.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/rolling_performance.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/seasonality.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/sharpe_vs_sortino.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/simulate_quant_strats.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/test_ewm.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/test_scatter.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/try_pybloqs.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/universe_corrs.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_conditional_returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_spy_by_year.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_tenor_analysis.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/examples/vol_without_weekends.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/file_utils.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/local_path.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/README.md +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/auto_corr.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/corr_cov_matrix.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm_convolution.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm_factors.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm_winsor_outliers.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/pca.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/plot_correlations.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ra_returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/stats/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/stats/bootstrap.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/stats/ohlc_vol.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/stats/rolling_stats.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/models/stats/test_bootstrap.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/README.md +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/cond_regression.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/config.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/desc_table.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/fx_ops.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/perf_stats.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/regime_classifier.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/returns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/perfstats/timeseries_bfill.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/README.md +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/bars.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/boxplot.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/contour.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/data_timeseries.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/desc_table.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/drawdowns.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/perf_table.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/prices.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_class_table.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_data.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_pdf.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_scatter.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/returns_heatmap.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/returns_scatter.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/errorbar.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/heatmap.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/histogram.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/histplot2d.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/lineplot.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/pie.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/qqplot.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/econ_data_single.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/gantt_data_history.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/price_history.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/utils.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/stackplot.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/table.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/plots/utils.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/README.md +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/backtester.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/ewm_portfolio_risk.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/portfolio_data.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/config.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/multi_assets_factsheet.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/multi_strategy_factsheet.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_factsheet.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/strats/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/portfolio/strats/seasonal_strats.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/settings.yaml +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/sql_engine.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/test_data.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/README.md +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/__init__.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/dates.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_agg.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_cut.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_freq.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_groups.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_melt.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_ops.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_str.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_to_scores.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/df_to_weights.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/generic.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/np_ops.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/ols.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/sampling.py +0 -0
- {qis-3.0.7 → qis-3.0.9}/qis/utils/struct_ops.py +0 -0
{qis-3.0.7 → qis-3.0.9}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qis
|
3
|
-
Version: 3.0.
|
3
|
+
Version: 3.0.9
|
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
|
@@ -92,7 +92,7 @@ def plot_scatter(df: pd.DataFrame,
|
|
92
92
|
hue_ids = df[hue].unique()
|
93
93
|
for idx, hue_id in enumerate(hue_ids):
|
94
94
|
# estimate model equation
|
95
|
-
data_hue = df[df[hue] == hue_id].sort_values(by=x)
|
95
|
+
data_hue = df[df[hue] == hue_id].replace([np.inf, -np.inf], np.nan).dropna().sort_values(by=x)
|
96
96
|
x_ = data_hue[x].to_numpy()
|
97
97
|
y_ = data_hue[y].to_numpy()
|
98
98
|
x1 = qu.get_ols_x(x=x_, order=order, fit_intercept=fit_intercept)
|
@@ -124,25 +124,26 @@ def plot_time_series(df: Union[pd.Series, pd.DataFrame],
|
|
124
124
|
elif trend_line in [TrendLine.TREND_LINE, TrendLine.TREND_LINE_SHADOWS]:
|
125
125
|
for column, color in zip(columns, trend_line_colors):
|
126
126
|
y = data1[column].dropna()
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
127
|
+
if not y.empty:
|
128
|
+
x0 = y.first_valid_index()
|
129
|
+
x1 = y.index[-1]
|
130
|
+
y0 = y[x0]
|
131
|
+
y1 = y.iloc[-1]
|
132
|
+
x = [x0, x1]
|
133
|
+
y = [y0, y1]
|
134
|
+
ax.plot(x, y,
|
135
|
+
color=color,
|
136
|
+
linestyle='--',
|
137
|
+
transform=ax.transData,
|
138
|
+
linewidth=linewidth)
|
139
|
+
|
140
|
+
if trend_line == TrendLine.TREND_LINE_SHADOWS:
|
141
|
+
x_ = (data1.index - data1.index[0]).days
|
142
|
+
slope = (y1 - y0) / (x_[-1] - x_[0])
|
143
|
+
y_line = [slope * x + y0 for x in x_]
|
144
|
+
y = data1[column]
|
145
|
+
ax.fill_between(data1.index, y, y_line, where=y_line >= y,
|
146
|
+
facecolor=color, interpolate=True, alpha=0.2, lw=linewidth)
|
146
147
|
|
147
148
|
# add last labels
|
148
149
|
if last_label in [LastLabel.AVERAGE_VALUE, LastLabel.AVERAGE_VALUE_SORTED]:
|
@@ -1002,6 +1002,7 @@ class MultiPortfolioData:
|
|
1002
1002
|
regime_benchmark: str = None,
|
1003
1003
|
regime_params: BenchmarkReturnsQuantileRegimeSpecs = REGIME_PARAMS,
|
1004
1004
|
time_period: TimePeriod = None,
|
1005
|
+
title: Optional[str] = 'Tracking error',
|
1005
1006
|
var_format: str = '{:.2%}',
|
1006
1007
|
ax: plt.Subplot = None,
|
1007
1008
|
**kwargs
|
@@ -1012,7 +1013,7 @@ class MultiPortfolioData:
|
|
1012
1013
|
pts.plot_time_series(df=tre,
|
1013
1014
|
var_format=var_format,
|
1014
1015
|
legend_stats=pts.LegendStats.AVG_NONNAN_LAST,
|
1015
|
-
title=
|
1016
|
+
title=title,
|
1016
1017
|
ax=ax,
|
1017
1018
|
**kwargs)
|
1018
1019
|
if regime_benchmark is not None:
|
@@ -174,7 +174,7 @@ def plot_brinson_totals_table(totals_table: pd.DataFrame,
|
|
174
174
|
**kwargs
|
175
175
|
) -> Optional[plt.Figure]:
|
176
176
|
special_rows_colors = [(len(totals_table.index), 'steelblue')]
|
177
|
-
rows_edge_lines = [len(totals_table.
|
177
|
+
rows_edge_lines = [len(totals_table.index)-1] # line before totals
|
178
178
|
|
179
179
|
special_columns_colors = [(0, 'lightblue'),
|
180
180
|
(len(totals_table.columns), 'steelblue')]
|
@@ -513,6 +513,7 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
513
513
|
add_benchmarks_to_navs: bool = True,
|
514
514
|
figsize: Tuple[float, float] = (11.7, 8.3),
|
515
515
|
var_format: str = '{:.1%}',
|
516
|
+
add_titles: bool = True,
|
516
517
|
**kwargs
|
517
518
|
) -> Tuple[Dict[str, plt.Figure], Dict[str, pd.DataFrame]]:
|
518
519
|
"""
|
@@ -528,13 +529,17 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
528
529
|
# navs + ra table
|
529
530
|
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
530
531
|
figs['navs'] = fig
|
532
|
+
if add_titles:
|
533
|
+
title = f"Cumulative performance with background colors using bear/normal/bull "
|
534
|
+
f"regimes of {regime_benchmark} {regime_params.freq}-returns"
|
535
|
+
else:
|
536
|
+
title = None
|
531
537
|
multi_portfolio_data.plot_nav(regime_benchmark=regime_benchmark,
|
532
538
|
time_period=time_period,
|
533
539
|
perf_params=perf_params,
|
534
540
|
regime_params=regime_params,
|
535
541
|
add_benchmarks_to_navs=add_benchmarks_to_navs,
|
536
|
-
title=
|
537
|
-
f"regimes of {regime_benchmark} {regime_params.freq}-returns",
|
542
|
+
title=title,
|
538
543
|
ax=ax,
|
539
544
|
**kwargs)
|
540
545
|
|
@@ -567,9 +572,11 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
567
572
|
**weight_kwargs)
|
568
573
|
|
569
574
|
# plot strategy and benchmark weights by ac
|
570
|
-
kwargs = qis.update_kwargs(kwargs, dict(strategy_ticker=strategy_ticker,
|
575
|
+
kwargs = qis.update_kwargs(kwargs, dict(strategy_ticker=f"(B) {strategy_ticker}",
|
576
|
+
benchmark_ticker=f"(A) {benchmark_ticker}"))
|
571
577
|
fig, axs = plt.subplots(1, 2, figsize=figsize, tight_layout=True)
|
572
|
-
|
578
|
+
if add_titles:
|
579
|
+
qis.set_suptitle(fig, title=f"Time series of weights by asset classes")
|
573
580
|
figs['strategy_benchmark_weights_stack'] = fig
|
574
581
|
plot_exposures_strategy_vs_benchmark_stack(strategy_exposures=strategy_exposures_ac,
|
575
582
|
benchmark_exposures=benchmark_exposures_ac,
|
@@ -579,20 +586,24 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
579
586
|
|
580
587
|
# boxplot by subac
|
581
588
|
fig, axs = plt.subplots(1, 2, figsize=figsize, tight_layout=True)
|
582
|
-
|
589
|
+
if add_titles:
|
590
|
+
qis.set_suptitle(fig, title=f"Boxplot of weights")
|
583
591
|
figs['strategy_benchmark_weights_box'] = fig
|
584
592
|
plot_exposures_strategy_vs_benchmark_boxplot(strategy_exposures=strategy_exposures_ac,
|
585
593
|
benchmark_exposures=benchmark_exposures_ac,
|
586
594
|
ax=axs[0],
|
587
595
|
ylabel='Weights',
|
588
596
|
title='(A) Weights by asset classes',
|
597
|
+
hue_var_name='Asset Class',
|
589
598
|
var_format=var_format,
|
599
|
+
allow_negative=True,
|
590
600
|
**kwargs)
|
591
601
|
plot_exposures_strategy_vs_benchmark_boxplot(strategy_exposures=strategy_exposures_subac,
|
592
602
|
benchmark_exposures=benchmark_exposures_subac,
|
593
603
|
ax=axs[1],
|
594
604
|
ylabel='Weights',
|
595
605
|
title='(B) Weights by sub-asset classes',
|
606
|
+
hue_var_name='Sub-Asset Class',
|
596
607
|
var_format=var_format,
|
597
608
|
**kwargs)
|
598
609
|
# risk contributions
|
@@ -617,7 +628,8 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
617
628
|
|
618
629
|
# stack for ac
|
619
630
|
fig, axs = plt.subplots(1, 2, figsize=figsize, tight_layout=True)
|
620
|
-
|
631
|
+
if add_titles:
|
632
|
+
qis.set_suptitle(fig, title=f"Time Series of risk contributions by asset classes")
|
621
633
|
figs['time_series_risk_contrib'] = fig
|
622
634
|
plot_exposures_strategy_vs_benchmark_stack(strategy_exposures=strategy_risk_contributions_ac,
|
623
635
|
benchmark_exposures=benchmark_risk_contributions_ac,
|
@@ -627,13 +639,16 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
627
639
|
|
628
640
|
# box plots for subac
|
629
641
|
fig, axs = plt.subplots(1, 2, figsize=figsize, tight_layout=True)
|
630
|
-
|
642
|
+
if add_titles:
|
643
|
+
qis.set_suptitle(fig, title=f"Boxplot of risk contributions")
|
631
644
|
figs['risk_contributions_boxplot'] = fig
|
632
645
|
plot_exposures_strategy_vs_benchmark_boxplot(
|
633
646
|
strategy_exposures=strategy_risk_contributions_ac,
|
634
647
|
benchmark_exposures=benchmark_risk_contributions_ac,
|
635
648
|
ax=axs[0],
|
636
649
|
title='(A) Risk contributions by asset classes',
|
650
|
+
hue_var_name='Asset Class',
|
651
|
+
ylabel='Risk contributions',
|
637
652
|
var_format=var_format,
|
638
653
|
allow_negative=True,
|
639
654
|
**kwargs)
|
@@ -642,6 +657,8 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
642
657
|
benchmark_exposures=benchmark_risk_contributions_subac,
|
643
658
|
ax=axs[1],
|
644
659
|
title='(B) Risk contributions by sub-asset classes',
|
660
|
+
hue_var_name='Sub-Asset Class',
|
661
|
+
ylabel='Risk contributions',
|
645
662
|
var_format=var_format,
|
646
663
|
allow_negative=True,
|
647
664
|
**kwargs)
|
@@ -649,9 +666,15 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
649
666
|
# tracking error
|
650
667
|
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
651
668
|
figs['tre_time_series'] = fig
|
669
|
+
if add_titles:
|
670
|
+
title = 'Tracking Error'
|
671
|
+
else:
|
672
|
+
title = None
|
652
673
|
multi_portfolio_data.plot_tre_time_series(strategy_idx=strategy_idx,
|
653
674
|
benchmark_idx=benchmark_idx,
|
654
675
|
regime_benchmark=regime_benchmark,
|
676
|
+
regime_params=regime_params,
|
677
|
+
title=title,
|
655
678
|
ax=ax,
|
656
679
|
time_period=time_period,
|
657
680
|
**kwargs)
|
@@ -671,17 +694,25 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
671
694
|
|
672
695
|
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
673
696
|
figs['brinson_total_time_series'] = fig
|
697
|
+
if add_titles:
|
698
|
+
title = 'Active total return'
|
699
|
+
else:
|
700
|
+
title = None
|
674
701
|
qis.plot_time_series(df=active_total.cumsum(axis=0),
|
675
|
-
title=
|
702
|
+
title=title,
|
703
|
+
legend_stats=qis.LegendStats.LAST,
|
704
|
+
var_format='{:.0%}',
|
676
705
|
ax=ax, **kwargs)
|
677
706
|
if regime_benchmark is not None:
|
678
707
|
multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
|
679
|
-
index=
|
708
|
+
index=active_total.index, regime_params=regime_params)
|
680
709
|
|
681
710
|
fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
|
682
711
|
figs['brinson_grouped_allocation_return'] = fig
|
683
712
|
qis.plot_time_series(df=grouped_allocation_return.cumsum(axis=0),
|
684
713
|
title='Grouped allocation return',
|
714
|
+
legend_stats=qis.LegendStats.LAST,
|
715
|
+
var_format='{:.0%}',
|
685
716
|
ax=ax, **kwargs)
|
686
717
|
if regime_benchmark is not None:
|
687
718
|
multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
|
@@ -691,10 +722,12 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
691
722
|
figs['brinson_grouped_selection_return'] = fig
|
692
723
|
qis.plot_time_series(df=grouped_selection_return.cumsum(axis=0),
|
693
724
|
title='Grouped selection return',
|
725
|
+
legend_stats=qis.LegendStats.LAST,
|
726
|
+
var_format='{:.0%}',
|
694
727
|
ax=ax, **kwargs)
|
695
728
|
if regime_benchmark is not None:
|
696
729
|
multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
|
697
|
-
index=
|
730
|
+
index=grouped_selection_return.index, regime_params=regime_params)
|
698
731
|
|
699
732
|
# brinson by sub-asset class
|
700
733
|
totals_table, active_total, grouped_allocation_return, grouped_selection_return, grouped_interaction_return = \
|
@@ -715,6 +748,7 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
715
748
|
multi_portfolio_data.plot_turnover(ax=ax,
|
716
749
|
time_period=time_period,
|
717
750
|
regime_benchmark=regime_benchmark,
|
751
|
+
regime_params=regime_params,
|
718
752
|
#turnover_rolling_period=260,
|
719
753
|
#freq_turnover=None,
|
720
754
|
**kwargs)
|
@@ -744,7 +778,7 @@ def plot_exposures_long_short_groups(exposures_short: pd.DataFrame,
|
|
744
778
|
y_var_name=ylabel,
|
745
779
|
ylabel=ylabel,
|
746
780
|
showmedians=True,
|
747
|
-
add_y_median_labels=
|
781
|
+
add_y_median_labels=False,
|
748
782
|
yvar_format=var_format,
|
749
783
|
x_rotation=90,
|
750
784
|
colors=qis.get_n_sns_colors(n=len(exposures_long.columns)),
|
@@ -803,7 +837,7 @@ def plot_exposures_strategy_vs_benchmark_boxplot(strategy_exposures: pd.DataFram
|
|
803
837
|
y_var_name=ylabel,
|
804
838
|
ylabel=ylabel,
|
805
839
|
showmedians=True,
|
806
|
-
add_y_median_labels=
|
840
|
+
add_y_median_labels=False,
|
807
841
|
yvar_format=var_format,
|
808
842
|
x_rotation=90,
|
809
843
|
title=title,
|
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
|
File without changes
|