Lesson 16 · Python for Banking and Finance
Analyzing Key Banking KPIs with Python: A Practical Guide for Finance Professionals
In this lesson, we focus on analyzing key banking KPIs using Python. KPIs (Key Performance Indicators) help banks measure important business health metrics.…
- CoursePython for Banking and Finance
- Lesson16 of 24
- Video26 min
- FormatJupyter notebook · 21 code cells
What you'll learn
- Understanding Banking Data Sources for KPIs
- Beginner Example 1: Number of Transactions KPI
- Beginner Example 2: Total Transaction Volume (Amount)
- Beginner Example 3: Transactions By Channel
- Intermediate Example 1: Unique Customers With Transactions
- Intermediate Example 2: Average Transaction Size
- Intermediate Example 3: Transactions Over Time
- Advanced Example 1: KPI - Customer Lifetime Value (CLV)
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbKey Banking KPIs in Python#
In this lesson, we focus on analyzing key banking KPIs using Python.
KPIs (Key Performance Indicators) help banks measure important business health metrics.
You will learn how to compute and interpret essential KPIs from various synthetic banking datasets.
By the end, you will be able to calculate, explain, and use banking KPIs with code and data.
No prior experience in finance is needed, but familiarity with basic Python and dataframes will help.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
Understanding Banking Data Sources for KPIs#
- Banking KPIs are often derived from real transaction, customer, and account data.
- Transaction tables track every financial move, including debits, credits, and channels used.
- Customers are grouped by segments and regions, which helps discover performance across groups.
- Account tables connect customers to specific account products and opening periods.
- Beginners often overlook the need to join or merge these datasets to get complete KPI insight.
np.random.seed(42)
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))
np.random.seed(42)
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: Number of Transactions KPI#
- One classic banking KPI is the total number of transactions in a period.
- This measures customer engagement and fee-generating activity.
- It is a basic foundation for more advanced metrics.
num_txns = df.shape[0]
print('Total number of transactions:', num_txns)
Beginner Example 2: Total Transaction Volume (Amount)#
- The sum of all money moved is a key bank volume metric.
- This helps banks understand financial throughput and liquidity.
total_volume = df['amount'].sum()
print('Total transaction volume:', total_volume)
Beginner Example 3: Transactions By Channel#
- Looking at KPIs by channel shows digital vs in-person trends.
- Channel analysis is important for understanding customer behavior.
txn_by_channel = df['channel'].value_counts()
print('Transactions by channel:')
print(txn_by_channel)
Intermediate Example 1: Unique Customers With Transactions#
- Not every customer is active active customer count is a vital KPI.
- This helps banks track engagement and churn.
active_customers = df['customer_id'].nunique()
print('Number of active customers:', active_customers)
customers_with_accounts = customers.merge(accounts, on='customer_id', how='left')
no_txn_customers = customers_with_accounts[~customers_with_accounts['customer_id'].isin(df['customer_id'])]
print('Customers with accounts but no transactions:', len(no_txn_customers))
Intermediate Example 2: Average Transaction Size#
- The average size of transactions provides a sense of account holder behavior.
- This is important for risk, fraud, and marketing analysis.
avg_amount = df['amount'].mean()
print('Average transaction amount:', round(avg_amount, 2))
avg_by_segment = df.merge(customers, on='customer_id').groupby('segment')['amount'].mean()
print('Average transaction by segment:')
print(avg_by_segment)
Intermediate Example 3: Transactions Over Time#
- Monitoring transaction patterns over days, weeks or months reveals trends.
- This is useful for planning, compliance, and identifying unusual behavior.
df['date_only'] = df['date'].dt.date
txns_per_day = df.groupby('date_only')['transaction_id'].count()
print(txns_per_day.head(7))
Advanced Example 1: KPI - Customer Lifetime Value (CLV)#
- CLV estimates the revenue a customer brings in their bank relationship.
- Knowing CLV helps banks prioritize retention and marketing.
clv = df.groupby('customer_id')['amount'].sum().sort_values(ascending=False)
print('Top 5 Customer Lifetime Values:')
print(clv.head(5))
Advanced Example 2: KPI - Product Holding Rate#
- Product holding rate shows average number of accounts per customer.
- It highlights cross-sell opportunities and customer relationship depth.
accounts_per_customer = accounts.groupby('customer_id')['account_id'].count()
avg_accounts_per_customer = accounts_per_customer.mean()
print('Average number of accounts per customer:', round(avg_accounts_per_customer, 2))
high_product_customers = accounts_per_customer[accounts_per_customer > 2]
print('Customers with more than 2 accounts:', len(high_product_customers))
Advanced Example 3: KPI - Active Product Penetration#
- Active product penetration looks at product usage instead of only holding.
- It shows how many products are actively used (with transactions) per customer.
active_accounts = df.merge(accounts, on='customer_id')[['customer_id','account_id']].drop_duplicates()
active_prods_per_customer = active_accounts.groupby('customer_id')['account_id'].count()
print('Average actively used products per customer:', round(active_prods_per_customer.mean(),2))
Error Handling: Dealing With Missing Data#
- In real bank datasets, missing values can break KPI calculations.
- Let us simulate and handle missing data in transaction amounts.
df_missing = df.copy()
df_missing.loc[np.random.choice(df.index, 20, replace=False), 'amount'] = np.nan
print(df_missing['amount'].isnull().sum(), 'missing values introduced.')
print('Mean with missing:', df_missing['amount'].mean())
print('Mean after fill:', df_missing['amount'].fillna(0).mean())
Debugging Example: Tracking Outlier KPIs#
- Unrealistic amounts or sudden spikes in KPI measures may indicate data issues or fraud.
- Let us learn to debug by tracking unusually large transaction amounts.
outliers = df[df['amount'] > df['amount'].mean() + 3*df['amount'].std()]
print('Unusual transactions found:', outliers.shape[0])
print(outliers[['transaction_id','amount']].head())
Best Practice: Modular KPI Calculation Functions#
- Turning KPI calculations into functions keeps your code clean and reusable.
- This is important for team projects and updating metric definitions in the future.
def kpi_total_transactions(df, txn_type=None):
if txn_type:
return df[df['transaction_type']==txn_type].shape[0]
return df.shape[0]
print('KPIs:')
print('Total:', kpi_total_transactions(df))
print('Debit:', kpi_total_transactions(df, 'Debit'))
Common Pattern: KPI Aggregation By Group#
- Most advanced KPIs use groupby for segmentation (e.g. by region, by product).
- This lets banks benchmark regions, branches, or segments against each other.
seg_kpi = df.merge(customers, on='customer_id').groupby(['region','segment'])['amount'].sum()
print('Transaction Volume by Region & Segment:')
print(seg_kpi)
End-to-End KPI Example: New Product Launch Performance#
- Suppose the bank just launched a new product, and wants to track its uptake and use.
- Let us add a 'new savings' account, assign to 25 customers, and track its KPIs end-to-end.
np.random.seed(42)
launch_customers = np.random.choice(customer_ids, 25, replace=False)
new_accounts = pd.DataFrame({
'account_id': [f'ACC_990{i:02d}' for i in range(25)],
'customer_id': launch_customers,
'account_type': ['New_Savings']*25,
'open_date': pd.to_datetime('2024-02-01')
})
accounts_full = pd.concat([accounts, new_accounts], ignore_index=True)
new_txns = pd.DataFrame({
'transaction_id': np.arange(2001,2026),
'customer_id': launch_customers,
'amount': np.random.normal(200, 30, 25),
'transaction_type': ['Credit']*25,
'channel': ['Online']*25,
'date': pd.date_range(start='2024-02-01', periods=25, freq='2D')
})
df_full = pd.concat([df, new_txns], ignore_index=True)
uptake = accounts_full[accounts_full['account_type']=='New_Savings'].shape[0]
active = new_txns.shape[0]
avg_txn_new = new_txns['amount'].mean()
print('New product uptake:', uptake)
print('Number of new product transactions:', active)
print('Average transaction (new product):', round(avg_txn_new,2))
For More Practice and Deep Dives#
- Try segmenting KPIs by custom attributes or merging with other bank datasets.
- Review all code cells and write your own comments this is the best way to learn.
- Subscribe to our YouTube for more banking data science and analytics tutorials!
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



