ATrade console quote display
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.

96 lines
3.4 KiB

6 years ago
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Brick.AttrMap
import Brick.BChan
import Brick.Main
import Brick.Types
import Brick.Widgets.Border
import Brick.Widgets.Core
import Control.Concurrent
import qualified Control.Concurrent.BoundedChan as BC
import Control.Exception
import Control.Monad
import Data.Aeson
import qualified Data.ByteString.Lazy as B
import qualified Data.Map.Strict as M
import qualified Graphics.Vty as Vty
import Lens.Micro.Platform
import Lens.Micro.TH
import System.ZMQ4
import ATrade.QuoteSource.Client
import ATrade.Types
import Config
import QuoteTable
data Name = Viewport1
deriving (Show, Eq, Ord)
data AppEvent = IncomingTick Tick
data AppState = AppState {
_quotes :: QuoteTable
} deriving (Show, Eq)
makeLenses ''AppState
qsThread :: BChan AppEvent -> AppConfig -> IO ()
qsThread eventChan config = withContext $ \ctx -> do
qschan <- BC.newBoundedChan 1000
bracket (startQuoteSourceClient qschan (config ^. tickers) ctx (config ^. quoteSourceEndpoint) defaultClientSecurityParams) stopQuoteSourceClient $ \_ -> forever $ do
qsdata <- BC.readChan qschan
case qsdata of
QDTick tick -> writeBChan eventChan (IncomingTick tick)
_ -> return ()
main :: IO ()
main = do
maybeConfig <- decode' <$> B.readFile "atrade-brick.config"
case maybeConfig of
Nothing -> error "Can't parse config"
Just config -> do
let app = App {
appDraw = draw,
appChooseCursor = chooseCursor,
appHandleEvent = handleEvent,
appStartEvent = startEvent,
appAttrMap = attrMap'
}
eventChan <- Brick.BChan.newBChan 10
let buildVty = Vty.mkVty Vty.defaultConfig
initialVty <- buildVty
qsThreadId <- forkIO $ qsThread eventChan config
void $ customMain buildVty (Just eventChan) app initialState
where
initialState = AppState M.empty
draw :: AppState -> [Widget Name]
draw s = [hBox [vBox (txt <$> tickers s),
vBorder,
vBox (str <$> fmap (printEntry s qteLastPrice) (tickers s)),
vBorder,
vBox (str <$> fmap (printEntry s qteBid) (tickers s)),
vBorder,
vBox (str <$> fmap (printEntry s qteAsk) (tickers s))] ]
printEntry s l tickerId = case s ^. quotes . at tickerId of
Just qte -> show $ qte ^. l
Nothing -> "-"
tickers s = M.keys (s ^. quotes)
chooseCursor s loc = Nothing
handleEvent s event = case event of
VtyEvent e -> case e of
Vty.EvKey (Vty.KChar 'q') [] -> halt s
_ -> continue s
AppEvent e -> case e of
IncomingTick t -> continue $ handleNewTick s t
_ -> continue s
startEvent = return
attrMap' s = attrMap Vty.defAttr []
handleNewTick s t = case datatype t of
LastTradePrice -> s & quotes . at (security t) . non emptyQuoteTableEntry . qteLastPrice .~ value t
BestBid -> s & quotes . at (security t) . non emptyQuoteTableEntry . qteBid .~ value t
BestOffer -> s & quotes . at (security t) . non emptyQuoteTableEntry . qteAsk .~ value t
_ -> s