{-|
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
  { PricesRow a -> Int
simFinId :: Int
  , PricesRow a -> Text
ticker :: Text
  , PricesRow a -> Maybe Day
date :: Maybe Day
  , PricesRow a -> a
open :: a
  , PricesRow a -> a
high :: a
  , PricesRow a -> a
low :: a
  , PricesRow a -> a
close :: a
  , PricesRow a -> a
adjClose :: a
  , PricesRow a -> Integer
volume :: Integer
  , PricesRow a -> Maybe a
dividend :: Maybe a
  , PricesRow a -> Maybe Integer
commonSharesOutstanding :: Maybe Integer
  } deriving (a -> PricesRow b -> PricesRow a
(a -> b) -> PricesRow a -> PricesRow b
(forall a b. (a -> b) -> PricesRow a -> PricesRow b)
-> (forall a b. a -> PricesRow b -> PricesRow a)
-> Functor PricesRow
forall a b. a -> PricesRow b -> PricesRow a
forall a b. (a -> b) -> PricesRow a -> PricesRow b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> PricesRow b -> PricesRow a
$c<$ :: forall a b. a -> PricesRow b -> PricesRow a
fmap :: (a -> b) -> PricesRow a -> PricesRow b
$cfmap :: forall a b. (a -> b) -> PricesRow a -> PricesRow b
Functor, Int -> PricesRow a -> ShowS
[PricesRow a] -> ShowS
PricesRow a -> String
(Int -> PricesRow a -> ShowS)
-> (PricesRow a -> String)
-> ([PricesRow a] -> ShowS)
-> Show (PricesRow a)
forall a. Show a => Int -> PricesRow a -> ShowS
forall a. Show a => [PricesRow a] -> ShowS
forall a. Show a => PricesRow a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PricesRow a] -> ShowS
$cshowList :: forall a. Show a => [PricesRow a] -> ShowS
show :: PricesRow a -> String
$cshow :: forall a. Show a => PricesRow a -> String
showsPrec :: Int -> PricesRow a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> PricesRow a -> ShowS
Show)

instance (Read a, RealFrac a) => FromJSON (PricesRow a) where
  parseJSON :: Value -> Parser (PricesRow a)
parseJSON = String
-> (Object -> Parser (PricesRow a))
-> Value
-> Parser (PricesRow a)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"PricesRow" ((Object -> Parser (PricesRow a)) -> Value -> Parser (PricesRow a))
-> (Object -> Parser (PricesRow a))
-> Value
-> Parser (PricesRow a)
forall a b. (a -> b) -> a -> b
$ \Object
v -> (PricesRow (StringFrac a) -> PricesRow a)
-> Parser (PricesRow (StringFrac a)) -> Parser (PricesRow a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((StringFrac a -> a) -> PricesRow (StringFrac a) -> PricesRow a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap StringFrac a -> a
forall a. StringFrac a -> a
unStringFrac) (Parser (PricesRow (StringFrac a)) -> Parser (PricesRow a))
-> Parser (PricesRow (StringFrac a)) -> Parser (PricesRow a)
forall a b. (a -> b) -> a -> b
$ Int
-> Text
-> Maybe Day
-> StringFrac a
-> StringFrac a
-> StringFrac a
-> StringFrac a
-> StringFrac a
-> Integer
-> Maybe (StringFrac a)
-> Maybe Integer
-> PricesRow (StringFrac a)
forall a.
Int
-> Text
-> Maybe Day
-> a
-> a
-> a
-> a
-> a
-> Integer
-> Maybe a
-> Maybe Integer
-> PricesRow a
PricesRow
    (Int
 -> Text
 -> Maybe Day
 -> StringFrac a
 -> StringFrac a
 -> StringFrac a
 -> StringFrac a
 -> StringFrac a
 -> Integer
 -> Maybe (StringFrac a)
 -> Maybe Integer
 -> PricesRow (StringFrac a))
-> Parser Int
-> Parser
     (Text
      -> Maybe Day
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Text -> Parser Int
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"SimFinId"
    Parser
  (Text
   -> Maybe Day
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser Text
-> Parser
     (Maybe Day
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Ticker"
    Parser
  (Maybe Day
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser (Maybe Day)
-> Parser
     (StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe Day)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Date"
    Parser
  (StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser (StringFrac a)
-> Parser
     (StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (StringFrac a)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Open"
    Parser
  (StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser (StringFrac a)
-> Parser
     (StringFrac a
      -> StringFrac a
      -> StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (StringFrac a)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"High"
    Parser
  (StringFrac a
   -> StringFrac a
   -> StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser (StringFrac a)
-> Parser
     (StringFrac a
      -> StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (StringFrac a)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Low"
    Parser
  (StringFrac a
   -> StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser (StringFrac a)
-> Parser
     (StringFrac a
      -> Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (StringFrac a)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Close"
    Parser
  (StringFrac a
   -> Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser (StringFrac a)
-> Parser
     (Integer
      -> Maybe (StringFrac a)
      -> Maybe Integer
      -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (StringFrac a)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Adj. Close"
    Parser
  (Integer
   -> Maybe (StringFrac a)
   -> Maybe Integer
   -> PricesRow (StringFrac a))
-> Parser Integer
-> Parser
     (Maybe (StringFrac a) -> Maybe Integer -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser Integer
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Volume"
    Parser
  (Maybe (StringFrac a) -> Maybe Integer -> PricesRow (StringFrac a))
-> Parser (Maybe (StringFrac a))
-> Parser (Maybe Integer -> PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe (StringFrac a))
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Dividend"
    Parser (Maybe Integer -> PricesRow (StringFrac a))
-> Parser (Maybe Integer) -> Parser (PricesRow (StringFrac a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe Integer)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"Common Shares Outstanding"

-- | Wrapper to parse a PricesRow record from SimFin's JSON format.

newtype PricesKeyed a = PricesKeyed { PricesKeyed a -> [PricesRow a]
unKeyPrices :: [PricesRow a] }

instance (Read a, RealFrac a) => FromJSON (PricesKeyed a) where
  parseJSON :: Value -> Parser (PricesKeyed a)
parseJSON Value
o = [PricesRow a] -> PricesKeyed a
forall a. [PricesRow a] -> PricesKeyed a
PricesKeyed ([PricesRow a] -> PricesKeyed a)
-> Parser [PricesRow a] -> Parser (PricesKeyed a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Value -> Parser (PricesRow a)) -> [Value] -> Parser [PricesRow a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser (PricesRow a)
forall a. FromJSON a => Value -> Parser a
parseJSON ([Value] -> Parser [PricesRow a])
-> Parser [Value] -> Parser [PricesRow a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Value -> Parser [Value]
createKeyedRows Value
o)