-
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathrun.py
More file actions
207 lines (170 loc) · 7.82 KB
/
Copy pathrun.py
File metadata and controls
207 lines (170 loc) · 7.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python3
"""
Paperium Unified Runner
Provides an easy-to-use CLI to run all project workflows.
"""
import os
import sys
import subprocess
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Prompt, IntPrompt, Confirm
console = Console()
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')
def run_script(script_path, *args):
"""Helper to run scripts with uv."""
cmd = ["uv", "run", "python", script_path]
cmd.extend(args)
console.print(f"\n[yellow]Executing: {' '.join(cmd)}[/yellow]\n")
subprocess.run(cmd)
def main_menu():
clear_screen()
console.print(Panel.fit(
"[bold cyan]Paperium Trading System[/bold cyan]\n"
"[dim]LSTM + Triple Barrier Labeling Algorithm[/dim]",
border_style="cyan"
))
console.print("\n[bold]Main Menu:[/bold]")
console.print("0. Initial Setup & Data Prep (Mandatory)")
console.print("1. IDX Stock Prediction (Generate Signals)")
console.print("2. Model Training (LSTM)")
console.print("3. Evaluation (LSTM Backtest)")
console.print("4. Ensemble Backtest (LSTM + XGBoost)")
console.print("5. Hyperparameter Tuning (Optimize LSTM)")
console.print("X. Exit")
choice = Prompt.ask("\nSelect action", choices=["0", "1", "2", "3", "4", "5", "X", "x"], default="1")
if choice == "0":
setup_menu()
elif choice == "1":
fetch_latest = Confirm.ask("Fetch latest data from Yahoo Finance?", default=False)
custom_capital = IntPrompt.ask("Capital to allocate (IDR, 0=show all signals)", default=0)
num_stock = IntPrompt.ask("Number of stocks to trade (0=show all)", default=0)
cmd = ["scripts/signals.py"]
if fetch_latest:
cmd.append("--fetch-latest")
if custom_capital > 0:
cmd.extend(["--capital", str(custom_capital)])
if num_stock > 0:
cmd.extend(["--num-stock", str(num_stock)])
run_script(*cmd)
elif choice == "2":
train_menu()
elif choice == "3":
eval_menu()
elif choice == "4":
ensemble_eval_menu()
elif choice == "5":
tune_menu()
elif choice.upper() == "X":
console.print("[dim]Goodbye![/dim]")
sys.exit(0)
input("\nPress Enter to return to menu...")
main_menu()
def setup_menu():
clear_screen()
console.print(Panel.fit("[bold yellow]Initial Setup & Data Prep[/bold yellow]", border_style="yellow"))
console.print("\n[dim]Prepare your environment and sync market data[/dim]\n")
console.print("1. [bold cyan]Clean Universe[/bold cyan] (Filter illiquid/suspended stocks)")
console.print("2. [bold magenta]Sync Stock Data[/bold magenta] (Fetch historical data)")
console.print("3. [bold green]Download IHSG Index[/bold green] (For market context)")
console.print("4. [bold red]Clear Cache[/bold red] (Delete .cache folder)")
console.print("B. Back to Main Menu")
choice = Prompt.ask("\nSelect setup action", choices=["1", "2", "3", "4", "B", "b"], default="1")
if choice == "1":
console.print("\n[yellow]Running: uv run python scripts/clean_universe.py[/yellow]\n")
subprocess.run(["uv", "run", "python", "scripts/clean_universe.py"])
elif choice == "2":
console.print("\n[yellow]Running: uv run python scripts/sync_data.py[/yellow]\n")
subprocess.run(["uv", "run", "python", "scripts/sync_data.py"])
elif choice == "3":
days = IntPrompt.ask("Days of IHSG history to download", default=1825)
console.print(f"\n[yellow]Running: uv run python scripts/download_ihsg.py --days {days}[/yellow]\n")
subprocess.run(["uv", "run", "python", "scripts/download_ihsg.py", "--days", str(days)])
elif choice == "4":
import shutil
if os.path.exists(".cache"):
from rich.prompt import Confirm
confirm = Confirm.ask("\n[red]⚠ Delete .cache folder? This cannot be undone.[/red]")
if confirm:
shutil.rmtree(".cache")
console.print("[green]✓ Cache cleared[/green]")
else:
console.print("[dim]Cancelled[/dim]")
else:
console.print("[dim].cache folder does not exist[/dim]")
elif choice.upper() == "B":
return
def tune_menu():
clear_screen()
console.print(Panel.fit("[bold yellow]Hyperparameter Tuning[/bold yellow]", border_style="yellow"))
console.print("\n[dim]Optimize LSTM architecture (Hidden Size, Layers, Dropout)[/dim]\n")
cmd = ["uv", "run", "python", "scripts/tune_lstm.py"]
console.print(f"[yellow]Launching tuner...[/yellow]\n")
subprocess.run(cmd)
def train_menu():
clear_screen()
console.print(Panel.fit("[bold cyan]LSTM Model Training[/bold cyan]", border_style="cyan"))
# Customizable parameters
console.print("\n[dim]Configure training parameters:[/dim]\n")
# Check if existing model exists
model_exists = os.path.exists("models/best_lstm.pt")
if model_exists:
console.print("[yellow]⚠ Existing model detected:[/yellow] models/best_lstm.pt\n")
training_mode = Prompt.ask(
"Training mode",
choices=["fresh", "retrain"],
default="retrain"
)
console.print()
if training_mode == "fresh":
console.print("[bold yellow]Fresh Training:[/bold yellow] Starting new model from scratch")
else:
console.print("[bold cyan]Retrain Mode:[/bold cyan] Continuing from existing model")
else:
console.print("[dim]No existing model found - will start fresh training[/dim]\n")
training_mode = "fresh"
epochs = IntPrompt.ask("Training epochs", default=50)
cmd = ["uv", "run", "python", "scripts/train.py", "--epochs", str(epochs)]
if training_mode == "retrain":
cmd.append("--retrain")
console.print(f"\n[yellow]Executing: {' '.join(cmd)}[/yellow]\n")
subprocess.run(cmd)
def eval_menu():
clear_screen()
console.print(Panel.fit("[bold cyan]Evaluation Lab (LSTM)[/bold cyan]", border_style="cyan"))
console.print("\n[dim]Configure evaluation parameters:[/dim]\n")
start_date = Prompt.ask("Start date (YYYY-MM-DD)", default="2024-01-01")
end_date = Prompt.ask("End date (YYYY-MM-DD)", default="2025-09-30")
cmd = ["uv", "run", "python", "scripts/eval.py",
"--start", start_date,
"--end", end_date]
console.print(f"\n[yellow]Executing: {' '.join(cmd)}[/yellow]\n")
subprocess.run(cmd)
def ensemble_eval_menu():
clear_screen()
console.print(Panel.fit("[bold magenta]Ensemble Backtest (LSTM + XGBoost)[/bold magenta]", border_style="magenta"))
console.print("\n[dim]Test combined LSTM + XGBoost predictions with dynamic SL/TP[/dim]\n")
# Check if XGBoost model exists
if not os.path.exists("models/global_xgb_champion.pkl") and not os.path.exists("models/global_xgb_champion.json"):
console.print("[yellow]Warning: XGBoost model not found[/yellow]")
console.print("[dim]To train XGBoost model:[/dim]")
console.print(" 1. git checkout paperium-v1")
console.print(" 2. uv run python scripts/train.py --days max --train-window max")
console.print(" 3. git checkout main")
console.print("")
proceed = Confirm.ask("Continue anyway? (will fail)", default=False)
if not proceed:
return
start_date = Prompt.ask("Start date (YYYY-MM-DD)", default="2024-01-01")
end_date = Prompt.ask("End date (YYYY-MM-DD)", default="2025-09-30")
cmd = ["uv", "run", "python", "scripts/eval_ensemble.py",
"--start", start_date,
"--end", end_date]
console.print(f"\n[yellow]Executing: {' '.join(cmd)}[/yellow]\n")
subprocess.run(cmd)
if __name__ == "__main__":
try:
main_menu()
except KeyboardInterrupt:
console.print("\n[dim]Aborted by user.[/dim]")