GET /v1/heatmap aggregates RSI across the 28 major pairs and
returns one 0–10 strength value per currency, with the strongest, the weakest and the
dispersion between them. Switch one parameter and the same endpoint returns an
8 × 8 Pearson correlation matrix instead.
currencies comes back as an object keyed by code, not a sorted list — the
ordering below is the client's. Every value sits on the same 0–10 scale with 5.0 as the
neutral midpoint, which is what makes two currencies directly comparable.
1CAD 6.8 out of 10, trend bullish
2USD 6.3 out of 10, trend bullish
3GBP 5.6 out of 10, trend neutral
4CHF 5.1 out of 10, trend neutral
5EUR 4.7 out of 10, trend neutral
6NZD 4.2 out of 10, trend neutral
7AUD 3.8 out of 10, trend bearish
8JPY 3.1 out of 10, trend bearish
Illustrative values, real arithmetic. The numbers above are a sample, but
trend and change are derived from strength by the
endpoint's own rules — bullish above 6, bearish below 4, and
change = (strength − 5) × 0.3 — so the sample cannot contradict the API. The
bar length is strength ÷ 10, and every row also prints its number, so
magnitude is never carried by colour or length alone.
How it is derived
Seven pairs per currency, one inverted.
A currency is only measurable against something else, so the endpoint reads it through
the seven pairs that contain it. Where the currency is the base, a high RSI means
strength; where it is the quote, the same reading means the opposite — so that value is
flipped to 100 − RSI before it joins the average.
RSI_14 on the requested timeframe, from the same cache /v1/indicator reads.
Inverted to 100 − RSI on the quote side of the pair.
Averaged over whatever was cached, then divided by 10 and rounded to one decimal.
?type=correlation — or the boolean alias ?correlations=true,
which wins over type either way — returns a nested object instead of the
strength map. It correlates currencies, not pairs: log returns per pair are
attributed positively to the base and negatively to the quote, averaged into eight
strength series, and Pearson-correlated against each other.
Illustrative values. The structural facts are real: the diagonal is exactly 1.0, the
matrix is symmetric, and off-diagonal values are Pearson coefficients rounded to four
decimals and clamped to [-1, 1]. Every cell prints its number, so sign and magnitude
are never carried by colour alone.
Currency
USD
EUR
GBP
JPY
CHF
AUD
CAD
NZD
USD
1.00
-0.82
-0.54
-0.31
-0.61
-0.58
-0.44
-0.57
EUR
-0.82
1.00
0.61
0.18
0.74
0.35
0.22
0.33
GBP
-0.54
0.61
1.00
0.12
0.44
0.29
0.19
0.27
JPY
-0.31
0.18
0.12
1.00
0.41
-0.22
-0.35
-0.19
CHF
-0.61
0.74
0.44
0.41
1.00
0.16
0.08
0.14
AUD
-0.58
0.35
0.29
-0.22
0.16
1.00
0.47
0.86
CAD
-0.44
0.22
0.19
-0.35
0.08
0.47
1.00
0.41
NZD
-0.57
0.33
0.27
-0.19
0.14
0.86
0.41
1.00
LOOKBACK
The window is set by the timeframe
Correlation needs enough bars to be stable, so each timeframe carries its own horizon.
A longer timeframe is a longer window, not more bars of the same length.
H1 — 7 days (168 hours)
H4 — 30 days (720 hours)
D1 — 90 days (2,160 hours)
W1 — 365 days (8,760 hours)
SOFT FAIL
Not enough history is a 200, not a 500
Pairs need at least ten bars each, and the endpoint then intersects timestamps across
every pair it kept and needs at least ten in common. Below either threshold it returns
an empty matrix with available:false and a message, so a client can
render "not enough data yet" instead of an error.
time axis is the intersection, not a union
a pair on a different candle cadence is dropped
available is the field to branch on
Three parameters
Two products behind one path.
No required parameters at all: a bare GET /v1/heatmap is strength mode on
H4. Everything else is one of three optional parameters, and invalid values are rejected
with a named error code rather than coerced.
type — default strength. strength or correlation. Anything else is a 400 with INVALID_TYPE and the valid set in the detail.
timeframe — default H4. H1, H4, D1, W1. Uppercased for you; anything else is a 400 with INVALID_TIMEFRAME.
correlations — default —. Boolean alias. When true it promotes the request to type=correlation regardless of what type says, so the two spellings can never conflict.
# read dispersion, and check your inputs
d = requests.get(
"https://tickatlas.com/v1/heatmap",
headers={"X-API-Key": KEY},
params={"timeframe": "H4"},
).json()["data"]
print(d["strongest"], d["weakest"], d["range"])
# currencies is an object — sort it yourself if you want a rankingfor code, c in sorted(
d["currencies"].items(), key=lambda kv: -kv[1]["strength"]
):
# 0 means the 5.0/neutral fallback applied, not a real readingif c["pairs_analyzed"] == 0:
continue
print(code, c["strength"], c["trend"], c["pairs_analyzed"])
# correlation: branch on `available`, never on truthiness of the matrix
m = requests.get(URL, headers=H, params={"correlations": True}).json()["data"]
if m["available"]:
print(m["correlation_matrix"]["AUD"]["NZD"])
currencies.CAD.strength
6.8 of 10 · H4 · 7 of 7 pairs read
bullish
Ends of the scalestrongest CAD · weakest JPY
Dispersionrange 3.7 on 0–10
Confidence in the inputpairs_analyzed 0–7
Other modecorrelation_matrix · available
Read pairs_analyzed first
The response tells you how much to trust it.
A missing currency would break a fixed-width layout, so the endpoint never omits one. It
returns the documented fallback instead — 5.0, neutral,
0.0 — and sets pairs_analyzed to the number of pairs it really
read. That field is the difference between a neutral market and no data.
The envelope is { "success": true, "data": { … } }.
Three keys are shared; the rest depend on which mode ran, and type tells you
which one did.
data.
Type
Mode
What it carries
type
string
both
strength or correlation — echoes which mode ran.
timeframe
string
both
Uppercased echo of the request. H1, H4, D1 or W1.
timestamp
string
both
ISO 8601, server time at which the response was assembled.
currencies
object
strength
An object keyed by currency code — USD, EUR, GBP, JPY, CHF, AUD, CAD, NZD — each holding the four fields above. Always all eight keys, even when a currency had no data.
strongest
string
strength
Code with the highest strength. null only when the currency map is empty.
weakest
string
strength
Code with the lowest strength.
range
number
strength
strongest.strength − weakest.strength, two decimals. A dispersion measure on the 0–10 scale, not a percentage.
correlation_matrix
object
correlation
Nested object, currency × currency. Diagonal is exactly 1.0; off-diagonal values are Pearson coefficients to four decimals, clamped to [-1, 1]. Empty object when unavailable.
available
boolean
correlation
false when there was not enough overlapping history to compute a stable matrix. The status is still 200 — never a 5xx.
message
string
correlation
Present only when available is false, explaining that a shorter timeframe may have enough overlapping bars.
Every value inside currencies has these four keys, for all
8 codes, always.
currencies.<CODE>.
Type
What it carries
strength
number
Mean RSI_14 across the currency’s seven pairs, inverted to 100 − RSI where the currency is the quote side, divided by 10. One decimal, so the scale is 0–10 with 5.0 as the neutral midpoint.
trend
string
bullish above 6, bearish below 4, neutral in between. A classification of strength, not an independent measurement.
change
number
(strength − 5) × 0.3, to one decimal. It is a restatement of strength, NOT a price change — the endpoint would need historical data for a real one, and says so in its own source.
pairs_analyzed
number
How many of the seven pairs actually had a cached RSI_14. Below 7 the strength value is an average over fewer inputs; 0 means the whole fallback applied.
Timeframes
4 intervals, and W1 is one of them.
This endpoint's set is not the indicator endpoints' set. The sub-hourly timeframes are
absent because neither an RSI aggregate nor a correlation over a handful of minutes is
worth publishing, and W1 is present because correlation benefits from the longest
window. H4 is the default.
H1
H4 (default)
D1
W1
Developer-first behavior
Fixed shape, named errors, no surprises.
The strength response has the same keys on every call, which is what lets a dashboard
bind to it once. Where the endpoint cannot answer, it says which parameter was wrong or
which data was missing.
SHAPE
Always eight currencies
No currency is ever omitted, so a bound layout cannot shift. Missing data shows up as the documented fallback plus pairs_analyzed: 0.
5.0 · neutral · 0.0 · 0
ERRORS
Named codes, valid sets included
A bad type is INVALID_TYPE and a bad timeframe is INVALID_TIMEFRAME, each returning the list of values that would have worked.
400 with a machine-readable detail
ALIASES
Two spellings, one precedence
correlations=true promotes the request to correlation mode regardless of type, so the two parameters can never contradict each other.
boolean alias wins
QUOTA
2× weight, premium scope
Premium tier, multiplier 2.0 — the same weight as /v1/ohlc, /v1/multi, /v1/screener and /v1/calendar. The key needs the premium scope.
X-API-Key: tk_…
Related endpoints
Currency level up here, pair level everywhere else.
The heatmap deliberately returns nothing per pair. When you need the instrument rather
than the currency, these are the endpoints that carry it — weights are the real usage
multipliers.
The heatmap sits in the premium endpoint tier: a call counts once against your quota and costs two weighted units of credit.
Pay-as-you-go counts as a paid plan for endpoint access, which means a new account can
call it immediately.
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
A fixed set of eight keys on a fixed scale is unusually easy to render, which is most of
why this endpoint exists in the shape it does.
◫
Strength dashboards
Eight values on a fixed 0–10 scale with a neutral midpoint of 5.0 map onto meters and a sorted bar list with no client-side normalisation step.
metersbar listswidgets
⌗
Exposure checks
The correlation matrix is the direct answer to "are these two positions the same bet?" — read the coefficient between the two currencies rather than eyeballing two charts.
portfolio viewsrisk panels
⚙
Regime watch
Store range per cycle: a widening dispersion across the eight currencies is a different market from a narrow one, and it is one number to track.
What the strength number really measures, what change is and is not, which
timeframes exist, and how the endpoint behaves when the data is thin.
How is currency strength actually calculated?
Each currency is read through the seven pairs that contain it. The endpoint takes RSI_14 on the requested timeframe for each of those pairs, uses it as-is where the currency is the base and inverts it to 100 − RSI where the currency is the quote, averages what it found, and divides by 10. The result is a 0–10 value with 5.0 as the neutral midpoint. It is an oscillator aggregate, not an average price change.
What is the change field, if not a price move?
It is (strength − 5) × 0.3, rounded to one decimal — a linear restatement of the strength value on a smaller scale. The endpoint’s own source calls it simplified and notes that a real change figure would need historical data. Treat it as a signed distance from neutral, and read strength for the underlying number.
Which timeframes are supported?
H1, H4, D1, W1, defaulting to H4. That is deliberately not the same set the indicator endpoints accept: the sub-hourly timeframes are missing and W1 is added, because correlation needs a lookback long enough to be stable — H1 looks back 7 days, H4 looks back 30 days, D1 looks back 90 days, W1 looks back 365 days.
What does the correlation matrix correlate?
Not pairs — currencies. For each of the 28 pairs the endpoint computes log returns over a shared time axis, attributes the return to the base currency and its negative to the quote currency, averages that per currency to get eight strength series, and Pearson-correlates those series against each other. The result is an 8 × 8 object with an exact 1.0 diagonal and off-diagonal values to four decimals.
What happens when there is not enough history?
Correlation mode returns HTTP 200 with an empty correlation_matrix, available:false and a message suggesting a shorter timeframe — never a 500. It needs at least ten bars per pair and at least ten timestamps common to every pair it kept, because a matrix built on fewer is not stable enough to publish.
Which currencies and pairs are covered?
The eight majors — USD, EUR, GBP, JPY, CHF, AUD, CAD, NZD — and the 28 distinct pairs between them. There is no exotic coverage and no per-pair output of any kind in this endpoint: strength mode returns eight currency objects, correlation mode returns an 8 × 8 currency matrix. Pair-level data lives on /v1/quote, /v1/indicator and /v1/ohlc.
What does a call cost, and which plans can use it?
One call counts once against your daily quota and costs 2 weighted units of pay-as-you-go credit, in the premium tier alongside /v1/ohlc, /v1/multi, /v1/screener and /v1/calendar, and the API key must carry the premium permission scope. Every plan includes it — the heatmap carries no plan gate — so a new account can call it on its $2.50 of starting credit. There is no free tier and no self-serve trial.
Why is a currency showing exactly 5.0 with neutral and 0?
That is the documented fallback: when none of a currency’s seven pairs has a cached RSI_14, the endpoint returns strength 5.0, trend neutral, change 0.0 and pairs_analyzed 0 rather than omitting the currency or failing the request. Read pairs_analyzed before trusting any strength value — it also tells you when an average came from fewer than seven inputs.
8 currencies, 28 pairs, one request
Aggregate the majors. Skip the plumbing.
One GET returns every major currency on the same scale, with the ends and the
dispersion already computed. Start on your $2.50 of credit and add the correlation mode
when you need it.
We use cookies to analyze traffic and improve your experience. You can
accept all cookies or reject non-essential cookies. See our
Privacy Policy
and GDPR notice for details.