F# 如何在F中重写和优化此EMA计算#

F# 如何在F中重写和优化此EMA计算#,f#,F#,这是一个EMA计算: let EMA (period : int) (data : double[]) : double[] = let multiplier = 2.0 / (double)(period + 1) let output = Array.create data.Length System.Double.NaN output.[period - 1] <- data.[0..period - 1] |> Seq.average fo

这是一个EMA计算:

let EMA (period : int) (data : double[]) : double[] =
    let multiplier = 2.0 / (double)(period + 1)
    let output = Array.create data.Length System.Double.NaN 

    output.[period - 1] <- data.[0..period - 1] |> Seq.average
    for i in seq {period .. (data.Length - 1)} do
        output.[i] <- (data.[i] * multiplier) + (output.[i - 1] * (1. - multiplier))

    output
它给出了:

[|NaN;Nan;2.66.;4.83;4.91;5.45;7.22;7.61|]
我的第一个问题是关于最后的循环:

for i in seq {period .. (data.Length - 1)} do
    output.[i] <- (data.[i] * multiplier) + (output.[i - 1] * (1. - multiplier))
seq{period..(data.Length-1)}do中i的

输出。[i]嗯,我不知道浮动,但我昨天确实写了一个EMA函数。看起来是这样的:

let ema alpha vs =
    (None, vs)
    ||> Array.scan (fun prev x ->
        match prev with
        | None -> Some(x)
        | Some(s) -> Some(alpha*x + (1. - alpha)*s))
    |> Array.choose id

我的版本与您的版本一样,可以追溯到很久以前,而不仅仅是几个时期。如果你想改变这种行为,你可以用一个
float[]
替换我版本中类型
float选项的状态,或者甚至使用
Array.windowed
函数来实现它。

我刚刚运行了你的测试示例-结果是
[|nan;nan;20.0;30.0;40.0;50.0;60.0;70.0 |]
。你遗漏了什么吗?对不起,是的,我没有看到我只是问题中的输出,而不是输入。我已经解决了这个问题。顺便说一下,它也可以使用
Array.mapFold
实现,但我认为
Array.scan
更容易理解。
let ema alpha vs =
    (None, vs)
    ||> Array.scan (fun prev x ->
        match prev with
        | None -> Some(x)
        | Some(s) -> Some(alpha*x + (1. - alpha)*s))
    |> Array.choose id