|
|
|
@ -13,8 +13,12 @@ module TXMLConnector |
|
|
|
, makeBrokerBackend |
|
|
|
, makeBrokerBackend |
|
|
|
) where |
|
|
|
) where |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import ATrade.Broker.Backend (BrokerBackend (..), |
|
|
|
|
|
|
|
BrokerBackendNotification (..)) |
|
|
|
import ATrade.Logging (Message, Severity (..), log, |
|
|
|
import ATrade.Logging (Message, Severity (..), log, |
|
|
|
logWith) |
|
|
|
logWith) |
|
|
|
|
|
|
|
import ATrade.QuoteSource.Server (QuoteSourceServerData (..)) |
|
|
|
|
|
|
|
import ATrade.Types (Order, OrderId) |
|
|
|
import Colog (HasLog (getLogAction, setLogAction), |
|
|
|
import Colog (HasLog (getLogAction, setLogAction), |
|
|
|
LogAction (LogAction, unLogAction)) |
|
|
|
LogAction (LogAction, unLogAction)) |
|
|
|
import Config (SubscriptionConfig (SubscriptionConfig), |
|
|
|
import Config (SubscriptionConfig (SubscriptionConfig), |
|
|
|
@ -23,6 +27,7 @@ import Config (SubscriptionConfig (Subscriptio |
|
|
|
transaqLogPath, transaqLogin, |
|
|
|
transaqLogPath, transaqLogin, |
|
|
|
transaqPassword, transaqPort) |
|
|
|
transaqPassword, transaqPort) |
|
|
|
import Control.Concurrent (ThreadId, forkIO, threadDelay) |
|
|
|
import Control.Concurrent (ThreadId, forkIO, threadDelay) |
|
|
|
|
|
|
|
import Control.Concurrent.BoundedChan (BoundedChan) |
|
|
|
import Control.Concurrent.STM (TVar, atomically, modifyTVar', |
|
|
|
import Control.Concurrent.STM (TVar, atomically, modifyTVar', |
|
|
|
newEmptyTMVar, newEmptyTMVarIO, |
|
|
|
newEmptyTMVar, newEmptyTMVarIO, |
|
|
|
newTVarIO, orElse, putTMVar, |
|
|
|
newTVarIO, orElse, putTMVar, |
|
|
|
@ -33,89 +38,30 @@ import Control.Concurrent.STM (TVar, atomically, modifyTVar', |
|
|
|
import Control.Concurrent.STM.TBQueue (TBQueue, flushTBQueue, |
|
|
|
import Control.Concurrent.STM.TBQueue (TBQueue, flushTBQueue, |
|
|
|
newTBQueue, readTBQueue, |
|
|
|
newTBQueue, readTBQueue, |
|
|
|
writeTBQueue) |
|
|
|
writeTBQueue) |
|
|
|
|
|
|
|
import Control.Concurrent.STM.TMVar (TMVar) |
|
|
|
import Control.Monad (forM_, forever, void, when) |
|
|
|
import Control.Monad (forM_, forever, void, when) |
|
|
|
import Control.Monad.Extra (whileM) |
|
|
|
import Control.Monad.Extra (whileM) |
|
|
|
|
|
|
|
import Control.Monad.IO.Class (MonadIO (liftIO)) |
|
|
|
|
|
|
|
import Control.Monad.Reader (ReaderT (runReaderT)) |
|
|
|
|
|
|
|
import Control.Monad.Reader.Class (MonadReader) |
|
|
|
import qualified Data.Bimap as BM |
|
|
|
import qualified Data.Bimap as BM |
|
|
|
|
|
|
|
import qualified Data.Map.Strict as M |
|
|
|
import Data.Maybe (mapMaybe) |
|
|
|
import Data.Maybe (mapMaybe) |
|
|
|
import qualified Data.Text as T |
|
|
|
import qualified Data.Text as T |
|
|
|
|
|
|
|
import Data.Time.Clock (UTCTime, getCurrentTime) |
|
|
|
import qualified Deque.Strict as D |
|
|
|
import qualified Deque.Strict as D |
|
|
|
|
|
|
|
import GHC.Exts (IsList (..)) |
|
|
|
|
|
|
|
import Prelude hiding (log) |
|
|
|
import Text.XML.Light.Input (parseXML) |
|
|
|
import Text.XML.Light.Input (parseXML) |
|
|
|
import Text.XML.Light.Types (Content (Elem), |
|
|
|
import Text.XML.Light.Types (Content (Elem), |
|
|
|
Element (elName), |
|
|
|
Element (elName), |
|
|
|
QName (qName)) |
|
|
|
QName (qName)) |
|
|
|
import TickTable (TickTable, insertTick, |
|
|
|
import TickerInfoServer (TickerInfoServerHandle) |
|
|
|
lookupTick, newTickTable) |
|
|
|
import TickTable (newTickTable) |
|
|
|
import Transaq (AllTradesTrade (..), |
|
|
|
import Transaq (TransaqResponse) |
|
|
|
Candle (..), ClientData (..), |
|
|
|
|
|
|
|
CommandChangePass (..), |
|
|
|
|
|
|
|
CommandConnect (..), |
|
|
|
|
|
|
|
CommandDisconnect (CommandDisconnect), |
|
|
|
|
|
|
|
CommandGetHistoryData (CommandGetHistoryData), |
|
|
|
|
|
|
|
CommandServerStatus (..), |
|
|
|
|
|
|
|
CommandSubscribe (..), |
|
|
|
|
|
|
|
ConnectionState (Disconnected), |
|
|
|
|
|
|
|
Language (LanguageEn), |
|
|
|
|
|
|
|
MarketInfo (..), |
|
|
|
|
|
|
|
OrderNotification (..), |
|
|
|
|
|
|
|
OrderStatus (..), |
|
|
|
|
|
|
|
Quotation (..), |
|
|
|
|
|
|
|
ResponseAllTrades (ResponseAllTrades), |
|
|
|
|
|
|
|
ResponseCandleKinds (ResponseCandleKinds), |
|
|
|
|
|
|
|
ResponseCandles (..), |
|
|
|
|
|
|
|
ResponseCandlesStatus (StatusPending), |
|
|
|
|
|
|
|
ResponseClient (ResponseClient), |
|
|
|
|
|
|
|
ResponseMarkets (ResponseMarkets), |
|
|
|
|
|
|
|
ResponseOrders (ResponseOrders), |
|
|
|
|
|
|
|
ResponseQuotations (ResponseQuotations), |
|
|
|
|
|
|
|
ResponseQuotes (ResponseQuotes), |
|
|
|
|
|
|
|
ResponseResult (..), |
|
|
|
|
|
|
|
ResponseSecurities (ResponseSecurities), |
|
|
|
|
|
|
|
ResponseTrades (ResponseTrades), |
|
|
|
|
|
|
|
Security (..), SecurityId (..), |
|
|
|
|
|
|
|
TradeNotification (..), |
|
|
|
|
|
|
|
TransaqCommand (toXml), |
|
|
|
|
|
|
|
TransaqResponse (..), |
|
|
|
|
|
|
|
TransaqResponse (..), |
|
|
|
|
|
|
|
TransaqResponseC (fromXml), |
|
|
|
|
|
|
|
UnfilledAction (..), |
|
|
|
|
|
|
|
kCandleKindId, kPeriod, state) |
|
|
|
|
|
|
|
import TXML (LogLevel, MonadTXML, |
|
|
|
import TXML (LogLevel, MonadTXML, |
|
|
|
freeCallback, initialize, |
|
|
|
initialize, sendCommand, |
|
|
|
sendCommand, setCallback) |
|
|
|
setCallback) |
|
|
|
|
|
|
|
|
|
|
|
import ATrade.Broker.Backend (BrokerBackend (..), |
|
|
|
|
|
|
|
BrokerBackendNotification (..)) |
|
|
|
|
|
|
|
import ATrade.QuoteSource.Server (QuoteSourceServerData (..)) |
|
|
|
|
|
|
|
import ATrade.Types (Bar (..), |
|
|
|
|
|
|
|
BarTimeframe (unBarTimeframe), |
|
|
|
|
|
|
|
DataType (BestBid, BestOffer, LastTradePrice), |
|
|
|
|
|
|
|
Order (..), OrderId, |
|
|
|
|
|
|
|
OrderPrice (..), |
|
|
|
|
|
|
|
OrderState (..), Tick (..), |
|
|
|
|
|
|
|
TickerId, Trade (..), |
|
|
|
|
|
|
|
fromDouble, toDouble) |
|
|
|
|
|
|
|
import qualified ATrade.Types as AT |
|
|
|
|
|
|
|
import Colog.Monad (WithLog) |
|
|
|
|
|
|
|
import Control.Applicative ((<|>)) |
|
|
|
|
|
|
|
import Control.Concurrent.BoundedChan (BoundedChan, writeChan) |
|
|
|
|
|
|
|
import Control.Concurrent.STM.TMVar (TMVar) |
|
|
|
|
|
|
|
import Control.Error (headMay) |
|
|
|
|
|
|
|
import Control.Monad.IO.Class (MonadIO (liftIO)) |
|
|
|
|
|
|
|
import Control.Monad.Reader (ReaderT (runReaderT)) |
|
|
|
|
|
|
|
import Control.Monad.Reader.Class (MonadReader, asks) |
|
|
|
|
|
|
|
import Data.Int (Int64) |
|
|
|
|
|
|
|
import qualified Data.Map.Strict as M |
|
|
|
|
|
|
|
import Data.Time.Clock (UTCTime, diffUTCTime, |
|
|
|
|
|
|
|
getCurrentTime) |
|
|
|
|
|
|
|
import FSM (FSMCallback (..), |
|
|
|
|
|
|
|
FSMState (isTerminalState), |
|
|
|
|
|
|
|
makeFsm, runFsm) |
|
|
|
|
|
|
|
import GHC.Exts (IsList (..)) |
|
|
|
|
|
|
|
import Prelude hiding (log) |
|
|
|
|
|
|
|
import TickerInfoServer (TickerInfo (..), |
|
|
|
|
|
|
|
TickerInfoServerHandle, |
|
|
|
|
|
|
|
putTickerInfo) |
|
|
|
|
|
|
|
import qualified Transaq |
|
|
|
|
|
|
|
import qualified TXML |
|
|
|
import qualified TXML |
|
|
|
import TXMLConnector.Internal (BrokerState (..), |
|
|
|
import TXMLConnector.Internal (BrokerState (..), |
|
|
|
ConnectionStage (..), Env (..), |
|
|
|
ConnectionStage (..), Env (..), |
|
|
|
@ -128,10 +74,10 @@ import qualified Win32.TXML as TXMLImpl |
|
|
|
import qualified Linux.TXML as TXMLImpl |
|
|
|
import qualified Linux.TXML as TXMLImpl |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data ConnectionParams = |
|
|
|
data ConnectionParams = |
|
|
|
ConnectionParams |
|
|
|
ConnectionParams |
|
|
|
{ |
|
|
|
{ cpLogin :: T.Text |
|
|
|
cpLogin :: T.Text |
|
|
|
|
|
|
|
, cpPassword :: T.Text |
|
|
|
, cpPassword :: T.Text |
|
|
|
, cpHost :: T.Text |
|
|
|
, cpHost :: T.Text |
|
|
|
, cpPort :: Int |
|
|
|
, cpPort :: Int |
|
|
|
@ -142,8 +88,7 @@ data ConnectionParams = |
|
|
|
|
|
|
|
|
|
|
|
data TXMLConnectorHandle = |
|
|
|
data TXMLConnectorHandle = |
|
|
|
TXMLConnectorHandle |
|
|
|
TXMLConnectorHandle |
|
|
|
{ |
|
|
|
{ threadId :: ThreadId |
|
|
|
threadId :: ThreadId |
|
|
|
|
|
|
|
, notificationQueue :: TBQueue TransaqResponse |
|
|
|
, notificationQueue :: TBQueue TransaqResponse |
|
|
|
, hRequestVar :: TMVar Request |
|
|
|
, hRequestVar :: TMVar Request |
|
|
|
, hResponseVar :: TMVar (TMVar Response) |
|
|
|
, hResponseVar :: TMVar (TMVar Response) |
|
|
|
@ -165,71 +110,69 @@ instance HasLog Env Message App where |
|
|
|
getLogAction env = LogAction { unLogAction = liftIO . (unLogAction . logger $ env) } |
|
|
|
getLogAction env = LogAction { unLogAction = liftIO . (unLogAction . logger $ env) } |
|
|
|
setLogAction _ env = env -- fuck it |
|
|
|
setLogAction _ env = env -- fuck it |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start :: |
|
|
|
start :: |
|
|
|
LogAction IO Message |
|
|
|
LogAction IO Message |
|
|
|
-> TransaqConnectorConfig |
|
|
|
-> TransaqConnectorConfig |
|
|
|
-> BoundedChan QuoteSourceServerData |
|
|
|
-> BoundedChan QuoteSourceServerData |
|
|
|
-> TickerInfoServerHandle |
|
|
|
-> TickerInfoServerHandle |
|
|
|
-> IO TXMLConnectorHandle |
|
|
|
-> IO TXMLConnectorHandle |
|
|
|
start logger config qssChannel tisH = do |
|
|
|
start logger' config' qssChannel' tisH = do |
|
|
|
logWith logger Info "TXMLConnector" "Starting" |
|
|
|
logWith logger' Info "TXMLConnector" "Starting" |
|
|
|
notificationQueue <- atomically $ newTBQueue 50000 |
|
|
|
notificationQueue' <- atomically $ newTBQueue 50000 |
|
|
|
tickTable <- newTickTable |
|
|
|
tickTable <- newTickTable |
|
|
|
requestVar <- newEmptyTMVarIO |
|
|
|
requestVar' <- newEmptyTMVarIO |
|
|
|
responseVar <- newEmptyTMVarIO |
|
|
|
responseVar' <- newEmptyTMVarIO |
|
|
|
currentCandles <- newTVarIO [] |
|
|
|
currentCandles' <- newTVarIO [] |
|
|
|
serverConnected <- liftIO $ newTVarIO StageConnection |
|
|
|
serverConnected' <- liftIO $ newTVarIO StageConnection |
|
|
|
candleKindMap <- newTVarIO M.empty |
|
|
|
candleKindMap' <- newTVarIO M.empty |
|
|
|
requestTimestamp <- getCurrentTime >>= newTVarIO |
|
|
|
requestTimestamp' <- getCurrentTime >>= newTVarIO |
|
|
|
orderMap <- newTVarIO M.empty |
|
|
|
orderMap <- newTVarIO M.empty |
|
|
|
notificationCallback <- newTVarIO Nothing |
|
|
|
notificationCallback <- newTVarIO Nothing |
|
|
|
orderTransactionIdMap <- newTVarIO BM.empty |
|
|
|
orderTransactionIdMap <- newTVarIO BM.empty |
|
|
|
pendingOrders <- newTVarIO (fromList []) |
|
|
|
pendingOrders <- newTVarIO (fromList []) |
|
|
|
runVar <- newEmptyTMVarIO |
|
|
|
runVar' <- newEmptyTMVarIO |
|
|
|
timerVar <- newEmptyTMVarIO |
|
|
|
timerVar' <- newEmptyTMVarIO |
|
|
|
let brokerState = |
|
|
|
let brokerState' = |
|
|
|
BrokerState |
|
|
|
BrokerState |
|
|
|
{ |
|
|
|
{ bsOrderTransactionIdMap = orderTransactionIdMap |
|
|
|
bsOrderTransactionIdMap = orderTransactionIdMap |
|
|
|
|
|
|
|
, bsNotificationCallback = notificationCallback |
|
|
|
, bsNotificationCallback = notificationCallback |
|
|
|
, bsOrderMap = orderMap |
|
|
|
, bsOrderMap = orderMap |
|
|
|
, bsPendingOrders = pendingOrders |
|
|
|
, bsPendingOrders = pendingOrders |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let env = |
|
|
|
let env = |
|
|
|
Env |
|
|
|
Env |
|
|
|
{ |
|
|
|
{ qssChannel = qssChannel' |
|
|
|
qssChannel = qssChannel |
|
|
|
|
|
|
|
, tisHandle = tisH |
|
|
|
, tisHandle = tisH |
|
|
|
, requestVar = requestVar |
|
|
|
, requestVar = requestVar' |
|
|
|
, responseVar = responseVar |
|
|
|
, responseVar = responseVar' |
|
|
|
, requestTimestamp = requestTimestamp |
|
|
|
, requestTimestamp = requestTimestamp' |
|
|
|
, currentCandles = currentCandles |
|
|
|
, currentCandles = currentCandles' |
|
|
|
, tickMap = tickTable |
|
|
|
, tickMap = tickTable |
|
|
|
, transaqQueue = notificationQueue |
|
|
|
, transaqQueue = notificationQueue' |
|
|
|
, logger = logger |
|
|
|
, logger = logger' |
|
|
|
, config = config |
|
|
|
, config = config' |
|
|
|
, serverConnected = serverConnected |
|
|
|
, serverConnected = serverConnected' |
|
|
|
, candleKindMap = candleKindMap |
|
|
|
, candleKindMap = candleKindMap' |
|
|
|
, brokerState = brokerState |
|
|
|
, brokerState = brokerState' |
|
|
|
, runVar = runVar |
|
|
|
, runVar = runVar' |
|
|
|
, timerVar = timerVar |
|
|
|
, timerVar = timerVar' |
|
|
|
} |
|
|
|
} |
|
|
|
threadId <- forkIO $ (runReaderT . unApp) workThread env |
|
|
|
workThreadId <- forkIO $ (runReaderT . unApp) workThread env |
|
|
|
return $ TXMLConnectorHandle |
|
|
|
return $ TXMLConnectorHandle |
|
|
|
{ |
|
|
|
{ threadId = workThreadId |
|
|
|
threadId = threadId |
|
|
|
, notificationQueue = notificationQueue' |
|
|
|
, notificationQueue = notificationQueue |
|
|
|
, hRequestVar = requestVar' |
|
|
|
, hRequestVar = requestVar |
|
|
|
, hResponseVar = responseVar' |
|
|
|
, hResponseVar = responseVar |
|
|
|
, hRequestTimestamp = requestTimestamp' |
|
|
|
, hRequestTimestamp = requestTimestamp |
|
|
|
|
|
|
|
, hNotificationCallback = notificationCallback |
|
|
|
, hNotificationCallback = notificationCallback |
|
|
|
, hRunVar = runVar |
|
|
|
, hRunVar = runVar' |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stop :: TXMLConnectorHandle -> IO () |
|
|
|
stop :: TXMLConnectorHandle -> IO () |
|
|
|
stop h = atomically $ putTMVar (hRunVar h) () |
|
|
|
stop h = atomically $ putTMVar (hRunVar h) () |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
brSubmitOrder :: TXMLConnectorHandle -> Order -> IO () |
|
|
|
brSubmitOrder :: TXMLConnectorHandle -> Order -> IO () |
|
|
|
brSubmitOrder h order = void $ makeRequest h (RequestSubmitOrder order) |
|
|
|
brSubmitOrder h order = void $ makeRequest h (RequestSubmitOrder order) |
|
|
|
|
|
|
|
|
|
|
|
@ -240,8 +183,8 @@ brSetNotificationCallback :: TXMLConnectorHandle -> Maybe (BrokerBackendNotifica |
|
|
|
brSetNotificationCallback h cb = atomically $ writeTVar (hNotificationCallback h) cb |
|
|
|
brSetNotificationCallback h cb = atomically $ writeTVar (hNotificationCallback h) cb |
|
|
|
|
|
|
|
|
|
|
|
makeBrokerBackend :: TXMLConnectorHandle -> T.Text -> BrokerBackend |
|
|
|
makeBrokerBackend :: TXMLConnectorHandle -> T.Text -> BrokerBackend |
|
|
|
makeBrokerBackend h account = |
|
|
|
makeBrokerBackend h accountId = |
|
|
|
BrokerBackend [account] (brSetNotificationCallback h) (brSubmitOrder h) (brCancelOrder h) (TXMLConnector.stop h) |
|
|
|
BrokerBackend [accountId] (brSetNotificationCallback h) (brSubmitOrder h) (brCancelOrder h) (TXMLConnector.stop h) |
|
|
|
|
|
|
|
|
|
|
|
makeRequest :: TXMLConnectorHandle -> Request -> IO Response |
|
|
|
makeRequest :: TXMLConnectorHandle -> Request -> IO Response |
|
|
|
makeRequest h request = do |
|
|
|
makeRequest h request = do |
|
|
|
|