comparison 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
comparison
equal deleted inserted replaced
214:4c725fde6999 220:eb8b4230fdb9
1 # Schwab Trader
2
3 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.
4
5 It does not recommend trades, choose symbols, allocate portfolio risk, or automate a strategy.
6
7 ## Can Schwab accounts be traded by API?
8
9 Yes. Schwab provides the Trader API through the Schwab Developer Portal. The flow is OAuth 2.0:
10
11 1. Create an app in the Schwab Developer Portal.
12 2. Get an app key and app secret.
13 3. Register a redirect URI.
14 4. Open the OAuth authorization URL and log in through Schwab.
15 5. Exchange the returned `code` for an access token and refresh token.
16 6. Use the access token against `https://api.schwabapi.com/trader/v1`.
17
18 Do not use username/password scraping or browser automation. The supported path is OAuth tokens.
19
20 Useful endpoints this project targets:
21
22 - `GET https://api.schwabapi.com/trader/v1/accounts/accountNumbers`
23 - `GET https://api.schwabapi.com/trader/v1/accounts`
24 - `GET https://api.schwabapi.com/trader/v1/accounts/{accountHash}`
25 - `POST https://api.schwabapi.com/trader/v1/accounts/{accountHash}/orders`
26
27 Schwab uses account hashes for trading API calls. Fetch them with `account-numbers` before placing any order.
28
29 ## Build and test
30
31 From the repo root:
32
33 ```bash
34 bazel build //schwab_trader:schwab_cli
35 bazel test //schwab_trader:schwab_client_test
36 bazel build //schwab_trader:schwab_dashboard
37 bazel test //schwab_trader:dashboard_test
38 ```
39
40 ## Configuration
41
42 Set these environment variables:
43
44 ```bash
45 export SCHWAB_APP_KEY="your-schwab-app-key"
46 export SCHWAB_APP_SECRET="your-schwab-app-secret"
47 export SCHWAB_REDIRECT_URI="https://127.0.0.1"
48 export SCHWAB_TOKEN_FILE="$HOME/.config/zenbu/schwab_tokens.json"
49 ```
50
51 `SCHWAB_TOKEN_FILE` is optional and defaults to `~/.config/zenbu/schwab_tokens.json`. Token files are written with `0600` permissions.
52
53 ## OAuth bootstrap
54
55 Print the Schwab login URL:
56
57 ```bash
58 bazel run //schwab_trader:schwab_cli -- auth-url
59 ```
60
61 Open it, log in through Schwab, authorize the app, then copy the full callback URL or just its `code` parameter:
62
63 ```bash
64 bazel run //schwab_trader:schwab_cli -- token --code 'https://127.0.0.1/?code=...'
65 ```
66
67 Refresh later:
68
69 ```bash
70 bazel run //schwab_trader:schwab_cli -- refresh
71 ```
72
73 ## Account discovery
74
75 ```bash
76 bazel run //schwab_trader:schwab_cli -- account-numbers
77 bazel run //schwab_trader:schwab_cli -- accounts --positions
78 ```
79
80 ## Order dry run
81
82 Build a stock order payload without sending it:
83
84 ```bash
85 bazel run //schwab_trader:schwab_cli -- build-equity-order \
86 --action BUY \
87 --symbol AAPL \
88 --quantity 1 \
89 --order-type MARKET
90 ```
91
92 `place-equity-order` is also dry-run by default:
93
94 ```bash
95 bazel run //schwab_trader:schwab_cli -- place-equity-order \
96 --account-hash "$SCHWAB_ACCOUNT_HASH" \
97 --action SELL \
98 --symbol AAPL \
99 --quantity 1 \
100 --order-type LIMIT \
101 --price 250.00
102 ```
103
104 To actually submit an order, both safety flags are required:
105
106 ```bash
107 bazel run //schwab_trader:schwab_cli -- place-equity-order \
108 --account-hash "$SCHWAB_ACCOUNT_HASH" \
109 --action BUY \
110 --symbol AAPL \
111 --quantity 1 \
112 --order-type MARKET \
113 --live \
114 --confirm-live-trade
115 ```
116
117 Use live trading only after checking the generated JSON, account hash, symbol, quantity, order type, and Schwab API permissions.
118
119 ## Local sentiment dashboard
120
121 Run the local dashboard:
122
123 ```bash
124 bazel run //schwab_trader:schwab_dashboard
125 ```
126
127 Then open:
128
129 ```text
130 http://127.0.0.1:8765
131 ```
132
133 The dashboard is intentionally local-first and read/paper-trade oriented. It has no live-trade endpoint. It shows:
134
135 - Schwab environment/token status without exposing token values
136 - risk settings such as profit target, stop loss, confidence threshold, and max paper-trade dollars
137 - manually added social evidence from Reddit/X/news/etc.
138 - deterministic sentiment signals and confidence
139 - paper trades with simple risk rejection
140 - audit events
141
142 The dashboard stores state in:
143
144 ```text
145 ~/.local/share/zenbu/schwab_trader/dashboard.db
146 ```
147
148 Override it when testing:
149
150 ```bash
151 bazel run //schwab_trader:schwab_dashboard -- --db /tmp/schwab_dashboard.db
152 ```
153
154 Social evidence can be added through the page or API:
155
156 ```bash
157 curl -X POST http://127.0.0.1:8765/api/evidence \
158 -H 'Content-Type: application/json' \
159 -d '{"source":"reddit","symbol":"AAPL","text":"$AAPL bullish strong growth","engagement":42}'
160 ```