Monzo is shutting down its US operation, and its European banking licence explains why
Back to Tutorials
techTutorialintermediate

Monzo is shutting down its US operation, and its European banking licence explains why

April 5, 20265 views6 min read

Learn to build a financial data analysis tool that works with banking APIs, similar to what Monzo and other fintech companies use for their operations.

Introduction

In the wake of Monzo's strategic pivot toward its European expansion and IPO preparation, this tutorial explores how to work with financial data APIs and banking regulations using Python. As Monzo transitions its focus from US operations to European compliance, we'll examine how to access and analyze banking data through regulated APIs, a crucial skill for fintech developers working with cross-border financial services.

This tutorial will teach you how to build a financial data analysis tool that can work with banking APIs, focusing on compliance and data handling practices that are essential for any fintech project operating in regulated environments.

Prerequisites

  • Python 3.8 or higher installed on your system
  • Familiarity with Python programming concepts including classes, modules, and API interactions
  • Basic understanding of financial data concepts and banking APIs
  • Development environment with pip package manager
  • Access to a sandbox banking API (we'll use a mock implementation for demonstration)

Step-by-Step Instructions

1. Set Up Your Development Environment

First, we need to create a clean Python environment for our project. This ensures we have all required dependencies isolated from your system.

python -m venv financial_analysis_env
source financial_analysis_env/bin/activate  # On Windows: financial_analysis_env\Scripts\activate
pip install requests pandas python-dotenv

Why: Creating a virtual environment isolates our project dependencies, preventing conflicts with other Python projects on your system. The packages we install are essential for making HTTP requests, handling data, and managing environment variables.

2. Create Configuration Files

Next, we'll set up configuration files to manage API keys and environment settings securely.

# Create .env file
API_KEY=your_api_key_here
BASE_URL=https://api.sandbox-bank.com/v1

Then create a configuration module:

# config.py
import os
from dotenv import load_dotenv

load_dotenv()

API_KEY = os.getenv('API_KEY')
BASE_URL = os.getenv('BASE_URL')

Why: Storing credentials in environment variables keeps sensitive information out of your codebase, which is crucial for compliance with banking regulations and data protection laws.

3. Build a Banking Data Client

Now we'll create a client class that handles interactions with the banking API, focusing on compliance aspects:

# banking_client.py
import requests
import json
from config import API_KEY, BASE_URL

class BankingClient:
    def __init__(self):
        self.base_url = BASE_URL
        self.headers = {
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json',
            'X-Client-ID': 'monzo_analysis_tool'
        }
    
    def get_account_data(self, account_id):
        """Fetch account information with proper error handling"""
        try:
            response = requests.get(
                f'{self.base_url}/accounts/{account_id}',
                headers=self.headers
            )
            response.raise_for_status()  # Raises an HTTPError for bad responses
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"API request failed: {e}")
            return None
    
    def get_transaction_history(self, account_id, limit=100):
        """Get transaction history with pagination support"""
        try:
            params = {'limit': limit}
            response = requests.get(
                f'{self.base_url}/accounts/{account_id}/transactions',
                headers=self.headers,
                params=params
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"Transaction fetch failed: {e}")
            return None

Why: This client class demonstrates proper error handling and compliance practices, including setting appropriate headers and handling different types of API responses that banking systems might return.

4. Implement Data Analysis Module

Let's create a module to analyze the banking data we retrieve:

# analysis.py
import pandas as pd
from datetime import datetime

class FinancialAnalyzer:
    def __init__(self):
        self.data = None
    
    def load_transactions(self, transactions_data):
        """Load transaction data into a pandas DataFrame"""
        if not transactions_data or 'transactions' not in transactions_data:
            return False
        
        df = pd.DataFrame(transactions_data['transactions'])
        df['created'] = pd.to_datetime(df['created'])
        df['amount'] = df['amount'].astype(float)
        self.data = df
        return True
    
    def calculate_spending_trends(self):
        """Calculate spending trends by category and time"""
        if self.data is None:
            return None
        
        # Group by month and category
        self.data['month'] = self.data['created'].dt.to_period('M')
        trends = self.data.groupby(['month', 'category']).agg({
            'amount': ['sum', 'count']
        }).round(2)
        
        return trends
    
    def get_compliance_report(self):
        """Generate a basic compliance report"""
        if self.data is None:
            return None
        
        report = {
            'total_transactions': len(self.data),
            'total_spent': self.data['amount'].sum(),
            'average_transaction': self.data['amount'].mean(),
            'largest_transaction': self.data['amount'].max(),
            'data_period': {
                'start': self.data['created'].min(),
                'end': self.data['created'].max()
            }
        }
        
        return report

Why: This module shows how to process financial data while maintaining compliance standards, including proper data type handling and generating reports that could be used for regulatory purposes.

5. Create Main Application

Now we'll put everything together in our main application:

# main.py
from banking_client import BankingClient
from analysis import FinancialAnalyzer
import json


def main():
    # Initialize components
    client = BankingClient()
    analyzer = FinancialAnalyzer()
    
    # Simulate fetching account data
    account_id = 'acc_123456'
    account_data = client.get_account_data(account_id)
    
    if not account_data:
        print("Failed to fetch account data")
        return
    
    # Fetch transaction history
    transactions = client.get_transaction_history(account_id, limit=50)
    
    if not transactions:
        print("Failed to fetch transactions")
        return
    
    # Process data
    if analyzer.load_transactions(transations):
        trends = analyzer.calculate_spending_trends()
        report = analyzer.get_compliance_report()
        
        print("Compliance Report:")
        print(json.dumps(report, indent=2, default=str))
        
        print("\nSpending Trends:")
        print(trends)
    
    print(f"\nData analysis complete for account {account_id}")

if __name__ == '__main__':
    main()

Why: This main application demonstrates how to integrate all components while maintaining proper error handling and data flow, which is crucial when working with regulated financial data.

6. Add Security and Compliance Features

Finally, let's add security measures that are essential for banking applications:

# security.py
import hashlib
import hmac
import time
from config import API_KEY

class SecurityManager:
    @staticmethod
    def generate_signature(method, url, timestamp, body=None):
        """Generate API signature for secure requests"""
        # In a real implementation, this would include proper signing
        # This is a simplified example
        message = f"{method}{url}{timestamp}"
        if body:
            message += str(body)
        
        signature = hmac.new(
            API_KEY.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()
        
        return signature
    
    @staticmethod
    def validate_data_integrity(data):
        """Validate that data hasn't been tampered with"""
        # Implement data integrity checks
        # This would include hash validation in production
        return True

# Enhanced banking client with security

class SecureBankingClient(BankingClient):
    def __init__(self):
        super().__init__()
        self.security = SecurityManager()
        
    def secure_request(self, method, endpoint, data=None):
        """Make a secure API request"""
        timestamp = str(int(time.time()))
        signature = self.security.generate_signature(method, endpoint, timestamp, data)
        
        self.headers['X-Timestamp'] = timestamp
        self.headers['X-Signature'] = signature
        
        # Make the actual request
        url = f'{self.base_url}{endpoint}'
        response = getattr(requests, method.lower())(
            url,
            headers=self.headers,
            json=data
        )
        
        return response

Why: Banking applications require robust security measures to protect sensitive financial data. This implementation shows how to add authentication and data integrity checks that are essential for compliance with financial regulations.

Summary

This tutorial demonstrated how to build a financial data analysis tool that works with banking APIs, similar to what Monzo and other fintech companies might use for their operations. We covered essential components including API client design, data analysis with pandas, compliance reporting, and security measures.

The key learning points include proper error handling, secure credential management, data integrity checks, and compliance-focused design patterns. These practices are crucial for any fintech developer working with regulated financial data, especially when transitioning between different markets like Monzo's move from US to European operations.

Remember that real banking APIs require proper licensing and compliance certifications, but this tutorial provides the foundational knowledge for working with financial data in regulated environments.

Source: TNW Neural

Related Articles