{-# LANGUAGE OverloadedStrings #-} module AllyInvest.Account ( getAccounts , AccountSummary(..) , Balance(..) , BuyingPower(..) , MoneyBalance(..) , SecuritiesBalance(..) , Holding(..) , Instrument(..) , AccountType(..) ) where import AllyInvest.Credentials import AllyInvest.Error import AllyInvest.Internal import Data.Aeson import Data.Time getAccounts :: Credentials -> IO (Either AllyInvestError AccountSummary) getAccounts cred = fetchAndDecode cred "https://api.tradeking.com/v1/accounts.json" data AccountSummary = AccountSummary { aNumber :: Int , aBalance :: Balance , aHoldings :: [Holding] } deriving Show instance FromJSON AccountSummary where parseJSON (Object o) = let o' = o .: "response" >>= (.: "accounts") >>= (.: "accountsummary") in AccountSummary <$> (fmap read $ o' >>= (.: "account")) <*> ( o' >>= (.: "accountbalance")) <*> ( o' >>= (.: "accountholdings") >>= (.: "holding")) data Balance = Balance { bAccountValue :: Double , bBuyingPower :: BuyingPower , bFedCall :: Double , bHouseCall :: Double , bMoney :: MoneyBalance , bSecurities :: SecuritiesBalance } deriving Show instance FromJSON Balance where parseJSON (Object o) = Balance <$> (read <$> o .: "accountvalue") <*> ( o .: "buyingpower") <*> (read <$> o .: "fedcall") <*> (read <$> o .: "housecall") <*> ( o .: "money") <*> ( o .: "securities") data BuyingPower = BuyingPower { bpCashAvailableForWithdrawal :: Double , bpDayTrading :: Double , bpEquityPercentage :: Double , bpOptions :: Double , bpSodDayTrading :: Double , bpSodOptions :: Double , bpSodStock :: Double , bpStock :: Double } deriving Show instance FromJSON BuyingPower where parseJSON (Object o) = BuyingPower <$> (read <$> o .: "cashavailableforwithdrawal") <*> (read <$> o .: "daytrading") <*> (read <$> o .: "equitypercentage") <*> (read <$> o .: "options") <*> (read <$> o .: "soddaytrading") <*> (read <$> o .: "sodoptions") <*> (read <$> o .: "sodstock") <*> (read <$> o .: "stock") data MoneyBalance = MoneyBalance { mbAccruedInterest :: Double , mbCash :: Double , mbCashAvailable :: Double , mbMarginBalance :: Double , mbMoneyMarketFund :: Double , mbTotal :: Double , mbUnclearedDeposits :: Double , mbUnsettledFunds :: Double , mbYield :: Double } deriving Show instance FromJSON MoneyBalance where parseJSON (Object o) = MoneyBalance <$> (read <$> o .: "accruedinterest") <*> (read <$> o .: "cash") <*> (read <$> o .: "cashavailable") <*> (read <$> o .: "marginbalance") <*> (read <$> o .: "mmf") <*> (read <$> o .: "total") <*> (read <$> o .: "uncleareddeposits") <*> (read <$> o .: "unsettledfunds") <*> (read <$> o .: "yield") data SecuritiesBalance = SecuritiesBalance { sbLongOptions :: Double , sbLongStocks :: Double , sbOptions :: Double , sbShortOptions :: Double , sbShortStocks :: Double , sbStocks :: Double , sbTotal :: Double } deriving Show instance FromJSON SecuritiesBalance where parseJSON (Object o) = SecuritiesBalance <$> (read <$> o .: "longoptions") <*> (read <$> o .: "longstocks") <*> (read <$> o .: "options") <*> (read <$> o .: "shortoptions") <*> (read <$> o .: "shortstocks") <*> (read <$> o .: "stocks") <*> (read <$> o .: "total") data Holding = Holding { hAccountType :: AccountType , hCostBasis :: Double , hGainLoss :: Double , hInstrument :: Instrument , hMarketValue :: Double , hMarketValueChange :: Double , hPrice :: Double , hPurchasePrice :: Double , hQuantity :: Double , hQuoteChange :: Double , hQuoteLastPrice :: Double } deriving Show instance FromJSON Holding where parseJSON (Object o) = Holding <$> ( o .: "accounttype") <*> (read <$> o .: "costbasis") <*> (read <$> o .: "gainloss") <*> ( o .: "instrument") <*> (read <$> o .: "marketvalue") <*> (read <$> o .: "marketvaluechange") <*> (read <$> o .: "price") <*> (read <$> o .: "purchaseprice") <*> (read <$> o .: "qty") <*> (read <$> (o .: "quote" >>= (.: "change"))) <*> (read <$> (o .: "quote" >>= (.: "lastprice"))) data Instrument = Instrument { iCusip :: String , iDesc :: String , iFactor :: Double , iMaturityDate :: ZonedTime , iMaturityMonthYear :: Maybe String , iMultiplier :: Double , iPutOrCall :: String , iSecurityType :: String , iStrikePrice :: Double , iSymbol :: String } deriving Show instance FromJSON Instrument where parseJSON (Object o) = Instrument <$> ( o .: "cusip") <*> ( o .: "desc") <*> (read <$> o .: "factor") <*> ( o .: "matdt") <*> ( o .: "mmy") <*> (read <$> o .: "mult") <*> ( o .: "putcall") <*> ( o .: "sectyp") <*> (read <$> o .: "strkpx") <*> ( o .: "sym") data AccountType = CashAccount | MarginLongAccount | MarginShortAccount deriving Show instance FromJSON AccountType where parseJSON v = case (fromJSON v :: Result String) of Error err -> fail err Success t -> case t of "1" -> return CashAccount "2" -> return MarginLongAccount "5" -> return MarginShortAccount _ -> fail "bad accounttype enum"