private static void Main(string[] args) { var activeAccounts = InstantiateAccounts(); // Stopwatch is necessary to terminate code if new loans are not found after a set time period. var stopwatch = new Stopwatch(); stopwatch.Start(); var msUntilTermination = 30000; // Multiple accounts can access the API so we might as well run them in parallel instead of waiting for one account after the other. Parallel.ForEach(activeAccounts, investableAccount => { // We only need to search for loans if the available balance >= minimum investment amount. if (investableAccount.availableCash < investableAccount.amountToInvestPerLoan) { Console.WriteLine("{0} does not have enough cash available to invest", investableAccount.accountTitle); Console.WriteLine("Amount of cash currently available: ${0}", investableAccount.availableCash); return; } Console.WriteLine("Searching for loans for the following account: {0}", investableAccount.accountTitle); Console.WriteLine("Amount of cash currently available: ${0}", investableAccount.availableCash); while (stopwatch.ElapsedMilliseconds < msUntilTermination && investableAccount.availableCash >= investableAccount.amountToInvestPerLoan) { // If this is the first time retrieving latest listed loans, retrieve all. // Retrieve only new loans for subsequent loops. if (investableAccount.getAllLoans) { latestLoansUrl = "https://api.lendingclub.com/api/investor/v1/loans/listing?showAll=true"; investableAccount.getAllLoans = false; } else { latestLoansUrl = "https://api.lendingclub.com/api/investor/v1/loans/listing?showAll=false"; } NewLoans latestListedLoans = GetNewLoansFromJson(RetrieveJsonString(latestLoansUrl, investableAccount.authorizationToken)); // If there are no newly listed loans then we do not need to continue and filter them. if (latestListedLoans.loans == null) { continue; } // We need to filter the new loans to see which ones pass the account's screening criteria. var filteredLoans = FilterNewLoans(latestListedLoans.loans, investableAccount); // There's no need to move on to building an order if there were no loans that passed the screening filter. if (!filteredLoans.Any()) { // Lending Club limited the API to one request per second so we need a delay before trying again to find new loans. Thread.Sleep(1000); continue; } Order order = BuildOrder(filteredLoans, investableAccount.amountToInvestPerLoan, investableAccount.investorID); string output = JsonConvert.SerializeObject(order); var orderResponse = JsonConvert.DeserializeObject <CompleteOrderConfirmation>(SubmitOrder(investableAccount.submitOrderUrl, output, investableAccount.authorizationToken)); var orderConfirmations = orderResponse.orderConfirmations.AsEnumerable(); // Collecting the loan IDs of purchased loans so we can prevent them from being invested in again on the next iteration of the loop. var loansPurchased = (from confirmation in orderConfirmations where confirmation.investedAmount >= 0 select confirmation.loanId); // We want to notify the user of any loans were successfully purchased. if (loansPurchased.Any()) { foreach (var loan in loansPurchased) { Console.WriteLine("The account {0} purchased loan ID: {1} at {2}", investableAccount.accountTitle, loan, DateTime.Now.ToLongTimeString()); } } // Updating the account to avoid purchasing loans that have already been purchased. investableAccount.loanIDsOwned.AddRange(loansPurchased); // Update the amount of available cash. Loop will then terminate if the available cash is less than the amount needed to invest in a loan. investableAccount.availableCash -= loansPurchased.Count() * investableAccount.amountToInvestPerLoan; } }); }
// Need to parse the API response to figure out which loans are newly listed. public static NewLoans GetNewLoansFromJson(string inputJson) { NewLoans newLoans = JsonConvert.DeserializeObject <NewLoans>(inputJson); return(newLoans); }