Custom signal
Tickerbot is the stock market API designed for agents. A custom signal is a named SQL expression on it: define it once, then use it like a built-in, ask for its history, and subscribe to it.
How it works
Chart-platform indicators (Pine Script, ThinkScript) are invisible to everything else you build. A custom signal lives in the API: define it once as a SQL predicate and the name works everywhere the built-in signals do.
1. Define it
A boolean SQL predicate over the 452+ built-in signals, or over other custom signals you own, so signals compose.
curl -X POST "https://api.tickerbot.io/v2/signals" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "oversold_quality",
"expr": "rsi_14 < 30 AND above_sma_200 AND pe_ratio < 20",
"description": "Oversold pullback in a profitable uptrend" }'Show responseHide response
{
"as_of": "2026-08-21T11:01:52Z",
"signal": {
"name": "oversold_quality",
"kind": "custom",
"description": "Oversold pullback in a profitable uptrend",
"expr": "rsi_14 < 30 AND above_sma_200 AND pe_ratio < 20",
…
}
}2. Use it like a built-in
Screen the whole market for it.
curl -X POST "https://api.tickerbot.io/v2/scan" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "q": "oversold_quality AND market_cap > 1e9" }'3. Ask for its history
Custom signals mix into /v2/series; transitions_only returns just the rows where it flipped: its full on/off history, as if it had always existed.
curl "https://api.tickerbot.io/v2/series?tickers=DVA,GTX&columns=close,oversold_quality&interval=1d&from=2024-01-01&transitions_only=true" \
-H "Authorization: Bearer YOUR_KEY"DVA entered on 2026-08-05, before this signal was defined. As-of reads work the same way: define it today, query its value at any past date.
4. Wire it to a push
Because it's a signal, it subscribes like one.
curl -X POST "https://api.tickerbot.io/v2/scan/subscribe" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "q": "oversold_quality AND market_cap > 1e9",
"target_url": "https://your-app.example.com/hook" }'The subscription stores the expanded predicate. The custom name compiles into its SQL at create time.
Show responseHide response
{
"id": "wh_q-s2lOSjLTM",
"q": "(rsi_14 < 30 AND above_sma_200 AND pe_ratio < 20) AND market_cap > 1e9",
"channel": "webhook",
"target_url": "https://your-app.example.com/hook",
"signing_secret": "whsec_…",
"status": "active",
…
}The calls behind it
| Call | What it does here |
|---|---|
POST /v2/signals | Create the signal: name + SQL predicate; composes with other customs |
POST /v2/scan | Screen on it across the whole market, mixed with any built-in |
GET /v2/series?transitions_only=true | Its flip history: every on/off edge on an aligned grid |
POST /v2/scan/subscribe | The signal as a push: fires when a ticker starts matching |