cot-0.1.0.0: exe/Main.hs
module Main (main) where
import Data.COT
import Data.Version
import Options.Applicative
import Paths_cot
import Prettyprinter
import Text.Megaparsec hiding (option)
import Text.Read
main :: IO ()
main = do
cli <- customExecParser prefs' $ pinfo $ showVersion version
case cli of
ParseCOT s fM -> do
i <- maybe getContents readFile fM
putStrLn $ either errorBundlePretty (render s) $ parseCOT i
PrettyCOT ty d c e u co oi (p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) cf
(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) (o0,o1,o2,o3,o4,o5,o6,o7,o8,o9,o10)
tt (t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) fM ->
maybe putStrLn writeFile fM $ show $ pretty $
Rpt{rptType=ty,date=d,contract=c,exchange=e,underlying=u
,code=co,openInterest=oi,changesFrom=cf,totTraders=tt
,prod=Cat{posLong=p0, posShort=p1, posSpread=Nothing
, changeLong=c0, changeShort=c1, changeSpread=Nothing
, pctOpenLong=o0, pctOpenShort=o1, pctOpenSpread=Nothing
, tradersLong=t0, tradersShort=t1, tradersSpread=Nothing}
,swap=Cat{posLong=p2, posShort=p3, posSpread=p4
, changeLong=c2, changeShort=c3, changeSpread=c4
, pctOpenLong=o2, pctOpenShort=o3, pctOpenSpread=o4
, tradersLong=t2, tradersShort=t3, tradersSpread=t4}
,managed=Cat{posLong=p5, posShort=p6, posSpread=p7
, changeLong=c5, changeShort=c6, changeSpread=c7
, pctOpenLong=o5, pctOpenShort=o6, pctOpenSpread=o7
, tradersLong=t5, tradersShort=t6, tradersSpread=t7}
,other=Cat{posLong=p8, posShort=p9, posSpread=p10
, changeLong=c8, changeShort=c9, changeSpread=c10
, pctOpenLong=o8, pctOpenShort=o9, pctOpenSpread=o10
, tradersLong=t8, tradersShort=t9, tradersSpread=t10}
}
render :: Bool -> COT -> String
render s c | s = show c
| otherwise = show $ vsep $ map pretty c
prefs' :: ParserPrefs
prefs' = prefs $ showHelpOnError <> showHelpOnEmpty
pinfo :: String -> ParserInfo CLI
pinfo v = info (parser <**> simpleVersioner v <**> helper) $
progDesc "Commitments of Traders"
data CLI = ParseCOT Bool (Maybe String)
| PrettyCOT RptType String String String String String
Integer (Row (Maybe Integer)) String (Row (Maybe Integer)) (Row (Maybe Double)) Integer
(Row (Maybe Integer)) (Maybe String)
type Row a = (a,a,a,a,a,a,a,a,a,a,a)
parser :: Parser CLI
parser = hsubparser $ mconcat
[ command "parse" $ info (ParseCOT <$> showSwitch <*> optional fileArg) $
progDesc "Parse COT reports"
, command "pretty" $ info prettyParser $ progDesc "Prettyprint COT report"
]
showSwitch :: Parser Bool
showSwitch = switch $ short 's' <> long "show" <> help "Show instance. Default pretty."
fileArg :: Parser String
fileArg = strArgument $ metavar "FILE" <> completer (bashCompleter "file")
<> help "Optional input file otherwise stream STDIN"
prettyParser :: Parser CLI
prettyParser = PrettyCOT
<$> (flag' Futes (long "futes" <> help "futures only report type") <|>
flag' OptsAndFutes (long "opts-futes" <> help "options and futures report type"))
<*> strOption (long "date" <> help "report date")
<*> strOption (long "contract" <> help "report contract")
<*> strOption (long "exchange" <> help "report exchange")
<*> strOption (long "under" <> help "underlying asset")
<*> strOption (long "code" <> value "000000" <> showDefault <> help "CFTC code")
<*> option auto (long "open-interest" <> value 0 <> showDefault <> help "report open interest")
<*> option (eitherReader row) (long "positions" <> value nrow <> help "report positions, default dots")
<*> strOption (long "changes-from" <> help "date of last change")
<*> option (eitherReader row) (long "changes" <> value nrow <> help "report changes, default dots")
<*> option (eitherReader row) (long "percents" <> value nrow <> help "percents of open interest, default dots")
<*> option auto (long "total-traders" <> value 0 <> showDefault <> help "report total traders")
<*> option (eitherReader row) (long "traders" <> value nrow <> help "report traders, default dots")
<*> optional fileArg
nrow :: Row (Maybe a)
nrow = (Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing
,Nothing,Nothing)
row :: Read a => String -> Either String (Row (Maybe a))
row = rrow readVal
where
readVal "." = Right Nothing
readVal v = Just <$> readEither v
rrow :: Read a => (String -> Either String a) -> String -> Either String (Row a)
rrow r s = case words s of
[w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10] -> (,,,,,,,,,,) <$> r w0 <*> r w1
<*> r w2 <*> r w3 <*> r w4 <*> r w5 <*> r w6 <*> r w7 <*> r w8 <*>
r w9 <*> r w10
_ -> Left "expecting 11 row elements"