这是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
您可以使用以下方法进行测试:
EMA 3 [|1.;3.;4.;7.;5.;6.;9.;8.|]
它给出:
[|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))
可以使用序列运算符重写吗?
我的第二个问题是:是否有快速实现的F#实现?我找不到。
好吧,我不了解浮动,但是昨天我确实写了一个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 option
我版本中的type状态float[]
,甚至可以使用Array.windowed
函数来实现它。
顺便说一句,它也可以使用来实现
Array.mapFold
,但我认为Array.scan
更容易理解。