Browse Source

Database++

master
Denis Tereshkin 9 years ago
parent
commit
d24c2a6ffb
  1. 2
      mds.cabal
  2. 44
      src/ATrade/MDS/Database.hs
  3. 14
      src/ATrade/MDS/HistoryServer.hs

2
mds.cabal

@ -26,6 +26,8 @@ library
, hslogger , hslogger
, time , time
, monad-loops , monad-loops
, text-format
, zeromq4-haskell
default-language: Haskell2010 default-language: Haskell2010
executable mds-exe executable mds-exe

44
src/ATrade/MDS/Database.hs

@ -1,10 +1,16 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module ATrade.MDS.Database ( module ATrade.MDS.Database (
DatabaseConfig(..),
DatabaseInterface(..),
startDatabase,
stopDatabase
) where ) where
import qualified Data.Configurator as C import qualified Data.Configurator as C
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Text.Format
import qualified Data.Vector as V import qualified Data.Vector as V
import ATrade.Types import ATrade.Types
import Data.Time.Clock import Data.Time.Clock
@ -44,6 +50,7 @@ data DatabaseInterface = DatabaseInterface {
startDatabase :: DatabaseConfig -> IO DatabaseInterface startDatabase :: DatabaseConfig -> IO DatabaseInterface
startDatabase config = do startDatabase config = do
conn <- connectPostgreSQL (mkConnectionString config) conn <- connectPostgreSQL (mkConnectionString config)
makeSchema conn
cmdVar <- newEmptyMVar cmdVar <- newEmptyMVar
respVar <- newEmptyMVar respVar <- newEmptyMVar
compVar <- newEmptyMVar compVar <- newEmptyMVar
@ -53,7 +60,8 @@ startDatabase config = do
getData = doGetData cmdVar respVar, getData = doGetData cmdVar respVar,
putData = doPutData cmdVar respVar } putData = doPutData cmdVar respVar }
where where
mkConnectionString = undefined makeSchema conn = runRaw conn "CREATE TABLE IF NOT EXISTS bars (id SERIAL PRIMARY KEY, ticker TEXT, timestamp BIGINT, open NUMERIC(20, 10), high NUMERIC(20, 10), low NUMERIC(20, 10), close NUMERIC(20,10), volume BIGINT);"
mkConnectionString config = TL.unpack $ format "User ID={};Password={};Host={};Port=5432;Database={}" (dbUser config, dbPassword config, dbHost config, dbDatabase config)
dbThread conn cmdVar respVar = forever $ do dbThread conn cmdVar respVar = forever $ do
cmd <- readMVar cmdVar cmd <- readMVar cmdVar
handleCmd conn cmd >>= putMVar respVar handleCmd conn cmd >>= putMVar respVar
@ -61,17 +69,35 @@ startDatabase config = do
takeMVar cmdVar takeMVar cmdVar
cleanup conn cmdVar respVar compVar _ = disconnect conn >> putMVar compVar () cleanup conn cmdVar respVar compVar _ = disconnect conn >> putMVar compVar ()
handleCmd conn cmd = case cmd of handleCmd conn cmd = case cmd of
DBPut tickerId (TimeInterval start end) (Timeframe timeframeSecs) bars -> do DBPut tickerId (TimeInterval start end) tf@(Timeframe timeframeSecs) bars -> do
delStmt <- prepare conn "DELETE FROM bars WHERE timestamp > ? AND timestamp < ? AND ticker == ? AND timeframe == ?;" delStmt <- prepare conn "DELETE FROM bars WHERE timestamp > ? AND timestamp < ? AND ticker == ? AND timeframe == ?;"
execute delStmt [utcTimeToPosixSeconds start, utcTimeToPosixSeconds end, tickerId, timeframeSecs] execute delStmt [(SqlPOSIXTime . utcTimeToPOSIXSeconds) start, (SqlPOSIXTime . utcTimeToPOSIXSeconds) end, (SqlString . T.unpack) tickerId, (SqlInteger . toInteger) timeframeSecs]
stmt <- prepare conn "INSERT INTO bars (ticker, timeframe, timestamp, open, high, low, close, volume)" ++ stmt <- prepare conn $ "INSERT INTO bars (ticker, timeframe, timestamp, open, high, low, close, volume)" ++
" values (?, ?, ?, ?, ?, ?, ?, ?); " " values (?, ?, ?, ?, ?, ?, ?, ?); "
executeMany stmt (map barToSql $ V.toList bars) executeMany stmt (map (barToSql tf) $ V.toList bars)
return DBOk return DBOk
DBGet tickerId interval@(TimeInterval start end) (Timeframe timeframeSecs) -> do DBGet tickerId interval@(TimeInterval start end) (Timeframe timeframeSecs) -> do
rows <- quickQuery' conn "SELECT timestamp, open, high, low, close, volume FROM bars WHERE ticker == ? AND timeframe == ? AND timestamp > ? AND timestamp < ?;" [tickerId, timeframeSecs, utcTimeToPosixSeconds start, utcTimeToPosixSeconds end] rows <- quickQuery' conn "SELECT timestamp, open, high, low, close, volume FROM bars WHERE ticker == ? AND timeframe == ? AND timestamp > ? AND timestamp < ?;" [(toSql. T.unpack) tickerId, toSql timeframeSecs, (toSql . utcTimeToPOSIXSeconds) start, (toSql . utcTimeToPOSIXSeconds) end]
return $ DBData [(interval, V.fromList $ map barFromResult rows)] return $ DBData [(interval, V.fromList $ mapMaybe (barFromResult tickerId) rows)]
barFromResult = undefined barFromResult ticker [ts, open, high, low, close, volume] = Just Bar {
barSecurity = ticker,
barTimestamp = fromSql ts,
barOpen = fromRational $ fromSql open,
barHigh = fromRational $ fromSql high,
barLow = fromRational $ fromSql low,
barClose = fromRational $ fromSql close,
barVolume = fromSql volume
}
barFromResult _ _ = Nothing
barToSql :: Timeframe -> Bar -> [SqlValue]
barToSql (Timeframe timeframeSecs) bar = [(SqlString . T.unpack . barSecurity) bar,
(SqlInteger . toInteger) timeframeSecs,
(SqlRational . toRational . barOpen) bar,
(SqlRational . toRational . barHigh) bar,
(SqlRational . toRational . barLow) bar,
(SqlRational . toRational . barClose) bar,
(SqlRational . toRational . barVolume) bar ]
stopDatabase :: MVar () -> DatabaseInterface -> IO () stopDatabase :: MVar () -> DatabaseInterface -> IO ()
stopDatabase compVar db = killThread (tid db) >> readMVar compVar stopDatabase compVar db = killThread (tid db) >> readMVar compVar
@ -100,5 +126,5 @@ doPutData cmdVar respVar tickerId timeInterval timeframe bars = do
return () return ()
_ -> do _ -> do
warningM "DB.Client" "Unexpected response" warningM "DB.Client" "Unexpected response"
return [] return ()

14
src/ATrade/MDS/HistoryServer.hs

@ -0,0 +1,14 @@
module ATrade.MDS.HistoryServer (
) where
import System.ZMQ4
import ATrade.MDS.Database
import Control.Concurrent
data HistoryServer = HistoryServer ThreadId
}
startHistoryServer :: DatabaseInterface -> Context -> IO HistoryServer
startHistoryServer db ctx = do
Loading…
Cancel
Save