indicatorCatalog top-level property
Every indicator the chart can draw, with the settings each one takes.
Drive an "add indicator" menu from this list rather than hard-coding the
types, so a new indicator shows up in the menu on its own. Nothing stops a
caller building indicators directly — AtrIndicator(period: 8) — the
catalog is there for menus and settings dialogs.
Implementation
final List<IndicatorType> indicatorCatalog = List.unmodifiable([
IndicatorType(
name: 'MA',
description: 'Simple moving average of the close.',
placement: IndicatorPlacement.overlay,
settings: [_periodOf(5)],
builder: (values, colors) => MaIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'EMA',
description: 'Exponential moving average of the close.',
placement: IndicatorPlacement.overlay,
settings: [_periodOf(5)],
builder: (values, colors) => EmaIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'BOLL',
description: 'Bollinger bands around a moving average.',
placement: IndicatorPlacement.overlay,
settings: [
_periodOf(20),
const IndicatorSetting(
key: 'deviations',
label: 'Deviations',
defaultValue: 2,
min: 0.5,
max: 5,
step: 0.5,
isInteger: false,
),
],
builder: (values, colors) => BollIndicator(
period: values['period']!.toInt(),
deviations: values['deviations']!.toDouble(),
colors: colors,
),
),
IndicatorType(
name: 'SAR',
description: 'Parabolic stop and reverse dots.',
placement: IndicatorPlacement.overlay,
settings: [
const IndicatorSetting(
key: 'start',
label: 'Start',
defaultValue: 0.02,
min: 0.001,
max: 0.2,
step: 0.01,
isInteger: false,
),
const IndicatorSetting(
key: 'step',
label: 'Step',
defaultValue: 0.02,
min: 0.001,
max: 0.2,
step: 0.01,
isInteger: false,
),
const IndicatorSetting(
key: 'maximum',
label: 'Maximum',
defaultValue: 0.2,
min: 0.01,
max: 1,
step: 0.05,
isInteger: false,
),
],
builder: (values, colors) => SarIndicator(
start: values['start']!.toDouble(),
step: values['step']!.toDouble(),
maximum: values['maximum']!.toDouble(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'VWAP',
description: 'Volume-weighted average price.',
placement: IndicatorPlacement.overlay,
settings: [],
builder: (values, colors) => VwapIndicator(color: colors?.firstOrNull),
),
IndicatorType(
name: 'ST',
description: 'Supertrend: an ATR stop that flips with the trend.',
placement: IndicatorPlacement.overlay,
settings: [
_periodOf(10),
const IndicatorSetting(
key: 'multiplier',
label: 'Multiplier',
defaultValue: 3,
min: 0.5,
max: 10,
step: 0.5,
isInteger: false,
),
],
builder: (values, colors) => SupertrendIndicator(
period: values['period']!.toInt(),
multiplier: values['multiplier']!.toDouble(),
colors: colors,
),
),
IndicatorType(
name: 'KC',
description: 'Keltner channels: an EMA with average-true-range bands.',
placement: IndicatorPlacement.overlay,
settings: [
_periodOf(20),
const IndicatorSetting(
key: 'atrPeriod',
label: 'ATR period',
defaultValue: 10,
min: 2,
max: 100,
),
const IndicatorSetting(
key: 'multiplier',
label: 'Multiplier',
defaultValue: 2,
min: 0.5,
max: 10,
step: 0.5,
isInteger: false,
),
],
builder: (values, colors) => KeltnerIndicator(
period: values['period']!.toInt(),
atrPeriod: values['atrPeriod']!.toInt(),
multiplier: values['multiplier']!.toDouble(),
colors: colors,
),
),
IndicatorType(
name: 'DC',
description: 'Donchian channels: the highest high and lowest low.',
placement: IndicatorPlacement.overlay,
settings: [_periodOf(20)],
builder: (values, colors) =>
DonchianIndicator(period: values['period']!.toInt(), colors: colors),
),
IndicatorType(
name: 'ICH',
description: 'Ichimoku Cloud: conversion, base, cloud and lagging span.',
placement: IndicatorPlacement.overlay,
settings: [
const IndicatorSetting(
key: 'conversionPeriod',
label: 'Conversion',
defaultValue: 9,
min: 2,
max: 100,
),
const IndicatorSetting(
key: 'basePeriod',
label: 'Base',
defaultValue: 26,
min: 2,
max: 200,
),
const IndicatorSetting(
key: 'spanPeriod',
label: 'Span B',
defaultValue: 52,
min: 2,
max: 400,
),
const IndicatorSetting(
key: 'displacement',
label: 'Shift',
defaultValue: 26,
min: 0,
max: 200,
),
],
builder: (values, colors) => IchimokuIndicator(
conversionPeriod: values['conversionPeriod']!.toInt(),
basePeriod: values['basePeriod']!.toInt(),
spanPeriod: values['spanPeriod']!.toInt(),
displacement: values['displacement']!.toInt(),
colors: colors,
),
),
IndicatorType(
name: 'ZigZag',
description: 'A line through the swing highs and lows.',
placement: IndicatorPlacement.overlay,
settings: [
const IndicatorSetting(
key: 'depth',
label: 'Swing % (0 = auto)',
defaultValue: 0,
min: 0,
max: 30,
step: 0.5,
isInteger: false,
),
],
builder: (values, colors) => ZigZagIndicator(
depth: values['depth']!.toDouble(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'FIB',
description: 'Fibonacci retracement levels over the last swing.',
placement: IndicatorPlacement.overlay,
settings: [
const IndicatorSetting(
key: 'depth',
label: 'Swing % (0 = auto)',
defaultValue: 0,
min: 0,
max: 30,
step: 0.5,
isInteger: false,
),
],
builder: (values, colors) =>
FibonacciIndicator(depth: values['depth']!.toDouble(), colors: colors),
),
IndicatorType(
name: 'Elliott',
description: 'Wave labels over the swings — a sketch, not a rules check.',
placement: IndicatorPlacement.overlay,
settings: [
const IndicatorSetting(
key: 'depth',
label: 'Swing % (0 = auto)',
defaultValue: 0,
min: 0,
max: 30,
step: 0.5,
isInteger: false,
),
],
builder: (values, colors) => ElliottWaveIndicator(
depth: values['depth']!.toDouble(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'MACD',
description: 'Moving average convergence divergence.',
placement: IndicatorPlacement.pane,
settings: [
const IndicatorSetting(
key: 'fast',
label: 'Fast',
defaultValue: 12,
min: 2,
max: 100,
),
const IndicatorSetting(
key: 'slow',
label: 'Slow',
defaultValue: 26,
min: 2,
max: 200,
),
const IndicatorSetting(
key: 'signal',
label: 'Signal',
defaultValue: 9,
min: 2,
max: 100,
),
],
builder: (values, colors) => MacdIndicator(
fast: values['fast']!.toInt(),
slow: values['slow']!.toInt(),
signal: values['signal']!.toInt(),
colors: colors,
),
),
IndicatorType(
name: 'KDJ',
description: 'Stochastic oscillator with a J line.',
placement: IndicatorPlacement.pane,
settings: [
_periodOf(9),
const IndicatorSetting(
key: 'kSmoothing',
label: 'K smoothing',
defaultValue: 3,
min: 1,
max: 50,
),
const IndicatorSetting(
key: 'dSmoothing',
label: 'D smoothing',
defaultValue: 3,
min: 1,
max: 50,
),
],
builder: (values, colors) => KdjIndicator(
period: values['period']!.toInt(),
kSmoothing: values['kSmoothing']!.toInt(),
dSmoothing: values['dSmoothing']!.toInt(),
colors: colors,
),
),
IndicatorType(
name: 'RSI',
description: 'Relative strength index.',
placement: IndicatorPlacement.pane,
settings: [_period],
builder: (values, colors) => RsiIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'WR',
description: 'Williams %R.',
placement: IndicatorPlacement.pane,
settings: [_period],
builder: (values, colors) => WrIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'CCI',
description: 'Commodity channel index.',
placement: IndicatorPlacement.pane,
settings: [_period],
builder: (values, colors) => CciIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'ATR',
description: 'Average true range: how far price travels per candle.',
placement: IndicatorPlacement.pane,
settings: [_period],
builder: (values, colors) => AtrIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'OBV',
description: 'On-balance volume.',
placement: IndicatorPlacement.pane,
settings: [],
builder: (values, colors) => ObvIndicator(color: colors?.firstOrNull),
),
IndicatorType(
name: 'MFI',
description: 'Money flow index: a volume-weighted RSI.',
placement: IndicatorPlacement.pane,
settings: [_period],
builder: (values, colors) => MfiIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'DMI',
description: 'Directional movement: +DI, -DI and ADX.',
placement: IndicatorPlacement.pane,
settings: [_period],
builder: (values, colors) =>
DmiIndicator(period: values['period']!.toInt(), colors: colors),
),
IndicatorType(
name: 'StochRSI',
description: 'Stochastic RSI: where the RSI sits in its own range.',
placement: IndicatorPlacement.pane,
settings: [
const IndicatorSetting(
key: 'rsiPeriod',
label: 'RSI period',
defaultValue: 14,
min: 2,
max: 200,
),
_periodOf(14),
const IndicatorSetting(
key: 'kSmoothing',
label: 'K smoothing',
defaultValue: 3,
min: 1,
max: 50,
),
const IndicatorSetting(
key: 'dSmoothing',
label: 'D smoothing',
defaultValue: 3,
min: 1,
max: 50,
),
],
builder: (values, colors) => StochRsiIndicator(
rsiPeriod: values['rsiPeriod']!.toInt(),
period: values['period']!.toInt(),
kSmoothing: values['kSmoothing']!.toInt(),
dSmoothing: values['dSmoothing']!.toInt(),
colors: colors,
),
),
IndicatorType(
name: 'ROC',
description: 'Rate of change: how far price has moved, in percent.',
placement: IndicatorPlacement.pane,
settings: [_periodOf(12)],
builder: (values, colors) => RocIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'TRIX',
description: 'TRIX: momentum of a triple-smoothed average.',
placement: IndicatorPlacement.pane,
settings: [
_periodOf(15),
const IndicatorSetting(
key: 'signalPeriod',
label: 'Signal',
defaultValue: 9,
min: 1,
max: 100,
),
],
builder: (values, colors) => TrixIndicator(
period: values['period']!.toInt(),
signalPeriod: values['signalPeriod']!.toInt(),
colors: colors,
),
),
IndicatorType(
name: 'VOLMA',
description: 'A moving average of volume.',
placement: IndicatorPlacement.pane,
settings: [_periodOf(20)],
builder: (values, colors) => VolumeMaIndicator(
period: values['period']!.toInt(),
color: colors?.firstOrNull,
),
),
IndicatorType(
name: 'AO',
description: 'Awesome oscillator: fast against slow midpoint averages.',
placement: IndicatorPlacement.pane,
settings: [
const IndicatorSetting(
key: 'fast',
label: 'Fast',
defaultValue: 5,
min: 2,
max: 100,
),
const IndicatorSetting(
key: 'slow',
label: 'Slow',
defaultValue: 34,
min: 2,
max: 200,
),
],
builder: (values, colors) => AwesomeIndicator(
fast: values['fast']!.toInt(),
slow: values['slow']!.toInt(),
color: colors?.firstOrNull,
),
),
]);