Skip to content

Plugin API Reference

This page documents the technical interface for Stratosfi chart plugins. It covers plugin structure, the calculate() function, input types, output format, the ta.* technical analysis library, and server-side plugin features.

Plugin Structure

Every plugin consists of two parts:

  1. Manifest — metadata describing the plugin (name, category, inputs)
  2. Calculate function — a pure function that receives price data and returns rendering output
js
const manifest = {
  name: 'my-indicator',
  displayName: 'My Custom Indicator',
  description: 'What this indicator does',
  category: 'overlay',   // 'overlay' | 'oscillator' | 'volume' | 'strategy' | 'special'
  display: 'overlay',    // 'overlay' (on chart) | 'panel' (separate panel below)
  inputs: [
    { id: 'period', type: 'number', default: 14, min: 2, max: 200, label: 'Period' },
    { id: 'color', type: 'color', default: '#2196F3', label: 'Color' },
  ],
};

function calculate(data, inputs, context) {
  // Your calculation logic here
  return { lines, markers, fills, hlines, histograms };
}

Input Data

The data parameter provides OHLCV price data in columnar format — each field is an array of numbers, all the same length:

FieldTypeDescription
data.time[]number[]Unix timestamps (seconds)
data.open[]number[]Opening prices
data.high[]number[]Highest prices
data.low[]number[]Lowest prices
data.close[]number[]Closing prices
data.volume[]number[]Trading volume

All arrays share the same index — data.close[i] is the closing price at time data.time[i].

Input Types

Plugins declare their configurable parameters in manifest.inputs. Each input has an id, type, default, and label. The resolved values are passed as the inputs parameter to calculate().

TypeDescriptionExtra Fields
numberNumeric input with slidermin, max
colorColor picker (hex string)
booleanToggle switch
selectDropdown menuoptions (string array)

Example input definitions:

js
inputs: [
  { id: 'period', type: 'number', default: 20, min: 2, max: 500, label: 'Period' },
  { id: 'color', type: 'color', default: '#FF9800', label: 'Line Color' },
  { id: 'showTable', type: 'boolean', default: true, label: 'Show Table' },
  { id: 'method', type: 'select', default: 'standard', label: 'Method',
    options: ['standard', 'fibonacci', 'woodie'] },
]

Return Format

The calculate() function returns an object with any combination of these fields:

Lines

Arrays of data points drawn as continuous lines. Used for moving averages, bands, oscillator values, etc.

js
lines: [
  {
    data: [{ time: 1700000000, value: 150.5 }, ...],
    color: '#2196F3',
    width: 2,           // optional, default: 1
    label: 'SMA 20',    // optional, shown in legend
    style: 'dashed',    // optional: 'solid' (default) | 'dashed' | 'dotted'
  },
]

Markers

Individual points on the chart — used for buy/sell signals, pattern markers, etc.

js
markers: [
  {
    time: 1700000000,
    position: 'above',   // 'above' | 'below' the candle
    shape: 'arrow',      // 'circle' | 'arrow'
    color: '#4CAF50',
    text: 'BUY',         // optional label
  },
]

Fills

Colored regions between two lines (e.g., Bollinger Band fill, Ichimoku Cloud).

js
fills: [
  {
    upper: 0,      // index into the lines array
    lower: 1,      // index into the lines array
    color: 'rgba(33, 150, 243, 0.1)',
  },
]

Horizontal Lines (hlines)

Static horizontal reference lines — used for overbought/oversold levels, zero line, etc.

js
hlines: [
  { value: 70, color: '#EF5350', width: 1, style: 'dashed' },
  { value: 30, color: '#4CAF50', width: 1, style: 'dashed' },
]

Histograms

Bar charts rendered in panels — used for MACD histogram, volume-based indicators, etc.

js
histograms: [
  {
    data: [{ time: 1700000000, value: 0.5, color: '#4CAF50' }, ...],
    label: 'MACD Histogram',
  },
]

Tables

On-chart tables for displaying multi-value dashboards, current indicator readings, or status summaries directly on the price chart.

js
tables: [
  {
    position: 'top-right',   // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
    title: 'Multi-TF Dashboard',
    columns: ['Timeframe', 'RSI', 'MACD', 'Trend'],
    rows: [
      ['1H', '45.2', 'Bullish', 'Up'],
      ['4H', '52.1', 'Bearish', 'Down'],
      ['Daily', '61.8', 'Bullish', 'Up'],
    ],
  },
]

Earnings Markers

Special markers for earnings report dates, rendered as HTML overlays at the bottom of the chart.

js
earningsMarkers: [
  {
    time: 1700000000,
    type: 'beat',        // 'beat' | 'miss' | 'inline'
    color: '#4CAF50',
    label: '$1.52',
    earning: { /* full earnings data */ },
  },
]

Technical Analysis Library (ta.*)

All plugins have access to the ta library — a collection of financial math functions that operate on arrays of numbers. In AI-generated plugins, these functions are available as top-level globals (e.g., sma(data.close, 20) instead of ta.sma(...)).

Moving Averages

FunctionSignatureDescription
smasma(source, period)Simple Moving Average
emaema(source, period)Exponential Moving Average — more responsive to recent prices
rmarma(source, period)Running Moving Average (Wilder's smoothing) — used internally by RSI and ATR

Volatility & Range

FunctionSignatureDescription
stdevstdev(source, period)Standard deviation over a rolling window
trueRangetrueRange(high, low, close)True Range — accounts for gaps
atratr(high, low, close, period)Average True Range — RMA of True Range

Lookback

FunctionSignatureDescription
highesthighest(source, period)Highest value in the lookback window
lowestlowest(source, period)Lowest value in the lookback window

Price Changes

FunctionSignatureDescription
diffdiff(source)Element-wise difference: source[i] - source[i-1]
gaingain(source)Positive changes only (0 for down bars)
lossloss(source)Absolute negative changes (0 for up bars)

Crossover Detection

FunctionSignatureDescription
crossovercrossover(a, b)Returns true at indices where a crosses above b
crossundercrossunder(a, b)Returns true at indices where a crosses below b

Aggregation

FunctionSignatureDescription
sumsum(source, period)Rolling sum over a window
typicalPricetypicalPrice(high, low, close)(High + Low + Close) / 3
meanDeviationmeanDeviation(source, period)Mean absolute deviation from SMA

Composite Indicators

These are higher-level functions that return multiple arrays:

FunctionSignatureReturns
rsirsi(source, period)number[] — RSI values (0-100)
macdmacd(source, fast, slow, signal){ macd, signal, histogram } — three arrays
bollingerbollinger(source, period, mult){ upper, middle, lower } — three arrays
stochasticstochastic(high, low, close, kPeriod, dPeriod){ k, d } — two arrays
obvobv(close, volume)number[] — cumulative OBV
vwapvwap(high, low, close, volume)number[] — VWAP values
adxadx(high, low, close, period)number[] — ADX values (0-100)

Usage Example

js
function calculate(data, inputs) {
  const smaLine = sma(data.close, inputs.period);
  const rsiVals = rsi(data.close, 14);
  const bb = bollinger(data.close, 20, 2);

  return {
    lines: [
      { data: smaLine.map((v, i) => ({ time: data.time[i], value: v })),
        color: inputs.color, label: `SMA ${inputs.period}` },
    ],
  };
}

Context Object

The third parameter to calculate() provides external data that goes beyond OHLCV:

js
function calculate(data, inputs, context) {
  // context.earnings — array of earnings data (if resources.apis includes 'earnings')
  // context.chart.symbol — current ticker symbol
  // context.chart.range — current date range
  // context.chart.interval — current candle interval
}

Available Context Properties

PropertyTypeDescription
context.earningsobject[]Earnings data (EPS actual/estimate, surprise, date)
context.chart.symbolstringCurrent chart symbol (e.g., "AAPL")
context.chart.rangestringCurrent date range (e.g., "1Y", "3M")
context.chart.intervalstringCurrent candle interval (e.g., "1d", "1h")

To request external data, declare it in the manifest:

js
manifest: {
  // ...
  resources: {
    apis: ['earnings'],  // requests earnings data be loaded into context
  },
}

Server-Side Plugins

Plugins that need to fetch external data (prices for other symbols, quotes, etc.) run on the server in a sandboxed environment. Server-side plugins have access to ctx.fetch() for making proxied API calls.

When a Plugin Runs on the Server

A plugin is automatically detected as server-side if:

  • The manifest includes requires: { data: true } or requires: { fetch: true }
  • The manifest includes runtime: 'server'
  • The code contains ctx.fetch(...) or ctx.fetchOHLCV(...) calls

Sandbox Environment

Server-side plugins execute in a Node.js VM sandbox with:

  • Full ta.* library access
  • Math, JSON, Array, Object (read-only)
  • console.log / console.warn for debugging
  • ctx.fetch() for approved API calls
  • Data functions: ctx.fetchOHLCV(), ctx.fetchQuote(), ctx.fetchEarnings(), ctx.fetchFinancials()
  • 5-second execution timeout

Not available in the sandbox: require, import, process, global, setTimeout, setInterval, Buffer, native fetch.

Data Functions

Server-side plugins have access to high-level data functions that fetch market data without needing to construct API URLs:

ctx.fetchOHLCV(symbol, options)

Fetches OHLCV price history for any symbol. Returns columnar data in the same format as the data parameter.

js
const ohlcv = await ctx.fetchOHLCV('QQQ', {
  range: ctx.chart.range,      // e.g. '1Y'
  interval: ctx.chart.interval // e.g. '1d'
});
// Returns: { time[], open[], high[], low[], close[], volume[] }

ctx.fetchQuote(symbol)

Fetches real-time quote data for any symbol.

js
const quote = await ctx.fetchQuote('AAPL');
// Returns: { price, change, changePct, volume, marketCap, ... }

ctx.fetchEarnings(symbol)

Fetches earnings history and forward estimates.

js
const earnings = await ctx.fetchEarnings('TSLA');
// Returns: { history: [{ date, epsActual, epsEstimate, surprise, ... }], ... }

ctx.fetchFinancials(symbol)

Fetches financial statements.

js
const financials = await ctx.fetchFinancials('MSFT');
// Returns: { income: [...], balance: [...], cashflow: [...], keyStats, ... }

Server-Side Plugin Example

Here is a plugin that overlays another symbol's price on the chart for comparison:

js
const manifest = {
  name: 'symbol-overlay',
  displayName: 'Symbol Overlay',
  category: 'special',
  display: 'overlay',
  runtime: 'server',
  requires: { data: true },
  inputs: [
    { id: 'symbol', type: 'text', default: 'QQQ', label: 'Symbol' },
    { id: 'color', type: 'color', default: '#FF9800', label: 'Color' },
  ],
};

async function calculate(data, inputs, ctx) {
  const ohlcv = await ctx.fetchOHLCV(inputs.symbol, {
    range: ctx.chart.range,
    interval: ctx.chart.interval,
  });

  return {
    lines: [{
      data: ohlcv.time.map((t, i) => ({ time: t, value: ohlcv.close[i] })),
      color: inputs.color,
      label: inputs.symbol,
    }],
  };
}

Complete Plugin Example

Here is a full plugin that combines RSI with a moving average and generates buy/sell signals:

js
const manifest = {
  name: 'rsi-ma-signals',
  displayName: 'RSI + MA Signal',
  description: 'Buy when RSI crosses above oversold and price is above SMA',
  category: 'strategy',
  display: 'overlay',
  inputs: [
    { id: 'rsiPeriod', type: 'number', default: 14, min: 2, max: 100, label: 'RSI Period' },
    { id: 'smaPeriod', type: 'number', default: 50, min: 5, max: 200, label: 'SMA Period' },
    { id: 'oversold', type: 'number', default: 30, min: 10, max: 50, label: 'Oversold Level' },
    { id: 'overbought', type: 'number', default: 70, min: 50, max: 90, label: 'Overbought Level' },
  ],
};

function calculate(data, inputs) {
  const rsiVals = rsi(data.close, inputs.rsiPeriod);
  const smaVals = sma(data.close, inputs.smaPeriod);
  const oversoldLine = new Array(data.close.length).fill(inputs.oversold);

  const buyCross = crossover(rsiVals, oversoldLine);
  const overboughtLine = new Array(data.close.length).fill(inputs.overbought);
  const sellCross = crossunder(rsiVals, overboughtLine);

  const markers = [];
  for (let i = 0; i < data.time.length; i++) {
    if (buyCross[i] && smaVals[i] != null && data.close[i] > smaVals[i]) {
      markers.push({
        time: data.time[i], position: 'below',
        shape: 'arrow', color: '#4CAF50', text: 'BUY',
      });
    }
    if (sellCross[i]) {
      markers.push({
        time: data.time[i], position: 'above',
        shape: 'arrow', color: '#EF5350', text: 'SELL',
      });
    }
  }

  return {
    lines: [
      {
        data: smaVals.map((v, i) => ({ time: data.time[i], value: v })),
        color: '#42A5F5', label: `SMA ${inputs.smaPeriod}`, style: 'dashed',
      },
    ],
    markers,
  };
}
  • Chart Plugins — browse all 40 built-in plugins and learn how to use them
  • Charts & Indicators — chart configuration, drawing tools, and time frames
  • AI Analysis — use AI to create custom plugins from natural language descriptions

STRATOSFI — Smart Trading Platform