# neusse/edge-trader-for-schwab architecture

> Architecture diagram of the GitHub repository neusse/edge-trader-for-schwab, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/neusse/edge-trader-for-schwab
- Repository: https://github.com/neusse/edge-trader-for-schwab

## Overview

Edge Trader is a local equities-trading dashboard for Alpaca Paper and Charles Schwab, with a read-only Demo mode. The main workflow is: a user reviews account and position data, configures and confirms an order, the selected broker adapter submits or manages it, and refreshed broker data is projected into the dashboard with P&L and protection coverage. The README documents additional Paper equity controls and Auto B/E; spreads and options are not enabled for trading. Edges use README statements or the SOURCE INDEX references; unsampled implementation details are not inferred.

Main entry points: [`companion/app.py`](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/app.py) (Web app), [`companion/poller.py`](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/poller.py) (Account poller), [`companion/brokers/canonical_view.py`](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/canonical_view.py) (Canonical projection), [`companion/store.py`](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/store.py) (Local SQLite)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["Dashboard"]
  node_app["Web app<br/>[app.py]"]
  node_cockpit["Dashboard client<br/>[cockpit.js]"]
end

subgraph group_runtime["Runtime and state"]
  node_poller["Account poller<br/>[poller.py]"]
  node_store[("Local SQLite<br/>[store.py]")]
end

subgraph group_broker["Broker integration"]
  node_models["Broker models<br/>[models.py]"]
  node_alpaca["Alpaca Paper<br/>[alpaca_paper.py]"]
  node_schwab["Schwab adapter<br/>[schwab_adapter.py]"]
  node_demo["Demo data<br/>[demo.py]"]
end

subgraph group_analytics["Account projections"]
  node_canonical["Canonical projection<br/>[canonical_view.py]"]
  node_view["Dashboard view<br/>[view.py]"]
  node_orders["Order coverage<br/>[orders.py]"]
  node_pnl["P&amp;L ledger<br/>[pnl.py]"]
end

subgraph group_trading["Order workflows"]
  node_trading["Order service<br/>[trading.py]"]
  node_bracket["Bracket sizing<br/>[bracket.py]"]
  node_order_service["Broker order service<br/>[order_service.py]"]
  node_auto_be["Paper Auto B/E<br/>[paper_auto_be.py]"]
  node_paper_equity["Paper equity controls<br/>[paper_equity.py]"]
  node_spread["Spread subsystem<br/>[spreads.py]"]
  node_spread_ui["Spread desk<br/>[spread_desk.py]"]
end

node_user(("Trader"))
node_schwab_api["Schwab API"]

node_user -->|"uses locally"| node_app
node_app -->|"serves dashboard"| node_cockpit
node_app -->|"uses polling"| node_poller
node_app -->|"uses state"| node_store
node_app -->|"uses demo"| node_demo
node_poller -->|"queries broker"| node_schwab
node_poller -->|"records results"| node_store
node_poller -->|"projects snapshots"| node_canonical
node_poller -->|"builds state"| node_view
node_schwab -->|"translates to"| node_models
node_alpaca -->|"translates to"| node_models
node_schwab -->|"calls"| node_schwab_api
node_canonical -->|"uses order projection"| node_orders
node_canonical -->|"uses fill ledger"| node_pnl
node_canonical -->|"feeds dashboard view"| node_view
node_app -->|"routes workflows"| node_trading
node_trading -->|"sizes brackets"| node_bracket
node_trading -->|"uses order service"| node_order_service
node_order_service -->|"records mutations"| node_store
node_order_service -->|"uses adapter"| node_alpaca
node_poller -->|"watches stops"| node_auto_be
node_auto_be -->|"persists watch"| node_store
node_app -->|"routes Paper controls"| node_paper_equity
node_app -.->|"spread routes"| node_spread_ui
node_spread_ui -->|"uses spread logic"| node_spread

click node_app "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/app.py"
click node_cockpit "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/static/cockpit.js"
click node_poller "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/poller.py"
click node_store "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/store.py"
click node_models "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/models.py"
click node_alpaca "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/alpaca_paper.py"
click node_schwab "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/schwab_adapter.py"
click node_demo "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/demo.py"
click node_canonical "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/canonical_view.py"
click node_view "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/view.py"
click node_orders "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/orders.py"
click node_pnl "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/pnl.py"
click node_trading "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/trading.py"
click node_bracket "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/bracket.py"
click node_order_service "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/order_service.py"
click node_auto_be "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/paper_auto_be.py"
click node_paper_equity "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/paper_equity.py"
click node_spread "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/spreads/spreads.py"
click node_spread_ui "https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/spreads/spread_desk.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app,node_cockpit toneBlue
class node_poller,node_store toneAmber
class node_models,node_alpaca,node_schwab,node_demo,node_schwab_api toneMint
class node_canonical,node_view,node_orders,node_pnl toneRose
class node_trading,node_bracket,node_order_service,node_auto_be,node_paper_equity,node_spread,node_spread_ui,node_user toneIndigo
```

## Components

### Dashboard

- [Web app](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/app.py): `companion/app.py`
- [Dashboard client](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/static/cockpit.js): `companion/static/cockpit.js`

### Runtime and state

- [Account poller](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/poller.py): `companion/poller.py`
- [Local SQLite](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/store.py): `companion/store.py`

### Broker integration

- [Broker models](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/models.py): `companion/brokers/models.py`
- [Alpaca Paper](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/alpaca_paper.py): `companion/brokers/alpaca_paper.py`
- [Schwab adapter](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/schwab_adapter.py): `companion/brokers/schwab_adapter.py`
- [Demo data](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/demo.py): `companion/demo.py`

### Account projections

- [Canonical projection](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/canonical_view.py): `companion/brokers/canonical_view.py`
- [Dashboard view](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/view.py): `companion/view.py`
- [Order coverage](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/orders.py): `companion/orders.py`
- [P&L ledger](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/pnl.py): `companion/pnl.py`

### Order workflows

- [Order service](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/trading.py): `companion/trading.py`
- [Bracket sizing](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/bracket.py): `companion/bracket.py`
- [Broker order service](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/order_service.py): `companion/brokers/order_service.py`
- [Paper Auto B/E](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/paper_auto_be.py): `companion/brokers/paper_auto_be.py`
- [Paper equity controls](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/brokers/paper_equity.py): `companion/brokers/paper_equity.py`
- [Spread subsystem](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/spreads/spreads.py): `companion/spreads/spreads.py`
- [Spread desk](https://github.com/neusse/edge-trader-for-schwab/blob/main/companion/spreads/spread_desk.py): `companion/spreads/spread_desk.py`

### Other components

- **Trader**
- **Schwab API**

## Connections

- Trader → Web app: uses locally (evidence: `README.md`)
- Web app → Dashboard client: serves dashboard (evidence: `companion/app.py`)
- Web app → Account poller: uses polling (evidence: `companion/app.py`)
- Web app → Local SQLite: uses state (evidence: `companion/app.py`)
- Web app → Demo data: uses demo (evidence: `companion/app.py`)
- Account poller → Schwab adapter: queries broker (evidence: `companion/poller.py`)
- Account poller → Local SQLite: records results (evidence: `companion/poller.py`)
- Account poller → Canonical projection: projects snapshots (evidence: `companion/poller.py`)
- Account poller → Dashboard view: builds state (evidence: `companion/poller.py`)
- Schwab adapter → Broker models: translates to (evidence: `companion/brokers/schwab_adapter.py`)
- Alpaca Paper → Broker models: translates to (evidence: `companion/brokers/alpaca_paper.py`)
- Schwab adapter → Schwab API: calls (evidence: `README.md`)
- Canonical projection → Order coverage: uses order projection (evidence: `companion/brokers/canonical_view.py`)
- Canonical projection → P&L ledger: uses fill ledger (evidence: `companion/brokers/canonical_view.py`)
- Canonical projection → Dashboard view: feeds dashboard view (evidence: `companion/brokers/canonical_view.py`)
- Web app → Order service: routes workflows (evidence: `companion/app.py`)
- Order service → Bracket sizing: sizes brackets (evidence: `companion/trading.py`)
- Order service → Broker order service: uses order service (evidence: `companion/trading.py`)
- Broker order service → Local SQLite: records mutations (evidence: `companion/brokers/order_service.py`)
- Broker order service → Alpaca Paper: uses adapter (evidence: `companion/brokers/order_service.py`)
- Account poller → Paper Auto B/E: watches stops (evidence: `companion/poller.py`)
- Paper Auto B/E → Local SQLite: persists watch (evidence: `companion/brokers/paper_auto_be.py`)
- Web app → Paper equity controls: routes Paper controls (evidence: `companion/app.py`)
- Web app → Spread desk: spread routes
- Spread desk → Spread subsystem: uses spread logic (evidence: `companion/spreads/spread_desk.py`)
