|
|
|
|
|
|
|
|
|
module MockBroker (
|
|
|
|
|
MockBrokerState(..),
|
|
|
|
|
mockSubmitOrder,
|
|
|
|
|
mockCancelOrder,
|
|
|
|
|
mockStopBroker,
|
|
|
|
|
mkMockBroker,
|
|
|
|
|
emitNotification,
|
|
|
|
|
mockBrokerLastOrderId
|
|
|
|
|
) where
|
|
|
|
|
|
|
|
|
|
import ATrade.Broker.Backend
|
|
|
|
|
import ATrade.Broker.Protocol
|
|
|
|
|
import ATrade.Broker.Server
|
|
|
|
|
import ATrade.Types
|
|
|
|
|
import ATrade.Util
|
|
|
|
|
import Data.IORef
|
|
|
|
|
import qualified Data.List as L
|
|
|
|
|
|
|
|
|
|
data MockBrokerState = MockBrokerState {
|
|
|
|
|
orders :: [Order],
|
|
|
|
|
cancelledOrders :: [Order],
|
|
|
|
|
notificationCallback :: Maybe (BrokerBackendNotification -> IO ()),
|
|
|
|
|
lastOrderId :: OrderId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mockSubmitOrder :: IORef MockBrokerState -> Order -> IO ()
|
|
|
|
|
mockSubmitOrder state order = do
|
|
|
|
|
atomicModifyIORef' state (\s -> (s { orders = submittedOrder : orders s,
|
|
|
|
|
lastOrderId = orderId submittedOrder }, ()))
|
|
|
|
|
maybeCb <- notificationCallback <$> readIORef state
|
|
|
|
|
case maybeCb of
|
|
|
|
|
Just cb -> cb $ BackendOrderNotification (orderId order) Submitted
|
|
|
|
|
Nothing -> return ()
|
|
|
|
|
where
|
|
|
|
|
submittedOrder = order { orderState = Submitted }
|
|
|
|
|
|
|
|
|
|
mockCancelOrder :: IORef MockBrokerState -> OrderId -> IO ()
|
|
|
|
|
mockCancelOrder state oid = do
|
|
|
|
|
ors <- orders <$> readIORef state
|
|
|
|
|
case L.find (\o -> orderId o == oid) ors of
|
|
|
|
|
Just order -> do
|
|
|
|
|
atomicModifyIORef' state (\s -> (s { cancelledOrders = order : cancelledOrders s}, ()))
|
|
|
|
|
maybeCb <- notificationCallback <$> readIORef state
|
|
|
|
|
case maybeCb of
|
|
|
|
|
Just cb -> cb $ BackendOrderNotification (orderId order) Cancelled
|
|
|
|
|
Nothing -> return ()
|
|
|
|
|
Nothing -> return ()
|
|
|
|
|
|
|
|
|
|
mockStopBroker :: IORef MockBrokerState -> IO ()
|
|
|
|
|
mockStopBroker state = return ()
|
|
|
|
|
|
|
|
|
|
emitNotification :: IORef MockBrokerState -> BrokerBackendNotification -> IO ()
|
|
|
|
|
emitNotification state notification = do
|
|
|
|
|
bro <- readIORef state
|
|
|
|
|
case notificationCallback bro of
|
|
|
|
|
Just cb -> cb notification
|
|
|
|
|
Nothing -> return ()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mkMockBroker accs = do
|
|
|
|
|
state <- newIORef MockBrokerState {
|
|
|
|
|
orders = [],
|
|
|
|
|
cancelledOrders = [],
|
|
|
|
|
notificationCallback = Nothing,
|
|
|
|
|
lastOrderId = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (BrokerBackend {
|
|
|
|
|
accounts = accs,
|
|
|
|
|
setNotificationCallback = \cb -> atomicMapIORef state (\s -> s { notificationCallback = cb }),
|
|
|
|
|
submitOrder = mockSubmitOrder state,
|
|
|
|
|
cancelOrder = mockCancelOrder state,
|
|
|
|
|
stop = mockStopBroker state
|
|
|
|
|
}, state)
|
|
|
|
|
|
|
|
|
|
mockBrokerLastOrderId :: IORef MockBrokerState -> IO OrderId
|
|
|
|
|
mockBrokerLastOrderId state = lastOrderId <$> readIORef state
|