Declarations
The top of a study declares everything it reads and publishes: its settings, the definitions whose events it measures, any indicators, the dimensions that split events into groups, and each result. Declarations run once, at module scope, before any event.
meta
meta({
name: "OR break first hit",
kind: "study",
category: "Opening range",
params: {
horizonMin: { type: "number", def: 60, min: 1, max: 1440, step: 1 },
markColor: { type: "color", def: "#26a69a", allowAlpha: false },
},
runOn: ["1m", "5m", "15m"],
runOnReason: "Needs several bars inside each opening range.",
});Field | Notes |
|---|---|
| Shown in the study list and on the run card. |
|
|
| Optional grouping label. |
| Settings the trader can change before a run. Read them as |
| Optional list of timeframes the study may run on. Leave it out to allow all. |
| Shown when someone picks a timeframe outside |
Each param takes type ("number", "string", "boolean" or "color"), def, and optionally min, max, step and options. Colour params also take allowAlpha and presetColors. Use type: "color" for any colour so the run dialog shows a picker.
flows.declare
flows.declare({ slug: "or-break", as: "orb", version: 3 });Field | Notes |
|---|---|
| The definition's slug, not its display name. |
| Alias. |
| Required. Lint fails with |
| Optional setting overrides for the definition. |
A study reads only the events recorded under the exact version you pin. When a definition is created and then written, its code lands on version 2, and version 1 is the empty row created with it. Pin version 1 and the study lints clean, then every run comes back with no events. Pin the version you ran over history.
A study that ships inside an app can name a definition from the same app by path: flows.declare({ from: "definitions/ib-structure", as: "ib" }). A from declaration takes no version. It resolves to whatever version is installed for the person running it.
indicators.declare
indicators.declare({ slug: "atr", as: "atr14", version: 1, settings: { period: 14 } });Same shape as in indicators and definitions, described in Declaring indicator dependencies. version is required here too (indicators/missing-version). Reading the values is covered in Dependencies.
dimensions.declare
A dimension is a way to split events into groups, such as break direction or session. Results indexed by a dimension report one row per group, and a Forward Insight uses scope dimensions to pick the reading for the event you click.
dimensions.declare({
id: "direction",
role: "scope",
title: "Break direction",
description: "Which side of the opening range the close broke.",
values: ["up", "down"],
});
dimensions.declare({
id: "next_regime",
role: "report",
title: "Next-day regime",
description: "Measured from the following session.",
values: ["rotational", "trending", "ranging"],
});id, title and description are required (study/dimension-declare-fields). Ids must be unique.
| Meaning | Returned by | Indexes a Forward Insight |
|---|---|---|---|
| Known when the event fires: direction, weekday, a volatility bucket at the event | Required, on every path | Yes |
| Measured later in | Forbidden | No |
Declare an outcome axis as role: "report". Left without a role it defaults to "scope", and lint then asks scope() to return an outcome it cannot know when the event fires. scope covers both roles.
values lists the canonical values. When it is set, scope() and published cells must use exactly those strings. Put display labels such as "Strong trending" in result text, never in a dimension value. Without values the dimension is open and takes any value.
results.declare
results.declare({
id: "hit_rate",
kind: "metric",
title: "Target hit rate",
description: "Share of breaks where the target hit before the stop.",
size: "xs",
});
results.declare({
id: "by_direction",
kind: "table",
title: "By break direction",
description: "Hit rate and sample for up and down breaks.",
indexedBy: ["direction"],
columns: [
{ id: "target_rate", format: "percent" },
{ id: "events_in_group", format: "count" },
],
});Field | Notes |
|---|---|
| What you pass to |
| One of the kinds in Results and stats. |
| Heading on the result. |
| One to three plain sentences on what it measures and in what unit. It also appears in Forward Insight popovers. Lint warns when it is missing. |
| Dimension ids whose values key the published rows. Each row must carry every listed id as a field. |
| Table columns: |
|
|
| For |
| Renderer options, such as |
Results render in the order you declare them. Consecutive xs metrics share a row of up to four tiles, consecutive md results sit side by side, and each lg takes a full row. Declare a prose answer first, then the headline metrics, then the main chart.
Declare every id you publish. Lint warns about a declared id you never publish (study/declare-without-publish).
A report table may be indexed by more dimensions than a Forward Insight uses, including report-role ones. ["direction", "next_regime"] is fine for a contingency table.
Common mistakes
Writing the definition's display name instead of its slug in
flows.declare.Pinning
version: 1on a definition that has moved on.Leaving
roleoff an outcome dimension.Using a display label as a dimension value when
valuesis declared.Writing a
pin_cellresult by hand. Attach to chart writes it. See Forward Insights.
