Stately Conformance

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
module Analytics.Trading.Indicators.MovingAverages.Exponential where

-- a solution to http://lpaste.net/109689

import Control.Monad.State

import Analytics.Trading.Data.Row       -- http://lpaste.net/109658
import Data.Monetary.USD                -- http://lpaste.net/109653

ema' :: Int -> Double -> State (Int, Double) Double
ema' period row = get >>= \(n, s) -> 
   let α = 2.0 / (fromInteger $ toInteger (pred n)) -- n /= 1
       ans = α * row + (1.0 - α) * s
   in  put (min (succ n) period, ans) >> return ans

{-- So, with your defined EMA-12 and EMA-26, run them against a month of data

The above is a mapping function in the State domain; how to apply it over the
entire row-set?

 --}

emas :: Int -> [Double] -> State (Int, Double) [Double]
emas period = mapM (ema' period)

-- our our protocol function devolves (catastrophe) to
-- (State-less representation):

ema :: Int -> [Row] -> [Double]
ema period rows = emaF period (map (value . close) rows)

emaF :: Int -> [Double] -> [Double]
emaF period vals = evalState (emas period vals) (2, 0.0)

{-- For EMA-12: -------------------------------------------------------
*Analytics.Trading.Indicators.MovingAverages.Exponential> 
readRows "screens/GMCR-1mos.csv" >>= \rows -> 
return $ runState (emas 12 rows) (2, 0.0)
([230.0
114.3
114.13333333333333
114.10166666666666
114.63300000000001
114.15533333333335
114.79380952380953
115.62785714285715
116.09722222222223
116.6397777777778
117.20709090909092
117.58398347107439
118.13235011269721
118.60101372857042
118.84628395973944
119.17968687615044
119.51065289866854
119.78871600800153
120.16894946109215
120.27277683180266
120.37227195329308
120.06822250723978
120.07036386955981
120.20847952963985
120.68330143334168
121.08633753637046
121.13973071157582
121.48159785492567
121.63039824493917],(12,121.63039824493917))

-- For EMA-26 ----------------------------------------------------------

*Analytics.Trading.Indicators.MovingAverages.Exponential> 
readRows "screens/GMCR-1mos.csv" >>= \rows -> 
mapM_ (putStrLn . show) $ fst $ runState (emas 26 rows) (2, 0.0)
([230.0
114.3
114.13333333333333
114.10166666666666
114.63300000000001
114.15533333333335
114.79380952380953
115.62785714285715
116.09722222222223
116.6397777777778
117.20709090909092
117.55257575757577
118.02141025641026
118.40549450549452
118.61142857142859
118.87
119.12058823529412
119.33385620915033
119.60187134502924
119.71568421052632
119.82085714285714
119.71896103896104
119.75035573122531
119.84032608695652
120.0787
120.304404
120.39045168000001
120.60081554560001
120.73675030195203],(26,120.73675030195203))

Graph showing screen, SMA, EMA-12, and EMA-26 up at the twitter-answer and on
my blog at 

logicaltypes.blogspot.com/http://logicaltypes.blogspot.com/p/1haskelladay-problems-with-solutions.html

 --}
12:12: Warning: Redundant $
Found:
2.0 / (fromInteger $ toInteger (pred n))
Why not:
2.0 / fromInteger (toInteger (pred n))