view schwab_trader/README.md @ 279:b3b547563ec7

Add Google connector service and agent wiki Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code. Co-authored-by: Copilot <[email protected]> Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:22:36 -0700
parents eb8b4230fdb9
children
line wrap: on
line source

# 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}'
```