The kScript (legacy) math namespace becomes AssemblyScript's Math:
absolute value, rounding, powers and roots, logarithms, and the full trig
and hyperbolic families, on f64. Call them on any number in state()
or finalize() and they evaluate per bar, exactly like their JavaScript
counterparts, with one difference worth knowing: the compiler is typed,
so an integer and a float never mix silently.
Every method lives under the Math. prefix (capital M). There is no
global abs() or round() for floats; it is always Math.abs(...),
Math.round(...). Use them to normalize a signal, scale a value into a
range, or build a custom indicator from primitives.
const spread = close - average;
// How far is price from its average, regardless of direction?
distance = Math.abs(spread);What is available
| Group | Methods |
|---|---|
| Basic | abs, sign |
| Rounding | round, floor, ceil, trunc |
| Powers and roots | pow, sqrt, cbrt, hypot |
| Exp and log | exp, expm1, log, log1p, log2, log10 |
| Comparison | max, min |
| Trig (radians) | sin, cos, tan, asin, acos, atan, atan2 |
| Hyperbolic | sinh, cosh, tanh, asinh, acosh, atanh |
Constants: Math.PI, Math.E, Math.SQRT2, Math.SQRT1_2, Math.LN2,
Math.LN10, Math.LOG2E, Math.LOG10E.
Each behaves like its JavaScript counterpart. Math.max and Math.min
take two f64 arguments and return the larger or smaller; nest them for
three. Math.round rounds to the nearest integer and returns an f64.
Trig functions work in radians, so divide a bar count or an angle
accordingly (Math.sin(f64(barIndex) / 10.0)).
Types. Math.* takes and returns f64. An i32 (a bar count, a
loop index, a ring cursor) must be cast in (f64(count)) and a result
used as an index must be cast out (i32(Math.floor(x))); the compiler
refuses the implicit conversion with AS200. For integer work
AssemblyScript has typed builtins that need no cast: abs<i32>(n),
max<i32>(a, b), min<i32>(a, b), and integer division truncates on
its own (7 / 2 is 3 for two i32 values, 3.5 for two f64).
There is no Math.avg. To average two values, write the arithmetic
((a + b) / 2.0); for a rolling average over a window, use Sma
(Moving averages). Calling a method that does not
exist is a compile error, not a runtime one: Math.unknownFn(x) stops
the build with TS2339: Property 'unknownFn' does not exist on type '~lib/math/NativeMath', with the line and column.
Every method in one module
This module runs the full namespace at once. It builds a few helper values
first (a centered series of price minus its average, a bounded value
safe for asin and acos, and a positive value safe for log and
sqrt), then writes each Math.* result to its own output.
import { input, line, lower, ohlcv, output, param } from "./sdk/declare";
import { in_close, in_high, in_low } from "./gen/inputs";
import {
emitRow,
out_abs,
out_acos,
out_acosh,
out_asin,
out_asinh,
out_atan,
out_atan2,
out_atanh,
out_cbrt,
out_ceil,
out_cos,
out_cosh,
out_exp,
out_expm1,
out_floor,
out_hypot,
out_log,
out_log10,
out_log1p,
out_log2,
out_max,
out_min,
out_pow,
out_round,
out_sign,
out_sin,
out_sinh,
out_sqrt,
out_tan,
out_tanh,
out_trunc,
} from "./gen/outputs";
import { p_period } from "./gen/params";
import { Sma } from "./sdk/ta";
param("period", 5, { min: 2, max: 200 });
input("close", ohlcv.close);
input("high", ohlcv.high);
input("low", ohlcv.low);
output("abs", line, lower, { description: "Math.abs of the centered close" });
output("round", line, lower, { description: "Math.round" });
output("max", line, lower, { description: "Math.max of high and close" });
output("min", line, lower, { description: "Math.min of low and close" });
output("pow", line, lower, { description: "Math.pow of the small value, squared" });
output("sqrt", line, lower, { description: "Math.sqrt of the positive value" });
output("log", line, lower, { description: "Math.log of the positive value" });
output("floor", line, lower, { description: "Math.floor" });
output("ceil", line, lower, { description: "Math.ceil" });
output("sign", line, lower, { description: "Math.sign: -1, 0, or 1" });
output("sin", line, lower, { description: "Math.sin of the bar index over 8" });
output("cos", line, lower, { description: "Math.cos of the bar index over 8" });
output("tan", line, lower, { description: "Math.tan of the bar index over 40" });
output("asin", line, lower, { description: "Math.asin of the bounded value" });
output("acos", line, lower, { description: "Math.acos of the bounded value" });
output("atan", line, lower, { description: "Math.atan of the centered close" });
output("atan2", line, lower, { description: "Math.atan2 of centered over positive" });
output("sinh", line, lower, { description: "Math.sinh of the small value" });
output("cosh", line, lower, { description: "Math.cosh of the small value" });
output("tanh", line, lower, { description: "Math.tanh of the small value" });
output("asinh", line, lower, { description: "Math.asinh of the small value" });
output("acosh", line, lower, { description: "Math.acosh of the positive value" });
output("atanh", line, lower, { description: "Math.atanh of half the bounded value" });
output("exp", line, lower, { description: "Math.exp of the small value" });
output("expm1", line, lower, { description: "Math.expm1 of the small value" });
output("log1p", line, lower, { description: "Math.log1p of the small value's magnitude" });
output("log2", line, lower, { description: "Math.log2 of the positive value" });
output("log10", line, lower, { description: "Math.log10 of the positive value" });
output("cbrt", line, lower, { description: "Math.cbrt of the centered close" });
output("hypot", line, lower, { description: "Math.hypot of centered and small" });
output("trunc", line, lower, { description: "Math.trunc of the centered close" });
let sma = new Sma(5);
let barIndex: i32 = 0;
let centered: f64 = NaN;
let bounded: f64 = NaN;
let positive: f64 = NaN;
let small: f64 = NaN;
let high: f64 = NaN;
let low: f64 = NaN;
let close: f64 = NaN;
export function init(): void {
sma = new Sma(i32(p_period()));
}
export function state(): i32 {
close = in_close();
high = in_high();
low = in_low();
const average = sma.update(close);
centered = close - average;
// The bar index is an i32 counter; the trig helpers want an f64 in radians.
bounded = Math.sin(f64(barIndex) / 10.0);
positive = Math.abs(centered) + 1.0;
small = centered / 10.0;
barIndex += 1;
return isNaN(average) ? 0 : 1;
}
export function finalize(): void {
const angle = f64(barIndex) / 8.0;
out_abs(Math.abs(centered));
out_round(Math.round(centered));
out_max(Math.max(high, close));
out_min(Math.min(low, close));
out_pow(Math.pow(small, 2.0));
out_sqrt(Math.sqrt(positive));
out_log(Math.log(positive));
out_floor(Math.floor(centered));
out_ceil(Math.ceil(centered));
out_sign(Math.sign(centered));
out_sin(Math.sin(angle));
out_cos(Math.cos(angle));
out_tan(Math.tan(f64(barIndex) / 40.0));
out_asin(Math.asin(bounded));
out_acos(Math.acos(bounded));
out_atan(Math.atan(centered));
out_atan2(Math.atan2(centered, positive));
out_sinh(Math.sinh(small));
out_cosh(Math.cosh(small));
out_tanh(Math.tanh(small));
out_asinh(Math.asinh(small));
out_acosh(Math.acosh(positive));
out_atanh(Math.atanh(bounded / 2.0));
out_exp(Math.exp(small));
out_expm1(Math.expm1(small));
out_log1p(Math.log1p(Math.abs(small)));
out_log2(Math.log2(positive));
out_log10(Math.log10(positive));
out_cbrt(Math.cbrt(centered));
out_hypot(Math.hypot(centered, small));
out_trunc(Math.trunc(centered));
emitRow();
}
export function reset(): void {
sma.reset();
barIndex = 0;
centered = NaN;
bounded = NaN;
positive = NaN;
small = NaN;
high = NaN;
low = NaN;
close = NaN;
}Domain notes
A few methods are only defined for part of the number line, exactly as in standard math:
Math.sqrtandMath.logexpect non-negative input. Guard withMath.abs(x) + 1.0or aMath.maxfloor if your series can go negative or hit zero.Math.asinandMath.acosonly accept values in[-1, 1]. Feed them something already bounded (the module usesMath.sin(...)).Math.acoshexpects input>= 1.
Out-of-domain input produces NaN rather than trapping, so an output may
simply show gaps where the input left the valid range, and NaN written
to an output draws nothing and never trips an alert. A division by zero
on f64 yields an infinity, not a trap; isFinite(x) catches both before
the value reaches an output. Integer division by zero DOES trap and
aborts the evaluation, so guard an i32 divisor.