You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1111 lines
37 KiB

2 years ago
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
3 years ago
module Transaq
(
CommandConnect(..),
Language(..),
TransaqCommand(..),
TransaqResponseC(..),
TransaqResponse(..),
SecurityId(..),
CommandDisconnect(..),
CommandServerStatus(..),
3 years ago
CommandSubscribe(..),
CommandNewOrder(..),
CommandCancelOrder(..),
CommandGetSecuritiesInfo(..),
3 years ago
CommandGetHistoryData(..),
3 years ago
CommandChangePass(..),
3 years ago
ResponseResult(..),
ResponseCandles,
ResponseCandlesB(..),
ResponseServerStatus,
ResponseServerStatusB(..),
3 years ago
ResponseCandleKinds(..),
ResponseMarkets(..),
ResponseSecurities(..),
ResponseSecInfo,
ResponseSecInfoB(..),
3 years ago
ResponseQuotations(..),
ResponseAllTrades(..),
ResponseTrades(..),
ResponseQuotes(..),
ResponseOrders(..),
ResponseClient(..),
ClientData,
ClientDataB(..),
Quotation,
QuotationB(..),
Quote,
QuoteB(..),
TradeNotification,
TradeNotificationB(..),
OrderNotification,
OrderNotificationB(..),
OrderStatus(..),
AllTradesTrade,
AllTradesTradeB(..),
Tick,
TickB(..),
3 years ago
ConnectionState(..),
MarketInfo,
MarketInfoB(..),
Security,
SecurityB(..),
CandleKind,
CandleKindB(..),
3 years ago
ResponseCandlesStatus(..),
Candle,
CandleB(..),
UnfilledAction(..),
TradeDirection(..),
TradingPeriod(..)
3 years ago
) where
import Barbies
import Barbies.Bare
5 months ago
import Control.Applicative ((<|>))
import Control.Error.Util (hush)
import Control.Monad (void)
import Data.Attoparsec.Text (Parser, char, decimal, many', parseOnly,
skipSpace)
import Data.Decimal (DecimalRaw (..))
import Data.Functor.Identity (Identity (..))
import Data.Int (Int64)
import Data.Maybe (catMaybes, fromMaybe, mapMaybe,
maybeToList)
import qualified Data.Text as T
import Data.Time (fromGregorian)
import Data.Time.Clock (UTCTime (UTCTime))
import GHC.Generics
5 months ago
import Text.Read (readMaybe)
import Text.XML.Light (Attr (..), CData (cdData),
Element (elName), Node (..), QName (..),
elChildren, findAttr, findChild,
onlyText, strContent, unode)
import Text.XML.Light.Output (showElement)
import Text.XML.Light.Types (Element (elContent), blank_name)
3 years ago
data Language = LanguageRu | LanguageEn
deriving (Show, Eq, Ord)
instance Node Language where
node n LanguageRu = node n ("ru" :: String)
node n LanguageEn = node n ("en" :: String)
type TransaqPrice = DecimalRaw Int
strAttr :: String -> String -> Attr
strAttr key val = Attr { attrKey = blank_name { qName = key}, attrVal = val}
fromBool :: Bool -> String
fromBool True = "true"
fromBool False = "false"
parseTimestamp :: T.Text -> Maybe UTCTime
parseTimestamp = hush . parseOnly parser
where
parser = parseWithDate <|> (UTCTime epoch <$> parseTime)
parseWithDate = do
!date <- parseDate
3 years ago
skipSpace
!time <- parseTime
3 years ago
pure $ UTCTime date time
parseDate = do
!day <- decimal
3 years ago
void $ char '.'
!month <- decimal
3 years ago
void $ char '.'
!year <- decimal
3 years ago
pure $ fromGregorian year month day
parseTime = do
!hour <- (decimal :: Parser Int)
3 years ago
void $ char ':'
!minute <- decimal
3 years ago
void $ char ':'
!second <- decimal
3 years ago
msecs <- many' $ do
void $ char '.'
(decimal :: Parser Int)
let !secofday = hour * 3600 + minute * 60 + second
3 years ago
case msecs of
[!ms] -> pure $ fromIntegral secofday + fromIntegral ms / 1000.0
_ -> pure $ fromIntegral secofday
3 years ago
epoch = fromGregorian 1970 1 1
class TransaqCommand t where
toXml :: t -> T.Text
class TransaqResponseC ctx t where
fromXml :: ctx -> Maybe t
3 years ago
data CommandConnect =
CommandConnect
{
login :: !T.Text,
password :: !T.Text,
host :: !T.Text,
port :: !Int,
language :: !Language,
autopos :: !Bool,
micexRegisters :: !Bool,
milliseconds :: !Bool,
utcTime :: !Bool,
3 years ago
proxy :: (), -- not supported
rqDelay :: !(Maybe Int),
sessionTimeout :: !(Maybe Int),
requestTimeout :: !(Maybe Int),
pushULimits :: !(Maybe Int),
pushPosEquity :: !(Maybe Int)
3 years ago
} deriving (Show, Eq, Ord)
instance Node CommandConnect where
node n CommandConnect {..} = node n (attrs, subnodes)
where
attrs = [strAttr "id" "connect"]
subnodes =
[ unode "login" (T.unpack login)
, unode "password" (T.unpack password)
, unode "host" (T.unpack host)
, unode "port" (show port)
, unode "language" language
, unode "autopos" (fromBool autopos)
, unode "micex_registers" (fromBool micexRegisters)
, unode "milliseconds" (fromBool milliseconds)
, unode "utc_time" (fromBool utcTime)
]
++ maybeToList (unode "rqdelay" . show <$> rqDelay)
++ maybeToList (unode "session_timeout" . show <$> sessionTimeout)
++ maybeToList (unode "request_timeout" . show <$> requestTimeout)
++ maybeToList (unode "push_u_limits" . show <$> pushULimits)
++ maybeToList (unode "push_pos_limits" . show <$> pushPosEquity)
instance TransaqCommand CommandConnect where
toXml = T.pack . showElement . unode "command"
data CommandDisconnect = CommandDisconnect
deriving (Show, Eq, Ord)
instance TransaqCommand CommandDisconnect where
toXml CommandDisconnect = T.pack . showElement $ unode "command" [strAttr "id" "disconnect"]
data SecurityId =
SecurityId
{
board :: !T.Text
, seccode :: !T.Text
3 years ago
} deriving (Show, Eq, Ord)
data CommandServerStatus = CommandServerStatus
deriving (Show, Eq, Ord)
instance TransaqCommand CommandServerStatus where
toXml CommandServerStatus = T.pack . showElement $ unode "command" [strAttr "id" "server_status"]
3 years ago
instance Node SecurityId where
node n SecurityId {..} = node n
[ unode "board" (T.unpack board)
, unode "seccode" (T.unpack seccode)
]
data CommandSubscribe =
CommandSubscribe
{
alltrades :: ![SecurityId]
, quotations :: ![SecurityId]
, quotes :: ![SecurityId]
3 years ago
} deriving (Show, Eq, Ord)
instance TransaqCommand CommandSubscribe where
toXml CommandSubscribe {..} =
T.pack . showElement $ unode "command" ([strAttr "id" "subscribe"],
[ unode "alltrades" $ fmap (unode "security") alltrades
, unode "quotations" $ fmap (unode "security") quotations
, unode "quotes" $ fmap (unode "security") quotes
])
data CommandUnsubscribe =
CommandUnsubscribe
{
alltrades :: ![SecurityId]
, quotations :: ![SecurityId]
, quotes :: ![SecurityId]
3 years ago
} deriving (Show, Eq, Ord)
instance TransaqCommand CommandUnsubscribe where
toXml CommandUnsubscribe {..} =
T.pack . showElement $ unode "command" ([strAttr "id" "unsubscribe"],
[ unode "alltrades" $ fmap (unode "security") alltrades
, unode "quotations" $ fmap (unode "security") quotations
, unode "quotes" $ fmap (unode "security") quotes
])
data CommandGetHistoryData =
CommandGetHistoryData
{
security :: !SecurityId
, periodId :: !Int
, count :: !Int
, reset :: !Bool
3 years ago
} deriving (Show, Eq, Ord)
instance TransaqCommand CommandGetHistoryData where
toXml CommandGetHistoryData {..} =
T.pack . showElement $ unode "command" ([strAttr "id" "gethistorydata"],
[ unode "security" security
, unode "period" (show periodId)
, unode "count" (show count)
, unode "reset" (fromBool reset)
])
data TradeDirection = Buy | Sell
deriving (Show, Eq, Ord)
instance Node TradeDirection where
node n Buy = node n ("B" :: String)
node n Sell = node n ("S" :: String)
data UnfilledAction =
UnfilledPutInQueue
| UnfilledFOK
| UnfilledIOC
deriving (Show, Eq, Ord)
instance Node UnfilledAction where
node n UnfilledPutInQueue = node n ("PutInQueue" :: String)
node n UnfilledFOK = node n ("FOK" :: String)
node n UnfilledIOC = node n ("IOC" :: String)
data CommandNewOrder =
CommandNewOrder
{
security :: !SecurityId
, client :: !T.Text
, unionCode :: !T.Text
, price :: !Double
, quantity :: !Int
, buysell :: !TradeDirection
, bymarket :: !Bool
, brokerRef :: !T.Text
, unfilled :: !UnfilledAction
, usecredit :: !Bool
, nosplit :: !Bool
3 years ago
} deriving (Show, Eq, Ord)
instance TransaqCommand CommandNewOrder where
toXml CommandNewOrder {..} =
T.pack . showElement $ unode "command" ([strAttr "id" "neworder"],
[ unode "security" security
, unode "client" $ T.unpack client
, unode "union" $ T.unpack unionCode
, unode "price" $ show price
, unode "quantity" $ show quantity
, unode "buysell" buysell
, unode "brokerref" $ T.unpack brokerRef
, unode "unfillled" unfilled
]
++ boolToList "bymarket" bymarket
++ boolToList "usecredit" usecredit
++ boolToList "nosplit" nosplit)
where
boolToList n True = [unode n ("" :: String)]
boolToList _ False = []
newtype CommandCancelOrder =
CommandCancelOrder
{
transactionId :: Integer
} deriving (Show, Eq, Ord)
instance TransaqCommand CommandCancelOrder where
toXml CommandCancelOrder{..} =
T.pack . showElement $ unode "command" ([strAttr "id" "cancelorder"],
3 years ago
[ unode "transactionid" (show transactionId)])
newtype CommandGetSecuritiesInfo =
CommandGetSecuritiesInfo
{
securities :: [SecurityId]
} deriving (Show, Eq, Ord)
instance TransaqCommand CommandGetSecuritiesInfo where
toXml CommandGetSecuritiesInfo{..} =
T.pack . showElement $ unode "command" ([strAttr "id" "get_securities_info"],
fmap (unode "security") securities)
3 years ago
data CommandChangePass =
CommandChangePass
{
cOldPass :: !T.Text
, cNewPass :: !T.Text
3 years ago
} deriving (Show, Eq)
instance TransaqCommand CommandChangePass where
toXml CommandChangePass{..} =
T.pack . showElement $ unode "command"
[strAttr "id" "change_pass",
strAttr "oldpass" $ T.unpack cOldPass,
strAttr "newpass" $ T.unpack cNewPass]
3 years ago
data ResponseResult =
ResponseSuccess (Maybe Int64)
3 years ago
| ResponseFailure T.Text
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseResult where
3 years ago
fromXml root =
if qName (elName root) == "result"
then
if findAttr (blank_name {qName = "success"}) root == Just "true"
then Just $ ResponseSuccess (findAttr (uname "transactionid") root >>= readMaybe)
3 years ago
else Just . ResponseFailure . T.pack . concatMap cdData . onlyText . elContent $ root
else Nothing
data CandleB t f =
3 years ago
Candle
{
cTimestamp :: Wear t f UTCTime
, cOpen :: Wear t f Double
, cHigh :: Wear t f Double
, cLow :: Wear t f Double
, cClose :: Wear t f Double
, cVolume :: Wear t f Int
, cOpenInterest :: Wear t f Int
} deriving (Generic)
type Candle = CandleB Bare Identity
deriving instance FunctorB (CandleB Covered)
deriving instance TraversableB (CandleB Covered)
deriving instance ConstraintsB (CandleB Covered)
deriving instance Show Candle
deriving instance Eq Candle
deriving instance Ord Candle
deriving instance BareB CandleB
3 years ago
data ResponseCandlesStatus =
StatusEndOfHistory
| StatusDone
| StatusPending
| StatusUnavaliable
deriving (Show, Eq, Ord)
data ResponseCandlesB t f =
3 years ago
ResponseCandles
{
cPeriodId :: Wear t f Int
, cStatus :: Wear t f ResponseCandlesStatus
, cSecurity :: Wear t f SecurityId
, cCandles :: Wear t f [Candle]
} deriving (Generic)
type ResponseCandles = ResponseCandlesB Bare Identity
deriving instance FunctorB (ResponseCandlesB Covered)
deriving instance TraversableB (ResponseCandlesB Covered)
deriving instance ConstraintsB (ResponseCandlesB Covered)
deriving instance Show ResponseCandles
deriving instance Eq ResponseCandles
deriving instance Ord ResponseCandles
deriving instance BareB ResponseCandlesB
3 years ago
uname :: String -> QName
uname x = blank_name {qName = x}
childContent :: String -> Element -> Maybe String
childContent tag el = strContent <$> findChild (uname tag) el
instance TransaqResponseC Element (ResponseCandlesB Bare f) where
3 years ago
fromXml root = do
!periodId <- findAttr (uname "period") root >>= readMaybe
!status <- findAttr (uname "status") root >>= readMaybe >>= parseStatus
!board <- T.pack <$> findAttr (uname "board") root
!seccode <- T.pack <$> findAttr (uname "seccode") root
let !candles = mapMaybe parseCandle . elChildren $ root
return (ResponseCandles
3 years ago
{
3 years ago
cPeriodId = periodId
, cStatus = status
, cSecurity = SecurityId board seccode
, cCandles = candles
} :: ResponseCandlesB Bare f)
3 years ago
where
parseStatus :: Int -> Maybe ResponseCandlesStatus
parseStatus intStatus =
case intStatus of
0 -> Just StatusEndOfHistory
1 -> Just StatusDone
2 -> Just StatusPending
3 -> Just StatusUnavaliable
_ -> Nothing
parseCandle element = do
!timestamp <- findAttr (uname "date") element >>= parseTimestamp . T.pack
!open <- findAttr (uname "open") element >>= readMaybe
!high <- findAttr (uname "high") element >>= readMaybe
!low <- findAttr (uname "low") element >>= readMaybe
!close <- findAttr (uname "close") element >>= readMaybe
!volume <- findAttr (uname "volume") element >>= readMaybe
let !openInterest = fromMaybe 0 $ findAttr (uname "oi") element >>= readMaybe
return (Candle
3 years ago
{
cTimestamp = timestamp
, cOpen = open
, cHigh = high
, cLow = low
, cClose = close
, cVolume = volume
, cOpenInterest = openInterest
} :: CandleB Bare f)
3 years ago
instance TransaqResponseC T.Text (ResponseCandlesB Bare f) where
5 months ago
fromXml _ = undefined
3 years ago
data ConnectionState =
Connected
| Disconnected
| Error T.Text
deriving (Show, Eq, Ord)
data ResponseServerStatusB t f =
3 years ago
ResponseServerStatus
{
serverId :: Wear t f (Maybe Int)
, state :: Wear t f ConnectionState
, recover :: Wear t f (Maybe Bool)
, serverTimezone :: Wear t f (Maybe T.Text)
, systemVersion :: Wear t f (Maybe Int)
, build :: Wear t f (Maybe Int)
} deriving (Generic)
type ResponseServerStatus = ResponseServerStatusB Bare Identity
deriving instance FunctorB (ResponseServerStatusB Covered)
deriving instance TraversableB (ResponseServerStatusB Covered)
deriving instance ConstraintsB (ResponseServerStatusB Covered)
deriving instance Show ResponseServerStatus
deriving instance Eq ResponseServerStatus
deriving instance Ord ResponseServerStatus
deriving instance BareB ResponseServerStatusB
instance TransaqResponseC Element ResponseServerStatus where
3 years ago
fromXml root = do
let !serverId = findAttr (uname "id") root >>= readMaybe
!connectedStr <- findAttr (uname "connected") root
!state <- case connectedStr of
3 years ago
"true" -> pure Connected
"false" -> pure Disconnected
"error" -> pure $ Error (T.pack $ strContent root)
_ -> pure Disconnected
let !recover =
3 years ago
case findAttr (uname "recover") root of
Just "true" -> pure True
_ -> pure False
let !serverTimezone = T.pack <$> findAttr (uname "server_tz") root
let !systemVersion = findAttr (uname "sys_ver") root >>= readMaybe
let !build = findAttr (uname "build") root >>= readMaybe
3 years ago
pure $ ResponseServerStatus {..}
data MarketInfoB t f =
3 years ago
MarketInfo
{ marketId :: Wear t f Int
, marketName :: Wear t f T.Text
} deriving (Generic)
type MarketInfo = MarketInfoB Bare Identity
deriving instance FunctorB (MarketInfoB Covered)
deriving instance TraversableB (MarketInfoB Covered)
deriving instance ConstraintsB (MarketInfoB Covered)
deriving instance Show MarketInfo
deriving instance Eq MarketInfo
deriving instance Ord MarketInfo
deriving instance BareB MarketInfoB
3 years ago
newtype ResponseMarkets = ResponseMarkets [MarketInfo]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseMarkets where
3 years ago
fromXml root = do
!markets <- mapM parseMarketInfo $ elChildren root
3 years ago
pure . ResponseMarkets . catMaybes $ markets
where
parseMarketInfo tag =
if (qName . elName) tag == "market"
then do
!marketId <- findAttr (uname "id") tag >>= readMaybe
let !marketName = T.pack $ strContent tag
pure $ Just $ (MarketInfo {..} :: MarketInfo)
3 years ago
else pure Nothing
data ClientDataB t f =
ClientData
{
cClientId :: Wear t f T.Text
, cType :: Wear t f T.Text
, cCurrency :: Wear t f T.Text
, cMarket :: Wear t f T.Text
, cUnion :: Wear t f T.Text
2 years ago
, cForts :: Maybe T.Text
} deriving (Generic)
type ClientData = ClientDataB Bare Identity
deriving instance FunctorB (ClientDataB Covered)
deriving instance TraversableB (ClientDataB Covered)
deriving instance ConstraintsB (ClientDataB Covered)
deriving instance Show ClientData
deriving instance Eq ClientData
deriving instance Ord ClientData
deriving instance BareB ClientDataB
newtype ResponseClient = ResponseClient ClientData
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseClient where
2 years ago
fromXml root = if (qName . elName) root == "client"
then do
!cClientId <- T.pack <$> findAttr (uname "id") root
!cType <- T.pack <$> childContent "type" root
!cCurrency <- T.pack <$> childContent "currency" root
!cMarket <- T.pack <$> childContent "market" root
!cUnion <- T.pack <$> childContent "union" root
let !cForts = T.pack <$> childContent "forts_acc" root
Just $ ResponseClient $ ClientData {..}
else Nothing
data CandleKindB t f=
3 years ago
CandleKind
{
kCandleKindId :: Wear t f Int
, kPeriod :: Wear t f Int
, kName :: Wear t f T.Text
} deriving (Generic)
type CandleKind = CandleKindB Bare Identity
deriving instance FunctorB (CandleKindB Covered)
deriving instance TraversableB (CandleKindB Covered)
deriving instance ConstraintsB (CandleKindB Covered)
deriving instance Show CandleKind
deriving instance Eq CandleKind
deriving instance Ord CandleKind
deriving instance BareB CandleKindB
3 years ago
newtype ResponseCandleKinds = ResponseCandleKinds [CandleKind]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseCandleKinds where
3 years ago
fromXml root = do
!kinds <- mapM parseCandleKind $ elChildren root
3 years ago
pure . ResponseCandleKinds . catMaybes $ kinds
where
parseCandleKind tag =
if (qName . elName) tag == "kind"
then do
!kCandleKindId <- childContent "id" tag >>= readMaybe
!kPeriod <- childContent "period" tag >>= readMaybe
!kName <- T.pack <$> childContent "name" tag
pure . Just $ (CandleKind {..} :: CandleKind)
3 years ago
else pure Nothing
data SecurityB t f =
3 years ago
Security
{
sSecId :: Wear t f Int
, sActive :: Wear t f Bool
, sSeccode :: Wear t f T.Text
, sInstrClass :: Wear t f T.Text
, sBoard :: Wear t f T.Text
, sMarket :: Wear t f T.Text
, sCurrency :: Wear t f T.Text
, sShortName :: Wear t f T.Text
, sDecimals :: Wear t f Int
, sMinStep :: Wear t f Double
, sLotSize :: Wear t f Int
, sLotDivider :: Wear t f Int
, sPointCost :: Wear t f Double
, sSecType :: Wear t f T.Text
} deriving (Generic)
type Security = SecurityB Bare Identity
deriving instance FunctorB (SecurityB Covered)
deriving instance TraversableB (SecurityB Covered)
deriving instance ConstraintsB (SecurityB Covered)
deriving instance Show Security
deriving instance Eq Security
deriving instance Ord Security
deriving instance BareB SecurityB
3 years ago
newtype ResponseSecurities =
ResponseSecurities [Security]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseSecurities where
3 years ago
fromXml root = do
securities <- mapM parseSecurity $ elChildren root
pure . ResponseSecurities . catMaybes $ securities
where
parseSecurity tag =
if (qName . elName) tag == "security"
then do
!sSecId <- findAttr (uname "secid") tag >>= readMaybe
!sActive <- findAttr (uname "active") tag >>= parseBool
!sSeccode <- T.pack <$> childContent "seccode" tag
!sInstrClass <- T.pack <$> childContent "instrclass" tag
!sBoard <- T.pack <$> childContent "board" tag
!sMarket <- T.pack <$> childContent "market" tag
let !sCurrency = fromMaybe "" $ T.pack <$> childContent "currency" tag
!sShortName <- T.pack <$> childContent "shortname" tag
!sDecimals <- childContent "decimals" tag >>= readMaybe
!sMinStep <- childContent "minstep" tag >>= readMaybe
!sLotSize <- childContent "lotsize" tag >>= readMaybe
!sLotDivider <- childContent "lotdivider" tag >>= readMaybe
!sPointCost <- childContent "point_cost" tag >>= readMaybe
!sSecType <- T.pack <$> childContent "sectype" tag
pure . Just $ (Security {..} :: Security)
3 years ago
else
pure Nothing
parseBool "true" = Just True
parseBool "false" = Just False
parseBool _ = Nothing
data ResponseSecInfoB t f =
3 years ago
ResponseSecInfo
{
secId :: Wear t f Int
, secName :: Wear t f T.Text
, secCode :: Wear t f T.Text
, market :: Wear t f Int
, pname :: Wear t f T.Text
, clearingPrice :: Wear t f Double
, minPrice :: Wear t f Double
, maxPrice :: Wear t f Double
, pointCost :: Wear t f Double
} deriving (Generic)
type ResponseSecInfo = ResponseSecInfoB Bare Identity
deriving instance FunctorB (ResponseSecInfoB Covered)
deriving instance TraversableB (ResponseSecInfoB Covered)
deriving instance ConstraintsB (ResponseSecInfoB Covered)
deriving instance Show ResponseSecInfo
deriving instance Eq ResponseSecInfo
deriving instance Ord ResponseSecInfo
deriving instance BareB ResponseSecInfoB
instance TransaqResponseC Element ResponseSecInfo where
3 years ago
fromXml tag = do
secId <- findAttr (uname "secid") tag >>= readMaybe
secName <- T.pack <$> childContent "secname" tag
secCode <- T.pack <$> childContent "seccode" tag
market <- childContent "market" tag >>= readMaybe
pname <- T.pack <$> childContent "pname" tag
clearingPrice <- childContent "clearing_price" tag >>= readMaybe
minPrice <- childContent "minprice" tag >>= readMaybe
maxPrice <- childContent "maxprice" tag >>= readMaybe
3 years ago
pointCost <- childContent "point_cost" tag >>= readMaybe
pure ResponseSecInfo {..}
data QuotationB t f =
3 years ago
Quotation
{
qSecId :: Wear t f Int
, qBoard :: Wear t f T.Text
, qSeccode :: Wear t f T.Text
, qOpen :: Maybe Double
, qWaprice :: Maybe Double
, qBidDepth :: Maybe Int
, qBidDepthT :: Maybe Int
, qNumBids :: Maybe Int
, qOfferDepth :: Maybe Int
, qOfferDepthT :: Maybe Int
, qBid :: Maybe Double
, qOffer :: Maybe Double
, qNumOffers :: Maybe Int
, qNumTrades :: Maybe Int
, qVolToday :: Maybe Int
, qOpenPositions :: Maybe Int
, qLastPrice :: Maybe Double
, qQuantity :: Maybe Int
2 years ago
, qTimestamp :: Maybe UTCTime
, qValToday :: Maybe Double
} deriving (Generic)
type Quotation = QuotationB Bare Identity
deriving instance FunctorB (QuotationB Covered)
deriving instance TraversableB (QuotationB Covered)
deriving instance ConstraintsB (QuotationB Covered)
deriving instance Show Quotation
deriving instance Eq Quotation
deriving instance Ord Quotation
deriving instance BareB QuotationB
3 years ago
newtype ResponseQuotations =
ResponseQuotations [Quotation]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseQuotations where
3 years ago
fromXml root = do
quotations <- mapM parseQuotation $ elChildren root
pure . ResponseQuotations . catMaybes $ quotations
where
parseQuotation tag = do
!qSecId <- findAttr (uname "secid") tag >>= readMaybe
!qBoard <- T.pack <$> childContent "board" tag
!qSeccode <- T.pack <$> childContent "seccode" tag
let !qOpen = childContent "open" tag >>= readMaybe
let !qWaprice = childContent "waprice" tag >>= readMaybe
let !qBidDepth = childContent "biddepth" tag >>= readMaybe
let !qBidDepthT = childContent "biddeptht" tag >>= readMaybe
let !qNumBids = childContent "numbids" tag >>= readMaybe
let !qBid = childContent "bid" tag >>= readMaybe
let !qOfferDepth = childContent "offerdepth" tag >>= readMaybe
let !qOfferDepthT = childContent "offerdeptht" tag >>= readMaybe
let !qNumOffers = childContent "numoffers" tag >>= readMaybe
let !qOffer = childContent "offer" tag >>= readMaybe
let !qNumTrades = childContent "numtrades" tag >>= readMaybe
let !qVolToday = childContent "voltoday" tag >>= readMaybe
let !qOpenPositions = childContent "openpositions" tag >>= readMaybe
let !qLastPrice = childContent "last" tag >>= readMaybe
let !qQuantity = childContent "quantity" tag >>= readMaybe
2 years ago
let !qTimestamp = childContent "time" tag >>= (parseTimestamp . T.pack)
let !qValToday = childContent "valtoday" tag >>= readMaybe
pure $ Just (Quotation {..} :: Quotation)
3 years ago
data TradingPeriod =
PeriodOpen
| PeriodNormal
| PeriodClose
| PeriodUnknown
deriving (Show, Eq, Ord)
data AllTradesTradeB t f =
3 years ago
AllTradesTrade
{
attSecId :: Wear t f Int
, attSecCode :: Wear t f T.Text
, attTradeNo :: Wear t f Int64
, attTimestamp :: Wear t f UTCTime
, attBoard :: Wear t f T.Text
, attPrice :: Wear t f Double
, attQuantity :: Wear t f Int
, attBuysell :: Wear t f TradeDirection
, attOpenInterest :: Wear t f Int
, attPeriod :: Wear t f TradingPeriod
} deriving (Generic)
type AllTradesTrade = AllTradesTradeB Bare Identity
deriving instance FunctorB (AllTradesTradeB Covered)
deriving instance TraversableB (AllTradesTradeB Covered)
deriving instance ConstraintsB (AllTradesTradeB Covered)
deriving instance Show AllTradesTrade
deriving instance Eq AllTradesTrade
deriving instance Ord AllTradesTrade
deriving instance BareB AllTradesTradeB
3 years ago
newtype ResponseAllTrades =
ResponseAllTrades [AllTradesTrade]
deriving (Show, Eq, Ord)
parseTradeDirection :: T.Text -> Maybe TradeDirection
parseTradeDirection t =
case t of
"B" -> Just Buy
"S" -> Just Sell
_ -> Nothing
instance TransaqResponseC Element ResponseAllTrades where
3 years ago
fromXml root = do
alltrades <- mapM parseAllTrade $ elChildren root
pure . ResponseAllTrades . catMaybes $ alltrades
where
parseAllTrade tag = do
!attSecId <- findAttr (uname "secid") tag >>= readMaybe
!attSecCode <- T.pack <$> childContent "seccode" tag
!attTradeNo <- childContent "tradeno" tag >>= readMaybe
!attTimestamp <- T.pack <$> childContent "time" tag >>= parseTimestamp
!attBoard <- T.pack <$> childContent "board" tag
!attPrice <- childContent "price" tag >>= readMaybe
!attQuantity <- childContent "quantity" tag >>= readMaybe
!attBuysell <- T.pack <$> childContent "buysell" tag >>= parseTradeDirection
let !attOpenInterest = fromMaybe 0 $ childContent "openinterest" tag >>= readMaybe
let !attPeriod = fromMaybe PeriodUnknown $ childContent "period" tag >>= parseTradingPeriod
pure . Just $ (AllTradesTrade {..} :: AllTradesTrade)
3 years ago
parseTradingPeriod :: String -> Maybe TradingPeriod
parseTradingPeriod "O" = Just PeriodOpen
parseTradingPeriod "N" = Just PeriodNormal
parseTradingPeriod "C" = Just PeriodClose
parseTradingPeriod _ = Nothing
data QuoteB t f =
3 years ago
Quote
{
secId :: Wear t f Int
, board :: Wear t f T.Text
, secCode :: Wear t f T.Text
, price :: Wear t f Double
, source :: Maybe T.Text
, yield :: Maybe Int
, buy :: Maybe Int
, sell :: Maybe Int
} deriving (Generic)
type Quote = QuoteB Bare Identity
deriving instance FunctorB (QuoteB Covered)
deriving instance TraversableB (QuoteB Covered)
deriving instance ConstraintsB (QuoteB Covered)
deriving instance Show Quote
deriving instance Eq Quote
deriving instance Ord Quote
deriving instance BareB QuoteB
3 years ago
newtype ResponseQuotes =
ResponseQuotes [Quote]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseQuotes where
3 years ago
fromXml root = do
quotes <- mapM parseQuote $ elChildren root
pure . ResponseQuotes . catMaybes $ quotes
where
parseQuote tag = do
!secId <- findAttr (uname "secid") tag >>= readMaybe
!secCode <- T.pack <$> childContent "seccode" tag
!board <- T.pack <$> childContent "board" tag
!price <- childContent "price" tag >>= readMaybe
let !source = T.pack <$> childContent "source" tag
let !yield = childContent "yield" tag >>= readMaybe
let !buy = childContent "buy" tag >>= readMaybe
let !sell = childContent "sell" tag >>= readMaybe
return . Just $ (Quote {..} :: Quote)
3 years ago
data OrderStatus =
OrderActive
| OrderCancelled
3 years ago
| OrderDenied
| OrderDisabled
| OrderExpired
| OrderFailed
| OrderForwarding
| OrderInactive
| OrderMatched
| OrderRefused
3 years ago
| OrderRejected
| OrderRemoved
| OrderWait
3 years ago
| OrderWatching
deriving (Show, Eq, Ord)
data OrderNotificationB t f =
3 years ago
OrderNotification
{
oTransactionId :: Wear t f Int
, oOrderNo :: Wear t f Int64
, oSecId :: Wear t f Int
, oBoard :: Wear t f T.Text
, oSecCode :: Wear t f T.Text
, oClient :: Maybe T.Text
, oUnion :: Maybe T.Text
, oStatus :: Maybe OrderStatus
, oBuysell :: Maybe TradeDirection
, oTimestamp :: Maybe UTCTime
, oBrokerRef :: Maybe T.Text
, oBalance :: Maybe Int
, oPrice :: Maybe Double
, oQuantity :: Maybe Int
, oResult :: Maybe T.Text
} deriving (Generic)
type OrderNotification = OrderNotificationB Bare Identity
deriving instance FunctorB (OrderNotificationB Covered)
deriving instance TraversableB (OrderNotificationB Covered)
deriving instance ConstraintsB (OrderNotificationB Covered)
deriving instance Show OrderNotification
deriving instance Eq OrderNotification
deriving instance Ord OrderNotification
deriving instance BareB OrderNotificationB
3 years ago
newtype ResponseOrders =
ResponseOrders [OrderNotification]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseOrders where
3 years ago
fromXml root = do
quotes <- mapM parseOrder $ elChildren root
pure . ResponseOrders . catMaybes $ quotes
where
parseOrder tag = do
!oTransactionId <- findAttr (uname "transactionid") tag >>= readMaybe
!oOrderNo <- childContent "orderno" tag >>= readMaybe
!oSecId <- childContent "secid" tag >>= readMaybe
!oBoard <- T.pack <$> childContent "board" tag
!oSecCode <- T.pack <$> childContent "seccode" tag
let !oClient = T.pack <$> childContent "client" tag
let !oUnion = T.pack <$> childContent "union" tag
let !oStatus = childContent "status" tag >>= parseStatus
let !oBuysell = childContent "buysell" tag >>= parseTradeDirection . T.pack
let !oTimestamp = childContent "time" tag >>= parseTimestamp . T.pack
let !oBrokerRef = T.pack <$> childContent "brokerref" tag
let !oBalance = childContent "balance" tag >>= readMaybe
let !oPrice = childContent "price" tag >>= readMaybe
let !oQuantity = childContent "quantity" tag >>= readMaybe
let !oResult = T.pack <$> childContent "result" tag
return . Just $ (OrderNotification {..} :: OrderNotification)
parseStatus "active" = Just OrderActive
parseStatus "cancelled" = Just OrderCancelled
parseStatus "denied" = Just OrderDenied
parseStatus "disabled" = Just OrderDisabled
parseStatus "expired" = Just OrderExpired
parseStatus "failed" = Just OrderFailed
parseStatus "forwarding" = Just OrderForwarding
parseStatus "inactive" = Just OrderInactive
parseStatus "matched" = Just OrderMatched
parseStatus "refused" = Just OrderRefused
parseStatus "rejected" = Just OrderRejected
parseStatus "removed" = Just OrderRemoved
parseStatus "wait" = Just OrderWait
parseStatus "watching" = Just OrderWatching
parseStatus _ = Nothing
3 years ago
data TradeNotificationB t f =
3 years ago
TradeNotification
{
tSecId :: Wear t f Int
, tTradeNo :: Wear t f Int64
, tOrderNo :: Wear t f Int64
, tBoard :: Wear t f T.Text
, tSecCode :: Wear t f T.Text
, tClient :: Wear t f T.Text
, tUnion :: Wear t f T.Text
, tBuysell :: Wear t f TradeDirection
, tTimestamp :: Wear t f UTCTime
, tValue :: Wear t f Double
, tComission :: Wear t f Double
, tQuantity :: Wear t f Int
, tPrice :: Wear t f Double
} deriving (Generic)
type TradeNotification = TradeNotificationB Bare Identity
deriving instance FunctorB (TradeNotificationB Covered)
deriving instance TraversableB (TradeNotificationB Covered)
deriving instance ConstraintsB (TradeNotificationB Covered)
deriving instance Show TradeNotification
deriving instance Eq TradeNotification
deriving instance Ord TradeNotification
deriving instance BareB TradeNotificationB
3 years ago
newtype ResponseTrades =
ResponseTrades [TradeNotification]
deriving (Show, Eq, Ord)
instance TransaqResponseC Element ResponseTrades where
3 years ago
fromXml root = do
quotes <- mapM parseTrade $ elChildren root
pure . ResponseTrades . catMaybes $ quotes
where
parseTrade tag = do
!tSecId <- childContent "secid" tag >>= readMaybe
!tTradeNo <- childContent "tradeno" tag >>= readMaybe
!tOrderNo <- childContent "orderno" tag >>= readMaybe
!tBoard <- T.pack <$> childContent "board" tag
!tSecCode <- T.pack <$> childContent "seccode" tag
!tClient <- T.pack <$> childContent "client" tag
!tUnion <- T.pack <$> childContent "union" tag
!tBuysell <- childContent "buysell" tag >>= parseTradeDirection . T.pack
!tTimestamp <- childContent "time" tag >>= parseTimestamp . T.pack
!tValue <- childContent "value" tag >>= readMaybe
!tComission <- childContent "comission" tag >>= readMaybe
!tQuantity <- childContent "quantity" tag >>= readMaybe
!tPrice <- childContent "price" tag >>= readMaybe
pure . Just $ (TradeNotification {..} :: TradeNotification)
3 years ago
data TickB t f =
3 years ago
Tick
{
secId :: Wear t f Int
, tradeNo :: Wear t f Int64
, timestamp :: Wear t f UTCTime
, price :: Wear t f Double
, quantity :: Wear t f Int
, period :: Wear t f TradingPeriod
, buySell :: Wear t f TradeDirection
, openInterest :: Wear t f Int
, board :: Wear t f T.Text
, secCode :: Wear t f T.Text
} deriving (Generic)
type Tick = TickB Bare Identity
deriving instance FunctorB (TickB Covered)
deriving instance TraversableB (TickB Covered)
deriving instance ConstraintsB (TickB Covered)
deriving instance Show Tick
deriving instance Eq Tick
deriving instance Ord Tick
deriving instance BareB TickB
3 years ago
newtype ResponseTicks =
ResponseTicks [Tick]
deriving (Show, Eq, Ord)
data TransaqResponse =
TransaqResponseResult ResponseResult
| TransaqResponseCandles ResponseCandles
| TransaqResponseClient ResponseClient
3 years ago
| TransaqResponseServerStatus ResponseServerStatus
| TransaqResponseMarkets ResponseMarkets
| TransaqResponseCandleKinds ResponseCandleKinds
| TransaqResponseSecurities ResponseSecurities
| TransaqResponseSecInfo ResponseSecInfo
| TransaqResponseQuotations ResponseQuotations
| TransaqResponseAllTrades ResponseAllTrades
| TransaqResponseQuotes ResponseQuotes
| TransaqResponseOrders ResponseOrders
| TransaqResponseTrades ResponseTrades
deriving (Show, Eq, Ord)
instance TransaqResponseC Element TransaqResponse where
3 years ago
fromXml root = case qName . elName $ root of
"result" -> TransaqResponseResult <$> fromXml root
"error" -> TransaqResponseResult <$> fromXml root
"client" -> TransaqResponseClient <$> fromXml root
3 years ago
"candles" -> TransaqResponseCandles <$> fromXml root
"server_status" -> TransaqResponseServerStatus <$> fromXml root
"markets" -> TransaqResponseMarkets <$> fromXml root
"candlekinds" -> TransaqResponseCandleKinds <$> fromXml root
"securities" -> TransaqResponseSecurities <$> fromXml root
"sec_info" -> TransaqResponseSecInfo <$> fromXml root
"quotations" -> TransaqResponseQuotations <$> fromXml root
"alltrades" -> TransaqResponseAllTrades <$> fromXml root
"quotes" -> TransaqResponseQuotes <$> fromXml root
"orders" -> TransaqResponseOrders <$> fromXml root
"trades" -> TransaqResponseTrades <$> fromXml root
_ -> Nothing
2 years ago