Docs menu

How a card is made

Every card goes through the same four steps: measure the gap, take the costs off, pass the gates, emit. This page walks through all four with one real-shaped example: NVDA at 14:02:18 ET.

8 min read · Concept · Numbers are illustrative

01Two prices

GAUGE watches two prices for the same name:

  • Cash mid. The Robinhood stock's mid price.
  • Token per share. The Robinhood Chain stock token, priced per share. The token feed is multiplied by the token's multiplier so both prices are in the same unit.
NOTE

The multiplier only touches the chain feed. The cash price is never adjusted.

LegSourceNVDA
Cash midRobinhood quotes$182.40
Token per shareChainlink · token × multiplier$182.71

02The gap, in basis points

GAP

|gap| = | token_per_share − cash_mid | ÷ cash_mid × 10,000

Basis points make every name comparable. A 31¢ gap on a $182 stock and a 53¢ gap on a $118 stock are very different trades, and bps shows it.

NVDA

| 182.71 − 182.40 | ÷ 182.40 × 10,000 = 17.0 bps

The token is trading rich: above the cash price. A negative gap (token cheap) is measured the same way. GAUGE uses the absolute value.

03The haircut

A gap that looks good before costs isn't a gap. GAUGE takes three things off every time:

CostWhat it isNVDA
FeesFrom the fee schedule. Same for every name.−3.5
SlippageEstimated for this name. Thinner books cost more.−2.1
BufferYour safety margin. Set in Settings → Gates.−2.0

NET

net = |gap| − fees − slippage − buffer
17.0 − 3.5 − 2.1 − 2.0 = 9.4 bps

04The four gates

Gates run in order. The first one that fails becomes the reason you see instead of a card.

FEEDSTALEage > 2.0 sSESSIONCLOSEDoutside RTHDEPTHTHINdepth < $100kNET GAPDUSTnet < 2.0 bpsCARD
GatePasses whenNVDA
FeedBoth legs are younger than the max quote age (2.0 s)0.3 s ✓
SessionThe cash market is in regular hours, 09:30–16:00 ETRTH ✓
DepthTop of book is at least $100k$420k ✓
Net gapNet is at least the floor (2.0 bps)9.4 ✓
CapYou have had fewer than 3 cards today1/3 ✓

See Reason codes for what each failure means and what to do about it.

05Emit the card

When every gate passes, GAUGE emits one card and pushes it to you. For NVDA that happened at 14:02:18.412 ET. The card:

  • lives for 75 seconds, then expires on its own;
  • shows the net, both prices and the leg GAUGE would trade (cash equity only);
  • counts toward your cap of 3 whether you take it, skip it or let it expire.

06Re-quote on confirm

The numbers on a card are never traded as-is. When you tap Do it, GAUGE holds the clock, fetches fresh prices for both legs and runs every gate again.

At cardAt confirm
Cash mid$182.40$182.41
Token per share$182.71$182.71
Net9.4 bps8.9 bps · clears

If the re-quote drops net under the floor, the card closes as RE-QUOTE FAIL and nothing is placed. Example from the ledger: META on Thu 25 Sep went from 4.6 at card to 1.4 at confirm.

RULE

The model does not place. In live mode a clear re-quote results in exactly one cash-equity order through the official Robinhood Trading MCP. In paper mode it fills at the confirm mid.

DEVSpecDRAFT

The same math as code. Names, types and field names are drafts until the engine API is published.

gauge-engine / src/gap.rsDRAFT
pub struct Costs { pub fees_bps: f64, pub slip_bps: f64, pub buffer_bps: f64 }

/// |token×mult − cash| / cash × 1e4. The multiplier only touches the chain leg.
pub fn gap_bps(cash_mid: f64, token: f64, mult: f64) -> f64 {
    ((token * mult - cash_mid) / cash_mid).abs() * 1e4
}

pub fn net_bps(gap: f64, c: &Costs) -> f64 {
    gap - c.fees_bps - c.slip_bps - c.buffer_bps
}
event: cardDRAFT
{
  "type": "card",
  "id": "card_7f3a91",
  "sym": "NVDA",
  "cash_mid": 182.40,
  "token_per_share": 182.71,
  "gap_bps": 17.0,
  "costs": { "fees_bps": 3.5, "slip_bps": 2.1, "buffer_bps": 2.0 },
  "net_bps": 9.4,
  "gates": { "feed_age_s": 0.3, "session": "RTH", "depth_usd": 420000, "cap": "1/3" },
  "leg": "cash_equity",
  "emitted_at": "2026-09-26T14:02:18.412-04:00",
  "expires_at": "2026-09-26T14:03:33.412-04:00",
  "mode": "live"
}
esc