// TRADERVIEW — TRADERVUE-STYLE TRADING JOURNAL

traderview v0.29.0 · Tauri v2 + axum · embedded or external Postgres · vanilla JS + uPlot frontend · 13 broker importers · 1425-tile launcher · MIT

943,870 Rust LOC · 8 library crates + Tauri shell · 125 tables · 110 migrations · 3,095 axum routes · 1424 view modules · 1425 launcher tiles · 299,955 JS LOC · 7,334 CSS LOC

Tutorial Report GitHub
// Color scheme

>_TRADERVIEW — FULL DESKTOP TRADING SUITE

Replaces TraderVue ($30/mo journal) + DayTradeDash ($187/mo scanner) + StockInvest in one self-hosted binary — $2,604/yr saved. Tauri v2 desktop that downloads and runs an embedded PostgreSQL on first launch with a local auto-user, plus an axum web binary with argon2 + JWT for multi-user deployment. Both share eight library crates and the vanilla JS + uPlot frontend. 1424 view modules across a 1425-tile categorized launcher (Cmd-K). Live streams: Nasdaq halts (3s RSS), SEC EDGAR + 4 PR wires (catalyst radar), Finnhub WebSocket (6-panel intraday scanner), Webull broker (read-only positions). Executions are the atom; trades are FIFO-derived; the journal is markdown; expenses get OCR receipts and Schedule-C export.

End-user walkthrough

If you're trying TraderView for the first time, jump into the 18-step tutorial — first launch through every major view, the 1425-tile Cmd-K launcher, broker imports, FIFO trade roll-up, journal + AI post-mortem, the 17-cut report engine, live halt / catalyst / scanner streams, stryke-JIT backtests, custom indicators, strategy alerts, Schedule D / C tax exports, and the community surface. Each step is self-contained and references the route handlers in crates/traderview-web/src/routes/ and the view modules in frontend/js/ by path.

Open tutorial →

Quickstart

Clone the repo, vendor uPlot, then pick a deploy target:

# 1. clone + vendor uPlot
git clone https://github.com/MenkeTechnologies/traderview
cd traderview
./scripts/vendor-uplot.sh

# 2a. desktop — Tauri v2, embedded Postgres
cargo tauri dev          # first launch downloads PostgreSQL (~80 MB)

# 2b. web — axum, external Postgres
docker compose up -d postgres
export DATABASE_URL=postgres://traderview:traderview@localhost:5432/traderview
export TRADERVIEW_JWT_SECRET=$(openssl rand -hex 32)
cargo run -p traderview-web --bin server
# open http://localhost:8080

The desktop app is a single user, fully offline. The web binary is multi-user with registration and JWT bearer auth. Same schema, same migrations, same FIFO roll-up, same frontend, same API surface.

Architecture — One Workspace, Two Deploy Targets

┌──────────────────────────────────────┐ │ frontend/ (vanilla JS + uPlot) │ │ dashboard / trades / journal / ... │ └──────────────┬───────────────────────┘ │ HTTP /api/* ┌────────────────┴────────────────┐ │ │ ┌─────────▼──────────────┐ ┌────────────▼─────────────┐ │ src-tauri │ │ traderview-web (axum) │ │ (traderview-desktop) │ │ bin: server │ │ embedded postgres │ │ external postgres │ │ auto-login local user │ │ argon2 + JWT auth │ └─────────┬──────────────┘ └────────────┬─────────────┘ │ │ └────────────────┬────────────────┘ │ ┌────────────────▼─────────────────┐ │ traderview-{core, db, import} │ │ shared library crates │ └──────────────────────────────────┘

The desktop and web binaries are thin shells. All domain logic, all SQL, all broker parsing lives in the three library crates. The decision "embedded vs external Postgres" and "local auto-user vs multi-user with auth" is the only thing that distinguishes them.

Desktop · traderview-desktop

Tauri v2 shell. postgresql_embedded downloads a portable PostgreSQL on first launch (cached in ~/.theseus), data lives under $APP_DATA_DIR/traderview/pg/. Auto-creates a single local user and auto-logs in. Axum router runs on a random localhost port; the WebView talks to it via fetch. Postgres shuts down cleanly on window close.

Web · server

Axum 0.7 router on 0.0.0.0:8080 (configurable). Connects to external Postgres via DATABASE_URL. argon2 password hashing on registration, JWT bearer auth on every protected route. CORS allowlist via TRADERVIEW_CORS_ORIGIN. Refuses to start without TRADERVIEW_JWT_SECRET.

Shared · traderview-{core,db,import}

Three library crates that both binaries link. core owns models + FIFO roll-up + stats. db owns sqlx pool + migrations + embedded-Postgres lifecycle. import owns broker parsers (Webull first). One-way dependency graph: desktop and web both depend on all three; import and db both depend on core; nothing depends on desktop or web.

Crate Graph

CrateLinesPurpose
traderview-core288,931Domain types (User / Account / Execution / Trade / Plan / Goal / Strategy), FIFO roll-up, statistics (win-rate / expectancy / R-multiple / SQN / Sharpe / Sortino), Kelly + correlation-aware position sizing, Monte Carlo equity forecaster, stryke-JIT backtest engine + walk-forward sweeper, sentiment scoring, custom indicator AST, and 1,500+ pure financial calculators (trading / investing / wealth / accounting / small-business / rental).
traderview-db87,714sqlx pool factory + 110 embedded migrations, embedded PostgreSQL lifecycle (stale-PID lock cleanup, persisted password file), 50+ repo modules covering everything from trades & journal to live halts & catalysts & live_ticks stores, plus the stryke lifecycle-hook store + edge-detection ledger. Background pollers for Yahoo / FINRA / EDGAR / nasdaqtrader / Finnhub WS / Reddit WSB / StockTwits / CoinGecko. In-process LRU caches with eviction.
traderview-import2,61613 broker CSV parsers — Webull, Lightspeed, IBKR Flex, ThinkOrSwim, TD Ameritrade, Schwab, Fidelity, ETrade, Robinhood, TradeStation, DAS Trader, TradeZero, Tradervue — plus a Generic ColumnMap parser for unknown sources (column-mapping wizard). Asset classes: stocks, options, futures, forex.
traderview-web87,554axum 0.7 router — 3,095 routes split across 180 route files. argon2 + JWT auth, multipart upload, WebSocket endpoints for halts / catalysts / live ticks / Webull. Custom request/response logging middleware (snippets bodies on 4xx/5xx). client-errors sink for browser-side reports.
traderview-expense462,973Trading-expense tracker — categorization rules engine, OCR-pipeline integration, Schedule-C report generator, multi-account reconciliation. Used by the expense view + receipt upload.
traderview-ocr5,243Receipt OCR via the system tesseract binary + image preprocessing (binarize, deskew). Extracts merchant / amount / date for the expense matcher.
traderview-tax6,583Tax computation crate — wage / cap-gains / Schedule-C lines, multi-state nexus, fed/state bracketing. Backs the tax wizard view.
traderview-stryke889Host bridge that runs stryke-language lifecycle hooks as sandboxed subprocesses. Invokes the embedded stryke binary (<bin> run <script>, context as JSON on stdin, effects as JSON on stdout) with a 5s timeout + output cap, then validates each emitted effect (tag / note / alert / webhook / journal) against the hook's capability grant. No compile-time fusevm dependency — the binary is a runtime resource.
src-tauri · traderview-desktop1,367Tauri v2 shell. Worker-thread bring-up of embedded Postgres → migrations → axum on a random localhost port; main thread waits on a channel for either an ApiConfig or a String error. Native-dialog on failure. tracing-appender non-blocking file log + panic hook to ~/Library/Application Support/traderview/traderview.log. Embedded handle held across axum::serve so Postgres can't be dropped mid-request.
Total943,870Plus 299,955 LOC vanilla JS (1424 view modules) and 7,334 LOC CSS. No bundler, no npm.

Schema — 125 Tables, 110 Migrations

Migrations under migrations/0001_initial.sql through 0110_asset_class_crypto.sql — each one adds a self-contained feature. Money is NUMERIC(20, 8) everywhere. 125 base tables, 179 indexes, 25 PostgreSQL enum types. Grouped by domain:

DomainRepresentative tables
Identity & accountsusers, accounts, api_tokens, mentorships
Execution & tradesexecutions, trades, trade_executions, trade_tags, tags, imports
Journaljournal_entries, note_templates, trade_reviews, chart_drawings, screenshots
Plans, goals, disciplineplans, trading_goals, goal_progress, discipline_violations
Price data & quotesbars, quote_snapshots, news_items, earnings_events, dividends
Live feedshalts, catalysts, mentions (sentiment), tick_snapshots
Watchlists & screeningwatchlists, watchlist_symbols, filter_sets
Alerts & webhooksalerts, strategy_alerts, strategy_alert_fires, hotkeys, webhooks, webhook_deliveries, disclosures_watchers
Backtest & strategybacktest_runs, backtest_presets, walk_forward_runs, custom_indicators
Paper tradingpaper_accounts, paper_orders, paper_positions
Portfolio / riskrebalance_targets, rebalance_runs, tax_lots
Disclosuresdisclosures (Form 4, 13D/G, Senate/House STOCK Act)
Communityshares, shared_comments, forum_categories, forum_threads, forum_posts, boards, board_items
Settings & AIuser_settings, ai_settings, ai_journal_cache, dashboards
Expensesexpense_accounts, expense_categories, expense_transactions, expense_rules, expense_receipts

Enum types (25): sides (side_t, trade_side_t), statuses (trade_status_t, order_status_t, review_status_t), asset classes, alert triggers, sentiment sources, halt reason codes, etc. — see migrations/0001_initial.sql and feature-incremental migrations for the full set.

HTTP API — 3,095 Routes Under /api/

180 route files in crates/traderview-web/src/routes/. Bearer-auth required on everything except /health, /config, /auth/*, and /client-errors. WebSocket endpoints expose live feeds. Grouped by domain (representative endpoints — see frontend/js/api.js for the full method-bound bindings):

GroupSample routes
Auth + configGET /config, GET /auth/me, POST /auth/login, POST /auth/register
Trades + executionsGET/POST /trades, POST /trades/rollup, POST /trades/{id}/risk, POST /trades/merge, POST /trades/bulk, POST /trades/close-expired-options, POST /trades/{id}/split, GET/POST /executions
Journal + AI + reviewsGET /journal/day/{day}, GET /journal/trade/{id}, POST /journal-ai/{id}/analyze, GET /trade-reviews/needed/{acct}
Reports (17 cuts)/reports/overview, /by-symbol, /by-day-of-week, /by-hour, /by-hold, /r-distribution, /comparison, /exit-efficiency, /liquidity, /drawdown, /risk-adjusted, /calendar
Live streams (WS)15 endpoints — WS /ws/halts, /ws/catalysts, /ws/ticks, /ws/webull, /ws/after-hours, /ws/gamma-squeeze, /ws/breadth-divergence, /ws/rvol-accel, /ws/insider-stream, /ws/uoa-stream, /ws/squeeze, /ws/confluence, /ws/catalyst-correlations, /ws/sentiment-velocity, /ws/stryke-lsp
Research per-symbol/symbols/{sym}/quote, /signals, /news, /earnings, /dividends, /recommendations, /insiders, /fundamentals, /holders
Screener + scannersGET /screener/run, GET /screener/top, GET /scans/run (24 presets)
Options + vol/options/{sym}, /greeks, /vol-surface/{sym}, /iv/scan, /iv/symbols/{sym}
Markets + breadth/markets/snapshot (cached), /premarket/snapshot, /breadth/snapshot, /fear-greed, /sector-rotation
Backtest enginePOST /backtest/run, POST /backtest/walk-forward, GET/POST /backtest-presets, POST /custom-indicators/eval/{sym}
Paper tradingPOST /paper/accounts, GET /paper/accounts/{id}/positions, POST /paper/accounts/{id}/orders, POST /paper/accounts/{id}/reset
Alerts + webhooks + hotkeysGET/POST /alerts, POST /alerts/{id}/toggle, GET/POST /strategy-alerts, GET /strategy-alerts/fires, GET/POST /hotkeys, GET/POST /webhooks, POST /webhooks/{id}/test
Sentiment/sentiment/feed, /sentiment/ranked, /sentiment/symbol/{sym}, /sentiment/series/{sym} (Reddit WSB + StockTwits)
Crypto/crypto/markets, /crypto/global, /crypto/btc/chain
Tax + reports/tax-lots/{acct}?year=&method=FIFO|LIFO, /r-distribution/{acct}, /discipline/{acct}, /mood-analytics/{acct}, /equity-forecast, /fill-quality/{acct}
Webull (read-only)POST /webull/connect (tokens in memory only), GET /webull/snapshot
Expenses + OCRGET/POST /expense/transactions, POST /expense/import, POST /expense/receipts, POST /expense/receipts/{id}/attach, GET /expense/report/schedule_c?year=
Community/shares, /shared/{slug}, /forum/threads, /forum/threads/{id}/posts, /mentorships, /boards
Custom dashboardsGET/POST /dashboards, GET /dashboards/{id} — user-defined boards built from widgets
Client error sinkPOST /client-errors (no auth — browser-side window.onerror + unhandledrejection + console.error funnel)

Desktop mode binds to a random localhost port and auto-logs in as the local user. Web mode requires POST /api/auth/login → JWT → Authorization: Bearer …. A custom request/response logging middleware records every request with elapsed_ms; 4xx/5xx responses get a 4KB body snippet attached to the log entry for offline debugging.

Frontend — Vanilla JS + uPlot, 1424 Views, 1425-Tile Launcher

Zero npm. Zero bundler. Zero JS framework. 299,955 LOC vanilla ES modules + 7,334 LOC CSS served as static files. axum's tower-http fs middleware in web mode; Tauri loads from disk via custom tauri://localhost scheme in desktop mode.

The launcher (Cmd+K) is the entry point — 1425 tiles across 10 categories with a live-filter search and Enter-jumps-to-first-match. There is no fixed nav strip; the topbar carries 11 shortcuts and the rest is the launcher.

⚡ Live Markets (41 tiles)

Live Scanner (Finnhub WS, 6-panel), Halts (Nasdaq RSS + TTS), Catalysts (EDGAR + PR wires), Pre-market / After-hours movers, UOA Stream, Gamma Squeeze, HTB Ranker, Insider Form 4, Breadth Divergence, RVOL Accel, IPO / Econ / FDA calendars, Tape, Heatmap.

📊 Trading (126 tiles)

Webull (read-only broker), Live Positions (open P/L), Paper Trade, New Trade, Pre-trade Plans, Position Size (Kelly + Optimal-f + correlation-aware), risk gates (daily-loss-limit, drawdown-throttle, risk-reward), Hotkeys editor, R-Multiple, Profit Factor, SQN, Omega / K-ratio, futures roll + tick value.

📓 Journal (12 tiles)

Journal (per-trade + daily + general), AI Journal (GPT post-mortem with cache), Trade Reviews (forced reflection on |R| ≥ 2), Trade Compare, Replay, Tape Replay, Discipline, Mood Analytics, Goals, Setups, Note Templates.

🔎 Charts & Research (156 tiles)

Charts (OHLC + persisted drawings), Screener, Scanners, Options chain + Greeks profile, Vol Surface / Smile / Term Structure, Yield Curve (PCA + duration), market microstructure (VPIN, Kyle's λ, order flow, footprint, microprice), 100+ technical indicators & statistical tests (ADF, ACF, Hurst, Kalman β, BOCPD), alternative bar types (range / tick / volume / dollar / imbalance).

📈 Reports & Analytics (678 tiles)

Dashboard, 17-cut Reports, R-Multiple, Monte Carlo forecast, Fill Quality, Risk, Rebalance, Tax Lots, Expenses (with OCR); equity valuation (DCF, Graham, DDM, EV/EBITDA, WACC, DuPont, Altman-Z, Piotroski-F); retirement (FIRE, RMD, Roth ladder, SS / PIA, annuities); fixed income (YTM/YTW, duration, convexity, ladders); real estate (cap rate, DSCR, BRRRR, rent roll, leases); accounting (income statement, trial balance, job / process costing, inventory EOQ/GMROI); business & legal docs (invoices, POs, NDAs, cap tables, payroll, offer letters).

🏛️ Tax Code · IRC § (273 tiles)

One calculator per Internal Revenue Code section — §179 / §168(k) depreciation, §1031 like-kind, §121 home-sale exclusion, §199A QBI, §1202 QSBS, §475(f) trader mark-to-market, §72(t) SEPP, §911 FEIE, §1411 NIIT, §280E, international (§951A GILTI, §901 FTC, §877A expatriation), estate & gift (§2010(c), §2032, §2518), penalties (§6651, §6662, §6694).

🧰 Misc / Specialized (99 tiles)

AMT, backdoor / mega-backdoor Roth, ESPP / ISO / NSO exercise, NUA, QCD, trusts (DAF / CRAT / CRUT / GRAT / SLAT), 13F + Form 4 + congressional-trade trackers, cost segregation, home office, mileage log, K-1 / MLP, ETF + mutual-fund profiles, USPTO patents, supply chain.

🧷 Strategy & Automation (14 tiles)

Backtest (stryke-JIT), Backtest Presets, Walk-forward, Custom Indicators, Strategy Alerts (AND/OR/NOT), Alerts (price/threshold), Webhooks (Discord/Slack/generic), Magic Formula, Confluence Autotrade.

💬 Community (4 tiles)

Shares (public trade links), Community (forum), Mentorship, Boards (public/private symbol boards).

⚙️ Admin & Data (15 tiles)

Import (13 brokers), CSV Wizard, Exports (CSV/JSON/Schedule D), Accounts, Businesses, Tags, Search (full-text), Settings, Developer (API tokens), Log Viewer, Toast History, Tutorial (? hotkey).

Race-safe view dispatch. app.js maintains a per-dispatch token (currentViewToken()) bumped on every navigation. Every view captures the token at render start and bails after each await if the token is stale — prevents the "document.getElementById(...) returns null after navigation" crash that hits naïve SPAs when slow async resolves into a replaced DOM.

js/api.js wraps fetch with auth, error reporting, JSON parsing, and an ApiError class. js/error_reporter.js funnels window.onerror, unhandledrejection, and overridden console.error to POST /api/client-errors, queue-capped at 200 to survive a console-error loop. uPlot vendored under frontend/lib/ — pinned, reproducible, no CDN at runtime.

Importing — 13 Brokers + Column-Mapping Wizard

Built-in parsers (crates/traderview-import/src/brokers.rs):

  • Webull · Lightspeed · IBKR Flex · ThinkOrSwim · TD Ameritrade · Schwab · Fidelity · ETrade · Robinhood · TradeStation · DAS Trader · TradeZero · Tradervue · Generic (column-mapping wizard)

Pipeline per upload:

  1. Raw rows + file hash recorded in imports for audit / re-parse.
  2. Each row maps to an execution and inserts under (account_id, broker_order_id, executed_at, symbol, side, qty, price) — dedupe-safe.
  3. FIFO roll-up re-runs for affected (account_id, symbol) pairs and rewrites trades.

Re-importing the same CSV is idempotent. Unknown brokers go through the CSV Wizard — you point at any CSV, the UI maps columns to execution fields (symbol / side / qty / price / executed_at / fees), and the mapping is saved per-broker per-user. Asset class is auto-detected from symbol patterns (options: SYMyyMMddCNNNN; futures: =F suffix; FX: =X suffix).

Live Data Streams — Polled Upstream, Pushed Downstream

Server-side pollers run on tokio tasks, push to in-process DashMap+broadcast stores, then fan out to browsers over WebSocket. All stores are bounded with oldest-first eviction (halts cap 2,000; catalysts cap 10,000) so multi-day sessions don't grow without limit.

StreamSourceInterval
Haltsnasdaqtrader.com/rss.aspx?feed=tradehalts3s
EDGAR filingssec.gov/cgi-bin/browse-edgar?action=getcurrent&type=4&output=atom6s
PR wiresBusiness Wire / PR Newswire / GlobeNewswire / AccessWire RSS30s each
Finnhub tickswss://ws.finnhub.io (free tier: 25 syms / connection — chunked)realtime
Webull brokertradeapi.webullbroker.com (your pasted tokens; never on disk)5s
Reddit WSBreddit.com/r/wallstreetbets/new.json60s
StockTwitsapi.stocktwits.com/api/2/streams/symbol/{sym}.json60s per symbol
FINRA Reg-SHOcdn.finra.org/equity/regsho/daily/on demand (back-walked by day)
Yahoo quote / fundamentalsquery1.finance.yahoo.com v8/v10cached 60s per symbol in quote_snapshots + 60s in-process world-markets cache
CoinGecko + blockchain.comCrypto markets + BTC chain statson demand

Ticker extraction (catalyst NER) handles $SYM cashtags, parenthetical (SYM) with stop-word filter, and exchange-prefixed forms (NYSE:, NASDAQ:, AMEX:, OTC:). Halt reason codes (T1, T5, LUDP, MWC1/2/3, H10, …) are looked up in a static reason-code table for readable labels.

Live WebSocket Feeds — Full Catalog (15 Endpoints)

Beyond the four foundational push feeds (halts / catalysts / ticks / Webull), the server mounts 15 WebSocket endpoints total under /ws/ in crates/traderview-web/src/routes/. Each pairs a server-side poller / scanner with a browser-side live view tile. The endpoint, its backing route file, and the scanner condition each one streams:

EndpointRoute fileStreams
/ws/haltshalts.rsNasdaq trade-halt RSS, 3s poll, with TTS voice alerts.
/ws/catalystscatalysts.rsSEC EDGAR + 4 PR wires with ticker NER.
/ws/tickslive_ticks.rsFinnhub WebSocket intraday ticks (6-panel scanner).
/ws/webullwebull.rsWebull read-only positions, 5s, in-memory tokens.
/ws/after-hoursafter_hours.rsPRE + POST movers vs RTH close — TTS at ±5%.
/ws/gamma-squeezegamma_squeeze.rsNegative dealer GEX ≥ $250M + spot within 2% of pin strike.
/ws/breadth-divergencebreadth_divergence.rsSPY vs market breadth — bullish or bearish non-confirmation.
/ws/rvol-accelrvol_accel.rsPer-minute volume acceleration — 3 strictly-rising bars + ≥5× baseline.
/ws/insider-streaminsider_stream.rsReal-time SEC Form 4 — parses insider buys/sells from XML, ranks cluster buys.
/ws/uoa-streamuoa_stream.rsLive unusual options activity — rotating poll of top-20 movers.
/ws/squeezesqueeze_scanner.rsCatalyst-driven squeeze detector — WS-fed by SEC + halts + PR; alerts to the second.
/ws/confluenceconfluence_autotrade.rsAuto-submit paper-market buys when a symbol crosses your confluence-score gate.
/ws/catalyst-correlationscatalyst_correlations.rsCatalysts that produced ≥2% move within 60s — sentiment-scored.
/ws/sentiment-velocitysentiment_velocity.rsWSB + StockTwits mention acceleration — ≥3× hour-over-hour + ≥2 consecutive.
/ws/stryke-lspstryke_lsp.rsLanguage-server channel for the in-app stryke custom-indicator / strategy-hook editor.

Algo Trading — End-to-End Strategy Engine

Full algorithmic trading subsystem: 21 strategies, 5 real brokers with native bracket orders, backtester, parameter optimizer, risk circuit breakers, and a live event stream. Built around the Strategy trait in traderview-core so the same code path runs in backtests and live.

Strategy Trait + Registry

Every strategy implements traderview_core::algo_strategies::Strategy:

pub trait Strategy: Send + Sync {
    fn kind(&self) -> StrategyKind;
    fn min_bars(&self) -> usize;
    fn evaluate_entry(&self, bars: &[PriceBar], side_mode: SideMode) -> Option<EntrySignal>;
    fn evaluate_exit(&self, bars: &[PriceBar], side: Side,
                     anchor_high: f64, anchor_low: f64) -> Option<ExitSignal>;
    // Multi-symbol strategies (pairs/stat-arb) override these:
    fn required_symbols(&self) -> Option<Vec<String>> { None }
    fn evaluate_entry_multi(&self, bars_by_symbol: &HashMap<String, Vec<PriceBar>>,
                            side_mode: SideMode) -> Option<EntrySignal> { None }
}

21 shipping strategies, each picked via strategy_type column on algo_strategies:

strategy_typeFamilyEntry condition
momentumTrend followEMA cross + RSI ≥ min + ROC ≥ min + RVOL ≥ min
mean_reversionReversionConnors RSI ≤ oversold + VWAP z-score ≤ −z_min
orbBreakoutOpening Range high break + RVOL ≥ min
donchian_trendTrend followDonchian channel break + ADX ≥ 20
bb_squeezeVolatilityBBW bottom decile + band break
ttm_squeezeVolatilityBB-inside-KC release + momentum histogram expanding
vwap_scalpReversionVWAP z-score ≥ z_entry + 1×ATR stop
supertrendTrend followSupertrend flag flip with ATR-banded stop
heikin_ashi_trendTrend followHeikin-Ashi run of N + EMA confirm
connors_rsi2ReversionRSI(2) ≤ max + price above 200 SMA
order_block_sweepSMCOrder block + liquidity sweep retest
peadFundamentalPost-earnings drift; runner pre-filters by earnings_cal
pairsStat-arbCointegrated spread z-score ≥ z_entry (multi-symbol)
ma_cross_adxTrend followFast/slow EMA cross gated on ADX ≥ adx_min + DI confirm
macd_crossMomentumMACD line crosses its signal line (optional zero-side filter for early reversals)
rsi_divergenceReversionConfirmed RSI swing divergence (price lower-low / RSI higher-low) below oversold
gap_fadeReversionModerate opening gap (~1–4%) reclaims session open → fade to prior close
adx_pullbackTrend followADX ≥ min + DI confirm; pullback touches EMA, close breaks prior bar's high (Raschke "Holy Grail")
nr7_breakoutVolatilityClose breaks the NR7 narrowest-range bar (optional inside-bar combo)
keltner_breakoutVolatilityClose clears EMA ± mult × ATR upper/lower band
ichimoku_cloudConfluenceClose clears cloud + TK cross + Chikou clear + cloud color matches

Broker Adapters — 5 Real REST + WS Fill Pumps

Adapter trait BrokerSink in algo_engine.rs; dispatcher picks the impl from accounts.broker at submit time. Every adapter is wiremock-tested at the contract level (38 broker tests total).

BrokerREST adapterFill pumpNative bracket
Alpacaalpaca_trading.rs — POST /v2/orders, native bracketalpaca_pump.rs trade_updates WS✓ (single envelope)
Tradiertradier_trading.rs — OTOCO complex ordertradier_pump.rs account events streamer (5-min session refresh)✓ (OTOCO)
Schwabschwab_trading.rs — OAuth 2.0 with 401→refresh→retry, TRIGGER+OCO bracketschwab_pump.rs ACCT_ACTIVITY streamer; XML MESSAGE_DATA scanner✓ (TRIGGER+OCO)
IBKRibkr_trading.rs — Client Portal Web API; symbol→conid resolver picks US listingibkr_pump.rs /ws sor+str topics with cOID matcher✓ (parent + 2 children with parentId)
Tastytradetastytrade_trading.rs — REST single-leg; session-token or username/passwordtastytrade_pump.rs streamer.tastyworks.com⚠ entry-only; logs tracing::warn! at submit so user sees the drop

OAuth + cookie-jar handling, refresh-token rotation, auto-retry on 401, broker-specific JSON shape (hyphenated Tastytrade, camel-case Schwab, conid for IBKR) — all isolated inside the adapter; BrokerSink::submit_bracket presents one uniform interface to the engine.

Risk Circuit Breakers

Three opt-in gates in algo_strategies.risk_gates JSON. Each gate auto-trips the kill switch (sets enabled=false, kill_switch=true, appends an audit row) and webhook-fires every enabled Discord/Slack hook the user has configured. Test coverage: engine_trips_on_daily_loss_cap, engine_trips_on_consecutive_losses_cap, engine_refuses_when_position_size_cap_breached.

{
  "max_concurrent_positions": 5,
  "max_daily_loss_usd":       500.0,   // SUM(algo_runs.pnl_realized today) ≤ −cap
  "max_consecutive_losses":   4,       // walk algo_runs newest-first
  "max_position_size_usd":    10000.0  // entry_price × qty cap
}

Backtester + Parameter Optimizer

traderview_core::algo_backtest walks historical bars through the same Strategy trait the live engine uses. Pessimistic intra-bar fill model (SL wins ties when a bar's range covers both stop and TP). Returns trades, equity curve, summary stats (Sharpe, profit factor, max DD, avg R, exit-reason histogram). Covered by 9 unit tests pinning SL/TP/EOD resolution + short-side mirroring.

traderview_core::algo_optimize takes a parameter grid {key: [v1, v2, …]}, expands the Cartesian product (hard cap 1024 combinations), runs the backtester for each combo, ranks by user-chosen metric (Sharpe / TotalReturn / ProfitFactor / AvgR / ReturnMinusDd). Frontend ships curated default grids per strategy_type — sane sweep on every strategy without writing JSON.

Live Engine Flow (per bar boundary)

  1. algo_runner::tick wakes on the 10s clock boundary (covers both sec10 and min1 strategies).
  2. list_active_strategies: enabled=TRUE AND kill_switch=FALSE AND deleted_at IS NULL.
  3. For each strategy: emit Heartbeat event with subscribed-symbol count + next-eval countdown so the frontend stdout pane shows proof-of-life every 10s.
  4. If is_boundary(now, interval) false, continue. Otherwise resolve symbol_universe: watchlist_id ⇒ watchlist symbols; autoscan ⇒ top-N from the 24k US-equity symbols catalog ranked by historical volume.
  5. Side-effect: LiveTickStore::ensure_subscribed(symbols) registers every pick with the Alpaca/Polygon/Finnhub WS so 10s bars start writing to price_bars within seconds.
  6. For each symbol, fetch_recent_bars tries the strategy's interval directly; if empty (typical for newly-subscribed symbols), pulls 6×/30×/90× as many 10s bars and aggregates on the fly via rollup_s10 so the strategy sees its first M1 bar within ~60s.
  7. Risk gates check (daily loss, consec losses, position-size cap). On breach: trip kill switch, fan-out webhooks, abort.
  8. BrokerSink::submit_bracket(intent) on the dispatcher-selected sink. Native bracket on 4/5 brokers ships entry + TP + SL in a single atomic submit.
  9. Fill arrives async via the broker WS pump → algo_engine::record_fillexecutions + trades::rollup_account. Same pipeline every dashboard / R-distribution / equity curve already reads.

Live Event Stream — /api/ws

Engine events fan out through the realtime hub with snake_case type tags. Frontend stdout pane in the algo view subscribes to all six:

EventFires when
algo_heartbeatEvery 10s per active strategy. Payload: universe_size, subscribed_live, bars_processed, signals_emitted, seconds_to_next_eval.
algo_bar_evaluatedStrategy ran evaluate_entry with enough bars but returned None.
algo_tick_skippedRunner short-circuited (no universe, no bars yet, broker-pending, etc.). Reason text is actionable; escalates after 3 min to "live tick worker is stuck — check log".
algo_signal_firedStrategy returned Some(EntrySignal). Order row inserted in pending_submit status before broker call.
algo_order_submittedBroker accepted the order; broker_order_id known.
algo_fill_receivedFill landed in algo_fills + executions.

UI Surfaces — Algo View

  • New strategy modal — picks strategy_type (21 options), broker_mode (internal_sim / paper / live with 30-day paper-lock), bound account, watchlist or autoscan, side_mode, sizing JSON, risk_gates JSON.
  • Stdout pane — multi-pane: one per strategy + global firehose. Renders HB / SKIP / EVAL / SIGNAL / ORDER / FILL lines with throttling so chatty events don't drown the rare important ones.
  • Backtest modal — symbol, interval, days back, equity, fees, slippage. Renders summary stats + last-30 trades color-coded. History panel below auto-refreshes after each run.
  • Optimize modal — grid JSON (pre-populated by strategy_type), metric picker, top-N. Result table has per-row "apply" button that PUTs the winning entry_rules back to the strategy.
  • Metrics modal — runs / bars / signals / orders / fills counters, total realized P&L, SVG sparkline equity curve, recent 25 orders.
  • Kill switch — manual engage/release with reason text; webhook fan-out on every transition.

Resilience & Hardening

  • Stale-lock recovery. Embedded Postgres checks postmaster.pid before start; if the recorded PID is dead, removes the lockfile so a SIGKILL'd parent doesn't permanently block the next launch.
  • Persisted PG password. Random password file (mode 0600) in the data dir — initialized once, reused forever — so auth survives across launches.
  • Backend held across axum::serve. The Embedded handle is owned by the worker thread for the lifetime of the server; explicit drop after serve. Earlier, the handle dropped at function exit and pg_ctl stop killed Postgres mid-request — every subsequent query timed out with "pool timed out".
  • Real concurrency for multi-symbol fan-outs. premarket::snapshot + markets::snapshot + market_data::quotes + compare::compare all use futures_util::future::join_all — previously serial loops blocked /api/premarket/snapshot for 150 seconds and starved the pool.
  • Pool sized for cold-start fan-out. max_connections=32, min_connections=4 (kept warm), acquire_timeout=15s.
  • Per-view race tokens. Frontend dispatch increments a counter on every navigation; views bail post-await if their captured token is stale, preventing null-DOM crashes.
  • Browser-side error sink. window.onerror, unhandledrejection, and overridden console.error all POST to /api/client-errors (queue-capped). The Rust log mirrors every browser failure.
  • WebKit SecurityError guards. Under Tauri's tauri://localhost custom scheme, navigator.sendBeacon, Notification.requestPermission, new Notification, speechSynthesis.speak, and localStorage all throw cross-origin SecurityErrors. Each is try/caught so boot survives.
  • CSP allows ws://127.0.0.1:* so WebSocket connections to the dynamic backend port aren't blocked under custom scheme.

Configuration

VariableModeDefaultPurpose
DATABASE_URLwebrequiredPostgres connection string.
TRADERVIEW_JWT_SECRETwebrequiredHMAC secret for JWT signing. Rotate to invalidate outstanding tokens.
TRADERVIEW_BINDweb0.0.0.0:8080axum listen address.
TRADERVIEW_CORS_ORIGINweb*CORS allowlist.
TRADERVIEW_LOGbothinfotracing-subscriber env-filter directive.
$APP_DATA_DIR/traderview/pg/desktopOS app-data dirEmbedded Postgres cluster location.

The desktop app stores its Postgres cluster under the OS-appropriate app-data directory: ~/Library/Application Support/com.menketechnologies.traderview/pg/ on macOS, ~/.local/share/com.menketechnologies.traderview/pg/ on Linux, %APPDATA%\com.menketechnologies.traderview\pg\ on Windows.

What's Built

AreaItemStatus
FoundationWorkspace + 8 crates + 110 migrationsDone
FoundationFIFO trade roll-up + stats (expectancy, R-multiple, SQN, Sharpe, Sortino)Done
FoundationTauri v2 desktop + embedded Postgres bootstrap, axum web binary w/ argon2 + JWTDone
Import13 broker parsers + Generic column-mapping wizardDone
LiveHalts (Nasdaq RSS, 3s) + Catalysts (EDGAR + 4 PR wires) + Finnhub WS scannerDone
LiveWebull read-only broker integration (paste session tokens)Done
JournalPer-trade + daily + general notes, templates, trade reviews, AI post-mortem cacheDone
Analytics17 reports + R-distribution + Monte Carlo forecast + fill-quality + tax-lot tracker + Schedule D exportDone
Strategystryke-JIT backtest + walk-forward sweeper + custom-indicator AST + strategy alerts (AND/OR/NOT)Done
ResearchOptions chain + Greeks + IV surface + earnings-IV crush + short interest + dark poolDone
CommunityPublic trade shares + forum + mentorship + boardsDone
ExpensesMulti-account expense tracker + receipt OCR + Schedule-C reportDone
UX1425-tile launcher (Cmd-K) + in-app tutorial (?) + 11-shortcut topbarDone
HardeningPer-view race tokens + browser-side error sink + WebKit SecurityError guards + bounded in-memory cachesDone
RoadmapLightspeed live broker (currently CSV-only)Planned
RoadmapCloud sync — encrypted snapshot to S3/R2Future

What This Replaces

ToolCostReplaced by
TraderVue (trade journal)$30/moTrades + Journal + Reports + AI Journal + Trade Reviews
DayTradeDash (Warrior Trading scanner)$187/moLive Scanner + Halts + Catalysts + Pre-market + Scanners (24 presets)
StockInvest.us (signal site)variesTop Signals + Screener + Research (per-symbol dossier)
Zendoo Live Scannersfree w/ TTSLive Scanner with built-in TTS voice alerts
Total saved$2,604/yr (self-hosted, your data stays local)

Built by MenkeTechnologies, part of the MenkeTechnologiesMeta stack alongside strykelang, zshrs, zpwr, and the broader Rust + CLI family.