qis 3.2.4__tar.gz → 3.2.7__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 (149) hide show
  1. {qis-3.2.4 → qis-3.2.7}/PKG-INFO +1 -1
  2. {qis-3.2.4 → qis-3.2.7}/pyproject.toml +1 -1
  3. {qis-3.2.4 → qis-3.2.7}/qis/models/__init__.py +2 -1
  4. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/ewm.py +98 -43
  5. {qis-3.2.4 → qis-3.2.7}/qis/plots/time_series.py +4 -2
  6. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/strategy_factsheet.py +1 -1
  7. {qis-3.2.4 → qis-3.2.7}/qis/settings.yaml +1 -0
  8. qis-3.2.4/qis/examples/bond_futures_portfolio.py +0 -49
  9. qis-3.2.4/qis/examples/credit_trackers.py +0 -42
  10. qis-3.2.4/qis/examples/perp_pricing.py +0 -56
  11. {qis-3.2.4 → qis-3.2.7}/LICENSE.txt +0 -0
  12. {qis-3.2.4 → qis-3.2.7}/README.md +0 -0
  13. {qis-3.2.4 → qis-3.2.7}/qis/__init__.py +0 -0
  14. {qis-3.2.4 → qis-3.2.7}/qis/examples/best_returns.py +0 -0
  15. {qis-3.2.4 → qis-3.2.7}/qis/examples/bootstrap_analysis.py +0 -0
  16. {qis-3.2.4 → qis-3.2.7}/qis/examples/boxplot_conditional_returns.py +0 -0
  17. {qis-3.2.4 → qis-3.2.7}/qis/examples/btc_asset_corr.py +0 -0
  18. {qis-3.2.4 → qis-3.2.7}/qis/examples/constant_notional.py +0 -0
  19. {qis-3.2.4 → qis-3.2.7}/qis/examples/constant_weight_portfolios.py +0 -0
  20. {qis-3.2.4 → qis-3.2.7}/qis/examples/core/perf_bbg_prices.py +0 -0
  21. {qis-3.2.4 → qis-3.2.7}/qis/examples/core/price_plots.py +0 -0
  22. {qis-3.2.4 → qis-3.2.7}/qis/examples/core/us_election.py +0 -0
  23. {qis-3.2.4 → qis-3.2.7}/qis/examples/credit_spreads.py +0 -0
  24. {qis-3.2.4 → qis-3.2.7}/qis/examples/europe_futures.py +0 -0
  25. {qis-3.2.4 → qis-3.2.7}/qis/examples/factsheets/multi_assets.py +0 -0
  26. {qis-3.2.4 → qis-3.2.7}/qis/examples/factsheets/multi_strategy.py +0 -0
  27. {qis-3.2.4 → qis-3.2.7}/qis/examples/factsheets/pyblogs_reports.py +0 -0
  28. {qis-3.2.4 → qis-3.2.7}/qis/examples/factsheets/strategy.py +0 -0
  29. {qis-3.2.4 → qis-3.2.7}/qis/examples/factsheets/strategy_benchmark.py +0 -0
  30. {qis-3.2.4 → qis-3.2.7}/qis/examples/generate_option_rolls.py +0 -0
  31. {qis-3.2.4 → qis-3.2.7}/qis/examples/interpolation_infrequent_returns.py +0 -0
  32. {qis-3.2.4 → qis-3.2.7}/qis/examples/leveraged_strategies.py +0 -0
  33. {qis-3.2.4 → qis-3.2.7}/qis/examples/long_short.py +0 -0
  34. {qis-3.2.4 → qis-3.2.7}/qis/examples/momentum_indices.py +0 -0
  35. {qis-3.2.4 → qis-3.2.7}/qis/examples/ohlc_vol_analysis.py +0 -0
  36. {qis-3.2.4 → qis-3.2.7}/qis/examples/overnight_returns.py +0 -0
  37. {qis-3.2.4 → qis-3.2.7}/qis/examples/perf_external_assets.py +0 -0
  38. {qis-3.2.4 → qis-3.2.7}/qis/examples/readme_performances.py +0 -0
  39. {qis-3.2.4 → qis-3.2.7}/qis/examples/risk_return_frontier.py +0 -0
  40. {qis-3.2.4 → qis-3.2.7}/qis/examples/rolling_performance.py +0 -0
  41. {qis-3.2.4 → qis-3.2.7}/qis/examples/seasonality.py +0 -0
  42. {qis-3.2.4 → qis-3.2.7}/qis/examples/sharpe_vs_sortino.py +0 -0
  43. {qis-3.2.4 → qis-3.2.7}/qis/examples/simulate_quant_strats.py +0 -0
  44. {qis-3.2.4 → qis-3.2.7}/qis/examples/test_ewm.py +0 -0
  45. {qis-3.2.4 → qis-3.2.7}/qis/examples/test_scatter.py +0 -0
  46. {qis-3.2.4 → qis-3.2.7}/qis/examples/try_pybloqs.py +0 -0
  47. {qis-3.2.4 → qis-3.2.7}/qis/examples/universe_corrs.py +0 -0
  48. {qis-3.2.4 → qis-3.2.7}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
  49. {qis-3.2.4 → qis-3.2.7}/qis/examples/vix_conditional_returns.py +0 -0
  50. {qis-3.2.4 → qis-3.2.7}/qis/examples/vix_spy_by_year.py +0 -0
  51. {qis-3.2.4 → qis-3.2.7}/qis/examples/vix_tenor_analysis.py +0 -0
  52. {qis-3.2.4 → qis-3.2.7}/qis/examples/vol_without_weekends.py +0 -0
  53. {qis-3.2.4 → qis-3.2.7}/qis/file_utils.py +0 -0
  54. {qis-3.2.4 → qis-3.2.7}/qis/local_path.py +0 -0
  55. {qis-3.2.4 → qis-3.2.7}/qis/models/README.md +0 -0
  56. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/__init__.py +0 -0
  57. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/auto_corr.py +0 -0
  58. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/corr_cov_matrix.py +0 -0
  59. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/ewm_convolution.py +0 -0
  60. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/ewm_factors.py +0 -0
  61. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/ewm_winsor_outliers.py +0 -0
  62. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/pca.py +0 -0
  63. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/plot_correlations.py +0 -0
  64. {qis-3.2.4 → qis-3.2.7}/qis/models/linear/ra_returns.py +0 -0
  65. {qis-3.2.4 → qis-3.2.7}/qis/models/stats/__init__.py +0 -0
  66. {qis-3.2.4 → qis-3.2.7}/qis/models/stats/bootstrap.py +0 -0
  67. {qis-3.2.4 → qis-3.2.7}/qis/models/stats/ohlc_vol.py +0 -0
  68. {qis-3.2.4 → qis-3.2.7}/qis/models/stats/rolling_stats.py +0 -0
  69. {qis-3.2.4 → qis-3.2.7}/qis/models/stats/test_bootstrap.py +0 -0
  70. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/README.md +0 -0
  71. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/__init__.py +0 -0
  72. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/cond_regression.py +0 -0
  73. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/config.py +0 -0
  74. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/desc_table.py +0 -0
  75. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/fx_ops.py +0 -0
  76. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/perf_stats.py +0 -0
  77. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/regime_classifier.py +0 -0
  78. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/returns.py +0 -0
  79. {qis-3.2.4 → qis-3.2.7}/qis/perfstats/timeseries_bfill.py +0 -0
  80. {qis-3.2.4 → qis-3.2.7}/qis/plots/README.md +0 -0
  81. {qis-3.2.4 → qis-3.2.7}/qis/plots/__init__.py +0 -0
  82. {qis-3.2.4 → qis-3.2.7}/qis/plots/bars.py +0 -0
  83. {qis-3.2.4 → qis-3.2.7}/qis/plots/boxplot.py +0 -0
  84. {qis-3.2.4 → qis-3.2.7}/qis/plots/contour.py +0 -0
  85. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/__init__.py +0 -0
  86. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/data_timeseries.py +0 -0
  87. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/desc_table.py +0 -0
  88. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/drawdowns.py +0 -0
  89. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/perf_table.py +0 -0
  90. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/prices.py +0 -0
  91. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/regime_class_table.py +0 -0
  92. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/regime_data.py +0 -0
  93. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/regime_pdf.py +0 -0
  94. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/regime_scatter.py +0 -0
  95. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/returns_heatmap.py +0 -0
  96. {qis-3.2.4 → qis-3.2.7}/qis/plots/derived/returns_scatter.py +0 -0
  97. {qis-3.2.4 → qis-3.2.7}/qis/plots/errorbar.py +0 -0
  98. {qis-3.2.4 → qis-3.2.7}/qis/plots/heatmap.py +0 -0
  99. {qis-3.2.4 → qis-3.2.7}/qis/plots/histogram.py +0 -0
  100. {qis-3.2.4 → qis-3.2.7}/qis/plots/histplot2d.py +0 -0
  101. {qis-3.2.4 → qis-3.2.7}/qis/plots/lineplot.py +0 -0
  102. {qis-3.2.4 → qis-3.2.7}/qis/plots/pie.py +0 -0
  103. {qis-3.2.4 → qis-3.2.7}/qis/plots/qqplot.py +0 -0
  104. {qis-3.2.4 → qis-3.2.7}/qis/plots/reports/__init__.py +0 -0
  105. {qis-3.2.4 → qis-3.2.7}/qis/plots/reports/econ_data_single.py +0 -0
  106. {qis-3.2.4 → qis-3.2.7}/qis/plots/reports/gantt_data_history.py +0 -0
  107. {qis-3.2.4 → qis-3.2.7}/qis/plots/reports/price_history.py +0 -0
  108. {qis-3.2.4 → qis-3.2.7}/qis/plots/reports/utils.py +0 -0
  109. {qis-3.2.4 → qis-3.2.7}/qis/plots/scatter.py +0 -0
  110. {qis-3.2.4 → qis-3.2.7}/qis/plots/stackplot.py +0 -0
  111. {qis-3.2.4 → qis-3.2.7}/qis/plots/table.py +0 -0
  112. {qis-3.2.4 → qis-3.2.7}/qis/plots/utils.py +0 -0
  113. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/README.md +0 -0
  114. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/__init__.py +0 -0
  115. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/backtester.py +0 -0
  116. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/ewm_portfolio_risk.py +0 -0
  117. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/multi_portfolio_data.py +0 -0
  118. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/portfolio_data.py +0 -0
  119. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/__init__.py +0 -0
  120. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/brinson_attribution.py +0 -0
  121. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/config.py +0 -0
  122. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/multi_assets_factsheet.py +0 -0
  123. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +0 -0
  124. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/multi_strategy_factsheet.py +0 -0
  125. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/strategy_benchmark_factsheet.py +0 -0
  126. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +0 -0
  127. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
  128. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/strats/__init__.py +0 -0
  129. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
  130. {qis-3.2.4 → qis-3.2.7}/qis/portfolio/strats/seasonal_strats.py +0 -0
  131. {qis-3.2.4 → qis-3.2.7}/qis/sql_engine.py +0 -0
  132. {qis-3.2.4 → qis-3.2.7}/qis/test_data.py +0 -0
  133. {qis-3.2.4 → qis-3.2.7}/qis/utils/README.md +0 -0
  134. {qis-3.2.4 → qis-3.2.7}/qis/utils/__init__.py +0 -0
  135. {qis-3.2.4 → qis-3.2.7}/qis/utils/dates.py +0 -0
  136. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_agg.py +0 -0
  137. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_cut.py +0 -0
  138. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_freq.py +0 -0
  139. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_groups.py +0 -0
  140. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_melt.py +0 -0
  141. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_ops.py +0 -0
  142. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_str.py +0 -0
  143. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_to_scores.py +0 -0
  144. {qis-3.2.4 → qis-3.2.7}/qis/utils/df_to_weights.py +0 -0
  145. {qis-3.2.4 → qis-3.2.7}/qis/utils/generic.py +0 -0
  146. {qis-3.2.4 → qis-3.2.7}/qis/utils/np_ops.py +0 -0
  147. {qis-3.2.4 → qis-3.2.7}/qis/utils/ols.py +0 -0
  148. {qis-3.2.4 → qis-3.2.7}/qis/utils/sampling.py +0 -0
  149. {qis-3.2.4 → qis-3.2.7}/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.4
3
+ Version: 3.2.7
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.4"
3
+ version = "3.2.7"
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>"]
@@ -47,7 +47,8 @@ from qis.models.linear.ewm import (
47
47
  compute_roll_mean,
48
48
  compute_rolling_mean_adj,
49
49
  set_init_dim1,
50
- set_init_dim2
50
+ set_init_dim2,
51
+ compute_ewm_covar_newey_west
51
52
  )
52
53
 
53
54
  from qis.models.linear.ewm_convolution import ConvolutionType, SignalAggType, ewm_xy_convolution
@@ -237,6 +237,7 @@ def compute_ewm_long_short_filter(data: Union[pd.DataFrame, pd.Series, np.ndarra
237
237
 
238
238
  @njit
239
239
  def compute_ewm_covar(a: np.ndarray,
240
+ b: np.ndarray = None,
240
241
  span: Union[int, np.ndarray] = None,
241
242
  ewm_lambda: float = 0.94,
242
243
  covar0: np.ndarray = None,
@@ -245,7 +246,13 @@ def compute_ewm_covar(a: np.ndarray,
245
246
  ) -> np.ndarray:
246
247
  """
247
248
  compute ewm covariance matrix
249
+ b is optional, when given the covar is cross product a and b
248
250
  """
251
+ if b is None:
252
+ b = a
253
+ else:
254
+ assert a.shape[0] == b.shape[0]
255
+ assert a.shape[1] == b.shape[1]
249
256
 
250
257
  if span is not None:
251
258
  ewm_lambda = 1.0 - 2.0 / (span + 1.0)
@@ -263,7 +270,7 @@ def compute_ewm_covar(a: np.ndarray,
263
270
 
264
271
  last_covar = covar
265
272
  if a.ndim == 1: # ndarry array
266
- r_ij = np.outer(a, a)
273
+ r_ij = np.outer(a, b)
267
274
  covar = ewm_lambda_1 * r_ij + ewm_lambda * last_covar
268
275
  if nan_backfill == NanBackfill.FFILL:
269
276
  fill_value = last_covar
@@ -277,8 +284,7 @@ def compute_ewm_covar(a: np.ndarray,
277
284
  else: # loop over rows
278
285
  t = a.shape[0]
279
286
  for idx in range(0, t): # row in x:
280
- row = a[idx]
281
- r_ij = np.outer(row, row)
287
+ r_ij = np.outer(a[idx], b[idx])
282
288
  covar = ewm_lambda_1 * r_ij + ewm_lambda * last_covar
283
289
 
284
290
  if nan_backfill == NanBackfill.FFILL:
@@ -290,21 +296,59 @@ def compute_ewm_covar(a: np.ndarray,
290
296
 
291
297
  last_covar = np.where(np.isfinite(covar), covar, fill_value)
292
298
 
293
- if is_corr:
294
- if np.nansum(np.diag(last_covar)) > 1e-10:
295
- inv_vol = np.reciprocal(np.sqrt(np.diag(last_covar)))
296
- norm = np.outer(inv_vol, inv_vol)
297
- else:
298
- norm = np.identity(n)
299
- last_covar_ = norm * last_covar
299
+ # for covar normalise
300
+ if is_corr:
301
+ if np.nansum(np.diag(last_covar)) > 1e-10:
302
+ inv_vol = np.reciprocal(np.sqrt(np.diag(last_covar)))
303
+ norm = np.outer(inv_vol, inv_vol)
300
304
  else:
301
- last_covar_ = last_covar
302
-
303
- covar = last_covar_
305
+ norm = np.identity(n)
306
+ covar = norm * last_covar
307
+ else:
308
+ covar = last_covar
304
309
 
305
310
  return covar
306
311
 
307
312
 
313
+ @njit
314
+ def compute_ewm_covar_newey_west(a: np.ndarray,
315
+ num_lags: int = 2,
316
+ span: Union[int, np.ndarray] = None,
317
+ ewm_lambda: float = 0.94,
318
+ covar0: np.ndarray = None,
319
+ is_corr: bool = False,
320
+ nan_backfill: NanBackfill = NanBackfill.FFILL
321
+ ) -> np.ndarray:
322
+ """
323
+ implementation of newey west covar estimator
324
+ """
325
+ ewm0 = compute_ewm_covar(a=a, span=span, ewm_lambda=ewm_lambda, covar0=covar0, is_corr=False, nan_backfill=nan_backfill)
326
+ # compute m recursions
327
+ if num_lags > 0:
328
+ nw_adjustment = np.zeros_like(ewm0)
329
+ for m in np.arange(1, num_lags+1):
330
+ # lagged value
331
+ a_m = np.empty_like(a)
332
+ a_m[m:] = a[:-m]
333
+ a_m[:m] = np.nan
334
+ ewm_m1 = compute_ewm_covar(a=a, b=a_m, span=span)
335
+ # ewm_m2 = compute_ewm_covar(a=a_m, b=a, span=span)
336
+ nw_adjustment += (1.0-m/(num_lags+1))*(ewm_m1 + np.transpose(ewm_m1))
337
+ ewm_nw = ewm0 + nw_adjustment
338
+ else:
339
+ ewm_nw = ewm0
340
+
341
+ if is_corr:
342
+ if np.nansum(np.diag(ewm_nw)) > 1e-10:
343
+ inv_vol = np.reciprocal(np.sqrt(np.diag(ewm_nw)))
344
+ norm = np.outer(inv_vol, inv_vol)
345
+ else:
346
+ norm = np.identity(a.shape[1])
347
+ ewm_nw = norm * ewm_nw
348
+
349
+ return ewm_nw
350
+
351
+
308
352
  @njit
309
353
  def compute_ewm_covar_tensor(a: np.ndarray,
310
354
  span: Union[int, np.ndarray] = None,
@@ -663,6 +707,27 @@ def compute_ewm_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
663
707
  return ewm
664
708
 
665
709
 
710
+ @njit
711
+ def matrix_recursion(a: np.ndarray,
712
+ a_m: np.ndarray,
713
+ span: Optional[Union[float, np.ndarray]] = None,
714
+ ewm_lambda: Union[float, np.ndarray] = 0.94
715
+ ) -> np.ndarray:
716
+ if span is not None:
717
+ ewm_lambda = 1.0 - 2.0 / (span + 1.0)
718
+ ewm_lambda_1 = 1.0 - ewm_lambda
719
+ t = a.shape[0]
720
+ last_covar = np.zeros((a.shape[1], a.shape[1]))
721
+ ewm_m = np.zeros_like(a_m)
722
+ for idx in range(0, t):
723
+ r_ij = np.outer(a[idx], a_m[idx])
724
+ covar = ewm_lambda_1 * r_ij + ewm_lambda * last_covar
725
+ fill_value = last_covar
726
+ last_covar = np.where(np.isfinite(covar), covar, fill_value)
727
+ ewm_m[idx, :] = np.diag(last_covar) + np.diag(np.transpose(last_covar))
728
+ return ewm_m
729
+
730
+
666
731
  def compute_ewm_newey_west_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
667
732
  num_lags: int = 2,
668
733
  span: Optional[Union[float, np.ndarray]] = None,
@@ -690,6 +755,7 @@ def compute_ewm_newey_west_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
690
755
  if mean_adj_type != MeanAdjType.NONE:
691
756
  a = compute_rolling_mean_adj(data=a,
692
757
  mean_adj_type=mean_adj_type,
758
+ span=span,
693
759
  ewm_lambda=ewm_lambda,
694
760
  init_type=init_type,
695
761
  nan_backfill=nan_backfill)
@@ -703,36 +769,25 @@ def compute_ewm_newey_west_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
703
769
  if isinstance(init_value, np.ndarray):
704
770
  init_value = float(init_value)
705
771
 
706
- if span is not None:
707
- ewm_lambda = 1.0 - 2.0 / (span + 1.0)
708
- ewm_lambda_1 = 1.0 - ewm_lambda
709
-
710
- def matrix_recursion(a_m: np.ndarray) -> np.ndarray:
711
- t = a.shape[0]
712
- last_covar = np.zeros((a.shape[1], a.shape[1]))
713
- ewm_m = np.zeros_like(a_m)
714
- for idx in range(0, t):
715
- r_ij = np.outer(a[idx], a_m[idx])
716
- covar = ewm_lambda_1 * r_ij + ewm_lambda * last_covar
717
- fill_value = last_covar
718
- last_covar = np.where(np.isfinite(covar), covar, fill_value)
719
- ewm_m[idx, :] = np.diag(last_covar) + np.diag(np.transpose(last_covar))
720
- return ewm_m
721
-
722
772
  ewm0 = ewm_recursion(a=np.square(a), ewm_lambda=ewm_lambda, init_value=init_value, nan_backfill=nan_backfill)
723
- nw_adjustment = np.zeros_like(ewm0)
724
- # compute m recursions
725
- for m in np.arange(1, num_lags+1):
726
- # lagged value
727
- a_m = np.empty_like(a)
728
- a_m[m:] = a[:-m]
729
- a_m[:m] = np.nan
730
- # qqq
731
- ewm_m = matrix_recursion(a_m=a_m)
732
- nw_adjustment += (1.0-m/(num_lags+1))*ewm_m
733
-
734
- ewm_nw = ewm0 + nw_adjustment
735
- nw_ratio = np.divide(ewm_nw, ewm0, where=ewm0 > 0.0)
773
+
774
+ if num_lags == 0:
775
+ ewm_nw = ewm0
776
+ nw_ratio = np.ones_like(ewm0)
777
+ else:
778
+ nw_adjustment = np.zeros_like(ewm0)
779
+ # compute m recursions
780
+ for m in np.arange(1, num_lags+1):
781
+ # lagged value
782
+ a_m = np.empty_like(a)
783
+ a_m[m:] = a[:-m]
784
+ a_m[:m] = np.nan
785
+ ewm_m = matrix_recursion(a=a, a_m=a_m, span=span)
786
+ nw_adjustment += (1.0-m/(num_lags+1))*ewm_m
787
+
788
+ ewm_nw = ewm0 + nw_adjustment
789
+ nw_ratio = np.divide(ewm_nw, ewm0, where=ewm0 > 0.0)
790
+ nw_ratio = np.where(nw_ratio > 0.0, nw_ratio, 1.0)
736
791
 
737
792
  if warmup_period is not None: # set to nan first nonnan in warmup_period
738
793
  ewm_nw = npo.set_nans_for_warmup_period(a=ewm_nw, warmup_period=warmup_period)
@@ -819,7 +874,7 @@ def compute_rolling_mean_adj(data: Union[pd.DataFrame, pd.Series, np.ndarray],
819
874
  mean_adj_type: MeanAdjType = MeanAdjType.EWMA,
820
875
  span: Union[float, np.ndarray] = None,
821
876
  ewm_lambda: Union[float, np.ndarray] = 0.94,
822
- init_type: InitType = InitType.MEAN,
877
+ init_type: InitType = InitType.X0,
823
878
  init_value: Union[float, np.ndarray, None] = None,
824
879
  nan_backfill: NanBackfill = NanBackfill.FFILL
825
880
  ) -> Union[pd.DataFrame, pd.Series, np.ndarray]:
@@ -345,6 +345,7 @@ def plot_time_series_2ax(df1: Union[pd.Series, pd.DataFrame],
345
345
  is_log=is_logs[0],
346
346
  y_limits=y_limits,
347
347
  ylabel=ylabel1,
348
+ fontsize=fontsize,
348
349
  ax=ax,
349
350
  **kwargs)
350
351
 
@@ -358,16 +359,17 @@ def plot_time_series_2ax(df1: Union[pd.Series, pd.DataFrame],
358
359
  is_log=is_logs[1],
359
360
  y_limits=y_limits_ax2,
360
361
  ylabel=ylabel2,
362
+ fontsize=fontsize,
361
363
  ax=ax_twin,
362
364
  **kwargs)
363
365
 
366
+ ax.tick_params(axis='x', which='both', bottom=False)
367
+
364
368
  put.set_ax_ticks_format(ax=ax, fontsize=fontsize, xvar_format=None, yvar_format=var_format, set_ticks=False,
365
369
  yvar_major_ticks=yvar_major_ticks1, x_rotation=x_rotation, **kwargs)
366
370
  put.set_ax_ticks_format(ax=ax_twin, fontsize=fontsize, xvar_format=None, yvar_format=var_format_yax2, set_ticks=False,
367
371
  yvar_major_ticks=yvar_major_ticks2, x_rotation=x_rotation, **kwargs)
368
372
 
369
- ax.tick_params(axis='x', which='both', bottom=False)
370
-
371
373
  if legend_loc is not None:
372
374
  if legend_labels is None:
373
375
  df1.columns = [f"{x} (left)" for x in df1.columns]
@@ -20,6 +20,7 @@ def generate_strategy_factsheet(portfolio_data: PortfolioData,
20
20
  benchmark_prices: Union[pd.DataFrame, pd.Series],
21
21
  time_period: TimePeriod = None,
22
22
  ytd_attribution_time_period: TimePeriod = qis.get_ytd_time_period(),
23
+ weight_report_time_period: TimePeriod = None,
23
24
  perf_params: PerfParams = PERF_PARAMS,
24
25
  regime_params: BenchmarkReturnsQuantileRegimeSpecs = REGIME_PARAMS,
25
26
  regime_benchmark: str = None, # default is set to benchmark_prices.columns[0]
@@ -39,7 +40,6 @@ def generate_strategy_factsheet(portfolio_data: PortfolioData,
39
40
  figsize: Tuple[float, float] = (8.5, 11.7), # A4 for portrait
40
41
  fontsize: int = 4,
41
42
  weight_change_sample_size: int = 20,
42
- weight_report_time_period: TimePeriod = None,
43
43
  add_current_position_var_risk_sheet: bool = False,
44
44
  add_weights_turnover_sheet: bool = False,
45
45
  add_grouped_exposures: bool = False,
@@ -18,3 +18,4 @@ OUTPUT_PATH:
18
18
 
19
19
  AWS_POSTGRES:
20
20
  ""
21
+
@@ -1,49 +0,0 @@
1
- import pandas as pd
2
- import numpy as np
3
- import matplotlib.pyplot as plt
4
- from enum import Enum
5
- import qis as qis
6
-
7
- import futures_strats.local_path as lp
8
-
9
- output_path = lp.OUTPUT_PATH
10
- local_path = lp.LOCAL_PATH
11
- # futures_strats
12
- from futures_strats import (compute_strategy_portfolio_data_with_costs,
13
- compute_multi_strategy_data_from_blocks,
14
- compute_marginal_perfs_for_strategy)
15
- from futures_strats.data.universes.futures.bbg_futures import Universes
16
- from futures_strats.data.providers.bloomberg.assets_bbg import AssetsBBG
17
- from futures_strats.research.cross_trend import (CSTF_RB_TRACKER,
18
- CSTF_EXACT_TRACKER,
19
- CSTF_RB_AC_TRACKER)
20
- from futures_strats.research.trackers import (CSTF_GOLDMAN_TRACKER_AC,
21
- GOLDMAN_UNIVERSE)
22
-
23
- strategy_universe = Universes.BBG_FUTURES_INVESTABLE.load_universe_data(local_path=local_path)
24
- prices = strategy_universe.get_prices(freq='B')[['UXY1 Comdty', 'US1 Comdty', 'WN1 Comdty']].ffill().dropna()
25
- prices = prices[prices.columns[::-1]]
26
- qis.plot_prices_with_dd(prices=prices)
27
-
28
- portfolio_data = qis.backtest_model_portfolio(prices=prices,
29
- weights=np.array([-1.0, 2.0, -1.0]),
30
- rebalancing_freq='ME',
31
- ticker='Butterly'
32
- )
33
-
34
- time_period = qis.TimePeriod('31Dec2015', None)
35
- figs = qis.generate_strategy_factsheet(portfolio_data=portfolio_data,
36
- benchmark_prices=prices.iloc[:, -1],
37
- is_grouped=False,
38
- add_current_position_var_risk_sheet=False,
39
- add_weights_turnover_sheet=False,
40
- add_grouped_exposures=False,
41
- add_grouped_cum_pnl=False,
42
- time_period=time_period,
43
- **qis.fetch_default_report_kwargs(time_period=time_period,
44
- add_rates_data=False))
45
-
46
- qis.save_figs_to_pdf(figs=figs, file_name=f"butterfly", orientation='landscape',
47
- local_path=output_path)
48
-
49
- plt.show()
@@ -1,42 +0,0 @@
1
-
2
- import pandas as pd
3
- import matplotlib.pyplot as plt
4
- import seaborn as sns
5
- import qis as qis
6
- from bbg_fetch import fetch_field_timeseries_per_tickers
7
-
8
-
9
- tickers = {'CICMCE5B Index': 'ITRAXX Main 5Y',
10
- 'CICMCE1B Index': 'ITRAXX Main 10Y',
11
- 'CICMCX5B Index': 'ITRAXX Xover 5Y',
12
- 'CICMCI5B Index': 'CDX NA IG 5Y',
13
- 'CICMCI1B Index': 'CDX NA IG 10Y',
14
- 'CICMCH5B Index': 'CDX NA HY 5Y',
15
- 'CICMCG05 Index': 'UK CDS 5Y',
16
- 'CICMCK05 Index': 'South Korea CDS 5Y',
17
- 'CICMCJ05 Index': 'Japan CDS 5Y',
18
- 'CICMCU05 Index': 'US CDS 5Y',
19
- 'CICMCE05 Index': 'Germany CDS 5Y'
20
- }
21
-
22
- tickers = {'UISYMH5S Index': 'UBS_CDX_HY',
23
- 'CICMCH5B Index': 'CITI_CDX_HY',
24
- 'CH5LMER5 Index': 'GS_CDX_HY',
25
- 'UISYMI5S Index': 'UBS_IG_5Y',
26
- 'CICMCI5B Index': 'CITI_IG_5Y',
27
- 'CI5LMER5 Index': 'GS_IG_5Y'}
28
-
29
- prices = fetch_field_timeseries_per_tickers(tickers=tickers, freq='B', field='PX_LAST').ffill()
30
- print(prices)
31
- benchmark_prices = fetch_field_timeseries_per_tickers(tickers={'LGDRTRUU Index': 'Agg IG'}, freq='B', field='PX_LAST').ffill()
32
-
33
- time_period = qis.TimePeriod('01Jan2008', pd.Timestamp.today())
34
- kwargs = qis.fetch_default_report_kwargs(time_period=time_period, add_rates_data=False)
35
-
36
- fig = qis.generate_multi_asset_factsheet(prices=prices,
37
- benchmark_prices=benchmark_prices,
38
- time_period=time_period,
39
- **kwargs)
40
- qis.save_figs_to_pdf(figs=[fig],
41
- file_name=f"credit_trackers_report", orientation='landscape',
42
- local_path=qis.local_path.get_output_path())
@@ -1,56 +0,0 @@
1
- import pandas as pd
2
- import numpy as np
3
- import matplotlib.pyplot as plt
4
- import seaborn as sns
5
- import qis as qis
6
- from bbg_fetch import fetch_field_timeseries_per_tickers, fetch_index_members_weights, fetch_bonds_info
7
-
8
-
9
- index_ticker = 'I31415US Index'
10
-
11
- end_dates = ['20180101', '20190101', '20200101', '20210101', '20220101', '20230101', '20240101', '20250101', '20250106']
12
-
13
- data_out = {}
14
- weighted_resets = []
15
- for idx, end_date in enumerate(end_dates):
16
- if idx > 0:
17
- members = fetch_index_members_weights(index_ticker, END_DATE_OVERRIDE=end_dates[idx-1])
18
- corp_index = [f"{x} corp" for x in members.index]
19
- members.index = corp_index
20
- """
21
- amt_outstanding = fetch_bonds_info(isins=members.index.to_list(), fields=['amt_outstanding'],
22
- END_DATE_OVERRIDE=end_dates[idx-1])['amt_outstanding']
23
- amt_outstanding = amt_outstanding.loc[members.index]
24
- amt_outstanding.index = corp_index
25
- """
26
- prices = fetch_field_timeseries_per_tickers(tickers=corp_index,
27
- start_date=pd.Timestamp(end_dates[idx-1]),
28
- end_date=pd.Timestamp(end_date),
29
- freq='B')
30
- prices = prices.resample('W-WED').last()
31
- # market_value = prices.multiply(amt_outstanding, axis=1)
32
- #market_value.divide(np.nansum(market_value, axis=1, keepdims=True), axis=1)
33
- is_reset = (prices > 100).astype(float)
34
- market_weights = members.iloc[:, 0]
35
- weighted_reset = is_reset.multiply(market_weights, axis=1)
36
- weighted_reset = weighted_reset.sum(1)
37
- weighted_resets.append(weighted_reset)
38
- data_out[f"{end_dates[idx-1]} members"] = members
39
- data_out[f"{end_date} prices"] = prices
40
- data_out[f"{end_date} is_reset"] = is_reset
41
-
42
- weighted_resets = pd.concat(weighted_resets)
43
- weighted_resets = weighted_resets.loc[~weighted_resets.index.duplicated(keep='first')]
44
- weighted_resets = weighted_resets.to_frame('weighted_par_reset %')
45
- print(weighted_resets)
46
-
47
- data_out['weighted_resets'] = weighted_resets
48
- qis.save_df_to_excel(data=data_out, file_name='perp_pricing')
49
-
50
- with sns.axes_style("darkgrid"):
51
- fig, ax = plt.subplots(1, 1, figsize=(15, 8), tight_layout=True)
52
- qis.plot_time_series(weighted_resets,
53
- title='weighted_par_reset',
54
- ax=ax)
55
-
56
- plt.show()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes