diff schwab_trader/README.md @ 220:eb8b4230fdb9

[schwab-trader] Add guarded trading experiment
author MrJuneJune <me@mrjunejune.com>
date Sun, 02 Aug 2026 08:52:13 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/schwab_trader/README.md	Sun Aug 02 08:52:13 2026 -0700
@@ -0,0 +1,160 @@
+# Schwab Trader
+
+Small Bazel-built helper for the Schwab Trader API. This project is only plumbing: it helps authenticate, inspect accounts, build explicit user-specified stock orders, and submit them only when a live-trade confirmation flag is present.
+
+It does not recommend trades, choose symbols, allocate portfolio risk, or automate a strategy.
+
+## Can Schwab accounts be traded by API?
+
+Yes. Schwab provides the Trader API through the Schwab Developer Portal. The flow is OAuth 2.0:
+
+1. Create an app in the Schwab Developer Portal.
+2. Get an app key and app secret.
+3. Register a redirect URI.
+4. Open the OAuth authorization URL and log in through Schwab.
+5. Exchange the returned `code` for an access token and refresh token.
+6. Use the access token against `https://api.schwabapi.com/trader/v1`.
+
+Do not use username/password scraping or browser automation. The supported path is OAuth tokens.
+
+Useful endpoints this project targets:
+
+- `GET https://api.schwabapi.com/trader/v1/accounts/accountNumbers`
+- `GET https://api.schwabapi.com/trader/v1/accounts`
+- `GET https://api.schwabapi.com/trader/v1/accounts/{accountHash}`
+- `POST https://api.schwabapi.com/trader/v1/accounts/{accountHash}/orders`
+
+Schwab uses account hashes for trading API calls. Fetch them with `account-numbers` before placing any order.
+
+## Build and test
+
+From the repo root:
+
+```bash
+bazel build //schwab_trader:schwab_cli
+bazel test //schwab_trader:schwab_client_test
+bazel build //schwab_trader:schwab_dashboard
+bazel test //schwab_trader:dashboard_test
+```
+
+## Configuration
+
+Set these environment variables:
+
+```bash
+export SCHWAB_APP_KEY="your-schwab-app-key"
+export SCHWAB_APP_SECRET="your-schwab-app-secret"
+export SCHWAB_REDIRECT_URI="https://127.0.0.1"
+export SCHWAB_TOKEN_FILE="$HOME/.config/zenbu/schwab_tokens.json"
+```
+
+`SCHWAB_TOKEN_FILE` is optional and defaults to `~/.config/zenbu/schwab_tokens.json`. Token files are written with `0600` permissions.
+
+## OAuth bootstrap
+
+Print the Schwab login URL:
+
+```bash
+bazel run //schwab_trader:schwab_cli -- auth-url
+```
+
+Open it, log in through Schwab, authorize the app, then copy the full callback URL or just its `code` parameter:
+
+```bash
+bazel run //schwab_trader:schwab_cli -- token --code 'https://127.0.0.1/?code=...'
+```
+
+Refresh later:
+
+```bash
+bazel run //schwab_trader:schwab_cli -- refresh
+```
+
+## Account discovery
+
+```bash
+bazel run //schwab_trader:schwab_cli -- account-numbers
+bazel run //schwab_trader:schwab_cli -- accounts --positions
+```
+
+## Order dry run
+
+Build a stock order payload without sending it:
+
+```bash
+bazel run //schwab_trader:schwab_cli -- build-equity-order \
+  --action BUY \
+  --symbol AAPL \
+  --quantity 1 \
+  --order-type MARKET
+```
+
+`place-equity-order` is also dry-run by default:
+
+```bash
+bazel run //schwab_trader:schwab_cli -- place-equity-order \
+  --account-hash "$SCHWAB_ACCOUNT_HASH" \
+  --action SELL \
+  --symbol AAPL \
+  --quantity 1 \
+  --order-type LIMIT \
+  --price 250.00
+```
+
+To actually submit an order, both safety flags are required:
+
+```bash
+bazel run //schwab_trader:schwab_cli -- place-equity-order \
+  --account-hash "$SCHWAB_ACCOUNT_HASH" \
+  --action BUY \
+  --symbol AAPL \
+  --quantity 1 \
+  --order-type MARKET \
+  --live \
+  --confirm-live-trade
+```
+
+Use live trading only after checking the generated JSON, account hash, symbol, quantity, order type, and Schwab API permissions.
+
+## Local sentiment dashboard
+
+Run the local dashboard:
+
+```bash
+bazel run //schwab_trader:schwab_dashboard
+```
+
+Then open:
+
+```text
+http://127.0.0.1:8765
+```
+
+The dashboard is intentionally local-first and read/paper-trade oriented. It has no live-trade endpoint. It shows:
+
+- Schwab environment/token status without exposing token values
+- risk settings such as profit target, stop loss, confidence threshold, and max paper-trade dollars
+- manually added social evidence from Reddit/X/news/etc.
+- deterministic sentiment signals and confidence
+- paper trades with simple risk rejection
+- audit events
+
+The dashboard stores state in:
+
+```text
+~/.local/share/zenbu/schwab_trader/dashboard.db
+```
+
+Override it when testing:
+
+```bash
+bazel run //schwab_trader:schwab_dashboard -- --db /tmp/schwab_dashboard.db
+```
+
+Social evidence can be added through the page or API:
+
+```bash
+curl -X POST http://127.0.0.1:8765/api/evidence \
+  -H 'Content-Type: application/json' \
+  -d '{"source":"reddit","symbol":"AAPL","text":"$AAPL bullish strong growth","engagement":42}'
+```