Created
February 25, 2015 09:59
-
-
Save elvinio/b0d840ddc6d50d5dc07d to your computer and use it in GitHub Desktop.
Audit Report Generator in haskell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Prelude hiding (lookup) | |
import Data.Map (Map) | |
import qualified Data.Map as Map | |
import System.IO | |
import Data.List | |
import Data.List.Split | |
msgType = Map.fromList [("D", "NEW ORDER"), ("G", "MODIFY"), ("F", "CANCEL"), ("8", "EXECUTION"), ("9", "CANCEL"), ("i", "MASS QUOTE"), ("r", "QUOTE REQUEST"), ("b", "QUOTE ACK"), ("c", "SECURITY DEFINITION")] | |
ordStatus = Map.fromList [("0", "NEW ORDER ACK"), ("1", "PARTIAL FILL"), ("2", "COMPLETE FILL"), ("4", "CANCEL ACK"), ("5", "MODIFY ACK"), ("8", "ORDER REJECTED"), ("C", "EXPIRED"), ("H", "TRADE CANCEL")] | |
ordType = Map.fromList [("1", "MKT"), ("2", "LMT"), ("3", "STP"), ("4", "STP-LMT"), ("K", "MKT-LMT")] | |
timeInForce = Map.fromList [("0", "DAY"), ("1", "GTC"), ("6", "GTD"), ("3", "FAK")] | |
buysell = Map.fromList [("1", "B"), ("2", "S")] | |
syminfo = Map.fromList [("0", ["200", "207", "461"])] | |
ignoreMsgType = ["0", "1", "2", "4", "5", "r", "b", "A"] | |
cmeTag = ["S", "52", "1028", "207", "D", "50", "7928", "1", "49", "11", "37", "35", "39", "378", "58", "54", "38", "210", "107", "55", "200", "461", "44", "99", "31", "40", "59", "9702", "204"] | |
header = "Server Transaction Number, Server Datetime, Manual Order Identifier, Exchange Code, Message Direction, Tag 50 ID, SMP ID, Account Number, Session ID, Executing Firm, Client Order ID, Host Order Number, Message Type, Order Status,Execution Restatement Reason, Reason Code, Buy/Sell, Quantity, Max Show, Instrument Description, Product Code, Maturity Date, CFI Code, Limit Price, Stop Price, Fill Price, Order Type, Order Qualifier, Customer Type Indicator, Origin, Give-up Firm, Give-up Indicator" | |
main = do | |
putStrLn header | |
handle <- openFile "current.log" ReadMode | |
contents <- hGetContents handle | |
symbol <- openFile "symbols.csv" ReadMode | |
symbolContent <- hGetContents symbol | |
mapM_ (parseSymbol) $ lines symbolContent | |
putStrLn $ unlines $ map (fixOutput) $ lines contents | |
hClose handle | |
parseSymbol :: String -> Maybe a | |
parseSymbol input = | |
let | |
fields = splitOn "," input | |
firstChar = head $ head fields | |
securityID = head $ drop 1 fields | |
tag200 = head $ drop 4 fields | |
tag207 = head $ drop 13 fields | |
tag461 = head $ drop 14 fields | |
in | |
if firstChar == "#" | |
then Nothing | |
else Map.insert securityID [tag200, tag207, tag461] syminfo | |
fixOutput :: String -> String | |
fixOutput input = | |
let | |
timeMessage = splitOn " : " input | |
fixMsgTags = splitOn "\1" $ last timeMessage | |
fixMsgDict = Map.fromList (map (\a -> splitFixTag a) fixMsgTags) | |
shortTags = foldr (\x acc -> parseTag x fixMsgDict : acc) [] cmeTag | |
result = concat (intersperse "," shortTags) | |
in result | |
splitFixTag :: String -> (String, String) | |
splitFixTag input = | |
let fixTag = splitOn "=" input | |
in (head fixTag, last fixTag) | |
parseTag :: String -> Map.Map String String -> String | |
parseTag tag fixMsgDict = | |
let v = Map.findWithDefault "" tag fixMsgDict | |
in case tag of | |
"35" -> | |
if v == "9" | |
then | |
let tag434 = Map.findWithDefault "" "434" fixMsgDict | |
in case tag434 of | |
"2" -> "MODIFY" | |
"1" -> "CANCEL" | |
else Map.findWithDefault "" v msgType | |
"39" -> | |
let msgtype = Map.findWithDefault "" "35" fixMsgDict | |
in | |
if msgtype == "9" then "REJECTED" | |
else Map.findWithDefault "" v ordStatus | |
"59" -> Map.findWithDefault "" v timeInForce | |
"40" -> Map.findWithDefault "" v ordType | |
"54" -> Map.findWithDefault "" v buysell | |
"D" -> if v == "O" then "To CME" else "From CME" | |
"49" -> let | |
direction = Map.findWithDefault "" "D" fixMsgDict | |
senderCompID = init $ Map.findWithDefault "" "49" fixMsgDict | |
targetCompID = init $ Map.findWithDefault "" "56" fixMsgDict | |
in | |
if direction == "O" | |
then take 3 senderCompID ++ "," ++ drop 3 senderCompID | |
else take 3 targetCompID ++ "," ++ drop 3 targetCompID | |
"38" -> let | |
msgtype = Map.findWithDefault "" "35" fixMsgDict | |
ordstatus = Map.findWithDefault "" "39" fixMsgDict | |
lastshares = Map.findWithDefault "" "32" fixMsgDict | |
in | |
if msgtype == "8" && ordstatus /= "0" && ordstatus /= "8" | |
then lastshares | |
else v | |
_ -> v |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment