Intro
In times of near-zero interest rates and stock valuations reaching bubble levels it's very hard to find worthwhile investment opportunities for retail investors, particularly in the fixed income space.
While searching for alternatives to traditional fixed income investments I stumbled across Lending Loop (LL), a peer-to-peer lending website that promises high single-digit returns. Their business proposition is to connect borrowers and savers, allowing retail investors to lend directly to small business.
The idea certainly has its merits. It essentially eliminates the middleman (the banks) from the equation, giving retail investors access to high return assets. On the downside, it exposes investors to a great deal of credit risk, which is assumed by the bank when they're involved.
Being aware of the potential risks involved I searched for online reviews of the platform that would give me an indication of the risk and return profile of the investment. Unfortunately, most of what I found online was very superficial and focused on explaining how the website works.
Frustrated with the lack of a proper risk return analysis I decided to run my own. My idea was to run a monte carlo simulation on a portfolio of hypothetical loans to assess the return distribution. Luckily, Lending Loop is transparent enough to publish the historical data needed for the analysis.
|
Rating
|
% of Loans
|
Average Interest Rate
|
Lifetime Prob. of Default
|
Phi
|
|
A+
|
0.96%
|
7.66%
|
2%
|
0.2
|
|
A
|
8.19%
|
9.62%
|
4%
|
0.2
|
|
B+
|
14.94%
|
11.06%
|
5%
|
0.2
|
|
B
|
21.40%
|
12.52%
|
6%
|
0.2
|
|
C+
|
17.83%
|
13.99%
|
7%
|
0.2
|
|
C
|
15.28%
|
15.47%
|
9%
|
0.2
|
|
D+
|
9.38%
|
17.26%
|
10%
|
0.2
|
|
D
|
6.48%
|
19.35%
|
12%
|
0.2
|
|
E+
|
4.09%
|
22.66%
|
16%
|
0.2
|
|
E
|
1.45%
|
26.28%
|
18%
|
0.2
|
Calculating Default Rates
The default rates provided in the table above are lifetime default rates so they need to be converted to monthly rates. According to Lending Loop, default rates can be modelled by an exponential distribution with the following cumulative function:
$F(\lambda,x) = LD(1 - e^{\lambda t})$
Where $LD$ is the lifetime default probability, $t$ is the time in months and $\lambda$ is a parameter estimated based on empirical data, usually in the neighborhood of 0.1 according to LL. We will adopt $\lambda = 0.2$ to be on the conservative side.
As an example, we can use the available data to calculate the cumulative default distribution of an A-rated loan.
import numpy as np
from matplotlib import pyplot as plt
t = 33 #Average term of lending loop loans
lifetime_pd = 0.06 #Lifetime default rate of A-rated loans
l = 0.2 #Lambda
t_vec = np.arange(t) + 1
cumulative_prob = lifetime_pd * (1 - np.exp(-t_vec * l))
plt.plot(t_vec, cumulative_prob)
This is the resulting output.
By using this function to describe the cumulative defaults we are assuming most defaults occur early on and then slowly converge the to lifetime default rate. This seems to be supported by empirical results and is more conservative than a linear default distribution.
Using the cumulative default values we can determine the monthly default rate by calculating the month-over-month difference using numpy's diff function.
prob = np.diff(cumulative_prob, prepend=0)
plt.plot(t_vec, prob)
From the chart we can see in the first month the probability of default is around 1%. This decreases rapidly and in month 5 it is already down to approximately 0.4%.
Simulating Default Events
We can use numpy's random number generator to simulate defaults based on the monthly default rates we just calculated. To do this, we create an array of random numbers sampled from a uniform distribution with the same length as the probability array. Then, we use numpy's where function to generate the default events by assigning 0 every time the probability of default is higher than the random number and 1 otherwise.
rnd = np.random.uniform(size=prob.shape)
default_event = np.where(rnd < prob, 0, 1)
To visualize how this works we can print the first 10 elements of the random array and monthly default rate.
In[1]: print(rnd[:10])
[0.417 0.720 0.000 0.302 0.147 0.092 0.186 0.346 0.397 0.539 ...]
In[2]: print(prob[:10])
[0.011 0.009 0.007 0.006 0.005 0.004 0.003 0.003 0.002 0.002 ...]
In this instance, the third element of the rnd array is smaller than the monthly default rate at the same position in prob, so the default event array will have a zero assigned to it at that position.
In[3]: print(default_event[:10])
[1 1 0 1 1 1 1 1 1 1 ...]
This is not the whole story as we still need to assign a zero to every element after the first default event, indicating the loan is no more performing after that point. We can do this using the cumprod function, which will perform a cumulative multiplication on all elements of the array.
In[4]: loan_default = np.cumprod(default_event)
print(loan_default[:10])
[1 1 0 0 0 0 0 0 0 0 ...]
I note that the calculation above assumes that once default happens no more payments are received. In reality, once a borrower start missing payments, Lending Loop will try to negotiate a payment plan or even pursue legal action to recover at least part of the loan. In my calculations I decided to be on the conservative side and assume there is no recovery after a default.
Loan Payments and Performance
At this point we are able calculate monthly default rates and simulate default events using a random number generator. The only thing missing to calculate how much money we can make out of this loan is the calculation of the monthly payment. Lending Loop charges a fixed monthly payment schedule, which can be calculated by:
$m= P \frac{r(1 + r)^t}{ (1 + r)^t - 1 }$
Where $m$ is the monthly payment, $P$ is the principal, $t$ is the term of the loan and $r$ is the monthly interest rate net of fees (Lending Loop charges a 1.5% annual fee). We can use numpy to apply this formula using an A-rated loan as an example.
In [5]: p = 100
r = (0.083 - 0.015)/12 #Monthly A-rated expected return net of fees
m = p * ((r * (1 + r)**t) / ((1 + r)**t - 1)) #Monthly payment calculation
print(m)
3.331
This results in a monthly payment of $3.33 that will be constant throughout the life of the loan unless there is a default.
Performance
We're going to use the internal rate of return (IRR) to calculate the performance of the loan. Mathematically, IRR is defined as the discount rate that makes the present value of all cash flows equal to zero. It's the same concept applied when we calculate the yield of a bond. In python we can apply it using numpy-financial, a spin-off of numpy containing financial functions.
To apply the IRR function we need an array with all the cash flows of the loan, which we can obtain by multiplying the loan_default array by the monthly payment m. We also need to add the initial investment a negative cash flows at the start of the array.
In [6]: cash_flows = np.append(-p, loan_default * m)
print(cash_flows[:10])
print(npf.irr(cash_flows))
[-100.000 3.331 3.331 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ...]
-0.800
Applying the IRR function on these cash flows results in a negative rate of 80%! That's a terrible result but it simply reflects the fact we only received 2 out of 33 payments back. If there was no default the IRR would be equal to the interest rate of the loan.
Monte Carlo
In the previous sections we built all the toolkit we need to run a monte carlo simulation. We just need to make some changes to the code since we are interested in simulating a portfolio of loans and not a single loan.
To measure risk and return in our simulation we will use the concept of a loan cohort, i.e., a set of loans we invest at t=0 and hold until maturity, collecting the interest and principal payments. To accomplish this we need to switch from working with a single dimensional array (single loan) to a multi-dimensional one (cohort of loans). Once these changes are done all we need is to create a loop to repeat this over n iterations and store the results.
I'm not going to get into the details of the implementation since this article is already getting much longer than I expected, but it should be straightforward if you have a little knowledge of python and numpy. You can find the complete code here. I also encapsulated the calculation in a class to make the implementation a little cleaner.
Results
With the monte carlo code ready we're almost ready to run our analysis, we just need to determine a key variables first.
The first decision is the number of loans in our cohort. On average LL had 60 loans listed on its platform per quarter, so that's a reasonable assumption for the number of loans in our cohort. We are also assuming these loans are available at the beginning of the quarter, which is not true, but this greatly simplifies our code. I also note the number of loans listed in the platform has recently dwindled as LL adopted stricter criteria for borrowers due to the Covid-19 but this is expected to rebound once the pandemic is over.
The loan cohort will be sampled according to the distribution of ratings published by LL, so out of the 60 loans in each cohort, on average 0.96% will be A+, 8.19% will be A, so on and so forth. The minimum investment allowed by Lending Loop is $25 per loan, so that's the principal we will use for all loans in our calculation (which won't really affect our results as measure by IRR).
With all our variables defined we can run our monte carlo simulation for the base scenario. After 10,000 iterations, the simulation resulted in an average IRR of 7.9% with a standard deviation of 2.4%. The 7.9% average return is a pretty attractive number these days, but but how risky is it? To answer that question we can take a look at the distribution of IRRs generated by the monte carlo simulation.

We can see the distribution is a bit skewed to the left but there are not too many negative IRRs. In fact, less than 1% of the simulations had a negative return and 89% of the time the return was above 5%. This gives us some comfort that the chance of losing money is somewhat remote if we believe the the historical data published by LL is a good guide for the future.
We can also stress the default rates and see what results we get. Doubling the default rates during the whole period (a really severe scenario) gives us an expected return of 3.2% and a 16% chance of having a negative IRR. Much worse than the base case but not a deal breaker, considering how remote the chance of this scenario playing out is. During the Covid-19 pandemic, for example, default rates increased by 50%, so it would take an even more severe scenario to make them double.

We can also use the monte carlo simulation to study the impact of other variables in our model. One particularly interesting effect comes from changing the number of loans in the cohort. Reducing the number of loans to 10 but keeping the same assumptions of the base case results in an average IRR of 5.9% and P(IRR < 0) = 12%, almost as bad as the previous scenario with doubled default rates. This shows the importance of having a large number of loans and a small exposure to each loan.
The histogram also shows an interesting story here. It doesn't resemble a single normal distribution anymore but various, clustered according to the number of defaults in the simulation.

We can extend this thought further and uncover some unintuitive results. Let's say you're a very conservative investor and want to invest only in A-rated loans. In theory, this should be safer than investing in loans of all ratings. However, there are not too many A-rated loans listed in the platform, in fact only about 10% of the total are A+ or A.
If we simulate a portfolio with 6 A-rated loans (10% of 60) we get worst results than our base case with an expected return of 5.6% and 17% of the simulations generating negative returns. Ironically, by being very conservative we might end up with a risky portfolio due to real-life constraints.
Here the histogram is even weirder, with a big bar with 0 defaults and smaller clusters of simulations where defaults happened.
My conclusion from all this is that Lending Loop is probably a worthwhile investment to diversify your portfolio with an asset class that is generally not accessible to retail investors. The risk return profile seems sounds as long as you don't have a concentrated exposure in a few loans. I already invested some money there, let's hope reality agrees with my analysis!
Comments
Post a Comment