Typed inputs

param() turns a value into a setting users can change without editing code. Each param you declare shows up in the chart's settings for the overlay and in om…

param() turns a value into a setting users can change without editing code. Each param you declare shows up in the chart's settings for the overlay and in om metric series --params, and the value you read in init() drives your logic. This is how you ship a configurable Indicator: an adjustable period, a threshold, a multiplier, an on/off toggle. kScript (legacy) had fifteen input() types; an Indicator has one, the number, and this page is what each of the fifteen becomes.

param("length", 20, { min: 2, max: 200, description: "Length" });
let n: i32 = 20;
export function init(): void { n = i32(p_length()); }

Every param takes a name, a default, and usually a description (the text shown beside the field). min and max bound the setting, and required: true refuses a use that does not set it. There is no step, no group, and no label: the description is the label.

The types

kScript typeSurfaced asIndicator
number, floatnumber fieldparam(name, default, { min, max }), read as f64
intinteger fieldthe same param, cast with i32(p_name()); the chart rounds nothing, so cast where you use it
slidersliderthe same param with min and max; the chart chooses the control
booleantoggleparam(name, 1, { min: 0, max: 1 }), tested as p_name() > 0.5
select, multiSelectdropdownnot in Indicators yet; a numeric mode param (0, 1, 2) switched on with switch is the nearest
string, texttext fieldnot in Indicators yet; strings leave the module through string slots, never enter it
color, color[]color pickernot in Indicators yet as a param; color and colors are declared per output, box, or segment, and a hand-written sheet can bind a style knob (Styling)
sourcesource dropdownnot in Indicators yet; the source is the declaration input(name, source.field)
timeframetimeframe fieldnot in Indicators yet; an interval pin on the input, honored on your machine
sessionsession fieldnot in Indicators yet; session math is integer math on the time source (Time and sessions)
symbolsymbol fieldnot in Indicators yet; a symbol + exchange pin on the input, honored on your machine

Every param is an f64 today; non-numeric params are product work, and the rows above name the declaration that carries the same intent. What a kScript select chose at runtime, an Indicator chooses at declaration time: two moving-average kinds are two classes, and a mode param picks which one writes the output.

Examples by type

Number with min and max. An adjustable period clamped to a sensible range; the cast makes it a bar count:

param("length", 14, { min: 2, max: 100, description: "Length" });

Select, as a mode number. A dropdown that switched behavior becomes a numeric mode and a switch in init() or state():

param("ma_type", 1, { min: 0, max: 1, description: "0 = simple, 1 = exponential" });

Color. The user recolors the plot in the chart's style settings; the file declares the default:

output("ma", line, overlay, { color: "#2563eb", width: 2 });

Boolean. An on/off toggle is a 0/1 param; to hide a line, write NaN to it while the toggle is off, and to switch a mark off, feed the toggle into its gate output:

param("show_fast", 1, { min: 0, max: 1, description: "Show the fast line" });

Source. Which data feeds the module is the declaration, and a second feed is a second input; the chart user picks the market, not the source:

input("close", ohlcv.close);
input("buy", trades.volume, { side: "BUY" });

Symbol and timeframe. Pins on the input, both halves together for a market, interval on its own; the chart reads its own market for every input, your machine honors the pins:

input("btc_4h", ohlcv.close, { symbol: "BTCUSDT", exchange: "BINANCE_FUTURES", interval: "FOUR_HOURS" });

Style-only inputs

kScript treated a plot color, line width, or show/hide toggle as style-only when it could prove the setting was presentation-only, and patched the rendered output without recomputing. An Indicator makes the split explicit: color, width, opacity, and line_style on an output are declared style the chart edits without a recompute, and a hand-written sheet can expose one as a settings knob with style: { "output", "property" } (no accessor, no recompute). Every param(...) is compute-affecting by construction: it reaches init() and the module re-runs when it changes.

Every type in one module

Number, integer, float, slider, and boolean params driving one average, with the select-as-mode and the color-as-declaration in the same file.

import { input, line, none, ohlcv, output, overlay, param, shape } from "./sdk/declare";
import { in_close, in_low } from "./gen/inputs";
import { emitRow, out_above, out_average, out_band, out_mark } from "./gen/outputs";
import { p_average, p_float_multiplier, p_int_length, p_number_length, p_show_marks, p_slider_width } from "./gen/params";
import { Ema, Sma } from "./sdk/ta";

// number: a period, cast to a bar count where it is used.
param("number_length", 12, { min: 2, max: 50, description: "Number Length" });
// int: the same declaration; the cast is what makes it an integer.
param("int_length", 14, { min: 2, max: 50, description: "Int Length" });
// float: a fractional multiplier, used as f64.
param("float_multiplier", 1.5, { min: 0.5, max: 5, description: "Float Multiplier" });
// boolean: 0 or 1.
param("show_marks", 1, { min: 0, max: 1, description: "Show marks on bars above the band" });
// select: a mode number, 0 = simple, 1 = exponential.
param("average", 1, { min: 0, max: 1, description: "Average: 0 simple, 1 exponential" });
// slider: a bounded number; the band width in percent.
param("slider_width", 2, { min: 1, max: 5, description: "Band width, percent" });
input("close", ohlcv.close);
input("low", ohlcv.low);
// color: declared on the output, editable in the chart's style settings.
output("average", line, overlay, { color: "#2563eb", width: 2, description: "The chosen average" });
output("band", line, overlay, { color: "#94a3b8", width: 1, line_style: "dotted", description: "Average plus the band width" });
output("mark", shape, overlay, { color: "#16a34a", shape_where: "above", description: "The low of each bar closing above the band" });
output("above", none, overlay, { description: "1 when the close is above the band and marks are on" });

let sma = new Sma(12);
let ema = new Ema(14);
let mode: i32 = 1;
let multiplier: f64 = 1.5;
let showMarks: bool = true;
let bandPct: f64 = 2.0;
let average: f64 = NaN;
let close: f64 = NaN;
let low: f64 = NaN;

export function init(): void {
  sma = new Sma(i32(p_number_length()));
  ema = new Ema(i32(p_int_length()));
  mode = i32(p_average());
  multiplier = p_float_multiplier();
  showMarks = p_show_marks() > 0.5;
  bandPct = p_slider_width();
}

export function state(): i32 {
  close = in_close();
  low = in_low();
  const simple = sma.update(close);
  const exponential = ema.update(close);
  switch (mode) {
    case 0:
      average = simple;
      break;
    default:
      average = exponential;
  }
  return isNaN(average) ? 0 : 1;
}

export function finalize(): void {
  const band = average * (1.0 + (bandPct * multiplier) / 100.0);
  out_average(average);
  out_band(band);
  out_mark(low);
  out_above(showMarks && close > band ? 1.0 : 0.0);
  emitRow();
}

export function reset(): void {
  sma.reset();
  ema.reset();
  average = NaN;
  close = NaN;
  low = NaN;
}

Both averages update on every bar whatever the mode, so switching the setting never restarts a warm-up; only the line written changes.

Defaults are checked

The default must sit inside min..max, and the build checks it before the compiler runs, naming the path:

MistakeError
a default above maxparams.0.default: default above max
min above maxparams.0.min: min must be <= max
a step optionparam options accept only { required, min, max, description }, not 'step'
a computed default (param("n", base * 2))expected a numeric literal
a name built from a variableexpected a string literal
a string default (param("mode", "ema"))expected a numeric literal

Declarations are literals: the extractor reads them from the text without running it. A kScript defaultValue type mismatch has no counterpart because there is one type.

Reading a param on your machine

An installed package's params are arguments to every surface that evaluates it, so the same setting the chart user drags is the one an alert or a series query pins:

om metric series --metric wrun/@you/typed-inputs/average --params number_length=20,average=0 --symbol BTCUSDT --exchange BINANCE_FUTURES --bars 60

om metric get --metric wrun/@you/name/output:length=20 is the inline form. A param the caller does not pass takes its default; one declared required: true refuses the call by name instead.