ml4t-diagnostic 0.1.0a1__py3-none-any.whl

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 (242) hide show
  1. ml4t/diagnostic/AGENT.md +25 -0
  2. ml4t/diagnostic/__init__.py +166 -0
  3. ml4t/diagnostic/backends/__init__.py +10 -0
  4. ml4t/diagnostic/backends/adapter.py +192 -0
  5. ml4t/diagnostic/backends/polars_backend.py +899 -0
  6. ml4t/diagnostic/caching/__init__.py +40 -0
  7. ml4t/diagnostic/caching/cache.py +331 -0
  8. ml4t/diagnostic/caching/decorators.py +131 -0
  9. ml4t/diagnostic/caching/smart_cache.py +339 -0
  10. ml4t/diagnostic/config/AGENT.md +24 -0
  11. ml4t/diagnostic/config/README.md +267 -0
  12. ml4t/diagnostic/config/__init__.py +219 -0
  13. ml4t/diagnostic/config/barrier_config.py +277 -0
  14. ml4t/diagnostic/config/base.py +301 -0
  15. ml4t/diagnostic/config/event_config.py +148 -0
  16. ml4t/diagnostic/config/feature_config.py +404 -0
  17. ml4t/diagnostic/config/multi_signal_config.py +55 -0
  18. ml4t/diagnostic/config/portfolio_config.py +215 -0
  19. ml4t/diagnostic/config/report_config.py +391 -0
  20. ml4t/diagnostic/config/sharpe_config.py +202 -0
  21. ml4t/diagnostic/config/signal_config.py +206 -0
  22. ml4t/diagnostic/config/trade_analysis_config.py +310 -0
  23. ml4t/diagnostic/config/validation.py +279 -0
  24. ml4t/diagnostic/core/__init__.py +29 -0
  25. ml4t/diagnostic/core/numba_utils.py +315 -0
  26. ml4t/diagnostic/core/purging.py +372 -0
  27. ml4t/diagnostic/core/sampling.py +471 -0
  28. ml4t/diagnostic/errors/__init__.py +205 -0
  29. ml4t/diagnostic/evaluation/AGENT.md +26 -0
  30. ml4t/diagnostic/evaluation/__init__.py +437 -0
  31. ml4t/diagnostic/evaluation/autocorrelation.py +531 -0
  32. ml4t/diagnostic/evaluation/barrier_analysis.py +1050 -0
  33. ml4t/diagnostic/evaluation/binary_metrics.py +910 -0
  34. ml4t/diagnostic/evaluation/dashboard.py +715 -0
  35. ml4t/diagnostic/evaluation/diagnostic_plots.py +1037 -0
  36. ml4t/diagnostic/evaluation/distribution/__init__.py +499 -0
  37. ml4t/diagnostic/evaluation/distribution/moments.py +299 -0
  38. ml4t/diagnostic/evaluation/distribution/tails.py +777 -0
  39. ml4t/diagnostic/evaluation/distribution/tests.py +470 -0
  40. ml4t/diagnostic/evaluation/drift/__init__.py +139 -0
  41. ml4t/diagnostic/evaluation/drift/analysis.py +432 -0
  42. ml4t/diagnostic/evaluation/drift/domain_classifier.py +517 -0
  43. ml4t/diagnostic/evaluation/drift/population_stability_index.py +310 -0
  44. ml4t/diagnostic/evaluation/drift/wasserstein.py +388 -0
  45. ml4t/diagnostic/evaluation/event_analysis.py +647 -0
  46. ml4t/diagnostic/evaluation/excursion.py +390 -0
  47. ml4t/diagnostic/evaluation/feature_diagnostics.py +873 -0
  48. ml4t/diagnostic/evaluation/feature_outcome.py +666 -0
  49. ml4t/diagnostic/evaluation/framework.py +935 -0
  50. ml4t/diagnostic/evaluation/metric_registry.py +255 -0
  51. ml4t/diagnostic/evaluation/metrics/AGENT.md +23 -0
  52. ml4t/diagnostic/evaluation/metrics/__init__.py +133 -0
  53. ml4t/diagnostic/evaluation/metrics/basic.py +160 -0
  54. ml4t/diagnostic/evaluation/metrics/conditional_ic.py +469 -0
  55. ml4t/diagnostic/evaluation/metrics/feature_outcome.py +475 -0
  56. ml4t/diagnostic/evaluation/metrics/ic_statistics.py +446 -0
  57. ml4t/diagnostic/evaluation/metrics/importance_analysis.py +338 -0
  58. ml4t/diagnostic/evaluation/metrics/importance_classical.py +375 -0
  59. ml4t/diagnostic/evaluation/metrics/importance_mda.py +371 -0
  60. ml4t/diagnostic/evaluation/metrics/importance_shap.py +715 -0
  61. ml4t/diagnostic/evaluation/metrics/information_coefficient.py +527 -0
  62. ml4t/diagnostic/evaluation/metrics/interactions.py +772 -0
  63. ml4t/diagnostic/evaluation/metrics/monotonicity.py +226 -0
  64. ml4t/diagnostic/evaluation/metrics/risk_adjusted.py +324 -0
  65. ml4t/diagnostic/evaluation/multi_signal.py +550 -0
  66. ml4t/diagnostic/evaluation/portfolio_analysis/__init__.py +83 -0
  67. ml4t/diagnostic/evaluation/portfolio_analysis/analysis.py +734 -0
  68. ml4t/diagnostic/evaluation/portfolio_analysis/metrics.py +589 -0
  69. ml4t/diagnostic/evaluation/portfolio_analysis/results.py +334 -0
  70. ml4t/diagnostic/evaluation/report_generation.py +824 -0
  71. ml4t/diagnostic/evaluation/signal_selector.py +452 -0
  72. ml4t/diagnostic/evaluation/stat_registry.py +139 -0
  73. ml4t/diagnostic/evaluation/stationarity/__init__.py +97 -0
  74. ml4t/diagnostic/evaluation/stationarity/analysis.py +518 -0
  75. ml4t/diagnostic/evaluation/stationarity/augmented_dickey_fuller.py +296 -0
  76. ml4t/diagnostic/evaluation/stationarity/kpss_test.py +308 -0
  77. ml4t/diagnostic/evaluation/stationarity/phillips_perron.py +365 -0
  78. ml4t/diagnostic/evaluation/stats/AGENT.md +43 -0
  79. ml4t/diagnostic/evaluation/stats/__init__.py +191 -0
  80. ml4t/diagnostic/evaluation/stats/backtest_overfitting.py +219 -0
  81. ml4t/diagnostic/evaluation/stats/bootstrap.py +228 -0
  82. ml4t/diagnostic/evaluation/stats/deflated_sharpe_ratio.py +591 -0
  83. ml4t/diagnostic/evaluation/stats/false_discovery_rate.py +295 -0
  84. ml4t/diagnostic/evaluation/stats/hac_standard_errors.py +108 -0
  85. ml4t/diagnostic/evaluation/stats/minimum_track_record.py +408 -0
  86. ml4t/diagnostic/evaluation/stats/moments.py +164 -0
  87. ml4t/diagnostic/evaluation/stats/rademacher_adjustment.py +436 -0
  88. ml4t/diagnostic/evaluation/stats/reality_check.py +155 -0
  89. ml4t/diagnostic/evaluation/stats/sharpe_inference.py +219 -0
  90. ml4t/diagnostic/evaluation/themes.py +330 -0
  91. ml4t/diagnostic/evaluation/threshold_analysis.py +957 -0
  92. ml4t/diagnostic/evaluation/trade_analysis.py +1136 -0
  93. ml4t/diagnostic/evaluation/trade_dashboard/__init__.py +32 -0
  94. ml4t/diagnostic/evaluation/trade_dashboard/app.py +315 -0
  95. ml4t/diagnostic/evaluation/trade_dashboard/export/__init__.py +18 -0
  96. ml4t/diagnostic/evaluation/trade_dashboard/export/csv.py +82 -0
  97. ml4t/diagnostic/evaluation/trade_dashboard/export/html.py +276 -0
  98. ml4t/diagnostic/evaluation/trade_dashboard/io.py +166 -0
  99. ml4t/diagnostic/evaluation/trade_dashboard/normalize.py +304 -0
  100. ml4t/diagnostic/evaluation/trade_dashboard/stats.py +386 -0
  101. ml4t/diagnostic/evaluation/trade_dashboard/style.py +79 -0
  102. ml4t/diagnostic/evaluation/trade_dashboard/tabs/__init__.py +21 -0
  103. ml4t/diagnostic/evaluation/trade_dashboard/tabs/patterns.py +354 -0
  104. ml4t/diagnostic/evaluation/trade_dashboard/tabs/shap_analysis.py +280 -0
  105. ml4t/diagnostic/evaluation/trade_dashboard/tabs/stat_validation.py +186 -0
  106. ml4t/diagnostic/evaluation/trade_dashboard/tabs/worst_trades.py +236 -0
  107. ml4t/diagnostic/evaluation/trade_dashboard/types.py +129 -0
  108. ml4t/diagnostic/evaluation/trade_shap/__init__.py +102 -0
  109. ml4t/diagnostic/evaluation/trade_shap/alignment.py +188 -0
  110. ml4t/diagnostic/evaluation/trade_shap/characterize.py +413 -0
  111. ml4t/diagnostic/evaluation/trade_shap/cluster.py +302 -0
  112. ml4t/diagnostic/evaluation/trade_shap/explain.py +208 -0
  113. ml4t/diagnostic/evaluation/trade_shap/hypotheses/__init__.py +23 -0
  114. ml4t/diagnostic/evaluation/trade_shap/hypotheses/generator.py +290 -0
  115. ml4t/diagnostic/evaluation/trade_shap/hypotheses/matcher.py +251 -0
  116. ml4t/diagnostic/evaluation/trade_shap/hypotheses/templates.yaml +467 -0
  117. ml4t/diagnostic/evaluation/trade_shap/models.py +386 -0
  118. ml4t/diagnostic/evaluation/trade_shap/normalize.py +116 -0
  119. ml4t/diagnostic/evaluation/trade_shap/pipeline.py +263 -0
  120. ml4t/diagnostic/evaluation/trade_shap_dashboard.py +283 -0
  121. ml4t/diagnostic/evaluation/trade_shap_diagnostics.py +588 -0
  122. ml4t/diagnostic/evaluation/validated_cv.py +535 -0
  123. ml4t/diagnostic/evaluation/visualization.py +1050 -0
  124. ml4t/diagnostic/evaluation/volatility/__init__.py +45 -0
  125. ml4t/diagnostic/evaluation/volatility/analysis.py +351 -0
  126. ml4t/diagnostic/evaluation/volatility/arch.py +258 -0
  127. ml4t/diagnostic/evaluation/volatility/garch.py +460 -0
  128. ml4t/diagnostic/integration/__init__.py +48 -0
  129. ml4t/diagnostic/integration/backtest_contract.py +671 -0
  130. ml4t/diagnostic/integration/data_contract.py +316 -0
  131. ml4t/diagnostic/integration/engineer_contract.py +226 -0
  132. ml4t/diagnostic/logging/__init__.py +77 -0
  133. ml4t/diagnostic/logging/logger.py +245 -0
  134. ml4t/diagnostic/logging/performance.py +234 -0
  135. ml4t/diagnostic/logging/progress.py +234 -0
  136. ml4t/diagnostic/logging/wandb.py +412 -0
  137. ml4t/diagnostic/metrics/__init__.py +9 -0
  138. ml4t/diagnostic/metrics/percentiles.py +128 -0
  139. ml4t/diagnostic/py.typed +1 -0
  140. ml4t/diagnostic/reporting/__init__.py +43 -0
  141. ml4t/diagnostic/reporting/base.py +130 -0
  142. ml4t/diagnostic/reporting/html_renderer.py +275 -0
  143. ml4t/diagnostic/reporting/json_renderer.py +51 -0
  144. ml4t/diagnostic/reporting/markdown_renderer.py +117 -0
  145. ml4t/diagnostic/results/AGENT.md +24 -0
  146. ml4t/diagnostic/results/__init__.py +105 -0
  147. ml4t/diagnostic/results/barrier_results/__init__.py +36 -0
  148. ml4t/diagnostic/results/barrier_results/hit_rate.py +304 -0
  149. ml4t/diagnostic/results/barrier_results/precision_recall.py +266 -0
  150. ml4t/diagnostic/results/barrier_results/profit_factor.py +297 -0
  151. ml4t/diagnostic/results/barrier_results/tearsheet.py +397 -0
  152. ml4t/diagnostic/results/barrier_results/time_to_target.py +305 -0
  153. ml4t/diagnostic/results/barrier_results/validation.py +38 -0
  154. ml4t/diagnostic/results/base.py +177 -0
  155. ml4t/diagnostic/results/event_results.py +349 -0
  156. ml4t/diagnostic/results/feature_results.py +787 -0
  157. ml4t/diagnostic/results/multi_signal_results.py +431 -0
  158. ml4t/diagnostic/results/portfolio_results.py +281 -0
  159. ml4t/diagnostic/results/sharpe_results.py +448 -0
  160. ml4t/diagnostic/results/signal_results/__init__.py +74 -0
  161. ml4t/diagnostic/results/signal_results/ic.py +581 -0
  162. ml4t/diagnostic/results/signal_results/irtc.py +110 -0
  163. ml4t/diagnostic/results/signal_results/quantile.py +392 -0
  164. ml4t/diagnostic/results/signal_results/tearsheet.py +456 -0
  165. ml4t/diagnostic/results/signal_results/turnover.py +213 -0
  166. ml4t/diagnostic/results/signal_results/validation.py +147 -0
  167. ml4t/diagnostic/signal/AGENT.md +17 -0
  168. ml4t/diagnostic/signal/__init__.py +69 -0
  169. ml4t/diagnostic/signal/_report.py +152 -0
  170. ml4t/diagnostic/signal/_utils.py +261 -0
  171. ml4t/diagnostic/signal/core.py +275 -0
  172. ml4t/diagnostic/signal/quantile.py +148 -0
  173. ml4t/diagnostic/signal/result.py +214 -0
  174. ml4t/diagnostic/signal/signal_ic.py +129 -0
  175. ml4t/diagnostic/signal/turnover.py +182 -0
  176. ml4t/diagnostic/splitters/AGENT.md +19 -0
  177. ml4t/diagnostic/splitters/__init__.py +36 -0
  178. ml4t/diagnostic/splitters/base.py +501 -0
  179. ml4t/diagnostic/splitters/calendar.py +421 -0
  180. ml4t/diagnostic/splitters/calendar_config.py +91 -0
  181. ml4t/diagnostic/splitters/combinatorial.py +1064 -0
  182. ml4t/diagnostic/splitters/config.py +322 -0
  183. ml4t/diagnostic/splitters/cpcv/__init__.py +57 -0
  184. ml4t/diagnostic/splitters/cpcv/combinations.py +119 -0
  185. ml4t/diagnostic/splitters/cpcv/partitioning.py +263 -0
  186. ml4t/diagnostic/splitters/cpcv/purge_engine.py +379 -0
  187. ml4t/diagnostic/splitters/cpcv/windows.py +190 -0
  188. ml4t/diagnostic/splitters/group_isolation.py +329 -0
  189. ml4t/diagnostic/splitters/persistence.py +316 -0
  190. ml4t/diagnostic/splitters/utils.py +207 -0
  191. ml4t/diagnostic/splitters/walk_forward.py +757 -0
  192. ml4t/diagnostic/utils/__init__.py +42 -0
  193. ml4t/diagnostic/utils/config.py +542 -0
  194. ml4t/diagnostic/utils/dependencies.py +318 -0
  195. ml4t/diagnostic/utils/sessions.py +127 -0
  196. ml4t/diagnostic/validation/__init__.py +54 -0
  197. ml4t/diagnostic/validation/dataframe.py +274 -0
  198. ml4t/diagnostic/validation/returns.py +280 -0
  199. ml4t/diagnostic/validation/timeseries.py +299 -0
  200. ml4t/diagnostic/visualization/AGENT.md +19 -0
  201. ml4t/diagnostic/visualization/__init__.py +223 -0
  202. ml4t/diagnostic/visualization/backtest/__init__.py +98 -0
  203. ml4t/diagnostic/visualization/backtest/cost_attribution.py +762 -0
  204. ml4t/diagnostic/visualization/backtest/executive_summary.py +895 -0
  205. ml4t/diagnostic/visualization/backtest/interactive_controls.py +673 -0
  206. ml4t/diagnostic/visualization/backtest/statistical_validity.py +874 -0
  207. ml4t/diagnostic/visualization/backtest/tearsheet.py +565 -0
  208. ml4t/diagnostic/visualization/backtest/template_system.py +373 -0
  209. ml4t/diagnostic/visualization/backtest/trade_plots.py +1172 -0
  210. ml4t/diagnostic/visualization/barrier_plots.py +782 -0
  211. ml4t/diagnostic/visualization/core.py +1060 -0
  212. ml4t/diagnostic/visualization/dashboards/__init__.py +36 -0
  213. ml4t/diagnostic/visualization/dashboards/base.py +582 -0
  214. ml4t/diagnostic/visualization/dashboards/importance.py +801 -0
  215. ml4t/diagnostic/visualization/dashboards/interaction.py +263 -0
  216. ml4t/diagnostic/visualization/dashboards.py +43 -0
  217. ml4t/diagnostic/visualization/data_extraction/__init__.py +48 -0
  218. ml4t/diagnostic/visualization/data_extraction/importance.py +649 -0
  219. ml4t/diagnostic/visualization/data_extraction/interaction.py +504 -0
  220. ml4t/diagnostic/visualization/data_extraction/types.py +113 -0
  221. ml4t/diagnostic/visualization/data_extraction/validation.py +66 -0
  222. ml4t/diagnostic/visualization/feature_plots.py +888 -0
  223. ml4t/diagnostic/visualization/interaction_plots.py +618 -0
  224. ml4t/diagnostic/visualization/portfolio/__init__.py +41 -0
  225. ml4t/diagnostic/visualization/portfolio/dashboard.py +514 -0
  226. ml4t/diagnostic/visualization/portfolio/drawdown_plots.py +341 -0
  227. ml4t/diagnostic/visualization/portfolio/returns_plots.py +487 -0
  228. ml4t/diagnostic/visualization/portfolio/risk_plots.py +301 -0
  229. ml4t/diagnostic/visualization/report_generation.py +1343 -0
  230. ml4t/diagnostic/visualization/signal/__init__.py +103 -0
  231. ml4t/diagnostic/visualization/signal/dashboard.py +911 -0
  232. ml4t/diagnostic/visualization/signal/event_plots.py +514 -0
  233. ml4t/diagnostic/visualization/signal/ic_plots.py +635 -0
  234. ml4t/diagnostic/visualization/signal/multi_signal_dashboard.py +974 -0
  235. ml4t/diagnostic/visualization/signal/multi_signal_plots.py +603 -0
  236. ml4t/diagnostic/visualization/signal/quantile_plots.py +625 -0
  237. ml4t/diagnostic/visualization/signal/turnover_plots.py +400 -0
  238. ml4t/diagnostic/visualization/trade_shap/__init__.py +90 -0
  239. ml4t_diagnostic-0.1.0a1.dist-info/METADATA +1044 -0
  240. ml4t_diagnostic-0.1.0a1.dist-info/RECORD +242 -0
  241. ml4t_diagnostic-0.1.0a1.dist-info/WHEEL +4 -0
  242. ml4t_diagnostic-0.1.0a1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,373 @@
1
+ """Template system for backtest tearsheets.
2
+
3
+ Provides persona-based templates that customize the tearsheet content
4
+ for different user types:
5
+ - quant_trader: Trade-level analysis, MFE/MAE, exit optimization
6
+ - hedge_fund: Risk-adjusted returns, cost attribution, drawdowns
7
+ - risk_manager: Statistical validity, DSR, confidence intervals
8
+ - full: Everything included
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass, field
14
+ from typing import TYPE_CHECKING, Literal
15
+
16
+ if TYPE_CHECKING:
17
+ pass
18
+
19
+
20
+ @dataclass
21
+ class TearsheetSection:
22
+ """Definition of a tearsheet section."""
23
+
24
+ name: str
25
+ title: str
26
+ enabled: bool = True
27
+ priority: int = 0 # Lower = higher priority (shown first)
28
+ description: str = ""
29
+
30
+
31
+ @dataclass
32
+ class TearsheetTemplate:
33
+ """Template configuration for a tearsheet."""
34
+
35
+ name: str
36
+ description: str
37
+ sections: list[TearsheetSection] = field(default_factory=list)
38
+
39
+ @classmethod
40
+ def quant_trader(cls) -> TearsheetTemplate:
41
+ """Template focused on trade-level analysis for quantitative traders.
42
+
43
+ Emphasizes:
44
+ - Trade execution efficiency (MFE/MAE)
45
+ - Exit reason analysis
46
+ - Trade-by-trade waterfall
47
+ - Duration and timing analysis
48
+ """
49
+ return cls(
50
+ name="quant_trader",
51
+ description="Trade-level deep dive for strategy optimization",
52
+ sections=[
53
+ TearsheetSection("executive_summary", "Executive Summary", priority=0),
54
+ TearsheetSection("key_insights", "Key Insights", priority=1),
55
+ TearsheetSection("mfe_mae", "Exit Efficiency (MFE/MAE)", priority=2),
56
+ TearsheetSection("exit_reasons", "Exit Reason Breakdown", priority=3),
57
+ TearsheetSection("trade_waterfall", "Trade-by-Trade PnL", priority=4),
58
+ TearsheetSection("duration", "Trade Duration Analysis", priority=5),
59
+ TearsheetSection("consecutive", "Win/Loss Streaks", priority=6),
60
+ TearsheetSection("size_return", "Position Size Analysis", priority=7),
61
+ TearsheetSection("shap_errors", "SHAP Error Patterns", priority=8, enabled=False),
62
+ # Disabled by default
63
+ TearsheetSection("equity_curve", "Equity Curve", priority=10, enabled=False),
64
+ TearsheetSection("drawdowns", "Drawdowns", priority=11, enabled=False),
65
+ TearsheetSection("dsr", "Statistical Validity", priority=12, enabled=False),
66
+ ],
67
+ )
68
+
69
+ @classmethod
70
+ def hedge_fund(cls) -> TearsheetTemplate:
71
+ """Template focused on risk-adjusted returns for hedge fund managers.
72
+
73
+ Emphasizes:
74
+ - Portfolio performance metrics
75
+ - Drawdown analysis
76
+ - Cost attribution
77
+ - Risk metrics
78
+ """
79
+ return cls(
80
+ name="hedge_fund",
81
+ description="Risk-adjusted performance for portfolio managers",
82
+ sections=[
83
+ TearsheetSection("executive_summary", "Executive Summary", priority=0),
84
+ TearsheetSection("key_insights", "Key Insights", priority=1),
85
+ TearsheetSection("equity_curve", "Equity Curve", priority=2),
86
+ TearsheetSection("drawdowns", "Drawdown Analysis", priority=3),
87
+ TearsheetSection("cost_waterfall", "Cost Attribution", priority=4),
88
+ TearsheetSection("cost_sensitivity", "Cost Sensitivity", priority=5),
89
+ TearsheetSection("rolling_metrics", "Rolling Performance", priority=6),
90
+ TearsheetSection("monthly_returns", "Monthly Returns Heatmap", priority=7),
91
+ TearsheetSection("annual_returns", "Annual Returns", priority=8),
92
+ # Disabled by default
93
+ TearsheetSection("mfe_mae", "Exit Efficiency", priority=10, enabled=False),
94
+ TearsheetSection("trade_waterfall", "Trade Details", priority=11, enabled=False),
95
+ TearsheetSection("dsr", "Statistical Tests", priority=12, enabled=False),
96
+ ],
97
+ )
98
+
99
+ @classmethod
100
+ def risk_manager(cls) -> TearsheetTemplate:
101
+ """Template focused on statistical validity for risk managers.
102
+
103
+ Emphasizes:
104
+ - Deflated Sharpe Ratio
105
+ - Confidence intervals
106
+ - Minimum track record length
107
+ - Tail risk metrics
108
+ """
109
+ return cls(
110
+ name="risk_manager",
111
+ description="Statistical rigor for risk oversight",
112
+ sections=[
113
+ TearsheetSection("executive_summary", "Executive Summary", priority=0),
114
+ TearsheetSection(
115
+ "statistical_summary", "Statistical Validity Overview", priority=1
116
+ ),
117
+ TearsheetSection("dsr_gauge", "Deflated Sharpe Ratio", priority=2),
118
+ TearsheetSection("confidence_intervals", "Metric Confidence Intervals", priority=3),
119
+ TearsheetSection("min_trl", "Minimum Track Record", priority=4),
120
+ TearsheetSection(
121
+ "ras_analysis", "RAS Overfitting Check", priority=5, enabled=False
122
+ ),
123
+ TearsheetSection("drawdowns", "Drawdown Analysis", priority=6),
124
+ TearsheetSection("tail_risk", "Tail Risk (VaR/CVaR)", priority=7),
125
+ TearsheetSection("distribution", "Returns Distribution", priority=8),
126
+ # Disabled by default
127
+ TearsheetSection("mfe_mae", "Exit Efficiency", priority=10, enabled=False),
128
+ TearsheetSection("cost_waterfall", "Cost Attribution", priority=11, enabled=False),
129
+ ],
130
+ )
131
+
132
+ @classmethod
133
+ def full(cls) -> TearsheetTemplate:
134
+ """Complete template with all available sections."""
135
+ return cls(
136
+ name="full",
137
+ description="Comprehensive analysis with all available visualizations",
138
+ sections=[
139
+ # Executive
140
+ TearsheetSection("executive_summary", "Executive Summary", priority=0),
141
+ TearsheetSection("key_insights", "Key Insights", priority=1),
142
+ # Performance
143
+ TearsheetSection("equity_curve", "Equity Curve", priority=10),
144
+ TearsheetSection("drawdowns", "Drawdown Analysis", priority=11),
145
+ TearsheetSection("monthly_returns", "Monthly Returns", priority=12),
146
+ TearsheetSection("annual_returns", "Annual Returns", priority=13),
147
+ TearsheetSection("rolling_metrics", "Rolling Performance", priority=14),
148
+ # Trade Analysis
149
+ TearsheetSection("mfe_mae", "Exit Efficiency (MFE/MAE)", priority=20),
150
+ TearsheetSection("exit_reasons", "Exit Reason Breakdown", priority=21),
151
+ TearsheetSection("trade_waterfall", "Trade-by-Trade PnL", priority=22),
152
+ TearsheetSection("duration", "Trade Duration Analysis", priority=23),
153
+ TearsheetSection("consecutive", "Win/Loss Streaks", priority=24),
154
+ TearsheetSection("size_return", "Position Size Analysis", priority=25),
155
+ # Cost Attribution
156
+ TearsheetSection("cost_waterfall", "Cost Attribution", priority=30),
157
+ TearsheetSection("cost_sensitivity", "Cost Sensitivity", priority=31),
158
+ TearsheetSection("cost_by_asset", "Costs by Asset", priority=32),
159
+ # Statistical Validity
160
+ TearsheetSection("statistical_summary", "Statistical Validity", priority=40),
161
+ TearsheetSection("dsr_gauge", "Deflated Sharpe Ratio", priority=41),
162
+ TearsheetSection("confidence_intervals", "Confidence Intervals", priority=42),
163
+ TearsheetSection("min_trl", "Minimum Track Record", priority=43),
164
+ TearsheetSection("ras_analysis", "RAS Analysis", priority=44, enabled=False),
165
+ # Distribution & Risk
166
+ TearsheetSection("distribution", "Returns Distribution", priority=50),
167
+ TearsheetSection("tail_risk", "Tail Risk", priority=51),
168
+ # SHAP (optional, requires model)
169
+ TearsheetSection("shap_errors", "SHAP Error Patterns", priority=60, enabled=False),
170
+ ],
171
+ )
172
+
173
+ def get_enabled_sections(self) -> list[TearsheetSection]:
174
+ """Return only enabled sections, sorted by priority."""
175
+ return sorted(
176
+ [s for s in self.sections if s.enabled],
177
+ key=lambda s: s.priority,
178
+ )
179
+
180
+ def enable_section(self, name: str) -> None:
181
+ """Enable a section by name."""
182
+ for section in self.sections:
183
+ if section.name == name:
184
+ section.enabled = True
185
+ return
186
+ raise ValueError(f"Section '{name}' not found in template")
187
+
188
+ def disable_section(self, name: str) -> None:
189
+ """Disable a section by name."""
190
+ for section in self.sections:
191
+ if section.name == name:
192
+ section.enabled = False
193
+ return
194
+ raise ValueError(f"Section '{name}' not found in template")
195
+
196
+
197
+ def get_template(
198
+ name: Literal["quant_trader", "hedge_fund", "risk_manager", "full"] = "full",
199
+ ) -> TearsheetTemplate:
200
+ """Get a tearsheet template by name.
201
+
202
+ Parameters
203
+ ----------
204
+ name : {"quant_trader", "hedge_fund", "risk_manager", "full"}
205
+ Template name
206
+
207
+ Returns
208
+ -------
209
+ TearsheetTemplate
210
+ The requested template
211
+
212
+ Examples
213
+ --------
214
+ >>> template = get_template("quant_trader")
215
+ >>> for section in template.get_enabled_sections():
216
+ ... print(section.title)
217
+ """
218
+ templates = {
219
+ "quant_trader": TearsheetTemplate.quant_trader,
220
+ "hedge_fund": TearsheetTemplate.hedge_fund,
221
+ "risk_manager": TearsheetTemplate.risk_manager,
222
+ "full": TearsheetTemplate.full,
223
+ }
224
+
225
+ if name not in templates:
226
+ raise ValueError(f"Unknown template: {name}. Available: {list(templates.keys())}")
227
+
228
+ return templates[name]()
229
+
230
+
231
+ # CSS styles for HTML tearsheet
232
+ TEARSHEET_CSS = """
233
+ <style>
234
+ :root {
235
+ --primary-color: #636EFA;
236
+ --success-color: #00CC96;
237
+ --warning-color: #FECB52;
238
+ --danger-color: #EF553B;
239
+ --text-color: #2E2E2E;
240
+ --bg-color: #FFFFFF;
241
+ --card-bg: #F8F9FA;
242
+ --border-color: #DEE2E6;
243
+ }
244
+
245
+ [data-theme="dark"] {
246
+ --primary-color: #636EFA;
247
+ --success-color: #00CC96;
248
+ --warning-color: #FECB52;
249
+ --danger-color: #EF553B;
250
+ --text-color: #E0E0E0;
251
+ --bg-color: #1E1E1E;
252
+ --card-bg: #2D2D2D;
253
+ --border-color: #404040;
254
+ }
255
+
256
+ body {
257
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
258
+ color: var(--text-color);
259
+ background-color: var(--bg-color);
260
+ margin: 0;
261
+ padding: 20px;
262
+ line-height: 1.6;
263
+ }
264
+
265
+ .tearsheet-container {
266
+ max-width: 1400px;
267
+ margin: 0 auto;
268
+ }
269
+
270
+ .tearsheet-header {
271
+ text-align: center;
272
+ margin-bottom: 30px;
273
+ padding-bottom: 20px;
274
+ border-bottom: 2px solid var(--border-color);
275
+ }
276
+
277
+ .tearsheet-header h1 {
278
+ margin: 0 0 10px 0;
279
+ font-size: 2em;
280
+ }
281
+
282
+ .tearsheet-header .subtitle {
283
+ color: #666;
284
+ font-size: 1.1em;
285
+ }
286
+
287
+ .section {
288
+ margin-bottom: 40px;
289
+ }
290
+
291
+ .section-title {
292
+ font-size: 1.4em;
293
+ font-weight: 600;
294
+ margin-bottom: 20px;
295
+ padding-bottom: 10px;
296
+ border-bottom: 1px solid var(--border-color);
297
+ }
298
+
299
+ .chart-container {
300
+ background: var(--card-bg);
301
+ border-radius: 8px;
302
+ padding: 15px;
303
+ margin-bottom: 20px;
304
+ border: 1px solid var(--border-color);
305
+ }
306
+
307
+ .row {
308
+ display: flex;
309
+ flex-wrap: wrap;
310
+ margin: -10px;
311
+ }
312
+
313
+ .col-6 {
314
+ flex: 0 0 50%;
315
+ padding: 10px;
316
+ box-sizing: border-box;
317
+ }
318
+
319
+ .col-12 {
320
+ flex: 0 0 100%;
321
+ padding: 10px;
322
+ box-sizing: border-box;
323
+ }
324
+
325
+ @media (max-width: 900px) {
326
+ .col-6 {
327
+ flex: 0 0 100%;
328
+ }
329
+ }
330
+
331
+ .footer {
332
+ text-align: center;
333
+ margin-top: 40px;
334
+ padding-top: 20px;
335
+ border-top: 1px solid var(--border-color);
336
+ color: #666;
337
+ font-size: 0.9em;
338
+ }
339
+
340
+ .timestamp {
341
+ font-size: 0.85em;
342
+ color: #888;
343
+ }
344
+ </style>
345
+ """
346
+
347
+ HTML_TEMPLATE = """
348
+ <!DOCTYPE html>
349
+ <html lang="en" data-theme="{theme}">
350
+ <head>
351
+ <meta charset="UTF-8">
352
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
353
+ <title>{title}</title>
354
+ {css}
355
+ <script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
356
+ </head>
357
+ <body>
358
+ <div class="tearsheet-container">
359
+ <header class="tearsheet-header">
360
+ <h1>{title}</h1>
361
+ <p class="subtitle">{subtitle}</p>
362
+ <p class="timestamp">Generated: {timestamp}</p>
363
+ </header>
364
+
365
+ {sections_html}
366
+
367
+ <footer class="footer">
368
+ <p>Generated by ml4t-diagnostic | State-of-the-art backtest analysis</p>
369
+ </footer>
370
+ </div>
371
+ </body>
372
+ </html>
373
+ """