my-github-tests 1.0.2__tar.gz → 1.0.3__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 (130) hide show
  1. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/PKG-INFO +1 -1
  2. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_github_tests.egg-info/PKG-INFO +1 -1
  3. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_github_tests.egg-info/SOURCES.txt +4 -0
  4. my_github_tests-1.0.3/my_private_github/QuantScreener/quant_screener/create_universe_data.py +127 -0
  5. my_github_tests-1.0.3/my_private_github/QuantScreener/quant_screener/run_sp_screener.py +75 -0
  6. my_github_tests-1.0.3/my_private_github/QuantScreener/quant_screener/sp_screener.py +367 -0
  7. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/pe_for_saa.py +46 -6
  8. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/pe_premia_with_factors.py +1 -1
  9. my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/research/saa/__init__.py +0 -0
  10. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/pyproject.toml +1 -1
  11. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.gitattributes +0 -0
  12. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.gitignore +0 -0
  13. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/.gitignore +0 -0
  14. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  15. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  16. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/misc.xml +0 -0
  17. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/modules.xml +0 -0
  18. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/my_private_github.iml +0 -0
  19. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/.idea/vcs.xml +0 -0
  20. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/GenAIassignment.md +0 -0
  21. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/LICENCSE.txt +0 -0
  22. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/README.md +0 -0
  23. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_github_tests.egg-info/dependency_links.txt +0 -0
  24. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_github_tests.egg-info/top_level.txt +0 -0
  25. {my_github_tests-1.0.2/my_private_github → my_github_tests-1.0.3/my_private_github/QuantScreener/quant_screener}/__init__.py +0 -0
  26. {my_github_tests-1.0.2/my_private_github/data → my_github_tests-1.0.3/my_private_github}/__init__.py +0 -0
  27. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/core → my_github_tests-1.0.3/my_private_github/data}/__init__.py +0 -0
  28. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/README.md +0 -0
  29. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/__init__.py +0 -0
  30. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/data → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/core}/__init__.py +0 -0
  31. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/core/backtester_optimiser.py +0 -0
  32. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/core/current_portfolio_optimiser.py +0 -0
  33. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/mac_prod → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/data}/__init__.py +0 -0
  34. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/__pycache__/__init__.cpython-311.pyc +0 -0
  35. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/__pycache__/__init__.cpython-312.pyc +0 -0
  36. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/__pycache__/excel_loader.cpython-311.pyc +0 -0
  37. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/__pycache__/excel_loader.cpython-312.pyc +0 -0
  38. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/__pycache__/mac_universe.cpython-311.pyc +0 -0
  39. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/__pycache__/mac_universe.cpython-312.pyc +0 -0
  40. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/db_loader.py +0 -0
  41. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/excel_loader.py +0 -0
  42. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/forecast_returns.py +0 -0
  43. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/data/mac_universe.py +0 -0
  44. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/hf_mac_report_20251019_1723.pdf +0 -0
  45. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/local_path.py +0 -0
  46. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/old_data → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/mac_prod}/__init__.py +0 -0
  47. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/mac_prod/fetch_prod_specs.py +0 -0
  48. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/mac_prod/futures_risk_model.py +0 -0
  49. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/mac_prod/prod_covar_specs.py +0 -0
  50. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/mac_prod/reporting.py +0 -0
  51. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/mac_prod/run_current_portfolio.py +0 -0
  52. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/mac_prod/run_funds_backtest.py +0 -0
  53. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/research → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/old_data}/__init__.py +0 -0
  54. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/check_corrs.py +0 -0
  55. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/factor_returns.py +0 -0
  56. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/funds_alpha.py +0 -0
  57. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/funds_universe.py +0 -0
  58. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/index_universe.py +0 -0
  59. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/universe.py +0 -0
  60. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/old_data/universe_report.py +0 -0
  61. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/optimise_prod_portfolio.py +0 -0
  62. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/requirements.txt +0 -0
  63. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/research/apac → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/research}/__init__.py +0 -0
  64. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/alts_universe.py +0 -0
  65. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/research/paper → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/research/apac}/__init__.py +0 -0
  66. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/apac/run_jp_bespoke_mandate.py +0 -0
  67. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/apac/run_range_saa.py +0 -0
  68. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/apac/run_saa_backtest.py +0 -0
  69. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/apac/set_risk_budget_for_range_saa.py +0 -0
  70. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/cma_alts_universe.py +0 -0
  71. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/cma_betas.py +0 -0
  72. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/covar_reporting.py +0 -0
  73. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/db_qis_portfolio.py +0 -0
  74. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/estimate_ar.py +0 -0
  75. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/hedge_funds_portfolio.py +0 -0
  76. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/mac_covar_reporting.py +0 -0
  77. {my_github_tests-1.0.2/my_private_github/mac_portfolio_optimizer/research/saa → my_github_tests-1.0.3/my_private_github/mac_portfolio_optimizer/research/paper}/__init__.py +0 -0
  78. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/paper/article_figures.py +0 -0
  79. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/paper/cross_sharpe.py +0 -0
  80. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/paper/run_backtest_for_article.py +0 -0
  81. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/paper/slides_figures.py +0 -0
  82. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/paper/vol_check.py +0 -0
  83. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/returns_unsmoothing.py +0 -0
  84. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/risk_budget_factors.py +0 -0
  85. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/saa/cma_backtester.py +0 -0
  86. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/saa/cma_saa_optimiser.py +0 -0
  87. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/saa/cma_saa_optimiser_old.py +0 -0
  88. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/saa/implied_returns.py +0 -0
  89. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/saa/saa_excel_loader.py +0 -0
  90. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/research/saa/saa_universe.py +0 -0
  91. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/CMA_US_no_valuations.xlsx +0 -0
  92. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/CMAs.xlsx +0 -0
  93. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC - PLF Allocation Tracker.xlsx +0 -0
  94. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.2_11mar2025.xlsx +0 -0
  95. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.2_15Apr2025.xlsx +0 -0
  96. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.2_may2025.xlsx +0 -0
  97. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.3.xlsx +0 -0
  98. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.4.xlsx +0 -0
  99. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.5.xlsx +0 -0
  100. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.6.xlsx +0 -0
  101. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.7.xlsx +0 -0
  102. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.8 - Copy (2).xlsx +0 -0
  103. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.8 - Copy.xlsx +0 -0
  104. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/MAC Allocation Tracker v.8.xlsx +0 -0
  105. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/Step 1 SAA - Artur.xlsx +0 -0
  106. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/WMI_Template_20250616.xlsx +0 -0
  107. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/blackrock-capital-market-assumptions.xlsx +0 -0
  108. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma/20250306_SAA_Update_en.pdf +0 -0
  109. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma/AC - Jakub.xlsx +0 -0
  110. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma/CMA changes summary.docx +0 -0
  111. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma/Global CMA & SAA universe.xlsx +0 -0
  112. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma/Global CMA SAA universe - APAC.xlsx +0 -0
  113. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma_factors.csv +0 -0
  114. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/cma_prices.csv +0 -0
  115. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/db_qis.xlsx +0 -0
  116. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/db_qis_prices.csv +0 -0
  117. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/db_qis_universe.csv +0 -0
  118. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/dm_indices.csv +0 -0
  119. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/futures_prices.csv +0 -0
  120. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/futures_risk_factors.csv +0 -0
  121. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/hf_indices.csv +0 -0
  122. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/mac_prices.xlsx +0 -0
  123. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/qach_prices.xlsx +0 -0
  124. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/rate.csv +0 -0
  125. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/wmi_bbg_prices.csv +0 -0
  126. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/~$MAC Allocation Tracker v.4.xlsx +0 -0
  127. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/~$MAC Allocation Tracker v.5.xlsx +0 -0
  128. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/resources/~$MAC Allocation Tracker v.8 - Copy (2).xlsx +0 -0
  129. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/my_private_github/mac_portfolio_optimizer/settings.yaml +0 -0
  130. {my_github_tests-1.0.2 → my_github_tests-1.0.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: my-github-tests
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: my github tests
5
5
  Author-email: AA SS <your.email@example.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: my-github-tests
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: my github tests
5
5
  Author-email: AA SS <your.email@example.com>
6
6
  License: MIT
@@ -16,6 +16,10 @@ my_github_tests.egg-info/SOURCES.txt
16
16
  my_github_tests.egg-info/dependency_links.txt
17
17
  my_github_tests.egg-info/top_level.txt
18
18
  my_private_github/__init__.py
19
+ my_private_github/QuantScreener/quant_screener/__init__.py
20
+ my_private_github/QuantScreener/quant_screener/create_universe_data.py
21
+ my_private_github/QuantScreener/quant_screener/run_sp_screener.py
22
+ my_private_github/QuantScreener/quant_screener/sp_screener.py
19
23
  my_private_github/data/__init__.py
20
24
  my_private_github/mac_portfolio_optimizer/README.md
21
25
  my_private_github/mac_portfolio_optimizer/__init__.py
@@ -0,0 +1,127 @@
1
+ """
2
+ create universe data
3
+ """
4
+ import pandas as pd
5
+ import qis as qis
6
+ from typing import List, Tuple
7
+ from enum import Enum
8
+ from bbg_fetch import fetch_fundamentals, fetch_field_timeseries_per_tickers
9
+
10
+ START_DATE = pd.Timestamp('31Dec2014') # pd.Timestamp('03Aug2001')
11
+ END_DATE = pd.Timestamp.now().normalize()
12
+
13
+ from quant_screener.sp_screener import Universe, FILE_NAME
14
+
15
+
16
+ def fetch_universe_data_for_tickers(tickers: List[str],
17
+ benchmark_tickers: List[str] = ('NDDUWI Index', 'LGTRTRUU Index',)
18
+ ) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
19
+ """
20
+ fetch price and fundamental data for list of tickeers
21
+ """
22
+ price_timeseries = fetch_field_timeseries_per_tickers(tickers=tickers, field='px_last',
23
+ start_date=START_DATE, end_date=END_DATE)
24
+ fundamentals = fetch_fundamentals(tickers=tickers, fields={'security_name': 'name',
25
+ 'industry_sector': 'sector',
26
+ 'id_isin': 'isin',
27
+ 'crncy': 'crncy',
28
+ '12mo_put_imp_vol': 'implied_vol'})
29
+ benchmark_prices = fetch_field_timeseries_per_tickers(tickers=benchmark_tickers,
30
+ field='px_last',
31
+ start_date=START_DATE, end_date=END_DATE)
32
+ return price_timeseries, fundamentals, benchmark_prices
33
+
34
+
35
+ def get_universe_tickers(local_path: str,
36
+ universe: Universe = Universe.SAMPLE,
37
+ file_name: str = FILE_NAME
38
+ ) -> List[str]:
39
+ """
40
+ read tickers from file_name by universe
41
+ """
42
+ df = qis.load_df_from_excel(file_name=file_name, local_path=local_path, sheet_name=universe.value)
43
+ tickers = df['Ticker'].to_list()
44
+ tickers_split = [x.split(' ') for x in tickers]
45
+ tickers = [f"{x[0].upper()} {x[1].upper()} {x[-1]}" for x in tickers_split]
46
+ tickers = list(set(tickers))
47
+
48
+ if universe == Universe.GLOBAL: # add etf tickers
49
+ df = qis.load_df_from_excel(file_name=file_name, local_path=local_path, sheet_name='etfs')
50
+ for ticker, country in zip(df['Primary Ticker**'].astype(str), df['Country'].astype(str)):
51
+ if not ticker == 'nan' and not country == 'nan':
52
+ tickers.append(f"{ticker} {country} Equity")
53
+ return tickers
54
+
55
+
56
+ def create_universe_data(local_path: str = None,
57
+ file_name: str = FILE_NAME,
58
+ universes: List[Universe] = (Universe.SAMPLE, Universe.GLOBAL, ),
59
+ benchmark_tickers: List[str] = ('NDDUWI Index', 'LGTRTRUU Index',)
60
+ ) -> None:
61
+ """
62
+ read tickers from file_name with sheets
63
+ """
64
+ price_dfs = {}
65
+ for universe in universes:
66
+ tickers = get_universe_tickers(local_path=local_path, universe=universe, file_name=file_name)
67
+ price_timeseries, fundamentals, benchmark_prices = fetch_universe_data_for_tickers(tickers=tickers,
68
+ benchmark_tickers=benchmark_tickers)
69
+ price_dfs[f"{universe.value}_price"] = price_timeseries
70
+ price_dfs[f"{universe.value}_fundamentals"] = fundamentals
71
+ price_dfs['benchmark_prices'] = benchmark_prices # same for all
72
+ qis.save_df_to_excel(data=price_dfs, mode='a', file_name=FILE_NAME, local_path=local_path)
73
+
74
+
75
+ class UnitTests(Enum):
76
+ GET_UNIVERSE_TICKERS = 1
77
+ CREATE_UNIVERSE_DATA = 2
78
+ FETCH_UNIVERSE_FROM_LIST = 3
79
+
80
+
81
+ def run_unit_test(unit_test: UnitTests):
82
+
83
+ pd.set_option('display.max_rows', 500)
84
+ pd.set_option('display.max_columns', 500)
85
+ pd.set_option('display.width', 1000)
86
+
87
+ local_path = f"C://Users//artur//OneDrive//analytics//qdev//resources//basket_screener//"
88
+ # local_path = f"C://Users//uarts//Python//quant_strats//resources//basket_screener//"
89
+
90
+ if unit_test == UnitTests.GET_UNIVERSE_TICKERS:
91
+ sample = get_universe_tickers(local_path=local_path, universe=Universe.SAMPLE)
92
+ all = get_universe_tickers(local_path=local_path, universe=Universe.GLOBAL)
93
+ print(qis.assert_list_subset(all, sample))
94
+
95
+ elif unit_test == UnitTests.CREATE_UNIVERSE_DATA:
96
+ create_universe_data(local_path=local_path, universes=[Universe.NOV19])
97
+
98
+ elif unit_test == UnitTests.FETCH_UNIVERSE_FROM_LIST:
99
+ tickers = ['NVDA US Equity',
100
+ 'ADBE US Equity',
101
+ 'SMH US Equity',
102
+ 'SOXX US Equity',
103
+ 'XBI US Equity',
104
+ 'META US Equity',
105
+ 'MC FP Equity',
106
+ 'AMZN US Equity',
107
+ 'ELV US Equity',
108
+ 'TMO US Equity',
109
+ 'GOOG US Equity',
110
+ 'HSY US Equity',
111
+ 'MSFT US Equity',
112
+ 'PEP US Equity']
113
+ price_timeseries, fundamentals, benchmark_prices = fetch_universe_data_for_tickers(tickers=tickers)
114
+ print(price_timeseries)
115
+ print(fundamentals)
116
+
117
+
118
+ if __name__ == '__main__':
119
+
120
+ unit_test = UnitTests.FETCH_UNIVERSE_FROM_LIST
121
+
122
+ is_run_all_tests = False
123
+ if is_run_all_tests:
124
+ for unit_test in UnitTests:
125
+ run_unit_test(unit_test=unit_test)
126
+ else:
127
+ run_unit_test(unit_test=unit_test)
@@ -0,0 +1,75 @@
1
+ """
2
+ run screener on the fly
3
+ """
4
+
5
+ import pandas as pd
6
+ import qis as qis
7
+ from typing import List, Tuple
8
+ from enum import Enum
9
+ from quant_screener.sp_screener import UniverseScreener
10
+ from create_universe_data import fetch_universe_data_for_tickers
11
+
12
+
13
+ class UnitTests(Enum):
14
+ CREATE_BACKETS_FROM_LIST = 1
15
+
16
+
17
+ def run_unit_test(unit_test: UnitTests):
18
+
19
+ pd.set_option('display.max_rows', 500)
20
+ pd.set_option('display.max_columns', 500)
21
+ pd.set_option('display.width', 1000)
22
+
23
+ import matplotlib.pyplot as plt
24
+ import seaborn as sns
25
+ local_path = f"C://Users//artur//OneDrive//analytics//qdev//resources//basket_screener//"
26
+ # local_path = f"C://Users//uarts//Python//quant_strats//resources//basket_screener//"
27
+
28
+ if unit_test == UnitTests.CREATE_BACKETS_FROM_LIST:
29
+
30
+ tickers = ['NVDA US Equity',
31
+ 'ADBE US Equity',
32
+ 'SMH US Equity',
33
+ 'SOXX US Equity',
34
+ 'XBI US Equity',
35
+ 'META US Equity',
36
+ 'MC FP Equity',
37
+ 'AMZN US Equity',
38
+ 'ELV US Equity',
39
+ 'TMO US Equity',
40
+ 'GOOG US Equity',
41
+ 'HSY US Equity',
42
+ 'MSFT US Equity',
43
+ 'PEP US Equity']
44
+
45
+ prices, fundamentals, benchmarks = fetch_universe_data_for_tickers(tickers=tickers)
46
+
47
+ screener = UniverseScreener(prices=prices, fundamentals=fundamentals, benchmarks=benchmarks)
48
+
49
+ selected_baskets, top_scores, corrs = screener.compute_top_baskets_min_pairs(span=104,
50
+ freq='W-WED',
51
+ vol_span=13,
52
+ top_quantile=None,
53
+ cluster_threshold=1,
54
+ max_number_inclusions=3
55
+ )
56
+
57
+ sample_baskets = screener.create_baskets_outputs(selected_baskets=selected_baskets, top_scores=top_scores,
58
+ corrs=corrs)
59
+ print(sample_baskets)
60
+ sample_baskets.to_clipboard()
61
+ qis.save_df_to_excel(sample_baskets, file_name='sample_baskets', local_path=local_path, add_current_date=True)
62
+
63
+ plt.show()
64
+
65
+
66
+ if __name__ == '__main__':
67
+
68
+ unit_test = UnitTests.CREATE_BACKETS_FROM_LIST
69
+
70
+ is_run_all_tests = False
71
+ if is_run_all_tests:
72
+ for unit_test in UnitTests:
73
+ run_unit_test(unit_test=unit_test)
74
+ else:
75
+ run_unit_test(unit_test=unit_test)
@@ -0,0 +1,367 @@
1
+ """
2
+ bond universe screener
3
+ """
4
+ import pandas as pd
5
+ import numpy as np
6
+ import qis as qis
7
+ import scipy.cluster.hierarchy as sch
8
+ from dataclasses import dataclass
9
+ from typing import Tuple, List, Dict, Optional
10
+ from enum import Enum
11
+
12
+
13
+ FILE_NAME = 'PBA EQ'
14
+
15
+
16
+ class Universe(Enum):
17
+ GLOBAL = 'global'
18
+ SAMPLE = 'sample'
19
+ NOV19 = 'NOV19'
20
+
21
+
22
+ @dataclass
23
+ class UniverseScreener:
24
+ """
25
+ data container for bond universe
26
+ """
27
+ prices: pd.DataFrame
28
+ fundamentals: pd.DataFrame
29
+ benchmarks: pd.DataFrame
30
+
31
+ def __post_init__(self):
32
+ self.prices = self.prices.asfreq('B', method='ffill')
33
+ self.benchmarks = self.benchmarks.reindex(index=self.prices.index, method='ffill')
34
+
35
+ def get_implied_vols(self) -> pd.Series:
36
+ return self.fundamentals['implied_vol'].astype(float) / 100.0
37
+
38
+ def compute_realised_volatility(self, span: int = 13, freq: str = 'W-WED', af: float = 52.0) -> pd.Series:
39
+ # quarterly span for vol
40
+ returns = qis.to_returns(prices=self.prices, freq=freq, drop_first=True, is_log_returns=True)
41
+ vol = qis.compute_ewm_vol(data=returns, span=span, af=af)
42
+ return vol.iloc[-1, :]
43
+
44
+ def get_volatility(self, span: int = 52, freq: str = 'W-WED') -> pd.Series:
45
+ implied = self.get_implied_vols()
46
+ realised = self.compute_realised_volatility(span=span, freq=freq)
47
+ realised = realised.reindex(index=implied.index)
48
+ vol = pd.Series(np.where(np.isnan(implied.to_numpy()) == False, implied, realised), index=implied.index)
49
+ return vol
50
+
51
+ def estimate_r2_and_resid_corr(self, span: int = 52, freq: str = 'W-WED',
52
+ cluster_threshold: float = 5.0
53
+ ) -> pd.DataFrame:
54
+ y = qis.to_returns(prices=self.prices, freq=freq, drop_first=True, is_log_returns=True)
55
+ x = qis.to_returns(prices=self.benchmarks, freq=freq, drop_first=True, is_log_returns=True)
56
+ ewm_linear_model = qis.EwmLinearModel(x=x, y=y)
57
+ ewm_linear_model.fit(span=span, is_x_correlated=True)
58
+
59
+ loadings = {}
60
+ for factor in x.columns:
61
+ loadings[factor] = ewm_linear_model.loadings[factor].iloc[-1, :]
62
+ loadings = pd.DataFrame.from_dict(loadings, orient='columns')
63
+
64
+ # estimate R^2
65
+ r2_t = ewm_linear_model.get_model_ewm_r2(span=span)
66
+ # qis.plot_time_series(df=r_2)
67
+ r2 = r2_t.iloc[-1, :] # .sort_values()
68
+ residual_corr_pd, residual_avg_corr = ewm_linear_model.get_model_residuals_corrs(span=span)
69
+ residual_corr_pd[np.isfinite(residual_corr_pd.to_numpy()) == False] = 0.0
70
+ # sns.clustermap(residual_corr_pd)
71
+
72
+ X = residual_corr_pd.to_numpy()
73
+ Z = sch.ward(sch.distance.pdist(X))
74
+ # sch.dendrogram(Z)
75
+ clusters = sch.fcluster(Z, t=cluster_threshold, criterion='distance')
76
+ clusters = pd.Series(clusters, index=self.prices.columns)
77
+ print(f"number of clusters: {len(clusters.unique())}")
78
+
79
+ df = pd.concat([loadings, r2.rename('r2'), residual_avg_corr.rename('resid corr'), clusters.rename('clusters')
80
+ ], axis=1)
81
+ df = df.sort_values(by='r2')
82
+ return df
83
+
84
+ def compute_correlations(self, tickers: List[str], span: int = 52, freq: str = 'W-WED') -> pd.DataFrame:
85
+ returns = qis.to_returns(prices=self.prices[tickers], freq=freq, drop_first=True, is_log_returns=True)
86
+ corrs = qis.compute_ewm_covar(a=returns.to_numpy(), span=span, is_corr=True)
87
+ corrs = pd.DataFrame(corrs, index=tickers, columns=tickers)
88
+ return corrs
89
+
90
+ def compute_top_stocks(self,
91
+ span: int = 52,
92
+ freq: str = 'W-WED',
93
+ vol_span: int = 13,
94
+ cluster_threshold: float = 5.0,
95
+ top_quantile: Optional[float] = 0.75
96
+ ) -> Tuple[pd.DataFrame, pd.DataFrame]:
97
+ """
98
+ compute correlation factors and vol factor
99
+ take integrated scores on low rs, resid correlation and high vol vol
100
+ """
101
+ correlation_factors = self.estimate_r2_and_resid_corr(span=span, freq=freq, cluster_threshold=cluster_threshold)
102
+ vols = self.get_volatility(span=vol_span, freq=freq).rename('implied_vol')
103
+
104
+ # compute scores for all universe
105
+ r2_score = qis.df_to_cross_sectional_score(1.0 - correlation_factors['r2'], is_sorted=True).rename('r2 score') # the more the better
106
+ resid_corr = qis.df_to_cross_sectional_score(1.0 - correlation_factors['resid corr'], is_sorted=True).rename('resid corr score') # the more the better
107
+ vol = qis.df_to_cross_sectional_score(vols, is_sorted=True).rename('vol score')
108
+ scores = pd.concat([r2_score, resid_corr, vol], axis=1)
109
+ # select top subset
110
+ if top_quantile is not None:
111
+ top_scores = qis.select_top_integrated_scores(scores=scores, top_quantile=top_quantile).copy()
112
+ else:
113
+ top_scores = scores
114
+ # merge outputs
115
+ all_scores = pd.concat([correlation_factors, vols], axis=1).reindex(index=top_scores.index)
116
+ top_scores = pd.concat([top_scores, all_scores], axis=1)
117
+ # add correlations
118
+ corrs = self.compute_correlations(tickers=top_scores.index.to_list(), span=span, freq=freq)
119
+ return top_scores, corrs
120
+
121
+ def compute_top_baskets(self, span: int = 52, freq: str = 'W-WED',
122
+ vol_span: int = 13,
123
+ cluster_threshold: float = 5.0,
124
+ top_quantile: Optional[float] = 0.75,
125
+ basket_size: int = 3
126
+ ) -> Tuple[Dict[int, List[str]], pd.DataFrame, pd.DataFrame]:
127
+ top_scores, corrs = self.compute_top_stocks(span=span, freq=freq, vol_span=vol_span,
128
+ cluster_threshold=cluster_threshold, top_quantile=top_quantile)
129
+ assets = corrs.columns.to_list()
130
+ n_assets = len(assets)
131
+ available_indices = np.full(n_assets, True)
132
+ corrs_np = corrs.to_numpy()
133
+ selected_baskets = {}
134
+ for idx, asset in enumerate(corrs.columns):
135
+ selected_assets_basket = []
136
+ if available_indices[idx]: # select it first to the basket
137
+ selected_assets_basket.append(asset)
138
+ available_indices[idx] = False
139
+ #array_rank = np.argsort(corrs_np[:, idx]).argsort() # ranks by smalleest corr
140
+ #array_idx_rank = {array_rank[n]: n for n in np.arange(n_assets)} # assign rank to idx
141
+ #array_idx_rank = dict(sorted(array_idx_rank.items())) # sort by rank
142
+ array_idx_rank = np.argsort(corrs_np[:, idx]) # get indices of inreasing values
143
+ # print(array_idx_rank)
144
+ for ranked_idx in array_idx_rank:
145
+ if available_indices[ranked_idx]:
146
+ selected_assets_basket.append(assets[ranked_idx])
147
+ available_indices[ranked_idx] = False
148
+ if len(selected_assets_basket) == basket_size:
149
+ selected_baskets[idx+1] = selected_assets_basket
150
+ break
151
+ if np.all(available_indices == False): # all assets are taken
152
+ break
153
+ # print(f"idx={idx}: {selected_assets_basket}")
154
+
155
+ return selected_baskets, top_scores, corrs
156
+
157
+ def compute_top_baskets_min_pairs(self,
158
+ span: int = 52,
159
+ freq: str = 'W-WED',
160
+ vol_span: int = 13,
161
+ cluster_threshold: float = 5.0,
162
+ top_quantile: Optional[float] = 0.75,
163
+ basket_size: int = 3,
164
+ max_number_inclusions: int = 3
165
+ ) -> Tuple[Dict[int, List[str]], pd.DataFrame, pd.DataFrame]:
166
+ """
167
+ compute list of top stocks and their pairwise correlation
168
+ """
169
+ top_scores, corrs = self.compute_top_stocks(span=span, freq=freq, vol_span=vol_span,
170
+ cluster_threshold=cluster_threshold, top_quantile=top_quantile)
171
+ corrs_np = corrs.to_numpy()
172
+ corr_pairs = {}
173
+ # collect corrs into a series
174
+ for row, asset1 in enumerate(corrs.columns):
175
+ for column, asset2 in enumerate(corrs.columns):
176
+ if column > row:
177
+ corr_pairs[f"{asset1}-{asset2}"] = pd.Series((asset1, asset2,
178
+ top_scores.loc[asset1, 'clusters'], top_scores.loc[asset2, 'clusters'],
179
+ corrs_np[row, column]),
180
+ index=['asset1', 'asset2', 'cluster1', 'cluster2', 'corr'])
181
+
182
+ # sort on last value in tuple
183
+ corr_pairs = pd.DataFrame.from_dict(corr_pairs, orient='index').sort_values(by='corr')
184
+ # remove pairs of stocks from the same
185
+ same_cluster = corr_pairs['cluster1'] == corr_pairs['cluster2']
186
+ corr_pairs = corr_pairs.loc[same_cluster == False, :]
187
+
188
+ selected_assets = {} # we count selected assets and and how many times they are included
189
+ n_assets = len(corrs.columns)
190
+ n_pairs = len(corr_pairs.index)
191
+ available_indices = np.full(n_pairs, True)
192
+ selected_baskets = {}
193
+ next_basket_idx = 1
194
+
195
+ def check_inclusion_capacity(asset: str) -> bool:
196
+ if asset not in selected_assets.keys():
197
+ can_be_included = True
198
+ else:
199
+ if selected_assets[asset] < max_number_inclusions:
200
+ can_be_included = True
201
+ else:
202
+ can_be_included = False
203
+ return can_be_included
204
+
205
+ def select_asset(asset: str) -> None:
206
+ if asset in selected_assets.keys():
207
+ selected_assets[asset] += 1
208
+ else:
209
+ selected_assets[asset] = 1
210
+
211
+ for idx, record in enumerate(corr_pairs.to_dict('records')): # to_dict('records') generates list of dict
212
+ selected_assets_basket = []
213
+ selected_assets_clusters = [] # do not include stocks from the same cluster
214
+ if available_indices[idx]: # select the pair to the basket if both assets didn't enter existing baskets
215
+ asset1, asset2, cluster1, cluster2 = record['asset1'], record['asset2'], record['cluster1'], record['cluster2']
216
+ if check_inclusion_capacity(asset1) and check_inclusion_capacity(asset2):
217
+ selected_assets_basket.append(asset1)
218
+ select_asset(asset1)
219
+ selected_assets_clusters.append(cluster1)
220
+ selected_assets_basket.append(asset2)
221
+ select_asset(asset2)
222
+ selected_assets_clusters.append(cluster2)
223
+ available_indices[idx] = False
224
+
225
+ # look for next fill
226
+ for idx1 in np.arange(0, n_pairs): # selet the tird asset if it didn't entered existing assets
227
+ if available_indices[idx1]:
228
+ asset1, asset2, cluster1, cluster2 = corr_pairs.iloc[idx1, 0], corr_pairs.iloc[idx1, 1],\
229
+ corr_pairs.iloc[idx1, 2], corr_pairs.iloc[idx1, 3]
230
+ if check_inclusion_capacity(asset1) and cluster1 not in selected_assets_clusters:
231
+ selected_assets_basket.append(asset1)
232
+ select_asset(asset1)
233
+ selected_assets_clusters.append(cluster1)
234
+ available_indices[idx1] = False
235
+ if len(selected_assets_basket) == basket_size:
236
+ selected_baskets[next_basket_idx] = selected_assets_basket
237
+ next_basket_idx += 1
238
+ break
239
+ if check_inclusion_capacity(asset2) and cluster2 not in selected_assets_clusters:
240
+ selected_assets_basket.append(asset2)
241
+ select_asset(asset2)
242
+ selected_assets_clusters.append(cluster2)
243
+ available_indices[idx1] = False
244
+ if len(selected_assets_basket) == basket_size:
245
+ selected_baskets[next_basket_idx] = selected_assets_basket
246
+ next_basket_idx += 1
247
+ break
248
+ if len(selected_assets) == n_assets or np.all(available_indices == False): # all assets are taken
249
+ break
250
+ return selected_baskets, top_scores, corrs
251
+
252
+ def create_baskets_outputs(self, selected_baskets: Dict[int, List[str]],
253
+ top_scores: pd.DataFrame,
254
+ corrs: pd.DataFrame
255
+ ) -> pd.DataFrame:
256
+ df_tickers = {}
257
+ df_names = {}
258
+ impled_vols = {}
259
+ asset_corrs = {}
260
+ industry_sector = {}
261
+ id_isin = {}
262
+ clusters = {}
263
+ column_names = [f"Asset {n+1}" for n in np.arange(len(selected_baskets[list(selected_baskets.keys())[0]]))]
264
+ for idx, basket in selected_baskets.items():
265
+ df_tickers[f"basket {idx}"] = pd.Series(basket, index=column_names)
266
+ rename_map = dict(zip(basket, column_names))
267
+ df_names[f"basket {idx}"] = self.fundamentals.loc[basket, 'name'].rename(rename_map)
268
+ impled_vols[f"basket {idx}"] = self.fundamentals.loc[basket, 'implied_vol'].rename(rename_map)
269
+ industry_sector[f"basket {idx}"] = self.fundamentals.loc[basket, 'sector'].rename(rename_map)
270
+ id_isin[f"basket {idx}"] = self.fundamentals.loc[basket, 'isin'].rename(rename_map)
271
+ clusters[f"basket {idx}"] = top_scores.loc[basket, 'clusters'].rename(rename_map)
272
+ asset_corrs[f"basket {idx}"] = pd.Series(dict(corr_1_2=corrs.loc[basket[0], basket[1]],
273
+ corr_1_3=corrs.loc[basket[0], basket[2]],
274
+ corr_2_3=corrs.loc[basket[1], basket[2]]))
275
+
276
+ df_tickers = pd.DataFrame.from_dict(df_tickers, orient='index')
277
+ df_names = pd.DataFrame.from_dict(df_names, orient='index')
278
+ impled_vols = pd.DataFrame.from_dict(impled_vols, orient='index')
279
+ asset_corrs = pd.DataFrame.from_dict(asset_corrs, orient='index')
280
+ industry_sector = pd.DataFrame.from_dict(industry_sector, orient='index')
281
+ id_isin = pd.DataFrame.from_dict(id_isin, orient='index')
282
+ clusters = pd.DataFrame.from_dict(clusters, orient='index')
283
+ dfs = {'BBG Tickers': df_tickers, 'Names': df_names, 'Implied vols': impled_vols,
284
+ 'Correlations': asset_corrs,
285
+ 'Sector': industry_sector, 'ISIN': id_isin, 'Clusters': clusters}
286
+ dfs = pd.concat(dfs, axis=1)
287
+ return dfs
288
+
289
+
290
+ def load_universe_screener(local_path: str,
291
+ universe: Universe = Universe.SAMPLE,
292
+ file_name: str = FILE_NAME
293
+ ) -> UniverseScreener:
294
+ dataset_keys = [f"{universe.value}_price", f"{universe.value}_fundamentals", 'benchmark_prices']
295
+ dfs = qis.load_df_dict_from_excel(file_name=file_name, dataset_keys=dataset_keys, local_path=local_path)
296
+
297
+ prices = dfs[f"{universe.value}_price"].asfreq('B', method='ffill').ffill()
298
+ fundamentals = dfs[f"{universe.value}_fundamentals"]
299
+ benchmarks = dfs[f"benchmark_prices"].asfreq('B', method='ffill').ffill()
300
+
301
+ fundamentals = fundamentals.reindex(index=prices.columns)
302
+ universe_screener = UniverseScreener(prices=prices, fundamentals=fundamentals, benchmarks=benchmarks)
303
+ return universe_screener
304
+
305
+
306
+ class UnitTests(Enum):
307
+ RUN_UNIVERSE = 1
308
+ CREATE_BASKETS = 2
309
+ CREATE_BASKETS2 = 3
310
+
311
+
312
+ def run_unit_test(unit_test: UnitTests):
313
+
314
+ pd.set_option('display.max_rows', 500)
315
+ pd.set_option('display.max_columns', 500)
316
+ pd.set_option('display.width', 1000)
317
+
318
+ import matplotlib.pyplot as plt
319
+ import seaborn as sns
320
+ local_path = f"C://Users//artur//OneDrive//analytics//qdev//resources//basket_screener//"
321
+ # local_path = f"C://Users//uarts//Python//quant_strats//resources//basket_screener//"
322
+
323
+ screener = load_universe_screener(local_path=local_path, universe=Universe.NOV19)
324
+
325
+ if unit_test == UnitTests.RUN_UNIVERSE:
326
+ implied = screener.get_implied_vols().rename('Implied Vol')
327
+ realised = screener.compute_realised_volatility().rename('Realised Vol')
328
+ df = pd.concat([realised, implied], axis=1).dropna()
329
+ with sns.axes_style('darkgrid'):
330
+ fig, ax = plt.subplots(1, 1, figsize=(8, 6))
331
+ qis.plot_scatter(df=df,
332
+ full_sample_order=1,
333
+ fit_intercept=False,
334
+ title='Implied volatility vs Realised volatility',
335
+ alpha_format='{0:+0.2%}',
336
+ ax=ax)
337
+
338
+ elif unit_test == UnitTests.CREATE_BASKETS:
339
+ # selected_baskets, top_scores, corrs = screener.compute_top_baskets(top_quantile=0.50, cluster_threshold=7.0)
340
+ selected_baskets, top_scores, corrs = screener.compute_top_baskets_min_pairs(top_quantile=0.44, cluster_threshold=7.0)
341
+ for key, value in selected_baskets.items():
342
+ print(f"basket {key}: {value}")
343
+
344
+ baskets = screener.create_baskets_outputs(selected_baskets=selected_baskets, top_scores=top_scores, corrs=corrs)
345
+ correlation_factors = screener.estimate_r2_and_resid_corr(cluster_threshold=7.0)
346
+ data = dict(baskets=baskets, corrs=corrs, top_scores=top_scores, correlation_factors=correlation_factors)
347
+ qis.save_df_to_excel(data=data, file_name='selected_baskets_3', local_path=local_path, add_current_date=True)
348
+
349
+ elif unit_test == UnitTests.CREATE_BASKETS2:
350
+ selected_baskets, top_scores, corrs = screener.compute_top_baskets_min_pairs(top_quantile=None, cluster_threshold=1)
351
+ sample_baskets = screener.create_baskets_outputs(selected_baskets=selected_baskets, top_scores=top_scores, corrs=corrs)
352
+ print(sample_baskets)
353
+ qis.save_df_to_excel(sample_baskets, file_name='sample_baskets', local_path=local_path, add_current_date=True)
354
+
355
+ plt.show()
356
+
357
+
358
+ if __name__ == '__main__':
359
+
360
+ unit_test = UnitTests.CREATE_BASKETS2
361
+
362
+ is_run_all_tests = False
363
+ if is_run_all_tests:
364
+ for unit_test in UnitTests:
365
+ run_unit_test(unit_test=unit_test)
366
+ else:
367
+ run_unit_test(unit_test=unit_test)
@@ -6,6 +6,7 @@ import pandas as pd
6
6
  import matplotlib.pyplot as plt
7
7
  import seaborn as sns
8
8
  import qis as qis
9
+ from qis import PerfStat
9
10
  from enum import Enum
10
11
  from typing import Tuple, Dict
11
12
  from optimalportfolios import rolling_maximize_cara_mixture
@@ -69,6 +70,7 @@ class LocalTests(Enum):
69
70
  CONSTRAINTS = 1
70
71
  MAX_CARRA = 2
71
72
  PLOT_MIXURE = 3
73
+ PE_PERFORMANCE = 4
72
74
 
73
75
 
74
76
  @qis.timer
@@ -161,11 +163,12 @@ def run_local_test(local_test: LocalTests):
161
163
  else:
162
164
  raise NotImplementedError
163
165
 
164
- rolling_covar_data = covar_estimator.fit_rolling_covars(
165
- prices=universe_data.get_saa_prices(apply_unsmoothing_for_pe=apply_unsmoothing_for_pe),
166
- risk_factor_prices=universe_data.get_risk_factors(),
167
- time_period=time_period)
168
- saa_taa_covar = rolling_covar_data.y_covars
166
+ if local_test != LocalTests.PE_PERFORMANCE:
167
+ rolling_covar_data = covar_estimator.fit_rolling_covars(
168
+ prices=universe_data.get_saa_prices(apply_unsmoothing_for_pe=apply_unsmoothing_for_pe),
169
+ risk_factor_prices=universe_data.get_risk_factors(),
170
+ time_period=time_period)
171
+ saa_taa_covar = rolling_covar_data.y_covars
169
172
 
170
173
  if local_test == LocalTests.CONSTRAINTS:
171
174
 
@@ -263,6 +266,43 @@ def run_local_test(local_test: LocalTests):
263
266
 
264
267
  plt.show()
265
268
 
269
+ elif local_test == LocalTests.PE_PERFORMANCE:
270
+
271
+ prices0 = universe_data.get_saa_prices(apply_unsmoothing_for_pe=False)
272
+ pe_reported = prices0[["Private Equity", "Private Debt"]].rename({"Private Equity": 'PE reported', "Private Debt": 'PD reported'}, axis=1)
273
+ benchmark_price = prices0["North America"].rename("S&P500")
274
+
275
+ prices1 = universe_data.get_saa_prices(apply_unsmoothing_for_pe=True)
276
+ pe_unsmoothed = prices1[["Private Equity", "Private Debt"]].rename({"Private Equity": 'PE unsmoothed', "Private Debt": 'PD unsmoothed'}, axis=1)
277
+
278
+ prices = pd.concat([pe_reported.iloc[:, 0], pe_unsmoothed.iloc[:, 0],
279
+ pe_reported.iloc[:, 1], pe_unsmoothed.iloc[:, 1]], axis=1)
280
+
281
+ perf_columns = [PerfStat.PA_RETURN,
282
+ PerfStat.VOL,
283
+ PerfStat.SHARPE_RF0,
284
+ PerfStat.MAX_DD,
285
+ PerfStat.SKEWNESS,
286
+ PerfStat.KURTOSIS,
287
+ PerfStat.ALPHA_AN,
288
+ PerfStat.BETA,
289
+ PerfStat.R2,
290
+ PerfStat.ALPHA_PVALUE]
291
+
292
+ prices = prices.loc['31Dec2004':, :]
293
+ qis.plot_ra_perf_table_benchmark(prices=prices, benchmark_price=benchmark_price,
294
+ perf_params=qis.PerfParams(freq='QE', alpha_an_factor=4),
295
+ perf_columns=perf_columns)
296
+ df = qis.to_returns(prices=pd.concat([benchmark_price,prices], axis=1).dropna(), freq='QE')
297
+ with sns.axes_style("darkgrid"):
298
+ qis.plot_histogram(df, legend_stats=qis.LegendStats.AVG_STD,
299
+ xvar_format='{:.1%}',
300
+ title='QUarterly returns',
301
+ add_data_std_pdf=True)
302
+
303
+ plt.show()
304
+
305
+
266
306
  if __name__ == '__main__':
267
307
 
268
- run_local_test(local_test=LocalTests.MAX_CARRA)
308
+ run_local_test(local_test=LocalTests.PE_PERFORMANCE)
@@ -195,4 +195,4 @@ def run_local_test(local_test: LocalTests):
195
195
 
196
196
  if __name__ == '__main__':
197
197
 
198
- run_local_test(local_test=LocalTests.PE_PREMIA)
198
+ run_local_test(local_test=LocalTests.PE_PERFORMANCE)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "my-github-tests"
7
- version = "1.0.2"
7
+ version = "1.0.3"
8
8
  description = "my github tests"
9
9
  authors = [
10
10
  {name = "AA SS", email = "your.email@example.com"}