Coverage for src / monte_neo / cli / menu / results.py: 0%
130 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-28 16:27 +0200
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-28 16:27 +0200
1"""Results viewing and display."""
3from __future__ import annotations
5import json
6import time
7from typing import TYPE_CHECKING
9import questionary
10from rich.console import Console
11from rich.panel import Panel
12from rich.table import Table
14from monte_neo.cli.styles import CUSTOM_STYLE
16if TYPE_CHECKING:
17 from monte_neo.cli.menu.main import InteractiveMenu
19console = Console()
22def view_results_workflow(menu: InteractiveMenu) -> None:
23 """View saved results."""
24 results_dir = menu.config.data_dir / "results"
25 if not results_dir.exists():
26 console.print("[yellow]⚠ No results directory found.[/]\n")
27 return
29 files = list(results_dir.glob("*.json"))
30 if not files:
31 console.print("[yellow]⚠ No saved results found.[/]\n")
32 return
34 choices = [f.stem for f in files] + ["🔙 Back"]
35 selected = questionary.select("Select result to view:", choices=choices, style=CUSTOM_STYLE).ask()
37 if not selected or selected == "🔙 Back":
38 return
40 _display_result_file(results_dir / f"{selected}.json")
43def _display_result_file(file_path):
44 try:
45 with open(file_path) as f:
46 data = json.load(f)
48 console.print(f"\n[bold cyan]📄 Results for {file_path.stem}[/]")
50 if "metrics" in data:
51 table = Table(title="Metrics")
52 table.add_column("Metric", style="cyan")
53 table.add_column("Value", style="green")
54 for k, v in data["metrics"].items():
55 val = f"{v:.4f}" if isinstance(v, float) else str(v)
56 table.add_row(k, val)
57 console.print(table)
59 if "mc_details" in data and data["mc_details"].get("step_results"):
60 steps_table = Table(title="Monte Carlo Sequential Details")
61 steps_table.add_column("Method", style="cyan")
62 steps_table.add_column("Status", style="bold")
63 steps_table.add_column("Pass Rate", style="green")
64 steps_table.add_column("Advice", style="yellow")
66 for step in data["mc_details"]["step_results"]:
67 status = "[green]PASS[/]" if step["passed"] else "[red]FAIL[/]"
68 steps_table.add_row(
69 step["method"],
70 status,
71 f"{step['rate']:.1%}",
72 step["advice"]
73 )
74 console.print(steps_table)
76 if "config" in data:
77 config = data['config']
78 content = config.get("source_code", "\n".join([f"{k}: {v}" for k, v in config.items()]))
79 console.print(Panel(content, title="Configuration", border_style="blue"))
81 except Exception as e:
82 console.print(f"[red]Error loading result: {e}[/]")
85def _format_time(seconds: float) -> str:
86 """Format seconds into M:SS or S.SSSs."""
87 if seconds < 0.001:
88 return f"{seconds*1000:.3f}ms"
89 if seconds < 1.0:
90 return f"{seconds:.4f}s"
91 if seconds < 60:
92 return f"{seconds:.2f}s"
93 minutes = int(seconds // 60)
94 remaining_seconds = seconds % 60
95 return f"{minutes}m {remaining_seconds:.1f}s"
98def show_generation_result(menu: InteractiveMenu, result) -> None:
99 """Display generation results and optionally save/plot."""
100 console.print()
102 # Success depends on mc_pass_rate >= mc_pass_threshold
103 threshold = getattr(menu, "_mc_pass_threshold", 0.80)
105 if result.success:
106 console.print(f"[bold green]✓ Indicator generated successfully! (MC Pass Rate {result.mc_pass_rate:.1%} >= {threshold:.0%})[/]\n")
107 elif result.indicator:
108 console.print(f"[bold yellow]⚠ Best indicator found but did not meet production criteria ({result.mc_pass_rate:.1%} < {threshold:.0%})[/]")
109 console.print(f"[dim]Requirement: Monte Carlo Pass Rate must be > {threshold:.0%} to be considered stable.[/]\n")
110 else:
111 console.print(f"[bold red]❌ No suitable indicator found matching criteria (MC Rate > {threshold:.0%})[/]\n")
113 if result.success:
114 _print_trust_certificate(result)
116 table = Table(title="Generation Results")
117 table.add_column("Metric", style="cyan")
118 table.add_column("Value", style="green")
119 table.add_row("Total Time", _format_time(result.elapsed_time))
120 table.add_row("Iterations", f"{result.iterations_tried:,}")
121 table.add_row("MC Pass Rate", f"{result.mc_pass_rate:.1%}")
123 # Add Hardware Timing Stats if available
124 if hasattr(result, "mc_details") and "timing_stats" in result.mc_details:
125 stats = result.mc_details["timing_stats"]
126 if "kernel_execution" in stats:
127 table.add_row("GPU Kernel", _format_time(stats['kernel_execution']))
128 if "data_prep" in stats:
129 table.add_row("GPU Data Prep", _format_time(stats['data_prep']))
130 if "result_formatting" in stats:
131 table.add_row("GPU Post-Process", _format_time(stats['result_formatting']))
132 if "total" in stats:
133 table.add_row("GPU Total", _format_time(stats['total']))
135 console.print(table)
137 if hasattr(result, "mc_details") and result.mc_details.get("step_results"):
138 steps_table = Table(title="Monte Carlo Sequential Details")
139 steps_table.add_column("Method", style="cyan")
140 steps_table.add_column("Status", style="bold")
141 steps_table.add_column("Pass Rate", style="green")
142 steps_table.add_column("Advice", style="yellow")
144 for step in result.mc_details["step_results"]:
145 status = "[green]PASS[/]" if step["passed"] else "[red]FAIL[/]"
146 steps_table.add_row(
147 step["method"],
148 status,
149 f"{step['rate']:.1%}",
150 step["advice"]
151 )
152 console.print(steps_table)
154 if result.indicator:
155 # Get formula using the new method
156 formula = result.indicator.get_formula()
158 # Color based on success
159 border_color = "green" if result.success else "yellow"
160 header_text = "Best Indicator Found" if result.success else "Best Indicator Found (Below Criteria)"
162 console.print(Panel(
163 f"[bold cyan]Indicator:[/] {result.indicator.name}\n"
164 f"[bold cyan]Formula:[/] {formula}\n"
165 f"[bold cyan]Parameters:[/] {result.parameters}",
166 title=header_text,
167 border_style=border_color
168 ))
169 _save_result(menu, result)
170 if questionary.confirm("Show chart?", style=CUSTOM_STYLE).ask():
171 _plot_result(menu, result)
172 else:
173 console.print("\n[red]❌ No indicator was found during the search.[/]")
176def _save_result(menu: InteractiveMenu, result) -> None:
177 results_dir = menu.config.data_dir / "results"
178 results_dir.mkdir(parents=True, exist_ok=True)
180 timestamp = int(time.time())
181 name = result.indicator.name if result.indicator else "unknown"
182 file_path = results_dir / f"result_{timestamp}_{name}.json"
184 data = {
185 "timestamp": timestamp,
186 "type": name,
187 "metrics": result.final_metrics,
188 "config": result.parameters,
189 "mc_pass_rate": result.mc_pass_rate,
190 "mc_details": getattr(result, "mc_details", {}),
191 }
193 with open(file_path, "w") as f:
194 json.dump(data, f, indent=4)
195 console.print(f"[dim]Result saved to: results/{file_path.name}[/]")
198def _plot_result(menu: InteractiveMenu, result) -> None:
199 from monte_neo.visualization.charts import ChartGenerator
200 if hasattr(menu, "_last_data") and menu._last_data is not None:
201 # Use generate_signals_fast for better performance if available
202 if hasattr(result.indicator, "generate_signals_fast"):
203 signals = result.indicator.generate_signals_fast(menu._last_data)
204 else:
205 signals = result.indicator.generate_signals(menu._last_data)
207 chart_gen = ChartGenerator()
208 chart_gen.plot_with_signals(menu._last_data, signals, title=f"Best: {result.indicator.name}")
209 else:
210 console.print("[yellow]⚠ No data available to plot chart. Please run generation first.[/]")
213def _print_trust_certificate(result):
214 """Print a robustness certificate."""
215 console.print()
217 # Check if we have detailed steps
218 details = ""
219 if hasattr(result, "mc_details") and result.mc_details.get("step_results"):
220 for step in result.mc_details["step_results"]:
221 if step["passed"]:
222 details += f"[green]✔ {step['method']}[/]\n"
224 if not details:
225 details = "[green]✔ Monte Carlo Simulation (Aggregated)[/]"
227 certificate = f"""
228 [bold green]🌟 CERTIFICATE OF ROBUSTNESS 🌟[/]
230 This certifies that the indicator:
231 [bold white]{result.indicator.name}[/]
233 Has successfully passed rigorous Monte Carlo Stress Tests:
234{details}
235 [bold]Pass Rate: {result.mc_pass_rate:.1%}[/]
237 Status: [bold green]PRODUCTION READY[/]
238 """
240 console.print(Panel(
241 certificate,
242 border_style="green",
243 expand=False
244 ))