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.
Files changed (150) hide show
  1. {qis-3.0.7 → qis-3.0.9}/PKG-INFO +1 -1
  2. {qis-3.0.7 → qis-3.0.9}/pyproject.toml +1 -1
  3. {qis-3.0.7 → qis-3.0.9}/qis/plots/scatter.py +1 -1
  4. {qis-3.0.7 → qis-3.0.9}/qis/plots/time_series.py +20 -19
  5. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/multi_portfolio_data.py +2 -1
  6. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/brinson_attribution.py +1 -1
  7. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_benchmark_factsheet.py +46 -12
  8. {qis-3.0.7 → qis-3.0.9}/LICENSE.txt +0 -0
  9. {qis-3.0.7 → qis-3.0.9}/README.md +0 -0
  10. {qis-3.0.7 → qis-3.0.9}/qis/__init__.py +0 -0
  11. {qis-3.0.7 → qis-3.0.9}/qis/examples/best_returns.py +0 -0
  12. {qis-3.0.7 → qis-3.0.9}/qis/examples/bond_futures_portfolio.py +0 -0
  13. {qis-3.0.7 → qis-3.0.9}/qis/examples/bootstrap_analysis.py +0 -0
  14. {qis-3.0.7 → qis-3.0.9}/qis/examples/boxplot_conditional_returns.py +0 -0
  15. {qis-3.0.7 → qis-3.0.9}/qis/examples/btc_asset_corr.py +0 -0
  16. {qis-3.0.7 → qis-3.0.9}/qis/examples/constant_notional.py +0 -0
  17. {qis-3.0.7 → qis-3.0.9}/qis/examples/constant_weight_portfolios.py +0 -0
  18. {qis-3.0.7 → qis-3.0.9}/qis/examples/core/perf_bbg_prices.py +0 -0
  19. {qis-3.0.7 → qis-3.0.9}/qis/examples/core/price_plots.py +0 -0
  20. {qis-3.0.7 → qis-3.0.9}/qis/examples/core/us_election.py +0 -0
  21. {qis-3.0.7 → qis-3.0.9}/qis/examples/credit_spreads.py +0 -0
  22. {qis-3.0.7 → qis-3.0.9}/qis/examples/credit_trackers.py +0 -0
  23. {qis-3.0.7 → qis-3.0.9}/qis/examples/europe_futures.py +0 -0
  24. {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/multi_assets.py +0 -0
  25. {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/multi_strategy.py +0 -0
  26. {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/pyblogs_reports.py +0 -0
  27. {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/strategy.py +0 -0
  28. {qis-3.0.7 → qis-3.0.9}/qis/examples/factsheets/strategy_benchmark.py +0 -0
  29. {qis-3.0.7 → qis-3.0.9}/qis/examples/generate_option_rolls.py +0 -0
  30. {qis-3.0.7 → qis-3.0.9}/qis/examples/interpolation_infrequent_returns.py +0 -0
  31. {qis-3.0.7 → qis-3.0.9}/qis/examples/leveraged_strategies.py +0 -0
  32. {qis-3.0.7 → qis-3.0.9}/qis/examples/long_short.py +0 -0
  33. {qis-3.0.7 → qis-3.0.9}/qis/examples/momentum_indices.py +0 -0
  34. {qis-3.0.7 → qis-3.0.9}/qis/examples/oakmark_analysis.py +0 -0
  35. {qis-3.0.7 → qis-3.0.9}/qis/examples/ohlc_vol_analysis.py +0 -0
  36. {qis-3.0.7 → qis-3.0.9}/qis/examples/overnight_returns.py +0 -0
  37. {qis-3.0.7 → qis-3.0.9}/qis/examples/perf_external_assets.py +0 -0
  38. {qis-3.0.7 → qis-3.0.9}/qis/examples/perp_pricing.py +0 -0
  39. {qis-3.0.7 → qis-3.0.9}/qis/examples/readme_performances.py +0 -0
  40. {qis-3.0.7 → qis-3.0.9}/qis/examples/risk_return_frontier.py +0 -0
  41. {qis-3.0.7 → qis-3.0.9}/qis/examples/rolling_performance.py +0 -0
  42. {qis-3.0.7 → qis-3.0.9}/qis/examples/seasonality.py +0 -0
  43. {qis-3.0.7 → qis-3.0.9}/qis/examples/sharpe_vs_sortino.py +0 -0
  44. {qis-3.0.7 → qis-3.0.9}/qis/examples/simulate_quant_strats.py +0 -0
  45. {qis-3.0.7 → qis-3.0.9}/qis/examples/test_ewm.py +0 -0
  46. {qis-3.0.7 → qis-3.0.9}/qis/examples/test_scatter.py +0 -0
  47. {qis-3.0.7 → qis-3.0.9}/qis/examples/try_pybloqs.py +0 -0
  48. {qis-3.0.7 → qis-3.0.9}/qis/examples/universe_corrs.py +0 -0
  49. {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
  50. {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_conditional_returns.py +0 -0
  51. {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_spy_by_year.py +0 -0
  52. {qis-3.0.7 → qis-3.0.9}/qis/examples/vix_tenor_analysis.py +0 -0
  53. {qis-3.0.7 → qis-3.0.9}/qis/examples/vol_without_weekends.py +0 -0
  54. {qis-3.0.7 → qis-3.0.9}/qis/file_utils.py +0 -0
  55. {qis-3.0.7 → qis-3.0.9}/qis/local_path.py +0 -0
  56. {qis-3.0.7 → qis-3.0.9}/qis/models/README.md +0 -0
  57. {qis-3.0.7 → qis-3.0.9}/qis/models/__init__.py +0 -0
  58. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/__init__.py +0 -0
  59. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/auto_corr.py +0 -0
  60. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/corr_cov_matrix.py +0 -0
  61. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm.py +0 -0
  62. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm_convolution.py +0 -0
  63. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm_factors.py +0 -0
  64. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ewm_winsor_outliers.py +0 -0
  65. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/pca.py +0 -0
  66. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/plot_correlations.py +0 -0
  67. {qis-3.0.7 → qis-3.0.9}/qis/models/linear/ra_returns.py +0 -0
  68. {qis-3.0.7 → qis-3.0.9}/qis/models/stats/__init__.py +0 -0
  69. {qis-3.0.7 → qis-3.0.9}/qis/models/stats/bootstrap.py +0 -0
  70. {qis-3.0.7 → qis-3.0.9}/qis/models/stats/ohlc_vol.py +0 -0
  71. {qis-3.0.7 → qis-3.0.9}/qis/models/stats/rolling_stats.py +0 -0
  72. {qis-3.0.7 → qis-3.0.9}/qis/models/stats/test_bootstrap.py +0 -0
  73. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/README.md +0 -0
  74. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/__init__.py +0 -0
  75. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/cond_regression.py +0 -0
  76. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/config.py +0 -0
  77. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/desc_table.py +0 -0
  78. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/fx_ops.py +0 -0
  79. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/perf_stats.py +0 -0
  80. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/regime_classifier.py +0 -0
  81. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/returns.py +0 -0
  82. {qis-3.0.7 → qis-3.0.9}/qis/perfstats/timeseries_bfill.py +0 -0
  83. {qis-3.0.7 → qis-3.0.9}/qis/plots/README.md +0 -0
  84. {qis-3.0.7 → qis-3.0.9}/qis/plots/__init__.py +0 -0
  85. {qis-3.0.7 → qis-3.0.9}/qis/plots/bars.py +0 -0
  86. {qis-3.0.7 → qis-3.0.9}/qis/plots/boxplot.py +0 -0
  87. {qis-3.0.7 → qis-3.0.9}/qis/plots/contour.py +0 -0
  88. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/__init__.py +0 -0
  89. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/data_timeseries.py +0 -0
  90. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/desc_table.py +0 -0
  91. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/drawdowns.py +0 -0
  92. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/perf_table.py +0 -0
  93. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/prices.py +0 -0
  94. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_class_table.py +0 -0
  95. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_data.py +0 -0
  96. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_pdf.py +0 -0
  97. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/regime_scatter.py +0 -0
  98. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/returns_heatmap.py +0 -0
  99. {qis-3.0.7 → qis-3.0.9}/qis/plots/derived/returns_scatter.py +0 -0
  100. {qis-3.0.7 → qis-3.0.9}/qis/plots/errorbar.py +0 -0
  101. {qis-3.0.7 → qis-3.0.9}/qis/plots/heatmap.py +0 -0
  102. {qis-3.0.7 → qis-3.0.9}/qis/plots/histogram.py +0 -0
  103. {qis-3.0.7 → qis-3.0.9}/qis/plots/histplot2d.py +0 -0
  104. {qis-3.0.7 → qis-3.0.9}/qis/plots/lineplot.py +0 -0
  105. {qis-3.0.7 → qis-3.0.9}/qis/plots/pie.py +0 -0
  106. {qis-3.0.7 → qis-3.0.9}/qis/plots/qqplot.py +0 -0
  107. {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/__init__.py +0 -0
  108. {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/econ_data_single.py +0 -0
  109. {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/gantt_data_history.py +0 -0
  110. {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/price_history.py +0 -0
  111. {qis-3.0.7 → qis-3.0.9}/qis/plots/reports/utils.py +0 -0
  112. {qis-3.0.7 → qis-3.0.9}/qis/plots/stackplot.py +0 -0
  113. {qis-3.0.7 → qis-3.0.9}/qis/plots/table.py +0 -0
  114. {qis-3.0.7 → qis-3.0.9}/qis/plots/utils.py +0 -0
  115. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/README.md +0 -0
  116. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/__init__.py +0 -0
  117. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/backtester.py +0 -0
  118. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/ewm_portfolio_risk.py +0 -0
  119. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/portfolio_data.py +0 -0
  120. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/__init__.py +0 -0
  121. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/config.py +0 -0
  122. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/multi_assets_factsheet.py +0 -0
  123. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +0 -0
  124. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/multi_strategy_factsheet.py +0 -0
  125. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +0 -0
  126. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_factsheet.py +0 -0
  127. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
  128. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/strats/__init__.py +0 -0
  129. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
  130. {qis-3.0.7 → qis-3.0.9}/qis/portfolio/strats/seasonal_strats.py +0 -0
  131. {qis-3.0.7 → qis-3.0.9}/qis/settings.yaml +0 -0
  132. {qis-3.0.7 → qis-3.0.9}/qis/sql_engine.py +0 -0
  133. {qis-3.0.7 → qis-3.0.9}/qis/test_data.py +0 -0
  134. {qis-3.0.7 → qis-3.0.9}/qis/utils/README.md +0 -0
  135. {qis-3.0.7 → qis-3.0.9}/qis/utils/__init__.py +0 -0
  136. {qis-3.0.7 → qis-3.0.9}/qis/utils/dates.py +0 -0
  137. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_agg.py +0 -0
  138. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_cut.py +0 -0
  139. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_freq.py +0 -0
  140. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_groups.py +0 -0
  141. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_melt.py +0 -0
  142. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_ops.py +0 -0
  143. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_str.py +0 -0
  144. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_to_scores.py +0 -0
  145. {qis-3.0.7 → qis-3.0.9}/qis/utils/df_to_weights.py +0 -0
  146. {qis-3.0.7 → qis-3.0.9}/qis/utils/generic.py +0 -0
  147. {qis-3.0.7 → qis-3.0.9}/qis/utils/np_ops.py +0 -0
  148. {qis-3.0.7 → qis-3.0.9}/qis/utils/ols.py +0 -0
  149. {qis-3.0.7 → qis-3.0.9}/qis/utils/sampling.py +0 -0
  150. {qis-3.0.7 → qis-3.0.9}/qis/utils/struct_ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qis
3
- Version: 3.0.7
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "qis"
3
- version = "3.0.7"
3
+ version = "3.0.9"
4
4
  description = "Implementation of visualisation and reporting analytics for Quantitative Investment Strategies"
5
5
  license = "LICENSE.txt"
6
6
  authors = ["Artur Sepp <artursepp@gmail.com>"]
@@ -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
- x0 = y.first_valid_index() or y.index[0] # if all are nons
128
- x1 = y.index[-1]
129
- y0 = y[x0]
130
- y1 = y.iloc[-1]
131
- x = [x0, x1]
132
- y = [y0, y1]
133
- ax.plot(x, y,
134
- color=color,
135
- linestyle='--',
136
- transform=ax.transData,
137
- linewidth=linewidth)
138
-
139
- if trend_line == TrendLine.TREND_LINE_SHADOWS:
140
- x_ = (data1.index - data1.index[0]).days
141
- slope = (y1 - y0) / (x_[-1] - x_[0])
142
- y_line = [slope * x + y0 for x in x_]
143
- y = data1[column]
144
- ax.fill_between(data1.index, y, y_line, where=y_line >= y,
145
- facecolor=color, interpolate=True, alpha=0.2, lw=linewidth)
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='Tracking error',
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.columns)] # line before totals
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=f"Cumulative performance with background colors using bear/normal/bull "
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, benchmark_ticker=benchmark_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
- qis.set_suptitle(fig, title=f"Time series of weights by asset classes")
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
- qis.set_suptitle(fig, title=f"Boxplot of weights")
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
- qis.set_suptitle(fig, title=f"Time Series of risk contributions by asset classes")
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
- qis.set_suptitle(fig, title=f"Boxplot of risk contributions")
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='Active total return',
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=grouped_allocation_return.index, regime_params=regime_params)
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=grouped_allocation_return.index, regime_params=regime_params)
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=True,
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=True,
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