-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscheduler.py
More file actions
executable file
·148 lines (114 loc) · 3.93 KB
/
scheduler.py
File metadata and controls
executable file
·148 lines (114 loc) · 3.93 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
#!/usr/bin/env python3
"""
Scheduler for Tech Losers Bot.
This script can be used to run the bot on a schedule without external tools like cron.
It runs the bot at a specified time each trading day (Tue-Sat).
Usage:
python scheduler.py [--time 17:00] [--timezone Asia/Singapore]
"""
import argparse
import subprocess
import sys
import time
from datetime import datetime, timedelta
from pathlib import Path
try:
from src.config import SGT
except ImportError:
import pytz
SGT = pytz.timezone('Asia/Singapore')
import pytz
HAS_PYTZ = True
def parse_args():
parser = argparse.ArgumentParser(description="Schedule Tech Losers Bot runs")
parser.add_argument(
'--time',
default='17:00',
help='Time to run (HH:MM format, default: 17:00)'
)
parser.add_argument(
'--timezone',
default='Asia/Singapore',
help='Timezone (default: Asia/Singapore)'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='Pass --dry-run to the bot'
)
parser.add_argument(
'--verify',
action='store_true',
help='Pass --verify to the bot'
)
return parser.parse_args()
def is_trading_day(dt):
"""Check if the given datetime is a US trading day (Tue-Sat)."""
# Simple check - doesn't account for holidays
return dt.weekday() in (1, 2, 3, 4, 5) # Tuesday=1, Saturday=5
def get_next_run_time(target_time_str, timezone_str):
"""Calculate the next run time."""
hour, minute = map(int, target_time_str.split(':'))
if HAS_PYTZ:
now = datetime.now(SGT)
else:
now = datetime.now()
# Start with today at target time
next_run = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
# If we've passed today's target time, start from tomorrow
if next_run <= now:
next_run += timedelta(days=1)
# Skip to next trading day if needed
while not is_trading_day(next_run):
next_run += timedelta(days=1)
return next_run
def run_bot(dry_run=False, verify=False):
"""Execute the main bot script."""
script_dir = Path(__file__).parent
cmd = [sys.executable, str(script_dir / 'main.py')]
if dry_run:
cmd.append('--dry-run')
if verify:
cmd.append('--verify')
print(f"\n{'='*60}")
print(f"Starting bot at {datetime.now(SGT).strftime('%Y-%m-%d %H:%M:%S')}")
print(f"{'='*60}\n")
result = subprocess.run(cmd, cwd=script_dir)
return result.returncode
def main():
args = parse_args()
print(f"Tech Losers Bot Scheduler")
print(f"{'='*40}")
print(f"Target time: {args.time} {args.timezone}")
print(f"Dry run: {args.dry_run}")
print(f"Verify: {args.verify}")
print(f"{'='*40}")
while True:
next_run = get_next_run_time(args.time, args.timezone)
if HAS_PYTZ:
now = datetime.now(SGT)
else:
now = datetime.now()
wait_seconds = (next_run - now).total_seconds()
print(f"\nNext run: {next_run.strftime('%Y-%m-%d %H:%M:%S %Z')}")
print(f"Waiting {wait_seconds/3600:.1f} hours...")
# Sleep until next run (check every minute to handle clock adjustments)
while wait_seconds > 0:
sleep_time = min(60, wait_seconds)
time.sleep(sleep_time)
if HAS_PYTZ:
now = datetime.now(SGT)
else:
now = datetime.now()
wait_seconds = (next_run - now).total_seconds()
# Run the bot
exit_code = run_bot(dry_run=args.dry_run, verify=args.verify)
print(f"\nBot finished with exit code: {exit_code}")
# Wait a minute before calculating next run to avoid duplicate runs
time.sleep(60)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\nScheduler stopped.")
sys.exit(0)