如何修复在bash脚本中EMA函数未返回预期值的问题?

huangapple go评论57阅读模式
英文:

How to fix EMA function not returning expected values in bash script?

问题

以下是您要翻译的代码部分:

function TA_EMA() {
    local inReal=("$@")
    local optInTimePeriod=$1
    local num=${#inReal[@]}
    local alpha=$(echo "2.0 / (${optInTimePeriod} + 1)" | bc -l)
    local outReal=()

    for ((i=0; i<num; i++)); do
        if (( i < optInTimePeriod )); then
            outReal+=("${inReal[i]}")
        else
            local ema=$(echo "${inReal[i]}*${alpha} + (1-${alpha})*${outReal[$((i-1))]}" | bc -l)
            outReal+=("$ema")
        fi
    done
    echo "${outReal[@]}"
}

inReal=(1 2 3 4 5)
optInTimePeriod=3
outReal=($(TA_EMA $optInTimePeriod "${inReal[@]}"))
echo "${outReal[@]}"
function TA_EMA() {
    local inReal=("$@")
    local optInTimePeriod=$1
    local num=${#inReal[@]}
    local alpha=$(echo "2 / (${optInTimePeriod} + 1)" | bc -l)
    local outReal=()

    for ((i=0; i<num; i++)); do
        if (( i < optInTimePeriod )); then
            outReal+=(0)
        elif (( i == optInTimePeriod )); then
            local sum=0
            for ((j=0; j<optInTimePeriod; j++)); do
                sum=$((sum+inReal[j]))
            done
            local sma=$((sum/optInTimePeriod))
            outReal+=("$sma")
        else
            local ema=$(echo "${inReal[i]}*$alpha + (1-$alpha)*${outReal[$((i-1))]}" | bc -l)
            outReal+=("$ema")
        fi
    done
    echo "${outReal[@]}"
}

希望这对您有所帮助。

英文:

Hi i have created this function in bash

function TA_EMA() {
    local inReal=("$@")
    local optInTimePeriod=$1
    local num=${#inReal[@]}
    local alpha=$(echo "2.0 / (${optInTimePeriod} + 1)" | bc -l)
    local outReal=()

    for ((i=0; i<num; i++)); do
        if (( i < optInTimePeriod )); then
            outReal+=("${inReal[i]}")
        else
            local ema=$(echo "${inReal[i]}*${alpha} + (1-${alpha})*${outReal[$((i-1))]}" | bc -l)
            outReal+=("$ema")
        fi
    done
    echo "${outReal[@]}"
}


inReal=(1 2 3 4 5)
optInTimePeriod=3
outReal=($(TA_EMA $optInTimePeriod "${inReal[@]}"))
echo "${outReal[@]}"

if i calculate Ema in this site https://goodcalculators.com/exponential-moving-average-calculator/ return 1,1.5,2.25,3.125,4.063
but my code return
3 1 2 2.50000000000000000000 3.25000000000000000000 4.12500000000000000000

i try also in this mode

function TA_EMA() {
    local inReal=("$@")
    local optInTimePeriod=$1
    local num=${#inReal[@]}
    local alpha=$(echo "2 / (${optInTimePeriod} + 1)" | bc -l)
    local outReal=()

    for ((i=0; i<num; i++)); do
        if (( i < optInTimePeriod )); then
            outReal+=(0)
        elif (( i == optInTimePeriod )); then
            local sum=0
            for ((j=0; j<optInTimePeriod; j++)); do
                sum=$((sum+inReal[j]))
            done
            local sma=$((sum/optInTimePeriod))
            outReal+=("$sma")
        else
            local ema=$(echo "${inReal[i]}*$alpha + (1-$alpha)*${outReal[$((i-1))]}" | bc -l)
            outReal+=("$ema")
        fi
    done
    echo "${outReal[@]}"
}

答案1

得分: 2

你可以将 optInTimePeriod 作为函数中 inReal 的一部分,如下所示:

local inReal=("$@")
local optInTimePeriod=$1

而不是:

local optInTimePeriod=$1
shift                    # 从$@中移除$1
local inReal=("$@")

第二个问题是,你在所有 i < 3 的值上都添加了当前值:

if (( i < optInTimePeriod )); then
    outReal+=("${inReal[i]}")

应该只在 i == 0 时添加。

通过使用 readarray 进行了一些简化:

#!/bin/bash

TA_EMA() {
    local optInTimePeriod=$1
    shift
    local inReal=( "$@" )
    local num=${#inReal[@]}
    local alpha
    alpha=$(echo "2 / (${optInTimePeriod} + 1)" | bc -l)
    local ema

    for ((i=0; i<num; i++)); do
        if (( i == 0 )); then
            ema=${inReal[0]}
        else
            ema=$(echo "${inReal[i]}*${alpha} + (1-${alpha})*${ema}" | bc -l)
        fi
        echo "$ema"
    done
}

inReal=(1 2 3 4 5)
optInTimePeriod=3
readarray -t outReal < <(TA_EMA $optInTimePeriod "${inReal[@]}")

for ema in "${outReal[@]}"
do
    echo "$ema"
done
英文:

You make the optInTimePeriod a part of inReal in your function:

local inReal=(&quot;$@&quot;)
local optInTimePeriod=$1

instead do:

local optInTimePeriod=$1
shift                    # remove $1 from $@
local inReal=(&quot;$@&quot;)

The second problem is that you add the current value for all values where i &lt; 3:

if (( i &lt; optInTimePeriod )); then
    outReal+=(&quot;${inReal[i]}&quot;)

it should only be when i == 0.

Somewhat simplified using readarray instead:

#!/bin/bash

TA_EMA() {
    local optInTimePeriod=$1
    shift
    local inReal=( &quot;$@&quot; )
    local num=${#inReal[@]}
    local alpha
    alpha=$(echo &quot;2 / (${optInTimePeriod} + 1)&quot; | bc -l)
    local ema

    for ((i=0; i&lt;num; i++)); do
        if (( i == 0 )); then
            ema=${inReal[0]}
        else
            ema=$(echo &quot;${inReal[i]}*${alpha} + (1-${alpha})*${ema}&quot; | bc -l)
        fi
        echo &quot;$ema&quot;
    done
}


inReal=(1 2 3 4 5)
optInTimePeriod=3
readarray -t outReal &lt; &lt;(TA_EMA $optInTimePeriod &quot;${inReal[@]}&quot;)

for ema in &quot;${outReal[@]}&quot;
do
    echo &quot;$ema&quot;
done

huangapple
  • 本文由 发表于 2023年3月7日 07:18:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75656696.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定