From 787c41ba630e52a9b37a3fd2f87b444bedcde932 Mon Sep 17 00:00:00 2001 From: Gahow Wang Date: Mon, 28 Sep 2026 22:03:57 +0800 Subject: [PATCH] Run the daily loop on a server with systemd user units deploy/systemd holds an IB Gateway service (IBC under Xvfb, paper) and timers for the 09:50 ET rebalance, 16:15 ET fills, and a weekly constituents refresh; make install-units installs them. Co-Authored-By: Claude Opus 5.5 --- Makefile | 12 +++++++++++- deploy/systemd/ibgateway.service | 12 ++++++++++++ deploy/systemd/ibkr-quant-fills.service | 9 +++++++++ deploy/systemd/ibkr-quant-fills.timer | 8 ++++++++ deploy/systemd/ibkr-quant-trade.service | 15 +++++++++++++++ deploy/systemd/ibkr-quant-trade.timer | 9 +++++++++ deploy/systemd/ibkr-quant-universe.service | 10 ++++++++++ deploy/systemd/ibkr-quant-universe.timer | 9 +++++++++ 8 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 deploy/systemd/ibgateway.service create mode 100644 deploy/systemd/ibkr-quant-fills.service create mode 100644 deploy/systemd/ibkr-quant-fills.timer create mode 100644 deploy/systemd/ibkr-quant-trade.service create mode 100644 deploy/systemd/ibkr-quant-trade.timer create mode 100644 deploy/systemd/ibkr-quant-universe.service create mode 100644 deploy/systemd/ibkr-quant-universe.timer diff --git a/Makefile b/Makefile index 7762a22..d52384e 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # open, so start after 09:47 ET. RUN = uv run ibkr-quant -.PHONY: test universe check bars plan submit fills backtest +.PHONY: test universe check bars plan submit fills backtest install-units test: uv run pytest -q @@ -32,3 +32,13 @@ fills: # e.g. make backtest ARGS="--top-n 5 10 20 --every 1 5 --capital 10000" backtest: $(RUN) backtest $(ARGS) + +# On the server: install the systemd user units from deploy/systemd. The timers +# start now; the Gateway is only enabled for boot, so start it by hand +# (systemctl --user start ibgateway) once ~/ibc/config.ini has the credentials. +install-units: + mkdir -p ~/.config/systemd/user + cp deploy/systemd/* ~/.config/systemd/user/ + systemctl --user daemon-reload + systemctl --user enable ibgateway.service + systemctl --user enable --now ibkr-quant-trade.timer ibkr-quant-fills.timer ibkr-quant-universe.timer diff --git a/deploy/systemd/ibgateway.service b/deploy/systemd/ibgateway.service new file mode 100644 index 0000000..4d30344 --- /dev/null +++ b/deploy/systemd/ibgateway.service @@ -0,0 +1,12 @@ +[Unit] +Description=IB Gateway (paper) logged in by IBC, headless under Xvfb +After=network-online.target + +[Service] +Type=simple +ExecStart=/usr/bin/xvfb-run -a -s "-screen 0 1024x768x24" %h/ibc/gatewaystart.sh -inline +Restart=always +RestartSec=60 + +[Install] +WantedBy=default.target diff --git a/deploy/systemd/ibkr-quant-fills.service b/deploy/systemd/ibkr-quant-fills.service new file mode 100644 index 0000000..87db9ad --- /dev/null +++ b/deploy/systemd/ibkr-quant-fills.service @@ -0,0 +1,9 @@ +[Unit] +Description=ibkr-quant: record today's executions +After=ibgateway.service + +[Service] +Type=oneshot +WorkingDirectory=%h/projects/ibkr-quant +Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin +ExecStart=/usr/bin/make fills diff --git a/deploy/systemd/ibkr-quant-fills.timer b/deploy/systemd/ibkr-quant-fills.timer new file mode 100644 index 0000000..390b7b3 --- /dev/null +++ b/deploy/systemd/ibkr-quant-fills.timer @@ -0,0 +1,8 @@ +[Unit] +Description=ibkr-quant executions, 16:15 New York time on weekdays + +[Timer] +OnCalendar=Mon..Fri 16:15 America/New_York + +[Install] +WantedBy=timers.target diff --git a/deploy/systemd/ibkr-quant-trade.service b/deploy/systemd/ibkr-quant-trade.service new file mode 100644 index 0000000..bbf98f6 --- /dev/null +++ b/deploy/systemd/ibkr-quant-trade.service @@ -0,0 +1,15 @@ +[Unit] +Description=ibkr-quant daily rebalance: today's bars, then MOC orders +After=ibgateway.service +# Retries cover today's bar arriving late (delayed data) and Gateway restarts; +# make submit refuses to double-submit while orders are open. +StartLimitIntervalSec=7200 +StartLimitBurst=6 + +[Service] +Type=oneshot +WorkingDirectory=%h/projects/ibkr-quant +Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin +ExecStart=/usr/bin/make bars submit +Restart=on-failure +RestartSec=300 diff --git a/deploy/systemd/ibkr-quant-trade.timer b/deploy/systemd/ibkr-quant-trade.timer new file mode 100644 index 0000000..f3d4de5 --- /dev/null +++ b/deploy/systemd/ibkr-quant-trade.timer @@ -0,0 +1,9 @@ +[Unit] +Description=ibkr-quant daily rebalance, 09:50 New York time on weekdays + +[Timer] +OnCalendar=Mon..Fri 09:50 America/New_York +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/deploy/systemd/ibkr-quant-universe.service b/deploy/systemd/ibkr-quant-universe.service new file mode 100644 index 0000000..2d6f44f --- /dev/null +++ b/deploy/systemd/ibkr-quant-universe.service @@ -0,0 +1,10 @@ +[Unit] +Description=ibkr-quant: refresh S&P 500 constituents from Wikipedia + +[Service] +Type=oneshot +WorkingDirectory=%h/projects/ibkr-quant +Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin +# pc reaches Wikipedia only through its local proxy. +Environment=https_proxy=http://127.0.0.1:7890 +ExecStart=/usr/bin/make universe diff --git a/deploy/systemd/ibkr-quant-universe.timer b/deploy/systemd/ibkr-quant-universe.timer new file mode 100644 index 0000000..db91bd5 --- /dev/null +++ b/deploy/systemd/ibkr-quant-universe.timer @@ -0,0 +1,9 @@ +[Unit] +Description=ibkr-quant constituents refresh, Sundays + +[Timer] +OnCalendar=Sun 12:00 America/New_York +Persistent=true + +[Install] +WantedBy=timers.target