API reference · Starter+
Volatility API
3 endpoints: ATR time-series, spike detection, and a day × hour heatmap.
Overview
Starter plan and above
apiKey query parameter.Volatility time-series
Returns a time-series of four complementary volatility metrics for a symbol and timeframe: raw ATR, ATR%, Bollinger Band Width, and Historical Volatility. Results are returned newest-first.
Query parameters
| Name | Type | Description |
|---|---|---|
| apiKeyrequired | string | Your API key. |
| symbolCoderequired | string | Symbol identifier (e.g. BTCUSD, XAUUSD). |
| timeFramerequired | string | Candle interval: M1 · M5 · M15 · H1 · H4 · D1. |
| period | integer | Lookback window for ATR, Band Width, and Historical Volatility. Range 2–500. Default: 14 |
Response fields
| Field | Type | Description |
|---|---|---|
| openTime | DateTimeOffset | Candle open timestamp (UTC). |
| atr | decimal | Average True Range, Wilder-smoothed over period candles. |
| atrPercent | decimal | ATR as a percentage of closing price: ATR ÷ Close × 100. |
| bandWidth | decimal | Bollinger Band Width: (Upper − Lower) ÷ Middle × 100, a proxy for price expansion. |
| historicalVolatility | decimal | Rolling standard deviation of log returns over period candles, as a percentage. |
GET https://api.realmarketapi.com/api/v1/volatility?apiKey=YOUR_API_KEY&symbolCode=BTCUSD&timeFrame=H1&period=14{
"data": [
{
"openTime": "2025-06-01T08:00:00+00:00",
"atr": 1234.560000,
"atrPercent": 1.8432,
"bandWidth": 7.2418,
"historicalVolatility": 0.9751
}
],
"totalCount": 1
}Code examples
const BASE = "https://api.realmarketapi.com"
const API_KEY = "YOUR_API_KEY"
const PERIOD = 14
const url = new URL("/api/v1/volatility", BASE)
url.searchParams.set("apiKey", API_KEY)
url.searchParams.set("symbolCode", "BTCUSD")
url.searchParams.set("timeFrame", "H1")
url.searchParams.set("period", String(PERIOD))
const res = await fetch(url.toString())
if (!res.ok) throw new Error("Request failed: " + res.status)
const { data } = await res.json()
for (const point of data) {
console.log(point.openTime, "ATR:", point.atr, "HV:", point.historicalVolatility)
}import requests
BASE = "https://api.realmarketapi.com"
API_KEY = "YOUR_API_KEY"
PERIOD = 14
resp = requests.get(f"{BASE}/api/v1/volatility", params={
"apiKey": API_KEY,
"symbolCode": "BTCUSD",
"timeFrame": "H1",
"period": PERIOD,
})
resp.raise_for_status()
for point in resp.json()["data"]:
print(point["openTime"], "ATR:", point["atr"], "HV:", point["historicalVolatility"])const string BASE = "https://api.realmarketapi.com";
const string API_KEY = "YOUR_API_KEY";
const int PERIOD = 14;
using var http = new HttpClient();
var url = $"{BASE}/api/v1/volatility" +
$"?apiKey={API_KEY}&symbolCode=BTCUSD&timeFrame=H1&period={PERIOD}";
var json = await http.GetStringAsync(url);
Console.WriteLine(json);import java.net.URI;
import java.net.http.*;
public class Volatility {
static final String BASE = "https://api.realmarketapi.com";
static final String API_KEY = "YOUR_API_KEY";
static final int PERIOD = 14;
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/api/v1/volatility?apiKey=" + API_KEY
+ "&symbolCode=BTCUSD&timeFrame=H1&period=" + PERIOD))
.GET().build();
var body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
System.out.println(body);
}
}Volatility spikes
Scans the full ATR series and returns only the candles where ATR exceeded a given multiple of the series average. Useful for spotting unusual bursts of activity: news events, liquidity gaps, or panic-driven moves.
Only candles where atr ≥ spikeMultiplier × atrAverage are included. The direction field tells you whether the spike candle closed Bullish, Bearish, or Neutral. Results are returned newest-first.
Query parameters
| Name | Type | Description |
|---|---|---|
| apiKeyrequired | string | Your API key. |
| symbolCoderequired | string | Symbol identifier (e.g. BTCUSD, XAUUSD). |
| timeFramerequired | string | Candle interval: M1 · M5 · M15 · H1 · H4 · D1. |
| period | integer | ATR lookback period. Range 2–500. Default: 14 |
| spikeMultiplier | decimal | Minimum ratio of candle ATR to series average ATR required to classify as a spike. Range 1.1–10.0. Default: 2.0 |
Response fields
| Field | Type | Description |
|---|---|---|
| openTime | DateTimeOffset | Candle open timestamp (UTC). |
| atr | decimal | ATR value at the spike candle. |
| atrAverage | decimal | Mean ATR across the entire series used for comparison. |
| multiplierReached | decimal | atr ÷ atrAverage: how many times above average the spike was. |
| direction | string | Candle direction: "Bullish", "Bearish", or "Neutral". |
GET https://api.realmarketapi.com/api/v1/volatility/spikes?apiKey=YOUR_API_KEY&symbolCode=BTCUSD&timeFrame=H1&period=14&spikeMultiplier=2.0{
"data": [
{
"openTime": "2025-05-12T14:00:00+00:00",
"atr": 3512.880000,
"atrAverage": 1204.320000,
"multiplierReached": 2.92,
"direction": "Bearish"
}
],
"totalCount": 1
}Code examples
const BASE = "https://api.realmarketapi.com"
const API_KEY = "YOUR_API_KEY"
const PERIOD = 14
const SPIKE_MULTIPLIER = 2.0
const url = new URL("/api/v1/volatility/spikes", BASE)
url.searchParams.set("apiKey", API_KEY)
url.searchParams.set("symbolCode", "BTCUSD")
url.searchParams.set("timeFrame", "H1")
url.searchParams.set("period", String(PERIOD))
url.searchParams.set("spikeMultiplier", String(SPIKE_MULTIPLIER))
const res = await fetch(url.toString())
if (!res.ok) throw new Error("Request failed: " + res.status)
const { data, totalCount } = await res.json()
console.log(`Found ${totalCount} spike candle(s)`)
for (const spike of data) {
console.log(spike.openTime, spike.direction, "×" + spike.multiplierReached)
}import requests
BASE = "https://api.realmarketapi.com"
API_KEY = "YOUR_API_KEY"
PERIOD = 14
SPIKE_MULTIPLIER = 2.0
resp = requests.get(f"{BASE}/api/v1/volatility/spikes", params={
"apiKey": API_KEY,
"symbolCode": "BTCUSD",
"timeFrame": "H1",
"period": PERIOD,
"spikeMultiplier": SPIKE_MULTIPLIER,
})
resp.raise_for_status()
body = resp.json()
print(f"Found {body['totalCount']} spike candle(s)")
for spike in body["data"]:
print(spike["openTime"], spike["direction"], f"x{spike['multiplierReached']}")const string BASE = "https://api.realmarketapi.com";
const string API_KEY = "YOUR_API_KEY";
const int PERIOD = 14;
const double SPIKE_MULTIPLIER = 2.0;
using var http = new HttpClient();
var url = $"{BASE}/api/v1/volatility/spikes" +
$"?apiKey={API_KEY}&symbolCode=BTCUSD&timeFrame=H1" +
$"&period={PERIOD}&spikeMultiplier={SPIKE_MULTIPLIER}";
var json = await http.GetStringAsync(url);
Console.WriteLine(json);import java.net.URI;
import java.net.http.*;
public class VolatilitySpikes {
static final String BASE = "https://api.realmarketapi.com";
static final String API_KEY = "YOUR_API_KEY";
static final int PERIOD = 14;
static final double SPIKE_MULTIPLIER = 2.0;
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/api/v1/volatility/spikes?apiKey=" + API_KEY
+ "&symbolCode=BTCUSD&timeFrame=H1&period=" + PERIOD
+ "&spikeMultiplier=" + SPIKE_MULTIPLIER))
.GET().build();
var body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
System.out.println(body);
}
}Volatility heatmap
Aggregates the true range of all available candles into a day-of-week × hour-of-day grid. Each cell shows the average true range and a 0–1 normalised intensity for that time bucket, so you can see when a symbol is typically most volatile. Uses all available historical candles: the more history on your plan, the more reliable the heatmap.
Results are sorted by dayOfWeek then hour ascending. Buckets with no candles are omitted. An intensity of 1.0000 marks the single most volatile time slot across the dataset.
Query parameters
| Name | Type | Description |
|---|---|---|
| apiKeyrequired | string | Your API key. |
| symbolCoderequired | string | Symbol identifier (e.g. XAUUSD, BTCUSD). |
| timeFramerequired | string | Candle interval: M1 · M5 · M15 · H1 · H4 · D1. |
Response fields
| Field | Type | Description |
|---|---|---|
| dayOfWeek | string | Day name ("Monday" … "Sunday"). |
| hour | integer | Hour of day in UTC (0–23). |
| avgRange | decimal | Mean true range across all candles that fell in this time bucket. |
| intensity | decimal | avgRange ÷ max(avgRange) across all buckets; 1.0 marks the most volatile slot. |
GET https://api.realmarketapi.com/api/v1/volatility/heatmap?apiKey=YOUR_API_KEY&symbolCode=XAUUSD&timeFrame=H1{
"data": [
{
"dayOfWeek": "Monday",
"hour": 9,
"avgRange": 812.340000,
"intensity": 0.6714
},
{
"dayOfWeek": "Monday",
"hour": 14,
"avgRange": 1209.110000,
"intensity": 1.0000
}
],
"totalCount": 2
}Code examples
const BASE = "https://api.realmarketapi.com"
const API_KEY = "YOUR_API_KEY"
const url = new URL("/api/v1/volatility/heatmap", BASE)
url.searchParams.set("apiKey", API_KEY)
url.searchParams.set("symbolCode", "XAUUSD")
url.searchParams.set("timeFrame", "H1")
const res = await fetch(url.toString())
if (!res.ok) throw new Error("Request failed: " + res.status)
const { data } = await res.json()
// Print the top-3 most volatile time slots
const sorted = [...data].sort((a, b) => b.intensity - a.intensity).slice(0, 3)
for (const slot of sorted) {
console.log(`${slot.dayOfWeek} ${String(slot.hour).padStart(2, "0")}:00 — intensity ${slot.intensity}`)
}import requests
BASE = "https://api.realmarketapi.com"
API_KEY = "YOUR_API_KEY"
resp = requests.get(f"{BASE}/api/v1/volatility/heatmap", params={
"apiKey": API_KEY,
"symbolCode": "XAUUSD",
"timeFrame": "H1",
})
resp.raise_for_status()
data = resp.json()["data"]
# Print top-3 most volatile time slots
top3 = sorted(data, key=lambda x: x["intensity"], reverse=True)[:3]
for slot in top3:
print(f"{slot['dayOfWeek']} {slot['hour']:02d}:00 — intensity {slot['intensity']:.4f}")const string BASE = "https://api.realmarketapi.com";
const string API_KEY = "YOUR_API_KEY";
using var http = new HttpClient();
var url = $"{BASE}/api/v1/volatility/heatmap" +
$"?apiKey={API_KEY}&symbolCode=XAUUSD&timeFrame=H1";
var json = await http.GetStringAsync(url);
Console.WriteLine(json);import java.net.URI;
import java.net.http.*;
public class VolatilityHeatmap {
static final String BASE = "https://api.realmarketapi.com";
static final String API_KEY = "YOUR_API_KEY";
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/api/v1/volatility/heatmap?apiKey=" + API_KEY
+ "&symbolCode=XAUUSD&timeFrame=H1"))
.GET().build();
var body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
System.out.println(body);
}
}Error codes
| Code | HTTP | Description |
|---|---|---|
| ERR_0001_DATA_NOT_FOUND | 400 | No market data available for the requested symbol / timeframe |
| ERR_0005_INVALID_API_KEY | 400 | API key is missing, inactive, or not found |
| ERR_0007_INVALID_TIME_FRAME | 400 | Requested timeframe is not available on your plan |
| ERR_0008_SYMBOL_NOT_SUPPORTED | 400 | Requested symbol is not available on your plan |
| ERR_0012_EMAIL_NOT_VERIFIED | 400 | Account email has not been verified |
| ERR_0014_INVALID_PLAN | 400 | Free plan is not permitted to access this endpoint |
| ERR_0017_REQUEST_QUOTA_EXCEEDED | 429 | Monthly request quota has been reached |
Try it in the Playground
Send real requests and inspect live responses in the browser.