quantlite 0.9.0__tar.gz → 1.0.0__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 (140) hide show
  1. {quantlite-0.9.0/src/quantlite.egg-info → quantlite-1.0.0}/PKG-INFO +57 -1
  2. {quantlite-0.9.0 → quantlite-1.0.0}/README.md +56 -0
  3. {quantlite-0.9.0 → quantlite-1.0.0}/pyproject.toml +1 -1
  4. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/__init__.py +17 -1
  5. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/antifragile/__init__.py +42 -22
  6. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/ergodicity/__init__.py +30 -16
  7. quantlite-1.0.0/src/quantlite/pipeline.py +338 -0
  8. quantlite-1.0.0/src/quantlite/regime_integration/__init__.py +31 -0
  9. quantlite-1.0.0/src/quantlite/regime_integration/portfolio.py +267 -0
  10. quantlite-1.0.0/src/quantlite/regime_integration/reporting.py +204 -0
  11. quantlite-1.0.0/src/quantlite/regime_integration/risk.py +212 -0
  12. {quantlite-0.9.0 → quantlite-1.0.0/src/quantlite.egg-info}/PKG-INFO +57 -1
  13. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite.egg-info/SOURCES.txt +7 -0
  14. quantlite-1.0.0/tests/test_pipeline.py +165 -0
  15. quantlite-1.0.0/tests/test_regime_integration.py +287 -0
  16. {quantlite-0.9.0 → quantlite-1.0.0}/LICENSE +0 -0
  17. {quantlite-0.9.0 → quantlite-1.0.0}/setup.cfg +0 -0
  18. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/backtesting/__init__.py +0 -0
  19. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/backtesting/analysis.py +0 -0
  20. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/backtesting/engine.py +0 -0
  21. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/backtesting/legacy.py +0 -0
  22. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/backtesting/signals.py +0 -0
  23. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/contagion/__init__.py +0 -0
  24. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/core/__init__.py +0 -0
  25. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/core/types.py +0 -0
  26. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/crypto/__init__.py +0 -0
  27. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/crypto/exchange.py +0 -0
  28. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/crypto/onchain.py +0 -0
  29. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/crypto/stablecoin.py +0 -0
  30. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/__init__.py +0 -0
  31. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/base.py +0 -0
  32. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/cache.py +0 -0
  33. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/crypto.py +0 -0
  34. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/fred.py +0 -0
  35. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/local.py +0 -0
  36. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/registry.py +0 -0
  37. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data/yahoo.py +0 -0
  38. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/data_generation.py +0 -0
  39. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/dependency/__init__.py +0 -0
  40. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/dependency/clustering.py +0 -0
  41. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/dependency/copulas.py +0 -0
  42. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/dependency/correlation.py +0 -0
  43. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/distributions/__init__.py +0 -0
  44. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/distributions/fat_tails.py +0 -0
  45. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/diversification/__init__.py +0 -0
  46. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/factors/__init__.py +0 -0
  47. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/factors/classical.py +0 -0
  48. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/factors/custom.py +0 -0
  49. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/factors/tail_risk.py +0 -0
  50. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/forensics/__init__.py +0 -0
  51. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/instruments/__init__.py +0 -0
  52. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/instruments/bond_pricing.py +0 -0
  53. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/instruments/exotic_options.py +0 -0
  54. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/instruments/option_pricing.py +0 -0
  55. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/metrics.py +0 -0
  56. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/monte_carlo.py +0 -0
  57. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/network/__init__.py +0 -0
  58. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/overfit/__init__.py +0 -0
  59. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/portfolio/__init__.py +0 -0
  60. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/portfolio/optimisation.py +0 -0
  61. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/portfolio/rebalancing.py +0 -0
  62. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/regimes/__init__.py +0 -0
  63. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/regimes/changepoint.py +0 -0
  64. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/regimes/conditional.py +0 -0
  65. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/regimes/hmm.py +0 -0
  66. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/report/__init__.py +0 -0
  67. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/report/html_renderer.py +0 -0
  68. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/report/pdf_renderer.py +0 -0
  69. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/report/sections.py +0 -0
  70. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/report/tearsheet.py +0 -0
  71. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/resample/__init__.py +0 -0
  72. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/risk/__init__.py +0 -0
  73. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/risk/evt.py +0 -0
  74. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/risk/metrics.py +0 -0
  75. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/scenarios/__init__.py +0 -0
  76. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/simulation/__init__.py +0 -0
  77. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/simulation/copula_mc.py +0 -0
  78. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/simulation/evt_simulation.py +0 -0
  79. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/simulation/regime_mc.py +0 -0
  80. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/visualisation.py +0 -0
  81. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/__init__.py +0 -0
  82. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/dependency.py +0 -0
  83. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/plotly_backend/__init__.py +0 -0
  84. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/plotly_backend/dependency.py +0 -0
  85. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/plotly_backend/portfolio.py +0 -0
  86. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/plotly_backend/regimes.py +0 -0
  87. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/plotly_backend/risk.py +0 -0
  88. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/plotly_backend/theme.py +0 -0
  89. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/portfolio.py +0 -0
  90. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/regimes.py +0 -0
  91. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/risk.py +0 -0
  92. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite/viz/theme.py +0 -0
  93. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite.egg-info/dependency_links.txt +0 -0
  94. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite.egg-info/requires.txt +0 -0
  95. {quantlite-0.9.0 → quantlite-1.0.0}/src/quantlite.egg-info/top_level.txt +0 -0
  96. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_analysis.py +0 -0
  97. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_antifragile.py +0 -0
  98. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_backtesting.py +0 -0
  99. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_changepoint.py +0 -0
  100. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_clustering.py +0 -0
  101. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_conditional.py +0 -0
  102. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_contagion.py +0 -0
  103. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_copulas.py +0 -0
  104. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_correlation.py +0 -0
  105. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_crypto_exchange.py +0 -0
  106. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_crypto_onchain.py +0 -0
  107. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_crypto_stablecoin.py +0 -0
  108. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_data_connectors.py +0 -0
  109. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_data_generation.py +0 -0
  110. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_diversification.py +0 -0
  111. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_engine.py +0 -0
  112. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_ergodicity.py +0 -0
  113. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_evt.py +0 -0
  114. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_factors_classical.py +0 -0
  115. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_factors_custom.py +0 -0
  116. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_factors_tail_risk.py +0 -0
  117. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_fat_tails.py +0 -0
  118. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_forensics.py +0 -0
  119. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_hmm.py +0 -0
  120. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_instruments.py +0 -0
  121. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_metrics.py +0 -0
  122. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_monte_carlo.py +0 -0
  123. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_network.py +0 -0
  124. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_optimisation.py +0 -0
  125. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_overfit.py +0 -0
  126. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_plotly_viz.py +0 -0
  127. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_rebalancing.py +0 -0
  128. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_report.py +0 -0
  129. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_resample.py +0 -0
  130. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_risk_metrics.py +0 -0
  131. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_scenarios.py +0 -0
  132. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_signals.py +0 -0
  133. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_sim_copula.py +0 -0
  134. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_sim_evt.py +0 -0
  135. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_sim_regime.py +0 -0
  136. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_visualisation.py +0 -0
  137. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_viz.py +0 -0
  138. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_viz_dependency.py +0 -0
  139. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_viz_portfolio.py +0 -0
  140. {quantlite-0.9.0 → quantlite-1.0.0}/tests/test_viz_regimes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quantlite
3
- Version: 0.9.0
3
+ Version: 1.0.0
4
4
  Summary: A fat-tail-native quantitative finance toolkit: EVT, risk metrics, and honest modelling for markets that bite.
5
5
  Author-email: Prasant Sudhakaran <code@prasant.net>
6
6
  License: MIT License
@@ -1096,6 +1096,62 @@ print(f"Tail diversification: {td['tail_diversification']:.3f}")
1096
1096
  | `quantlite.network` | Correlation networks, eigenvector centrality, cascade simulation, community detection |
1097
1097
  | `quantlite.diversification` | Effective Number of Bets, entropy diversification, tail diversification, diversification ratio, Herfindahl index |
1098
1098
 
1099
+ ## v1.0: The Dream API
1100
+
1101
+ QuantLite v1.0 introduces the **Dream API**, a five-function pipeline that chains the entire quant workflow:
1102
+
1103
+ ```python
1104
+ import quantlite as ql
1105
+
1106
+ data = ql.fetch(["AAPL", "BTC-USD", "GLD", "TLT"], period="5y")
1107
+ regimes = ql.detect_regimes(data, n_regimes=3)
1108
+ weights = ql.construct_portfolio(data, regime_aware=True, regimes=regimes)
1109
+ result = ql.backtest(data, weights)
1110
+ ql.tearsheet(result, regimes=regimes, save="portfolio.txt")
1111
+ ```
1112
+
1113
+ ### Regime-Aware Portfolio Construction
1114
+
1115
+ Weights automatically tilt defensive during crisis regimes, increasing allocations to bonds and gold while reducing equity exposure:
1116
+
1117
+ ![Pipeline Equity Curve](https://raw.githubusercontent.com/prasants/QuantLite/main/docs/images/pipeline_equity_curve.png)
1118
+
1119
+ ### Regime Risk Analysis
1120
+
1121
+ VaR, CVaR, volatility, skewness, and kurtosis computed separately for each market regime:
1122
+
1123
+ ![Regime Risk Summary](https://raw.githubusercontent.com/prasants/QuantLite/main/docs/images/regime_risk_summary.png)
1124
+
1125
+ ### Regime-Filtered Backtesting
1126
+
1127
+ Different weight sets applied per regime, with full performance attribution:
1128
+
1129
+ ![Regime Filtered Backtest](https://raw.githubusercontent.com/prasants/QuantLite/main/docs/images/regime_filtered_backtest.png)
1130
+
1131
+ ### v1.0 Module Reference
1132
+
1133
+ | Module | Description |
1134
+ |--------|-------------|
1135
+ | `quantlite.pipeline` | Dream API: `fetch`, `detect_regimes`, `construct_portfolio`, `backtest`, `tearsheet` |
1136
+ | `quantlite.regime_integration` | Regime-conditional risk, defensive portfolio tilting, filtered backtesting, tearsheets |
1137
+ | `quantlite.regimes` | HMM regime detection, Bayesian changepoint detection, conditional metrics |
1138
+ | `quantlite.portfolio` | Markowitz, CVaR, risk parity, HRP, Black-Litterman, Kelly optimisation |
1139
+ | `quantlite.backtesting` | Multi-asset engine with circuit breakers, slippage, regime-aware signals |
1140
+ | `quantlite.risk` | VaR, CVaR, Sortino, Calmar, omega ratio, tail ratio, drawdown analysis |
1141
+ | `quantlite.data` | Unified fetching: Yahoo Finance, CCXT, FRED, local files |
1142
+ | `quantlite.distributions` | Student-t, stable, GPD, GEV fitting and simulation |
1143
+ | `quantlite.simulation` | Fat-tail Monte Carlo: EVT-based, copula-based engines |
1144
+ | `quantlite.viz` | Stephen Few-inspired charts: regimes, portfolios, risk dashboards |
1145
+ | `quantlite.factors` | Classical factors, custom factors, tail risk factors |
1146
+ | `quantlite.ergodicity` | Time-average vs ensemble-average growth, Kelly sizing |
1147
+ | `quantlite.antifragile` | Barbell metrics, convexity scores, stress testing |
1148
+ | `quantlite.scenarios` | Historical, hypothetical, and Monte Carlo scenario analysis |
1149
+ | `quantlite.forensics` | Overfitting detection, data snooping tests, walk-forward analysis |
1150
+ | `quantlite.contagion` | CoVaR, Delta CoVaR, MES, Granger causality |
1151
+ | `quantlite.network` | Correlation networks, centrality, cascade simulation |
1152
+ | `quantlite.diversification` | Effective Number of Bets, entropy, tail diversification |
1153
+ | `quantlite.crypto` | On-chain risk, stablecoin depeg, exchange risk scoring |
1154
+
1099
1155
  ## Design Philosophy
1100
1156
 
1101
1157
  1. **Fat tails are the default.** Gaussian assumptions are explicitly opt-in, never implicit.
@@ -1015,6 +1015,62 @@ print(f"Tail diversification: {td['tail_diversification']:.3f}")
1015
1015
  | `quantlite.network` | Correlation networks, eigenvector centrality, cascade simulation, community detection |
1016
1016
  | `quantlite.diversification` | Effective Number of Bets, entropy diversification, tail diversification, diversification ratio, Herfindahl index |
1017
1017
 
1018
+ ## v1.0: The Dream API
1019
+
1020
+ QuantLite v1.0 introduces the **Dream API**, a five-function pipeline that chains the entire quant workflow:
1021
+
1022
+ ```python
1023
+ import quantlite as ql
1024
+
1025
+ data = ql.fetch(["AAPL", "BTC-USD", "GLD", "TLT"], period="5y")
1026
+ regimes = ql.detect_regimes(data, n_regimes=3)
1027
+ weights = ql.construct_portfolio(data, regime_aware=True, regimes=regimes)
1028
+ result = ql.backtest(data, weights)
1029
+ ql.tearsheet(result, regimes=regimes, save="portfolio.txt")
1030
+ ```
1031
+
1032
+ ### Regime-Aware Portfolio Construction
1033
+
1034
+ Weights automatically tilt defensive during crisis regimes, increasing allocations to bonds and gold while reducing equity exposure:
1035
+
1036
+ ![Pipeline Equity Curve](https://raw.githubusercontent.com/prasants/QuantLite/main/docs/images/pipeline_equity_curve.png)
1037
+
1038
+ ### Regime Risk Analysis
1039
+
1040
+ VaR, CVaR, volatility, skewness, and kurtosis computed separately for each market regime:
1041
+
1042
+ ![Regime Risk Summary](https://raw.githubusercontent.com/prasants/QuantLite/main/docs/images/regime_risk_summary.png)
1043
+
1044
+ ### Regime-Filtered Backtesting
1045
+
1046
+ Different weight sets applied per regime, with full performance attribution:
1047
+
1048
+ ![Regime Filtered Backtest](https://raw.githubusercontent.com/prasants/QuantLite/main/docs/images/regime_filtered_backtest.png)
1049
+
1050
+ ### v1.0 Module Reference
1051
+
1052
+ | Module | Description |
1053
+ |--------|-------------|
1054
+ | `quantlite.pipeline` | Dream API: `fetch`, `detect_regimes`, `construct_portfolio`, `backtest`, `tearsheet` |
1055
+ | `quantlite.regime_integration` | Regime-conditional risk, defensive portfolio tilting, filtered backtesting, tearsheets |
1056
+ | `quantlite.regimes` | HMM regime detection, Bayesian changepoint detection, conditional metrics |
1057
+ | `quantlite.portfolio` | Markowitz, CVaR, risk parity, HRP, Black-Litterman, Kelly optimisation |
1058
+ | `quantlite.backtesting` | Multi-asset engine with circuit breakers, slippage, regime-aware signals |
1059
+ | `quantlite.risk` | VaR, CVaR, Sortino, Calmar, omega ratio, tail ratio, drawdown analysis |
1060
+ | `quantlite.data` | Unified fetching: Yahoo Finance, CCXT, FRED, local files |
1061
+ | `quantlite.distributions` | Student-t, stable, GPD, GEV fitting and simulation |
1062
+ | `quantlite.simulation` | Fat-tail Monte Carlo: EVT-based, copula-based engines |
1063
+ | `quantlite.viz` | Stephen Few-inspired charts: regimes, portfolios, risk dashboards |
1064
+ | `quantlite.factors` | Classical factors, custom factors, tail risk factors |
1065
+ | `quantlite.ergodicity` | Time-average vs ensemble-average growth, Kelly sizing |
1066
+ | `quantlite.antifragile` | Barbell metrics, convexity scores, stress testing |
1067
+ | `quantlite.scenarios` | Historical, hypothetical, and Monte Carlo scenario analysis |
1068
+ | `quantlite.forensics` | Overfitting detection, data snooping tests, walk-forward analysis |
1069
+ | `quantlite.contagion` | CoVaR, Delta CoVaR, MES, Granger causality |
1070
+ | `quantlite.network` | Correlation networks, centrality, cascade simulation |
1071
+ | `quantlite.diversification` | Effective Number of Bets, entropy, tail diversification |
1072
+ | `quantlite.crypto` | On-chain risk, stablecoin depeg, exchange risk scoring |
1073
+
1018
1074
  ## Design Philosophy
1019
1075
 
1020
1076
  1. **Fat tails are the default.** Gaussian assumptions are explicitly opt-in, never implicit.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quantlite"
7
- version = "0.9.0"
7
+ version = "1.0.0"
8
8
  description = "A fat-tail-native quantitative finance toolkit: EVT, risk metrics, and honest modelling for markets that bite."
9
9
  requires-python = ">=3.9"
10
10
  license = { file = "LICENSE" }
@@ -6,7 +6,7 @@ portfolio optimisation, multi-asset backtesting, and
6
6
  Stephen Few-inspired visualisation.
7
7
  """
8
8
 
9
- __version__ = "0.2.0"
9
+ __version__ = "1.0.0"
10
10
 
11
11
  from .backtesting import (
12
12
  BacktestConfig,
@@ -79,6 +79,14 @@ __all__ = [
79
79
  "crypto",
80
80
  # Fat-tail Monte Carlo simulation
81
81
  "simulation",
82
+ # Regime-aware integration
83
+ "regime_integration",
84
+ # Dream API (pipeline)
85
+ "fetch",
86
+ "detect_regimes",
87
+ "construct_portfolio",
88
+ "backtest",
89
+ "tearsheet",
82
90
  ]
83
91
 
84
92
  from . import ( # noqa: E402
@@ -90,7 +98,15 @@ from . import ( # noqa: E402
90
98
  forensics,
91
99
  network,
92
100
  overfit,
101
+ regime_integration,
93
102
  resample,
94
103
  scenarios,
95
104
  simulation,
96
105
  )
106
+ from .pipeline import ( # noqa: E402
107
+ backtest,
108
+ construct_portfolio,
109
+ detect_regimes,
110
+ tearsheet,
111
+ )
112
+ from .pipeline import fetch as fetch # noqa: E402
@@ -218,44 +218,40 @@ def barbell_allocation(
218
218
  def lindy_estimate(age: float, confidence: float = 0.95) -> dict[str, float]:
219
219
  """Estimate remaining life expectancy using the Lindy effect.
220
220
 
221
- For non-perishable entities (ideas, technologies, institutions),
222
- expected remaining lifespan is proportional to current age.
221
+ Models non-perishable entities (ideas, technologies, institutions)
222
+ with a Pareto survival distribution (alpha = 1). Under this model:
223
223
 
224
- Uses a Pareto-like survival model where the expected remaining
225
- life equals the current age (for the median estimate).
224
+ P(T > age + t | T > age) = age / (age + t)
225
+
226
+ Key properties:
227
+
228
+ * **Expected remaining life** = age (the longer it has survived,
229
+ the longer we expect it to last).
230
+ * **Lower bound at confidence level c**: the additional time *t*
231
+ such that we are *c*-confident the entity survives at least *t*
232
+ more units. Solve ``age / (age + t) = 1 - c`` to get
233
+ ``t = age * c / (1 - c)``.
226
234
 
227
235
  Parameters
228
236
  ----------
229
237
  age : float
230
238
  Current age of the entity (in any consistent unit).
231
239
  confidence : float
232
- Confidence level for the survival bound (default 0.95).
240
+ Confidence level for the survival lower bound (default 0.95).
233
241
 
234
242
  Returns
235
243
  -------
236
244
  dict
237
- Keys: 'age', 'expected_remaining' (median estimate),
238
- 'lower_bound' (at given confidence), 'total_expected'.
245
+ Keys: 'age', 'expected_remaining', 'lower_bound' (at the
246
+ given confidence), 'total_expected'.
239
247
  """
240
248
  if age <= 0:
241
249
  raise ValueError("age must be positive")
242
250
  if not 0 < confidence < 1:
243
251
  raise ValueError("confidence must be between 0 and 1")
244
252
 
245
- # Under Lindy (Pareto with alpha=1), expected remaining life = age
246
253
  expected_remaining = age
247
-
248
- # Lower bound: at confidence level, survival beyond this point
249
- # P(survive t more) = age / (age + t), so t = age * (1/p - 1)
250
- lower_bound = age * (1.0 / (1.0 - confidence) - 1.0) * (1.0 - confidence)
251
- # Simplifies to: age * confidence / (1 - confidence) * (1 - confidence) = age * confidence
252
- # Actually: P(T > age + t | T > age) = age / (age + t) for Pareto
253
- # Set this = 1 - confidence: age/(age+t) = 1 - confidence
254
- # t = age * confidence / (1 - confidence)
255
- lower_bound = age * (1.0 - confidence) / confidence
256
- # That's the point we're confident we'll reach (small value)
257
- # More useful: expected remaining at median
258
- # P(T > age + t | T > age) = 0.5 => t = age (median remaining = age)
254
+ lower_bound = age * confidence / (1.0 - confidence)
259
255
 
260
256
  return {
261
257
  "age": age,
@@ -268,11 +264,25 @@ def lindy_estimate(age: float, confidence: float = 0.95) -> dict[str, float]:
268
264
  def skin_in_game_score(
269
265
  manager_returns: ArrayLike,
270
266
  fund_returns: ArrayLike,
267
+ alignment_weight: float = 0.4,
268
+ downside_weight: float = 0.4,
269
+ asymmetry_weight: float = 0.2,
271
270
  ) -> dict[str, float]:
272
271
  """Measure principal-agent alignment via payoff asymmetry.
273
272
 
274
273
  Compares the manager's exposure to downside vs upside relative
275
- to the fund. A good score means the manager shares the pain.
274
+ to the fund. A good score means the manager shares the pain.
275
+
276
+ The composite score weights three components:
277
+
278
+ * **Alignment** (default 0.4): correlation between manager and fund
279
+ returns. Are incentives actually correlated?
280
+ * **Downside sharing** (default 0.4): when the fund loses, does the
281
+ manager bleed proportionally? This matters as much as alignment —
282
+ asymmetric downside is the hallmark of agency problems.
283
+ * **Upside asymmetry** (default 0.2): does the manager capture
284
+ disproportionate upside? A secondary check — some asymmetry is
285
+ expected (performance fees), but extreme values signal misalignment.
276
286
 
277
287
  Parameters
278
288
  ----------
@@ -280,6 +290,12 @@ def skin_in_game_score(
280
290
  Returns experienced by the manager (compensation-adjusted).
281
291
  fund_returns : array-like
282
292
  Returns experienced by the fund investors.
293
+ alignment_weight : float
294
+ Weight for the alignment (correlation) component (default 0.4).
295
+ downside_weight : float
296
+ Weight for the downside-sharing component (default 0.4).
297
+ asymmetry_weight : float
298
+ Weight for the upside-asymmetry component (default 0.2).
283
299
 
284
300
  Returns
285
301
  -------
@@ -317,7 +333,11 @@ def skin_in_game_score(
317
333
 
318
334
  # Composite score: high alignment + high downside sharing + low upside asymmetry = good
319
335
  # Normalise to [0, 1] approximately
320
- score = (alignment * 0.4) + (min(downside_sharing, 1.0) * 0.4) + (max(0, 1.0 - abs(upside_asymmetry - 1.0)) * 0.2)
336
+ score = (
337
+ alignment * alignment_weight
338
+ + min(downside_sharing, 1.0) * downside_weight
339
+ + max(0, 1.0 - abs(upside_asymmetry - 1.0)) * asymmetry_weight
340
+ )
321
341
 
322
342
  return {
323
343
  "alignment": alignment,
@@ -91,11 +91,13 @@ def ergodicity_gap(returns: ArrayLike) -> float:
91
91
  def kelly_fraction(returns: ArrayLike, risk_free: float = 0.0) -> float:
92
92
  """Compute the optimal Kelly fraction for geometric growth.
93
93
 
94
- The Kelly criterion maximises the expected logarithmic growth rate.
95
- For a simple binary-style approximation from empirical returns,
96
- we optimise f to maximise E[log(1 + f * (r - risk_free))].
94
+ The Kelly criterion maximises the expected logarithmic growth rate:
97
95
 
98
- Uses a numerical grid search over [0, 2] for robustness.
96
+ f* = argmax_f E[log(1 + f * (r - r_f))]
97
+
98
+ Uses ``scipy.optimize.minimize_scalar`` with bounded search on
99
+ [-0.5, 3.0]. Falls back to Brent-bounded optimisation if the
100
+ primary solve fails.
99
101
 
100
102
  Parameters
101
103
  ----------
@@ -110,24 +112,36 @@ def kelly_fraction(returns: ArrayLike, risk_free: float = 0.0) -> float:
110
112
  Optimal fraction of capital to deploy. Can be < 0 (short)
111
113
  or > 1 (leveraged).
112
114
  """
115
+ from scipy.optimize import minimize_scalar
116
+
113
117
  r = _to_array(returns)
114
118
  excess = r - risk_free
115
119
 
116
- # Grid search over fractions from -0.5 to 3.0
117
- fractions = np.linspace(-0.5, 3.0, 3500)
118
- best_f = 0.0
119
- best_g = -np.inf
120
-
121
- for f in fractions:
120
+ def neg_expected_log_growth(f: float) -> float:
122
121
  portfolio = 1.0 + f * excess
123
122
  if np.any(portfolio <= 0):
124
- continue
125
- g = np.mean(np.log(portfolio))
126
- if g > best_g:
127
- best_g = g
128
- best_f = f
123
+ return 1e10 # infeasible
124
+ return -float(np.mean(np.log(portfolio)))
125
+
126
+ bounds = (-0.5, 3.0)
127
+
128
+ result = minimize_scalar(
129
+ neg_expected_log_growth, bounds=bounds, method="bounded",
130
+ options={"xatol": 1e-8, "maxiter": 500},
131
+ )
132
+
133
+ if result.success:
134
+ return float(round(result.x, 4))
135
+
136
+ # Fallback: try again with Brent in the same interval
137
+ result2 = minimize_scalar(
138
+ neg_expected_log_growth, bracket=(-0.5, 0.5, 3.0), method="brent",
139
+ )
140
+ if result2.success and bounds[0] <= result2.x <= bounds[1]:
141
+ return float(round(result2.x, 4))
129
142
 
130
- return float(round(best_f, 4))
143
+ # Last resort: return 0 (no bet)
144
+ return 0.0
131
145
 
132
146
 
133
147
  def leverage_effect(