- Python 99.8%
- Dockerfile 0.2%
Closes #3 Co-authored-by: Pi Worker <pi-worker@example.com> Reviewed-on: #4 Reviewed-by: pippero-bot <pregno+bot@pm.me> |
||
|---|---|---|
| .pippero | ||
| docs/superpowers | ||
| pivotbot | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| config.btc.yaml | ||
| config.example.yaml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| pyproject.toml | ||
| README.md | ||
PivotBot
Single-symbol pivot-bounce trading bot on Alpaca. Spec:
docs/superpowers/specs/2026-06-11-pivotbot-design.md.
Setup
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp config.example.yaml config.yaml # edit symbol etc.
cp .env.example .env # fill in your Alpaca keys
Secrets are read from a .env file sitting next to config.yaml (gitignored).
Real environment variables, when set, take precedence over .env.
Backtest first
python -m pivotbot backtest --start 2025-01-01 --end 2026-01-01
Do not run the live loop until the backtest shows an edge on YOUR symbol.
Paper trading
python -m pivotbot live # mode: paper in config.yaml
Stop it any time: touch HALT (checked every tick) or Ctrl-C.
While running, the live loop prints a one-character-per-bar pulse to the
console (▢ quiet · B/S entry · C close · E error · H halt ·
! loss-limit · ~ stale feed). Pass --quiet to suppress it. Full
tracebacks for any tick error are appended to errors.log (path:
error_log_path in config); trade/decision history stays in pivotbot.db.
A steady stream of ~ means the data feed lags more than two bar periods
behind. Alpaca's free stock feed (stock_feed: iex) is delayed ~15 minutes,
which exceeds the 2-bar staleness window on short timeframes (e.g. 5m → 10m
window), so the bot never takes entries. Use timeframe_minutes: 15 (the
default — 30m window absorbs the delay) or set stock_feed: sip for real-time
data (requires a paid Alpaca market-data subscription).
Real-money live additionally requires I_UNDERSTAND_LIVE_TRADING=yes
(in the environment or in .env).
Multiple live bots
Run two or more paper/live configs in one process by repeating --config:
python -m pivotbot live-many --config config.spy.yaml --config config.btc.yaml
live-many is only for paper/live configs, not parallel backtests or sweeps.
Each paper/live config must set cash_cap; entries are capped to
cash_cap / entry_price before final submission. Runtime artifacts stay in
the configured directories and are namespaced by config label (for example,
pivotbot.config-spy.db, errors.config-spy.log, HALT.config-spy). The
dashboard shows each bot's label, symbol, mode, status, last pulse,
consecutive errors, and last update time; pass --quiet to suppress dashboard
refreshes. Ctrl-C stops the
bot threads gracefully without writing halt files or closing positions.
Docker Compose
Docker Compose runs PivotBot in a local container image so you do not need to
install the Python package directly on the host. Secrets stay in your local
.env file and config.yaml is bind-mounted at runtime; neither file is baked
into the image.
-
Create local configuration files:
cp config.example.yaml config.yaml # edit symbol, mode, risk, paths, etc. cp .env.example .env # fill in your Alpaca keysKeep
mode: paperinconfig.yamluntil you are ready for real-money trading. Real-money live trading also requiresI_UNDERSTAND_LIVE_TRADING=yesin.envor the environment. -
Build the image:
docker compose build -
Smoke-test the CLI:
docker compose run --rm pivotbot python -m pivotbot --help -
Run a backtest with the mounted
config.yaml:docker compose run --rm pivotbot python -m pivotbot backtest \ --config /app/config.yaml --start 2025-01-01 --end 2026-01-01 -
Run the live loop (paper by default when
mode: paperis inconfig.yaml):docker compose up pivotbotStop it with Ctrl-C followed by:
docker compose down
The default Compose command is equivalent to:
python -m pivotbot live --config /app/config.yaml
Because config.yaml is mounted read-only from the repository root, edit the
host file to change symbols, trading mode, or runtime artifact paths. By
default, relative paths such as pivotbot.db, errors.log, and HALT are
inside the container unless you configure absolute or mounted paths.
Tests
python -m pytest