{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TemplateHaskell #-}
module Net.Stocks
(
getChart,
getCompany,
getBook,
getDelayedQuote,
getDelayedDividend,
getEarnings,
getEffectiveSpread,
getFinancials,
getStats,
getNewsItem,
getOHLC,
getPrevious,
getPeers,
getPrice,
getQuote,
getRelevant,
getSplit,
getVolumeByVenue,
getTS,
getBatch,
getBatchCompany,
getMarket,
getIntraDayStats,
getRecentStats,
getRecordStats,
getHistoricalStats,
typeQuery,
Batch (..),
BatchQuery (..)
) where
import System.IO
import GHC.Generics
import Data.Aeson
import Data.Char
import Data.HashMap.Strict
import Data.Maybe
import Network.HTTP.Conduit
import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.List as DL
import qualified Data.Map as DM
import qualified Net.IEX.Chart as IEXChart
import qualified Net.IEX.Company as IEXCompany
import qualified Net.IEX.Stats as IEXStats
import qualified Net.IEX.Earnings as IEXEarnings
import qualified Net.IEX.NewsItem as IEXNewsItem
import qualified Net.IEX.DelayedQuote as IEXDelayedQuote
import qualified Net.IEX.Dividend as IEXDividend
import qualified Net.IEX.EffectiveSpread as IEXEffectiveSpread
import qualified Net.IEX.Financials as IEXFinancials
import qualified Net.IEX.OHLC as IEXOHLC
import qualified Net.IEX.PriceTime as IEXPriceTime
import qualified Net.IEX.Previous as IEXPrevious
import qualified Net.IEX.Quote as IEXQuote
import qualified Net.IEX.Split as IEXSplit
import qualified Net.IEX.VolumeByVenue as IEXVolumeByVenue
import qualified Net.IEX.Relevant as IEXRelevant
import qualified Net.IEX.Market as IEXMarket
import qualified Net.IEX.IntraDayStats as IEXIntraDayStats
import qualified Net.IEX.RecentStats as IEXRecentStats
import qualified Net.IEX.RecordStats as IEXRecordStats
import qualified Net.IEX.Book as IEXBook
import qualified Net.IEX.TimeSeries as IEXTimeSeries
type Symbol = String
data BatchQuery = NewsQuery |
ChartQuery |
CompanyQuery |
DelayedQuoteQuery |
DividendQuery |
EarningsQuery |
EffectiveSpreadQuery |
FinancialsQuery |
StatsQuery |
OHLCQuery |
PriceTimeQuery |
PreviousQuery |
QuoteQuery |
SplitQuery |
VolumeByVenueQuery
batchQueryToStr :: BatchQuery -> String
batchQueryToStr NewsQuery = "news"
batchQueryToStr ChartQuery = "chart"
batchQueryToStr CompanyQuery = "company"
batchQueryToStr DelayedQuoteQuery = "delayedquote"
batchQueryToStr DividendQuery = "dividends"
batchQueryToStr EarningsQuery = "earnings"
batchQueryToStr EffectiveSpreadQuery = "effectivespread"
batchQueryToStr FinancialsQuery = "financials"
batchQueryToStr StatsQuery = "stats"
batchQueryToStr OHLCQuery = "ohlc"
batchQueryToStr PriceTimeQuery = "price"
batchQueryToStr QuoteQuery = "quote"
batchQueryToStr SplitQuery = "split"
batchQueryToStr VolumeByVenueQuery = "volumebyvenue"
data Batch = Batch {
news :: Maybe [IEXNewsItem.NewsItem],
chart :: Maybe [IEXChart.Chart],
company :: Maybe IEXCompany.Company,
delayedQuote :: Maybe IEXDelayedQuote.DelayedQuote,
dividend :: Maybe [IEXDividend.Dividend],
earnings :: Maybe IEXEarnings.Earnings,
effectiveSpread :: Maybe [IEXEffectiveSpread.EffectiveSpread],
financials :: Maybe IEXFinancials.Financials,
stats :: Maybe IEXStats.Stats,
ohlc :: Maybe IEXOHLC.OHLC,
priceTime :: Maybe Integer,
previous :: Maybe IEXPrevious.Previous,
quote :: Maybe IEXQuote.Quote,
split :: Maybe [IEXSplit.Split],
volumeByVenue :: Maybe [IEXVolumeByVenue.VolumeByVenue]
} deriving (Generic, Show, Eq)
instance ToJSON Batch
instance FromJSON Batch
baseURL :: String
baseURL = "https://api.iextrading.com/1.0/stock/"
marketURL :: String
marketURL = "https://api.iextrading.com/1.0/market"
intraDayURL :: String
intraDayURL = "https://api.iextrading.com/1.0/stats/intraday"
statsURL :: String
statsURL = "https://api.iextrading.com/1.0/stats/"
lowerString :: Symbol -> String
lowerString = DL.map toLower
getChart :: Symbol -> IO (Maybe [IEXChart.Chart])
getChart symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/chart")
return $ decode obj
getCompany :: Symbol -> IO (Maybe IEXCompany.Company)
getCompany symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/company")
return $ decode obj
getBook :: Symbol -> IO (Maybe IEXBook.Book)
getBook symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/book")
return $ decode obj
getDelayedQuote :: Symbol -> IO (Maybe IEXDelayedQuote.DelayedQuote)
getDelayedQuote symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/delayed-quote")
return $ decode obj
getDelayedDividend :: Symbol -> IO (Maybe [IEXDividend.Dividend])
getDelayedDividend symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/dividends/5y")
return $ decode obj
getEarnings :: Symbol -> IO (Maybe IEXEarnings.Earnings)
getEarnings symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/earnings")
return $ decode obj
getEffectiveSpread :: Symbol -> IO (Maybe [IEXEffectiveSpread.EffectiveSpread])
getEffectiveSpread symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/effective-spread")
return $ decode obj
getFinancials :: Symbol -> IO (Maybe IEXFinancials.Financials)
getFinancials symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/financials")
return $ decode obj
getStats :: Symbol -> IO (Maybe IEXStats.Stats)
getStats symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/stats")
return $ decode obj
getNewsItem :: Symbol -> IO (Maybe [IEXNewsItem.NewsItem])
getNewsItem symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/news/last/1")
return $ decode obj
getOHLC :: Symbol -> IO (Maybe IEXOHLC.OHLC)
getOHLC symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/ohlc")
return $ decode obj
getPeers :: Symbol -> IO L8.ByteString
getPeers symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/peers")
return $ obj
getPrevious :: Symbol -> IO (Maybe IEXPrevious.Previous)
getPrevious symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/previous")
return $ decode obj
getPrice :: Symbol -> IO (Maybe Double)
getPrice symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/price")
return $ decode obj
getQuote :: Symbol -> IO (Maybe IEXQuote.Quote)
getQuote symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/quote")
return $ decode obj
getRelevant :: Symbol -> IO (Maybe IEXRelevant.Relevant)
getRelevant symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/relevant")
return $ decode obj
getSplit :: Symbol -> IO (Maybe [IEXSplit.Split])
getSplit symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/splits/5y")
return $ decode obj
getVolumeByVenue :: Symbol -> IO (Maybe [IEXVolumeByVenue.VolumeByVenue])
getVolumeByVenue symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/volume-by-venue")
return $ decode obj
getTS :: Symbol -> IO (Maybe [IEXTimeSeries.TimeSeries])
getTS symb = do
obj <- getNonJSONData (baseURL ++ lowerString symb ++ "/time-series")
return $ decode obj
typeQuery :: [BatchQuery] -> String
typeQuery [] = ""
typeQuery inp =
"types=" ++ (concat $ DL.intersperse "," (fmap batchQueryToStr inp))
symbolQuery :: [Symbol] -> String
symbolQuery [] = ""
symbolQuery inp = "symbols=" ++ (concat $ DL.intersperse "," inp)
questionMark :: [BatchQuery] -> String
questionMark [] = ""
questionMark _ = "?"
getBatch :: [Symbol] -> [BatchQuery] -> IO (Maybe (DM.Map String Batch))
getBatch symbs queryParams =
let urlPt = baseURL ++ "market/batch?"
fullQuery = urlPt ++ symbolQuery symbs ++ "&" ++ typeQuery queryParams
in do
obj <- getNonJSONData fullQuery
return $ decode obj
getBatchCompany :: Symbol -> [BatchQuery] -> IO (Maybe Batch)
getBatchCompany symb queryParams =
let urlPt = (baseURL ++ lowerString symb ++ "/batch/")
fullQuery = urlPt ++ (questionMark queryParams) ++ (typeQuery queryParams)
in do
obj <- getNonJSONData fullQuery
return $ decode obj
getMarket :: IO (Maybe [IEXMarket.Market])
getMarket = do
obj <- getNonJSONData marketURL
return $ decode obj
getIntraDayStats :: IO (Maybe IEXIntraDayStats.IntraDayStats)
getIntraDayStats = do
obj <- getNonJSONData intraDayURL
return $ decode obj
getRecentStats :: IO (Maybe [IEXRecentStats.RecentStats])
getRecentStats = do
obj <- getNonJSONData (statsURL ++ "recent")
return $ decode obj
getRecordStats :: IO (Maybe IEXRecordStats.RecordStats)
getRecordStats = do
obj <- getNonJSONData (statsURL ++ "records")
return $ decode obj
getHistoricalStats :: IO (Maybe [IEXRecentStats.RecentStats])
getHistoricalStats = undefined
getNonJSONData :: String -> IO L8.ByteString
getNonJSONData query = do
obj <- simpleHttp query
return obj