Datascience Econ Lectures - Randomess

Hi everyone,

First, thanks to authors for such nicely paced yet simple lectures.

I have question regarding simulate Loan repayment function. It appears in Quantecon Datascience Lectures - Scientific Computing - Randomness section (For easy access to readers).

In function def simulate_loan_repayments_slow each value in the array repayment_sims is present valued using code line repayment_sims[i] = (1 / (1 + r)) * repaid.

However, in the vectorized version def simulate_loan_repayments, no such discounting is conducted for both repayment_sims arrays.

Have I missed any subtlety?

Also, while defining full in the vectorized version def simulate_loan_repayments, Bitwise NOT (~) was used(full = ~partial & (random_numbers <= 0.95). How exactly this operation works in this function? For, as I understand, this bitwise inversion works only on integral numbers whereas code generates random numbers between 0 and 1.

Also, correlated question is, how the vectorized function def simulate_loan_repayments covers entire range of 95% probability of both full and partial repayments, when it returns repayment_sims?.

Thank You for your assistance and I apologize if this is all very trivial.

Hi @Devendra42!

Thanks for asking these questions – We’re glad that you’re using the material.

For the first question, you are correct that the payments should be discounted – This is a mistake in the lectures (which we will correct). We should update the simulate_loan_repayments function to discount future payments. This could be done simply by returning (1 / (1+r))*repayment_sims rather than just repayment_sims.

Good question on the ~ operator. We probably should have a little more explanation on what this does. In this case, we create a new array called partial = random_numbers <= 0.20 which is an array of booleans that denotes whether that particular loan was partially repaid. We then fill the repayment_sims array with the partial payment (repayment_part) everywhere that array has True values. Next, we want to determine whether there was full repayment. Partial repayment happened with probability 0.20 and full repayment occurs with probability 0.75. The ~ operator will simply act like not from the boolean lectures, so it will switch True to False and False to True. The & operator will act like the and operator f rom the boolean lecture – The loans that are fully repaid are the ones that happen when the random number is less than 0.95 (0.2 + 0.75) AND that aren’t partial repayments. This also could have been defined as full = (random_numbers > 0.20) & (random_numbers < 0.95).

Does this help? Please continue to ask questions if you have more questions on this or any other lecture.


Hi Chase,

Thank you for your reply. For (~) query creation of boolean array was the idea, I was missing. I should have used print statements at appropriate locations as shown below. However, I was able to guess the NOT operator is used to exclude probability with partial repayments.

Thanks again

def simulate_loan_repayments(N, r=0.05, repayment_full=25000.0,repayment_part=12500.0):
random_numbers = np.random.rand(N)
repayment_sims = np.zeros(N)

partial = random_numbers<=0.2

full = ~partial&(random_numbers<=0.95)

print((1 / (1 + r)) *repayment_sims)

return (1 / (1 + r)) *repayment_sims



[0.21223472 0.62148251 0.54621512 0.07365904 0.16142408] #print(random_numbers)
[0. 0. 0. 0. 0.] #print(repayment_sims(zeros))
[ 0. 0. 0. 12500. 12500.] #print(repayment_sims(Partial))
[25000. 25000. 25000. 12500. 12500.] #print(repayment_sims(Full))
[23809.52380952 23809.52380952 23809.52380952 11904.76190476
11904.76190476] #print((1 / (1 + r)) *repayment_sims)
19047.619047619046 #np.mean(simulate_loan_repayments(5))