Simple Moving Averages as a Haskell Library

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
module Analytics.Trading.Indicators.MovingAverages.Simple where

import Data.Time
import Control.Arrow

import Analytics.Trading.Data.Row      -- http://lpaste.net/109658
import Control.Comonad                 -- http://lpaste.net/107661
import Control.List                    -- http://lpaste.net/107211
import Control.Scan.CSV                -- http://lpaste.net/109651

import Data.Monetary.USD               -- http://lpaste.net/109653


-- Our SMA function: gives a simple moving average of a data stream.

sma :: Int -> [Row] -> Double
sma period rows = 
   let val = value . close
   in  either (map val >>> sum >>> flip mean period) val
                         $ mbtake rows period

mean :: Double -> Int -> Double
mean sum count = sum / fromIntegral count

{--

run with, e.g.:

*Analytics.Trading.Indicators.MovingAverages.Simple> 
readRows "screens/GMCR-1mos.csv" >>= \rows -> return $ rows =>> sma 15
[117.16133333333332,117.53999999999999,117.98666666666666,118.45266666666666,
 118.97333333333334,119.32733333333336,119.83533333333334,119.9893333333333,
 120.11933333333333,120.32533333333332,120.59266666666666,120.802,
 120.94200000000001,121.10333333333334,121.20933333333336,120.68,121.0,121.04,
 121.88,120.74,120.82,118.7,120.08,120.83,122.82,122.9,121.38,123.02,122.3]

A picture is worth 1,000 words. This problem statement was more than 1,000
words, so I suppose I could have just lpasted the picture here and be done
with it, eh?

Picture on @1HaskellADay tweet of this solution and on the 1HaskellADay page
of http://logicaltypes.blogspot.com.

 --}