Mercurial
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}' +```