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.
Files changed (147) hide show
  1. {qis-3.2.9 → qis-3.2.11}/PKG-INFO +1 -1
  2. {qis-3.2.9 → qis-3.2.11}/pyproject.toml +1 -1
  3. {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/multi_assets.py +1 -1
  4. {qis-3.2.9 → qis-3.2.11}/qis/plots/lineplot.py +31 -4
  5. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/multi_portfolio_data.py +19 -6
  6. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/portfolio_data.py +2 -2
  7. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/multi_assets_factsheet.py +1 -1
  8. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +1 -1
  9. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/multi_strategy_factsheet.py +1 -1
  10. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_benchmark_factsheet.py +6 -1
  11. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +1 -1
  12. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_factsheet.py +1 -1
  13. {qis-3.2.9 → qis-3.2.11}/qis/settings.yaml +0 -1
  14. {qis-3.2.9 → qis-3.2.11}/qis/utils/dates.py +5 -2
  15. {qis-3.2.9 → qis-3.2.11}/LICENSE.txt +0 -0
  16. {qis-3.2.9 → qis-3.2.11}/README.md +0 -0
  17. {qis-3.2.9 → qis-3.2.11}/qis/__init__.py +0 -0
  18. {qis-3.2.9 → qis-3.2.11}/qis/examples/best_returns.py +0 -0
  19. {qis-3.2.9 → qis-3.2.11}/qis/examples/bootstrap_analysis.py +0 -0
  20. {qis-3.2.9 → qis-3.2.11}/qis/examples/boxplot_conditional_returns.py +0 -0
  21. {qis-3.2.9 → qis-3.2.11}/qis/examples/btc_asset_corr.py +0 -0
  22. {qis-3.2.9 → qis-3.2.11}/qis/examples/constant_notional.py +0 -0
  23. {qis-3.2.9 → qis-3.2.11}/qis/examples/constant_weight_portfolios.py +0 -0
  24. {qis-3.2.9 → qis-3.2.11}/qis/examples/core/perf_bbg_prices.py +0 -0
  25. {qis-3.2.9 → qis-3.2.11}/qis/examples/core/price_plots.py +0 -0
  26. {qis-3.2.9 → qis-3.2.11}/qis/examples/core/us_election.py +0 -0
  27. {qis-3.2.9 → qis-3.2.11}/qis/examples/credit_spreads.py +0 -0
  28. {qis-3.2.9 → qis-3.2.11}/qis/examples/europe_futures.py +0 -0
  29. {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/multi_strategy.py +0 -0
  30. {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/pyblogs_reports.py +0 -0
  31. {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/strategy.py +0 -0
  32. {qis-3.2.9 → qis-3.2.11}/qis/examples/factsheets/strategy_benchmark.py +0 -0
  33. {qis-3.2.9 → qis-3.2.11}/qis/examples/generate_option_rolls.py +0 -0
  34. {qis-3.2.9 → qis-3.2.11}/qis/examples/interpolation_infrequent_returns.py +0 -0
  35. {qis-3.2.9 → qis-3.2.11}/qis/examples/leveraged_strategies.py +0 -0
  36. {qis-3.2.9 → qis-3.2.11}/qis/examples/long_short.py +0 -0
  37. {qis-3.2.9 → qis-3.2.11}/qis/examples/momentum_indices.py +0 -0
  38. {qis-3.2.9 → qis-3.2.11}/qis/examples/ohlc_vol_analysis.py +0 -0
  39. {qis-3.2.9 → qis-3.2.11}/qis/examples/overnight_returns.py +0 -0
  40. {qis-3.2.9 → qis-3.2.11}/qis/examples/perf_external_assets.py +0 -0
  41. {qis-3.2.9 → qis-3.2.11}/qis/examples/readme_performances.py +0 -0
  42. {qis-3.2.9 → qis-3.2.11}/qis/examples/risk_return_frontier.py +0 -0
  43. {qis-3.2.9 → qis-3.2.11}/qis/examples/rolling_performance.py +0 -0
  44. {qis-3.2.9 → qis-3.2.11}/qis/examples/seasonality.py +0 -0
  45. {qis-3.2.9 → qis-3.2.11}/qis/examples/sharpe_vs_sortino.py +0 -0
  46. {qis-3.2.9 → qis-3.2.11}/qis/examples/simulate_quant_strats.py +0 -0
  47. {qis-3.2.9 → qis-3.2.11}/qis/examples/test_ewm.py +0 -0
  48. {qis-3.2.9 → qis-3.2.11}/qis/examples/test_scatter.py +0 -0
  49. {qis-3.2.9 → qis-3.2.11}/qis/examples/try_pybloqs.py +0 -0
  50. {qis-3.2.9 → qis-3.2.11}/qis/examples/universe_corrs.py +0 -0
  51. {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
  52. {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_conditional_returns.py +0 -0
  53. {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_spy_by_year.py +0 -0
  54. {qis-3.2.9 → qis-3.2.11}/qis/examples/vix_tenor_analysis.py +0 -0
  55. {qis-3.2.9 → qis-3.2.11}/qis/examples/vol_without_weekends.py +0 -0
  56. {qis-3.2.9 → qis-3.2.11}/qis/file_utils.py +0 -0
  57. {qis-3.2.9 → qis-3.2.11}/qis/local_path.py +0 -0
  58. {qis-3.2.9 → qis-3.2.11}/qis/models/README.md +0 -0
  59. {qis-3.2.9 → qis-3.2.11}/qis/models/__init__.py +0 -0
  60. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/__init__.py +0 -0
  61. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/auto_corr.py +0 -0
  62. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/corr_cov_matrix.py +0 -0
  63. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm.py +0 -0
  64. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm_convolution.py +0 -0
  65. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm_factors.py +0 -0
  66. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ewm_winsor_outliers.py +0 -0
  67. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/pca.py +0 -0
  68. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/plot_correlations.py +0 -0
  69. {qis-3.2.9 → qis-3.2.11}/qis/models/linear/ra_returns.py +0 -0
  70. {qis-3.2.9 → qis-3.2.11}/qis/models/stats/__init__.py +0 -0
  71. {qis-3.2.9 → qis-3.2.11}/qis/models/stats/bootstrap.py +0 -0
  72. {qis-3.2.9 → qis-3.2.11}/qis/models/stats/ohlc_vol.py +0 -0
  73. {qis-3.2.9 → qis-3.2.11}/qis/models/stats/rolling_stats.py +0 -0
  74. {qis-3.2.9 → qis-3.2.11}/qis/models/stats/test_bootstrap.py +0 -0
  75. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/README.md +0 -0
  76. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/__init__.py +0 -0
  77. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/cond_regression.py +0 -0
  78. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/config.py +0 -0
  79. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/desc_table.py +0 -0
  80. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/fx_ops.py +0 -0
  81. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/perf_stats.py +0 -0
  82. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/regime_classifier.py +0 -0
  83. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/returns.py +0 -0
  84. {qis-3.2.9 → qis-3.2.11}/qis/perfstats/timeseries_bfill.py +0 -0
  85. {qis-3.2.9 → qis-3.2.11}/qis/plots/README.md +0 -0
  86. {qis-3.2.9 → qis-3.2.11}/qis/plots/__init__.py +0 -0
  87. {qis-3.2.9 → qis-3.2.11}/qis/plots/bars.py +0 -0
  88. {qis-3.2.9 → qis-3.2.11}/qis/plots/boxplot.py +0 -0
  89. {qis-3.2.9 → qis-3.2.11}/qis/plots/contour.py +0 -0
  90. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/__init__.py +0 -0
  91. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/data_timeseries.py +0 -0
  92. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/desc_table.py +0 -0
  93. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/drawdowns.py +0 -0
  94. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/perf_table.py +0 -0
  95. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/prices.py +0 -0
  96. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_class_table.py +0 -0
  97. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_data.py +0 -0
  98. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_pdf.py +0 -0
  99. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/regime_scatter.py +0 -0
  100. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/returns_heatmap.py +0 -0
  101. {qis-3.2.9 → qis-3.2.11}/qis/plots/derived/returns_scatter.py +0 -0
  102. {qis-3.2.9 → qis-3.2.11}/qis/plots/errorbar.py +0 -0
  103. {qis-3.2.9 → qis-3.2.11}/qis/plots/heatmap.py +0 -0
  104. {qis-3.2.9 → qis-3.2.11}/qis/plots/histogram.py +0 -0
  105. {qis-3.2.9 → qis-3.2.11}/qis/plots/histplot2d.py +0 -0
  106. {qis-3.2.9 → qis-3.2.11}/qis/plots/pie.py +0 -0
  107. {qis-3.2.9 → qis-3.2.11}/qis/plots/qqplot.py +0 -0
  108. {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/__init__.py +0 -0
  109. {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/econ_data_single.py +0 -0
  110. {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/gantt_data_history.py +0 -0
  111. {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/price_history.py +0 -0
  112. {qis-3.2.9 → qis-3.2.11}/qis/plots/reports/utils.py +0 -0
  113. {qis-3.2.9 → qis-3.2.11}/qis/plots/scatter.py +0 -0
  114. {qis-3.2.9 → qis-3.2.11}/qis/plots/stackplot.py +0 -0
  115. {qis-3.2.9 → qis-3.2.11}/qis/plots/table.py +0 -0
  116. {qis-3.2.9 → qis-3.2.11}/qis/plots/time_series.py +0 -0
  117. {qis-3.2.9 → qis-3.2.11}/qis/plots/utils.py +0 -0
  118. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/README.md +0 -0
  119. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/__init__.py +0 -0
  120. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/backtester.py +0 -0
  121. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/ewm_portfolio_risk.py +0 -0
  122. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/__init__.py +0 -0
  123. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/brinson_attribution.py +0 -0
  124. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/config.py +0 -0
  125. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
  126. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/signal_data.py +0 -0
  127. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/strats/__init__.py +0 -0
  128. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
  129. {qis-3.2.9 → qis-3.2.11}/qis/portfolio/strats/seasonal_strats.py +0 -0
  130. {qis-3.2.9 → qis-3.2.11}/qis/sql_engine.py +0 -0
  131. {qis-3.2.9 → qis-3.2.11}/qis/test_data.py +0 -0
  132. {qis-3.2.9 → qis-3.2.11}/qis/utils/README.md +0 -0
  133. {qis-3.2.9 → qis-3.2.11}/qis/utils/__init__.py +0 -0
  134. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_agg.py +0 -0
  135. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_cut.py +0 -0
  136. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_freq.py +0 -0
  137. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_groups.py +0 -0
  138. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_melt.py +0 -0
  139. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_ops.py +0 -0
  140. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_str.py +0 -0
  141. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_to_scores.py +0 -0
  142. {qis-3.2.9 → qis-3.2.11}/qis/utils/df_to_weights.py +0 -0
  143. {qis-3.2.9 → qis-3.2.11}/qis/utils/generic.py +0 -0
  144. {qis-3.2.9 → qis-3.2.11}/qis/utils/np_ops.py +0 -0
  145. {qis-3.2.9 → qis-3.2.11}/qis/utils/ols.py +0 -0
  146. {qis-3.2.9 → qis-3.2.11}/qis/utils/sampling.py +0 -0
  147. {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.9
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "qis"
3
- version = "3.2.9"
3
+ version = "3.2.11"
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>"]
@@ -23,7 +23,7 @@ class UnitTests(Enum):
23
23
 
24
24
  def run_unit_test(unit_test: UnitTests):
25
25
 
26
- end_date = '10Jan2025' # performance repoting
26
+ end_date = '17Apr2025' # performance repoting
27
27
 
28
28
  prices = None # if Noe, use yahoo finance data
29
29
 
@@ -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
- colors = put.get_n_colors(n=len(df.columns), **kwargs)
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, palette=colors, dashes=False, markers=markers, linestyle=linestyle, linewidth=linewidth, ax=ax)
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
- legend_labels = put.get_legend_lines(data=df, legend_stats=legend_stats, var_format=yvar_format)
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='Total')
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='{:,.2%}',
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 = 4,
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 = 4,
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 = 4,
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 = 4,
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
@@ -33,7 +33,7 @@ def generate_strategy_benchmark_factsheet_with_pyblogs(multi_portfolio_data: Mul
33
33
  heatmap_freq: str = 'YE',
34
34
  weight_freq: str = 'ME',
35
35
  is_input_weights: bool = True,
36
- fontsize: int = 4,
36
+ fontsize: int = 5,
37
37
  **kwargs
38
38
  ) -> p.VStack:
39
39
  """
@@ -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 = 4,
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,
@@ -18,4 +18,3 @@ OUTPUT_PATH:
18
18
 
19
19
  AWS_POSTGRES:
20
20
  ""
21
-
@@ -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 252
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 impelemnted')
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