--- url: /reference/outputs/bgColor.md --- # Background color {#module-bgcolor} **Kind:** `module` **Namespace:** `bgColor` Paints a per-bar background color on the chart. For line or histogram series, use [`spline`](./spline.md); for numeric outputs without drawing, use [`output`](./output.md). Each `bgColor` layer maintains one color per bar. A new color is added when a new bar starts and replaced when the current bar updates. ## bgColor() {#fun-bgcolor} **Kind:** `func` Outputs a background color for the current bar for one layer. **Syntax** ``` bgColor(color) → void bgColor(color, {title, offset, numberOfLast, overlay}) → void ``` **Arguments** | Name | Type | Description | |-------|--------|-------------| | color | color? | [Color](/reference/core/color) for the current bar. Pass `null` if this layer should not paint on this bar. | **Options** Static (ignored after the first call): | Name | Type | Default | Description | |---------------|---------|---------|-------------| | title? | string | `null` | Display name in the legend | | offset? | int | `0` | Horizontal offset in bars (positive = right) | | numberOfLast? | int | `0` | How many of the last bars this layer applies to (host-defined semantics) | | overlay? | boolean | `true` | If `true`, draws on the main price chart instead of a separate pane (same idea as [`spline`](./spline.md)) | The **color** is always the first argument (not an option), so it can change on every tick. **Returns** `void` **Caveats** * Must be called inside [`onTick()`](/getting-started/quick-start#ontick-function), not in the [`init`](/getting-started/quick-start#init-section) section * Must be at the top level of [`onTick()`](/getting-started/quick-start#ontick-function), not inside conditionals or loops. This ensures the call count and order remain constant across ticks ::: danger Pitfall ```javascript function onTick() { if (bar.isConfirmed()) { bgColor(color.RED); // ❌ inside conditional } } ``` ::: **Example** ```javascript const bull = input.color("Bull", color.GREEN); const bear = input.color("Bear", color.RED); function onTick() { const regime = close > ta.sma(close, 20); bgColor(regime ? bull : bear, { title: "Regime", offset: 0, numberOfLast: 100, overlay: true }); } ``` --- --- url: /reference/core/bar.md --- # Bar {#module-bar} **Kind:** `module` **Namespace:** `bar` Provides functions for accessing the current bar state and detecting time-based boundaries. ## bar.index() {#fun-bar-index} **Kind:** `func` Returns the index of the current bar. **Syntax** ``` bar.index() → int ``` **Returns** Zero-based index of the current bar. First bar is `0`. **Example** ```javascript function onTick() { // plot bar index as a rising line spline(bar.index(), {title: "Bar #"}); } ``` ## bar.isNew() {#fun-bar-isnew} **Kind:** `func` Checks if this is the first tick of a new bar. **Syntax** ``` bar.isNew() → bool ``` **Returns** `true` on the first tick of a new bar (including all historical bars), `false` on subsequent real-time updates to the same bar. ## bar.isConfirmed() {#fun-bar-isconfirmed} **Kind:** `func` Checks if the current bar is confirmed (closed). **Syntax** ``` bar.isConfirmed() → bool ``` **Returns** `true` if the bar is confirmed and will not change, `false` if the bar is still updating. ## bar.isHistory() {#fun-bar-ishistory} **Kind:** `func` Checks if the current bar is historical data. **Syntax** ``` bar.isHistory() → bool ``` **Returns** `true` if processing historical data, `false` if processing realtime data. **Example** ```javascript function onTick() { const sma = ta.sma(close, 20); // different colors for history vs realtime const lineColor = bar.isHistory() ? color.GRAY : color.BLUE; spline(sma, {title: "SMA", color: lineColor}); } ``` ## bar.isNewDay() {#fun-bar-isnewday} **Kind:** `func` Checks if this bar starts a new day. **Syntax** ``` bar.isNewDay() → bool ``` **Returns** `true` if the current bar is the first bar of a new day, `false` otherwise. ## bar.isNewWeek() {#fun-bar-isnewweek} **Kind:** `func` Checks if this bar starts a new week. **Syntax** ``` bar.isNewWeek() → bool ``` **Returns** `true` if the current bar is the first bar of a new week, `false` otherwise. ## bar.isNewMonth() {#fun-bar-isnewmonth} **Kind:** `func` Checks if this bar starts a new month. **Syntax** ``` bar.isNewMonth() → bool ``` **Returns** `true` if the current bar is the first bar of a new month, `false` otherwise. --- --- url: /reference/outputs/barColor.md --- # Bar color {#module-barcolor} **Kind:** `module` **Namespace:** `barColor` Change the bar color on the chart. Always draws on the main price chart (overlay is implicit). For background fill, use [`bgColor`](./bgColor.md); for line or histogram series, use [`spline`](./spline.md); for numeric outputs without drawing, use [`output`](./output.md). A bar has exactly one color, so `barColor` is a **single-slot** output — calling it multiple times in the same `onTick()` does not create several layers. Instead: * **Color:** the last call in the current tick wins. * **Options** (`title`, `offset`, `numberOfLast`): captured on the very first call and ignored on any later call — they stay static for the lifetime of the indicator. * Across ticks, the color history still reflects one color per bar: a new point is appended when a new bar starts and overwritten on intra-bar updates. This differs from [`bgColor`](./bgColor.md), [`spline`](./spline.md), and [`shape`](./shape.md), which are positional — each call site registers its own layer. ## barColor() {#fun-barcolor} **Kind:** `func` Outputs a bar color for the current bar for one layer. **Syntax** ``` barColor(color) → void barColor(color, {title, offset, numberOfLast}) → void ``` **Arguments** | Name | Type | Description | |-------|--------|-------------------------------------------------------------------------------------------------------------| | color | color? | [Color](/reference/core/color) for the current bar. Pass `null` if this layer should not paint on this bar. | **Options** Static (ignored after the first call): | Name | Type | Default | Description | |---------------|--------|---------|--------------------------------------------------------------------------| | title? | string | `null` | Display name in the legend | | offset? | int | `0` | Horizontal offset in bars (positive = right) | | numberOfLast? | int | `0` | How many of the last bars this layer applies to (host-defined semantics) | The **color** is always the first argument (not an option), so it can change on every tick. **Returns** `void` **Caveats** * Must be called inside [`onTick()`](/getting-started/quick-start#ontick-function), not in the [`init`](/getting-started/quick-start#init-section) section * Must be at the top level of [`onTick()`](/getting-started/quick-start#ontick-function), not inside conditionals or loops. This ensures the call count and order remain constant across ticks ::: danger Pitfall ```javascript function onTick() { if (bar.isConfirmed()) { barColor(color.RED); // ❌ inside conditional } } ``` ::: **Example** ```javascript const bull = input.color("Bull", color.GREEN); const bear = input.color("Bear", color.RED); function onTick() { const regime = close > ta.sma(close, 20); barColor(regime ? bull : bear, { title: "Regime", offset: 0, numberOfLast: 100 }); } ``` --- --- url: /reference/core/color.md --- # Color {#module-color} **Kind:** `module` **Namespace:** `color` Provides named color constants and functions for creating custom colors with transparency. ## color.create() {#fun-color-create} **Kind:** `func` Creates a color from hex string, RGBA components, or applies transparency to an existing color. **Syntax** ``` color.create(hex) → color color.create({r, g, b, a}) → color color.create(baseColor, transparency) → color ``` **Overloads** Creates a color from hex string or named color: `color.create(hex) → color` | Name | Type | Description | |------|--------|---------------------------------------------------------------------| | hex | string | Hex string (`"#RGB"`, `"#RRGGBB"`, `"#RRGGBBAA"`) or name (`"red"`) | *** Creates a color from RGBA components: `color.create({r, g, b, a}) → color` | Name | Type | Default | Description | |------|------|---------|---------------| | r? | int | 0 | Red (0-255) | | g? | int | 0 | Green (0-255) | | b? | int | 0 | Blue (0-255) | | a? | int | 255 | Alpha (0-255) | *** Applies transparency to existing color: `color.create(baseColor, transparency) → color` | Name | Type | Description | |--------------|-------|---------------------------------------| | baseColor | color | Base color to modify | | transparency | int | 0 (opaque) to 100 (fully transparent) | **Returns** The `color` value. **Example** ```javascript // Create from hex string const c1 = color.create("#FF0000"); // red const c2 = color.create("#FF000080"); // red, 50% opacity const c3 = color.create("#F00"); // shorthand red // Create from RGBA components const c4 = color.create({r: 255, g: 0, b: 0}); // red const c5 = color.create({r: 255, g: 0, b: 0, a: 128}); // red, 50% opacity // Apply transparency const c6 = color.create(color.RED, 50); // red, 50% transparent const c7 = color.create(color.BLUE, 90); // blue, 90% transparent ``` ```javascript // Conditional coloring function onTick() { const sma = ta.sma(close, 20); const priceColor = close > sma ? color.GREEN : color.RED; spline(close, {title: "Price", color: priceColor}); } ``` ## Named Colors {#named-colors} Predefined color constants. Values follow the [CSS Color specification](https://www.w3.org/TR/css-color-4/#named-colors). *** ### color.BLACK {#const-color-black} **Kind:** `constant` **Value:** `black` (`#000000`) Predefined black color. *** ### color.SILVER {#const-color-silver} **Kind:** `constant` **Value:** `silver` (`#C0C0C0`) Predefined silver color. *** ### color.GRAY {#const-color-gray} **Kind:** `constant` **Value:** `gray` (`#808080`) Predefined gray color. *** ### color.WHITE {#const-color-white} **Kind:** `constant` **Value:** `white` (`#FFFFFF`) Predefined white color. *** ### color.MAROON {#const-color-maroon} **Kind:** `constant` **Value:** `maroon` (`#800000`) Predefined maroon color. *** ### color.RED {#const-color-red} **Kind:** `constant` **Value:** `red` (`#FF0000`) Predefined red color. *** ### color.PURPLE {#const-color-purple} **Kind:** `constant` **Value:** `purple` (`#800080`) Predefined purple color. *** ### color.FUCHSIA {#const-color-fuchsia} **Kind:** `constant` **Value:** `fuchsia` (`#FF00FF`) Predefined fuchsia color. *** ### color.MAGENTA {#const-color-magenta} **Kind:** `constant` **Value:** `magenta` (`#FF00FF`) Predefined magenta color. Alias for [FUCHSIA](#const-color-fuchsia). *** ### color.GREEN {#const-color-green} **Kind:** `constant` **Value:** `green` (`#008000`) Predefined green color. *** ### color.LIME {#const-color-lime} **Kind:** `constant` **Value:** `lime` (`#00FF00`) Predefined lime color. *** ### color.OLIVE {#const-color-olive} **Kind:** `constant` **Value:** `olive` (`#808000`) Predefined olive color. *** ### color.YELLOW {#const-color-yellow} **Kind:** `constant` **Value:** `yellow` (`#FFFF00`) Predefined yellow color. *** ### color.ORANGE {#const-color-orange} **Kind:** `constant` **Value:** `orange` (`#FFA500`) Predefined orange color. *** ### color.NAVY {#const-color-navy} **Kind:** `constant` **Value:** `navy` (`#000080`) Predefined navy color. *** ### color.BLUE {#const-color-blue} **Kind:** `constant` **Value:** `blue` (`#0000FF`) Predefined blue color. *** ### color.TEAL {#const-color-teal} **Kind:** `constant` **Value:** `teal` (`#008080`) Predefined teal color. *** ### color.AQUA {#const-color-aqua} **Kind:** `constant` **Value:** `aqua` (`#00FFFF`) Predefined aqua color. *** ### color.CYAN {#const-color-cyan} **Kind:** `constant` **Value:** `cyan` (`#00FFFF`) Predefined cyan color. Alias for [AQUA](#const-color-aqua). *** ### color.CRIMSON {#const-color-crimson} **Kind:** `constant` **Value:** `crimson` (`#DC143C`) Predefined crimson color. *** ### color.CORAL {#const-color-coral} **Kind:** `constant` **Value:** `coral` (`#FF7F50`) Predefined coral color. *** ### color.GOLD {#const-color-gold} **Kind:** `constant` **Value:** `gold` (`#FFD700`) Predefined gold color. *** ### color.DODGER\_BLUE {#const-color-dodgerblue} **Kind:** `constant` **Value:** `dodgerblue` (`#1E90FF`) Predefined dodger blue color. *** ### color.SKY\_BLUE {#const-color-skyblue} **Kind:** `constant` **Value:** `skyblue` (`#87CEEB`) Predefined sky blue color. *** ### color.VIOLET {#const-color-violet} **Kind:** `constant` **Value:** `violet` (`#EE82EE`) Predefined violet color. *** ### color.PINK {#const-color-pink} **Kind:** `constant` **Value:** `pink` (`#FFC0CB`) Predefined pink color. --- --- url: /reference/core/core.md --- # Core {#core} Core modules provide fundamental building blocks for scripts. ### [indicator](./indicator.md) Initializes the indicator context (display settings, overlay mode). ### [input](./input.md) Configurable parameters declared in the [`init`](/getting-started/quick-start#init-section) section. ### [ts](./ts.md) Time series creation and historical value access. ### [bar](./bar.md) Current bar state and time boundary detection. ### [color](./color.md) Color constants and factory methods. ### [location](./location.md) Vertical placement constants for bar-anchored outputs (e.g. [`shape()`](/reference/outputs/shape)). ### [session](./session.md) Trading sessions and time-based filtering. --- --- url: /reference/errors.md --- # Error Reference This page describes all runtime errors you may encounter when writing dxScript indicators, along with explanations and solutions. ## Member Access Errors ### `Not a function` Occurs when you try to invoke a non-callable value as a function. **Common Causes** * Calling a property that is not a method * Calling a built-in series (like `close`, `open`) as a function **Example** ```javascript // ❌ Wrong: 'close' is a series, not a function const x = close(); ``` *** ### `'module' has no member 'X'` Occurs when accessing a non-existent member of a module or object. **Common Causes** * Typo in method or property name * Accessing removed or renamed API **Example** ```javascript // ❌ Wrong: Typo in method name const avg = color.GREN; // Error: 'color' has no member 'GREN'. Did you mean 'color.GREEN'? // ❌ Wrong: Typo in method name const len = input.bol("bool", true); // Error: 'input' has no member 'bol'. Did you mean 'input.bool'? ``` *** ### `'module.X' is read-only and cannot be modified` Occurs when trying to assign a value to a read-only property. **Common Causes** * Trying to modify module objects **Example** ```javascript // ❌ Wrong: Cannot modify module input.bool = function () { }; // Error: 'input.bool' is read-only and cannot be modified ``` ## Argument Errors ### `'method' expected at least N argument(s), got M` Occurs when a function receives fewer arguments than required. **Common Causes** * Missing required parameters * Optional parameters placed before required ones * Forgetting to pass options object **Example** ```javascript // ❌ Wrong: Missing name parameter input.bool(true); // Error: 'input.bool' expected at least 2 argument(s), got 1 ``` *** ### `'method' parameter 'name' must be T, got T'` Occurs when an argument has the wrong type. **Common Causes** * Passing a string where a number is expected * Passing a number where a series is expected * Passing the wrong object type **Example** ```javascript // ❌ Wrong: String instead of number const len = input.double("length", "20"); // Error: 'input.double' parameter 'argument 2' must be number, got string ``` *** ## Troubleshooting Checklist When you encounter an error: 1. **Check the spelling**: error messages often suggest the correct name 2. **Verify the module**: make sure you're using the right module (e.g., `ta.sma` not `ts.sma`) 3. **Count arguments**: check required vs optional parameters in reference 4. **Check types**: ensure arguments match expected types (number, string, series, etc.) 5. **Check context**: some functions only work in `init` section, others in `onTick()` 6. **Check mutability**: built-in series and modules are read-only --- --- url: /reference/core/indicator.md --- # indicator() {#fun-indicator} **Kind:** `func` Initializes the indicator context. Call once in the [`init`](/getting-started/quick-start#init-section) section to configure how the indicator is displayed on the chart. Calling `indicator()` is optional. When omitted, all settings use their default values. **Syntax** ``` indicator(options?) → void ``` **Arguments** | Name | Type | Description | |---------|--------|--------------------------------------------| | options | object | Partial configuration object (see Options) | **Options** | Name | Type | Default | Description | |-----------|--------|---------------|----------------------------------------------------------------------------------------------------------| | overlay? | bool | `true` | When `true`, plots are drawn on the main price chart. When `false`, a separate pane is used | | lookback? | number | platform default | Number of historical bars the indicator can access. Must be at least `1` | **Returns** `void` **Caveats** * Must be called in the [`init`](/getting-started/quick-start#init-section) section, not inside [`onTick()`](/getting-started/quick-start#ontick-function). * Should be called at most once per script. * `lookback` must be at least `1`; otherwise an error is thrown. **Example** ```javascript // Overlay indicator — drawn on the main price chart indicator({overlay: true}); const length = input.double("length", 20); function onTick() { spline(ta.sma(close, length), {title: "SMA"}); } ``` ```javascript // Separate pane indicator (default behavior) indicator({overlay: false}); function onTick() { const rsi = ta.rsi(close, 14); spline(rsi, {title: "RSI"}); } ``` ```javascript // Limit history access to 50 bars indicator({lookback: 50}); function onTick() { spline(ta.sma(close, 50), {title: "SMA 50"}); } ``` --- --- url: /reference/core/input.md --- # Input Parameters {#module-input} **Kind:** `module` **Namespace:** `input` Provides functions for declaring configurable input parameters. Parameters are declared in the [`init`](/getting-started/quick-start#init-section) section, and their default values can be changed by the user without modifying the source code. **Caveats** * Must be called in the [`init`](/getting-started/quick-start#init-section) section, not inside [`onTick()`](/getting-started/quick-start#ontick-function) function. * Must be at the top level, not inside conditionals or loops. This ensures all parameters are discoverable. ::: danger Pitfall ```javascript const mode = input.string("mode", "fast"); if (mode === "fast") { const mult = input.double("mult", 2.0); // ❌ inside conditional } function onTick() { const len = input.double("len", 20); // ❌ inside onTick() } ``` ::: ## input() {#fun-input} **Kind:** `func` Adds an input with automatic type detection based on the default value. **Syntax** ``` input(name, defValue) → bool | double | string | color | source ``` **Arguments** | Name | Type | Description | |----------|--------|-------------------------------------------------------| | name | string | Unique identifier | | defValue | any | Default value. Type determines input kind (see Notes) | **Returns** The value of the input with the same type as `defValue`. **Notes** {#notes-input} Type is inferred from `defValue`: | Default value type | Input kind | Description | |-------------------------------------------------------|-----------------------------|-----------------| | `bool` | [bool](#fun-input-bool) | Checkbox | | `number` | [double](#fun-input-double) | Numeric field | | `string` | [string](#fun-input-string) | Text field | | `color` | [color](#fun-input-color) | Color picker | | [built-in series](/reference/core/ts#built-in-series) | [source](#fun-input-source) | Source selector | **Example** ```javascript const length = input("length", 20); // double const useEma = input("useEma", true); // bool const title = input("title", "Average"); // string const lineColor = input("lineColor", color.RED); // color const source = input("source", close); // source function onTick() { const avg = useEma ? ta.ema(source, length) : ta.sma(source, length); spline(avg, {title: title, color: lineColor}); } ``` ## input.bool() {#fun-input-bool} **Kind:** `func` Adds a bool input (checkbox). **Syntax** ``` input.bool(name, defValue) → bool ``` **Arguments** | Name | Type | Description | |----------|--------|-----------------------------------| | name | string | Unique identifier | | defValue | bool | Default value (`true` or `false`) | **Returns** The bool value of the input. **Example** ```javascript const useEma = input.bool("useEma", true); function onTick() { const avg = useEma ? ta.ema(close, 20) : ta.sma(close, 20); spline(avg, {title: "Average"}); } ``` ## input.double() {#fun-input-double} **Kind:** `func` Adds a double input. **Syntax** ``` input.double(name, defValue) → double input.double(name, defValue, {min, max, step}) → double input.double(name, defValue, {options}) → double ``` **Arguments** | Name | Type | Description | |----------|--------|-------------------| | name | string | Unique identifier | | defValue | double | Default value | **Options** With constraints: | Name | Type | Description | |-------|--------|-----------------------| | min? | double | Minimum allowed value | | max? | double | Maximum allowed value | | step? | double | Step increment for UI | With predefined values: | Name | Type | Description | |----------|----------|------------------------| | options? | double\[] | List of allowed values | **Returns** The double value of the input. **Notes** * `step` is used for UI control only and does not affect validation * Use either `{min, max, step}` or `{options}`. If both specified, `options` takes precedence **Example** ```javascript // Basic const length = input.double("length", 20); // With min/max constraints const period = input.double("period", 14, { min: 1, max: 500 }); // With min/max constraints and step const multiplier = input.double("multiplier", 2.0, { min: 0.1, max: 10.0, step: 0.1 }); // With predefined options const deviation = input.double("deviation", 2.0, { options: [1.0, 1.5, 2.0, 2.5, 3.0] }); ``` ## input.string() {#fun-input-string} **Kind:** `func` Adds a text input or dropdown selector. **Syntax** ``` input.string(name, defValue) → string input.string(name, defValue, {options}) → string ``` **Arguments** | Name | Type | Description | |----------|--------|-------------------| | name | string | Unique identifier | | defValue | string | Default value | **Options** | Name | Type | Description | |----------|----------|------------------------| | options? | string\[] | List of allowed values | **Returns** The string value of the input. **Example** ```javascript // Free text const title = input.string("title", "My Indicator"); // Dropdown selector const avgType = input.string("avgType", "SMA", {options: ["SMA", "EMA", "WMA"]}); function onTick() { let avg; switch (avgType) { case "SMA": avg = ta.sma(close, 20); break; case "EMA": avg = ta.ema(close, 20); break; case "WMA": avg = ta.wma(close, 20); break; } spline(avg, {title: avgType}); } ``` ## input.source() {#fun-input-source} **Kind:** `func` Adds a source selector. Allows users to choose which [built-in series](/reference/core/ts#built-in-series) to use for calculations. **Syntax** ``` input.source(name, defValue) → series input.source(name, defValue, {options}) → series ``` **Arguments** | Name | Type | Description | |----------|--------|----------------------| | name | string | Unique identifier | | defValue | series | Default price series | **Options** | Name | Type | Description | |----------|----------|---------------------------| | options? | series\[] | List of available sources | **Returns** The selected [`series`](/reference/core/ts#object-series). **Example** ```javascript // All sources available const source = input.source("source", close); // Limited to OHLC only const priceSource = input.source("price", close, { options: [open, high, low, close] }); function onTick() { spline(ta.sma(source, 20), {title: "SMA"}); } ``` ## input.color() {#fun-input-color} **Kind:** `func` Adds a color picker. **Syntax** ``` input.color(name, defValue) → color ``` **Arguments** | Name | Type | Description | |----------|--------|---------------------| | name | string | Unique identifier | | defValue | color | Default color value | **Returns** The [`color`](/reference/core/color) value of the input. **Example** ```javascript const bullColor = input.color("bullColor", color.GREEN); const bearColor = input.color("bearColor", color.RED); function onTick() { spline(close, {color: close > open ? bullColor : bearColor}); } ``` ## input.session() {#fun-input-session} **Kind:** `func` Adds a session input. Allows users to define time intervals and days of the week. **Syntax** ``` input.session(name, defValue) → session input.session(name, defValue, {options, timeZone}) → session ``` **Arguments** | Name | Type | Description | |----------|--------|------------------------| | name | string | Unique identifier | | defValue | string | Default session string | **Options** | Name | Type | Description | |-----------|----------|------------------------------------------------------------------| | options? | string\[] | List of available session values | | timeZone? | string | Time zone used to evaluate the session (see below). Default: UTC | **Time zone** The `timeZone` option controls how timestamps are interpreted when checking session boundaries. Supported values: * **IANA region name** (recommended) - e.g. `"America/New_York"`, `"Europe/London"`, `"Asia/Tokyo"`. Handles Daylight Saving Time transitions automatically. * **UTC / GMT-prefixed offset** - e.g. `"UTC+3"`, `"GMT-5"`, `"GMT+0530"`. * **Pure offset** — e.g. `"+05:30"`, `"-08:00"`, `"Z"` (UTC). Fixed offsets do **not** observe DST, use an IANA region name if you need DST-aware behavior. Short abbreviations like `"EST"`, `"PST"`, `"MSK"`, `"IST"` are **not** accepted: they are ambiguous and would silently give wrong results. Use the full IANA name instead: `"America/New_York"`, `"Asia/Kolkata"`, etc. When the option is omitted, the session evaluates in UTC. **Returns** A [`session`](/reference/core/session) object. **Example** ```javascript // Free input const sess = input.session("Market Hours", "0930-1600:12345"); function onTick() { const inSession = sess.contains(time); spline(close, { title: "Price", color: inSession ? color.BLUE : color.GRAY }); } ``` ```javascript // Dropdown selector with predefined sessions const sess = input.session("Session", "0930-1600:12345", { options: [ "0930-1600:12345", // Regular "0400-2000:12345", // Extended ] }); function onTick() { const inSession = sess.contains(time); spline(close, { title: "Price", color: inSession ? color.BLUE : color.GRAY }); } ``` ```javascript // US Pre-Market session, DST-aware const pm = input.session("Pre-Market", "0400-0930:12345", { timeZone: "America/New_York" }); function onTick() { const inPm = pm.contains(time); spline(close, { title: "Price", color: inPm ? color.ORANGE : color.GRAY }); } ``` ```javascript // Multiple sessions active at once, sharing a market time zone selected via input.enum const tz = input.enum("Market", "New York", { "New York": "America/New_York", "London": "Europe/London", "Tokyo": "Asia/Tokyo" }); const pm = input.session("Pre-Market", "0400-0930:12345", {timeZone: tz}); const rth = input.session("Regular", "0930-1600:12345", {timeZone: tz}); const ah = input.session("After-Hours", "1600-2000:12345", {timeZone: tz}); function onTick() { let c; switch (true) { case pm.contains(time): c = color.ORANGE; break; case rth.contains(time): c = color.GREEN; break; case ah.contains(time): c = color.BLUE; break; default: c = color.GRAY; } spline(close, {title: "Price", color: c}); } ``` ```javascript // Single session chosen from predefined presets, with a market time zone const tz = input.enum("Market", "New York", { "New York": "America/New_York", "London": "Europe/London" }); const sess = input.session("Session", "0930-1600:12345", { timeZone: tz, options: [ "0400-0930:12345", // Pre-Market "0930-1600:12345", // Regular "1600-2000:12345" // After-Hours ] }); function onTick() { const inSession = sess.contains(time); spline(close, { title: "Price", color: inSession ? color.GREEN : color.GRAY }); } ``` ## input.enum() {#fun-input-enum} **Kind:** `func` Adds a dropdown to choose one of the given options. **Syntax** ``` input.enum(name, defLabel, options) → any ``` **Arguments** | Name | Type | Description | |----------|--------|----------------------------------------------------| | name | string | Unique identifier | | defLabel | string | Default selected label. Must be a key in `options` | | options | object | Enum options: label → value `{label: value, ...}` | **Returns** The value corresponding to the selected label. **Example** ```javascript // Functions const avgFn = input.enum("method", "SMA", { "SMA": ta.sma, "EMA": ta.ema, "WMA": ta.wma }); const length = input.double("length", 20); function onTick() { const avg = avgFn(close, length); spline(avg, {title: "MA"}); } ``` ```javascript // Numbers const length = input.enum("length", "Medium", { "Short": 10, "Medium": 20, "Long": 50 }); function onTick() { const sma = ta.sma(close, length); spline(sma, {title: "SMA"}); } ``` ```javascript // Colors (accessibility) const palette = input.enum("palette", "Default", { "Default": {bull: color.GREEN, bear: color.RED}, "Colorblind": {bull: color.BLUE, bear: color.ORANGE}, "Monochrome": {bull: color.WHITE, bear: color.GRAY} }); function onTick() { const bull = close > open; spline(close, {color: bull ? palette.bull : palette.bear}); } ``` ```javascript // Objects (presets) const preset = input.enum("preset", "Default", { "Default": {fast: 10, slow: 20}, "Scalping": {fast: 5, slow: 10}, "Swing": {fast: 20, slow: 50} }); function onTick() { const fastMA = ta.sma(close, preset.fast); const slowMA = ta.sma(close, preset.slow); spline(fastMA, {title: "Fast"}); spline(slowMA, {title: "Slow"}); } ``` --- --- url: /reference/core/location.md --- # Location {#module-location} **Kind:** `module` **Namespace:** `location` Placement constants that determine how a drawing is anchored vertically relatively to the current bar, to the chart pane, or to an explicit price. *** ## location.ABOVE\_BAR {#const-location-above-bar} **Kind:** `constant` **Value:** `ABOVE_BAR` Places the shape above the bar's high. *** ## location.BELOW\_BAR {#const-location-below-bar} **Kind:** `constant` **Value:** `BELOW_BAR` Places the shape below the bar's low. *** ## location.TOP {#const-location-top} **Kind:** `constant` **Value:** `TOP` Places the shape at the top of the visible pane, independent of price. *** ## location.BOTTOM {#const-location-bottom} **Kind:** `constant` **Value:** `BOTTOM` Places the shape at the bottom of the visible pane, independent of price. *** ## location.ABSOLUTE {#const-location-absolute} **Kind:** `constant` **Value:** `ABSOLUTE` Places the drawing at an explicit `y` coordinate (price value). Use this when the vertical position is a specific price rather than being anchored to a bar or the pane. --- --- url: /reference/outputs/output.md --- # Output {#module-output} **Kind:** `module` **Namespace:** `output` Outputs values without visualization. For most use cases, use [`spline`](./spline.md) which provides styling and chart integration. For per-bar background fill, use [`bgColor`](./bgColor.md). Each output maintains one value per bar. A new value is added when a new bar starts and replaced when the current bar updates. ## output() {#fun-output} **Kind:** `func` Outputs a named value. **Syntax** ``` output(name, value) → void ``` **Arguments** | Name | Type | Description | |-------|----------------|-------------------------------------| | name | string | Unique identifier for the output | | value | number, series | Value to output for the current bar | **Returns** `void` **Caveats** * Must be called inside [`onTick()`](/getting-started/quick-start#ontick-function), not in the [`init`](/getting-started/quick-start#init-section) section * Must be at the top level of [`onTick()`](/getting-started/quick-start#ontick-function), not inside conditionals or loops. This ensures the call count and order remain constant across ticks ::: danger Pitfall ```javascript function onTick() { if (bar.isConfirmed()) { output("close", close); // ❌ inside conditional } } ``` ::: **Example** ```javascript function onTick() { const sma = ta.sma(close, 20); const ema = ta.ema(close, 20); output("sma", sma); output("ema", ema); output("diff", sma - ema); output("close", close); } ``` --- --- url: /reference/outputs/outputs.md --- # Outputs {#section-outputs} Modules for outputting calculated results. ### [spline](./spline.md) Chart visualization with styling options. ### [shape](./shape.md) Per-bar symbol markers (arrows, tags, crosses) for signals, highlights, and short text labels. ### [output](./output.md) Numeric values without visualization. ### [bgColor](./bgColor.md) Per-bar background fill color (`bgColor`). ### [barColor](./barColor.md) Per-bar candle color (`barColor`). --- --- url: /getting-started/quick-start.md --- # Quick Start dxScript is a JavaScript-based language for creating custom technical analysis indicators with built-in support for time series, historical lookback, and technical analysis functions. ## Script Structure Every indicator has two sections: the [init section](#init-section) that runs once, and the [onTick function](#ontick-function) that runs for each bar. ```javascript // Init section — runs once const length = input.double("length", 20); // onTick function — runs for each tick function onTick() { const sma = ta.sma(close, length); spline(sma, {title: "SMA"}); } ``` ## Init Section {#init-section} All code outside `onTick()` executes **once** when the indicator is created, before processing any market data. **Use for:** * Declaring [input parameters](/reference/core/input) * Defining constants * Defining helper functions **Example** ```javascript // Input parameters const length = input.double("length", 20, {min: 1, max: 200}); const source = input.source("source", close); // Constants const OVERBOUGHT = 70; const OVERSOLD = 30; // Helper functions function inRange(value, min, max) { return value >= min && value <= max; } ``` **Caveats** * Price data (`open`, `high`, `low`, `close`, etc.) is not available. ## onTick Function {#ontick-function} The `onTick()` function is called **for each bar** (candle) in the data. **Use for:** * Accessing [market data](/reference/core/ts#built-in-series) (`open`, `high`, `low`, `close`, `volume`) * Creating [time series](/reference/core/ts) with `ts()` * Performing calculations * Producing outputs with `spline()` **Example** ```javascript function onTick() { const sma = ta.sma(close, length); const signal = ts(close > sma ? 1 : -1); spline(sma, {title: "SMA"}); spline(signal, {title: "Signal"}); } ``` ## Key Concepts ### Inputs Declare configurable parameters in the [init section](#init-section): ```javascript const length = input.double("length", 20, {min: 1, max: 200}); const useEma = input.bool("useEma", true); const source = input.source("source", close); ``` ### Time Series Store calculated values with history access: ```javascript function onTick() { const sma = ta.sma(close, length); // ta.* returns series const prev = sma[1]; // previous bar value const old = sma[10]; // 10 bars ago } ``` ### Outputs Plot values on the chart: ```javascript function onTick() { spline(close, {title: "Price", color: color.BLUE}); } ``` ## Complete Example Moving Average Crossover indicator: ```javascript // INIT const length = input.double("length", 20, {min: 1, max: 200}); // TICK function onTick() { const sma = ta.sma(close, length); const trend = close > sma ? color.GREEN : color.RED; spline(sma, {title: "SMA"}); spline(close, {title: "Price", color: trend}); } ``` ## Next Steps * Explore [Time Series](/reference/core/ts) in depth * Understand [Real-time Behavior](/concepts/realtime-behavior) * Learn about the [Runtime Environment](/concepts/runtime) * Browse the [Language Reference](/reference/core/core) --- --- url: /concepts/realtime-behavior.md --- # Real-time Behavior This section explains how indicators update in real time to help you write correct code. ## Bar Lifecycle A bar progresses through several states: ``` Historical bars: Bar 1 → Bar 2 → Bar 3 → Bar 4 → Bar 5 (confirmed, one tick each) Real-time bar: Bar 6 ↓ tick 1 (bar.isNew() = true) ↓ tick 2 (market data update) ↓ tick 3 (market data update) ↓ tick 4 (bar.isConfirmed() = true) ``` **Historical bars** — processed once, already confirmed. **Real-time bar** — receives multiple updates until confirmed. Each update calls `onTick()` again. ## Built-in Functions Functions from [`ts()`](/reference/core/ts#fun-ts) and [`ta.*`](/reference/ta) modules automatically reset on each tick. The current value `[0]` starts fresh, while historical values `[1]`, `[2]`, etc. remain stable: ```javascript function onTick() { const sma = ta.sma(close, 20); // recalculated each tick const trend = ts(); trend.set(close > sma ? 1 : -1); // [0] set fresh each tick // trend[1] — previous bar, stable // trend[2] — two bars ago, stable spline(trend, {title: "Trend"}); } ``` ``` Bar 6 tick 1: trend[0] = 1, trend[1] = -1 Bar 6 tick 2: trend[0] = 1, trend[1] = -1 ← [1] unchanged Bar 6 tick 3: trend[0] = -1, trend[1] = -1 ← [0] recalculated ``` ## Regular JS Variables Regular JS variables in the `init` section persist across `onTick()` calls: ```javascript // INIT let tickCount = 0; function onTick() { tickCount++; spline(tickCount, {title: "Ticks"}); } ``` ``` Bar 6 tick 1: tickCount = 1 Bar 6 tick 2: tickCount = 2 Bar 6 tick 3: tickCount = 3 ``` ## Historical vs Real-time Check processing mode with [`bar.isHistory()`](/reference/core/bar#fun-bar-ishistory): ```javascript function onTick() { const sma = ta.sma(close, 20); const lineColor = bar.isHistory() ? color.GRAY : color.BLUE; spline(sma, {title: "SMA", color: lineColor}); } ``` | Mode | `bar.isNew()` | `bar.isConfirmed()` | Updates per bar | |------------|----------------------|---------------------|-----------------| | Historical | `true` | `true` | 1 | | Real-time | `true` on first tick | `true` on last tick | multiple | ## Summary | Type | Behavior on bar updates | |---------------------|-----------------------------------------| | `ts()`, `ta.*` | Reset automatically, `[0]` recalculated | | JS variables | Persist, accumulate across ticks | | `bar.isNew()` | `true` only on first tick of bar | | `bar.isConfirmed()` | `true` only on final tick | --- --- url: /concepts/runtime.md --- # Runtime Environment dxScript executes with ECMAScript 2024 (ES15) support. ## Available JS Features Standard JavaScript features are fully supported: ```javascript // Arrow functions const double = x => x * 2; // Destructuring const {min, max} = Math; // Template literals const msg = `Price: ${close}`; // Array methods const values = [1, 2, 3].map(x => x * 2); // Spread operator const combined = [...arr1, ...arr2]; // Optional chaining const value = obj?.nested?.prop; // Nullish coalescing const fallback = value ?? defaultValue; ``` ## Not Available dxScript runs in a sandboxed environment without access to: * Timers (`setTimeout`, `setInterval`) * Network (`fetch`, `XMLHttpRequest`) * Module system (`import`, `require`, `module`, `exports`) * Node.js APIs (`process`, `Buffer`, `__dirname`, `__filename`) * Browser globals (`window`, `self`, `document`) ## Example ```javascript // INIT const threshold = 0.5; const labels = ["Low", "Medium", "High"]; function classify(value) { if (value < threshold) return labels[0]; if (value < threshold * 2) return labels[1]; return labels[2]; } // TICK function onTick() { const sma = ta.sma(close, 20); const distance = Math.abs(close - sma) / sma * 100; spline(sma, {title: "SMA"}); spline(distance, {title: classify(distance)}); } ``` --- --- url: /generated/samples.md --- # Samples Ready-to-use indicator scripts demonstrating dxScript features. ## Accumulation Distribution (ADL) ```javascript // https://devexperts.com/dxcharts/kb/docs/accumulationdistribution function onTick() { const moneyFlowMultiplier = (high[0] !== low[0]) ? ((close - low) - (high - close)) / (high - low) : 1.0; const moneyFlowVolume = moneyFlowMultiplier * volume; spline(ta.cum(moneyFlowVolume), {title: "adl", color: color.BLUE, overlay: false}); spline(0, {title: "zero", color: color.GRAY, overlay: false}); } ``` ## Aroon ```javascript // https://devexperts.com/dxcharts/kb/docs/aroon-indicator indicator({overlay: false}); const n = input("n", 25); const overBought = input("overBought", 70); const overSold = input("overSold", 30); function onTick() { const aroonUp = 100 * (n - ta.highestBar(high, n)) / n; const aroonDown = 100 * (n - ta.lowestBar(low, n)) / n; spline(aroonUp, {title: "aroonUp", color: color.GREEN}); spline(aroonDown, {title: "aroonDown", color: color.RED}); spline(overBought, {title: "overBought", color: color.GRAY}); spline(overSold, {title: "overSold", color: color.GRAY}); } ``` ## Average True Range (ATR) ```javascript // https://devexperts.com/dxcharts/kb/docs/average-true-range-atr const n = input("n", 14); function onTick() { spline(ta.atr(n), {title: "atr", color: color.BLUE, overlay: false}); } ``` ## Awesome Oscillator (AO) ```javascript // https://devexperts.com/dxcharts/kb/docs/awesome-oscillator-ao const fastLength = input("Fast Length", 5); const slowLength = input("Slow Length", 34); function onTick() { const mid = hl2; const ao = ta.sma(mid, fastLength) - ta.sma(mid, slowLength); spline(ao, {title: "awesome", color: color.BLUE, overlay: false}); spline(0, {title: "zero", color: color.GRAY, overlay: false}); } ``` ## Bollinger Bands (BB) ```javascript // https://devexperts.com/dxcharts/kb/docs/bollinger-bands const n = input("n", 20); const displace = input("displace", 0); const numDevUp = input("numDevUp", 2); const numDevDown = input("numDevDown", -2); const typical = input.source("typical", close); function onTick() { const midLineValue = ta.sma(typical, n); const sd = ta.stdev(typical, n); spline(midLineValue, {title: "midLine", color: color.BLUE}); spline(midLineValue + numDevUp * sd, {title: "upBand", color: color.RED}); spline(midLineValue + numDevDown * sd, {title: "lowBand", color: color.GREEN}); } ``` ## Chande Momentum Oscillator (CMO) ```javascript // https://devexperts.com/dxcharts/kb/docs/chandle-momentum-oscillator indicator({overlay: false}); const n = input("n", 20); function onTick() { const diff = close - close[1]; const inc = ts(Math.max(diff, 0)); const dec = ts(Math.max(diff * -1, 0)); const hasFullWindow = !isNaN(inc[n - 1]) && !isNaN(dec[n - 1]); const sumInc = ta.sum(inc, n); const sumDec = ta.sum(dec, n); const cmo = hasFullWindow ? (sumInc - sumDec) / (sumInc + sumDec) * 100 : NaN; spline(cmo, {title: "CMO", color: color.BLUE}); spline(50, {title: "UpperLevel", color: color.RED}); spline(-50, {title: "LowerLevel", color: color.GREEN}); spline(0, {title: "Zero", color: color.GRAY}); } ``` ## Commodity Channel Index (CCI) ```javascript // https://devexperts.com/dxcharts/kb/docs/commodity-channel-index indicator({overlay: false}); const n = input("n", 14); const overBought = input("overBought", 100); const overSold = input("overSold", -100); function onTick() { const cci = ta.cci(hlc3, n) spline(cci, {title: "cci", color: color.BLUE}); spline(overBought, {title: "OverBought", color: color.RED}); spline(overSold, {title: "OverSold", color: color.GREEN}); spline(0, {title: "Zero", color: color.GRAY}); } ``` ## Directional Movement Index(DMI) ```javascript // https://devexperts.com/dxcharts/kb/docs/directional-movement-index indicator({overlay: false}); const n = input("length", 20); function onTick() { const [dplus, dminus, adx] = ta.dmi(n); spline(dplus, {title: "D+", color: color.GREEN}); spline(dminus, {title: "D-", color: color.RED}); spline(adx, {title: "ADX", color: color.BLUE}); } ``` ## Double Exponential Moving Average ```javascript // https://devexperts.com/dxcharts/kb/docs/double-exponential-moving-average const n = input("n", 9); function onTick() { const c = close; const ema1 = ta.ema(c, n); const ema2 = ta.ema(ema1, n); spline(2 * ema1 - ema2, {title: "dema", color: color.BLUE}); } ``` ## Exponential Moving Average (EMA) ```javascript // https://devexperts.com/dxcharts/kb/docs/exponential-moving-average-ema const n = input("n", 9); const price = input.source("price", close) function onTick() { spline(ta.ema(price, n), {title: "ema", color: color.BLUE}); } ``` ## Linear Regression Curve ```javascript // https://devexperts.com/dxcharts/kb/docs/linear-regression-curve const price = input.source("price", close); const length = input("length", 20); function onTick() { const liRegression = ta.lreg(price, length); spline(liRegression, {title: "LinearRegression", color: color.GREEN}); } ``` ## Mass Index ```javascript // https://devexperts.com/dxcharts/kb/docs/mass-index indicator({overlay: false}); const n = input("n", 9); const sumLength = input("sumLength", 25); const triggerLevel = input("triggerLevel", 26.5); const setupLevel = input("setupLevel", 27); function onTick() { const diff = ts(high - low); const emaDiff1 = ta.ema(diff, n); const emaEmaDiff = ta.ema(emaDiff1, n); const emaEmaCoef = ts(emaDiff1 / emaEmaDiff); spline(ta.sum(emaEmaCoef, sumLength), {title: "mi", color: color.BLUE}); spline(triggerLevel, {title: "trigger", color: color.ORANGE}); spline(setupLevel, {title: "setup", color: color.RED}); } ``` ## Momentum ```javascript // https://devexperts.com/dxcharts/kb/docs/momentum const n = input("n", 12); function onTick() { const mom = close - close[n]; spline(mom, {title: "momentum", color: mom >= 0 ? color.GREEN : color.RED, overlay: false}); } ``` ## Money Flow (MFI) ```javascript // https://devexperts.com/dxcharts/kb/docs/money-flow-index-mfi indicator({overlay: false}); const n = input("n", 14); const overBought = input("overBought", 80); const overSold = input("overSold", 20); function onTick() { const tp = ts((high + low + close) / 3); const tpPrev = ts((high[1] + low[1] + close[1]) / 3); const positiveMoneyFlow = ts((tp > tpPrev) ? tp * volume : 0); const negativeMoneyFlow = ts((tp < tpPrev) ? tp * volume : 0); const sumPositiveMoneyFlow = ta.sum(positiveMoneyFlow, n); const sumNegativeMoneyFlow = ta.sum(negativeMoneyFlow, n); const mfidx = 100 - (100 / (1 + sumPositiveMoneyFlow / sumNegativeMoneyFlow)); spline(mfidx, {title: "MFidx", color: color.BLUE}); spline(overBought, {title: "OverBought", color: color.RED}); spline(overSold, {title: "OverSold", color: color.GREEN}); } ``` ## Moving Average Convergence Divergence (MACD) ```javascript // https://devexperts.com/dxcharts/kb/docs/moving-average-convergence-divergence-macd indicator({overlay: false}); const fastLen = input("fastLen", 12); const slowLen = input("slowLen", 26); const macdLen = input("macdLen", 9); const avgFn = input.enum("averageType", "EXPONENTIAL", { "EXPONENTIAL": ta.ema, "SMA": ta.sma, "WMA": ta.wma, "WILDERS": ta.wima, }); function onTick() { const series = close; const MACD = ts(ta.ema(series, fastLen) - ta.ema(series, slowLen)); const avg = avgFn(MACD, macdLen); const diff = MACD - avg; spline(MACD, {title: "MACD", color: color.BLUE}); spline(avg, {title: "avg", color: color.ORANGE}); spline(diff, {title: "diff", color: diff >= 0 ? color.GREEN : color.RED}); } ``` ## On Balance Volume (OBV) ```javascript // https://devexperts.com/dxcharts/kb/docs/on-balance-volume function onTick() { const diff = close - close[1]; const v = (diff > 0) ? volume : ((diff < 0) ? -volume : 0); spline(ta.cum(v), {title: "obv", color: color.BLUE, overlay: false}); } ``` ## Pivot High ```javascript // https://devexperts.com/dxcharts/kb/docs/pivot-points const left = input("left", 3); const right = input("right", 2); function onTick() { let pivotH = ta.pivotHigh(close, left, right); spline(pivotH, {title: "pivotHigh", color: color.RED, offset: -right}); } ``` ## Pivot Low ```javascript // https://devexperts.com/dxcharts/kb/docs/pivot-points const left = input("left", 3); const right = input("right", 2); function onTick() { let pivotL = ta.pivotLow(close, left, right); spline(pivotL, {title: "pivotLow", color: color.GREEN, offset: -right}); } ``` ## Price Oscillator ```javascript // https://devexperts.com/dxcharts/kb/docs/price-oscillator const fastLen = input("fastLen", 9); const slowLen = input("slowLen", 18); function onTick() { const emaFast = ta.ema(close, fastLen); const emaSlow = ta.ema(close, slowLen); const ppo = emaFast - emaSlow; spline(ppo, {title: "PriceOscillator", color: ppo >= 0 ? color.GREEN : color.RED, overlay: false}); spline(0, {title: "Zero", color: color.GRAY, overlay: false}); } ``` ## Price Volume Trend (PVT) ```javascript // https://devexperts.com/dxcharts/kb/docs/price-and-volume-trend function onTick() { const prevClose = close[1]; const currentClose = close; const v = (currentClose - prevClose) / prevClose * volume; spline(ta.cum(v), {title: "pvt", color: color.BLUE, overlay: false}); } ``` ## Rate of Change (ROC) ```javascript // https://devexperts.com/dxcharts/kb/docs/rate-of-change const n = input("n", 12); function onTick() { const prevClose = close[n]; const currentClose = close; const roc = ((currentClose - prevClose) / prevClose) * 100; spline(roc, {title: "roc", color: roc >= 0 ? color.GREEN : color.RED, overlay: false}); spline(0, {title: "zero", color: color.GRAY, overlay: false}); } ``` ## Relative Strength Index (RSI) ```javascript // https://devexperts.com/dxcharts/kb/docs/relative-strength-index-rsi indicator({overlay: false}) const n = input("n", 14); const overBought = input("overBought", 70); const overSold = input("overSold", 30); function onTick() { spline(ta.rsi(close, n), {title: "RSI", color: color.BLUE}); spline(overBought, {title: "overBought", color: color.RED}); spline(overSold, {title: "overSold", color: color.GREEN}); } ``` ## Relative Vigor Index (RVI) ```javascript // https://devexperts.com/dxcharts/kb/docs/relative-vigor-index function onTick() { const nominator = close - open; const denominator = high - low; const rvi = denominator !== 0 ? nominator / denominator: 0; spline(rvi, {title: "rvi", color: rvi >= 0 ? color.GREEN : color.RED, overlay: false}); } ``` ## Simple Moving Average ```javascript // https://devexperts.com/dxcharts/kb/docs/simple-moving-average-sma const n = input("n", 9); const price = input.source("price", open) function onTick() { spline(ta.sma(price, n), {title: "sma", color: color.BLUE}); } ``` ## Smoothed Moving Average ```javascript // https://devexperts.com/dxcharts/kb/docs/smoothed-simple-moving-average const n = input("n", 9); function onTick() { spline(ta.wima(close, n), {title: "SMMA", color: color.BLUE}); } ``` ## SuperTrend ```javascript // https://devexperts.com/dxcharts/kb/docs/super-trend const factor = input("factor", 3.0); const atrPeriod = input("atrPeriod", 10); function onTick() { const [st, dir] = ta.supertrend(factor, atrPeriod); spline(dir < 0 ? st : NaN, {title: "Up direction", color: color.GREEN, style: spline.STYLE_LINE_BREAK}); spline(dir > 0 ? st : NaN, {title: "Down direction", color: color.RED, style: spline.STYLE_LINE_BREAK}); spline(hl2, {title: "HL2 Line", color: color.GRAY}) } ``` ## Triple Exponential Average (TRIX) ```javascript // https://devexperts.com/dxcharts/kb/docs/triple-exponential-average const n = input("n", 9); function trix(x, n) { const ema1 = ta.ema(x, n); const ema2 = ta.ema(ema1, n); return ta.ema(ema2, n); } function onTick() { const logPrice = ts(Math.log(close)); const logPrevPrice = ts(Math.log(close[1])); const triple = trix(logPrice, n); const triplePrev = trix(logPrevPrice, n); const trixValue = (triple - triplePrev) * 10000; spline(trixValue, {title: "TRIX", color: trixValue >= 0 ? color.GREEN : color.RED, overlay: false}); } ``` ## Triple Exponential Moving Average (TEMA) ```javascript // https://devexperts.com/dxcharts/kb/docs/triple-exponential-moving-average const n = input("n", 9); function onTick() { const series = close; const ema1 = ta.ema(series, n); const ema2 = ta.ema(ema1, n); const ema3 = ta.ema(ema2, n); spline(3 * ema1 - 3 * ema2 + ema3, {title: "tema", color: color.BLUE}); } ``` ## True Strength Index (TSI) ```javascript // https://devexperts.com/dxcharts/kb/docs/true-strength-index indicator({overlay: false}); const price = input.source("source", close) const longLength = input("longLength", 25); const shortLength = input("shortLength", 13); const signalLength = input("signalLength", 8); function doubleEma(x, longLength, shortLength) { const ema1 = ta.ema(x, longLength); return ta.ema(ema1, shortLength); } function onTick() { const momentum = ts(price - price[1]); const averageOfAverage = doubleEma(momentum, longLength, shortLength); const absMomentum = ts(Math.abs(momentum)); const absEmaEma = doubleEma(absMomentum, longLength, shortLength); const tsi = ts(averageOfAverage / absEmaEma * 100); spline(tsi, {title: "tsi", color: color.BLUE}); spline(ta.ema(tsi, signalLength), {title: "signal", color: color.ORANGE}); spline(0, {title: "zero", color: color.GRAY}); } ``` ## Weighted Moving Average ```javascript // https://devexperts.com/dxcharts/kb/docs/weighted-moving-average-wma const n = input("n", 9); const price = input("price", open); function onTick() { spline(ta.wma(price, n), {title: "wma", color: color.BLUE}); } ``` ## Williams Alligator ```javascript // https://devexperts.com/dxcharts/kb/docs/williams-alligator const jawLen = input("jawLen", 13); const jawDisplace = input("jawDisplace", 8); const teethLen = input("teethLen", 8); const teethDisplace = input("teethDisplace", 5); const lipsLen = input("lipsLen", 5); const lipsDisplace = input("lipsDisplace", 3); function onTick() { const median = ts((high + low) / 2); const lips = ta.wima(median, lipsLen); const teeth = ta.wima(median, teethLen); const jaw = ta.wima(median, jawLen); spline(lips, {title: "Lips", color: color.LIME, offset: lipsDisplace}); spline(teeth, {title: "Teeth", color: color.RED, offset: teethDisplace}); spline(jaw, {title: "Jaw", color: color.BLUE, offset: jawDisplace}); } ``` --- --- url: /reference/core/session.md --- # Session {#module-session} **Kind:** `module` **Namespace:** `session` Provides functions for working with trading sessions and time-based filtering. ## Overview A session defines a time window with optional day-of-week filtering. Sessions are useful for restricting calculations to specific market hours or trading periods. Sessions are created via [`input.session()`](/reference/core/input#fun-input-session) and represented as a `session` object. Session boundaries are evaluated in UTC by default. Pass a `timeZone` option to [`input.session()`](/reference/core/input#fun-input-session) to interpret the session in a specific time zone (e.g. `"America/New_York"` for US regular hours). IANA region names are DST-aware; fixed offsets like `"UTC+3"` are not. **Format** ``` HHMM-HHMM HHMM-HHMM:days ``` | Part | Description | Example | |--------|--------------------------------------------|-------------------| | `HHMM` | Time in 24-hour format | `0930` = 9:30 AM | | `days` | Days of week (ISO 8601): 1=Mon, ..., 7=Sun | `12345` = Mon-Fri | **Day numbers (ISO 8601)** | Number | Day | |--------|-----------| | 1 | Monday | | 2 | Tuesday | | 3 | Wednesday | | 4 | Thursday | | 5 | Friday | | 6 | Saturday | | 7 | Sunday | **Examples of session strings** | String | Meaning | |---------------------|----------------------------------------| | `"0930-1600"` | 9:30 AM - 4:00 PM, every day | | `"0930-1600:12345"` | 9:30 AM - 4:00 PM, Mon-Fri | | `"0000-0000"` | Full 24 hours | ## Session Object {#object-session} The `session` object represents a time window and provides methods for checking if a given time falls within it. ### session.contains() {#method-session-contains} **Kind:** `method` Checks if a time is within the session. **Syntax** ``` session.contains() → bool session.contains(time) → bool ``` **Arguments** | Name | Type | Default | Description | |------|-------|---------|----------------------------------------------------| | time | long? | `time` | Timestamp in milliseconds. Defaults to current bar | **Returns** `true` if the time is within the session, `false` otherwise. **Example** ```javascript const marketHours = input.session("Market Hours", "0930-1600:12345"); function onTick() { const inSession = marketHours.contains(); spline(close, { title: "Price", color: inSession ? color.BLUE : color.GRAY }); } ``` --- --- url: /reference/outputs/shape.md --- # Shape {#module-shape} **Kind:** `module` **Namespace:** `shape` Plots a symbol at a price level for each bar, handy for signals, highlights, and short labels. Use `style`, `location`, `color`, and optional `text` to control how it looks ([Styles](#shape-styles), [Location](/reference/core/location)). Each shape series maintains one value per bar. A new value is added when a new bar starts and replaced when the current bar updates. ## shape() {#fun-shape} **Kind:** `func` Plots one symbol at the given value for each active shape call. **Syntax** ``` shape(value) → void shape(value, {title, style, offset, location, overlay, color, textColor, text}) → void ``` **Arguments** | Name | Type | Description | |-------|----------------|-------------------------| | value | number, series | Value or series to plot | **Options** Static (captured on the first call, ignored afterwards): | Name | Type | Default | Description | |-----------|--------------------------------------|----------------------|-----------------------------------------------------------------------| | title? | string | `null` | Display name in the legend | | style? | const | `shape.STYLE_XCROSS` | Visual style (see [Styles](#shape-styles)) | | offset? | int | `0` | Horizontal offset in bars (positive = right) | | location? | [location](/reference/core/location) | `location.ABOVE_BAR` | Vertical placement (e.g. `location.ABOVE_BAR`, `location.BELOW_BAR`) | | overlay? | boolean | `true` | Draw on the main price chart (`true`) or in a separate pane (`false`) | Dynamic (can change per bar): | Name | Type | Default | Description | |------------|--------------------------------|---------|----------------------------------------------------------------------| | color? | [color](/reference/core/color) | `null` | Shape color | | textColor? | [color](/reference/core/color) | `null` | Text label color (independent of the shape color) | | text? | string | `""` | Text label. Passing `null` or omitting is the same as `""` (no text) | **Returns** `void` **Caveats** * Must be called inside [`onTick()`](/getting-started/quick-start#ontick-function), not in the [`init`](/getting-started/quick-start#init-section) section * Must be at the top level of [`onTick()`](/getting-started/quick-start#ontick-function), not inside conditionals or loops. This ensures the call count and order remain constant across ticks ::: danger Pitfall ```javascript function onTick() { if (bar.isConfirmed()) { shape(close); // ❌ inside conditional } } ``` ::: **Example** ```javascript const length = input.double("length", 20); function onTick() { const sma = ta.sma(close, length); shape(close > sma ? high : NaN, { title: "Above SMA", style: shape.STYLE_ARROW_UP, location: location.ABOVE_BAR, color: color.LIME, }); } ``` ## Styles {#shape-styles} Visual style constants for [shape()](#fun-shape) output. Use with the `style` option. *** ### shape.STYLE\_TAG {#const-shape-tag} **Kind:** `constant` **Value:** `TAG` Tag shape at the data point. *** ### shape.STYLE\_ARROW\_UP {#const-shape-arrow-up} **Kind:** `constant` **Value:** `ARROW_UP` Upward arrow at the data point. *** ### shape.STYLE\_ARROW\_DOWN {#const-shape-arrow-down} **Kind:** `constant` **Value:** `ARROW_DOWN` Downward arrow at the data point. *** ### shape.STYLE\_XCROSS {#const-shape-xcross} **Kind:** `constant` **Value:** `XCROSS` Diagonal cross (X) at the data point. *** ### shape.STYLE\_CROSS {#const-shape-cross} **Kind:** `constant` **Value:** `CROSS` Plus cross (+) at the data point. *** ### shape.STYLE\_BEACON {#const-shape-beacon} **Kind:** `constant` **Value:** `BEACON` Beacon (diamond-style) marker at the data point. *** ### shape.STYLE\_CIRCLE {#const-shape-circle} **Kind:** `constant` **Value:** `CIRCLE` Circle at the data point. *** See [`location`](/reference/core/location) for the full list of vertical placement constants. Common choices for `shape()` are `location.ABOVE_BAR` and `location.BELOW_BAR`. --- --- url: /reference/outputs/spline.md --- # Spline {#module-spline} **Kind:** `module` **Namespace:** `spline` Outputs values to the chart. Supports lines, histograms, areas, and other visual styles. For bar background fill only, see [`bgColor`](./bgColor.md). Each spline maintains one value per bar. A new value is added when a new bar starts and replaced when the current bar updates. ## spline() {#fun-spline} **Kind:** `func` Outputs a value to the chart as a line or other visual element. **Syntax** ``` spline(value) → void spline(value, {title, style, offset, color, overlay}) → void ``` **Arguments** | Name | Type | Description | |-------|----------------|-------------------------| | value | number, series | Value or series to plot | **Options** Static (ignored after the first call): | Name | Type | Default | Description | |----------|---------|---------------------|---------------------------------------------------------------------| | title? | string | `null` | Display name in the legend | | style? | const | `spline.STYLE_LINE` | Visual style (see [Styles](#spline-styles)) | | offset? | int | `0` | Horizontal offset in bars (positive = right) | | overlay? | boolean | `false` | If `true`, draws on the main price chart instead of a separate pane | Dynamic (can change per bar): | Name | Type | Default | Description | |--------|--------------------------------|---------|-------------| | color? | [color](/reference/core/color) | `null` | Line color | **Returns** `void` **Caveats** * Must be called inside [`onTick()`](/getting-started/quick-start#ontick-function), not in the [`init`](/getting-started/quick-start#init-section) section * Must be at the top level of [`onTick()`](/getting-started/quick-start#ontick-function), not inside conditionals or loops. This ensures the call count and order remain constant across ticks ::: danger Pitfall ```javascript function onTick() { if (bar.isConfirmed()) { spline(close); // ❌ inside conditional } } ``` ::: **Example** ```javascript const length = input.double("length", 20); function onTick() { const sma = ta.sma(close, length); // Basic output spline(sma, {title: "SMA"}); // Static type + dynamic color spline(close, { title: "Trend", style: spline.STYLE_STEPLINE, color: close > sma ? color.GREEN : color.RED, overlay: true }); // Histogram type spline(volume, {title: "Volume", style: spline.STYLE_HISTOGRAM}); } ``` ## Styles {#spline-styles} Visual style constants for [spline()](#fun-spline) output. Use with the `style` option. Styles are grouped by family: for each line-like base (`LINE`, `STEPLINE`, `LINE_BREAK`), the solid stroke comes first, then the dashed variant, then the variant with point markers. Other chart types follow, then `AREA_BREAK` and `STEPLINE_BREAK`. *** ### spline.STYLE\_LINE {#const-spline-line} **Kind:** `constant` **Value:** `LINE` Standard line connecting all data points. *** ### spline.STYLE\_LINE\_DASHED {#const-spline-line-dashed} **Kind:** `constant` **Value:** `LINE_DASHED` Same as [`STYLE_LINE`](#const-spline-line), but the stroke is dashed instead of solid. *** ### spline.STYLE\_LINE\_POINTS {#const-spline-line-points} **Kind:** `constant` **Value:** `LINE_POINTS` Same as [`STYLE_LINE`](#const-spline-line), but each data point is drawn with a visible marker. *** ### spline.STYLE\_STEPLINE {#const-spline-stepline} **Kind:** `constant` **Value:** `STEPLINE` Step line (horizontal then vertical). *** ### spline.STYLE\_STEPLINE\_DASHED {#const-spline-stepline-dashed} **Kind:** `constant` **Value:** `STEPLINE_DASHED` Same as [`STYLE_STEPLINE`](#const-spline-stepline), but the stroke is dashed instead of solid. *** ### spline.STYLE\_STEPLINE\_POINTS {#const-spline-stepline-points} **Kind:** `constant` **Value:** `STEPLINE_POINTS` Same as [`STYLE_STEPLINE`](#const-spline-stepline), but each data point is drawn with a visible marker. *** ### spline.STYLE\_HISTOGRAM {#const-spline-histogram} **Kind:** `constant` **Value:** `HISTOGRAM` Vertical bars from zero to value. *** ### spline.STYLE\_CROSS {#const-spline-cross} **Kind:** `constant` **Value:** `CROSS` Cross markers at each data point. *** ### spline.STYLE\_AREA {#const-spline-area} **Kind:** `constant` **Value:** `AREA` Filled area from zero to line. *** ### spline.STYLE\_COLUMNS {#const-spline-columns} **Kind:** `constant` **Value:** `COLUMNS` Column bars at each data point. *** ### spline.STYLE\_CIRCLES {#const-spline-circles} **Kind:** `constant` **Value:** `CIRCLES` Circle markers at each data point. *** ### spline.STYLE\_LINE\_BREAK {#const-spline-line-break} **Kind:** `constant` **Value:** `LINE_BREAK` Line with gaps on `NaN` values. *** ### spline.STYLE\_LINE\_BREAK\_DASHED {#const-spline-line-break-dashed} **Kind:** `constant` **Value:** `LINE_BREAK_DASHED` Like [`STYLE_LINE_BREAK`](#const-spline-line-break): line with gaps on `NaN` values, but the stroke is dashed instead of solid. *** ### spline.STYLE\_LINE\_BREAK\_POINTS {#const-spline-line-break-points} **Kind:** `constant` **Value:** `LINE_BREAK_POINTS` Like [`STYLE_LINE_BREAK`](#const-spline-line-break): line with gaps on `NaN` values, but each data point is drawn with a visible marker. *** ### spline.STYLE\_AREA\_BREAK {#const-spline-area-break} **Kind:** `constant` **Value:** `AREA_BREAK` Area with gaps on `NaN` values. *** ### spline.STYLE\_STEPLINE\_BREAK {#const-spline-stepline-break} **Kind:** `constant` **Value:** `STEPLINE_BREAK` Step line with gaps on `NaN` values. --- --- url: /reference/ta.md --- # Technical Analysis {#module-ta} **Kind:** `module` **Namespace:** `ta` Provides functions for technical analysis, including moving averages, statistical calculations, and series manipulations. ## ta.sum() {#fun-ta-sum} **Kind:** `func` Calculates the sum of the last `length` values. **Syntax** ``` ta.sum(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the sum. **Notes** * `NaN` values are ignored * Returns `NaN` until `length` bars are available **Example** ```javascript function onTick() { const totalVolume = ta.sum(volume, 20); spline(totalVolume, {title: "20-bar Volume Sum"}); } ``` ## ta.cum() {#fun-ta-cum} **Kind:** `func` Calculates the cumulative sum of a series. **Syntax** ``` ta.cum(source) → series ta.cum(number) → series ``` **Arguments** | Name | Type | Description | |--------|----------------|------------------------| | source | series, double | Source series or value | **Returns** A series containing the cumulative sum. **Notes** * `NaN` values are treated as `0` **Example** ```javascript function onTick() { const cumVolume = ta.cum(volume); spline(cumVolume, {title: "Cumulative Volume"}); } ``` ## ta.sma() {#fun-ta-sma} **Kind:** `func` Calculates the Simple Moving Average (SMA). **Syntax** ``` ta.sma(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the SMA. **Notes** * `NaN` values are ignored; the average is calculated over non-NaN values only * Returns `NaN` until `length` bars are available **Example** ```javascript function onTick() { const sma20 = ta.sma(close, 20); spline(sma20, {title: "SMA 20"}); } ``` ## ta.ema() {#fun-ta-ema} **Kind:** `func` Calculates the Exponential Moving Average (EMA). **Syntax** ``` ta.ema(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the EMA. **Notes** * Returns `NaN` if the current source value is `NaN` * Returns `NaN` until `length` bars are available * Uses SMA for initial `length` bars, then switches to EMA formula **Example** ```javascript function onTick() { const ema20 = ta.ema(close, 20); spline(ema20, {title: "EMA 20"}); } ``` ## ta.wma() {#fun-ta-wma} **Kind:** `func` Calculates the Weighted Moving Average (WMA). **Syntax** ``` ta.wma(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the WMA. **Notes** * `NaN` values are ignored; weights are assigned by position, not by value count * Returns `NaN` until `length` bars are available **Example** ```javascript function onTick() { const wma20 = ta.wma(close, 20); spline(wma20, {title: "WMA 20"}); } ``` ## ta.wima() {#fun-ta-wima} **Kind:** `func` Calculates the Wilder's Smoothing Moving Average (WIMA). **Syntax** ``` ta.wima(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the WIMA. **Notes** * Returns `NaN` if the current source value is `NaN` * Returns `NaN` until `length` bars are available * Uses SMA for initial `length` bars, then switches to WIMA formula **Example** ```javascript function onTick() { const wima20 = ta.wima(close, 20); spline(wima20, {title: "WIMA 20"}); } ``` ## ta.highest() {#fun-ta-highest} **Kind:** `func` Returns the highest value in the last `length` bars. **Syntax** ``` ta.highest(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the highest value. **Notes** * `NaN` values are ignored * Returns `NaN` until `length` bars are available * Returns `NaN` if all values in the window are `NaN` **Example** ```javascript function onTick() { const high20 = ta.highest(high, 20); spline(high20, {title: "20-bar High"}); } ``` ## ta.highestBar() {#fun-ta-highest-bar} **Kind:** `func` Returns the bar offset to the highest value in the last `length` bars. **Syntax** ``` ta.highestBar(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the bar offset to the highest value (0 = current bar). **Notes** * `NaN` values are ignored * Returns `NaN` until `length` bars are available * Returns `NaN` if all values in the window are `NaN` **Example** ```javascript function onTick() { const offset = ta.highestBar(high, 20); const highestValue = isNaN(offset) ? NaN : high[offset]; spline(highestValue, {title: "20-bar High"}); } ``` ## ta.lowest() {#fun-ta-lowest} **Kind:** `func` Returns the lowest value in the last `length` bars. **Syntax** ``` ta.lowest(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the lowest value. **Notes** * `NaN` values are ignored * Returns `NaN` until `length` bars are available * Returns `NaN` if all values in the window are `NaN` **Example** ```javascript function onTick() { const low20 = ta.lowest(low, 20); spline(low20, {title: "20-bar Low"}); } ``` ## ta.lowestBar() {#fun-ta-lowest-bar} **Kind:** `func` Returns the bar offset to the lowest value in the last `length` bars. **Syntax** ``` ta.lowestBar(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the bar offset to the lowest value (0 = current bar). **Notes** * `NaN` values are ignored * Returns `NaN` until `length` bars are available * Returns `NaN` if all values in the window are `NaN` **Example** ```javascript function onTick() { const offset = ta.lowestBar(low, 20); const lowestValue = isNaN(offset) ? NaN : low[offset]; spline(lowestValue, {title: "20-bar Low"}); } ``` ## ta.pivotHigh() {#fun-ta-pivot-high} **Kind:** `func` Returns the pivot high value if found. **Syntax** ``` ta.pivotHigh(source, left, right) → series ``` **Arguments** | Name | Type | Description | |--------|--------|-----------------------------| | source | series | Source series | | left | int | Number of bars to the left | | right | int | Number of bars to the right | **Returns** The pivot high value, or `NaN` if not found. **Notes** * Returns `NaN` until `left + right + 1` bars are available * Returns `NaN` if no pivot found at current position * For plotting, pass `offset: -right` to `spline()` (or another drawing call that supports `offset`) so the marker appears on the candle where the pivot actually occurred, not on the latest bar. **Example** ```javascript function onTick() { const right = 5; const ph = ta.pivotHigh(high, 5, right); spline(ph, {title: "Pivot High", style: spline.STYLE_CIRCLES, offset: -right}); } ``` ## ta.pivotLow() {#fun-ta-pivot-low} **Kind:** `func` Returns the pivot low value if found. **Syntax** ``` ta.pivotLow(source, left, right) → series ``` **Arguments** | Name | Type | Description | |--------|--------|-----------------------------| | source | series | Source series | | left | int | Number of bars to the left | | right | int | Number of bars to the right | **Returns** The pivot low value, or `NaN` if not found. **Notes** * Returns `NaN` until `left + right + 1` bars are available * Returns `NaN` if no pivot found at current position * For plotting, pass `offset: -right` to `spline()` (or another drawing call that supports `offset`) so the marker appears on the candle where the pivot actually occurred, not on the latest bar. **Example** ```javascript function onTick() { const right = 5; const pl = ta.pivotLow(low, 5, right); spline(pl, {title: "Pivot Low", style: spline.STYLE_CIRCLES, offset: -right}); } ``` ## ta.tr() {#fun-ta-tr} **Kind:** `func` Calculates the True Range (TR) for the current bar. **Syntax** ``` ta.tr() → series ``` **Arguments** None **Returns** A series containing the True Range value for the current bar. **Notes** * True Range is the maximum of `(high-low, abs(high - close[1]), abs(low-close[1]))` * Might return `NaN` if some of the above sources are not available **Example** ```javascript function onTick() { const tr = ta.tr(); spline(tr, {title: "True Range"}); } ``` ## ta.atr() {#fun-ta-atr} **Kind:** `func` Calculates the Average True Range (ATR) over a specified period. **Syntax** ``` ta.atr(length) → series ``` **Arguments** | Name | Type | Description | |--------|------|--------------------| | length | int | Number of bars | **Returns** A series containing the Average True Range(ATR) value for the current bar. **Notes** * ATR is calculated as the Wilder's Moving Average (WIMA) of the True Range (TR) over the specified period * You can use `ta.tr()` to get the True Range series for custom ATR calculations * Returns `NaN` until `length` bars are available **Example** Default ATR calculation: ```javascript function onTick() { const atr14 = ta.atr(14); spline(atr14, {title: "ATR (14)"}); } ``` ATR using Simple Moving Average instead of WIMA: ```javascript function onTick() { const tr = ta.tr(); const atr14 = ta.sma(tr, 14); spline(atr14, {title: "ATR (14) with SMA"}); } ``` ## ta.wpr() {#fun-ta-wpr} **Kind:** `func` Calculates the Williams Percent Range (%R) for the current bar. **Syntax** ``` ta.wpr(period) → series ``` **Arguments** | Name | Type | Description | |--------|------|----------------| | period | int | Number of bars | **Returns** A series containing the %R values. **Notes** * Formula: `%R = (Close - Highest High) / (Highest High - Lowest Low) × 100` * Uses an expanding window: produces values from the first bar, widening the lookback until `period` bars are available * Returns `NaN` if the highest high equals the lowest low (zero-range bar) **Example** ```javascript function onTick() { const wr = ta.wpr(14); spline(wr, {title: "Williams %R (14)"}); } ``` ## ta.rsi() {#fun-ta-rsi} **Kind:** `func` Calculates the Relative Strength Index (RSI) for the current bar. **Syntax** ``` ta.rsi(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the RSI values. **Notes** * Formula: `change = source[0] - source[1]`; `RSI = 50 × (1 + wima(change) / wima(|change|))` * Uses Wilder's smoothing (WIMA) for both average gain and average loss components * Returns `NaN` until `length + 1` bars are available * Returns `NaN` when the smoothed absolute change is zero **Example** ```javascript function onTick() { const rsi = ta.rsi(close, 14); spline(rsi, {title: "RSI (14)", color: color.BLUE}); } ``` ## ta.sar() {#fun-ta-sar} **Kind:** `func` Calculates the Parabolic Stop and Reverse (SAR) for the current bar. **Syntax** ``` ta.sar() → series ta.sar(start, increment, maximum) → series ``` **Arguments** | Name | Type | Description | |-----------|--------|--------------------------------------------------| | start | double | Initial acceleration factor (default: `0.02`) | | increment | double | Acceleration factor increment (default: `0.02`) | | maximum | double | Maximum acceleration factor (default: `0.2`) | **Returns** A series containing the SAR values. **Notes** * Values are clamped to the previous two bars' extremes and seeded on the second bar from the close direction. * The no-argument form uses defaults: start `0.02`, increment `0.02`, maximum `0.2` * Returns `NaN` on the first bar (no prior bar to seed the trend) **Example** ```javascript function onTick() { const sar = ta.sar(); spline(sar, {title: "SAR", style: spline.STYLE_CIRCLES, color: color.YELLOW}); } ``` ## ta.supertrend() {#fun-ta-supertrend} **Kind:** `func` Calculates the SuperTrend indicator line and trend direction for the current bar. **Syntax** ``` ta.supertrend(factor, atrPeriod) → [line, direction] ``` **Arguments** | Name | Type | Description | |-----------|--------|--------------------------------------| | factor | double | ATR multiplier | | atrPeriod | int | ATR period (Wilder's smoothing/WIMA) | **Returns** An array of two series: `[line, direction]`. * `line`: SuperTrend line value * `direction`: Trend direction — `-1` for uptrend, `1` for downtrend **Notes** * ATR is calculated as WIMA of True Range (`ta.atr` path) * Upper and lower bands are ratcheted using the previous bar's values * Returns `NaN` until enough bars are available for ATR calculation **Example** ```javascript function onTick() { const [st, dir] = ta.supertrend(3.0, 10); spline(dir < 0 ? st : NaN, {title: "Up direction", color: color.GREEN, style: spline.STYLE_LINE_BREAK}); spline(dir > 0 ? st : NaN, {title: "Down direction", color: color.RED, style: spline.STYLE_LINE_BREAK}); } ``` ## ta.stdev() {#fun-ta-stdev} **Kind:** `func` Calculates the Standard Deviation of the last `length` values. **Syntax** ``` ta.stdev(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the standard deviation for the current bar. **Notes** * Uses the population standard deviation formula: * `stdev = sqrt( ( Σ(x^2) - (Σx)^2 / n ) / n )`, where `n = length` * Returns `NaN` until `length` bars are available * If any value in the lookback window is `NaN`, the result is `NaN` **Example** ```javascript function onTick() { const sd20 = ta.stdev(close, 20); spline(sd20, {title: "StdDev (20)", color: color.RED}); } ``` ## ta.dmi() {#fun-ta-dmi} **Kind:** `func` Calculates the Directional Movement Index (DMI) indicators: Plus Directional Indicator (+DI), Minus Directional Indicator (-DI), and Average Directional Index (ADX). **Syntax** ``` ta.dmi(length) → [plusDI, minusDI, adx] ``` **Arguments** | Name | Type | Description | |--------|------|--------------------| | length | int | Number of bars | **Returns** An array of three series: `[plusDI, minusDI, adx]`. * `plusDI`: Plus Directional Indicator series * `minusDI`: Minus Directional Indicator series * `adx`: Average Directional Index series **Notes** * DMI is a trend strength indicator composed of +DI, -DI, and ADX * All series propagate `NaN` if any required value is not available * Returns `NaN` until enough bars are available for the calculation * +DI and -DI are calculated using Wilder's smoothing (WIMA) * ADX is the smoothed average of the DX (difference index) **Example** ```javascript function onTick() { const [plusDI, minusDI, adx] = ta.dmi(14); spline(plusDI, {title: "+DI", color: color.GREEN}); spline(minusDI, {title: "-DI", color: color.RED}); spline(adx, {title: "ADX", color: color.BLUE}); } ``` ## ta.lreg() {#fun-ta-lreg} **Kind:** `func` Calculates the value of the linear regression line at the most recent bar over a rolling window. **Syntax** ``` ta.lreg(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the value of the linear regression line at the most recent bar for each window. **Notes** * Returns `NaN` until `length` bars are available * If any source value in the window is `NaN`, the result is `NaN` for that bar * The result is the value of the regression line at the most recent (rightmost) bar in the window **Example** ```javascript function onTick() { const lreg = ta.lreg(close, 20); spline(lreg, {title: "Linear Regression (20)"}); } ``` ## ta.dev() {#fun-ta-dev} **Kind:** `func` Calculates the Mean Absolute Deviation (MAD) of the last `length` values. **Syntax** ``` ta.dev(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the mean absolute deviation. **Notes** * Uses the population MAD formula: `dev = Σ|x - mean| / length`, where `mean = sma(source, length)` * Returns `NaN` until `length` bars are available * If any value in the loopback window is `NaN`, the result is `NaN` **Example** ```javascript function onTick() { const deviation = ta.dev(close, 20); spline(deviation, {title: "Mean Abs Deviation (20)"}); } ``` ## ta.cci() {#fun-ta-cci} **Kind:** `func` Calculates the Commodity Channel Index (CCI) for the current bar. **Syntax** ``` ta.cci(source, length) → series ``` **Arguments** | Name | Type | Description | |--------|--------|----------------| | source | series | Source series | | length | int | Number of bars | **Returns** A series containing the CCI value for the current bar. **Notes** * CCI is calculated using the formula: `CCI = (source - sma(source, length)) / (0.015 * dev(source, length))` * If any value in the loopback window is `NaN`, the result is `NaN` **Example** ```javascript function onTick() { const cci = ta.cci(hlc3, 20); spline(cci, {title: "CCI (20)"}); } ``` ## ta.cross() {#fun-ta-cross} **Kind:** `func` Detects whether two series crossed each other on the current bar (in either direction). **Syntax** ``` ta.cross(source1, source2) → bool ta.cross(source1, constant) → bool ``` **Arguments** | Name | Type | Description | |----------|----------------|-------------------------------------| | source1 | series | First data series | | source2 | series, number | Second data series or constant line | **Returns** `true` if the two series crossed each other on the current bar, otherwise `false`. **Notes** * Equivalent to `ta.crossover(source1, source2) || ta.crossunder(source1, source2)` * Returns `false` if either series has fewer than two bars or any required value is `NaN` **Example** RSI midline cross — highlight when RSI crosses the 50 level in either direction: ```javascript indicator({overlay: false}); const length = input("length", 14); function onTick() { const rsi = ta.rsi(close, length); spline(rsi, {title: "RSI", color: color.BLUE}); spline(70, {title: "Overbought", color: color.RED}); spline(30, {title: "Oversold", color: color.GREEN}); spline(ta.cross(rsi, 50) ? rsi : NaN, {title: "Midline cross", style: spline.STYLE_CIRCLES, color: color.YELLOW, }); } ``` ## ta.crossover() {#fun-ta-crossover} **Kind:** `func` Detects whether `source1` crossed over `source2` on the current bar: the value of `source1` is greater than `source2`, and on the previous bar `source1` was less than or equal to `source2`. **Syntax** ``` ta.crossover(source1, source2) → bool ta.crossover(source1, constant) → bool ``` **Arguments** | Name | Type | Description | |----------|----------------|-------------------------------------| | source1 | series | First data series | | source2 | series, number | Second data series or constant line | **Returns** `true` if `source1` crossed over `source2`, otherwise `false`. **Notes** * Returns `false` if either series has fewer than two bars or any required value is `NaN` **Example** Golden cross — mark when the short MA crosses above the long MA: ```javascript const shortLength = input("shortLength", 50); const longLength = input("longLength", 200); function onTick() { const maShort = ta.sma(close, shortLength); const maLong = ta.sma(close, longLength); spline(maShort, {title: "MA Short", color: color.GREEN}); spline(maLong, {title: "MA Long", color: color.RED}); spline(ta.crossover(maShort, maLong) ? maShort : NaN, { title: "Golden cross", style: spline.STYLE_CIRCLES, color: color.YELLOW, }); } ``` ## ta.crossunder() {#fun-ta-crossunder} **Kind:** `func` Detects whether `source1` crossed under `source2` on the current bar: the value of `source1` is less than `source2`, and on the previous bar `source1` was greater than or equal to `source2`. **Syntax** ``` ta.crossunder(source1, source2) → bool ta.crossunder(source1, constant) → bool ``` **Arguments** | Name | Type | Description | |----------|----------------|-------------------------------------| | source1 | series | First data series | | source2 | series, number | Second data series or constant line | **Returns** `true` if `source1` crossed under `source2`, otherwise `false`. **Notes** * Returns `false` if either series has fewer than two bars or any required value is `NaN` **Example** Death cross — mark when the short MA crosses below the long MA: ```javascript const shortLength = input("shortLength", 50); const longLength = input("longLength", 200); function onTick() { const maShort = ta.sma(close, shortLength); const maLong = ta.sma(close, longLength); spline(maShort, {title: "MA Short", color: color.GREEN}); spline(maLong, {title: "MA Long", color: color.RED}); spline(ta.crossunder(maShort, maLong) ? maShort : NaN, { title: "Death cross", style: spline.STYLE_CIRCLES, color: color.YELLOW, }); } ``` --- --- url: /reference/core/ts.md --- # Time Series {#module-ts} **Kind:** `module` **Namespace:** `ts` Provides functions for creating and manipulating time series. # Overview Time series are the core data structure for calculations. A series stores historical values with efficient lookback access, enabling stateful calculations across bars. Series are **continuous**: every bar must have a value. If not explicitly set, it defaults to `NaN`. Internally, series use a ring buffer with constant memory usage regardless of how many bars are processed. Index `0` is the current (most recent) value, `1` is the previous value, and so on: ``` Index: [0] [1] [2] [3] [4] ↓ ↓ ↓ ↓ ↓ Value: 100 99 101 98 97 ↑ current ``` The [`ts()`](#fun-ts) function creates a series once on the first tick, then reuses the same instance on subsequent ticks. Each tick either shifts the series forward (new bar) or overwrites `[0]` (bar update): ``` Bar 0: [10] ← created Bar 1: [20, 10] ← shifted, 10 is now [1] Bar 1*: [25, 10] ← update, [0] changed from 20 to 25 Bar 2: [30, 25, 10] ← shifted ``` A series without an index is automatically converted to its current value in a numeric context (`+`, `-`, `>`, `<`, `==`, `!=`, etc.). However, `===` and `!==` never trigger this conversion. Also, `==` and `!=` between two series compare references, not values. See [details below](#operator-series-index). # Built-in Series {#built-in-series} Price and volume data are available as pre-defined read-only series: | Series | Description | |-----------------|---------------------------------| | `time` | Candle timestamp in millisecond | | `open` | Opening price | | `high` | Highest price | | `low` | Lowest price | | `close` | Closing price | | `volume` | Total volume | | `bidVolume` | Bid volume | | `askVolume` | Ask volume | | `count` | Number of trades | | `vwap` | Volume-weighted average price | | `impVolatility` | Implied volatility | | `openInterest` | Open interest | | `hl2` | (high + low) / 2 | | `hlc3` | (high + low + close) / 3 | | `ohlc4` | (open + high + low + close) / 4 | ## ts() {#fun-ts} **Kind:** `func` Creates a new time series for storing calculated values. **Syntax** ``` ts() → series ts(value) → series ``` **Arguments** | Name | Type | Default | Description | |--------|--------|---------|--------------------------------------------------------------| | value? | double | `NaN` | Value for the current bar. Defaults to `NaN` if not provided | **Returns** A mutable [`series`](#object-series) object. **Caveats** * Must be called inside [`onTick`](/getting-started/quick-start#ontick-function), not in the [`init`](/getting-started/quick-start#init-section) section * Must be at the top level of `onTick`, not inside conditionals or loops. This ensures the call count and order remain constant across ticks ::: danger Pitfall ```javascript const y = ts(); // ❌ in init section function onTick() { if (close > open) { const x = ts(close); // ❌ inside conditional } } ``` ::: **Example** ```javascript function onTick() { // Create series at top level const diff = ts(close - open); const range = ts(high - low); const trend = ts(); // Access history using [index] const prevDiff = diff[1]; const avgRange = (range + range[1] + range[2]) / 3; // Update inside conditionals using .set() if (close > close[1]) { trend.set(1); // method syntax } else if (close < close[1]) { trend[0] = -1; // array syntax (equivalent) } else { trend.set(trend[1]); } spline(diff, {title: "diff"}); spline(trend, {title: "trend"}); } ``` ## Series Object {#object-series} The `series` object stores values and provides history access. *** ### series\[index] {#operator-series-index} **Kind:** `operator` Reads historical values of a series. **Syntax** ``` series[lookback] → double series → double ``` **Arguments** | Name | Type | Description | |----------|------|--------------------------------------------------------| | lookback | int | Offset from current bar. `0` = current, `1` = previous | **Returns** The value at the specified offset, or `NaN` if the index exceeds available history. **Notes** * `series` without index is equivalent to `series[0]` * Index `0` is the current bar, `1` is previous, etc. **Example** ```javascript function onTick() { // Explicit index access const current = close[0]; const prev = close[1]; const old = close[10]; // Implicit current value (numeric context) const sum = close + open; // same as close[0] + open[0] const change = close - close[1]; // Comparisons (numeric context) const isUp = close > close[1]; // ⚠️ Strict equality — use explicit [0] const equal = close[0] === high[0]; // ✅ const noEqual = close[0] !== high[0]; // ✅ } ``` ::: warning Equality operators with series `===` and `!==` never convert a series to its value, bevause they compare object references: ```javascript // ❌ always true — two different objects if (high !== low) { ... } // ❌ always false — object vs number if (close === 5) { ... } ``` `==` and `!=` convert a series to a number when compared **with a primitive**, but not when comparing **two series**: ```javascript // ✅ works — series is converted to number if (close != 0) { ... } // ❌ compares references, not values if (high != low) { ... } ``` Use explicit `[0]` to avoid ambiguity: ```javascript // ✅ always correct if (high[0] !== low[0]) { ... } if (close[0] === 5) { ... } ``` ::: *** ### series.set() {#method-series-set} **Kind:** `method` Sets the value for the current bar. **Syntax** ```javascript series.set(value) series[0] = value ``` **Arguments** | Name | Type | Description | |-------|--------|--------------| | value | double | Value to set | **Returns** `void` **Notes** * Only index `0` (current bar) can be written * Calling multiple times overwrites the same bar * Can be used inside conditionals (unlike `ts()`) **Example** ```javascript function onTick() { const signal = ts(); if (close > close[1]) { signal.set(1); // method syntax } else { signal[0] = -1; // array syntax (equivalent) } spline(signal, {title: "signal"}); } ```