simfin-1.0.0: src/SimFin/Types/Prices.hs
{-|
Module : SimFin.Types.Prices
Description : Types to represent SimFin price results.
Copyright : (c) Owen Shepherd, 2022
License : MIT
Maintainer : owen@owen.cafe
-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module SimFin.Types.Prices
( PricesRow(..)
, PricesKeyed(..)
) where
import Data.Aeson
import Data.Text (Text)
import Data.Time.Calendar (Day)
import SimFin.Types.StringFrac
import SimFin.Internal
-- | Prices of a company over a single day.
data PricesRow a
= PricesRow
{ simFinId :: Int
, ticker :: Text
, date :: Maybe Day
, open :: a
, high :: a
, low :: a
, close :: a
, adjClose :: a
, volume :: Integer
, dividend :: Maybe a
, commonSharesOutstanding :: Maybe Integer
} deriving (Functor, Show)
instance (Read a, RealFrac a) => FromJSON (PricesRow a) where
parseJSON = withObject "PricesRow" $ \v -> fmap (fmap unStringFrac) $ PricesRow
<$> v .: "SimFinId"
<*> v .: "Ticker"
<*> v .: "Date"
<*> v .: "Open"
<*> v .: "High"
<*> v .: "Low"
<*> v .: "Close"
<*> v .: "Adj. Close"
<*> v .: "Volume"
<*> v .: "Dividend"
<*> v .: "Common Shares Outstanding"
-- | Wrapper to parse a PricesRow record from SimFin's JSON format.
newtype PricesKeyed a = PricesKeyed { unKeyPrices :: [PricesRow a] }
instance (Read a, RealFrac a) => FromJSON (PricesKeyed a) where
parseJSON o = PricesKeyed <$> (traverse parseJSON =<< createKeyedRows o)