Coverage for src / monte_neo / cli / menu / settings.py: 0%

55 statements  

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

1"""Evolutionary settings workflow.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING 

6 

7import questionary 

8from rich.console import Console 

9 

10from monte_neo.cli.styles import CUSTOM_STYLE 

11 

12if TYPE_CHECKING: 

13 from monte_neo.cli.menu.main import InteractiveMenu 

14 

15console = Console() 

16 

17 

18def settings_workflow(menu: InteractiveMenu) -> None: 

19 """Settings menu for evolutionary parameters.""" 

20 console.print("\n[bold cyan]⚙️ Evolutionary Settings[/]\n") 

21 

22 choices = [ 

23 {"name": f"👥 Population Size ({menu._pop_size})", "value": "pop_size"}, 

24 {"name": f"🔄 Generations ({menu._generations})", "value": "generations"}, 

25 {"name": f"🧪 Mutation Rate ({menu._mutation_rate:.2f})", "value": "mutation"}, 

26 {"name": f"🧬 Crossover Rate ({menu._crossover_rate:.2f})", "value": "crossover"}, 

27 {"name": f"🛡️ Stop Loss ({menu._stop_loss_pct:.1f}%)", "value": "sl"}, 

28 {"name": f"🎯 Take Profit ({menu._take_profit_pct:.1f}%)", "value": "tp"}, 

29 {"name": f"⚖️ Use SL/TP ({'✅' if menu._use_sl_tp else '❌'})", "value": "use_sl_tp"}, 

30 {"name": f"🏁 MC Threshold ({menu._mc_pass_threshold:.0%})", "value": "mc_threshold"}, 

31 {"name": f"🚀 Use GPU ({'✅' if menu._use_gpu else '❌'})", "value": "use_gpu"}, 

32 {"name": f"💎 GPU Precision ({menu._gpu_precision})", "value": "gpu_precision"}, 

33 {"name": f"⚡ Metal Driver ({menu._metal_driver.upper()})", "value": "metal_driver"}, 

34 {"name": "🔙 Back", "value": "back"}, 

35 ] 

36 

37 choice = questionary.select("Select setting to modify:", choices=choices, style=CUSTOM_STYLE).ask() 

38 

39 if choice == "pop_size": 

40 val = questionary.text("Population Size:", default=str(menu._pop_size)).ask() 

41 if val: menu._pop_size = int(val) 

42 elif choice == "generations": 

43 val = questionary.text("Generations:", default=str(menu._generations)).ask() 

44 if val: menu._generations = int(val) 

45 elif choice == "mutation": 

46 val = questionary.text("Mutation Rate (0.0-1.0):", default=str(menu._mutation_rate)).ask() 

47 if val: menu._mutation_rate = float(val) 

48 elif choice == "crossover": 

49 val = questionary.text("Crossover Rate (0.0-1.0):", default=str(menu._crossover_rate)).ask() 

50 if val: menu._crossover_rate = float(val) 

51 elif choice == "sl": 

52 rr_choices = [ 

53 {"name": "Custom (%)", "value": "custom"}, 

54 {"name": "Conservative (0.5%)", "value": 0.5}, 

55 {"name": "Standard (1.0%)", "value": 1.0}, 

56 {"name": "Aggressive (2.0%)", "value": 2.0}, 

57 ] 

58 val = questionary.select("Select Stop Loss:", choices=rr_choices, style=CUSTOM_STYLE).ask() 

59 if val == "custom": 

60 val = questionary.text("Stop Loss Percentage:", default=str(menu._stop_loss_pct)).ask() 

61 if val: menu._stop_loss_pct = float(val) 

62 elif val is not None: 

63 menu._stop_loss_pct = val 

64 elif choice == "tp": 

65 rr_choices = [ 

66 {"name": "Custom (%)", "value": "custom"}, 

67 {"name": f"Risk Ratio 1:1 ({menu._stop_loss_pct * 1.0:.1f}%)", "value": menu._stop_loss_pct * 1.0}, 

68 {"name": f"Risk Ratio 1.5:1 ({menu._stop_loss_pct * 1.5:.1f}%)", "value": menu._stop_loss_pct * 1.5}, 

69 {"name": f"Risk Ratio 2:1 ({menu._stop_loss_pct * 2.0:.1f}%)", "value": menu._stop_loss_pct * 2.0}, 

70 {"name": f"Risk Ratio 3:1 ({menu._stop_loss_pct * 3.0:.1f}%)", "value": menu._stop_loss_pct * 3.0}, 

71 ] 

72 val = questionary.select("Select Take Profit (Risk Ratio):", choices=rr_choices, style=CUSTOM_STYLE).ask() 

73 if val == "custom": 

74 val = questionary.text("Take Profit Percentage:", default=str(menu._take_profit_pct)).ask() 

75 if val: menu._take_profit_pct = float(val) 

76 elif val is not None: 

77 menu._take_profit_pct = val 

78 elif choice == "use_sl_tp": 

79 menu._use_sl_tp = not menu._use_sl_tp 

80 elif choice == "mc_threshold": 

81 val = questionary.text("MC Pass Threshold (0.0-1.0):", default=str(menu._mc_pass_threshold)).ask() 

82 if val: menu._mc_pass_threshold = float(val) 

83 elif choice == "use_gpu": 

84 menu._use_gpu = not menu._use_gpu 

85 elif choice == "gpu_precision": 

86 prec_choices = [ 

87 {"name": "float32 (Standard)", "value": "float32"}, 

88 {"name": "float16 (Faster)", "value": "float16"}, 

89 {"name": "float8_e4m3 (Extreme - 4x memory)", "value": "float8_e4m3"}, 

90 {"name": "float8_e5m2 (Extreme - 4x memory)", "value": "float8_e5m2"}, 

91 ] 

92 val = questionary.select("Select GPU Precision:", choices=prec_choices, style=CUSTOM_STYLE).ask() 

93 if val: menu._gpu_precision = val 

94 elif choice == "metal_driver": 

95 driver_choices = [ 

96 {"name": "Auto-Select (Recommended, Micro-Benchmark)", "value": "auto"}, 

97 {"name": "Clang C++ (Optimized)", "value": "cpp"}, 

98 {"name": "Objective-C++ (Native)", "value": "objc"}, 

99 {"name": "Apple Swift (Modern)", "value": "swift"}, 

100 ] 

101 val = questionary.select("Select Metal Driver:", choices=driver_choices, style=CUSTOM_STYLE).ask() 

102 if val: 

103 menu._metal_driver = val 

104 menu.config.metal_driver = val 

105 from monte_neo.utils.config import save_config 

106 save_config(menu.config, "config.yaml") 

107 console.print(f"[green]Metal driver set to {val.upper()} and saved to config.yaml[/]")