qis 3.2.9__tar.gz → 3.2.11__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.9 → qis-3.2.11}/PKG-INFO +1 -1
- {qis-3.2.9 → qis-3.2.11}/pyproject.toml +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/multi_assets.py +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/plots/lineplot.py +31 -4
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/multi_portfolio_data.py +19 -6
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/portfolio_data.py +2 -2
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/multi_assets_factsheet.py +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/multi_strategy_factsheet.py +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_benchmark_factsheet.py +6 -1
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_factsheet.py +1 -1
- {qis-3.2.9 → qis-3.2.11}/qis/settings.yaml +0 -1
- {qis-3.2.9 → qis-3.2.11}/qis/utils/dates.py +5 -2
- {qis-3.2.9 → qis-3.2.11}/LICENSE.txt +0 -0
- {qis-3.2.9 → qis-3.2.11}/README.md +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/best_returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/bootstrap_analysis.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/boxplot_conditional_returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/btc_asset_corr.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/constant_notional.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/constant_weight_portfolios.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/core/perf_bbg_prices.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/core/price_plots.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/core/us_election.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/credit_spreads.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/europe_futures.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/multi_strategy.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/pyblogs_reports.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/strategy.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/strategy_benchmark.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/generate_option_rolls.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/interpolation_infrequent_returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/leveraged_strategies.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/long_short.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/momentum_indices.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/ohlc_vol_analysis.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/overnight_returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/perf_external_assets.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/readme_performances.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/risk_return_frontier.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/rolling_performance.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/seasonality.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/sharpe_vs_sortino.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/simulate_quant_strats.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/test_ewm.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/test_scatter.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/try_pybloqs.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/universe_corrs.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_conditional_returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_spy_by_year.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_tenor_analysis.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/examples/vol_without_weekends.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/file_utils.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/local_path.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/README.md +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/auto_corr.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/corr_cov_matrix.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm_convolution.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm_factors.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm_winsor_outliers.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/pca.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/plot_correlations.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ra_returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/stats/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/stats/bootstrap.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/stats/ohlc_vol.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/stats/rolling_stats.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/models/stats/test_bootstrap.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/README.md +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/cond_regression.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/config.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/desc_table.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/fx_ops.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/perf_stats.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/regime_classifier.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/returns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/perfstats/timeseries_bfill.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/README.md +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/bars.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/boxplot.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/contour.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/data_timeseries.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/desc_table.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/drawdowns.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/perf_table.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/prices.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_class_table.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_data.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_pdf.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_scatter.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/returns_heatmap.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/returns_scatter.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/errorbar.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/heatmap.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/histogram.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/histplot2d.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/pie.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/qqplot.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/econ_data_single.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/gantt_data_history.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/price_history.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/utils.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/scatter.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/stackplot.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/table.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/time_series.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/plots/utils.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/README.md +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/backtester.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/ewm_portfolio_risk.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/brinson_attribution.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/config.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/signal_data.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/strats/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/portfolio/strats/seasonal_strats.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/sql_engine.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/test_data.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/README.md +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/__init__.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_agg.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_cut.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_freq.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_groups.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_melt.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_ops.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_str.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_to_scores.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/df_to_weights.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/generic.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/np_ops.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/ols.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/qis/utils/sampling.py +0 -0
- {qis-3.2.9 → qis-3.2.11}/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.11
|
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
|
@@ -15,6 +15,9 @@ import qis.plots.utils as put
|
|
15
15
|
|
16
16
|
|
17
17
|
def plot_line(df: Union[pd.Series, pd.DataFrame],
|
18
|
+
x: str = None,
|
19
|
+
y: str = None,
|
20
|
+
hue: str = None,
|
18
21
|
linestyles: List[str] = None,
|
19
22
|
linestyle: Any = '-',
|
20
23
|
linewidth: float = 1.0,
|
@@ -37,7 +40,13 @@ def plot_line(df: Union[pd.Series, pd.DataFrame],
|
|
37
40
|
ax: plt.Subplot = None,
|
38
41
|
**kwargs
|
39
42
|
) -> Optional[plt.Figure]:
|
40
|
-
|
43
|
+
"""
|
44
|
+
line plot wrapper for sns, lineplot
|
45
|
+
plot df using index
|
46
|
+
x: str = None: x column
|
47
|
+
y: str = None: y column
|
48
|
+
hue: str = None: hue
|
49
|
+
"""
|
41
50
|
if isinstance(df, pd.DataFrame):
|
42
51
|
pass
|
43
52
|
elif isinstance(df, pd.Series):
|
@@ -45,22 +54,40 @@ def plot_line(df: Union[pd.Series, pd.DataFrame],
|
|
45
54
|
else:
|
46
55
|
raise TypeError(f"unsuported data type {type(df)}")
|
47
56
|
|
57
|
+
if x is not None:
|
58
|
+
if y is None:
|
59
|
+
raise ValueError(f"y column must be given with x column")
|
60
|
+
else:
|
61
|
+
if hue is not None:
|
62
|
+
df = df[[x, y, hue]]
|
63
|
+
else:
|
64
|
+
df = df[[x, y]]
|
65
|
+
|
48
66
|
if ax is None:
|
49
67
|
fig, ax = plt.subplots()
|
50
68
|
else:
|
51
69
|
fig = None
|
52
70
|
|
53
71
|
if colors is None:
|
54
|
-
|
72
|
+
if hue is None:
|
73
|
+
colors = put.get_n_colors(n=len(df.columns), **kwargs)
|
74
|
+
else:
|
75
|
+
colors = put.get_n_colors(n=len(df[hue].unique()), **kwargs)
|
55
76
|
|
56
|
-
sns.lineplot(data=df,
|
77
|
+
sns.lineplot(data=df, x=x, y=y, hue=hue,
|
78
|
+
palette=colors, dashes=False, markers=markers, linestyle=linestyle, linewidth=linewidth,
|
79
|
+
style=hue,
|
80
|
+
ax=ax)
|
57
81
|
|
58
82
|
if title is not None:
|
59
83
|
put.set_title(ax=ax, title=title, fontsize=fontsize, **kwargs)
|
60
84
|
|
61
85
|
if legend_loc is not None:
|
62
86
|
if legend_labels is None:
|
63
|
-
|
87
|
+
if hue is None:
|
88
|
+
legend_labels = put.get_legend_lines(data=df, legend_stats=legend_stats, var_format=yvar_format)
|
89
|
+
else:
|
90
|
+
h, legend_labels = ax.get_legend_handles_labels()
|
64
91
|
put.set_legend(ax=ax,
|
65
92
|
labels=legend_labels,
|
66
93
|
colors=colors,
|
@@ -195,7 +195,8 @@ class MultiPortfolioData:
|
|
195
195
|
benchmark_idx: int = 1,
|
196
196
|
is_grouped: bool = False,
|
197
197
|
group_data: pd.Series = None,
|
198
|
-
group_order: List[str] = None
|
198
|
+
group_order: List[str] = None,
|
199
|
+
total_column: Optional[str] = 'Total'
|
199
200
|
) -> Union[pd.Series, pd.DataFrame]:
|
200
201
|
"""
|
201
202
|
compute Ex ante tracking error =
|
@@ -224,7 +225,7 @@ class MultiPortfolioData:
|
|
224
225
|
group_order = self.portfolio_datas[strategy_idx].group_order
|
225
226
|
group_dict = dfg.get_group_dict(group_data=group_data,
|
226
227
|
group_order=group_order,
|
227
|
-
total_column=
|
228
|
+
total_column=total_column)
|
228
229
|
tracking_error = {key: {} for key in group_dict.keys()}
|
229
230
|
for date, pd_covar in self.covar_dict.items():
|
230
231
|
w = weight_diffs.loc[date]
|
@@ -645,7 +646,7 @@ class MultiPortfolioData:
|
|
645
646
|
**kwargs)
|
646
647
|
if regime_benchmark is not None:
|
647
648
|
self.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark, index=diff.index, regime_params=regime_params)
|
648
|
-
|
649
|
+
|
649
650
|
def get_turnover(self,
|
650
651
|
time_period: TimePeriod = None,
|
651
652
|
turnover_rolling_period: Optional[int] = 12,
|
@@ -662,7 +663,7 @@ class MultiPortfolioData:
|
|
662
663
|
if time_period is not None:
|
663
664
|
turnover = time_period.locate(turnover)
|
664
665
|
return turnover
|
665
|
-
|
666
|
+
|
666
667
|
def plot_turnover(self,
|
667
668
|
regime_benchmark: str = None,
|
668
669
|
time_period: TimePeriod = None,
|
@@ -673,7 +674,7 @@ class MultiPortfolioData:
|
|
673
674
|
is_unit_based_traded_volume: bool = True,
|
674
675
|
ax: plt.Subplot = None,
|
675
676
|
**kwargs) -> None:
|
676
|
-
|
677
|
+
|
677
678
|
turnover = self.get_turnover(turnover_rolling_period=turnover_rolling_period,
|
678
679
|
freq_turnover=freq_turnover,
|
679
680
|
is_unit_based_traded_volume=is_unit_based_traded_volume,
|
@@ -1039,13 +1040,25 @@ class MultiPortfolioData:
|
|
1039
1040
|
regime_params: BenchmarkReturnsQuantileRegimeSpecs = REGIME_PARAMS,
|
1040
1041
|
time_period: TimePeriod = None,
|
1041
1042
|
title: Optional[str] = 'Tracking error',
|
1043
|
+
total_column: Optional[str] = 'Total',
|
1042
1044
|
var_format: str = '{:.2%}',
|
1045
|
+
tre_max_clip: Optional[float] = None,
|
1043
1046
|
ax: plt.Subplot = None,
|
1044
1047
|
**kwargs
|
1045
1048
|
) -> None:
|
1046
1049
|
tre = self.compute_tracking_error_implied_by_covar(strategy_idx=strategy_idx, benchmark_idx=benchmark_idx,
|
1047
1050
|
is_grouped=is_grouped, group_data=group_data,
|
1048
|
-
group_order=group_order
|
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
|
+
|
1049
1062
|
if time_period is not None:
|
1050
1063
|
tre = time_period.locate(tre)
|
1051
1064
|
pts.plot_time_series(df=tre,
|
@@ -1504,13 +1504,13 @@ class PortfolioData:
|
|
1504
1504
|
freq = pd.infer_freq(turnover.index)
|
1505
1505
|
turnover_title = title or f"{turnover_rolling_period}-period rolling {freq}-freq Turnover"
|
1506
1506
|
qis.plot_time_series(df=turnover,
|
1507
|
-
var_format='{:,.
|
1507
|
+
var_format='{:,.1%}',
|
1508
1508
|
y_limits=(0.0, None),
|
1509
1509
|
legend_stats=qis.LegendStats.AVG_NONNAN_LAST,
|
1510
1510
|
title=turnover_title,
|
1511
1511
|
ax=ax,
|
1512
1512
|
**kwargs)
|
1513
|
-
if regime_benchmark is not None:
|
1513
|
+
if regime_benchmark is not None and self.benchmark_prices is not None:
|
1514
1514
|
self.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark, index=turnover.index,
|
1515
1515
|
regime_params=regime_params)
|
1516
1516
|
|
@@ -420,7 +420,7 @@ def generate_multi_asset_factsheet(prices: pd.DataFrame,
|
|
420
420
|
heatmap_freq: str = 'YE',
|
421
421
|
time_period: TimePeriod = None, # time period for reporting
|
422
422
|
figsize: Tuple[float, float] = (8.3, 11.7), # A4 for portrait
|
423
|
-
fontsize: int =
|
423
|
+
fontsize: int = 5,
|
424
424
|
factsheet_name: str = None,
|
425
425
|
performance_bars: Tuple[PerfStat, PerfStat] = (PerfStat.SHARPE_RF0, PerfStat.MAX_DD),
|
426
426
|
drop_1y_ra_perf_table: bool = True,
|
@@ -232,7 +232,7 @@ def generate_multi_portfolio_factsheet(multi_portfolio_data: MultiPortfolioData,
|
|
232
232
|
heatmap_freq: str = 'YE',
|
233
233
|
figsize: Tuple[float, float] = (8.3, 11.7), # A4 for portrait
|
234
234
|
is_grouped: bool = False,
|
235
|
-
fontsize: int =
|
235
|
+
fontsize: int = 5,
|
236
236
|
**kwargs
|
237
237
|
) -> plt.Figure:
|
238
238
|
"""
|
@@ -27,7 +27,7 @@ def generate_multi_portfolio_factsheet(multi_portfolio_data: MultiPortfolioData,
|
|
27
27
|
group_data: pd.Series = None,
|
28
28
|
add_group_exposures_and_pnl: bool = False,
|
29
29
|
add_strategy_factsheets: bool = False,
|
30
|
-
fontsize: int =
|
30
|
+
fontsize: int = 5,
|
31
31
|
**kwargs
|
32
32
|
) -> List[plt.Figure]:
|
33
33
|
"""
|
@@ -35,7 +35,7 @@ def generate_strategy_benchmark_factsheet_plt(multi_portfolio_data: MultiPortfol
|
|
35
35
|
add_exposures_comp: bool = False,
|
36
36
|
is_grouped: Optional[bool] = None,
|
37
37
|
figsize: Tuple[float, float] = (8.3, 11.7), # A4 for portrait
|
38
|
-
fontsize: int =
|
38
|
+
fontsize: int = 5,
|
39
39
|
**kwargs
|
40
40
|
) -> List[plt.Figure]:
|
41
41
|
"""
|
@@ -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,
|
@@ -758,6 +759,7 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
758
759
|
group_order=ac_group_order,
|
759
760
|
regime_benchmark=regime_benchmark,
|
760
761
|
regime_params=regime_params,
|
762
|
+
tre_max_clip=tre_max_clip,
|
761
763
|
title=title,
|
762
764
|
ax=ax,
|
763
765
|
time_period=time_period,
|
@@ -785,6 +787,9 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
|
|
785
787
|
group_order=turnover_order,
|
786
788
|
add_total=False,
|
787
789
|
**kwargs)
|
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)
|
788
793
|
if not add_titles:
|
789
794
|
ax.title.set_visible(False)
|
790
795
|
return figs, dfs
|
@@ -38,7 +38,7 @@ def generate_strategy_factsheet(portfolio_data: PortfolioData,
|
|
38
38
|
sharpe_rolling_window: int = 260,
|
39
39
|
add_benchmarks_to_navs: bool = False,
|
40
40
|
figsize: Tuple[float, float] = (8.5, 11.7), # A4 for portrait
|
41
|
-
fontsize: int =
|
41
|
+
fontsize: int = 5,
|
42
42
|
weight_change_sample_size: int = 20,
|
43
43
|
add_current_position_var_risk_sheet: bool = False,
|
44
44
|
add_weights_turnover_sheet: bool = False,
|
@@ -28,6 +28,9 @@ CALENDAR_DAYS_IN_MONTH = 30
|
|
28
28
|
CALENDAR_DAYS_PER_YEAR_SHARPE = 365.25 # for total return computations for Sharpe
|
29
29
|
|
30
30
|
|
31
|
+
DEFAULT_TRADING_YEAR_DAYS = 252 # How mny trading days we assume per year, see get_period_days()
|
32
|
+
|
33
|
+
|
31
34
|
def get_current_time_with_tz(tz: Optional[str] = 'UTC',
|
32
35
|
days_offset: int = None,
|
33
36
|
normalize: bool = True,
|
@@ -67,7 +70,7 @@ def get_period_days(freq: str = 'B',
|
|
67
70
|
an_f will return the number of period in year
|
68
71
|
consistent with using 252 for vol annualization
|
69
72
|
"""
|
70
|
-
an_days = 365 if is_calendar else
|
73
|
+
an_days = 365 if is_calendar else DEFAULT_TRADING_YEAR_DAYS
|
71
74
|
if freq in ['1M']:
|
72
75
|
days = 1.0 / 24.0 / 60.0
|
73
76
|
an_f = an_days * 24.0 * 60.0
|
@@ -117,7 +120,7 @@ def get_period_days(freq: str = 'B',
|
|
117
120
|
days = an_days
|
118
121
|
an_f = 1.0
|
119
122
|
else:
|
120
|
-
raise TypeError(f'freq={freq} is not
|
123
|
+
raise TypeError(f'freq={freq} is not implemented')
|
121
124
|
|
122
125
|
return days, an_f
|
123
126
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|