Reference data
dataset(...) gives a script reference data that is not market prices: the economic calendar and daily rates and yields. You declare a handle once at module scope and read it on every bar. Indicators, definitions and studies all use it.
const cal = dataset("econ.calendar", {
where: { country: { fromInstrument: true }, localImportance: { gte: 3 } },
lookahead: "1d",
});
export function onBar(ctx) {
// Stand aside from 15 minutes before to 30 minutes after an important release that is still happening.
if (cal.within({ before: "15m", after: "30m" }).some((r) => r.state === "scheduled")) return;
// ...
}Every read is as known at that bar
A read is made at the end of the bar being computed. Inside a timeframe handler it is the end of the bucket being handled. On a bar that has not closed yet (a live chart's forming bar, or a run fetched up to now) it is now. The handle answers with what was known at that moment:
A release is visible once it was listed, which is never more than 7 days before its time.
Its forecast is visible once published, and its previous figure once printed.
A postponement or cancellation takes effect from when it was known.
A rate or yield is visible from when it was published.
A backtest sees exactly what a live chart saw at the same moment, so a filter you test on history behaves the same way live. Where history cannot say when something became known, the platform uses the latest safe time, so a backtest may know less than a live chart, never more.
Declaring a handle
dataset(name, options) must be called at module scope with literal arguments.
Option | Meaning |
|---|---|
| Which rows. Required. Keys are the dataset's filterable fields |
| How far back reads reach, e.g. |
| How far ahead reads reach. The calendar allows up to |
A where value is one of these:
a literal, meaning equals:
{ country: "US" };an array, meaning any of:
{ code: ["US.NFP", "US.CPI.YOY"] };one operator:
{ importance: { gte: 2 } },{ code: { in: [...] } }, or{ country: { fromInstrument: true } }for the economies that move the chart's instrument.
Values are checked when the handle is declared:
countries are two-letter economy codes (
US,EUfor the euro area,UK,JP); case does not matter, andGB,USAandEZare read asUK,USandEU;importanceandlocalImportanceare 1, 2 or 3, orlow,mediumorhigh;categories and rate families are their listed names;
codes look like
US.NFPorGBOND.US10Y.
Anything else is refused, and so is a code or economy the data does not have: a filter never silently matches nothing.
Settings cannot appear in where. To filter by a setting, read everything the setting can reach and filter the rows in the script:
const cal = dataset("econ.calendar", { where: { country: { fromInstrument: true } } });
export function onBar(ctx) {
const soon = cal.within({ after: "1h" }).filter((r) => r.localImportance >= ctx.params.minImportance);
}Plans set how many handles one script may declare: Free 1, Starter 2, Pro 4, Ultra 8. An indicator that reads a dataset can be used as a dependency like any other: it reads the same data wherever it runs.
Reading
Read | Returns |
|---|---|
| The newest row whose time has passed |
| The earliest row still ahead (always |
| The main value of |
| Rows whose time is in |
| Rows whose time is in |
| The last |
| What changed since the previous bar: |
| The same reads as known at an earlier instant |
|
|
|
|
last, next, value and history skip rows that are withdrawn, cancelled or rescheduled. A replacement counts once it is listed. within, between and updatesThisBar return every row, so check row.state === "scheduled" before treating a row as a release that is happening.
Rows are frozen and hold only their dataset's fields. Reading any other name (row.actual, row.forecast, row.time) throws; an optional field without a value (estimate, previous, rescheduledTo) is undefined.
Times are unix seconds, like ctx.time. A millisecond timestamp, a Date or a date string is refused. within takes { before, after } and nothing else, history(n) takes a whole number, and between(from, to) takes two times in order.
within spans may not exceed the handle's lookback and lookahead: asking for more throws, so declare what you read. asOf(t) may look back but never past the bar being computed.
In studies
A study has no current bar, so it reads at a time with h.asOf(t). ctx.event.knownAt is the end of the bar the event fired on: the moment the definition decided, with what it knew then. Inside scope(ctx) read at knownAt and never later; onEvent may read later times to measure an outcome. See scope.
A time past now (the latest moment the run's data covers) has not happened yet. h.asOf(t) and h.valueAt(t) there return undefined and the event is marked not ready, the same as a forward candle read past the last bar, so its result is computed on a run after that moment rather than stored from a calendar that can still change. Check for it: const later = cal.asOf(t); if (!later) return;.
const cal = dataset("econ.calendar", { where: { country: { fromInstrument: true }, localImportance: { gte: 3 } } });
export function scope(ctx) {
const n = cal.asOf(ctx.event.knownAt)?.next;
const hours = n ? (n.scheduledAt - ctx.event.knownAt) / 3600 : Infinity;
return { newsSoon: hours <= 1 ? "within 1h" : "later" };
}