Lesson 19 · Python for Banking and Finance
Understanding End-of-Day Processing Logic in Banking with Python
We will learn how banks process transactions and balances at the end of each day. EOD logic is crucial for accurate account balances, interest calculation,…
- CoursePython for Banking and Finance
- Lesson19 of 24
- Video21 min
- FormatJupyter notebook · 17 code cells
- Data1 dataset
What you'll learn
- Understanding the Data for EOD Processing
- Beginner Example 1: Daily Transaction Counts
- Beginner Example 2: Daily Totals for Debits and Credits
- Beginner Example 3: Find Missing Transaction Days
- Intermediate Example 1: EOD Account Balance Calculation
- Intermediate Example 2: Interest Accrual at EOD
- Intermediate Example 3: Suspicious Transaction Patterns at EOD
- Advanced Example 1: EOD Region-Wise Consolidated Balances
Datasets used in this lesson
Save these next to the notebook. In Google Colab, upload them with the 📁 icon on the left first.
- eod_closure_sample.csv6.7 KB
📓 Full notebook
Download .ipynbEnd-of-Day (EOD) Processing Logic in Banking#
- We will learn how banks process transactions and balances at the end of each day.
- EOD logic is crucial for accurate account balances, interest calculation, and regulatory reports.
- You will build Python tools to mimic real-world EOD processing using synthetic banking data.
- By the end, you will know how to summarize transactions, calculate balances, and spot possible issues.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
np.random.seed(42)
Understanding the Data for EOD Processing#
- We will use sample banking transactions, customers, and accounts.
- Transactions record debits and credits by customer and account.
- Accounts link to customers and types (savings, cheque, credit, etc).
- Common pitfalls: incorrect grouping, missing timestamps, or misclassified transactions.
n_transactions = 1000
n_customers = 200
df = pd.DataFrame({
'transaction_id': range(1, n_transactions + 1),
'customer_id': np.random.choice([f'CUST_{i:04d}' for i in range(1, n_customers + 1)], n_transactions),
'amount': np.round(np.random.normal(150, 60, n_transactions), 2),
'transaction_type': np.random.choice(['Debit', 'Credit'], n_transactions),
'channel': np.random.choice(['ATM', 'Online', 'Branch', 'POS'], n_transactions),
'date': pd.date_range(start='2024-01-01', periods=n_transactions, freq='h')
})
print(df.shape)
print(df.head(3))
customer_ids = [f'CUST_{i:04d}' for i in range(1, 201)]
customers = pd.DataFrame({
'customer_id': customer_ids,
'segment': ['Retail'] * 150 + ['Business'] * 50,
'region': ['Metro'] * 100 + ['Regional'] * 100
})
print(customers.shape)
print(customers.head(3))
accounts = pd.DataFrame({
'account_id': [f'ACC_{i:05d}' for i in range(1, 201)],
'customer_id': customer_ids,
'account_type': np.random.choice(['Savings', 'Cheque', 'Credit'], size=200),
'open_date': pd.date_range(start='2015-01-01', periods=200, freq='30D')
})
print(accounts.shape)
print(accounts.head(3))
Beginner Example 1: Daily Transaction Counts#
- A simple EOD check is to count the number of transactions per day.
- This shows overall banking activity and helps detect spikes or outages.
daily_counts = df.groupby(df['date'].dt.date).size()
print(daily_counts.head(3))
Beginner Example 2: Daily Totals for Debits and Credits#
- EOD processing checks that money in and out is tracked daily.
- Let us summarize daily totals by transaction type.
daily_sums = df.groupby([df['date'].dt.date, 'transaction_type'])['amount'].sum().unstack().fillna(0)
print(daily_sums.head(3))
Beginner Example 3: Find Missing Transaction Days#
- Sometimes no transactions are recorded on holidays or weekends.
- Missing days can cause confusion or errors in EOD routines.
all_days = pd.date_range(df['date'].min().date(), df['date'].max().date(), freq='D')
transaction_days = pd.to_datetime(daily_counts.index)
missing_days = set(all_days.date) - set(transaction_days.date)
print(sorted(list(missing_days))[:5])
Intermediate Example 1: EOD Account Balance Calculation#
- EOD balance is a core step in all account processing.
- For each account and day, calculate the running balance.
df['amount_signed'] = np.where(df['transaction_type'] == 'Debit', -df['amount'], df['amount'])
df_merged = df.merge(accounts[['account_id', 'customer_id']], on='customer_id')
eod_balances = df_merged.groupby(['account_id', df_merged['date'].dt.date])['amount_signed'].sum().groupby('account_id').cumsum()
eod_balances = eod_balances.reset_index(name='balance')
print(eod_balances.head(5))
acct_summary = eod_balances.groupby('account_id').tail(1).sort_values(by='balance', ascending=False)
print(acct_summary.head(5))
Intermediate Example 2: Interest Accrual at EOD#
- Banks often calculate interest at EOD, especially for savings accounts.
- We will estimate interest on balances above $1000.
interest_rate = 0.01 / 365
eod_interest = eod_balances.copy()
eod_interest['interest'] = np.where(eod_interest['balance'] > 1000, eod_interest['balance'] * interest_rate, 0)
print(eod_interest[['account_id', 'balance', 'interest']].head(5))
total_interest = eod_interest.groupby('account_id')['interest'].sum().sort_values(ascending=False)
print(total_interest.head(5))
Intermediate Example 3: Suspicious Transaction Patterns at EOD#
- EOD systems must flag suspicious transaction spikes for review.
- Let us mark days where a customer makes more than four transactions in one day.
suspicious = df.groupby([df['customer_id'], df['date'].dt.date]).size().reset_index(name='num_tx')
flagged = suspicious[suspicious['num_tx'] > 4]
print(flagged.head(5))
Advanced Example 1: EOD Region-Wise Consolidated Balances#
- Banks aggregate customer balances by region for reporting and liquidity management.
- Let us summarize final EOD balances by customer region.
acct_region = acct_summary.merge(accounts[['account_id', 'customer_id']], on='account_id')
acct_region = acct_region.merge(customers[['customer_id', 'region']], on='customer_id')
region_totals = acct_region.groupby('region')['balance'].sum()
print(region_totals)
Advanced Example 2: EOD Closure File Generation#
- EOD systems normally write daily closure files with balances and summaries for audit.
- Let us export the end-of-day balance data for compliance review.
closure_file = 'eod_closure_sample.csv'
acct_summary.to_csv(closure_file, index=False)
print(f'Closure file created: {closure_file}')
Error Handling Example: Invalid or Duplicate Transactions#
- EOD processing should catch errors such as duplicate transactions or invalid amounts.
- Let us check for negative or zero transaction amounts and duplicate IDs.
invalid = df[df['amount'] <= 0]
dupes = df[df['transaction_id'].duplicated()]
print('Invalid amount rows:', len(invalid))
print('Duplicate transaction IDs:', len(dupes))
# Remove invalid transactions for clean EOD processing
df_clean = df[(df['amount'] > 0) & (~df['transaction_id'].duplicated())]
print(df_clean.shape)
Best Practices and Patterns for EOD Processing#
- Always clean input data for out-of-range or duplicate values.
- Include audit steps (logging, export files) in your logic.
- Use clear groupby and merge steps to avoid mixing up customer or account data.
- Separate code for transaction processing and reporting.
End-to-End Mini Problem: Balance Proof Across Days#
- Suppose auditors ask to prove that the closing balance for day N matches the opening for day N+1 for one account.
- Let us fetch one account's day-by-day balances and check for mismatches.
acct_id = acct_summary.iloc[0]['account_id']
account_balances = eod_balances[eod_balances['account_id'] == acct_id].sort_values('date').reset_index(drop=True)
account_balances['prev_balance'] = account_balances['balance'].shift(1)
account_balances['diff'] = account_balances['balance'] - account_balances['prev_balance'].fillna(0)
print(account_balances[['date', 'balance', 'prev_balance', 'diff']].head(5))
Congratulations! You have built an End-of-Day Processing Engine#
You tracked daily transactions, calculated balances, checked errors, and generated EOD closure files.
Practice: Can you add more EOD checks, such as overdraft detection?
For more banking Python tutorials, search YouTube for "Finance Python EOD" and subscribe to learn more.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



