this is an EMA calculation:
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
you can test it with:
EMA 3 [|1.;3.;4.;7.;5.;6.;9.;8.|]
and it gives:
[|NaN;Nan;2.66.;4.83;4.91;5.45;7.22;7.61|]
my first question is regarding the loop at the end:
for i in seq {period .. (data.Length - 1)} do
output.[i] <- (data.[i] * multiplier) + (output.[i - 1] * (1. - multiplier))
can this be rewritten using a sequence operator?
my second question is: is there a fast F# implementation floating around? I couldn't find any.
Well, I don't know about floating around, but I did just write an EMA function yesterday. It looks like this:
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
My version looks all the way back, rather than only a number of periods, as your version. If you want that behaviour instead, you could replace the state of type float option
in my version with a float[]
, or even implement it using the Array.windowed
function.
By the way, it could have been implemented using
Array.mapFold
as well, but I thinkArray.scan
is easier to understand.