Skip to content

charlielao/loanlib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

(this is a take-home assignment) loanlib is a library aimed to help analysts analyse a portfolio of loans. It provides simple APIs to load data, construct features, construct various loan metrics and run cashflow model simulations in a notebook. Extending features and increasing complexity should also be quite straightforward as the way iterative operation is defined is very similarly to Excel.

for examples, please read below and check the notebook folder

the library contains several pieces:

  1. data_handler.py that loads data and automatically constructs features from custom_feature.py (in a new copy)
#load the data like this

from loanlib.data_handler import DataLoader, create_features 
loader = DataLoader(SOURCE_FILE_PATH)
df = loader.combined_data_frame
loader.create_features(df)
  1. creating your own features to add to the data frame is simple, there are two main ways

I. (more recommended) add numba @njit for complex recursive operations that don't cannot get vectorised easily, either wise use numpy operations (can choose either depends on which one is more natural as the speed improvements of numba on numpy is case dependent)

    @custom_feature('input_1', 'input_2')
    @njit
    def custom_feature_1(arr1: ArrayLike, arr2: ArrayLike) -> ArrayLike:
        results = arr1+arr2
        return results

II. alternatively if it's not possible, you can still pass in dataframe, meant for dealing with objects like datetime like don't work well in numpy/numba

    @custom_feature()
    def custom_feature_2(df: pd.DataFrame) -> pd.DataFrame:
        return df.apply(some_func, axis=1)

in the first case, the order of inputs in the @custom_feature decorator is important as it transforms from pandas object to arrays for you (numba cannot deal with pandas), it also provides dependency information that helps automatically determine the order of execution so that you can define the feature in any order and the library will generate them in the correct order

  1. load_metrics.py provides LoanMetrics class that constructs loan metrics curves (SMM, MDR, CPR, CDR, Recovery) and provides plotting and pivot tables
#can pass in df, or just the data source, it will automatically load data and run the create features routine

from loanlib.core.loan_metrics import LoanMetrics

curves = LoanMetrics(df, index='time_to_reversion', pivots=['product'])
curves.curve('CPR')
curves.curve('SMM')

curves2 = LoanMetrics(SOURCE_FILE_PATH)
curves2.plot('CDR')
  1. model.py provides a simple implementation of the cashflow model that takes can configuration as a dictionary, to modify the model or add a row simply provide a pair of functions in this form, currently as there are nonvectorisable recursive functions, we use numba to iterate through functions quickly the code below roughly translates as X[T] := Y[T] - Z[T-1] similar to excel how one column could depend on previous columns if the performance doesn't matter that much, only the def _x(self, forecast_month) needs to be implemented for the final data frame to be constructed properly
    @lru_cache()
    def _x(self, forecast_month: int) -> float:
        return self._jitted_x(self._y(forecast_month), self._z(forecast_month-1))

    @staticmethod
    @njit(cache=True)
    def _jitted_x(y: float, z: float) -> float:
        return y - z
  1. lastly, to run cashflow models with run_simulations, which uses multiprocessing libraries to parallel workflow; on my laptop 10000 basic loans take about 15 seconds to simulate
from loanlib.core.model import run_simulations

base_curves = LoanMetrics(SOURCE_FILE_PATH, index ='time_to_reversion')
base_cpr = base_curves.curve('CPR')
base_cdr = base_curves.curve('CDR')
config1 = {'cpr': base_cpr, 'cdr':base_cdr}

base_cpr_2['cpr'] = base_cpr.reset_index().apply(lambda x:x['cpr'] * (2.0 if x['time_to_reversion']>=0 else 1.0 ), axis=1).values
config2 = {'cpr': base_cpr_2, 'cdr':base_cdr}

run_simulations([config1, config2])
  1. there's also a testing cases that provides skeletons to test custom features/loan_merics/models but it's by no means complete; for details see notebook q11

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published