技术指标
const id = chart.indicators.add({ type: 'BOLL', params: { period: 26 } });
chart.indicators.update(id, { colors: { mid: '#f5b942' } });
chart.indicators.remove(id);添加指标
interface IndicatorInput {
id?: string; // 自动生成,例如 'macd-1'
type: string; // 'MA'、'MACD' 等,或已注册的自定义类型
params?: Record<string, number | number[]>; // 覆盖下文列出的默认值
pane?: string; // 'main'、'new'(独立子图)或已有子图的 id
source?: PriceSource | IndicatorReference; // 默认 'close'
visible?: boolean;
colors?: Record<string, string>; // 按输出的 key 指定
}
type PriceSource = 'open' | 'high' | 'low' | 'close' | 'hl2' | 'hlc3' | 'ohlc4';
type IndicatorReference = { kind: 'indicator'; id: string; key?: string }; // 见下文叠加指标默认放在主图,震荡指标默认放在新的子图。要把两个震荡指标放进同一个子图,把第二个指标放到第一个指标所在的子图即可:
const rsi = chart.indicators.add({ type: 'RSI' });
chart.indicators.add({ type: 'WR', pane: chart.indicators.get(rsi)!.pane });修改 params 或 source 会重新计算指标;参数会经过校验,未知的键会被拒绝。
指标叠加指标
指标可以读取另一个指标的输出,而不是价格:例如 RSI 的均线、成交量的布林带、MACD 信号线的 EMA。
const rsi = chart.indicators.add({ type: 'RSI', params: { periods: [14] } });
chart.indicators.add({
type: 'MA',
params: { periods: [9] },
source: { kind: 'indicator', id: rsi }
});
const macd = chart.indicators.add({ type: 'MACD' });
chart.indicators.add({ type: 'EMA', source: { kind: 'indicator', id: macd, key: 'dea' } });- 不指定
key时读取第一个输出;源指标改参数导致输出键变化(例如rsi6变成rsi14)时会自动跟随。指定了key时这个输出必须一直存在,否则会导致它消失的修改会抛出错误。 - 叠加类指标默认放在所读取指标的子图里,震荡类指标放到新子图。精度为
price的指标沿用源指标的精度。 - 计算函数把源指标的值当作价格,同时也作为这根 K 线的开高低收。源指标没有值的 K 线(预热期)会被跳过,所以均线要等源指标有值之后才开始计算。
- 实时推送仍是增量计算;修改源指标时,读取它的指标会重新计算。
- 指标被其他指标读取时不能删除,指标之间也不能循环读取。
- 图例会标出输入,例如
MA 9 · RSI。
放置指标
pane 选择子图,scale 选择子图中的价格坐标:right(默认)、left,或者指标自己的叠加坐标。把成交量放在主图底部:
chart.indicators.add({ type: 'VOL', pane: 'main', scale: 'volume' });
chart.priceScale('main', 'volume').setMargins({ top: 0.8, bottom: 0 });给 K 线着色
mainSeries.barColor 可以按任意条件给主序列的单根 K 线着色:返回一个颜色,或返回 null 使用默认的涨跌色。回调会拿到这根 K 线,可以读取指标在这根 K 线上的值;每次重绘时对可见的 K 线调用。蜡烛图、空心蜡烛图、美国线和高低线支持着色。
const ma = chart.indicators.add({ type: 'MA', params: { periods: [20] } });
chart.applyOptions({
mainSeries: {
barColor: ({ bar, indicator }) => (bar.close > indicator(ma) ? '#0d9488' : null)
}
});indicator(id, key?) 读取指标的某个输出(默认第一个),指标没有值时返回 NaN。回调返回字符串和 null 之外的值,或者读取了不存在的指标时,图表绘制时会抛出错误。
内置指标
计算公式遵循国内看盘软件(同花顺 / 通达信)的口径:EMA 和 SMA(X, N, 1) 平滑以第一个值作为初始值,MACD 柱乘以 2,KDJ 的 K 和 D 从 50 起算,标准差为总体标准差。无法计算的值(预热期、除以零)留空,而不是用某个数字代替。
| 类型 | 子图 | 参数(默认值) | 输出 |
|---|---|---|---|
MA | 主图 | periods [5, 10, 20, 30] | ma5、ma10…… |
EMA | 主图 | periods [12, 26] | ema12、ema26 |
SMMA | 主图 | periods [7, 14] | smma7、smma14:平滑移动平均(Wilder) |
BOLL | 主图 | period 20、multiplier 2 | mid、upper、lower |
VOL | 新子图 | periods [5, 10] | volume(柱状)、ma5、ma10 |
MACD | 新子图 | fast 12、slow 26、signal 9 | dif、dea、macd(柱状) |
RSI | 新子图 | periods [6, 12, 24] | rsi6、rsi12、rsi24 |
KDJ | 新子图 | period 9、k 3、d 3 | k、d、j |
WR | 新子图 | periods [14, 28] | wr14、wr28(最高价处为 0,最低价处为 100) |
CCI | 新子图 | period 14 | cci |
ROC | 新子图 | period 12 | roc |
BIAS | 新子图 | periods [6, 12, 24] | bias6、bias12、bias24 |
OBV | 新子图 | — | obv |
VR | 新子图 | period 24 | vr |
EMV | 新子图 | period 14、signal 9 | emv、maemv |
MFI | 新子图 | period 14 | mfi |
ATR | 新子图 | period 14 | atr |
STD | 新子图 | period 20 | std |
DMI | 新子图 | period 14 | pdi、mdi、adx、adxr |
periods 类参数最多接受 8 个值,每个值绘制一条线。
读取数值
chart.indicators.valuesAt(id); // 最新一根 K 线
chart.indicators.valuesAt(id, chart.crosshair.get()?.index ?? chart.data.length - 1);
// [{ key: 'dif', label: 'DIF', color: '#f5b942', value: 0.0293, text: '0.0293' }, …]图表也会在每个子图的图例中显示这些值(options.legend.visible)。预警可以监控任意一项输出,参见交易。
自定义指标
先在图表上注册类型,然后像内置指标一样添加即可。最简单的形式是根据最近若干根 K 线算出每个值:
chart.indicators.register<{ period: number }>('MOM', {
name: 'MOM',
pane: 'new',
precision: 2,
params: { period: { default: 10, min: 1, integer: true } },
outputs: () => [{ key: 'mom', label: 'MOM', plot: { kind: 'line' } }],
levels: () => [0],
lookback: ({ period }) => period + 1,
compute: (window) => [window.price(window.length - 1) - window.price(0)]
});
chart.indicators.add({ type: 'MOM', params: { period: 20 } });compute() 接收最近的 lookback 根 K 线(按从旧到新排列),并为每项输出返回一个数字(无值时返回 NaN)。窗口填满之后,每根 K 线调用一次。
对于取值依赖全部历史的指标(例如指数平均),请改为实现流式计算器。next() 每次处理一根 K 线;clone() 必须复制全部状态,因为图表会在最新一根 K 线之前保存一个检查点,每个 tick 只重放这一根 K 线。
import type { Bar, IndicatorStream } from '@kumochart-sdk/core';
class EmaStream implements IndicatorStream {
constructor(
private readonly alpha: number,
private value = Number.NaN
) {}
next(_bar: Bar, price: number): number[] {
this.value = Number.isNaN(this.value) ? price : this.value + this.alpha * (price - this.value);
return [this.value];
}
clone(): EmaStream {
return new EmaStream(this.alpha, this.value);
}
}
chart.indicators.register<{ period: number }>('MY_EMA', {
name: 'EMA',
pane: 'main',
precision: 'price',
params: { period: { default: 20, min: 1, integer: true } },
outputs: () => [{ key: 'ema', label: 'EMA', plot: { kind: 'line' } }],
create: ({ period }) => new EmaStream(2 / (period + 1))
});定义参考
| 字段 | 说明 |
|---|---|
name | 显示在图例中 |
pane | 'main' 或 'new':默认放置位置 |
params | { key: { default, min?, max?, integer?, label? } };默认值为数组时即为列表参数 |
outputs(params) | [{ key, label, plot, color?, legend? }],plot 见绘制方式;legend: false 的值不显示在图例中 |
levels?(params) | 水平参考线 |
fills? | [{ from, to }]:在两项输出之间填充颜色 |
precision | 小数位数、'price'(跟随主序列)或 'volume'(紧凑格式,例如 1.2M) |
range? | 该子图固定的坐标范围,例如 { min: 0, max: 100 } |
create(params) 或 lookback(params) + compute(window, params) | 计算逻辑 |
绘制方式
plot | 画法 |
|---|---|
{ kind: 'line', style? } | 线;style 为 'solid'、'dashed' 或 'dotted' |
{ kind: 'histogram', colorBy } | 从 0 开始的柱子,按数值正负('sign')、涨跌('change')或 K 线方向('bar')着色 |
{ kind: 'columns', from, width?, hollow? } | 用该输出的颜色,从 from(另一项输出的 key,或一个数)画到该值的柱子,两者都有值时才画 |
{ kind: 'marker', shape?, text?, size? } | 在该值处画形状(同标记)、文字或两者,有值时才画 |
{ kind: 'hidden' } | 不画:只显示在图例中,可供预警读取 |
值为 NaN 时不画,所以柱子和标记只出现在有值的 K 线上:信号、高亮的 K 线、自定义 K 线的实体。坐标会为柱子的两端留出空间。向上的形状从下方指向该值,向下的形状从上方指向该值,所以放在最低价的箭头会在 K 线下方;圆形和方形就在该值处。标记的文字在形状外侧,没有形状时就在该值处。不指定颜色时,箭头和三角形使用主题的 buy、sell 颜色。
chart.indicators.register('SIGNALS', {
name: 'Signals',
pane: 'main',
precision: 'price',
params: {},
outputs: () => [
// 指向连涨三根的 K 线最低价的箭头。
{
key: 'buy',
label: 'Buy',
plot: { kind: 'marker', shape: 'arrow-up', text: 'B' },
legend: false
},
// 这些 K 线的实体,从开盘价到收盘价。
{ key: 'open', label: 'Open', plot: { kind: 'hidden' }, legend: false },
{ key: 'close', label: 'Close', plot: { kind: 'columns', from: 'open' }, legend: false }
],
lookback: () => 4,
compute: (window) => {
const bars = [0, 1, 2, 3].map((index) => window.bar(index));
const rising = bars
.slice(1)
.every((bar, index) => bar.close > (bars[index]?.close ?? Infinity));
const last = bars[3];
return rising && last ? [last.low, last.open, last.close] : [NaN, NaN, NaN];
}
});