Skip to content

generative-jesse/PolyMatrix

Repository files navigation

PolyMatrix

PolyMatrix is a no-auth, no-mock crypto prediction dashboard focused on real live Polymarket up/down markets and real live Coinbase spot data.

This repo is the source of truth for:

  • what the app does,
  • how the live data is pulled,
  • why certain tradeoffs were made,
  • and how the current sniper-style view logic works.

What this app does

The app tracks live crypto up/down markets for:

  • BTC
  • ETH
  • SOL
  • XRP

Across these Polymarket timeframes:

  • 5 minute
  • 15 minute
  • 1 hour

It gives you:

  • a matrix-first dashboard,
  • a dedicated chart lab view,
  • and a sniper view that ranks current setups using price context + momentum.

There is no auth, no fake data, no simulation, and no database dependency for runtime market data.


Current product views

1. Dashboard

Primary scan view. This is the centerpiece of the product.

Includes:

  • compact header
  • live status pills
  • full up/down market matrix
  • color logic toggle: Classic, Sniper, Mono
  • selected market detail panel
  • live spot chart panel

2. Chart Lab

The chart becomes the hero.

Includes:

  • live Coinbase chart
  • support / resistance context
  • contract start price reference
  • distance-to-support / distance-to-resistance
  • distance-to-flip / distance-to-win context
  • RSI + EMA trend state

3. Sniper View

This is now a column-based tactical view tied directly to the matrix.

Includes:

  • cheapest Up contract in each timeframe column
  • cheapest Down contract in each timeframe column
  • dominant direction emphasis per timeframe column
  • quick click-through into the exact asset/contract that is being highlighted

Architecture

Frontend

  • React
  • Tailwind CSS
  • shadcn/ui primitives
  • Recharts for chart rendering

Backend

  • FastAPI

Data Sources

  • Polymarket Gamma API for market metadata validation
  • Polymarket public crypto pages as fallback discovery hints
  • Polymarket CLOB book endpoint for initial top-of-book seeding
  • Polymarket public market WebSocket for live contract updates
  • Coinbase Advanced Trade public WebSocket for live spot prices
  • Coinbase public candles REST for seeded chart history

Exact logic used to pull Polymarket prices smoothly and accurately

This is the most important section.

The app does not rely on weak snapshot-only fields like the raw Gamma outcomePrices as the main source of truth for live contract prices.

Instead, the pipeline is split into discovery, initial seeding, and live updates.

Step 1 — Discover the live markets we care about

We only care about:

  • BTC / ETH / SOL / XRP
  • 5m / 15m / 1h up-down markets

The backend route /api/markets/updown resolves these contracts using a two-layer strategy.

A. Deterministic slug generation

For 5m and 15m markets, the backend generates candidate slugs from the current UTC bucket:

  • btc-updown-5m-<bucket_timestamp>
  • eth-updown-15m-<bucket_timestamp>
  • etc.

It checks:

  • current bucket
  • previous bucket
  • next bucket

This handles rollover timing and small creation delays.

For 1h markets, the backend generates the current ET hourly slug, for example:

  • bitcoin-up-or-down-march-31-2026-9pm-et
  • ethereum-up-or-down-march-31-2026-9pm-et

It also checks previous and next hour candidates.

B. Public page scrape fallback

If deterministic slug generation alone is not enough, the backend scrapes:

  • https://polymarket.com/crypto/5M
  • https://polymarket.com/crypto/15M
  • https://polymarket.com/crypto/hourly

It extracts matching candidate slugs from the page HTML and uses them as fallback candidates.

C. Gamma validation

Every candidate slug is validated via:

  • GET https://gamma-api.polymarket.com/events/slug/<slug>

The backend only accepts markets that are:

  • active
  • not closed
  • have valid clobTokenIds

That gives us a clean final set of 12 live target markets.


Step 2 — Seed initial prices the right way

This is where the quality difference really matters.

The app does not use Gamma outcomePrices as the primary visible contract price.

Why?

Because for these short-dated crypto up/down markets, raw snapshot fields can look stale, misleading, or glitchy.

Instead, once the live market slugs are resolved, the backend fetches the CLOB order book for each contract token via:

  • GET https://clob.polymarket.com/book?token_id=<token_id>

For each token book:

  • best_bid = max(bids[].price)
  • best_ask = min(asks[].price)

This is important because the raw arrays are not guaranteed to be top-first in the intuitive way. If you just grab the first bid/ask entry, you can get nonsense-looking values like the wrong 1-cent level.

That normalization is the key reason this version behaves much better.

So the initial displayed contract prices are seeded from:

  • top-of-book bid
  • top-of-book ask
  • not from weak display-only snapshot fields

Step 3 — Keep prices live with the Polymarket market WebSocket

After initial seed, the frontend subscribes directly to:

  • wss://ws-subscriptions-clob.polymarket.com/ws/market

Using all current live token IDs.

The app sends:

  • type: "market"
  • assets_ids: [...]
  • custom_feature_enabled: true

And a PING heartbeat every 10 seconds.

The frontend consumes two event types for contract price quality:

A. book

Used as a reliable full-book snapshot.

Again, we normalize it with:

  • best_bid = max(bids)
  • best_ask = min(asks)

B. best_bid_ask

Used whenever Polymarket emits direct top-of-book changes.

This becomes the cleanest live update source when available.


Why this approach feels smooth and accurate

Because the pipeline is:

  1. discover the exact live contracts,
  2. seed real top-of-book from the CLOB,
  3. stream live changes from the Polymarket WebSocket,
  4. avoid relying on glitch-prone display snapshot fields.

That is the core pricing logic.

If you keep only one mental model from this README, keep that one.


Coinbase logic

Live spot

Frontend subscribes to Coinbase Advanced Trade public WebSocket:

  • ticker channel
  • heartbeats channel

For:

  • BTC-USD
  • ETH-USD
  • SOL-USD
  • XRP-USD

Seeded chart history

Backend seeds the chart from Coinbase public candles REST.

This means the chart is useful immediately instead of starting from a blank line.

Why the chart feels more product-native now

The chart is no longer just a side decoration.

It is tied to:

  • the selected asset
  • the selected contract timeframe
  • support / resistance range logic
  • contract start price
  • distance-to-flip context

Support / resistance logic

Current implementation uses recent swing highs/lows from live price history.

Window mapping:

  • 5m market -> use the 15 minute running range
  • 15m market -> use the 1 hour running range
  • 1h market -> use the 4 hour running range

For each selected market:

  • support = min(low) in the mapped range window
  • resistance = max(high) in the mapped range window

These are shown in the chart lab and fed into sniper scoring.


Momentum logic

Current momentum layer uses:

  • RSI
  • EMA(5)
  • EMA(20)

Trend state:

  • bullish if price > EMA5 > EMA20
  • bearish if price < EMA5 < EMA20
  • otherwise neutral

This is intentionally simple and readable for the first sniper pass.

Future candidates:

  • CVD
  • MACD
  • range expansion
  • TradingView-derived custom logic

Sniper logic

The sniper layer is now centered on timeframe columns, not a generic global ranking.

For each timeframe column (5m, 15m, 1h), the app computes:

  1. Cheapest Up contract in that column
  2. Cheapest Down contract in that column
  3. Dominant side for that column using the aggregated momentum/value model

Visual behavior:

  • both cheapest contracts can be surfaced
  • the dominant side gets the stronger solid emphasis
  • the non-dominant cheap side stays outlined / secondary

This makes sniper mode much more actionable for quick scanning because it answers:

  • what is the cheapest Up here?
  • what is the cheapest Down here?
  • which side currently has the stronger momentum/value bias?

The underlying directional bias still uses the momentum/range model:

  • bullish score = bullish setup quality × (1 - up_bid)
  • bearish score = bearish setup quality × (1 - down_bid)

But the UI no longer presents this as a broad generic ranking first. It presents it in a column-native PolyMatrix format.


Chart Lab targets

Chart Lab now plots the selected asset with explicit target-to-beat lines for:

  • 5m market
  • 15m market
  • 1h market

These target prices come from each active contract’s start-price threshold, so you can immediately see:

  • where price currently is,
  • what each timeframe needs to beat,
  • and what the corresponding Up / Down contract prices are right now.

Color logic modes

Classic

Green/red directional read.

Sniper

Highlights the strongest current bullish and bearish opportunities.

Mono

Neutral terminal look with understated emphasis and less visual noise.


Mobile behavior

The app is responsive-first.

Desktop:

  • dense matrix table
  • wider chart layouts

Mobile:

  • matrix collapses into stacked asset cards
  • controls stay reachable
  • views remain tab-based on a single page

The goal is to preserve utility rather than blindly shrinking desktop layouts.


Key tradeoffs

1. No auth, direct public feeds

This keeps the system light and fast, but it also means the app is fully dependent on public endpoint availability.

2. We use seeded snapshots + live websockets, not a persistent backend stream processor

That keeps the architecture simpler now. If part 2 becomes a serious trading engine, a more stateful backend process may be worth adding.

3. Sniper scoring is a ranking aid, not a guaranteed signal engine

It is intentionally interpretable first.

4. Support / resistance is based on recent swing ranges, not a complex institutional indicator stack yet

This makes the first pass easier to reason about and debug.


File map

Backend

  • backend/server.py — API routes
  • backend/market_data.py — Polymarket discovery, CLOB seeding, Coinbase history fetch

Frontend

  • frontend/src/components/dashboard/TerminalDashboard.jsx — page shell + view switching
  • frontend/src/components/dashboard/MarketMatrix.jsx — comparison matrix + color logic modes
  • frontend/src/components/dashboard/SpotChartPanel.jsx — chart lab UI
  • frontend/src/components/dashboard/SniperBoard.jsx — sniper ranking view
  • frontend/src/hooks/useMarketDiscovery.js — fetches normalized live contract list
  • frontend/src/hooks/usePolymarketFeed.js — live Polymarket WS updates
  • frontend/src/hooks/useSpotFeed.js — live Coinbase WS quotes
  • frontend/src/hooks/useSpotAnalytics.js — seeded chart history for all tracked assets
  • frontend/src/lib/dashboard-utils.js — shared formatting + UI helpers
  • frontend/src/lib/market-analytics.js — support/resistance, RSI, EMA, sniper scoring

Next logical steps

  1. Add a more advanced signal engine layer
  2. Introduce CVD / volume-based logic
  3. Add market rollover awareness to smooth transitions even more
  4. Build part 2 bot logic on top of this signal and pricing foundation

Bottom line

The pricing quality of this app comes from:

  • correct market discovery,
  • correct CLOB book normalization,
  • correct real-time websocket handling,
  • and avoiding misleading shortcut fields.

That is the core edge in the current implementation.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors