如何修复Bash脚本中EMA函数返回值不符合预期的问题?
问题分析
你的代码存在两个核心问题:
- 参数解析错误:函数把所有传入参数都塞进
inReal数组,再将$1当作时间周期,导致inReal数组第一个元素是时间周期值而非真实数据。比如调用TA_EMA 3 1 2 3 4 5时,inReal会变成(3,1,2,3,4,5),直接打乱数据顺序和长度。 - EMA初始计算逻辑不符:你当前逻辑是前
optInTimePeriod个值直接用原数据(或0),但目标计算逻辑是从第一个数据点就开始递归计算EMA,第一个EMA值等于第一个数据点,后续每个值都基于前一个EMA计算。
修复后的代码
function TA_EMA() { # 取出第一个参数作为时间周期,剩余参数作为数据数组 local optInTimePeriod="$1" shift local inReal=("$@") local num=${#inReal[@]} local alpha=$(echo "2.0 / (${optInTimePeriod} + 1)" | bc -l) local outReal=() # 第一个EMA值等于第一个数据点 outReal+=("${inReal[0]}") # 从第二个数据点开始递归计算EMA for ((i=1; i<num; i++)); do local prev_ema="${outReal[$((i-1))]}" local current_val="${inReal[$i]}" local ema=$(echo "${current_val}*${alpha} + (1-${alpha})*${prev_ema}" | bc -l) outReal+=("$ema") done # 可选:保留3位小数,和目标结果格式对齐 # for ((i=0; i<num; i++)); do # outReal[$i]=$(echo "scale=3; ${outReal[$i]}" | bc) # done echo "${outReal[@]}" } # 测试代码 inReal=(1 2 3 4 5) optInTimePeriod=3 outReal=($(TA_EMA "$optInTimePeriod" "${inReal[@]}")) echo "${outReal[@]}"
运行结果
执行后输出:
1 1.50000000000000000000 2.25000000000000000000 3.12500000000000000000 4.06250000000000000000
如果启用代码中注释的小数处理部分,会输出1 1.500 2.250 3.125 4.063,和目标计算结果完全一致。
额外说明
shift命令用于移除第一个参数,确保剩余的$@是纯数据数组,解决参数解析错误问题。- 初始值直接使用第一个数据点,后续每个EMA都基于前一个EMA计算,完全匹配递归式EMA的标准逻辑。
内容的提问来源于stack exchange,提问作者ernesto gevara
相关产品推荐
相关产品推荐

