如何基于上一周期计算Zenbot中的lib.ema指数移动平均线?
Zenbot环境下指数移动平均线(EMA)实现函数
这里有一个专为Zenbot环境编写的EMA计算函数,它基于上一周期的EMA值推导当前周期结果,完美适配Zenbot的策略上下文(s对象)结构:
函数参数说明
s: Zenbot的核心策略上下文对象,包含当前周期数据(s.period)和历史回溯数据集(s.lookback)key: 自定义的EMA存储键名(比如ema20),计算结果会写入s.period[key],方便后续策略调用length: EMA的周期长度(例如传入20就表示计算20周期EMA)source_key(可选): 计算EMA的源数据字段,默认使用收盘价close,你也可以指定open、high等其他字段
核心逻辑解析
这个函数的计算逻辑完全遵循EMA标准算法,同时兼容Zenbot的数据结构:
- 首先处理可选参数,若未传入
source_key则默认使用收盘价 - 只有当历史回溯数据长度满足周期要求时,才会执行计算(避免数据不足导致的误差)
- 获取上一周期的EMA值:
- 如果上一周期EMA不存在或是无效值(NaN),会先计算**简单移动平均线(SMA)**作为EMA的初始值(取前
length个周期的源数据平均值) - 如果上一周期EMA有效,直接复用该值作为计算基础
- 如果上一周期EMA不存在或是无效值(NaN),会先计算**简单移动平均线(SMA)**作为EMA的初始值(取前
- 计算EMA的平滑乘数:
2 / (length + 1),这个值决定了新数据对EMA的权重 - 用标准EMA公式计算当前周期的EMA值,并将结果存入当前周期的数据对象中
完整代码实现
function ema (s, key, length, source_key) { if (!source_key) source_key = 'close' if (s.lookback.length >= length) { var prev_ema = s.lookback[0][key] if (typeof prev_ema === 'undefined' || isNaN(prev_ema)) { var sum = 0 s.lookback.slice(0, length).forEach(function (period) { sum += period[source_key] }) prev_ema = sum / length } var multiplier = 2 / (length + 1) s.period[key] = (s.period[source_key] - prev_ema) * multiplier + prev_ema } }
内容的提问来源于stack exchange,提问作者user901790




