Skip to content

signals · 信号层

信号层在技术指标之上做事件识别——金叉 / 死叉、超买 / 超卖、布林突破、SAR 反转。同样是纯计算、零网络、零依赖,从 subpath stock-sdk/signals 导入。

ts
import { calcSignals } from 'stock-sdk/signals'

核心只有一个函数 calcSignals:输入一段已经算好指标的 K 线(KlineWithIndicators[]),输出一个按时间升序的信号事件数组。

方法表

方法说明
calcSignals(klines, options?)从带指标的 K 线序列识别信号,返回 Signal[]

前置条件

calcSignals 不自己算指标,它读取 K 线上已有的 ma / macd / kdj / rsi / boll / sar 字段。所以先用 addIndicators(或 sdk.kline.withIndicators)把指标贴上去,再传进来。

重要:信号侧的周期必须与指标侧实际算出的键一致。例如要识别 5/20 MA 金叉,addIndicators 必须算了 ma5ma20;RSI 同理(信号默认读 rsi6)。周期不匹配会抛 InvalidArgumentError(而非静默返回空数组)。

信号类型

SignalType 共 14 种,覆盖六类形态:

类别信号类型触发条件
MA 金叉 / 死叉ma_golden_cross / ma_death_cross快线 maFast 上穿 / 下穿 慢线 maSlow
MACD 金叉 / 死叉macd_golden_cross / macd_death_crossdif 上穿 / 下穿 dea
KDJ 金叉 / 死叉kdj_golden_cross / kdj_death_crossk 上穿 / 下穿 d
KDJ 超买 / 超卖kdj_overbought / kdj_oversoldk > 超买阈值(默认 80)/ < 超卖阈值(默认 20)
RSI 超买 / 超卖rsi_overbought / rsi_oversoldrsi > 超买阈值(默认 70)/ < 超卖阈值(默认 30)
BOLL 突破boll_break_upper / boll_break_lower收盘价突破布林上轨 / 跌破下轨
SAR 反转sar_reversal_up / sar_reversal_downSAR 趋势方向由跌转涨 / 由涨转跌

options

只为传入的指标计算信号——不传的位不产生对应信号:

ts
interface SignalOptions {
  /** MA 金叉/死叉:fast 上穿/下穿 slow */
  ma?: { fast: number; slow: number }
  /** MACD 金叉/死叉:DIF 上穿/下穿 DEA */
  macd?: boolean
  /** KDJ 金叉死叉 + 超买超卖(阈值默认 80 / 20) */
  kdj?: { overbought?: number; oversold?: number }
  /** RSI 超买超卖(默认 period=6,阈值 70 / 30) */
  rsi?: { period?: number; overbought?: number; oversold?: number }
  /** BOLL 收盘突破上/下轨 */
  boll?: boolean
  /** SAR 趋势反转 */
  sar?: boolean
}

kdj{} 即用默认阈值,也可覆写 overbought / oversoldrsiperiod 必须与指标侧算出的 RSI 周期对应。

调用示例

ts
import { addIndicators } from 'stock-sdk/indicators'
import { calcSignals } from 'stock-sdk/signals'

// 1. 取 K 线(回测口径建议后复权)
const klines = await sdk.kline.cn('600519', { adjust: 'hfq' })

// 2. 计算需要的指标(注意 MA/RSI 周期要和信号侧对齐)
const enriched = addIndicators(klines, {
  ma: { periods: [5, 20] },
  macd: true,
  kdj: true,
  rsi: { periods: [6] },
  boll: true,
  sar: true,
})

// 3. 识别信号
const signals = calcSignals(enriched, {
  ma: { fast: 5, slow: 20 },
  macd: true,
  kdj: { overbought: 80, oversold: 20 },
  rsi: { period: 6, overbought: 70, oversold: 30 },
  boll: true,
  sar: true,
})

// 只取最近一根 K 线上的金叉
const lastIdx = enriched.length - 1
const todayGolden = signals.filter(
  s => s.index === lastIdx && s.type.endsWith('golden_cross'),
)

返回说明

calcSignals 返回 Signal[],按 K 线顺序排列:

ts
interface Signal {
  /** 信号类型,见上表 */
  type: SignalType
  /** 对应 K 线的 timestamp(UTC ms,恒非空) */
  at: number
  /** 对应 K 线在输入数组中的下标 */
  index: number
  /** 附加信息,如金叉的快慢周期、超买超卖的指标值 */
  detail?: Record<string, number>
}
字段类型说明
typeSignalType14 种信号之一
atnumber触发 K 线的 timestamp(UTC 毫秒);恒非空
indexnumber触发 K 线在输入数组中的下标,可回查整根 K 线
detailRecord<string, number>?上下文,如 { fast: 5, slow: 20 }{ rsi: 72.4 }

时间锚点一致性:v2 把 K 线 timestamp 改为 number | null,但 Signal.at 恒为 number——calcSignals跳过 timestampnull 的 K 线(无有效时间锚点不产信号),保证信号与时间轴类型一致。

纯计算、零网络、零依赖、浏览器 + Node 双端可用。具体字段以实现为准。

相关