Skip to content
earlisrealPublic

About

Free, open-source day-trading platform - real-time charts with 10-second candles, a Level 2 DOM ladder, time & sales, and hotkey multi-broker order execution. Local-first: your machine, your keys.

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Repository files navigation

eTape logo

eTape

A free, open-source day-trading platform — read the tape, work the ladder, fire orders from hotkeys.

Real-time charts · Level 2 DOM ladder · Time & Sales · Pre-market scanner · Multi-broker execution

Go React Platforms Local first License: MIT Latest release

eTape workspace — chart, DOM ladder, and time & sales


eTape is a trading platform built the way scalpers and momentum day traders actually work: one screen with fast charts, a live order book, the tape, and one-keystroke order entry — running entirely on your own machine. No subscription, no cloud middleman, no per-month platform fee. Bring a moomoo account for market data and the broker of your choice for execution, and everything else is free and open source.

Why eTape?

  • Speed as a design rule. The engine is pure Go; the chart, ladder, and tape are canvas surfaces painted imperatively and coalesced to one repaint per frame. High-frequency market data never touches React state.
  • 10-second candles, built live from raw ticks. Sub-minute momentum most retail platforms simply can't show — bucketed by exchange timestamp with live buy/sell direction. Completed candle ranges reconcile safely to OpenD's finalized one-minute envelope when its tick and K-line feeds disagree.
  • A real Level 2 DOM ladder. Full-depth order book rendered on canvas, fed by moomoo's tick-and-depth feed — not a 1-level quote widget.
  • A clearly labelled local LULD aid. During regular hours, supported symbols may show display-only LULD Boundary Rows built from the local eligible-print feed. They are never an official band, halt signal, order control, or risk control; unsupported/expired symbols remain unavailable.
  • Broker-agnostic execution. The same order ticket, hotkeys, and risk gates drive TradeZero, Alpaca, or the built-in simulator. Fills come back as generic events and land on your chart as markers in real time, whatever the venue.
  • Ticketless hotkeys. The order ticket is optional: hotkeys use the most recently user-activated grouped Dockview panel across open windows. The target is ephemeral, never saved in a workspace or restored across a full restart, and its read-only cue shows the linked symbol and resolved venue.
  • Chart Risk Entry. A preset hotkey starts a two-point buy/stop tool on the active grouped chart. Dollar, Cash %, or BP % loss budgets size linked engine-held stop-limit orders; both prices can be adjusted from the chart. Optional auto-send accepts the pair on placement or a completed draft drag; missing recent trades leave it waiting in the engine for a fresh trigger.
  • Safety-gated by default. Zero venues are configured out of the box. Every order must pass a two-layer risk gate (global caps + per-venue caps: max day loss, order value, position size, open orders), and the eTape master execution switch must be explicitly armed.
  • A live demo that actually feels live. No account, no setup: a synthetic market with a warm year of history, a breathing DOM, and a moving scanner board, streaming indefinitely — not a fixed prerecorded session. The universe (which symbols run, which gap, which crash) reshuffles every launch, so spotting the mover is part of the practice, not something you memorize.
  • Local-first and private. Config, credentials, and local state live in ~/.eTape/ on your disk. The UI is served from 127.0.0.1. Your API keys talk to your broker and no one else.

Features

Charting

  • TradingView Lightweight Charts candlesticks, from 10-second bars up to daily/weekly/monthly
  • Indicators: VWAP, EMA, SMA, MACD, Volume
  • Drawing tools — horizontal line, trend line, extended line, rectangle — with per-tool color/width/style memory
  • Live fill markers (buy/sell diamonds) and fill sounds
  • Extended-hours (pre-market / after-hours) data support

Order flow

  • Level 2 DOM ladder with full order-book depth
  • Time & Sales tape with buy/sell coloring, virtualized over a ring buffer

Scanning & context

  • Session-aware gap scanner with float, daily Vol, Session Volume, Dollar Turnover, REL VOL (Daily Rate), and inclusive Last-price bounds using the session-aware displayed price (zero disables, unknown/non-positive values fail active bounds, and admissions stay sticky), plus %-change filters, Reported Short Interest context, and per-Scanner column visibility/order
  • Independent Scanner Panels with per-panel filters, sticky boards, sorting, seen state and sound; one shared quota-controlled service supplies discovery. Session Volume finds stocks outside the mover lists from the provider's top 200 current-session-volume candidates; rows show discovery freshness.
  • Session-aware scanner (gainers, losers, and most active)
  • Stock Info panel: fundamentals grid plus a de-duplicated live news feed with publish times and type badges; headlines open in an unmaximized reusable reader

Execution

  • Order ticket with market / limit / stop / stop-limit / limit-if-touched (LIT)
  • Hotkey deck: configurable one-keystroke order templates with price offsets and position sizing by buying-power % or position %
  • Account, positions, open/closed orders, and trade-history panels
  • Built-in paper simulator with realistic fills: orders walk the live book, partial fills, resting limit orders, configurable slippage and fill latency

Workspace

  • Dockable, drag-and-drop panel layout (dockview) — arrange chart/ladder/tape/scanner however you trade, with linked symbol groups
  • Type a ticker anywhere to load a symbol — the engine subscribes on demand
  • In-app settings for venues, credentials, hotkeys, and appearance

How it works

flowchart TB
    MOOSRV(["moomoo servers"])

    subgraph MACHINE["Your machine — everything runs locally"]
        OPEND["moomoo OpenD — local gateway"]
        ENGINE["eTape engine — Go<br/>order books · bars · indicators · scanner<br/>SQLite journal · risk gate<br/>broker adapters · built-in simulator"]
        UI["eTape UI — React + TypeScript<br/>chart · L2 DOM ladder · time & sales<br/>order ticket · hotkeys · panels"]
    end

    BROKERS(["broker APIs<br/>Alpaca · TradeZero"])

    MOOSRV --> OPEND
    OPEND -->|"quotes · ticks · depth"| ENGINE
    ENGINE <-->|"orders · fills (moomoo)"| OPEND
    ENGINE <-->|"WebSocket + JSON<br/>127.0.0.1:8686"| UI
    ENGINE <-->|"orders · fills"| BROKERS
Loading

The engine speaks OpenD's wire protocol natively in Go (no Python SDK required), builds books/bars/indicators, persists bars and execution state to SQLite, and serves the UI over a localhost WebSocket. TypeScript types for the wire contract are generated from the Go structs, so the two sides can't silently drift.

Download

⬇ Download the latest release — a prebuilt, self-contained binary with the UI embedded. Single file, no installer, no Go or Node toolchain required.

Platform Artifact Run it
Windows (x64) eTape-<version>-windows-amd64.zip Unzip and run etape.exe. Click "Try demo" in the app to start with a synthetic market (no setup needed) — or configure OpenD + venues in settings for live mode. README-FIRST.txt inside covers the details.
macOS (Apple Silicon) eTape-<version>-macos-arm64.tar.gz tar xzf it, then run ./etape-darwin-arm64. Click "Try demo" in the app for a synthetic market, or configure settings for live mode. (Developers: ./etape-darwin-arm64 -demo is equivalent.)
Linux (Ubuntu 24.04 or 26.04 LTS, x64) eTape-<version>-linux-amd64.tar.gz tar xzf it, then run ./etape-linux-amd64 in a terminal. It opens the default browser; if that fails, open http://127.0.0.1:8686 manually. Press Ctrl+C to stop it. Use ./etape-linux-amd64 -demo for a session without OpenD; live mode needs OpenD installed and configured separately.

The Linux archive is portable and does not install a desktop launcher or OpenD. To upgrade, stop eTape with Ctrl+C, replace the extracted executable, and start it again; leave ~/.eTape/ in place so settings and local state remain intact.

The binaries aren't code-signed (personal-use release, no certificate), so expect a one-time warning on first launch: Windows SmartScreen says "unrecognized app" — click More info → Run anyway; macOS Gatekeeper blocks it — right-click → Open (or xattr -d com.apple.quarantine etape-darwin-arm64).

Prefer building from source? The quick start below has you covered.

Quick start from source

Demo mode, no accounts needed. Prerequisites: Go ≥ 1.26 and Node.js 22 LTS on your PATH.

git clone https://github.com/earlisreal/eTape.git
cd eTape
./run.sh demo          # Windows: run.cmd demo

This builds the UI, boots a live synthetic market — no OpenD, no broker, no config — and opens the full app at http://127.0.0.1:8686 with a funded paper simulator: charts warm with a year of history at every timeframe, the DOM ladder breathes, the scanner updates as the (fictional) low-float names run, and hotkeys are live. Place trades immediately; fills price against the live book. The universe reshuffles every launch — pin it to a specific seed for a reproducible session:

./run.sh demo 42       # Windows: run.cmd demo 42

Live market data: moomoo OpenD

eTape's market data comes from moomoo OpenD, the local gateway that ships with moomoo's OpenAPI program. One-time setup:

  1. Create a moomoo account at moomoo.com and enable OpenAPI access.

  2. Download and install OpenD for your OS from the OpenAPI portal.

  3. Launch OpenD and log in with your moomoo credentials. By default it listens on 127.0.0.1:11111, which is where eTape expects it.

  4. Run eTape in live mode:

    ./run.sh live          # Windows: run.cmd live

Then just type a ticker in any panel — the engine subscribes on demand, and the scanner keeps the day's leading symbols warm automatically.

Quote entitlements (check what your moomoo account includes for US stocks):

Your entitlement What works
Level 1 quotes Charts, time & sales, scanner, news — everything except book depth
Level 2+ depth All of the above plus the full DOM ladder

Notes:

  • eTape only ever reads market data from OpenD. It never sends trade commands to it and never touches your moomoo trade password.
  • The DOM's optional LULD Boundary Rows are a local approximation, not an official SIP band or trading-pause indicator. They warm from eligible prints, freeze on provider/transport interruptions, and never change order or risk behavior.
  • US stocks only for now — one market keeps sessions, timezones, and entitlements simple.

Connecting brokers

Venue Environments Status
Built-in simulator (sim) paper ✅ Realistic fills: book-walk pricing, partials, slippage & latency models
Alpaca paper + live ✅ Fully supported (REST + streaming)
TradeZero live ✅ Fully supported (REST + WebSocket)
moomoo paper + live ✅ Fully supported (native OpenD trade connection)

Execution is off by default — with no venues configured, every order is blocked. The easiest way to add one is in-app: Settings → Venues lets you add a venue, enter API credentials, and test the connection; it writes the config for you (with an automatic backup of your previous config.toml).

Credentials are stored locally in ~/.eTape/credentials.json and are only ever sent to the broker they belong to. moomoo is the exception — it has no API key/secret at all; it authenticates over the same local OpenD connection as market data, keyed by account ID, and trade unlock happens once per OpenD restart in the OpenD GUI itself (never inside eTape).

Before any order reaches a broker it must pass the two-layer risk gate — global caps (max day loss, per-symbol position value/shares) and per-venue caps (max order value, position size, open orders) — and the eTape master execution switch must be explicitly armed in the UI. Live venues trade real money; configure them deliberately. Moomoo's separate trade-password unlock remains managed in OpenD.

Setting up Alpaca

Alpaca is the quickest venue to get running: a free account gives you paper trading with no funding required, and eTape reuses the same keys for deep chart history.

  1. Create a free account at alpaca.markets. Paper trading works without depositing anything.
  2. Generate paper API keys (Key ID + Secret Key) from the dashboard — steps 1–2 of Alpaca's connection guide show exactly where. Live keys are separate, generated from the live dashboard, and only needed if you configure a live venue.
  3. Add the venue in eTape: Settings → Venues → Add venue, pick broker Alpaca, paste the Key ID and Secret Key, and hit Test connection — eTape verifies the keys and auto-detects the environment (paper/live) before saving.
  4. Arm the eTape master switch in the UI when you're ready to send orders; until then the gate blocks everything. OpenD's separate trade unlock is still managed in OpenD.

As a bonus, once a paper Alpaca venue is configured the engine automatically reuses its keys (read-only) for historical chart data — full daily history plus deep 1-minute backfill from Alpaca's free market-data API — no extra setup. The Scanner's Vol and Turnover columns use the latest base daily totals from the Moomoo snapshot. REL VOL uses that daily volume divided by the arithmetic mean of up to 50 preceding raw Alpaca SIP daily bars; it is a full-day ratio at every time of day. Short listing histories use the available contiguous days, while missing or unavailable history leaves REL VOL as —. Raw profile bars are temporary and are not added to the chart archive. REL VOL requires Alpaca SIP historical access; with IEX, missing credentials, or an unavailable historical client the column remains —. Live keys are deliberately never used for this.

Configuration

Everything lives in ~/.eTape/ (%USERPROFILE%\.eTape\ on Windows):

File Purpose
config.toml Engine config — optional; a missing file means built-in defaults
credentials.json Broker API keys (managed by Settings → Venues)
etape.db SQLite execution state + bar archives (created automatically)
ticks/ Separate bounded tick/BBO/MD-evidence SQLite archive

Real-feed launches automatically record existing TICKER subscriptions, including Scanner warm-pool activity. Recording does not change candle filters. Optional BOOK captures available top bid/ask observations; it yields to ordinary demand and may be unavailable. Failures warn through existing sys.events while the live feed continues. Defaults retain up to 30 ET dates within a 10 GiB physical cap and a 2 GiB free-disk reserve; heavy traffic can retain much less history. See archive operation and backup guidance and bootstrap settings. -demo is excluded.

Chart-history limits are calendar spans. The default 10-second limit keeps the current trading cycle only, beginning at the latest NYSE close/post-market start. intraday_days applies to focused charts and generic scanner/watch archive warming; it is not the Scanner REL VOL lookback, which requests up to the prior 50 NYSE sessions from Alpaca SIP:

[backfill]
ten_second_days = 0
intraday_days = 70
daily_years = 0

A minimal hand-written config with a paper simulator and tight risk caps:

# ~/.eTape/config.toml — every omitted field falls back to a sane default

[[venue]]
id = "sim-paper"
broker = "sim"            # sim | alpaca | tradezero | moomoo
env = "paper"             # paper | live
starting_balance = 100000

[gate.global]
max_day_loss = 500
max_symbol_position_value = 10000
max_symbol_position_shares = 2000

[gate.venue.sim-paper]
max_order_value = 5000
max_open_orders = 10

The UI and WebSocket are served on 127.0.0.1:8686 by default ([uihub] section to change it). On startup, eTape opens the UI in the default browser. OpenD is expected on 127.0.0.1:11111 ([opend] section).

Windows

run.cmd mirrors ./run.sh exactly — same modes, same arguments — and needs nothing beyond Go, Node.js, and (for live mode) OpenD for Windows. For a self-contained distributable there's also:

cd engine && make release-windows

which produces dist/etape-windows-amd64.exe — a single binary with the UI embedded and a system-tray icon, no console window, no installer. make release-macos does the same for macOS (arm64), and make release-linux produces dist/etape-linux-amd64 for the supported Ubuntu LTS releases. The engine is pure Go (no cgo), so cross-compiling from any OS just works. From the repository root, the Linux release smoke check is:

bash scripts/smoke-linux-release.sh eTape-<version>-linux-amd64.tar.gz

Prebuilt binaries for all three platforms are attached to the latest release.

Race tests with MinGW-w64

The regular Windows build and tests do not need cgo, but go test -race does. For the native Windows race runtime, use a MinGW-w64 compiler; Cygwin's gcc is not compatible. MSYS2 provides the recommended toolchain.

  1. Install MSYS2, using the default C:\msys64 installation path.

  2. Open MSYS2 UCRT64 from the Start menu. Do not use Cygwin or the plain MSYS terminal; UCRT64 puts the native compiler first on PATH.

  3. Update MSYS2 and install the compiler plus the Make executable:

    pacman -Suy
    # If the terminal closes during the core update, reopen MSYS2 UCRT64 and run
    # `pacman -Suy` again before continuing.
    pacman -S --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-make
  4. Verify the toolchain from the same UCRT64 terminal:

    which gcc
    gcc --version
    mingw32-make --version
    go version

    which gcc should resolve to /ucrt64/bin/gcc, not /usr/bin/gcc or a C:\cygwin64\bin\gcc.exe installation.

  5. From the repository root, run the race test:

    mingw32-make -C engine test-race

    Or run Go directly from engine:

    go test -race -short ./...

See the MSYS2 UCRT64 environment guide for environment details. WSL/Linux and CI remain alternatives if a native Windows race toolchain is not needed.

Development

Codebase guides: engine · UI · documentation · external APIs · performance evidence · prototypes · scripts

engine/     Go engine — feed, books, bars, scanner, brokers, risk gate, WS hub
ui/         React + TypeScript + Vite UI — panels, canvas renderers, settings
docs/       Current architecture, dependency, evidence, and planning guides
prototypes/ Python research scripts (latency benchmarks, tick aggregation, …)
Task Command
UI iteration w/ hot reload ./run.sh dev [fixture] (mock engine + Vite on :5173)
Engine tests cd engine && go test ./... (full) + go test -race -short ./...
Engine lint / vet cd engine && golangci-lint run / go vet ./...
UI unit tests cd ui && npm test
UI typecheck / lint cd ui && npm run typecheck / npm run lint
E2E (Playwright, real engine in demo mode) cd ui && npm run e2e
Regenerate TS wire types from Go mingw32-make -C engine gen-ts (gen-ts-check to verify drift)

CI-equivalent validation on Windows

The executable source of truth is .github/workflows/ci.yml. Follow AGENTS.md for focused local checks and hosted CI requirements. Full hosted CI continues to run on every push to main and every pull request. The checklist below is available for broader local verification and CI failure diagnosis; if it drifts from the workflow, follow the workflow and update this guide.

Install the pinned linter once, then verify it before using the fast command:

go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
Get-Command golangci-lint
golangci-lint version

The reported version must be 2.12.2. To run the full local CI-equivalent suite, start from the repository root:

Set-Location engine
go test ./...
go test -race -short ./...
go vet ./...
golangci-lint run
# If the installed binary is not v2.12.2:
go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 run
Set-Location ..
mingw32-make -C engine gen-ts-check
Set-Location ui
npm ci
npm run lint
npm test
npm run build
Set-Location ..
git diff --check

Native Windows go test -race requires the existing MSYS2 UCRT64 toolchain. The UI E2E suite (npm run e2e) is an additional proportional check, not a step in the current CI workflow. For Go changes, verify that changed files use LF line endings; for WebSocket contract changes, verify that ui/src/gen/wsmsg.ts has no generated drift. Before every handoff, run git diff --check, verify that no credentials or runtime data were introduced, and list checks run and results plus every skipped required check and its reason. Hosted CI remains authoritative for its Ubuntu and Windows environments. Prose-only documentation changes need Markdown link validation and git diff --check; they may be handed off while hosted CI is pending, as described in AGENTS.md.

The Go structs are the single source of truth for the engine↔UI protocol — ui/src/gen/wsmsg.ts is generated, never hand-edited.

Roadmap

  • Desktop packaging (Wails)
  • Smarter extended-hours order handling

Disclaimer

eTape is a tool, not advice. Day trading involves substantial risk of loss. This software is provided as-is, without warranty of any kind; you are solely responsible for any orders placed through it and for complying with your brokers' terms. Test against the simulator or a paper account before arming a live venue.

Contributing

Issues, bug reports, and pull requests are welcome. If you're adding a broker adapter or panel, open an issue first and follow its subsystem README plus current specifications in docs/specs/.

License

MIT — free to use, modify, and distribute.

About

Free, open-source day-trading platform - real-time charts with 10-second candles, a Level 2 DOM ladder, time & sales, and hotkey multi-broker order execution. Local-first: your machine, your keys.

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages