mkt

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 1 Imported by: 0

README

mkt

Real-time stock and crypto market dashboard for the terminal — single binary, no API keys.

Crypto prices stream live via Coinbase WebSocket. Stock quotes poll from Yahoo Finance. Watchlist with sparklines, candlestick/line charts with technical indicators, portfolio P&L tracking, macro dashboard, news feed, sector heatmap, and price alerts with desktop notifications. 7 color themes.

Built with Go, Bubbletea v2, and Lipgloss v2.

mkt demo


Installation

go install
go install github.com/stxkxs/mkt@latest
Build from source

Requires Go 1.25+ and Task (brew install go-task or go install github.com/go-task/task/v3/cmd/task@latest).

git clone https://github.com/stxkxs/mkt.git
cd mkt
task build    # or: go build -o mkt .
./mkt

Usage

mkt                             # launch TUI dashboard
mkt watch BTC-USD ETH-USD AAPL  # stream prices to stdout (no TUI)
mkt daemon                      # headless: hub + alerts + notifiers, no TUI
mkt mcp                         # Model Context Protocol server over stdio
mkt backtest rules.yaml replay.ndjson   # replay an alert ruleset against a recorded stream
mkt config show                 # view configuration
mkt config add TSLA LINK-USD    # add symbols to watchlist
mkt config remove DOGE-USD      # remove a symbol
mkt config set poll_interval 30s
mkt config validate             # check config for invalid values
mkt portfolio import --portfolio Tech schwab-export.csv   # import broker CSV
mkt position --equity 100000 --risk 1 --entry 50 --stop 48 # share-sizing calc
mkt version

Global flags (available on every subcommand):

  • --listen 127.0.0.1:9999 — start a read-only HTTP server exposing /quotes, /quotes/{symbol}, /alerts, /metrics, and /webhook/tradingview. Works in dashboard or daemon mode.
  • --listen-token <token> — require Authorization: Bearer <token> (header only; query-string tokens are rejected so secrets don't leak into logs) on every HTTP request. This is mandatory for any non-loopback bind — a loopback bind (127.0.0.1:9999) may omit it, but mkt refuses to start on any other address (including the all-interfaces form :9999 / 0.0.0.0) without a token, since /webhook/tradingview can inject alerts and /alerts leaks configured destinations. The webhook is also rate-limited to guard against notification spam.
  • Record a live quote stream for later backtesting: MKT_RECORD=session.ndjson mkt. Replay it: mkt backtest rules.yaml session.ndjson.

Import supports two CSV formats (auto-detected from the header):

  • genericdate,type,symbol,quantity,price,fee,note where type is buy|sell|dividend
  • schwab — Charles Schwab transaction export (Buy / Sell / Reinvest Dividend)

--dry-run parses and prints a summary without modifying the config; --format overrides auto-detect.

TUI Keybindings
Key Action
19 Jump to tab (Watch, Portfolio, Alerts, Chart, Macro, News, Heatmap, Options, Correl)
tab / shift+tab Cycle tabs
j / k Navigate rows
? Keybinding help for the active tab
enter Detail panel (watchlist) / open link (news) / drill down (heatmap)
s Cycle watchlist sort (config order → change% → volume → price)
c Full-screen chart for selected symbol
i Symbol info (watchlist) / toggle indicator menu on chart (1-9, a, p, v, k to toggle SMA/EMA/Bollinger/RSI/MACD/VWAP/OBV/ATR/Stoch/ADX/Pivots/VolProfile/Patterns)
O Load options chain for selected symbol (switches to Options tab)
: Open command palette (type a tab name, theme <name>, or q)
a Add selected symbol to comparison set
C Open multi-symbol comparison chart
[ / ] Change chart interval (1m → 1w) / switch portfolio
+ / - Zoom chart in/out
m Toggle candlestick / line chart
T Cycle color theme
esc Close panel / chart / go back
q Quit
Watchlist Tab

Live prices with 24h change, volume, and sparkline trend for each symbol. Crypto updates in real-time via WebSocket; stocks poll at a configurable interval (default 15s).

Portfolio Tab

Track holdings with live unrealized P&L across multiple thematic portfolios. Switch portfolios with [ / ]. Configure positions in ~/.config/mkt/config.yaml.

Alerts Tab

Set price alerts that fire desktop notifications:

alerts:
  - symbol: BTC-USD
    condition: above    # above, below, pct_up, pct_down, volume_above, stddev_above
    value: 100000
    enabled: true

volume_above triggers when the quote's reported volume exceeds the value. stddev_above triggers when the rolling standard deviation over period quotes exceeds value percent of the rolling mean — a volatility expansion proxy when full OHLC isn't available.

Alerts have a 5-minute cooldown to prevent spam. Toggle and delete alerts from the TUI.

Compound rules combine multiple conditions with match: all, match: any, or match: sequence (in declared order):

alerts:
  - symbol: BTC-USD
    enabled: true
    match: all                       # every sub-condition must fire
    conditions:
      - condition: above
        value: 100000
      - condition: rsi_above
        value: 70

  - symbol: ETH-USD
    enabled: true
    match: sequence                  # first crossed up, then dropped
    conditions:
      - condition: above
        value: 3500
      - condition: below
        value: 3300

Alerts can also POST a JSON payload to a webhook on every trigger — useful for Slack/Discord/IFTTT or any custom receiver. Set a default URL at the top level and/or override per rule:

webhook_url: https://hooks.slack.com/services/...   # default destination (optional)

alerts:
  - symbol: BTC-USD
    condition: above
    value: 100000
    enabled: true
    webhooks:                                       # per-rule override (optional)
      - https://discord.com/api/webhooks/...

The payload is {symbol, condition, value, price, message, timestamp}.

For mobile push, configure ntfy.sh (no signup) and/or Pushover (free dev account):

ntfy_topic: mkt-alerts-<your-unique-string>   # subscribe in the ntfy app
# ntfy_server: https://ntfy.sh                # optional override

pushover_user: u-...                          # your Pushover user key
pushover_token: a-...                         # your Pushover application token
Charts

Press c on any symbol for a full-screen candlestick or line chart. Press i to overlay technical indicators:

  • SMA(20) / EMA(20) — moving average lines on the price axis
  • Bollinger Bands — upper/middle/lower bands on the price axis
  • VWAP — anchored volume-weighted average price overlay on the price axis
  • RSI(14) — relative strength index in a sub-panel (0–100, ref lines at 30/70)
  • MACD(12,26,9) — MACD line, signal line, and histogram in a sub-panel
  • OBV — on-balance volume in a sub-panel (running signed-volume total)
  • ATR(14) — Wilder-smoothed Average True Range in a sub-panel
  • Stochastic(14,3) — %K and %D oscillator in a sub-panel (ref lines at 20/80)
  • ADX(14) — trend strength with +DI/-DI in a sub-panel (ref line at 25)
  • Pivots — classic floor-trader pivot lines (P, R1-R3, S1-S3) overlaid on the main chart from the prior session's HLC
  • Volume Profile — horizontal volume histogram in a right-side gutter; point-of-control row highlighted
  • Candle Patterns — Doji, Hammer, Shooting Star, Bullish/Bearish Engulfing marked with glyphs on the candlestick chart

Multiple indicators can be active simultaneously.

Comparison Chart

From the watchlist, press a on up to 3 symbols to add them to a comparison set, then C to open. Prices are normalized to % change from the first visible candle. Each symbol gets a distinct color.

Macro Dashboard

Fixed set of macro indicators updated on the same poll interval: 10Y Treasury, 13W T-Bill, VIX, Dollar (DXY), Gold, WTI Crude, S&P 500, and Bitcoin. Includes a computed 2s10s yield spread.

News Feed

Aggregated RSS headlines from Yahoo Finance, MarketWatch, and CNBC. Polls every 3 minutes. Press enter to open a headline in your browser.

Optionally, add SEC EDGAR per-ticker filings into the same feed via edgar_tickers in config:

edgar_tickers: [AAPL, NVDA, TSLA]

Filings appear with source SEC:<TICKER> and a category (8-K, 10-Q, etc.). Press f in the News tab to cycle the filter: All / News / Filings.

Sector Heatmap

Treemap overview of 18 sectors colored by average daily change (red → green gradient). Press enter to drill down into a sector and see individual stock tiles sorted by performance with price, change%, volume, and colored bars. Press esc to return to the overview.

Themes

Press T to cycle through 7 color themes: Tokyonight (default), Catppuccin Mocha, Gruvbox Dark, Nord, Dracula, Solarized Dark, and Catppuccin Latte (light). Theme choice persists in config.


Configuration

Config lives at ~/.config/mkt/config.yaml and is created with defaults on first run.

watchlist:
  - BTC-USD
  - ETH-USD
  - SOL-USD
  - AAPL
  - NVDA
portfolios: []
alerts: []
poll_interval: 15s
sparkline_len: 60
theme: tokyonight

Data Sources

Source Protocol Data Auth
Coinbase Advanced Trade WebSocket Real-time crypto prices, level-2 order book None
Coinbase Exchange REST Historical crypto candles, REST order-book snapshot None
Yahoo Finance REST (polling) Stock quotes, history, macro indicators, options chains, earnings calendar None (session cookies)
FRED (St. Louis Fed) REST (CSV) Economic series (DFF, T10Y2Y, UNRATE, CPIAUCSL, …) via FRED: prefix None
DeFiLlama REST Per-chain TVL None
Binance Futures REST Funding rate + open interest (BTC/ETH/SOL perps) None
Yahoo Finance / MarketWatch / CNBC RSS News headlines None
SEC EDGAR Atom (RSS) Per-ticker filings (8-K, 10-Q, 10-K) None

No API keys required. Crypto streams from Coinbase (US-native, no geo-restrictions). Stock data polls from Yahoo Finance.


Integrations

mkt is both a TUI and a headless data source, so it drops into the terminal ecosystem two ways: hosts run its TUI, and consumers read its data over MCP, HTTP, or a Prometheus scrape. Almost everything below is config-only — no rebuild.

Serve over SSH (mkt serve)

Run the dashboard as a Charm Wish SSH app: every connection gets its own live, per-session dashboard driven by one shared data plane. Access is gated by a public-key allowlistmkt serve refuses to start with an empty allowlist rather than expose your holdings.

# ~/.config/mkt/config.yaml
serve:
  addr: "0.0.0.0:2222"                   # 127.0.0.1:2222 for local-only (the default)
  host_key: ~/.config/mkt/ssh_host_key   # ed25519 key, auto-generated on first run
  authorized_keys:
    - ssh-ed25519 AAAA...you@laptop
    - ssh-ed25519 AAAA...you@phone       # or: authorized_keys_file: ~/.ssh/authorized_keys
mkt serve                 # start the SSH server
ssh -p 2222 your.host     # from any allowed key → a live dashboard

Every tab streams live; the crypto detail order-book falls back to REST snapshots in serve mode (the live level-2 stream is single-program by design).

AI agents (mkt mcp)

mkt mcp is a stdio Model Context Protocol server exposing quotes, query_history (OHLCV), and alerts as structured JSON — any MCP host can query live market data mid-task.

# Claude Code
claude mcp add --transport stdio mkt -- mkt mcp
// Crush (charm-native), Claude Desktop, Cursor, Zed, Goose, Cline, Continue …
{ "mcp": { "mkt": { "type": "stdio", "command": "mkt", "args": ["mcp"] } } }
HTTP data surface (--listen)

--listen exposes a read-only HTTP API (any non-loopback bind requires --listen-token). /quotes carries price, change, and a pre-computed direction; /metrics emits per-symbol gauges in Prometheus text format.

mkt --listen 127.0.0.1:9999
curl -s 127.0.0.1:9999/quotes/BTC-USD
# {"symbol":"BTC-USD","price":64210.5,"change":1342.1,"change_pct":2.14,"dir":"up"}
# /metrics
mkt_price{symbol="BTC-USD"} 64210.5
mkt_change_pct{symbol="BTC-USD"} 2.14
mkt_symbols_cached 12
mkt_uptime_seconds 3841.0

Prometheus / Grafana / Netdata — point a scrape at it:

scrape_configs:
  - job_name: mkt
    static_configs:
      - targets: ['127.0.0.1:9999']
    # non-loopback bind → set --listen-token and uncomment:
    # authorization: { credentials: "<token>" }
Terminal multiplexer (tmux)

Host the TUI in a popup, and put a live ticker in the status bar off /quotes:

# ~/.tmux.conf — floating dashboard on prefix + g
bind-key g display-popup -E -w 90% -h 90% 'mkt'

# ticker in status-right (start `mkt --listen 127.0.0.1:9999` first)
set -g status-interval 5
set -g status-right '#(curl -s 127.0.0.1:9999/quotes/BTC-USD | jq -r "\(.dir=="up" ? "▲" : "▼") \(.price)")'

For a busy status line, curl in a small cached wrapper script rather than inline — tmux re-runs #() on every interval.

Prompt ticker (Starship)

A single-symbol glance on every prompt (needs mkt --listen running):

# ~/.config/starship.toml
command_timeout = 1000

[custom.mkt]
command = '''curl -s 127.0.0.1:9999/quotes/BTC-USD | jq -r '"\(.symbol) \(.price) (\(.change_pct)%)"' '''
when = true
format = '[$output]($style) '
style = 'bold yellow'
Demo GIF (VHS)

demo/mkt.tape drives the binary through its tabs, theme toggle, and help overlay. Regenerate with:

task demo          # builds ./mkt, then renders demo/mkt.gif via vhs

Hardening

mkt's sharp surfaces are off by default — the HTTP API (--listen), the SSH dashboard (mkt serve), the MCP server (mkt mcp), and the webhook/ntfy/Pushover notifiers all require explicit opt-in. When you do enable them, these knobs scope them down:

To disable / restrict Do this
Desktop popups + bell --no-desktop-notify (already off under mkt serve) or desktop_notify: false
All notifiers (keep rules + history) --no-notify or notifications: false
Inbound TradingView webhook off by default; needs --enable-webhook and --listen-token (even on loopback)
/alerts webhook-URL leak redacted automatically — the API returns has_webhooks, never the URLs
Token on a loopback bind --require-token (loopback is not a trust boundary on shared hosts)
MCP config exposure mkt://config is off unless --expose-config, and secrets are always redacted
MCP holdings exposure get_portfolio + mkt://portfolios are off unless --expose-portfolio
Egress to a provider providers: { binance: false, defillama: false, news: false, macro: false }
SEC EDGAR egress edgar_tickers: []
Swap/drop news feeds news_feeds: [{name: ..., url: ...}] (built-ins use https)

Notifiers are additionally capped at ~20/min each, so a webhook flood can't drain a paid Pushover quota. Secrets at rest (config.yaml) are written 0600.

Egress allowlist (hosts mkt may contact; notifier/build hosts only apply when configured):

advanced-trade-ws.coinbase.com  api.exchange.coinbase.com
query1.finance.yahoo.com  query2.finance.yahoo.com  finance.yahoo.com
fapi.binance.com  api.llama.fi  feeds.marketwatch.com  search.cnbc.com
www.sec.gov  fred.stlouisfed.org  api.stlouisfed.org
ntfy.sh  api.pushover.net                       # notifiers, only if configured

Architecture

Quote providers (Coinbase WS, Yahoo HTTP, recording/replay)
        │
        ▼
   chan Quote (cap 128)
        │
        ▼
       Hub ─────► cache.Push()  (ring buffer per symbol)
        │  ─────► alertEngine.Check() ──► Notifiers (desktop, webhook, ntfy, Pushover, history)
        │                              ──► /metrics, /alerts on --listen
        ▼
  dispatchCh (cap 256, drops on TUI stall)
        │
        ▼
  program.Send(QuoteUpdateMsg)
        │
        ▼
  bubbletea Update() ──► route to tab views

Background pollers (each its own goroutine):
  Yahoo macro / earnings ──► MacroUpdateMsg, CalendarUpdateMsg
  Binance futures        ──► FuturesUpdateMsg
  DeFiLlama TVL          ──► TVLUpdateMsg
  RSS + SEC EDGAR        ──► NewsUpdateMsg
  Portfolio equity mark  ──► EquitySnapshotMsg

External integrations:
  --listen 127.0.0.1:9999 → /quotes (price+change+dir), /alerts, /metrics (per-symbol gauges), /webhook/tradingview
  mkt mcp (stdio)         → MCP tools/resources/prompts for Claude clients
  mkt serve               → Wish SSH server; one program per session, shared data plane (broadcaster)
  MKT_RECORD=path         → tee provider quotes to NDJSON (replay-able via mkt backtest)

The data plane is program-agnostic: a broadcaster fans every quote/update out to all attached tea.Programs, so mkt (one local program) and mkt serve (one per SSH session) share the exact same hub, cache, alert engine, and pollers — built once in cmd/backend.go.

  • Providers stream/poll quotes into a shared channel; Hub fans out behind a bounded dispatcher with drop-on-back-pressure semantics
  • Alert engine evaluates rules inline on each quote; notifiers run outside the lock with per-call timeouts and error isolation
  • Indicator package provides pure-math SMA, EMA, RSI, MACD, Bollinger, VWAP, OBV, ATR, Stochastic, ADX, Pivots, VolumeProfile, Patterns calculations
  • Portfolio package is stateless math: transactions → holdings, realized P&L (FIFO/LIFO/HIFO/Average), dividends, risk metrics (Sharpe, Sortino, Beta, MaxDD), correlation matrix, position sizing
  • Bubbletea serializes all UI updates — no mutexes in the TUI layer
  • Webhook receiver (/webhook/tradingview) injects TradingView alerts through the same notifier fan-out, bypassing rule evaluation
Project Layout
mkt/
├── main.go                        # cmd.Execute()
├── cmd/
│   ├── root.go                    # cobra root, --listen, --listen-token, version
│   ├── backend.go                 # shared data plane (setup + buildApp + startDataPlane) for dashboard & serve
│   ├── dashboard.go               # default cmd — one local program attached to the backend
│   ├── serve.go                   # mkt serve — Wish SSH; one program per session, key allowlist
│   ├── daemon.go                  # mkt daemon — headless hub + alerts + notifiers
│   ├── watch.go                   # mkt watch — non-TUI price streaming
│   ├── config.go                  # mkt config show/set/add/remove/validate
│   ├── portfolio.go               # mkt portfolio import (CSV)
│   ├── position.go                # mkt position — share-sizing calc
│   ├── backtest.go                # mkt backtest — replay rules against an NDJSON stream
│   └── mcp.go                     # mkt mcp — Model Context Protocol server over stdio
└── internal/
    ├── config/                    # viper load/save ~/.config/mkt/config.yaml
    ├── provider/
    │   ├── provider.go            # QuoteProvider, HistoryProvider interfaces
    │   ├── types.go               # Quote, OHLCV, Interval
    │   ├── coinbase/              # WebSocket streaming + REST history + L2 order book
    │   ├── yahoo/                 # HTTP polling + chart history + macro + options + earnings
    │   ├── fred/                  # FRED economic series via CSV endpoint
    │   ├── defillama/             # per-chain TVL
    │   ├── binance/               # futures funding rate + open interest
    │   ├── calendar/              # curated economic calendar + EarningsSource interface
    │   └── recording/             # NDJSON tee decorator + replay provider
    ├── market/
    │   ├── hub.go                 # aggregates providers, fan-out via callback, drop-on-stall
    │   ├── cache.go               # ring buffer per symbol + last full quote (price, change, dir)
    │   └── history.go             # multi-provider history routing
    ├── broadcast/                 # fan bubbletea messages out to N attached programs (dashboard + serve sessions)
    ├── alert/                     # rule engine, conditions, cooldown, notifier fan-out (desktop/webhook/ntfy/Pushover/history)
    ├── portfolio/                 # stateless math: P&L, tax lots, dividends, equity curve, risk, correlation, sizing
    ├── indicator/                 # SMA, EMA, RSI, MACD, Bollinger, VWAP, OBV, ATR, Stoch, ADX, Pivots, VolProfile, Patterns
    ├── importer/                  # broker CSV formats (generic, Schwab) with header auto-detect
    ├── news/                      # RSS + SEC EDGAR feed parsing, browser URL opener
    ├── api/                       # --listen HTTP server (/quotes, /alerts, /metrics, /webhook/tradingview)
    ├── mcp/                       # JSON-RPC over stdio: tools, resources, prompts
    └── tui/
        ├── app.go                 # root model: tab switching, message routing, full-screen overlays
        ├── keys.go                # keybindings, tab types
        ├── messages.go            # TUI message types
        ├── theme/                 # color palette, 7 theme presets, panel renderer
        ├── watchlist/             # price table with sparklines
        ├── detail/                # expanded symbol info panel with live order book
        ├── chart/                 # candlestick/line charts, indicators, comparison, hover crosshair
        ├── portfolio/             # holdings table with live P&L, realized, dividends, equity sparkline
        ├── alerts/                # alert rule management
        ├── macro/                 # macro indicators, futures, TVL, upcoming events
        ├── news/                  # RSS news feed with EDGAR filings filter
        ├── heatmap/               # sector treemap with click-to-drill
        ├── options/               # options chain grid with max-pain
        ├── correlation/           # rolling-window correlation matrix
        ├── palette/               # command palette (jump-to-tab, theme switch)
        ├── alertdialog/           # modal for creating alerts from a symbol
        ├── symbolinfo/            # modal symbol info overlay
        ├── statusbar/             # connection status, theme name, help
        └── format/                # price/volume formatting utilities

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
api
Package api exposes a small read-only HTTP surface for scripting and monitoring: /quotes, /quotes/{symbol}, /alerts, /metrics.
Package api exposes a small read-only HTTP surface for scripting and monitoring: /quotes, /quotes/{symbol}, /alerts, /metrics.
broadcast
Package broadcast fans out bubbletea messages to a dynamic set of running programs.
Package broadcast fans out bubbletea messages to a dynamic set of running programs.
httpx
Package httpx centralizes the GET → check-status → read-capped-body → decode pattern that every HTTP provider (yahoo, coinbase REST, binance, defillama, news) was hand-rolling.
Package httpx centralizes the GET → check-status → read-capped-body → decode pattern that every HTTP provider (yahoo, coinbase REST, binance, defillama, news) was hand-rolling.
importer
Package importer parses broker-export CSV files into portfolio transactions.
Package importer parses broker-export CSV files into portfolio transactions.
mcp
Package mcp implements a Model Context Protocol server over stdio.
Package mcp implements a Model Context Protocol server over stdio.
observe
Package observe is a tiny, dependency-free metrics registry used to expose provider health on the /metrics endpoint.
Package observe is a tiny, dependency-free metrics registry used to expose provider health on the /metrics endpoint.
provider/binance
Package binance fetches public Binance futures data (funding rate and open interest).
Package binance fetches public Binance futures data (funding rate and open interest).
provider/calendar
Package calendar provides economic-release and earnings calendar data types and a curated 2026 schedule for the major US macro events.
Package calendar provides economic-release and earnings calendar data types and a curated 2026 schedule for the major US macro events.
provider/defillama
Package defillama fetches DeFi TVL data from DeFiLlama's public API.
Package defillama fetches DeFi TVL data from DeFiLlama's public API.
provider/fred
Package fred implements a HistoryProvider for FRED (St.
Package fred implements a HistoryProvider for FRED (St.
provider/recording
Package recording captures live quote streams to NDJSON and replays them as a QuoteProvider.
Package recording captures live quote streams to NDJSON and replays them as a QuoteProvider.
symbol
Package symbol is the single source of truth for classifying a market symbol as crypto, a FRED economic series, or a stock.
Package symbol is the single source of truth for classifying a market symbol as crypto, a FRED economic series, or a stock.
tui
tui/correlation
Package correlation renders a Pearson correlation matrix between the watchlist symbols using each symbol's recent prices from the market cache.
Package correlation renders a Pearson correlation matrix between the watchlist symbols using each symbol's recent prices from the market cache.
tui/help
Package help renders a centered keybinding-reference overlay.
Package help renders a centered keybinding-reference overlay.
tui/options
Package options renders the Yahoo options chain (calls + puts) for a chosen symbol as a strike-aligned grid with a max-pain header.
Package options renders the Yahoo options chain (calls + puts) for a chosen symbol as a strike-aligned grid with a max-pain header.
tui/palette
Package palette is a tiny command prompt for jump-to-tab, theme switching, and quit.
Package palette is a tiny command prompt for jump-to-tab, theme switching, and quit.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL