Signal arrays · 47 documented conditions

Every condition that fired, and what it was worth.

GET /v1/summary evaluates 47 fixed conditions over 26 cached indicator series and returns them as three arrays of readable sentences, four category directions and two signed scores. Nothing is hidden behind the verdict — the whole derivation comes back with it.

47 conditions 7 timeframes 5× request weight
tickatlas.com / v1 / summary 200 OK
GET /v1/summary?symbol=EURUSD&timeframe=H1
EUR/USD · H1 · bias
bullish
normal
bullish_signals4
bearish_signals1
neutral_signals1
confidence0.55
signals.trendbullish
signals.momentumneutral
trend_score+3.0
momentum_score−0.5
{
  "success": true,
  "data": {
    "symbol": "EURUSD", "timeframe": "H1",
    "bias": "bullish", "bias_strength": "normal",
    "confidence": 0.55,
    "trend_score": 3.0, "momentum_score": -0.5,
    "signals": { "trend": "bullish", "momentum": "neutral",
                 "volatility": "normal", "volume": "bullish" },
    "bullish_signals": [
      "Price above 200 SMA (long-term uptrend)",
      "20 SMA above 50 SMA (short-term bullish)",
      "MACD histogram positive (0.00012)",
      "MFI bullish (61.3)"
    ],
    "bearish_signals": [ "RSI bearish at 38.7" ],
    "neutral_signals": [ "ADX 21.4 (weak/ranging market)" ],
    "volatility_info": [ … ], "recommendations": [ … ],
    "updated_at": 1774620183
  }
}
47Documented conditions
30That move the score
26Series read per call
5×Request weight
Definitions first

A signal is a condition that was measured. Not an instruction.

Every entry in these arrays is the endpoint describing a state it just tested against a fixed numeric boundary. Knowing exactly which boundaries exist is what makes the output usable — and knowing which ones do not exist is what stops you building on air.

IT DOES

Evaluate a fixed list, and show its working

Reads 26 cached series, tests 47 conditions with constant weights, appends a sentence per condition that fired, keeps two signed running totals and maps their sum onto a bias with a confidence value.

  • Three arrays: bullish, bearish, neutral
  • Four category directions in signals
  • Every sentence carries its triggering number
IT DOES NOT

Detect patterns, or adapt to the regime

There is no divergence detection, no breakout or exhaustion pattern, no cross-timeframe alignment, no volume confirmation of a price event, and no weighting that changes with market conditions. Nothing is back-tested and nothing is calibrated against outcomes.

  • No standalone signals route exists
  • No entry or exit levels anywhere in the payload
  • confidence is arithmetic, not probability

Array length is not score. 17 of the 47 conditions write a signal string and add exactly zero: all six Bollinger branches, all three ATR branches, the Parabolic SAR pair, the Williams %R pair, the ranging-ADX note, the mid-band RSI note, an MFI at exactly 50, and the OBV line. A symbol can carry six bullish sentences worth a combined +1.5 while another carries two worth +3. Read trend_score and momentum_score when you need the magnitude.

Complete catalogue

All 47 conditions, with their exact weights.

Four analysers, one table each, every branch listed. This is the whole inventory rather than a sample of it: if a condition is not below, the endpoint does not test it. Weights are the literal constants the code adds, and the two analysers marked as not reaching the bias are exactly that — their output is real, it simply never enters the sum.

_analyze_trend 17 branches · scores into the bias

Trend

Moving-average structure, MACD state, directional dominance and Parabolic SAR position. This analyser owns the single heaviest condition in the endpoint: price against the 200 SMA, worth twice anything else.

Series read Condition Appends to Score
SMA_200 bid above SMA_200 bullish_signals +2
SMA_200 bid at or below SMA_200 bearish_signals -2
SMA_50 · SMA_200 SMA_50 above SMA_200 (golden-cross territory) bullish_signals +1
SMA_50 · SMA_200 SMA_50 at or below SMA_200 (death-cross territory) bearish_signals -1
SMA_20 · SMA_50 SMA_20 above SMA_50 bullish_signals +1
SMA_20 · SMA_50 SMA_20 at or below SMA_50 bearish_signals -1
EMA_20 · EMA_50 bid above EMA_20 above EMA_50 (fully aligned) bullish_signals +1
EMA_20 · EMA_50 bid below EMA_20 below EMA_50 (fully aligned) bearish_signals -1
MACD_hist · MACD_main · MACD_signal histogram positive and main above signal bullish_signals +1
MACD_hist histogram positive, main not above signal bullish_signals +0.5
MACD_hist · MACD_main · MACD_signal histogram negative and main below signal bearish_signals -1
MACD_hist histogram negative, main not below signal bearish_signals -0.5
ADX · ADX_plusDI · ADX_minusDI ADX above 25 with +DI dominant (labelled strong above 40) bullish_signals +1
ADX · ADX_plusDI · ADX_minusDI ADX above 25 with −DI dominant (labelled strong above 40) bearish_signals -1
ADX ADX at or below 25 — ranging neutral_signals 0
SAR bid above Parabolic SAR bullish_signals 0
SAR bid at or below Parabolic SAR bearish_signals 0
_analyze_momentum 15 branches · scores into the bias

Momentum

Five oscillators against fixed numeric boundaries. Note the symmetry that trips people up: an extreme reading is scored as a REVERSAL, so RSI above 70 is bearish and RSI below 30 is bullish.

Series read Condition Appends to Score
RSI_14 above 70 bearish_signals -1
RSI_14 above 60, at or below 70 bullish_signals +0.5
RSI_14 at or above 40, at or below 60 neutral_signals 0
RSI_14 at or above 30, below 40 bearish_signals -0.5
RSI_14 below 30 bullish_signals +1
Stochastic_K · Stochastic_D %K above 80 and %K below %D bearish_signals -1
Stochastic_K %K above 80, %K not below %D bearish_signals -0.5
Stochastic_K · Stochastic_D %K below 20 and %K above %D bullish_signals +1
Stochastic_K %K below 20, %K not above %D bullish_signals +0.5
CCI_14 above 100 bearish_signals -0.5
CCI_14 below −100 bullish_signals +0.5
WilliamsR_14 above −20 bearish_signals 0
WilliamsR_14 below −80 bullish_signals 0
Momentum_14 above 100 bullish_signals +0.5
Momentum_14 below 100 bearish_signals -0.5
_analyze_volatility 9 branches · does not reach the bias

Volatility

Band position and range expansion. Every condition here scores exactly zero: it writes a signal string and nothing else, so it can never change the bias no matter how many of them fire.

Series read Condition Appends to Score
BB_upper bid above the upper band bearish_signals 0
BB_lower bid below the lower band bullish_signals 0
BB_middle bid inside the bands, above the middle bullish_signals 0
BB_middle bid inside the bands, at or below the middle bearish_signals 0
BB_width below 0.01 — bands contracted info_signals 0
BB_width above 0.03 — bands expanded info_signals 0
ATR_7 · ATR_14 ATR_7 above 1.2 × ATR_14 — range expanding info_signals 0
ATR_7 · ATR_14 ATR_7 below 0.8 × ATR_14 — range contracting info_signals 0
ATR_7 · ATR_14 between those bounds — range stable info_signals 0
_analyze_volume 6 branches · does not reach the bias

Volume

Money-flow classification. These conditions DO score — and the score sets signals.volume — but the volume total is not added to the bias arithmetic, so a ±2 here moves a category light and nothing else.

Series read Condition Appends to Score
MFI_14 above 80 bearish_signals -2
MFI_14 above 50, at or below 80 bullish_signals +1
MFI_14 exactly 50 neutral_signals 0
MFI_14 at or above 20, below 50 bearish_signals -1
MFI_14 below 20 bullish_signals +2
OBV present — reported as text only, never classified info_signals 0
From score to verdict

Two numbers in, one ladder, no judgement.

trend_score + momentum_score is the whole input. That single total picks the bias, the strength and the confidence from the fixed boundaries below — so given the scores you can reproduce the verdict exactly, and the same scores always give the same answer.

Confidence is capped at 0.9 and bottoms out around 0.4 at the edges of the neutral band, so the field never reports certainty and never reports none.
trend_score + momentum_score bias bias_strength confidence
total ≥ +4 bullish strong min(0.9, 0.5 + |total| × 0.05)
+2 ≤ total < +4 bullish normal min(0.75, 0.4 + |total| × 0.05)
−2 < total < +2 neutral normal 0.3 + (1 − |total| ÷ 4) × 0.2
−4 < total ≤ −2 bearish normal min(0.75, 0.4 + |total| × 0.05)
total ≤ −4 bearish strong min(0.9, 0.5 + |total| × 0.05)

The four category directions use a different rule. signals.trend, signals.momentum and signals.volume are each that analyser’s own score against a ±0.5 boundary, so the volume light can read bullish while the overall bias is neutral. signals.volatility is the odd one out: it is hard-coded to "normal" and never varies.

Request pattern

Poll the pair. Ignore the prose.

A symbol and a header is a working call. The durable thing to store is bias plus bias_strength — a two-value key that changes only when the verdict does. The sentence arrays are generated text and will shift on a rounding change without meaning anything new.

  • Required: symbol. timeframe defaults to H1.
  • Key needs the indicators permission scope.
  • One call, one symbol — there is no batch form.
  • Whole-market counts are on the free cached cards.
# the signal arrays for one symbol on one timeframe
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://tickatlas.com/v1/summary?symbol=EURUSD&timeframe=H4"
# act on the TRANSITION, not on every poll.
# bias + bias_strength is the stable pair to store; the arrays are
# free text and will churn on a rounding change.
URL   = "https://tickatlas.com/v1/summary"
H     = { "X-API-Key": KEY }
state = {}

def poll(symbol, timeframe="H1"):
    d = requests.get(URL, headers=H,
                     params={"symbol": symbol, "timeframe": timeframe}
                     ).json()["data"]

    now  = (d["bias"], d["bias_strength"])
    prev = state.get((symbol, timeframe))
    state[(symbol, timeframe)] = now

    if prev and prev != now:
        # descriptive record of what changed - no instruction attached
        log(symbol, timeframe, "bias", prev, "->", now,
            "confidence", d["confidence"],
            "fired", len(d["bullish_signals"]), "/", len(d["bearish_signals"]))

# Counting array entries is NOT the score: several conditions
# append a sentence and add 0. Read trend_score / momentum_score.
trend_score + momentum_score
+2.5 +3.0 trend, −0.5 momentum · lands in the +2 to +4 band
bullish · normal · 0.55
The tracebullish · bearish · neutral arrays
The directionstrend · momentum · volatility · volume
The verdictbias · bias_strength · confidence
Freshnessupdated_at (epoch)
Signal-bearing fields

The verdict and its derivation ship together.

Most analysis APIs return a label and keep the workings. This one returns both, which means you can log why a bias changed, reproduce it from the scores, and decide for yourself whether a +2 from one moving-average condition should outweigh three zero-weight notes.

Field reference

The signal-bearing part of data.

The envelope is { "success": true, "data": { … } }. These are the fields a signal integration touches; the raw readings that produced them arrive in the same response under key_values.

Field Type What it carries
bullish_signals string[] Every bullish condition that fired, across all four analysers, in analyser order. Each entry is a sentence with its triggering number inlined — "RSI oversold at 28.4 (potential reversal)".
bearish_signals string[] The same for bearish conditions. The two arrays are independent: a symbol routinely carries entries in both at once.
neutral_signals string[] Conditions that fired but scored nothing — an ADX at or below 25, an RSI in the 40–60 band, an MFI at exactly 50.
signals object Per-category direction: trend, momentum, volatility, volume. Each is bullish / bearish / neutral at a ±0.5 boundary on that analyser’s score — except volatility, which is hard-coded to "normal".
trend_score number Signed trend total to one decimal. One of the two numbers that select the bias.
momentum_score number Signed momentum total to one decimal. The other one.
bias string bullish, bearish or neutral — lowercase. The uppercase form appears only inside the generated summary sentence.
bias_strength string strong or normal, reached at a total of ±4. A separate field, not a prefix on bias.
confidence number Two decimals, bounded 0.4 to 0.9 by the ladder. It is a closed-form function of the score band, not a count of agreeing conditions.
volatility_info string[] Band-width and range observations. Informational — they never move the bias.
volume_info string[] Volume observations, on the same informational footing.
recommendations string[] Generated strings, selected by the bias band. TickAtlas documents this field by name and type and does not reproduce its wording — see the note below this table.

On recommendations and summary. TickAtlas publishes market data and computed analytics for software use. It does not provide personalised investment advice, and it does not reprint the wording of the generated recommendations strings in its own documentation. The field is documented by name, type and origin so your integration handles it deliberately — and be aware that the first entry is appended to the summary paragraph, so rendering summary verbatim in a user-facing surface renders that clause with it.

Timeframes

The same 7 intervals, evaluated independently.

M1, M5, M15, M30, H1, H4, D1, defaulting to H1. Each call scores one timeframe in isolation — there is no cross-timeframe agreement field and no combined verdict, so an H1 bullish and a D1 bearish is a perfectly ordinary pair of answers that your code, not the API, decides what to do with.

  • M1 — 1 Minute
  • M5 — 5 Minutes
  • M15 — 15 Minutes
  • M30 — 30 Minutes
  • H1 — 1 Hour (default)
  • H4 — 4 Hours
  • D1 — Daily

The cached whole-market view covers four. The six-hourly snapshot job runs this same scoring code over M30, H1, H4 and D1 for every symbol and caches the result, exposing bullish_count and bearish_count per card at no quota cost. See the snapshot surface.

Developer-first behavior

Deterministic, inspectable, and cheap to diff.

The properties that matter when signals drive something automated: the same input always gives the same output, the output explains itself, and the part you store is small.

DETERMINISM

No model in the path

Fixed thresholds, fixed constants, closed-form confidence. Two calls on the same cached values return byte-identical scores — nothing is sampled and nothing drifts between requests.

  • Reproducible from the scores alone
TRACEABILITY

Numbers inlined in the sentences

A signal reads "RSI overbought at 72.4", not "RSI overbought". The triggering value is in the string, so a log line is self-contained and a support question answers itself.

  • No follow-up call to explain a verdict
DIFFING

Two fields make the state key

bias plus bias_strength is five possible values. Store that, not the arrays, and a transition is a string comparison instead of a set difference over generated prose.

  • 5 states, not N sentences
QUOTA

5× live, 0× cached

The live call is premium tier, multiplier 5.0. The pre-computed card set is not under /v1/, so the usage middleware never meters it — whole-market signal counts cost nothing.

  • X-API-Key: tk_… · scope indicators
Developer API pricing

Included on every plan.

The summary endpoint is in the 5× premium tier and carries no plan gate for developer API keys, so pay-as-you-go reaches it on day one. The free whole-market card set has no gate at all.

There is no free tier and no self-serve trial. Every account starts on pay-as-you-go with $2.50 of prepaid credit, no card and no overage — monthly plans lift the starting quota.
Pay as you go
$0 to start 200 requests/day · 30/min until you top up
  • $2.50 of credit included
  • Every REST endpoint except raw ticks
  • No card required, no overage
  • 10 API keys
Start free
Starter
$29/mo 10,000 requests · 120/min
  • Every REST endpoint except raw ticks
  • WebSocket streaming, 5 symbols
  • Released calendar actuals
  • Email support
  • 3 API keys
View plan
Enterprise
$349/mo 1,000,000 requests · 6000/min
  • Everything in Pro
  • Dedicated support
  • 100 API keys
  • Custom indicators
  • SLA guarantee
  • On-premise option
Contact sales
Common software patterns

The same three shapes, over and over.

Almost everything built on these fields is one of three moves: watch for a change, render a state, or feed a model. All three want the scores more than the prose.

Transition alerts

Store bias and bias_strength per symbol and timeframe, compare on the next poll and fire on the change. The pair is a small, stable key; the signal sentences are free text and will churn on a rounding change.

alertswebhooksschedulers

Signal boards

Four category directions plus two array lengths fill a status panel with no client-side maths — and because every sentence carries its own triggering number, a row explains itself without a second request.

dashboardswidgetsstatus panels

Agent and model features

trend_score, momentum_score, confidence and the four directions are a compact numeric feature vector; the sentence arrays are the human-readable trace of how it was reached.

agentsfeature vectorsaudit trails
Frequently asked questions

Signals, clarified.

Where they actually live, why array length is not strength, how confidence is derived, and what the generated text field is for.

Is there a dedicated signals endpoint?

No. Signals are fields, not a route. The live per-symbol source is GET /v1/summary, which returns bullish_signals, bearish_signals and neutral_signals alongside the scores that produced them. The whole-market source is the cached market-insights card set, which carries bullish_count and bearish_count for every symbol on a timeframe at no quota cost. Anything you may have seen documented as a standalone signals path would return a 404.

Are signals weighted by how many indicators agree?

No, and this is the most common misreading. Every weight is a constant attached to the individual condition, fixed in the endpoint: price against the 200 SMA and an extreme MFI are worth ±2, most conditions are ±1 or ±0.5, and 17 of the 47 conditions add exactly zero while still writing a signal string. There is no regime detector, no reliability weighting and no promotion of one indicator over another based on market conditions. Counting the length of bullish_signals is therefore not the same as reading trend_score.

How is confidence calculated?

From the score band alone. The trend and momentum scores are added; that single total selects the bias and strength at fixed boundaries of ±2 and ±4, and confidence is a closed-form expression of the same total — capped at 0.9 and, in practice, never below 0.4. It is not a probability, it is not calibrated against outcomes, and it does not rise because more conditions fired.

Why does a symbol have bullish and bearish signals at the same time?

Because the arrays record every condition that fired, not a verdict. A market can be above its 200 SMA (bullish, +2) while its RSI sits at 38 (bearish, −0.5); both sentences appear and the score keeps the net. That is the point of returning the trace beside the number — you can see what the bias was built from rather than trusting it.

Do the volatility and volume conditions affect the bias?

Neither one. Only the trend and momentum scores are summed into the total. Volatility conditions score zero outright. Volume conditions do produce a score, and that score sets signals.volume, but the volume total is never added to the bias — so an MFI extreme worth ±2 moves a category light and leaves the verdict untouched.

Which timeframes are covered?

M1, M5, M15, M30, H1, H4, D1 on /v1/summary — the same seven every indicator endpoint accepts, defaulting to H1. The pre-computed market-insights cards cover four of them: M30, H1, H4 and D1. There is no cross-timeframe agreement field on either surface; comparing timeframes is one call per timeframe and a comparison in your own code.

How many indicator series does one call read?

26 — the distinct series named by the 47 conditions. The platform publishes 42 series in total, so a summary is a documented subset, not everything. It reads them from the cache rather than calculating anything: the values were computed when our data last updated.

What is the recommendations field?

A short list of generated strings chosen by the bias band, plus a volatility clause. TickAtlas publishes market data and computed analytics for software use; it does not provide personalised investment advice and it does not reproduce the wording of that field in its own documentation. The field is documented here by name, type and origin so your integration can handle it — and note that the first entry is also spliced into the end of the generated summary paragraph, so anything that renders summary verbatim renders that clause too.

What does a call cost?

One /v1/summary call counts once against your daily quota and costs 5 weighted units of pay-as-you-go credit — the premium tier, alongside /v1/indicator/history. The key needs the indicators permission scope. There is no plan gate for developer API keys, so a pay-as-you-go account can call it on its $2.50 of starting credit. The cached market-insights teasers cost no quota at all, because usage accounting only applies to paths beginning /v1/.

How often is it worth polling?

Values change when our data updates, which is about every 60 seconds for the fast timeframes and every 10 to 30 minutes for the slower ones. Polling faster returns the same numbers and spends 5× each time. updated_at tells you whether anything moved; the honest cadence is one call per new candle on the timeframe you asked for.

47 conditions, 26 series, one request

Take the derivation, not just the label.

Every condition that fired, the constant it was worth, the two running totals and the verdict they produce — in one JSON object you can reproduce, log and diff. Start on your $2.50 of credit.