module Network.GDAX.Types.MarketData where
import Data.Aeson
import Data.Aeson.Types
import Data.Int
import Data.String
import Data.Text (Text)
import Data.Time
import Data.Time.Clock.POSIX
import Data.Typeable
import Data.UUID
import Data.Vector (Vector)
import qualified Data.Vector.Generic as V
import GHC.Generics
import Network.GDAX.Parsers
newtype ProductId = ProductId { unProductId :: Text }
deriving (Eq, Ord, Typeable, Generic, ToJSON, FromJSON, IsString)
instance Show ProductId where
show = show . unProductId
data Product
= Product
{ _prodId :: ProductId
, _prodBaseCurrency :: CurrencyId
, _prodQuoteCurrency :: CurrencyId
, _prodBaseMinSize :: Double
, _prodBaseMaxSize :: Double
, _prodQuoteIncrement :: Double
, _prodDisplayName :: Text
, _prodMarginEnabled :: Bool
}
deriving (Show, Typeable, Generic)
instance FromJSON Product where
parseJSON = withObject "Product" $ \o -> Product
<$> o .: "id"
<*> o .: "base_currency"
<*> o .: "quote_currency"
<*> (o .: "base_min_size" >>= textDouble)
<*> (o .: "base_max_size" >>= textDouble)
<*> (o .: "quote_increment" >>= textDouble)
<*> o .: "display_name"
<*> o .: "margin_enabled"
newtype Sequence = Sequence { unSequence :: Int64 }
deriving (Eq, Ord, Enum, Typeable, Generic, ToJSON, FromJSON)
instance Show Sequence where
show = show . unSequence
data AggrigateBid
= AggrigateBid
{ _aggbidPrice :: Double
, _aggbidSize :: Double
, _aggbidOrderCount :: Int64
}
deriving (Show, Typeable, Generic)
instance FromJSON AggrigateBid where
parseJSON = bookItem "AggrigateBid" AggrigateBid
data AggrigateAsk
= AggrigateAsk
{ _aggaskPrice :: Double
, _aggaskSize :: Double
, _aggaskOrderCount :: Int64
}
deriving (Show, Typeable, Generic)
instance FromJSON AggrigateAsk where
parseJSON = bookItem "AggrigateAsk" AggrigateAsk
data Bid
= Bid
{ _bidPrice :: Double
, _bidSize :: Double
, _bidId :: UUID
}
deriving (Show, Typeable, Generic)
instance FromJSON Bid where
parseJSON = bookItem "Bid" Bid
data Ask
= Ask
{ _askPrice :: Double
, _askSize :: Double
, _askId :: UUID
}
deriving (Show, Typeable, Generic)
instance FromJSON Ask where
parseJSON = bookItem "Ask" Ask
data AggrigateBook
= AggrigateBook
{ _aggbookBids :: Vector AggrigateBid
, _aggbookAsks :: Vector AggrigateAsk
, _aggbookSequence :: Sequence
}
deriving (Show, Typeable, Generic)
instance FromJSON AggrigateBook where
parseJSON = withObject "AggrigateBook" $ \o -> AggrigateBook
<$> o .: "bids"
<*> o .: "asks"
<*> o .: "sequence"
data Book
= Book
{ _bookBids :: Vector Bid
, _bookAsks :: Vector Ask
, _bookSequence :: Sequence
}
deriving (Show, Typeable, Generic)
instance FromJSON Book where
parseJSON = withObject "Book" $ \o -> Book
<$> o .: "bids"
<*> o .: "asks"
<*> o .: "sequence"
data Tick
= Tick
{ _tickTradeId :: TradeId
, _tickPrice :: Double
, _tickSize :: Double
, _tickBid :: Double
, _tickAsk :: Double
, _tickVolume :: Double
, _tickTime :: UTCTime
}
deriving (Show, Typeable, Generic)
instance FromJSON Tick where
parseJSON = withObject "Tick" $ \o -> Tick
<$> o .: "trade_id"
<*> (o .: "price" >>= textDouble)
<*> (o .: "size" >>= textDouble)
<*> (o .: "bid" >>= textDouble)
<*> (o .: "ask" >>= textDouble)
<*> (o .: "volume" >>= textDouble)
<*> o .: "time"
newtype TradeId = TradeId { unTradeId :: Int64 }
deriving (Eq, Ord, Enum, Typeable, Generic, ToJSON, FromJSON)
instance Show TradeId where
show = show . unTradeId
data Side
= Buy
| Sell
deriving (Show, Typeable, Generic)
instance FromJSON Side where
parseJSON = withText "Side" $ \t ->
case t of
"buy" -> pure Buy
"sell" -> pure Sell
_ -> fail "Side was not either buy or sell."
data Trade
= Trade
{ _tradeId :: TradeId
, _tradeTime :: UTCTime
, _tradePrice :: Double
, _tradeSize :: Double
, _tradeSide :: Side
}
deriving (Show, Typeable, Generic)
instance FromJSON Trade where
parseJSON = withObject "Trade" $ \o -> Trade
<$> o .: "trade_id"
<*> o .: "time"
<*> (o .: "price" >>= textDouble)
<*> (o .: "size" >>= textDouble)
<*> o .: "side"
type StartTime = UTCTime
type EndTime = UTCTime
type Granularity = Int
type Low = Double
type High = Double
type Open = Double
type Close = Double
type Volume = Double
data Candle = Candle UTCTime Low High Open Close Volume
deriving (Show, Typeable, Generic)
instance FromJSON Candle where
parseJSON = withArray "Candle" $ \v ->
case V.length v of
6 -> Candle <$> ((posixSecondsToUTCTime . fromIntegral) <$> (parseJSON (v V.! 0) :: Parser Int64))
<*> parseJSON (v V.! 1)
<*> parseJSON (v V.! 2)
<*> parseJSON (v V.! 3)
<*> parseJSON (v V.! 4)
<*> parseJSON (v V.! 5)
_ -> fail "Candle array was not 6 elements wide."
data Stats
= Stats
{ _statsOpen :: Open
, _statsHigh :: High
, _statsLow :: Low
, _statsVolume :: Volume
, _statsVolume30Day :: Volume
}
deriving (Show, Typeable, Generic)
instance FromJSON Stats where
parseJSON = withObject "Stats" $ \o -> Stats
<$> o .: "open"
<*> o .: "high"
<*> o .: "low"
<*> o .: "volume"
<*> o .: "volume_30day"
newtype CurrencyId = CurrencyId { unCurrencyId :: Text }
deriving (Eq, Ord, Typeable, Generic, ToJSON, FromJSON)
instance Show CurrencyId where
show = show . unCurrencyId
data Currency
= Currency
{ _currId :: CurrencyId
, _currName :: Text
, _currMinSize :: Double
}
deriving (Show, Typeable, Generic)
instance FromJSON Currency where
parseJSON = withObject "Currency" $ \o -> Currency
<$> o .: "id"
<*> o .: "name"
<*> (o .: "min_size" >>= textDouble)