Files
alpaclaudia/docs/STRATEGY.md
T
admin 39875112a0 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.
2026-04-16 21:38:25 +02:00

48 lines
2.1 KiB
Markdown

# Strategy notes
## The Wheel
A short-volatility, cash-secured income strategy. Two phases per underlying:
**Phase 1 — no shares held:** sell a cash-secured put (CSP). The bot picks a
contract 14-28 DTE (`WHEEL_PUT_DTE_MIN/MAX`) with absolute delta closest to
`WHEEL_PUT_TARGET_DELTA` (default 0.30). If the trade's annualised yield falls
below `WHEEL_MIN_ANNUAL_YIELD`, it's skipped. If delta data is missing (Alpaca
snapshot), it falls back to "closest to `WHEEL_PUT_OTM_PCT` below spot".
Two outcomes at expiry:
- Put expires worthless → keep premium, repeat Phase 1.
- Put is assigned → own 100 shares per contract at strike, go to Phase 2.
**Phase 2 — shares held:** for each uncovered 100-share lot, sell a covered
call ~same DTE, same target delta, **at or above cost basis** (hard floor in
`risk.check_covered_call`). Two outcomes at expiry:
- Call expires worthless → keep premium, keep shares, sell another call.
- Call is assigned → 100 shares called away at strike (a locked-in gain,
because strike ≥ cost basis), back to Phase 1.
Assumption: the underlying is one we'd be happy to own. That's why
`WHEEL_UNIVERSE` should be small and considered.
## Trailing stops
Separate from the wheel — applies to any long equity position. On each tick,
for every long stock position without an existing open trailing-stop order,
the bot submits a `trailing_stop` sell at `TRAILING_STOP_PCT` trail.
In practice this is idempotent: duplicates are avoided by the open-order check.
## Why not long calls / verticals?
Deliberately kept out of v0. They require managing more Greeks than the wheel
and increase the surface area of risk mistakes. Easy to add under
`strategies/` once the wheel is stable on paper for weeks.
## Candidates to consider later
- **Trailing-stop on short puts** once they're deep ITM vs. the underlying's
drift — close early and re-roll.
- **Cash-sweep** into BIL/SGOV for idle cash while waiting for assignments.
- **Volatility filter** — skip CSPs when IV rank is below a threshold (low premium).
- **Earnings blackout** — skip CSP entries within N days of earnings.