initial: alpaclaudia paper-trading bot + dashboard

Python bot (bot/alpaclaudia): alpaca-py client, wheel strategy (CSP + covered
calls) plus equity trailing stops, risk gates (cash buffer, cost-basis guard,
per-symbol concentration cap), SQLite state log, Typer CLI (tick/loop/status/
report/dump-state), Discord daily report, pytest suite.

Next.js 14 dashboard (dashboard/): read-only — reads the bot's SQLite directly
and pulls live account/positions/orders from Alpaca. KPIs, equity chart,
positions, bot-intents audit table, and orders table. Dark UI with Tailwind.

systemd/: user-unit templates for the polling loop and the post-close report
timer.

docs/STRATEGY.md: wheel mechanics, risk invariants, later candidates.

Defaults to BOT_MODE=dry — nothing is submitted to Alpaca until explicitly
enabled in .env. ALPACA_ENV=paper by default; flipping to live requires an
explicit second guard.
This commit is contained in:
2026-04-16 21:38:25 +02:00
commit 39875112a0
46 changed files with 5195 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
# alpaclaudia
Automated **Alpaca paper-trading bot** with a **Next.js dashboard**.
Strategy coverage today:
- **Wheel** — sells cash-secured puts on a configurable universe, rolls into covered calls after assignment.
- **Trailing stops** — on every long equity position (opt-in).
Safety first: by default `BOT_MODE=dry` — the bot plans and logs intents but **submits nothing** to Alpaca. Flip to `live` only after you've reviewed the intent log.
```
finhacks/
├── bot/ # Python 3.11+ trading bot (alpaca-py, SQLite state)
├── dashboard/ # Next.js 14 dashboard (read-only view of bot + Alpaca)
├── systemd/ # user-unit templates for loop + daily report
├── data/ # SQLite DB lives here (gitignored)
├── logs/ # bot logs (gitignored)
└── docs/ # extra docs
```
## Quick start (paper)
```bash
# 0. prerequisites: Python 3.11+, Node 20+, a paper Alpaca account
# 1. credentials
cp .env.example .env
# edit .env and set ALPACA_API_KEY, ALPACA_API_SECRET
# leave BOT_MODE=dry for the first few runs
# 2. bot
cd bot
python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m alpaclaudia status # smoke test
.venv/bin/python -m alpaclaudia tick # one dry iteration
# 3. dashboard
cd ../dashboard
cp .env.example .env.local
# set ALPACA_API_KEY + ALPACA_API_SECRET (same paper creds)
npm install
npm run dev # http://localhost:3030
# 4. schedule (optional, systemd user units)
# see systemd/README.md
```
## How a tick runs
```
scheduler.tick()
├─ snapshot account / positions / orders (Alpaca)
├─ record_tick() → SQLite
├─ plan_wheel() ── produces OrderIntent[]
├─ plan_trailing_stops() ── produces OrderIntent[]
├─ risk.check_*() ── per intent; blocked → logged, never submitted
└─ executor.submit_intent() ── no-op in dry-run; else Alpaca REST
```
Everything the bot considers ends up in `data/alpaclaudia.db::order_intents`, whether submitted, blocked, or dry-run. The dashboard reads this table verbatim, so you can audit the bot's reasoning independently of Alpaca.
## Going live (on paper — still "paper" at Alpaca)
After reviewing a couple of dry runs:
```bash
# in .env
BOT_MODE=live
ALPACA_ENV=paper # still paper account — don't touch this unless you mean it
```
`ALPACA_ENV=live` is a separate, explicit guard that flips the SDK to the production endpoint. Don't set it unless you really want real money at stake.
## Daily Discord report
Set `DISCORD_WEBHOOK_URL` in `.env` and enable the timer:
```bash
systemctl --user enable --now alpaclaudia-report.timer
```
It fires MonFri at 22:30 local time (≈30 min after NYSE close if you're in Europe).
## Risk invariants (code in `bot/alpaclaudia/risk.py`)
- CSPs require `strike * 100 * qty ≤ cash equity * MIN_CASH_BUFFER_PCT`.
- CSP collateral per symbol capped at `MAX_POSITION_PCT` of equity.
- Covered calls only sell above cost basis — never locking in a loss.
- Covered calls require ≥ `qty*100` underlying shares already held.
- Trailing stops only on long equity positions we own.
Tests: `cd bot && .venv/bin/pytest`.
## Repo
- Mirror: https://git.zeitanker.digital/admin/alpaclaudia