F# 如何在F中重写和优化此EMA计算#
这是一个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
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