Fusion script authoring conventions
Use this page for the rules shared by custom indicators, custom strategies, and custom functions.
The category-specific pages should only answer the category-specific questions:
- which built-in file is the best template
- what the script type usually outputs
- which helpers matter most for that category
- what a representative source file looks like
Everything else belongs here.
Public runtime vs source-level authoring
The typed public package surface gives you getScripts() and addScript(scriptKey, proto?) on ChartInstance.
That is enough for:
- reading the metadata for built-in scripts
- cloning an existing definition
- overriding inputs for an existing key
It is not enough for a brand-new key by itself. The runtime resolves controllers, outputs, and plotters from the internal Fusion registry by config.key, so a net-new script must be added to the package source and registered into the registry before chart.addScript("YOUR_KEY") can work.
This is an existing-key customization:
const ema = JSON.parse(JSON.stringify(chart.getScripts().EMA));
ema.inputs.PERIODS.value = 34;
chart.addScript("EMA", ema);
That is useful, but it is not source-level authoring.
Shared helper pattern
Most current Fusion scripts use the internal helpers from packages/chart/src/fusion-scripts/helpers/scriptDefinition.ts.
The common building blocks are:
defineScript()for the top-level definition objectcreateController()for the runtimeinit()andcalculate()hookscreateSeriesOutput()for standard series outputscreateSeriesLinePlotter()for line-style numeric outputscreateSignalInput()for strategy signal pickerscreateStrategyPlotter()for strategy signal rendering
The common skeleton looks like this:
import type { CoreFusionStatic } from "../../internal-types/fusion";
import type { FusionScriptControllerRuntime } from "../../internal-types/scripts";
import { createController, defineScript } from "../helpers/scriptDefinition";
export default function createExampleScript(FUSION: CoreFusionStatic) {
return defineScript({
title: "exampleTitle",
description: "exampleDescription",
type: "indicators",
newPane: false,
inputs: {},
outputs: {},
plotters: [],
controller: createController(function (this: FusionScriptControllerRuntime) {
this.init = function () {};
this.calculate = function (index: number) {};
}),
});
}
Definition rules that apply everywhere
titleanddescriptionshould be locale keys, not final English strings.typemust match the target category exactly:indicators,strategies, orfunctions.newPanecontrols whether the script opens in a separate pane.centerZerois useful for oscillators and zero-centered transforms.inputsdefine the editable runtime inputs.outputsdefine the runtime series objects created for the script.- Output field names become controller wrappers, for example
fields: ["EMA"]createsthis.EMA. properties.defon aseriesinput lets the runtime auto-bind to a default field such aso,h,l,c, orv.
Registry locations
Every new key needs two source edits:
- Add the new script file under the right category directory.
- Register that file in the corresponding category index.
Category map:
- Indicators:
packages/chart/src/fusion-scripts/indicators/andpackages/chart/src/fusion-scripts/indicators/index.ts - Strategies:
packages/chart/src/fusion-scripts/strategies/andpackages/chart/src/fusion-scripts/strategies/index.ts - Functions:
packages/chart/src/fusion-scripts/functions/andpackages/chart/src/fusion-scripts/functions/index.ts
Those category registries are then assembled into the internal Fusion registry in packages/chart/src/fusion.ts. That is the registry read by chart.getScripts() and chart.addScript().
Locale rules
Script titles, descriptions, and many input labels are stored as locale keys in packages/chart/src/locale/en-US.ts.
Add new locale strings for:
- the script title
- the script description
- any brand-new input names you introduce
Reuse existing keys when they already fit. Common reusable keys include:
priceOpen,priceHigh,priceLow,priceClose,priceVolumeperiods,value,series,aSeries,bSeriescrossOnUp,crossOnDn
Typical locale additions look like this:
exampleTitle: "Example Script",
exampleDescription: "Describe what the script computes",
Validation workflow
After adding the source file, registry entry, and locale strings, validate the package first:
cd packages/chart
npm run build
npm run typecheck
Then verify the runtime path:
const scripts = chart.getScripts();
console.log(scripts.YOUR_KEY);
chart.addScript("YOUR_KEY");
Authoring checklist
- Start from the nearest built-in script in the same category.
- Add the new source file under the category directory.
- Use the shared helper pattern unless that file needs a very custom shape.
- Register the new key in the category index.
- Add locale strings in
en-US.ts. - Build and typecheck
packages/chart. - Verify the key through
chart.getScripts()andchart.addScript().