Market-aware cron wrapper — drop-in replacement for /bin/bash in your crontab that only runs your script on trading days.
Also works as a standalone CLI tool with structured, parseable output — friendly to agentic AI workflows.
Why agentic-friendly? LLM agents and orchestration loops can call
fin-bash checkorfin-bash nextto decide at runtime whether to trigger market-dependent tasks. The output is concise and deterministic — no scraping, no API keys, no rate limits — just a local calendar lookup with clear exit codes (0= open,10= closed).
# An AI agent can gate a data-fetch step like this:
if fin-bash check --exchange XNYS --date 2026-03-16; then
echo "Market open — proceed with data pipeline"
fi
# Or ask for the next N trading days to plan ahead:
fin-bash next --count 5- Python 3.9+ (check with
python3 --version) - pip (usually bundled with Python)
# 1. Clone the repo
git clone https://github.com/mvpp/fin-bash.git
cd fin-bash
# 2. Create a virtual environment and install
python3 -m venv .venv
.venv/bin/pip install -e .
# 3. (Option A) Symlink to a directory on your PATH
sudo ln -s "$(pwd)/.venv/bin/fin-bash" /usr/local/bin/fin-bash
# 3. (Option B) Or use the full path directly in crontab
# ~/path/to/fin-bash/.venv/bin/fin-bashNote: On macOS, if
/usr/local/bindoesn't exist, create it withsudo mkdir -p /usr/local/binor use~/.local/bininstead (make sure it's on your$PATH).
On Windows, cron is not available natively. Use Task Scheduler instead.
# 1. Clone the repo
git clone https://github.com/mvpp/fin-bash.git
cd fin-bash
# 2. Create a virtual environment and install
python -m venv .venv
.venv\Scripts\pip install -e .
# 3. Verify it works
.venv\Scripts\fin-bash.exe checkTo use with Task Scheduler:
- Open Task Scheduler → Create Basic Task
- Set the trigger to your desired schedule (e.g., daily at 9:30 AM, weekdays only)
- Set the action to Start a program:
- Program:
C:\path\to\fin-bash\.venv\Scripts\fin-bash.exe - Arguments:
your_script.sh(or--exchange XLON your_script.sh)
- Program:
Note:
fin-bashinvokes/bin/bashto run scripts, which requires WSL or Git Bash on Windows. If you're using PowerShell scripts (.ps1), you'll need to modify the tool to callpowershell.exeinstead.
fin-bash --help # show all options
fin-bash check # is today a trading day?
fin-bash next --count 5 # upcoming trading daysReplace /bin/bash with fin-bash:
# Before:
30 9 * * 1-5 /bin/bash ~/scripts/scan.sh
# After (only runs on NYSE trading days):
30 9 * * 1-5 fin-bash ~/scripts/scan.sh
# With a specific exchange:
30 9 * * 1-5 fin-bash --exchange XLON ~/scripts/london_scan.sh- If the market is open: runs
/bin/bash <script>(viaexecvp, zero overhead). - If the market is closed: logs the skip and exits with code
10.
fin-bash check # today
fin-bash check --date 2026-12-25 # specific date
fin-bash check --exchange XLON # London Stock Exchangefin-bash next --count 5fin-bash --dry-run ~/scripts/scan.sh
fin-bash --dry-run --date 2026-03-13 ~/scripts/scan.sh# Only run during regular trading hours (09:30–16:00 for NYSE)
fin-bash --session regular ~/scripts/intraday.sh
# Only run during pre-market (04:00–09:30 for NYSE)
fin-bash --session pre ~/scripts/premarket.sh
# Only run during post-market (16:00–20:00 for NYSE)
fin-bash --session post ~/scripts/afterhours.sh
# Default: "any" — just checks if it's a trading day, ignores time
fin-bash ~/scripts/daily.shOptional YAML config at ~/.config/fin-bash/config.yaml:
exchange: XNYS # default exchange
session: any # any | regular | pre | post
logging:
level: INFO
file: ~/.local/log/fin-bash/fin-bash.logCLI flags override config values. See config/fin-bash.example.yaml for all options.
| Code | Meaning |
|---|---|
0 |
Job ran (or would run in dry-run) |
10 |
Market closed — job skipped |
1 |
Error (bad args, exec failure, etc.) |
Any exchange supported by exchange_calendars, including:
| Code | Exchange |
|---|---|
XNYS |
NYSE (default) |
XNAS |
NASDAQ |
XLON |
London |
XTKS |
Tokyo |
XHKG |
Hong Kong |
XSHG |
Shanghai |
Run with an invalid code to see the full list.
Q: Does fin-bash distinguish between open and closed hours on a trading day?
By default, no — fin-bash runs your script as long as it's a trading day, regardless of what time it is. Cron already handles the scheduling; fin-bash just gates on "is it a trading day?"
If you need time-of-day awareness, opt in with --session:
| Flag | Behavior |
|---|---|
--session any (default) |
Runs if today is a trading day — ignores time |
--session regular |
Runs only during market hours (e.g., 09:30–16:00 ET) |
--session pre |
Runs only during pre-market (e.g., 04:00–09:30 ET) |
--session post |
Runs only during post-market (e.g., 16:00–20:00 ET) |
Q: Does --session regular handle half trading days (like the day before Thanksgiving)?
Yes. fin-bash uses the actual close time from the exchange calendar, not a hardcoded 16:00. On early-close days, the session window adjusts automatically:
$ fin-bash check --date 2026-11-27
✓ 2026-11-27 is a trading day on XNYS
Session: 09:30 – 13:00 America/New_York
So --session regular at 14:00 ET on that day would skip, because 14:00 is past the 13:00 early close.
Q: Is there a risk of the market calendar being out of date? Do I need to re-compile fin-bash?
There is a small risk for unexpected, ad-hoc market closures (e.g., emergency weather closures or a National Day of Mourning). Standard recurring holidays are calculated dynamically and will remain accurate far into the future.
Since fin-bash is a Python tool, you do not need to re-compile anything. The calendar data comes from the exchange-calendars package. To get the latest calendar updates for sudden closures, simply upgrade the dependency in your virtual environment:
# On macOS / Linux
cd fin-bash
.venv/bin/pip install --upgrade exchange-calendars
# On Windows
cd fin-bash
.venv\Scripts\pip install --upgrade exchange-calendarsThe next time fin-bash runs, it will immediately use the newly downloaded calendar rules.
Q: I run fin-bash from California but check a non-US exchange (e.g. XHKG). Does it use the right date?
By default, fin-bash uses date.today() from the machine's local clock. If you run it Sunday night in California, it checks Sunday — even though it is already Monday in Hong Kong.
Use --tz-aware to resolve "today" in the exchange's own timezone instead:
fin-bash check --exchange XHKG --tz-aware
# Output: (date resolved in exchange timezone: Asia/Hong_Kong)This applies to all commands:
fin-bash check --exchange XHKG --tz-aware
fin-bash next --exchange XHKG --tz-aware --count 5
fin-bash --exchange XHKG --tz-aware ~/scripts/hk_scan.shNote:
--tz-awareis only needed when your machine's date and the exchange's local date could differ — which happens when there is a large timezone offset and you are running close to midnight.