Tech Tips - LendingClub REST API Access With Python
Tech Tips - LendingClub REST API Access With Python
Tech Tips
Random ramblings on technical topics.
We d n e s d a y, N o v e m b e r 2 5 , 2 0 1 5
Summary
LendingClub is one of the peer‐to‐peer lenders out there. They provide a REST API for simple account transactions such as querying account data, available loans, and
submitting loan orders. In this article, I'll be discussing the development of a simple auto‐investment tool I wrote in Python with the Lending Club API. The application
reads a user‐configurable file for options and then if funds are available and loans exist that meet the user's criteria, orders are placed with LendingClub for those loans. Follow 34
The application was designed to be run out of a cron script to periodically check funds + loans and place orders accordingly.
View my complete pro
I have an additional set of articles discussing integration of machine learning techniques with this API here.
Preparation
Obviously, Step 1 is to establish an account at LendingClub. After that, you can make a request for access to the REST API. There are two critical pieces of info you'll need
execute any API calls: the Account ID and an Authorization Key. LendingClub uses the auth key method for securing access to their API. As will be discussed later, the Follow by Email
auth key will be passed as a HTTP header item for any API call.
Email address...
Application Organization
Figure 1 below depicts the overall organization of this application. All user‐configurable options are held in a configuration file. The ConfigParser module is utilized for
Blog Archive
reading that file. Configuration state is managed in a class I developed called ConfigData. All the REST calls to the LendingClub API are bundled into a class I developed
called LendingClub. The requests module is leveraged for the HTTP operations. ► 2018 (8)
► 2017 (15)
► 2016 (6)
▼ 2015 (11)
▼ November (1)
LendingClub RES
with Python
► August (1)
► July (1)
► June (2)
► May (1)
► April (2)
► February (2)
► January (1)
► 2014 (22)
► 2013 (13)
Total Pageviews
17
Figure 1
Code Snippets
Configuration File
1. [AccountData]
2. investorId = yourId
3. authKey = yourAuthKey
4. reserveCash = 0.0
5. investAmount = 25.00
6. portfolioName = A Loans
7. [LoanCriteria]
8. grade = A
9. term = 36
10. delinq2Yrs = 0
http://joeywhelan.blogspot.com/2015/11/lendingclub-rest-api-access-with-python.html 1/4
3/22/2018 Tech Tips: LendingClub REST API access with Python
Line 3: The authorization key issued by LendingClub when you request access to their API.
Line 4: The amount of cash you want to remain in 'reserve'. That means it will not be invested.
Line 5: The amount you want invested in each loan.
Line 6: The textual name of the portfolio where you want any loan purchases to be placed.
Line 7: LoanCriteria section of the configuration file.
Lines 8‐10: Any criteria you wish to employ to filter loans for investment. The filtering logic in the main app (discussed later) is very simple ‐ it looks at equality only,
e.g. does Grade = 'A'. You can find a full listing of the various loan data points in the Lending Club API documentation for the LoanList resource.
Application Body
1. class ConfigData(object):
2. def __init__(self, filename):
3. cfgParser = ConfigParser.ConfigParser()
4. cfgParser.optionxform = str
5. cfgParser.read(filename)
6. self.investorId = self.castNum(cfgParser.get('AccountData', 'investorId'))
7. self.authKey = cfgParser.get('AccountData', 'authKey')
8. self.reserveCash = self.castNum(cfgParser.get('AccountData', 'reserveCash'))
9. self.investAmount = self.castNum(cfgParser.get('AccountData', 'investAmount'))
10. if self.investAmount < 25 or self.investAmount % 25 != 0:
11. raise RuntimeError('Invalid investment amount specified in configuration file')
12. self.portfolioName = cfgParser.get('AccountData', 'portfolioName')
13. criteriaOpts = cfgParser.options('LoanCriteria') #Loan filtering criteria
14. self.criteria = {}
15. for opt in criteriaOpts:
16. self.criteria[opt] = self.castNum(cfgParser.get('LoanCriteria', opt));
17.
18. def castNum(self, val):
19. try:
20. i = int(val)
21. return i
22. except ValueError:
23. try:
24. d = decimal.Decimal(val)
25. return d
26. except decimal.InvalidOperation:
27. return val
1. class LendingClub(object):
2. apiVersion = 'v1'
3.
4. def __init__(self, config):
5. self.config = config
6. self.header = {'Authorization' : self.config.authKey, 'Content-Type': 'application/json'}
7. self.loans = None
8. self.cash = None
9. self.portfolioId = None
10.
11. self.acctSummaryURL = 'https://api.lendingclub.com/api/investor/' + LendingClub.apiVersion + \
12. '/accounts/' + str(self.config.investorId) + '/summary'
13. self.loanListURL = 'https://api.lendingclub.com/api/investor/' + LendingClub.apiVersion + \
14. '/loans/listing'
15. self.portfoliosURL = 'https://api.lendingclub.com/api/investor/' + LendingClub.apiVersion + \
16. '/accounts/' + str(self.config.investorId) + '/portfolios'
17. self.ordersURL = 'https://api.lendingclub.com/api/investor/' + LendingClub.apiVersion + \
18. '/accounts/' + str(self.config.investorId) + '/orders'
19.
20. def __getCash(self):
21. resp = requests.get(self.acctSummaryURL, headers=self.header)
22. resp.raise_for_status()
23. return decimal.Decimal(str(resp.json()['availableCash']))
24.
25.
26. def __getLoans(self):
27. payload = {'showAll' : 'true'}
28. resp = requests.get(self.loanListURL, headers=self.header, params=payload)
29. resp.raise_for_status()
30.
31. loanDict = {}
32. for loan in resp.json()['loans']:
33. numChecked = 0
34. for criterion in self.config.criteria:
http://joeywhelan.blogspot.com/2015/11/lendingclub-rest-api-access-with-python.html 2/4
3/22/2018 Tech Tips: LendingClub REST API access with Python
35. if loan[criterion] == self.config.criteria[criterion]:
36. numChecked += 1
37. else:
38. break
39. if numChecked == len(self.config.criteria):
40. loanDict[loan['id']] = loan['fundedAmount'] / loan['loanAmount']
41. logger.info('Loan id:' + str(loan['id']) + \
42. ' was a match, funded percentage = ' + str(loanDict[loan['id']]))
43. return sorted(loanDict.items(), key=operator.itemgetter(1), reverse=True)
44.
45. def __postOrder(self, aid, loanId, requestedAmount, portfolioId):
46. payload = json.dumps({'aid': aid, \
47. 'orders':[{'loanId' : loanId, \
48. 'requestedAmount' : float(requestedAmount), \
49. 'portfolioId' : portfolioId}]})
50. resp = requests.post(self.ordersURL, headers=self.header, data=payload)
51. retVal = resp.json();
52.
53. if 'errors' in retVal:
54. for error in retVal['errors']:
55. logger.error('Order error: ' + error['message'])
56. resp.raise_for_status()
57.
58. confirmation = retVal['orderConfirmations'][0]
59. logger.info('OrderId:' + str(retVal['orderInstructId']) + ', $' + \
60. str(confirmation['investedAmount']) + ' was invested in loanId:' + str(confirmation['loanId']))
61. return decimal.Decimal(str(confirmation['investedAmount']))
1. try:
2. lc = LendingClub(ConfigData(CONFIG_FILENAME))
3. while lc.hasCash() and lc.hasLoans():
4. lc.buy()
5. except:
6. logger.exception('')
Line 2: Instantiate a LendingClub object with the configuration data object as the input parameter.
Lines 3‐4: Loop based on availability of cash and matching loans. If both exist, place an order.
No comments:
Post a Comment
Publish Preview
http://joeywhelan.blogspot.com/2015/11/lendingclub-rest-api-access-with-python.html 3/4
3/22/2018 Tech Tips: LendingClub REST API access with Python
http://joeywhelan.blogspot.com/2015/11/lendingclub-rest-api-access-with-python.html 4/4