To try out F#I decided to make a function to calculate simple moving average (SMA) and exponential moving average (EMA). The SMA and EMA have enough math to try many of the features of F# and functional programming.
The first thing I learned was F# has a way to quickly execute code. If you haven’t played with F#’s Interactive it’s sort of like a REPL loop. While coding you can highlight the code and do a Alt-Enter to execute it. It’s very convenient.
To keep with the functional style of programming I put the SMA and EMA into a type. In OO this would be the equivalent of using a base class for moving averages and then creating classes for SMA and EMA. As you can see in F# this is a very small amount of code using type declaration / discriminators. You can see comments in my code below for things I learned and picked up while doing this exercise.
type movingAverage = | Simple of int * seq<float> | Exponential of int * float list // sma is an example of using a private / utility function // pipelining operator |> allows execution of a series of operations let sma(size, seq) = Seq.windowed size seq |> Seq.map Array.average // example of Matching on discriminated unions let calculate(movingAverage) = match movingAverage with |Simple(size, seq) -> sma(size, seq) |Exponential(period, data) -> let multiplier = 2.0 / (1.0 + (float period)) //Calc a sum to use in the SMA to prime the EMA calculation //http://bit.ly/bG73sx Slice like functionality from a List let iniSum = data |> List.toSeq |> Seq.take (int period) |> Seq.sum //first float from list using period as the start let firstItem = data |> List.toSeq |> Seq.skip (int period) |> Seq.head //setup first ema with sma let firstEma = (iniSum / (float period)) let out : float array = Array.zeroCreate (List.length data) //setup initial Ema to previous day out.[period - 2] <- firstEma //calculate the rest of the Ema's for i in period - 1 .. (List.length data - 1) do let close = data.[i] let prev = out.[i - 1] out.[i] <- multiplier * (close - prev) + prev Array.toSeq out // F# Note - intrinsic type extensions adds the calculate member to the movingAverage type type movingAverage with member x.calculate() = calculate(x) //Test Simple let simpleMovingAverage = Simple(10, (Seq.map float [|1..30|])) let avgs = simpleMovingAverage.calculate(); for avg in avgs do printfn "%f" avg //Test Exponential let expMovingAverage = Exponential(10, [1.0..30.0]) let expAvgs = expMovingAverage.calculate(); for e in expAvgs do printfn "%f" e
a big thanks to this F# technical indicator series.
Leave a Reply