Skip to content

Documentation / @finchart/core / index / ComputationSpec

Interface: ComputationSpec<TIn, TOut> ​

Defined in: packages/core/src/data/computation.ts:28

Type Parameters ​

TIn ​

TIn extends readonly Source<any>[]

TOut ​

TOut extends Record<string, BaseDataPoint[]>

Properties ​

calc ​

calc: (...inputs) => TOut

Defined in: packages/core/src/data/computation.ts:48

Produces the points to draw for each branch. Receives the whole input, not just the visible range — an indicator that looks backward, like a moving average, needs that so it doesn't cut off at the left edge of the screen. Must emit the same keys even when the input is empty — branch names are fixed on the first computation, and a key absent then can never be referenced later.

Parameters ​

inputs ​

...ReadOf<TIn>

Returns ​

TOut


calcFirst? ​

optional calcFirst?: (previous, inputs, changes) => TOut | null

Defined in: packages/core/src/data/computation.ts:86

The head increment — a history page landing on this node's inputs. Only called when every input's change reads as a prepend (or nothing); null falls back to a full computation, and that fallback is also the door's own safety valve — a kernel that can't vouch for its resume point (a recursion whose seed moved) answers null instead of guessing.

Build each branch by computing the new head (plus whatever old head positions the landing corrects) and reusing the previous array's tail beyond that (slice/concat) — the reused identities are how this branch's consumers classify the landing in turn. Unlike the declared door, this one does not call calc, so the node leaves your calcLast checkpoints alone — if your calcFirst touches them, it owns keeping them true.

Parameters ​

previous ​

TOut

inputs ​

ReadOf<TIn>

changes ​

readonly (HeadChange | { kind: "none"; })[]

Returns ​

TOut | null


calcLast? ​

optional calcLast?: (previous, inputs, changes) => TOut | null

Defined in: packages/core/src/data/computation.ts:64

The tail increment. Without it, this is a full recompute. Only called when every input's change is tail-only (changes[i] is input i's shape). Returning null falls back to a full computation — the escape hatch for a shape the checkpoint can't handle (multiple replacements, etc.).

Build the output array by reusing the front of the previous array (slice/concat) — unchanged point objects need to keep their identity for this branch's consumers to reach the same verdict. A kernel without a cheap resume point can still hand them that: a full recompute that keeps the unchanged objects, (previous, inputs) => reuseUnchanged(previous, calc(...inputs)).

Parameters ​

previous ​

TOut

inputs ​

ReadOf<TIn>

changes ​

readonly TailChange[]

Returns ​

TOut | null


headLookback? ​

optional headLookback?: number | (() => number)

Defined in: packages/core/src/data/computation.ts:112

The declarative head door — for the common case, where calc emits one output per input position, left to right. Declare how far back a landing corrects (a window's warmup, a recursion's decay horizon) and the node lands pages by itself: it re-runs calc on the prefix (count + input corrections + headLookback positions — a landing's resume point is the beginning of time, so no checkpoint is needed) and reuses each branch's tail as is.

That prefix run is a real call to your calc: a resume checkpoint it keeps for calcLast now describes the prefix's end, not the array's. The node knows this — the first tick after a declared landing is a full computation, and calcLast is used again only after that.

The 1:1 assumption is checked at runtime, per branch, per landing — a branch whose prefix output isn't position-aligned makes the door decline and the full path answer, which is always correct. A door that needs a different head shape writes calcFirst instead; the two are one way each, so declaring both is refused.


inputs ​

inputs: TIn

Defined in: packages/core/src/data/computation.ts:38

What this runs on. An array — some indicators watch price and volume together, and an element can be a series handle or another computation's branch (which is why an indicator built on an indicator comes for free).