Rules Reference

This page documents all individual rules available in the Underwriting Engine (located in pkg/rules). Each rule implements specific logic to evaluate a user’s eligibility for Floats or Installment Loans.

Rule Categories

Rules are organized by the dimension they evaluate:

Category Purpose Rule Count

Account Health

Verify account status and standing

3 rules

Transaction Activity

Analyze account usage patterns

6 rules

Payment History

Evaluate loan repayment behavior

3 rules

Income Stability

Verify regular income and deposits

3 rules

Risk Assessment

Identify fraud and suspicious behavior

4 rules

Balance & Limits

Verify available funds and limits

3 rules

Behavior Patterns

Analyze spending and transfer patterns

4 rules

Subscription & Loyalty

Verify subscription status and renewals

1 rule

External Scoring

Use ML models and external services

3 rules

Rules Summary Table

Rule Type Key Properties Min Float Rank

AgeOfAccount

Account

min_age (days)

-

AverageBalance

Balance

available_threshold

-

BalanceBetweenBounds

Balance

min_balance, max_balance, max_float_rank

0-N

BalanceRequirement

Balance

min_available, min_current

Optional

CashAdvanceScore

Scoring

min_cash_advance_score, loan_amount_window

Optional

CollectionsErrors

Payment

max_error_ratio

-

CompetitorEwa

Activity

min_advances, min_repayments, number_of_days

Optional

EssentialSpend

Activity

required_float_rank, required_number_of_transactions

Y

EWADollarAmount

Activity

required_min_borrow_amount, required_min_repayment_amount

-

FloatRank

Account

min_float_rank, max_float_rank

-

GoodStanding

Account

None

-

HighTransfer

Behavior

max_transfer_ratio, min_income

-

InstitutionCheck

Risk

institution_list, min_balance

-

LowTransactions

Activity

average_transactions, float_rank

-

MLPaybackPrediction

Scoring

min_prediction_score, max_float_count

Optional

MLPaybackPredictionVariableThreshold

Scoring

low_float_threshold, high_float_threshold, min_float_count_for_high_threshold

-

MultipleAccounts

Risk

max_accounts

-

OnTimeFloatPayback

Payment

days_after_float_on_time, required_last_floats_on_time

Y

PayrollSpend

Behavior

N/A

-

RecentFloat

Payment

max_days

Y

RecurringDeposits

Income

min_income

-

RecurringDepositsAndHighTransfer

Income

min_income, transfer_ratio

-

SpendVelocity

Behavior

spend_percentage, min_income, days_after_income

-

SubscriptionRank

Loyalty

min_rank, paid_within_days

-

SuspiciousHighBalance

Risk

high_account_balance, min_age_of_account

-

TransferRatio

Behavior

transfer_categories, max_transfer_percentage

-

ValidDebitCard

Account

None

-

Rule Definitions

Account Health

RuleAgeOfAccount

Establishes that the user’s account has been active for a minimum duration by checking the age of the oldest transaction.

  • Properties:

    • min_age (Integer): The minimum required age in days

  • Input Data: User transaction history

  • Pass Criteria: Oldest transaction date is older than min_age days ago

  • Fail Criteria: Account is younger than min_age days

  • Use Case: Prevent fraud from newly-created accounts

  • Common Values: min_age = 30, 60, 90 days

Example:

Configuration: min_age = 30 days
User account created: 45 days ago
Result: PASS (45 > 30)

RuleBalanceRequirement

Verifies the user maintains minimum funds in either Available or Current balance, optionally requiring a minimum float history.

  • Properties:

    • min_available (Integer/int64): Minimum required available balance (cents)

    • min_current (Integer/int64): Minimum required current balance (cents)

    • min_num_of_floats (Integer, Optional): Minimum completed floats required

  • Input Data: Account balances, float history

  • Pass Criteria:

    • (If min_num_of_floats set) User must have completed that many floats

    • AND (Available Balance >= min_available OR Current Balance >= min_current)

  • Fail Criteria: Both balances below thresholds OR float count insufficient

  • Use Case: Ensure user has capacity to repay

  • Common Values: min_available = $50-500, min_current = $100-1000

Example:

Configuration:
  min_available: 5000 (cents = $50)
  min_current: 10000 (cents = $100)

User State:
  available_balance: 15000 ($150)
  current_balance: 8000 ($80)

Result: PASS
  (available_balance $150 >= $50)

RuleGoodStanding

Fundamental account health check ensuring the user is an active customer without outstanding debts.

  • Properties: None

  • Input Data: User status, active floats, pending transactions

  • Pass Criteria:

    • User status is "ACTIVE" (not disabled/suspended)

    • No outstanding (Active/Pending) floats

    • No payment failures

  • Fail Criteria: User disabled OR has unpaid float outstanding

  • Use Case: Gating rule - prevents approving inactive or over-indebted users

  • Criticality: Often configured as required gate

Example:

User State:
  status: "ACTIVE" ✓
  active_floats: [] (empty) ✓
  pending_payments: [] (empty) ✓

Result: PASS (all conditions met)

RuleValidDebitCard

Verifies the user has a valid debit card on file for repayment processing.

  • Properties: None

  • Input Data: Debit card information from payment service

  • Pass Criteria: DebitCard.IsValid is true

  • Fail Criteria: No valid debit card

  • Use Case: Ensure repayment mechanism exists

  • Criticality: Gateway rule - cannot approve without payment method

Example:

User State:
  debit_card:
    card_ending_in: 1234
    is_valid: true
    expiration: 2026-12-31

Result: PASS

Transaction Activity

RuleLowTransactions

Ensures the user actively uses their account (minimum transaction velocity).

  • Properties:

    • days_to_consider (Integer): Lookback period in days

    • average_transactions (Float): Minimum average transactions per day

    • float_rank (Integer): Float count threshold for exemption

    • run_chime_varo_check (Boolean): Enable special logic for these institutions

  • Input Data: Transaction history, bank institution, float history

  • Pass Criteria:

    • Average txns/day >= average_transactions

    • OR User has > float_rank completed floats AND no active float

    • OR (If enabled) Chime/Varo special rules pass

  • Fail Criteria: Too few transactions AND no exemption triggered

  • Use Case: Identify dormant accounts (higher risk)

  • Common Values: average_transactions = 2.0, float_rank = 5

Example:

Configuration:
  days_to_consider: 30
  average_transactions: 1.5  (1.5 transactions/day)
  float_rank: 3

User State:
  transactions_last_30_days: 60
  average: 2.0 txns/day
  float_history: 2 floats

Result: PASS (2.0 >= 1.5)

RuleEssentialSpend

Rewards users who spend on essential categories (groceries, gas, utilities), indicating responsible budgeting.

  • Properties:

    • required_float_rank (Integer): Minimum floats to qualify

    • required_dollar_amount (Integer): Minimum transaction amount

    • required_number_of_transactions (Integer): Count threshold

    • essential_categories (List of Strings): Plaid category list

    • days_to_consider (Integer): Lookback period

  • Input Data: Categorized transactions (via Plaid)

  • Pass Criteria:

    • User has >= required_float_rank floats

    • AND >= required_number_of_transactions in essential categories

    • AND each >= required_dollar_amount

  • Fail Criteria: Thresholds not met

  • Use Case: Approve users with demonstrated financial responsibility

  • Common Values: required_float_rank = 1, required_number_of_transactions = 3

RuleCompetitorEwa

Analyzes whether user actively uses competitor Early Wage Access (EWA) services, indicating financial need but also experience with loans.

  • Properties:

    • number_of_days (Integer): Lookback window in days

    • min_advance_amount (Integer): Threshold to count as cash advance

    • min_inflows (Integer): Minimum competitor advances required

    • min_repayments (Integer): Minimum competitor repayments required

    • min_floats (Integer): Minimum FloatMe floats to apply rule

  • Input Data: Transaction history, merchant classification

  • Pass Criteria:

    • User has >= min_floats FloatMe floats (or N/A if not set)

    • AND >= min_inflows competitor advances

    • AND >= min_repayments competitor repayments

  • Fail Criteria: Counts insufficient

  • Use Case: Target users experienced with short-term lending

  • Common Values: min_inflows = 2, min_repayments = 2, min_floats = 0

Example:

Configuration:
  days_to_consider: 90
  min_advance_amount: 2500 ($25)
  min_inflows: 2
  min_repayments: 2

User Transactions (90 days):
  Competitor A: +$25 (inflow 1)
  Competitor A: +$20 (inflow 2)
  Competitor A: -$25 (repayment 1)
  Competitor B: -$20 (repayment 2)

Result: PASS (meets all counts)

RuleTransferRatio

Identifies users who primarily transfer money (potentially money laundering or fraudulent activity).

  • Properties:

    • days_to_consider (Integer): Lookback window

    • transfer_categories (List of Strings): Merchant categories counting as transfers

    • required_number_of_transactions (Integer): Minimum txns to evaluate (avoids false positives)

    • max_transfer_percentage (Float): Maximum allowed % transfers

  • Input Data: Categorized transactions

  • Pass Criteria:

    • (Transfer Txns / Total Txns) * 100 ⇐ max_transfer_percentage

    • OR Too few transactions to evaluate (below required_number_of_transactions)

  • Fail Criteria: Transfer percentage exceeds threshold

  • Use Case: Fraud prevention

  • Common Values: max_transfer_percentage = 30.0

Example:

Configuration:
  max_transfer_percentage: 30%
  required_number_of_transactions: 10

User Transactions (30 days): 20 total
  Transfer txns: 4
  Other txns: 16

Calculation: (4/20) * 100 = 20%

Result: PASS (20% <= 30%)

RuleEWADollarAmount

Similar to CompetitorEwa but evaluates total dollar amounts borrowed and repaid (vs. transaction counts).

  • Properties:

    • days_to_consider (Integer): Lookback window

    • required_min_borrow_amount (Integer): Minimum total borrowed

    • required_min_repayment_amount (Integer): Minimum total repaid

    • min_advance_amount (Integer): Threshold per transaction

  • Input Data: Transaction history, merchant classification

  • Pass Criteria: Total Borrowed >= threshold AND Total Repaid >= threshold

  • Fail Criteria: Amounts insufficient

  • Use Case: Identify active, substantial users of competitor services

  • Common Values: required_min_borrow_amount = 10000 ($100), required_min_repayment_amount = 10000

Payment History

RuleOnTimeFloatPayback

Validates that the user has a recent pattern of paying floats back on time.

  • Properties:

    • days_after_float_on_time (Integer): Grace period (definition of on-time)

    • required_last_floats_on_time (Integer): How many recent floats must be on time

    • required_float_rank (Integer): Minimum total floats required

  • Input Data: Float history, repayment dates

  • Pass Criteria:

    • User has >= required_float_rank completed floats

    • AND last required_last_floats_on_time consecutive floats paid within grace period

  • Fail Criteria: Float rank too low OR recent floats have late payments

  • Use Case: Reward reliable borrowers

  • Criticality: Often required for repeat users

  • Common Values: days_after_float_on_time = 3, required_last_floats_on_time = 3

RuleRecentFloat

Checks that the user actively borrows (paid back a float recently).

  • Properties:

    • max_days (Integer): Maximum days since last payback

  • Input Data: Float history, repayment dates

  • Pass Criteria: Most recent float payback is within max_days ago

  • Fail Criteria: Last float was paid back too long ago

  • Use Case: Identify dormant but otherwise qualified users

  • Common Values: max_days = 180 (6 months)

RuleCollectionsErrors

Analyzes payment failure rate (Usio debit collection errors) relative to float volume.

  • Properties:

    • max_error_ratio (Float): Maximum allowed ratio errors:floats

  • Input Data: Failed debit transactions, float count

  • Pass Criteria: (Error Count / Completed Floats) < max_error_ratio

  • Fail Criteria: Ratio >= threshold

  • Use Case: Prevent users with payment method issues

  • Common Values: max_error_ratio = 0.15 (max 15% failure rate)

Example:

User State:
  failed_debits: 2
  completed_floats: 20

Calculation: 2 / 20 = 0.10 (10%)

Configuration: max_error_ratio = 0.15 (15%)

Result: PASS (10% < 15%)

Income Stability

RuleRecurringDeposits

Verifies the user receives regular payroll or income deposits.

  • Properties:

    • min_income (Integer): Minimum amount to count as payroll

  • Input Data: Transaction history, income classification

  • Pass Criteria:

    • At least 2 payroll deposits in lookback period

    • AND at least one is "recent" (within typical pay schedule)

  • Fail Criteria: Insufficient income instances or no recent income

  • Use Case: Verify income stability

  • Common Values: min_income = 10000 ($100)

Example:

User Transaction History (90 days):
  Deposits >= $100:
    Day 15: $1000 (paycheck) ✓
    Day 30: $1000 (paycheck) ✓ recent
    Day 60: $500 (other income)

Result: PASS (2 payroll deposits, 1 recent)

RuleRecurringDepositsAndHighTransfer

Combines income stability check with transfer behavior check. User must have recent income AND not immediately transfer it away.

  • Properties:

    • min_income (Integer): Minimum income amount

    • transfer_ratio (Float): Max allowed transfer ratio

  • Input Data: Income deposits, transfer transactions

  • Pass Criteria:

    • (At least one recent Payroll Income AND No High Transfers found)

    • OR (At least one recent "Any Income" > min AND No High Transfers)

  • Fail Criteria: No recent income OR High Transfers detected

  • Use Case: Approve users with stable income and reasonable spending

  • Complexity: Combines two rule logics

RuleSpendVelocity

Identifies users who spend their paycheck too quickly after payday (risky spending pattern).

  • Properties:

    • spend_percentage (Float): Threshold % of income to spend

    • min_income (Integer): Minimum income to apply rule

    • days_after_income (Integer): Lookback window after payday

    • allowed_high_spend_instances (Integer): Max violations allowed

  • Input Data: Income deposits, spending transactions

  • Pass Criteria: Number of "high spend" instances ⇐ allowed_high_spend_instances

  • Fail Criteria: Too many instances where (Spend % Income) > threshold

  • Use Case: Prevent approving users with poor budget control

  • Common Values: spend_percentage = 0.8, allowed_high_spend_instances = 1

Example:

Configuration:
  spend_percentage: 0.8 (80%)
  days_after_income: 7
  allowed_high_spend_instances: 1

User Recent Paychecks:
  Paycheck 1: $1000
    Spending within 7 days: $950 (95% > 80%) ← violation 1

  Paycheck 2: $1000
    Spending within 7 days: $700 (70% < 80%) ← OK

violations = 1, allowed = 1

Result: PASS (violations == allowed)

Risk Assessment

RuleSuspiciousHighBalance

Flags new accounts with unusually high balances (potential fraud/money laundering).

  • Properties:

    • high_account_balance (Integer): Balance threshold (cents)

    • min_age_of_account (Integer): Age threshold (days)

  • Input Data: Current balance, account age, float history

  • Pass Criteria: User is NOT suspicious:

    • Account is old enough (>= min_age_of_account)

    • OR Balance is low enough (< high_account_balance)

    • OR User already has floats (grandfathered/trusted)

  • Fail Criteria: Account is young AND Balance is high AND No floats

  • Use Case: AML/fraud prevention

  • Common Values: high_account_balance = 500000 ($5000), min_age = 30 days

Example:

Configuration:
  high_account_balance: 500000 ($5000)
  min_age_of_account: 30 days

New User Account:
  age: 5 days (< 30) ❌
  balance: 1000000 ($10,000) (> $5000) ❌
  float_history: 0 floats ❌

Result: FAIL (suspicious)

RuleInstitutionCheck

Applies special handling for known problematic banking institutions (Chime, Varo, etc.) that allow overdrafts or have delayed posting.

  • Properties:

    • institution_list (List of Strings): List of Institution IDs/names

    • min_balance (Integer/int64): Stricter balance requirement

  • Input Data: Bank institution, account balances

  • Pass Criteria:

    • User is NOT in institution_list (Auto-pass for other banks)

    • OR User IS in list AND meets stricter balance check:

      • Available Balance >= min_balance while Current Balance >= 0

      • OR Current Balance >= min_balance while Available Balance >= 0

  • Fail Criteria: In problematic institution AND fails balance check

  • Use Case: Risk mitigation for unreliable bank data

  • Common Values: institution_list = ["chime", "varo"], min_balance = 50000 ($500)

RuleMultipleAccounts

Prevents fraud by detecting users with multiple linked accounts in the system.

  • Properties:

    • max_accounts (Integer): Maximum allowed linked accounts

  • Input Data: Linked accounts list (from user service)

  • Pass Criteria:

    • User already has completed floats (grandfathered/trusted)

    • OR unique linked accounts count ⇐ max_accounts

  • Fail Criteria: Too many linked accounts AND new user

  • Use Case: Fraud/abuse prevention

  • Common Values: max_accounts = 2

Example:

Configuration: max_accounts = 2

New User (no floats):
  Linked accounts: 5
  Result: FAIL (5 > 2, no grandfathering)

Existing User (3 previous floats):
  Linked accounts: 5
  Result: PASS (grandfathered despite high count)

RuleCashAdvanceScore

Uses an external Cash Advance Score (CAS) plus optional float rank constraints to evaluate creditworthiness.

  • Properties:

    • min_cash_advance_score (Integer): Minimum passing CAS

    • loan_amount_window (Integer): Loan amount to select correct score interval

    • min_float_rank (Integer, Optional): Minimum float count

    • max_float_rank (Integer, Optional): Maximum float count

    • deny_for_float_rank (Boolean): Enforce float rank range

  • Input Data: External CAS service, float history

  • Pass Criteria:

    • Float rank within acceptable bounds (or ignored if not enforced)

    • AND CAS Score >= min_cash_advance_score

  • Fail Criteria: Float rank violated (if enforced) OR CAS Score too low

  • Use Case: Incorporate external lending criteria

  • Complexity: References external scoring system

Behavior Patterns

RuleHighTransfer

Checks for excessive transfers immediately after payday (potential emergency need or financial distress).

  • Properties:

    • max_transfer_ratio (Float): Max allowed (Transfers / Income) ratio

    • min_income (Integer): Minimum income to apply

  • Input Data: Income deposits, transfer transactions

  • Pass Criteria: No instances where (Transfers on Payday + Next Day) > (Income * max_transfer_ratio)

  • Fail Criteria: One or more "high transfer" instances found

  • Use Case: Identify users in financial distress

  • Common Values: max_transfer_ratio = 0.5

Example:

Configuration: max_transfer_ratio = 0.5 (50%)

Payday: $2000 deposit
Transfers on Payday + Next Day: $1200

Check: $1200 > ($2000 * 0.5 = $1000) ✓ HIGH TRANSFER

Result: FAIL (found high transfer instance)

RulePayrollSpend

Analyzes spending behavior relative to payday patterns (variant of SpendVelocity).

  • Properties: (Varies, implementation-specific)

  • Input Data: Payroll deposits, spending transactions

  • Use Case: Assess budget control

  • Similar To: SpendVelocity but may have different thresholds

RuleBalanceBetweenBounds

Denies specific balance ranges for new users (prevents "testing" with small amounts).

  • Properties:

    • max_float_rank (Integer): Float count threshold, users below are subject to check

    • min_balance (Integer/int64): Lower bound of deny range

    • max_balance (Integer/int64): Upper bound of deny range

  • Input Data: Current available balance, float history

  • Pass Criteria:

    • User has >= max_float_rank floats (experienced users exempt)

    • OR Balance is outside deny range: ABS(AvailableBalance) < min_balance OR ABS(AvailableBalance) > max_balance

  • Fail Criteria: New user (< floats) AND balance falls in deny range

  • Use Case: Prevent "testing" accounts, fraud

  • Common Values: max_float_rank = 1, min_balance = 1000, max_balance = 5000

Example:

Configuration:
  max_float_rank: 1
  min_balance: 1000 ($10)
  max_balance: 5000 ($50)

New User (0 floats):
  available_balance: 2500 ($25)

Check: In deny range [1000, 5000]? YES ❌

Result: FAIL (new user with suspicious balance)

RuleAverageBalance

Verifies the user maintains sufficient average available balance over time (financial stability).

  • Properties:

    • available_threshold (Integer/int64): Minimum average available balance required (cents)

  • Input Data: Account balance history

  • Pass Criteria: Average Available Balance >= available_threshold

  • Fail Criteria: Average balance below threshold

  • Use Case: Ensure financial stability

  • Common Values: available_threshold = 50000 ($500)

Example:

Configuration: available_threshold = 50000 ($500)

User Balance History (30 days):
  Day 1: 60000
  Day 10: 45000
  Day 20: 55000
  Day 30: 50000

Average: (60000 + 45000 + 55000 + 50000) / 4 = 52500

Result: PASS (52500 >= 50000)

Subscription & Loyalty

RuleSubscriptionRank

Uses subscription history and renewals as a proxy for user stability and loyalty to FloatMe.

  • Properties:

    • min_rank (Integer): Minimum subscription renewals required

    • paid_within_days (Integer): Subscription must be paid within this many days

  • Input Data: Subscription payment history

  • Pass Criteria:

    • Current subscription rank >= min_rank

    • AND (if applicable) subscription payment occurred within paid_within_days

  • Fail Criteria: Rank too low or no recent payment

  • Use Case: Reward loyal subscribers

  • Common Values: min_rank = 2, paid_within_days = 365

External Scoring

RuleMLPaybackPrediction

Uses a Machine Learning model’s "Probability to Default" prediction score.

  • Properties:

    • min_prediction_score (Float): Maximum allowed probability to default (threshold)

    • max_float_count (Integer, Optional): Max float count to apply rule

    • deny_non_applicable (Boolean, Optional): Behavior if float count exceeded

  • Input Data: ML model inference from Sagemaker

  • Pass Criteria:

    • (If max_float_count set) Float count ⇐ threshold (or ignored if deny_non_applicable = false)

    • AND Probability to default ⇐ min_prediction_score

  • Fail Criteria: Probability to default > threshold OR float count exceeded with deny flag

  • Use Case: Leverage ML for credit decisions

  • Common Values: min_prediction_score = 0.3 (30% max default probability)

Note: The field is named min_prediction_score but actually represents the maximum allowed bad probability (confusing naming).

RuleMLPaybackPredictionVariableThreshold

Uses a Machine Learning model’s "Probability to Default" prediction score with variable thresholds based on the user’s completed float history.

  • Properties:

    • low_float_threshold (Float): Maximum allowed probability to default for users with fewer completed floats

    • high_float_threshold (Float): Maximum allowed probability to default for users with more completed floats

    • min_float_count_for_high_threshold (Integer): Minimum completed floats to use the higher (more lenient) threshold

  • Input Data: ML model inference from Sagemaker, user’s float history

  • Pass Criteria:

    • If completed floats < min_float_count_for_high_threshold: Probability to default ⇐ low_float_threshold

    • If completed floats >= min_float_count_for_high_threshold: Probability to default ⇐ high_float_threshold

  • Fail Criteria: Probability to default exceeds the applicable threshold

  • Use Case: Apply stricter ML thresholds to newer users while being more lenient with users who have a proven repayment history

  • Common Values: low_float_threshold = 0.8, high_float_threshold = 0.85, min_float_count_for_high_threshold = 3

Note: Only floats with COMPLETED debit status are counted when determining which threshold to apply.

Example:

Configuration: low_float_threshold = 0.8, high_float_threshold = 0.85, min_float_count_for_high_threshold = 3
User A: 2 completed floats, score = 0.82 → FAIL (0.82 > 0.8)
User B: 3 completed floats, score = 0.82 → PASS (0.82 <= 0.85)

Rule Execution Order

Within a rulebook, rules are typically executed in order defined in the YAML configuration. There’s no automatic re-ordering based on rule type or dependency. If rule B depends on data from rule A, they should be ordered accordingly in the rulebook definition.

Error Handling

  • If a rule errors (exception): Error is recorded at rule outcome level

  • The rulebook continues to next rule

  • Error is surfaced to rulebook level

  • Rulebook results in ERROR status

  • Final evaluation may return EVALERR status

Custom Properties

Each rule accepts a properties object in YAML that defines its behavior. Properties are rule-specific and type-safe (validated during rulebook loading).