EngineSJS

Indicators and algorithms

Choose between local calculations, registered calculators, configured models, and injected helpers.

SJS can calculate a value directly or consume engine capabilities. Choose based on the data and lifecycle your strategy needs, then verify the result's type and readiness before using it.

For configuration, lifecycle, signal composition, and execution primitives, read the Indicators & Algorithms guides.

Calculate locally

The quickstart maintains three closes in context.sjsState and computes their mean. Its warmup, gap handling, and sample ordering are fully owned by the script. This is useful for learning because every input to the signal is visible.

That local mean is not interchangeable with every indicator named SMA. A calculator based on a time window can return a different value from a fixed-count window, especially when data has gaps.

Call a registered calculator

await cal(name, params) invokes a registered L2 model's calculator with the current context and bar. The shared helper constructs a calculator instance for the call; do not use it as a persistent model-instance store. Missing calculators and calculation failures return null through the normal helper path.

This complete observation-only SJS script calls the built-in SMA calculator. Run it separately from the quickstart while inspecting the result:

export async function app({ bar, cal, log }) {
  if (!bar?.instrument || bar.date == null || typeof cal !== "function") {
    return "waiting: calculator inputs unavailable";
  }
  const average = await cal("sma", { minutes: 3 });
  if (typeof average !== "number" || !Number.isFinite(average)) {
    return "waiting: SMA unavailable";
  }
  log?.("sjs-sma", { frame: bar.date, average });
  return "observed";
}

The current SMA calculator requests a historical window ending at bar.date, using the supplied minutes value and one-minute data. It averages the rows returned, and an empty window yields no usable number. It does not require exactly three returned rows for minutes: 3.

Check the SMA reference and the other indicator pages for their individual parameters. Preserve numeric zero as a valid result; if (!average) would incorrectly reject it.

Read a configured algorithm

context.algos.find("sessionRegime", "fast") looks up a configured instance. It does not create one. Configure the exact model name and ID, then read the model's documented state or getter methods.

Different algorithms have different readiness and update behavior. Do not treat a missing instance, an uninitialized snapshot, and a neutral signal as the same state. See sessionRegime for its reference.

Use injected decision helpers

Helpers such as pureSides, rangeIntent, and positionMemory arrive at the top level of the SJS scope. They return information you can use in your main algorithm; they are not L3 policy objects and do not automatically submit your entry.

For example, a pureSides decision can contain decision.regimes.entry with ready, aligned, action, and regimeSide. Your strategy still needs to verify the required model instances, handle missing evidence, inspect orders and positions, and choose whether to request execution.

Use the helper observer example to understand the helper's input shape, but do not paste that L3 policy object as an SJS entry point. SJS calls helpers from its own app function.

Continue with Orders and positions.

On this page