Coverage for src / monte_neo / visualization / metrics.py: 46%

56 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-28 16:27 +0200

1"""Metrics display module.""" 

2 

3from __future__ import annotations 

4 

5from rich.console import Console 

6from rich.panel import Panel 

7from rich.table import Table 

8 

9console = Console() 

10 

11 

12class MetricsDisplay: 

13 """Display trading metrics.""" 

14 

15 def show_metrics_table(self, metrics: dict) -> None: 

16 """Display metrics in a formatted table. 

17 

18 Args: 

19 metrics: Dictionary of metric names to values. 

20 """ 

21 table = Table(title="Trading Metrics") 

22 table.add_column("Metric", style="cyan") 

23 table.add_column("Value", style="green") 

24 table.add_column("Status", style="bold") 

25 

26 targets = { 

27 "profit_factor": (2.0, ">="), 

28 "sharpe_ratio": (1.0, ">="), 

29 "sortino_ratio": (1.5, ">="), 

30 "max_drawdown": (0.20, "<="), 

31 "winrate": (0.45, ">="), 

32 "recovery_factor": (2.0, ">="), 

33 "calmar_ratio": (0.5, ">="), 

34 } 

35 

36 for name, value in metrics.items(): 

37 if isinstance(value, float): 

38 formatted = f"{value:.4f}" 

39 else: 

40 formatted = str(value) 

41 

42 # Check against target 

43 status = "" 

44 if name in targets: 

45 target, op = targets[name] 

46 if op == ">=" and value >= target: 

47 status = "[green]✓[/]" 

48 elif op == "<=" and value <= target: 

49 status = "[green]✓[/]" 

50 else: 

51 status = "[red]✗[/]" 

52 

53 table.add_row(name, formatted, status) 

54 

55 console.print(table) 

56 

57 def show_metrics_panel(self, metrics: dict, title: str = "Metrics") -> None: 

58 """Display metrics in a panel. 

59 

60 Args: 

61 metrics: Dictionary of metrics. 

62 title: Panel title. 

63 """ 

64 lines = [] 

65 for name, value in metrics.items(): 

66 if isinstance(value, float): 

67 lines.append(f"[cyan]{name}:[/] {value:.4f}") 

68 else: 

69 lines.append(f"[cyan]{name}:[/] {value}") 

70 

71 panel = Panel( 

72 "\n".join(lines), 

73 title=f"[bold]{title}[/]", 

74 border_style="cyan", 

75 ) 

76 console.print(panel) 

77 

78 def compare_metrics( 

79 self, 

80 before: dict, 

81 after: dict, 

82 title: str = "Metrics Comparison", 

83 ) -> None: 

84 """Compare two sets of metrics. 

85 

86 Args: 

87 before: Before metrics. 

88 after: After metrics. 

89 title: Table title. 

90 """ 

91 table = Table(title=title) 

92 table.add_column("Metric", style="cyan") 

93 table.add_column("Before", style="yellow") 

94 table.add_column("After", style="green") 

95 table.add_column("Change", style="bold") 

96 

97 all_keys = set(before.keys()) | set(after.keys()) 

98 

99 for key in sorted(all_keys): 

100 before_val = before.get(key) 

101 after_val = after.get(key) 

102 

103 before_str = ( 

104 f"{before_val:.4f}" 

105 if isinstance(before_val, float) 

106 else str(before_val or "-") 

107 ) 

108 after_str = ( 

109 f"{after_val:.4f}" 

110 if isinstance(after_val, float) 

111 else str(after_val or "-") 

112 ) 

113 

114 # Calculate change 

115 change = "" 

116 if isinstance(before_val, (int, float)) and isinstance( 

117 after_val, (int, float) 

118 ): 

119 diff = after_val - before_val 

120 if diff > 0: 

121 change = f"[green]+{diff:.4f}[/]" 

122 elif diff < 0: 

123 change = f"[red]{diff:.4f}[/]" 

124 else: 

125 change = "=" 

126 

127 table.add_row(key, before_str, after_str, change) 

128 

129 console.print(table)