summaryrefslogtreecommitdiff
path: root/examples/example2/Example2.hs
blob: e9e043c8920238fa2914c7179ab859004ec5f80d (plain)
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
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}

import           Data.Aeson
import qualified Data.Text         as T
import           GHC.Generics
import           Porcupine

import           Prelude           hiding (id, (.))


-- This example uses the porcupine to read a data that represents the evloution of a given stock in given data and
-- gives back the average and standard deviation of the stock on that date.

data Stockdaily = Stockdaily {date :: String , close :: Double}
  deriving (Generic)
instance FromJSON Stockdaily

newtype Stock = Stock { chart :: [Stockdaily] }
  deriving (Generic)
instance FromJSON Stock

getCloseStock :: Stock -> [Double]
getCloseStock s = map close (chart s)

-- | How to load Stock prices
stockFile :: DataSource Stock
stockFile = dataSource ["Inputs", "Stock"]
                       (somePureDeserial JSONSerial)

-- | How to write the smoothed stock prices
globalMatrix :: DataSink (Tabular [[Double]])
globalMatrix = dataSink ["Outputs" , "globalData"]
                        (somePureSerial (CSVSerial (T.pack "csv") False ','))

avg :: [Double] -> Double
avg list = let s = sum list
               n = fromIntegral (length list)
               in s/n

msliding :: Int -> [a] -> [[a]]
msliding n p = case p of
  []     -> []
  (_:xs) -> [take n p] ++ (msliding n xs)

-- | The simple computation we want to perform
computeSmoothedCurve :: Stock -> [Double]
computeSmoothedCurve s = curve
  where
    price = getCloseStock s
    curve = map avg (msliding 10 price)

analyseStocks :: (LogThrow m) => PTask m () ()
analyseStocks =
   arr (const ["aapl"::TRIndex, "fb" , "googl"])  -- We want the stocks for some
                                                 -- fixed set of companies
   >>> loadDataList "company" stockFile
   >>> arr (Tabular Nothing . map (\(_idx,stock) -> computeSmoothedCurve stock))
   >>> writeData globalMatrix

main :: IO ()
main = runPipelineTask (FullConfig "example2" "porcupine-example2.yaml" "porcupine-core/examples/example2/data" ())
                          -- The CLI/Yaml configuration to use (prog name,
                          -- default config file to create, and default root to
                          -- use for the porcupine tree)
                       (baseContexts "")
                          -- The contexts to use. 'baseContexts' is the
                          -- minimum. It gives out katip logging and local files
                          -- access (through ResourceT). The string param is the
                          -- top namespace for the logger. When we use
                          -- FullConfig (and therefore CLI), the progName for
                          -- the CLI given above ("example1") will be inherited
                          -- by the logger, so we can leave it blank
                       analyseStocks ()