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,32 @@
1
+ """Trade SHAP diagnostics dashboard package.
2
+
3
+ This package provides an interactive Streamlit dashboard for visualizing
4
+ Trade-SHAP analysis results, including statistical validation, worst trades,
5
+ SHAP explanations, and error patterns.
6
+
7
+ Usage:
8
+ >>> from ml4t.diagnostic.evaluation.trade_dashboard import run_diagnostics_dashboard
9
+ >>> run_diagnostics_dashboard(result)
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from ml4t.diagnostic.evaluation.trade_dashboard.app import run_dashboard
15
+ from ml4t.diagnostic.evaluation.trade_dashboard.normalize import normalize_result
16
+ from ml4t.diagnostic.evaluation.trade_dashboard.types import (
17
+ DashboardBundle,
18
+ DashboardConfig,
19
+ ReturnSummary,
20
+ )
21
+
22
+ # Backward compatibility alias
23
+ run_diagnostics_dashboard = run_dashboard
24
+
25
+ __all__ = [
26
+ "DashboardBundle",
27
+ "DashboardConfig",
28
+ "ReturnSummary",
29
+ "normalize_result",
30
+ "run_dashboard",
31
+ "run_diagnostics_dashboard", # Backward compat alias
32
+ ]
@@ -0,0 +1,315 @@
1
+ """Dashboard application orchestrator.
2
+
3
+ Main entry point for the Trade-SHAP diagnostics dashboard.
4
+ Handles page configuration, data loading, and tab routing.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import time
10
+ import traceback
11
+ from datetime import datetime
12
+ from typing import TYPE_CHECKING, Any
13
+
14
+ if TYPE_CHECKING:
15
+ from ml4t.diagnostic.evaluation.trade_shap.models import TradeShapResult
16
+
17
+ # Module-level load time tracking for styled mode
18
+ _LOAD_START_TIME: float | None = None
19
+
20
+
21
+ def _measure_load_time_start() -> None:
22
+ """Start measuring load time."""
23
+ global _LOAD_START_TIME
24
+ _LOAD_START_TIME = time.time()
25
+
26
+
27
+ def _measure_load_time_end() -> float:
28
+ """End load time measurement and return elapsed seconds."""
29
+ global _LOAD_START_TIME
30
+ if _LOAD_START_TIME is None:
31
+ return 0.0
32
+ elapsed = time.time() - _LOAD_START_TIME
33
+ _LOAD_START_TIME = None
34
+ return elapsed
35
+
36
+
37
+ def run_dashboard(
38
+ result: TradeShapResult | dict[str, Any] | None = None,
39
+ title: str = "Trade-SHAP Diagnostics Dashboard",
40
+ styled: bool = False,
41
+ allow_pickle_upload: bool = False,
42
+ ) -> None:
43
+ """Run the Streamlit diagnostics dashboard.
44
+
45
+ This is the main entry point for the dashboard. It can be called
46
+ programmatically with a result object, or run as a standalone app
47
+ that allows file uploads.
48
+
49
+ Parameters
50
+ ----------
51
+ result : TradeShapResult or dict, optional
52
+ Pre-loaded analysis result. If None, dashboard will show file upload.
53
+ title : str, default "Trade-SHAP Diagnostics Dashboard"
54
+ Dashboard title.
55
+ styled : bool, default False
56
+ Enable professional styling with custom CSS, load time tracking,
57
+ spinners, export buttons, and enhanced error handling.
58
+ allow_pickle_upload : bool, default False
59
+ Allow pickle file uploads. SECURITY WARNING: Pickle files can
60
+ execute arbitrary code. Only enable for trusted sources.
61
+
62
+ Examples
63
+ --------
64
+ Programmatic usage:
65
+ >>> from ml4t.diagnostic.evaluation import TradeShapAnalyzer
66
+ >>> from ml4t.diagnostic.evaluation.trade_dashboard import run_dashboard
67
+ >>>
68
+ >>> analyzer = TradeShapAnalyzer(model, features_df, shap_values)
69
+ >>> result = analyzer.explain_worst_trades(worst_trades)
70
+ >>> run_dashboard(result)
71
+
72
+ Styled mode with professional theme:
73
+ >>> run_dashboard(result, styled=True)
74
+
75
+ Standalone app:
76
+ $ streamlit run -m ml4t.diagnostic.evaluation.trade_dashboard.app
77
+ """
78
+ # Lazy import streamlit
79
+ try:
80
+ import streamlit as st
81
+ except ImportError:
82
+ raise ImportError(
83
+ "streamlit is required for dashboard functionality. Install with: pip install streamlit"
84
+ ) from None
85
+
86
+ from ml4t.diagnostic.evaluation.trade_dashboard.io import (
87
+ PickleDisabledError,
88
+ load_result_from_upload,
89
+ )
90
+ from ml4t.diagnostic.evaluation.trade_dashboard.normalize import normalize_result
91
+ from ml4t.diagnostic.evaluation.trade_dashboard.style import STYLED_CSS
92
+ from ml4t.diagnostic.evaluation.trade_dashboard.tabs import (
93
+ patterns,
94
+ shap_analysis,
95
+ stat_validation,
96
+ worst_trades,
97
+ )
98
+ from ml4t.diagnostic.evaluation.trade_dashboard.types import DashboardConfig
99
+
100
+ # Start load time measurement in styled mode
101
+ if styled:
102
+ _measure_load_time_start()
103
+
104
+ # Page config
105
+ page_config: dict[str, Any] = {
106
+ "page_title": title,
107
+ "page_icon": "📊",
108
+ "layout": "wide",
109
+ "initial_sidebar_state": "expanded",
110
+ }
111
+ if styled:
112
+ page_config["menu_items"] = {
113
+ "Get Help": "https://github.com/ml4t/ml4t-diagnostic",
114
+ "Report a bug": "https://github.com/ml4t/ml4t-diagnostic/issues",
115
+ "About": "# Trade-SHAP Diagnostics\nSystematic trade debugging for ML strategies",
116
+ }
117
+ st.set_page_config(**page_config)
118
+
119
+ # Apply professional CSS in styled mode
120
+ if styled:
121
+ st.markdown(STYLED_CSS, unsafe_allow_html=True)
122
+
123
+ # Title and description
124
+ st.title(title)
125
+ st.markdown(
126
+ """
127
+ **Systematic trade debugging and continuous improvement for ML trading strategies**
128
+
129
+ This dashboard visualizes Trade-SHAP analysis results to help you:
130
+ - Identify why specific trades failed
131
+ - Discover recurring error patterns
132
+ - Get actionable recommendations for improvement
133
+ """
134
+ )
135
+ st.divider()
136
+
137
+ # Sidebar for data loading
138
+ with st.sidebar:
139
+ st.header("Configuration")
140
+
141
+ st.subheader("Data Loading")
142
+
143
+ if result is None:
144
+ # File upload mode
145
+ file_types = ["json"]
146
+ if allow_pickle_upload:
147
+ file_types.extend(["pkl", "pickle"])
148
+
149
+ uploaded_file = st.file_uploader(
150
+ "Upload TradeShapResult",
151
+ type=file_types,
152
+ help="Upload a JSON file containing TradeShapResult"
153
+ + (" (or pickle if enabled)" if allow_pickle_upload else ""),
154
+ )
155
+
156
+ if uploaded_file is not None:
157
+ try:
158
+ with st.spinner("Loading data..."):
159
+ result = load_result_from_upload(
160
+ uploaded_file,
161
+ allow_pickle=allow_pickle_upload,
162
+ )
163
+ st.success("Data loaded successfully!")
164
+ except PickleDisabledError as e:
165
+ st.error(str(e))
166
+ return
167
+ except Exception as e:
168
+ st.error(f"Failed to load data: {e}")
169
+ if styled:
170
+ with st.expander("Error Details"):
171
+ st.code(traceback.format_exc())
172
+ return
173
+ else:
174
+ st.info("Upload a file to get started")
175
+ if not allow_pickle_upload:
176
+ st.caption(
177
+ "Pickle uploads disabled for security. Use JSON format for data transfer."
178
+ )
179
+ st.stop()
180
+ else:
181
+ st.success("Data loaded programmatically")
182
+
183
+ # Normalize result once for all tabs
184
+ if result is not None:
185
+ config = DashboardConfig(
186
+ allow_pickle_upload=allow_pickle_upload,
187
+ styled=styled,
188
+ title=title,
189
+ )
190
+ bundle = normalize_result(result, config)
191
+
192
+ # Display data summary in sidebar
193
+ _display_sidebar_summary(st, bundle, styled)
194
+
195
+ # Main content - tabs
196
+ tab1, tab2, tab3, tab4 = st.tabs(
197
+ [
198
+ "Statistical Validation",
199
+ "Worst Trades",
200
+ "SHAP Analysis",
201
+ "Patterns",
202
+ ]
203
+ )
204
+
205
+ if styled:
206
+ with tab1, st.spinner("Loading statistical validation..."):
207
+ stat_validation.render_tab(st, bundle)
208
+
209
+ with tab2, st.spinner("Loading worst trades..."):
210
+ worst_trades.render_tab(st, bundle)
211
+
212
+ with tab3, st.spinner("Loading SHAP analysis..."):
213
+ shap_analysis.render_tab(st, bundle)
214
+
215
+ with tab4, st.spinner("Loading error patterns..."):
216
+ patterns.render_tab(st, bundle)
217
+
218
+ # Show load time
219
+ load_time = _measure_load_time_end()
220
+ if load_time > 0:
221
+ if load_time < 5.0:
222
+ st.sidebar.success(f"Loaded in {load_time:.2f}s")
223
+ else:
224
+ st.sidebar.warning(f"Loaded in {load_time:.2f}s (>5s target)")
225
+ else:
226
+ with tab1:
227
+ stat_validation.render_tab(st, bundle)
228
+
229
+ with tab2:
230
+ worst_trades.render_tab(st, bundle)
231
+
232
+ with tab3:
233
+ shap_analysis.render_tab(st, bundle)
234
+
235
+ with tab4:
236
+ patterns.render_tab(st, bundle)
237
+ else:
238
+ st.info("Please load data from the sidebar to begin analysis.")
239
+
240
+
241
+ def _display_sidebar_summary(st: Any, bundle: Any, styled: bool) -> None:
242
+ """Display data summary in sidebar."""
243
+ with st.sidebar:
244
+ st.divider()
245
+ st.subheader("Data Summary")
246
+
247
+ col1, col2 = st.columns(2)
248
+ with col1:
249
+ st.metric("Trades Analyzed", bundle.n_trades_analyzed)
250
+ with col2:
251
+ st.metric("Trades Explained", bundle.n_trades_explained)
252
+
253
+ if bundle.n_trades_failed > 0:
254
+ st.warning(f"{bundle.n_trades_failed} trades failed explanation")
255
+
256
+ n_patterns = len(bundle.patterns_df) if not bundle.patterns_df.empty else 0
257
+ st.metric("Patterns Found", n_patterns)
258
+
259
+ # Export buttons (styled mode)
260
+ if styled:
261
+ st.divider()
262
+ st.subheader("Export")
263
+ _render_export_buttons(st, bundle)
264
+
265
+ # Display options
266
+ st.divider()
267
+ st.subheader("Display Options")
268
+ st.checkbox("Show timestamps", value=True, key="show_timestamps")
269
+ st.checkbox("Show confidence scores", value=True, key="show_confidence")
270
+
271
+ # Footer
272
+ st.divider()
273
+ st.caption(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
274
+ if styled:
275
+ st.caption("Dashboard v2.0 (Modular)")
276
+
277
+
278
+ def _render_export_buttons(st: Any, bundle: Any) -> None:
279
+ """Render export buttons in sidebar."""
280
+ try:
281
+ from ml4t.diagnostic.evaluation.trade_dashboard.export import (
282
+ export_html_report,
283
+ export_trades_csv,
284
+ )
285
+
286
+ # CSV export
287
+ csv_data = export_trades_csv(bundle)
288
+ if csv_data:
289
+ st.download_button(
290
+ label="Download Trades CSV",
291
+ data=csv_data,
292
+ file_name=f"trades_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
293
+ mime="text/csv",
294
+ use_container_width=True,
295
+ )
296
+
297
+ # HTML report export
298
+ html_data = export_html_report(bundle)
299
+ if html_data:
300
+ st.download_button(
301
+ label="Download HTML Report",
302
+ data=html_data,
303
+ file_name=f"report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html",
304
+ mime="text/html",
305
+ use_container_width=True,
306
+ )
307
+ except ImportError:
308
+ st.caption("Export modules not available")
309
+ except Exception as e:
310
+ st.error(f"Export error: {e}")
311
+
312
+
313
+ # Allow running as a standalone Streamlit app
314
+ if __name__ == "__main__":
315
+ run_dashboard()
@@ -0,0 +1,18 @@
1
+ """Dashboard export modules.
2
+
3
+ Provides CSV and HTML export functionality for dashboard data.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from ml4t.diagnostic.evaluation.trade_dashboard.export.csv import (
9
+ export_patterns_csv,
10
+ export_trades_csv,
11
+ )
12
+ from ml4t.diagnostic.evaluation.trade_dashboard.export.html import export_html_report
13
+
14
+ __all__ = [
15
+ "export_html_report",
16
+ "export_patterns_csv",
17
+ "export_trades_csv",
18
+ ]
@@ -0,0 +1,82 @@
1
+ """CSV export functions for dashboard data."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ from ml4t.diagnostic.evaluation.trade_dashboard.types import DashboardBundle
9
+
10
+
11
+ def export_trades_csv(bundle: DashboardBundle) -> str:
12
+ """Export trades with SHAP values to CSV format.
13
+
14
+ Parameters
15
+ ----------
16
+ bundle : DashboardBundle
17
+ Normalized dashboard data.
18
+
19
+ Returns
20
+ -------
21
+ str
22
+ CSV formatted string with trade data.
23
+ """
24
+ if bundle.trades_df.empty:
25
+ return ""
26
+
27
+ # Select columns for export
28
+ export_columns = [
29
+ "trade_id",
30
+ "symbol",
31
+ "entry_time",
32
+ "exit_time",
33
+ "pnl",
34
+ "return_pct",
35
+ "duration_days",
36
+ "entry_price",
37
+ "exit_price",
38
+ "top_feature",
39
+ "top_shap_value",
40
+ ]
41
+
42
+ # Only include columns that exist
43
+ available_columns = [c for c in export_columns if c in bundle.trades_df.columns]
44
+
45
+ df = bundle.trades_df[available_columns].copy()
46
+
47
+ return df.to_csv(index=False)
48
+
49
+
50
+ def export_patterns_csv(bundle: DashboardBundle) -> str:
51
+ """Export error patterns to CSV format.
52
+
53
+ Parameters
54
+ ----------
55
+ bundle : DashboardBundle
56
+ Normalized dashboard data.
57
+
58
+ Returns
59
+ -------
60
+ str
61
+ CSV formatted string with pattern data.
62
+ """
63
+ if bundle.patterns_df.empty:
64
+ return ""
65
+
66
+ # Select columns for export
67
+ export_columns = [
68
+ "cluster_id",
69
+ "n_trades",
70
+ "description",
71
+ "hypothesis",
72
+ "confidence",
73
+ "separation_score",
74
+ "distinctiveness",
75
+ ]
76
+
77
+ # Only include columns that exist
78
+ available_columns = [c for c in export_columns if c in bundle.patterns_df.columns]
79
+
80
+ df = bundle.patterns_df[available_columns].copy()
81
+
82
+ return df.to_csv(index=False)