# Inputs



import { Callout } from 'fumadocs-ui/components/callout';

Inputs are declared at top level and rendered in the script settings UI.

Rules [#rules]

* `input.*` calls are top-level only (not allowed inside `onBar()`)
* Maximum inputs per script: `256`
* The `257th+` input is ignored with a warning
* Every input has a key; duplicate keys throw an error

<Callout type="warn" title="Top-Level Only">
  Call `input.*` before `onBar()`. Calling input APIs inside `onBar()` throws an error.
</Callout>

Keys and Shared Options [#keys-and-shared-options]

For APIs that accept an options object, you can set:

| Option        | Type   | Description                                               |
| ------------- | ------ | --------------------------------------------------------- |
| `key`         | string | Stable input key (recommended for overrides and `onlyIf`) |
| `description` | string | UI description text                                       |
| `sameLine`    | bool   | Render inline with previous input                         |
| `required`    | bool   | Mark value as required                                    |
| `onlyIf`      | object | Conditional visibility                                    |

If `key` is omitted, the engine derives one from label text (lowercase with separators).

Conditional Visibility [#conditional-visibility]

Inputs are visible by default. Use `onlyIf` when an input should appear only for a specific mode or toggle state.

Most scripts should build conditions with the `input.when*` helpers:

* `input.when(key, value)` for equality
* `input.when(key, [values])` for membership
* `input.whenEq(key, value)`
* `input.whenNeq(key, value)`
* `input.whenIn(key, values)`
* `input.whenTrue(key)`
* `input.whenFalse(key)`

```js
onlyIf: {
  key: "mode",
  op: "eq" | "neq" | "in",
  value: string | number | bool,    // for eq/neq
  values: [string | number | bool]  // for in
}
```

```js
//@version=2
indicator("Conditional Inputs", false)
const mode = input.select("Mode", 0, {
  key: "mode",
  selectables: ["Fixed", "ATR", "Disabled"]
})

const fixed = input.float("Fixed Value", 10, {
  key: "fixed_value",
  onlyIf: input.when("mode", "Fixed")
})

const atrLen = input.int("ATR Length", 14, {
  key: "atr_length",
  onlyIf: input.when("mode", "ATR")
})

function onBar(index) {}
```

Input APIs [#input-apis]

input.int [#inputint]

```js
input.int(name, value, options?) -> number
```

```js
//@version=2
indicator("Integer Input Example", false)
const len = input.int("Length", 20, {
  key: "length",
  min: 1,
  max: 500,
  description: "SMA period"
})

function onBar(index) {}
```

Options: `min`, `max`, plus shared options.

input.float [#inputfloat]

```js
input.float(name, value, options?) -> number
```

```js
//@version=2
indicator("Float Input Example", false)
const mult = input.float("Multiplier", 2.0, { min: 0.1, max: 10 })

function onBar(index) {}
```

Options: `min`, `max`, plus shared options.

input.color [#inputcolor]

```js
input.color(name, value, options?) -> string
```

`value` may be ABGR number or hex color (`#RRGGBB` / `#RRGGBBAA`).
Return value is normalized hex (`#RRGGBBAA`).

```js
//@version=2
indicator("Color Input Example", false)
const upColor = input.color("Up Color", color.green)
const downColor = input.color("Down Color", "#ff4d4d")

function onBar(index) {}
```

Options: shared options.

input.bool [#inputbool]

```js
input.bool(name, value, options?) -> boolean
```

```js
//@version=2
indicator("Boolean Input Example", false)
const showSignals = input.bool("Show Signals", true)

function onBar(index) {}
```

Options: shared options.

input.timeframe [#inputtimeframe]

```js
input.timeframe(name, value, options?) -> number
```

`value` may be a positive integer number of seconds or a timeframe string such as `5m`, `1h`, `4h`, `1D`, `1W`, `3M`, or `1Y`.

The return value is always a number of seconds, which makes it suitable for `subscribe(..., { timeframe })`.

In the client UI, the picker is populated from:

* the built-in chart timeframe list
* the user's custom extra timeframes

The selected value is still passed to the script as seconds.

```js
//@version=2
indicator("Timeframe Input Example", false)
const htf = input.timeframe("Higher Timeframe", "4h", { key: "htf" })
const htfCandles = subscribe(data.OHLCV, { timeframe: htf })

function onBar(index) {
  plot("HTF Close", htfCandles.close(), { color: color.blue })
}
```

Options: shared options.

input.select [#inputselect]

```js
input.select(name, defaultIndex, options) -> string | undefined
```

```js
//@version=2
indicator("Select Input Example", false)
const mode = input.select("Mode", 0, {
  key: "mode",
  selectables: ["SMA", "EMA", "RMA"]
})

function onBar(index) {}
```

Required option: `selectables: string[]`.
Also supports shared options.

input.section [#inputsection]

```js
input.section(name, options?) -> string
```

```js
//@version=2
indicator("Section Input Example", false)
input.section("Appearance")

function onBar(index) {}
```

Supports shared options.

input.tab [#inputtab]

```js
input.tab(name, options?) -> string
```

Creates a tab container. Supports `key` in `options`.

```js
//@version=2
indicator("Tab Input Example", false)
input.tab("General", { key: "tab_general" })

function onBar(index) {}
```

input.group [#inputgroup]

```js
input.group(name, options?) -> string
```

Creates a group (inside active tab when present).

```js
//@version=2
indicator("Group Input Example", false)
input.group("Signals", {
  key: "grp_signals",
  collapsible: true,
  collapsed: false
})

function onBar(index) {}
```

Options: `key`, `collapsible`, `collapsed`.

input.exchange [#inputexchange]

```js
input.exchange(name, defaultExchange, options?) -> string
```

Single exchange selector.

```js
//@version=2
indicator("Exchange Input Example", false)
const ex = input.exchange("Exchange", "binancef", {
  key: "exchange",
  required: true,
  filter: ["futures", "inverse"]
})

function onBar(index) {}
```

Options: `key`, `required`, `filter: string[]`, `onlyIf`.

`filter` accepts exchange-type categories, not exchange IDs. Accepted values are:

* `"futures"` for linear futures/perpetual exchanges
* `"inverse"` for inverse-settled futures/perpetual exchanges
* `"spot"` for spot exchanges

input.exchanges [#inputexchanges]

```js
input.exchanges(name, defaultExchanges, options?) -> string[]
```

Multi-exchange selector.

```js
//@version=2
indicator("Exchanges Input Example", false)
const exchanges = input.exchanges("Exchanges", ["binancef"], {
  key: "exchanges",
  required: true,
  minSelected: 1,
  maxSelected: 3,
  filter: ["futures"]
})

function onBar(index) {}
```

Options: `key`, `required`, `minSelected`, `maxSelected`, `filter: string[]`, `onlyIf`.

`filter` accepts exchange-type categories, not exchange IDs. Accepted values are:

* `"futures"` for linear futures/perpetual exchanges
* `"inverse"` for inverse-settled futures/perpetual exchanges
* `"spot"` for spot exchanges

Tabs, Groups, and Conditional Inputs [#tabs-groups-and-conditional-inputs]

```js
//@version=2
indicator("Tabbed Input Layout", false)

input.tab("General", { key: "general" })

input.group("Display", {
  key: "display",
  collapsible: true
})

const mode = input.select("Calculation Mode", 0, {
  key: "mode",
  selectables: ["Fixed", "ATR", "Disabled"]
})

const showLabels = input.bool("Show Labels", true, {
  key: "show_labels"
})

const fixed = input.float("Fixed Value", 10, {
  key: "fixed_value",
  min: 0.1,
  max: 100,
  onlyIf: input.when("mode", "Fixed")
})

const atrLen = input.int("ATR Length", 14, {
  key: "atr_length",
  min: 1,
  max: 100,
  onlyIf: input.when("mode", "ATR")
})

input.tab("Advanced", { key: "advanced" })

input.group("Signals", {
  key: "signals",
  collapsible: true,
  collapsed: false
})

const enableSignals = input.bool("Enable Signals", false, {
  key: "enable_signals"
})

const signalThreshold = input.float("Signal Threshold", 1.5, {
  key: "signal_threshold",
  min: 0.1,
  max: 10,
  onlyIf: input.whenTrue("enable_signals")
})

const signalStyle = input.select("Signal Style", 0, {
  key: "signal_style",
  selectables: ["Trend", "Reversal", "Breakout"],
  onlyIf: input.whenTrue("enable_signals")
})

function onBar(index) {}
```
