{-# LANGUAGE OverloadedStrings #-}
module AllyInvest.Quote (
getQuotes
, TradeConditionCode(..)
, TradingSession(..)
, DividendFrequency(..)
, OptionDelivery(..)
, OptionStyle(..)
, OptionClass(..)
, OptionType(..)
, Quote(..)
) where
import AllyInvest.Credentials
import AllyInvest.Error
import AllyInvest.Internal
import Safe
import Data.Aeson
import qualified Data.Text as T
import Data.List
getQuotes :: Credentials -> [String] -> IO (Either AllyInvestError [Quote])
getQuotes cred syms
= if length syms > 1
then fmap unQuotesResult <$> fetchAndDecode cred url
else fmap (return . unQuoteResult) <$> fetchAndDecode cred url
where
url = "https://api.tradeking.com/v1/market/ext/quotes.json?symbols=" ++ intercalate "," syms
data TradeConditionCode = TradeHalted | TradeResumed | TradeConditionUnknown String
deriving Show
instance FromJSON TradeConditionCode where
parseJSON (String "H") = return TradeHalted
parseJSON (String "R") = return TradeResumed
parseJSON (String x) = return . TradeConditionUnknown . T.unpack $ x
parseJSON x = fail (show x)
data TradingSession = PremarketSession | RegularSession | PostmarketSession | MarketClosed
deriving Show
instance FromJSON TradingSession where
parseJSON (String "pre") = return PremarketSession
parseJSON (String "regular") = return RegularSession
parseJSON (String "post") = return PostmarketSession
parseJSON (String "na") = return MarketClosed
parseJSON x = fail (show x)
data DividendFrequency = AnnualDividend | SemiAnnualDividend | QuarterlyDividend | MonthlyDividend | NoDividend
deriving Show
instance FromJSON DividendFrequency where
parseJSON (String "A") = return AnnualDividend
parseJSON (String "S") = return SemiAnnualDividend
parseJSON (String "Q") = return QuarterlyDividend
parseJSON (String "M") = return MonthlyDividend
parseJSON (String "N") = return NoDividend
parseJSON x = fail (show x)
data OptionDelivery = StandardSettlement | NonstandardSettlement | NoSettlement
deriving Show
instance FromJSON OptionDelivery where
parseJSON (String "S") = return StandardSettlement
parseJSON (String "N") = return NonstandardSettlement
parseJSON (String "X") = return NoSettlement
parseJSON x = fail (show x)
data OptionStyle = AmericanOption | EuropeanOption
deriving Show
instance FromJSON OptionStyle where
parseJSON (String "A") = return AmericanOption
parseJSON (String "E") = return EuropeanOption
parseJSON x = fail (show x)
data OptionClass = StandardOption | LeapOption | ShortTermOption
deriving Show
instance FromJSON OptionClass where
parseJSON (String "0") = return StandardOption
parseJSON (String "1") = return LeapOption
parseJSON (String "3") = return ShortTermOption
parseJSON x = fail (show x)
data OptionType = PutOption | CallOption
deriving Show
instance FromJSON OptionType where
parseJSON (String "Put") = return PutOption
parseJSON (String "Call") = return CallOption
parseJSON x = fail (show x)
data Quote
= StockQuote {
sqAskPrice :: Double
, sqLatestAskSize :: Int
, sqLatestAskTime :: Pending
, sqReportedPrecision :: Maybe Int
, sqBidPrice :: Double
, sqLatestBidSize :: Int
, sqLatestBidTime :: Pending
, sqChangeSincePriorDayClose :: Pending
, sqChangeSign :: Maybe Ordering
, sqChangeText :: Maybe String
, sqPreviousClose :: Double
, sqDateTime :: Pending
, sqLastTradeDate :: Pending
, sqTotalValueTradedToday :: Double
, sqExchangeDescription :: String
, sqExchangeCode :: Pending
, sqTodayHighTradePrice :: Double
, sqLastTradeVolume :: Int
, sqLastTradePrice :: Double
, sqTodayLowTradePrice :: Double
, sqCompanyName :: String
, sqOpenTradePrice :: Double
, sqPercentageChangeFromPriorDayClose :: Double
, sqPercentageChangeSign :: Maybe Ordering
, sqPriorDayClose :: Double
, sqPriorDayHighTradePrice :: Double
, sqPriorDayLowTradePrice :: Double
, sqPriorDayOpenPrice :: Double
, sqPriorDayPriceChange :: Double
, sqPriorLastTradeDate :: Pending
, sqPriorDayTotalVolume :: Int
, sqSecurityIsOption :: Bool
, sqTradingSession :: TradingSession
, sqSymbol :: String
, sqTradeConditionCode :: TradeConditionCode
, sqTimestamp :: Pending
, sqTickDirFromPriorTrade :: Ordering
, sqTrendBasedOn10PriorTicks :: Maybe Ordering
, sqNumTradesSinceMarketOpen :: Int
, sqCumulativeVolume :: Int
, sqVolumeWeightedAveragePrice :: Double
, sq52WeekHigh :: Double
, sq52WeekHighDate :: Pending
, sq52WeekLow :: Double
, sq52WeekLowDate :: Pending
, sq100DayAveragePrice :: Double
, sq200DayAveragePrice :: Double
, sq50DayAveragePrice :: Double
, sq21DayAverageVolume :: Int
, sq30DayAverageVolume :: Int
, sq90DaysAverageVolume :: Int
, sqBeta :: Double
, sqTickDirSinceLastBid :: Ordering
, sqCusip :: Maybe String
, sqExDividendDate :: Pending
, sqDividendFrequency :: DividendFrequency
, sqLatestAnnouncedCashDividend :: Double
, sqLastAnnouncedDividendPayDate :: Pending
, sqEarningsPerShare :: Double
, sqIndicatedAnnualDividend :: Pending
, sqSecurityHasOptions :: Bool
, sqPriceEarningsRatio :: Double
, sqPrior100DayAveragePrice :: Double
, sqPrior200DayAveragePrice :: Double
, sqPrior50DayAveragePrice :: Double
, sqBookValuePrice :: Double
, sqSharesOutstanding :: Int
, sqOneYearVolatilityMeasure :: Double
, sqDividendYield :: Double
}
| OptionQuote {
oqAskPrice :: Double
, oqLatestAskSize :: Int
, oqLatestAskTime :: Pending
, oqReportedPrecision :: Maybe Int
, oqBidPrice :: Double
, oqLatestBidSize :: Int
, oqLatestBidTime :: Pending
, oqChangeSincePriorDayClose :: Pending
, oqChangeSign :: Maybe Ordering
, oqChangeText :: Maybe String
, oqPreviousClose :: Double
, oqDateTime :: Pending
, oqLastTradeDate :: Pending
, oqTotalValueTradedToday :: Double
, oqExchangeDescription :: String
, oqExchangeCode :: Pending
, oqTodayHighTradePrice :: Double
, oqLastTradeVolume :: Int
, oqLastTradePrice :: Double
, oqTodayLowTradePrice :: Double
, oqCompanyName :: String
, oqOpenTradePrice :: Double
, oqPercentageChangeFromPriorDayClose :: Double
, oqPercentageChangeSign :: Maybe Ordering
, oqPriorDayClose :: Double
, oqPriorDayHighTradePrice :: Double
, oqPriorDayLowTradePrice :: Double
, oqPriorDayOpenPrice :: Double
, oqPriorDayPriceChange :: Double
, oqPriorLastTradeDate :: Pending
, oqPriorDayTotalVolume :: Int
, oqSecurityIsOption :: Bool
, oqTradingSession :: TradingSession
, oqSymbol :: String
, oqTradeConditionCode :: TradeConditionCode
, oqTimestamp :: Pending
, oqTickDirFromPriorTrade :: Ordering
, oqTrendBasedOn10PriorTicks :: Maybe Ordering
, oqNumTradesSinceMarketOpen :: Int
, oqCumulativeVolume :: Int
, oqVolumeWeightedAveragePrice :: Double
, oq52WeekHigh :: Double
, oq52WeekHighDate :: Pending
, oq52WeekLow :: Double
, oq52WeekLowDate :: Pending
, oqContractSize :: Int
, oqDaysUntilExpiration :: Int
, oqImpliedVolatilityDelta :: Double
, oqImpliedVolatilityGamma :: Double
, oqImpliedVolatilityPrice :: Double
, oqImpliedVolatilityRho :: Double
, oqIssueDescription :: String
, oqImpliedVolatilityTheta :: Double
, oqImpliedVolatilityVega :: Double
, oqSettlementDesignation :: OptionDelivery
, oqOpenInterest :: Double
, oqOptionStyle :: OptionStyle
, oqOptionClass :: OptionClass
, oqEstimatedOptionValue :: Double
, oqPremiumMultiplier :: Double
, oqPriorDayOpenInterest :: Double
, oqOptionType :: OptionType
, oqConditionCode :: String
, oqRootSymbol :: String
, oqStrikePrice :: Double
, oqUnderlyingCusip :: String
, oqUnderlyingSymbol :: String
, oqExpirationDate :: Pending
, oqExpirationDay :: Pending
, oqExpirationMonth :: Pending
, oqExpirationYear :: Pending
}
deriving Show
toOrd :: String -> Ordering
toOrd "u" = GT
toOrd "e" = EQ
toOrd "d" = LT
toOrdMay :: String -> Maybe Ordering
toOrdMay "na" = Nothing
toOrdMay x = Just $ toOrd x
toBool :: String -> Bool
toBool "0" = False
toBool "1" = True
toStrMay :: String -> Maybe String
toStrMay "na" = Nothing
toStrMay x = Just x
instance FromJSON Quote where
parseJSON (Object o)
= do
askPrice <- read <$> o .: "ask"
latestAskSize <- (*100) . read <$> o .: "asksz"
latestAskTime <- o .: "ask_time"
reportedPrecision <- readMay <$> o .: "basis"
bidPrice <- read <$> o .: "bid"
latestBidSize <- (*100) . read <$> o .: "bidsz"
latestBidTime <- o .: "bid_time"
changeSincePriorDayClose <- o .: "chg"
changeSign <- toOrdMay <$> o .: "chg_sign"
changeText <- toStrMay<$> o .: "chg_t"
previousClose <- read <$> o .: "cl"
dateTime <- o .: "datetime"
lastTradeDate <- o .: "date"
totalValueTradedToday <- read <$> o .: "dollar_value"
exchangeDescription <- o .: "exch_desc"
exchangeCode <- o .: "exch"
todayHighTradePrice <- read <$> o .: "hi"
lastTradeVolume <- read <$> o .: "incr_vl"
lastTradePrice <- read <$> o .: "last"
todayLowTradePrice <- read <$> o .: "lo"
companyName <- o .: "name"
openTradePrice <- read <$> o .: "opn"
percentageChangeFromPriorDayClose <- read <$> o .: "pchg"
percentageChangeSign <- toOrdMay <$> o .: "pchg_sign"
priorDayClose <- read <$> o .: "pcls"
priorDayHighTradePrice <- read <$> o .: "phi"
priorDayLowTradePrice <- read <$> o .: "plo"
priorDayOpenPrice <- read <$> o .: "popn"
priorDayPriceChange <- read <$> o .: "prchg"
priorLastTradeDate <- o .: "pr_date"
priorDayTotalVolume <- read <$> o .: "pvol"
securityIsOption <- toBool <$> o .: "secclass"
tradingSession <- o .: "sesn"
symbol <- o .: "symbol"
tradeConditionCode <- o .: "tcond"
timestamp <- o .: "timestamp"
tickDirFromPriorTrade <- toOrd <$> o .: "tradetick"
trendBasedOn10PriorTicks <- toOrdMay <$> o .: "trend"
numTradesSinceMarketOpen <- read <$> o .: "tr_num"
cumulativeVolume <- read <$> o .: "vl"
volumeWeightedAveragePrice <- read <$> o .: "vwap"
week52High <- read <$> o .: "wk52hi"
week52HighDate <- o .: "wk52hidate"
week52Low <- read <$> o .: "wk52lo"
week52LowDate <- o .: "wk52lodate"
if securityIsOption
then OptionQuote
askPrice latestAskSize latestAskTime reportedPrecision bidPrice
latestBidSize latestBidTime changeSincePriorDayClose changeSign changeText
previousClose dateTime lastTradeDate totalValueTradedToday exchangeDescription
exchangeCode todayHighTradePrice lastTradeVolume lastTradePrice todayLowTradePrice
companyName openTradePrice percentageChangeFromPriorDayClose percentageChangeSign priorDayClose
priorDayHighTradePrice priorDayLowTradePrice priorDayOpenPrice priorDayPriceChange priorLastTradeDate
priorDayTotalVolume securityIsOption tradingSession symbol tradeConditionCode
timestamp tickDirFromPriorTrade trendBasedOn10PriorTicks numTradesSinceMarketOpen cumulativeVolume
volumeWeightedAveragePrice week52High week52HighDate week52Low week52LowDate
<$> (read <$> o .: "contract_size")
<*> (read <$> o .: "days_to_expiration")
<*> (read <$> o .: "idelta")
<*> (read <$> o .: "igamma")
<*> (read <$> o .: "imp_volatility")
<*> (read <$> o .: "irho")
<*> (read <$> o .: "issue_desc")
<*> (read <$> o .: "itheta")
<*> (read <$> o .: "ivega")
<*> ( o .: "op_delivery")
<*> (read <$> o .: "openinterest")
<*> ( o .: "op_style")
<*> ( o .: "op_subclass")
<*> (read <$> o .: "opt_val")
<*> (read <$> o .: "prem_mult")
<*> (read <$> o .: "pr_openinterest")
<*> ( o .: "put_call")
<*> (read <$> o .: "qcond")
<*> (read <$> o .: "rootsymbol")
<*> (read <$> o .: "strikeprice")
<*> (read <$> o .: "under_cusip")
<*> (read <$> o .: "undersymbol")
<*> (read <$> o .: "xdate")
<*> (read <$> o .: "xday")
<*> (read <$> o .: "xmonth")
<*> (read <$> o .: "xyear")
else StockQuote
askPrice latestAskSize latestAskTime reportedPrecision bidPrice
latestBidSize latestBidTime changeSincePriorDayClose changeSign changeText
previousClose dateTime lastTradeDate totalValueTradedToday exchangeDescription
exchangeCode todayHighTradePrice lastTradeVolume lastTradePrice todayLowTradePrice
companyName openTradePrice percentageChangeFromPriorDayClose percentageChangeSign priorDayClose
priorDayHighTradePrice priorDayLowTradePrice priorDayOpenPrice priorDayPriceChange priorLastTradeDate
priorDayTotalVolume securityIsOption tradingSession symbol tradeConditionCode
timestamp tickDirFromPriorTrade trendBasedOn10PriorTicks numTradesSinceMarketOpen cumulativeVolume
volumeWeightedAveragePrice week52High week52HighDate week52Low week52LowDate
<$> (read <$> o .: "adp_100")
<*> (read <$> o .: "adp_200")
<*> (read <$> o .: "adp_50")
<*> (read <$> o .: "adv_21")
<*> (read <$> o .: "adv_30")
<*> (read <$> o .: "adv_90")
<*> (read <$> o .: "beta")
<*> (toOrd<$> o .: "bidtick")
<*> (toStrMay<$> o .: "cusip")
<*> ( o .: "divexdate")
<*> ( o .: "divfreq")
<*> (read <$> o .: "div")
<*> ( o .: "divpaydt")
<*> (read <$> o .: "eps")
<*> ( o .: "iad")
<*> (toBool<$>o .: "op_flag")
<*> (read <$> o .: "pe")
<*> (read <$> o .: "pr_adp_100")
<*> (read <$> o .: "pr_adp_200")
<*> (read <$> o .: "pr_adp_50")
<*> (read <$> o .: "prbook")
<*> (read <$> o .: "sho")
<*> (read <$> o .: "volatility12")
<*> (read <$> o .: "yield")
parseJSON x = fail . show $ x
data QuoteResult
= QuoteResult {
unQuoteResult :: Quote
}
instance FromJSON QuoteResult
where
parseJSON (Object o)
= QuoteResult <$> (o .: "response" >>= (.: "quotes") >>= (.: "quote"))
data QuotesResult
= QuotesResult {
unQuotesResult :: [Quote]
}
instance FromJSON QuotesResult
where
parseJSON (Object o)
= QuotesResult <$> (o .: "response" >>= (.: "quotes") >>= (.: "quote"))