How it works
Architecture
Ingest, normalise, evaluate, dispatch. One architectural decision does most of the work: cashcat.bot does not calculate the primary TA signal.
cashcat.bot does not calculate the primary TA signal in V0.1. TradingView does. cashcat.bot ingests, stores, combines, explains and distributes it.
That single decision is what makes a days-not-weeks launch realistic. Building a charting engine and a proprietary indicator is months of work with a long tail of edge cases; receiving a webhook, storing it idempotently and presenting it well is a weekend. The value the product adds is not the calculation — it is combining five timeframes into one honest number, explaining what the perp market is doing around it, and never overstating what any of it means.
The pipeline — ingest → normalise → evaluate → dispatch
-
1 Ingest
A TradingView alert fires and POSTs JSON to an unguessable webhook path. The endpoint authenticates the token in the path, validates the payload against the schema, deduplicates on
event_idvia a UNIQUE constraint, inserts the raw payload — preserved forever, exactly as received — and returns HTTP 200. Target: under 500 ms. TradingView cancels anything that takes longer than three seconds, so nothing slow may run before the acknowledgement. -
2 Normalise
Market data arrives on a separate path. A market-data worker polls the spot provider and writes normalised snapshots; venue adapters poll each perp venue and map three different responses onto one internal shape. Several providers, one data model. The frontend never calls a provider directly, which buys central rate limiting, server-side validation, a single cache, and the ability to replace a provider without shipping frontend code.
-
3 Evaluate
After the webhook is acknowledged, and never before it, asynchronous work updates the timeframe state for that asset, strategy and timeframe, recomputes the weighted aggregate across all five timeframes, calculates metadata such as signal age, and decides whether an alert should be emitted. Because evaluation is downstream of the acknowledgement, a slow recompute can never cost you an alert.
-
4 Dispatch
State lands in Postgres, hot reads are served from a Redis cache, and the cashcat.bot API serves the UI. Failure of any single provider degrades the affected block and nothing else: the rule throughout is to show the gap rather than fabricate a number to fill it.
The webhook contract — cc webhook
POST /api/v1/webhooks/tradingview/{secret}
Content-Type: application/json
{
"schema_version": "1.0",
"event_id": "{{ticker}}-{{interval}}-{{time}}-BUY",
"source": "tradingview",
"strategy": "cashcat-main",
"indicator_version": "v1.0.0",
"symbol": "{{ticker}}",
"exchange": "{{exchange}}",
"timeframe": "{{interval}}",
"signal": "BUY",
"signal_strength": 1,
"price": "{{close}}",
"bar_time": "{{time}}",
"trend": "BULLISH",
"momentum": "STRONG",
"rsi": 61.4,
"ema_fast": 0.1281,
"ema_slow": 0.1243,
"volume_state": "EXPANDING",
"reason": "trend_confirmed"
}
Required: schema_version, event_id,
strategy, indicator_version, symbol,
timeframe, signal, price, bar_time.
Everything else is optional and stored when present.
Seven security layers
- A long random token in the webhook path, never exposed in frontend JavaScript.
- An optional TradingView IP allowlist in front of the endpoint.
- Payload validation against the schema before anything is written.
- Rate limiting on the endpoint.
- Deduplication on
UNIQUE(event_id), so retries are idempotent. - Every rejected request logged and counted: received, rejected, duplicate.
- No exchange keys, wallet keys or passwords ever appear in an alert body.
Responses
200accepted200duplicate (idempotent replay)400invalid payload401unauthorized429rate limited
Data sources — what is real on this site, and what is not
| Source | Supplies | On this site | Notes |
|---|---|---|---|
| GeckoTerminal | OHLCV candles per timeframe | LIVE | Public, keyless, CORS-open. Rate-limited by IP on the free tier; on 429 the chart falls back to the seeded generator and relabels itself. |
| Dexscreener | Spot price, liquidity, 24h volume, market cap, FDV, txn counts | LIVE | Same pool, same chain. Cached in memory for 60 seconds so repeated commands do not re-hit the API. |
| TradingView | The primary TA signal per timeframe | SIMULATED | Arrives by webhook in production. There is no public read API for the indicator state, so the terminal demonstrates it with deterministic demo data. |
| Perp venue adapters | Mark, index, basis, open interest, funding | LIVE | Hyperliquid, Lighter and Aster all list a CASHCAT perpetual and all three serve the browser directly. Open interest is summed; funding and basis come from Hyperliquid, which carries most of the open interest and is the only one publishing funding history. Each venue reports its own state, so a failure shows as UNREACHABLE rather than shrinking the aggregate silently. MEXC lists the pair but sends no CORS header and is excluded. |
| Perp liquidations | Long/short liquidation split over 24h | SIMULATED | No venue listing CASHCAT exposes a public aggregate liquidation feed: Hyperliquid has no liquidations endpoint and Aster’s force-order history requires an authenticated key. Shown as a shape preview and labelled in place. |
| CATSCAN | Contract risk heuristics | SIMULATED | A P3 roadmap capability, previewed in the terminal and labelled [PREVIEW — NOT IN V1.0]. |
Pool 0xA70fc67C9F69da90B63a0e4C05D229954574E313 · Uniswap v3 ·
Robinhood Chain · token 0x020bfC650A365f8BB26819deAAbF3E21291018b4.