Week 10 · Build Your Own Automated Options Trading System
From script
to system.
A script runs when you babysit it. A system runs while you sleep. This week we wire the cron, refresh the token, audit before market open, and keep the diary — so the bot is still there on Monday.
This week, in one glance
Same five beats. New topic.
1
Idea
The difference between "it worked today" and "it will run for a year while I sleep."
2
Outcome
Your strategy restarts itself, refreshes its token before open, audits itself, writes its diary.
3
Vocabulary
cron schedule · daily token refresh · pre-live audit · log rotation · background daemon
4
Hands-on
Set up daily reminders · run the pre-live audit · verify the bot comes back after a reboot.
5
War story
Three independent bugs hit a brand-new strategy in 60 seconds of live trading. 99 unit tests sat happy and green.
1 · The idea
"Worked today" is not the same as "will run for a year."
A script (Week 9)
- You start it manually at 09:00.
- You watch it all day.
- If the laptop sleeps, the bot dies.
- Token expired at 3:30 AM? You'll find out at 09:15.
- Yesterday's log is in a file called
nohup.out.
A system (Week 10)
- cron starts it at 09:00 — even if you're asleep.
- A separate cron refreshes the token at 03:30 AM.
- A separate cron sends you a "ready to trade?" check at 08:55.
- Each day's log is dated. Old logs rotate away automatically.
- On reboot, cron picks up where it left off. Nothing to remember.
The system is just the script + four invisible helpers. Set them up once. Forget about them — that's the point.
The four pillars of "runs while you sleep"
Four crons. No daemon to babysit.
🌙
1 · Token refresh
Broker tokens die overnight. A cron at 03:30 AM gets a fresh one and saves it to .env.
30 3 * * 1-5
🔍
2 · Pre-live audit
At 08:55 a script checks: today is a trading day, margin is enough, holiday file is current, token works.
55 8 * * 1-5
🚀
3 · Strategy start
At 09:00, cron launches the strategy via nohup ./start_oc.sh &. Logs to today's dated file.
0 9 * * 1-5
🧹
4 · Log rotation
At 23:00 each Saturday, gzip logs older than 7 days. Keeps logs/ small.
0 23 * * 6
Each cron does one job. If one fails, the others keep working — and you get a Telegram alert about the failure.
What your crontab actually looks like
Five lines. One file.
crontab -e (on the Lightsail server)
five lines, in order of when they run
# min hour dom mon dow command
30 3 * * 1-5 /home/ubuntu/scripts/refresh_token.sh # overnight token refresh
55 8 * * 1-5 /home/ubuntu/scripts/prelive_audit.sh # 35 min before market open
3 9 * * 1-5 /home/ubuntu/scripts/daily_reminder.sh # Telegram "today's plan"
0 9 * * 1-5 /home/ubuntu/start_optioncracker.sh # strategy goes live
0 23 * * 6 /home/ubuntu/scripts/rotate_logs.sh # Saturday log rotation
# dow = day of week. 1-5 = Mon-Fri. * in any field = "every".
# Every command logs to its own file under /home/ubuntu/logs/.
Five lines is the whole "system." Anything more is over-engineering for a one-person trading operation.
2 · By the end of this week
Reboot the server. Bot comes back.
All four crons are installed and active. crontab -l shows the five lines from the previous slide.
The token refresh ran successfully overnight — your morning Telegram says "token refreshed · valid until 03:30 tomorrow".
The pre-live audit at 08:55 sends a Telegram message: "today is trading day · margin OK · token OK · ready".
You rebooted the Lightsail server on a Sunday evening. On Monday morning, the bot was live without you doing anything.
By Friday, you should be able to take a phone call for an hour at market open without panic. That's the upgrade.
3 · New vocabulary
Five words. Use them this week.
cron schedule
A line saying "run this command at this time." The clock that turns your script into a service.
0 9 * * 1-5
daily token refresh
A nightly cron that gets a new broker access token before the old one expires.
30 3 * * 1-5
pre-live audit
A script that runs before market open and checks everything that has to be true before money moves.
trading_day · margin · token
log rotation
Compress or move old log files so the disk doesn't fill up. Keeps the system healthy without your attention.
logrotate · gzip
background daemon
A program that runs detached from your terminal session. Survives logout. Used by your strategy at runtime.
nohup ./start.sh &
All five together = the bot survives weekends, reboots, lost SSH sessions, and your phone going on Do Not Disturb.
4 · The hands-on bit — your task
Wire the four crons. Reboot. Verify.
What to do this week (3–4 hours, spread across two days)
- Write the four scripts in
~/scripts/ on your server: refresh_token.sh, prelive_audit.sh, daily_reminder.sh, rotate_logs.sh. Each is 20–40 lines of bash that calls a Python helper.
- Install the crontab.
crontab -e. Paste the five lines from the slide. Adjust paths to your home folder. Save.
- Verify schedule lines parse with
crontab -l. Then run each script manually once to confirm it works end-to-end before relying on the schedule.
- Write the pre-live audit in Python: it checks
is_trading_day(), fetches funds (token is alive), reads margin (≥ minimum), prints PASS/FAIL for each. Send the summary to Telegram.
- The reboot test. On Sunday evening, SSH into Lightsail and run
sudo reboot. Don't open the laptop on Monday morning until 09:30. Then check Telegram — the system should be running.
- Inspect the diary. Open
logs/optioncracker_$(date +%F).log. Read it end-to-end. Anything you didn't expect → write it down.
Cron failures are silent by default. Wire every script to send a Telegram ERROR on non-zero exit code — your phone is the only thing you'll check.
5 · A real-money war story · 2026-05-13
Three independent bugs in 60 seconds. Ninety-nine unit tests sat green.
First Strike launched live for the first time. The pre-live audit said green. The tests said green. Within sixty seconds of the reference capture at 09:16, the engine logged three independent failure modes — each one a real bug, all hiding in production-only code paths the test suite never exercised.
The first 60 seconds, live
09:16:02
Bug 1 — wrong candle timestamp. The BID signal asked Upstox for the previous day's 15:30 candle. Upstox stamps the closing minute as 15:29. The lookup returned None.
09:16:11
Bug 2 — None not handled. The code path for "no candle returned" silently fell through to a default direction instead of bailing. A real-money decision based on a fabricated value.
09:16:43
Bug 3 — unmigrated workaround. A defensive shim that existed in DecayDoctor's code (from a similar bug a month earlier) had never been ported into First Strike. The same hole, in a new strategy.
09:17:00
The test suite during all of this: 99 unit tests · 0 failures · 0 warnings. Every test passed against mocks that returned happy-path values.
The lesson, pinned
Tests protect what they exercise. Not what they don't.
Three independent failures arriving together in the first sixty seconds of production is a
signal: production is doing real work the tests aren't. The test suite was protecting a
different, easier code path — one with happy-path return values, no Nones, no
404s, no timestamp quirks.
The defence is not "more unit tests." It is end-to-end coverage: a test that runs the
same code path live does, with mocks that resemble the broker's actual shape — including the
404s, the Nones, and the off-by-one timestamps. And cross-strategy migration: when a
defensive shim is added to one strategy, every other strategy with the same hole needs the
same fix. Tests don't audit that for you. A human does, with a checklist.
3
independent failures, all in 60 seconds
99
unit tests passing the whole time
1
end-to-end test today reproduces the live path with broker-shaped mocks
Week 10 — takeaway
A system is four crons,
a diary, and a paranoid audit.
Wire the helpers once. Trust them with your Sunday. And remember the day three production bugs landed while every unit test was green — go-live is a different code path than the test suite, and the difference is exactly where the real-money bugs live.
End of Week 10
Next: Backtesting honestly.
Week 11 — Walk-forward, slippage, the lies your spreadsheet tells →
source: cowork/Course_Outline_12_Weeks · Week 10 · 2026-05-13 First Strike incident