{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} module LendingClub.Listing ( Listing (..) , Offer (..) , Credit (..) , Grade (..) , SubGrade (..) , Purpose (..) ) where import Control.Applicative import Control.Monad (mzero) import Data.Aeson import Data.Typeable import GHC.Generics import LendingClub.Money data Listing = Listing { listingId :: !Int , listingGrade :: !Grade -- ^ analogous to ProsperRating , subGrade :: !SubGrade -- ^ maybe analogous to score? , purpose :: !Purpose -- ^ "purpose" in the API -- Market data , fundedAmount :: !Money , offer :: !Offer -- ^ Contract data , credit :: !Credit -- ^ Credit data } deriving Show -- | Two listings are equivalent if their serial numbers are equal instance Eq Listing where (Listing { listingId = id1 }) == (Listing { listingId = id2 }) = id1 == id2 -- | Data related to the listing's offer and contract terms data Offer = Offer { requestAmount :: !Money , rate :: !Double -- ^ Interest rate for the borrower , termInMonths :: !Int -- ^ Integer number of months } deriving Show -- estimatedLossRate :: Double -- Maybe Money? -- estimatedReturn :: Double -- Maybe Money? -- startDate :: Date -- Add dates later -- creationDate :: Date -- verificationStage :: Maybe Int -- Don't know what VerificationStage is... -- Add WholeLoanStartDate and WholeLoanEndDate -- | Data related to the credibility of the listing data Credit = Credit { fico :: !Int , bankcardUtilization :: !Double , isHomeowner :: !Bool , debtToIncome :: !Double , monthsEmployed :: !(Maybe Int) , currentDelinquencies :: !(Maybe Int) , amountDelinquent :: !(Maybe Money) , openCreditLines :: !(Maybe Int) , totOpenRevolvingAccts :: !(Maybe Int) , revolvingBalance :: !(Maybe Money) , revolvingAvailableCredit :: !(Maybe Int) -- ^ Percent } deriving Show -- firstCreditLine :: Date -- creditLinesLast7Years :: Int -- inquiriesLast6Months :: Int -- delinquenciesLast7Years :: Int -- These are maybe too specific to Prosper -- publicRecordsLast10Years :: Int -- oldestTradeOpenDate :: Date -- TODO Need to compare nullables to Prosper's nullables instance FromJSON Listing where parseJSON (Object v) = Listing <$> v .: "id" -- Lending club specific data <*> v .: "grade" <*> v .: "subGrade" <*> v .: "purpose" -- Market data <*> v .: "fundedAmount" <*> (Offer <$> v .: "loanAmount" <*> v .: "intRate" -- Interest Rate, might not be the same as "borrower rate" <*> v .: "term") <*> (Credit <$> v .: "ficoRangeLow" -- Choose the low-end of the FICO range <*> v .: "bcUtil" <*> (lcHomeowner <$> v .: "homeOwnership") <*> v .: "dti" <*> v .:? "empLength" <*> v .:? "accNowDelinq" <*> v .:? "delinqAmnt" <*> v .:? "openAcc" -- TODO check if "open credit lines" is the same as in Prosper <*> v .:? "numRevAccts" <*> v .:? "revolBal" <*> v .:? "revolUtil" -- TODO check if this is the same as in Prosper ) parseJSON _ = mzero data Homeownership = RENT | OWN | MORTGAGE | OTHER deriving (Show, Eq, Typeable, Generic) instance FromJSON Homeownership where lcHomeowner :: Homeownership -> Bool lcHomeowner OWN = True lcHomeowner MORTGAGE = True -- TODO This is debatable... We should think about this lcHomeowner _ = False data Grade = G | F | E | D | C | B | A deriving (Show, Eq, Ord, Typeable, Generic, Read, Enum) instance FromJSON Grade where instance ToJSON Grade where data SubGrade = G5 | G4 | G3 | G2 | G1 | F5 | F4 | F3 | F2 | F1 | E5 | E4 | E3 | E2 | E1 | D5 | D4 | D3 | D2 | D1 | C5 | C4 | C3 | C2 | C1 | B5 | B4 | B3 | B2 | B1 | A5 | A4 | A3 | A2 | A1 deriving (Show, Eq, Ord, Typeable, Generic, Read, Enum) instance FromJSON SubGrade where data Purpose = DebtConsolidation | Medical | HomeImprovement | RenewableEnergy | SmallBusiness | Wedding | Vacation | Moving | House | Car | MajorPurchase | CreditCard | Other deriving (Show, Eq, Read) instance FromJSON Purpose where parseJSON (String "debt_consolidation") = pure DebtConsolidation parseJSON (String "medical") = pure Medical parseJSON (String "home_improvement") = pure HomeImprovement parseJSON (String "renewable_energy") = pure RenewableEnergy parseJSON (String "small_business") = pure SmallBusiness parseJSON (String "wedding") = pure Wedding parseJSON (String "vacation") = pure Vacation parseJSON (String "moving") = pure Moving parseJSON (String "house") = pure House parseJSON (String "car") = pure Car parseJSON (String "major_purchase") = pure MajorPurchase parseJSON (String "credit_card") = pure CreditCard parseJSON _ = pure Other