Welcome
This demonstrates the capabilities of Ruleau. Below you can see an
extract of the python code used
def fib(n):
from ruleau import rule, All, Any
from datetime import datetime
@rule("rul_1", "KYC Check")
def no_high_kyc_risk(context, payload):
"""
Borrower should not have a high KYC (Know Your Customer) Risk
>>> no_high_kyc_risk(None, {"creditBureau": {"KYCRisk": "HIGH"}})
True
>>> no_high_kyc_risk(None, {"creditBureau": {"KYCRisk": "Low"}})
False
"""
return payload["creditBureau"]["KYCRisk"] != "HIGH"
@rule("rul_2", "Bankruptcy Check")
def no_bankruptcy_flag(context, payload):
"""
Borrower should not have filed any bankruptcies
>>> no_bankruptcy_flag(None, {"creditBureau": {"Bankruptcies": []}})
True
>>> no_bankruptcy_flag(None, {"creditBureau": {"Bankruptcies": [{"date": "2019-01-10"}]}})
False
"""
return not bool(payload["creditBureau"]["Bankruptcies"])
@rule("rul_3", "Tax Liens")
def no_open_tax_liens(context, payload):
"""
Borrower should not have any open tax liens
>>> no_open_tax_liens(None, {"creditBureau": {"TaxLiens": []}})
True
>>> no_open_tax_liens(None, {"creditBureau": {"TaxLiens": [{"date": "2019-01-10", "status": "OPEN"}]}})
False
>>> no_open_tax_liens(None, {"creditBureau": {"TaxLiens": [{"date": "2019-01-10", "status": "CLOSE"}]}})
True
"""
return not len([x for x in payload["creditBureau"]["TaxLiens"] if x["status"] == "Open"])
@rule("rul_4", "CCJs Check")
def no_ccjs(context, payload):
"""
Borrower should not have any CCJs (County Court Judgements)
https://www.citizensadvice.org.uk/debt-and-money/borrowing-money/county-court-judgments-and-your-credit-rating/
>>> no_ccjs(None, {"creditBureau": {"CCJs": []}})
True
>>> no_ccjs(None, {"creditBureau": {"CCJs": [{"date": "2019-01-10"}]}})
False
"""
return not bool(payload["creditBureau"]["CCJs"])
@rule("rul_5", "Credit Hard Enquiries")
def no_hard_enquiries(context, payload):
"""
Borrower should not have any hard enquiries
>>> no_hard_enquiries(None, {"creditBureau": {"Inquiries": [{"date": "2020-03-11", "type": "hard"}]}})
False
>>> no_hard_enquiries(None, {"creditBureau": {"Inquiries": [{"date": "2020-03-11", "type": "none"}]}})
True
"""
return not len([x for x in payload["creditBureau"]["Inquiries"] if x["type"] == "hard"])
@rule("rul_6", "Credit Check - Max 1 Major Derogatory Incident")
def at_most_1_major_derogatory_incidents(context, payload):
"""
Borrower can have at most 1 major derogatory incident
>>> at_most_1_major_derogatory_incidents(None, {"creditBureau": {"Inquiries": [{"date": "2020-03-11", "type": "hard"}, {"date": "2020-03-11", "type": "hard"}]}})
False
>>> at_most_1_major_derogatory_incidents(None, {"creditBureau": {"Inquiries": [{"date": "2020-03-11", "type": "none"}]}})
True
"""
return len([x for x in payload["creditBureau"]["Inquiries"] if x["type"] == "hard"]) < 2
@rule("rul_7", "Credit File Length")
def years_on_credit_file(context, payload):
"""
How long has the borrower been on credit bureau's records
>>> years_on_credit_file(None, {"creditBureau": {"CreatedAt": "2021-01-02"}})
True
>>> years_on_credit_file(None, {"creditBureau": {"CreatedAt": "2010-01-01"}})
False
"""
return (datetime.now() - datetime.strptime(payload["creditBureau"]["CreatedAt"], "%Y-%m-%d")).days < 2555
@rule("rul_8", "Large Credit Cards")
def number_of_active_credit_cards_above_10k_gbp(context, payload):
"""
Borrower's number of active credit cards above GBP 10k
>>> number_of_active_credit_cards_above_10k_gbp(None, {"creditBureau": {"CreditCards": [{"status": "active", "creditLimit": 11000, "currency": "GBP"}]}})
True
>>> number_of_active_credit_cards_above_10k_gbp(None, {"creditBureau": {"CreditCards": [{"status": "active", "creditLimit": 1000, "currency": "GBP"}]}})
False
"""
return len([x for x in payload["creditBureau"]["CreditCards"] if x["status"] == "active" and x["currency"] == "GBP" and x["creditLimit"] > 10000])
@rule("rul_9", "Credit Score Lower")
def proprietary_risk_score_decline_flow(context, payload):
"""
Proprietary risk score of the customer required for a hard decline
>>> proprietary_risk_score_decline_flow(None, {"creditBureau": {"RiskScore": 580}})
True
>>> proprietary_risk_score_decline_flow(None, {"creditBureau": {"RiskScore": 600}})
False
"""
return payload["creditBureau"]["RiskScore"] < 590
@rule("rul_10", "Credit Score Higher")
def proprietary_risk_score_refer_flow(context, payload):
"""
Borrower's proprietary risk score required to qualify for referral
>>> proprietary_risk_score_refer_flow(None, {"creditBureau": {"RiskScore": 580}})
True
>>> proprietary_risk_score_refer_flow(None, {"creditBureau": {"RiskScore": 700}})
False
"""
return payload["creditBureau"]["RiskScore"] < 680
@rule("rul_11", "Debt to Income - Lower")
def unsecured_debt_to_income_ratio_decline_flow(context, payload):
"""
Borrower's unsecured debt to income ratio required to qualify for a hard decline
>>> unsecured_debt_to_income_ratio_decline_flow(None, {"creditBureau": {"UnsecuredDebtToIncomePercentage": 55}})
True
>>> unsecured_debt_to_income_ratio_decline_flow(None, {"creditBureau": {"UnsecuredDebtToIncomePercentage": 5}})
False
"""
return payload["creditBureau"]["UnsecuredDebtToIncomePercentage"] > 50
@rule("rul_12", "Debt to Income - Higher")
def unsecured_debt_to_income_ratio_refer_flow(context, payload):
"""
Borrower's unsecured debt to income ratio required to qualify for a hard decline
>>> unsecured_debt_to_income_ratio_refer_flow(None, {"creditBureau": {"RiskScore": 30}})
True
>>> unsecured_debt_to_income_ratio_refer_flow(None, {"creditBureau": {"RiskScore": 5}})
False
"""
return payload["creditBureau"]["UnsecuredDebtToIncomePercentage"] > 25
decline_if = Any(
"rul_16",
"Decline If",
no_high_kyc_risk,
no_bankruptcy_flag,
no_open_tax_liens,
no_ccjs,
no_hard_enquiries,
proprietary_risk_score_decline_flow,
unsecured_debt_to_income_ratio_decline_flow,
)
refer_if = All(
"rul_17",
"Refer If",
years_on_credit_file,
number_of_active_credit_cards_above_10k_gbp,
proprietary_risk_score_refer_flow,
unsecured_debt_to_income_ratio_refer_flow,
)
credit_lending = All(
"TOP-RULE-MA",
"Pre Release Testing",
decline_if,
refer_if,
at_most_1_major_derogatory_incidents,
good_bureau_score,
)
kudos = All(
"rul_19",
"Extra Checks",
is_income_not_consistent,
is_income_not_validated,
)
all_lending_rules = Any("rul_20", "All lending Rules", credit_lending, kudos)