Follow the Money: Analyzing Capital Flows from Central Banks to Key Sectors

Author

Financial Data Analysis Report

Published

May 22, 2025

Abstract

This notebook provides a comprehensive technical framework for tracing capital distribution from central banks into the real estate, technology, and healthcare sectors. By utilizing Python to interface with the Federal Reserve Economic Data (FRED) and World Bank APIs, the analysis retrieves critical economic indicators for the period spanning 2019 to 2025. The study quantifies total investment volumes and calculates specific ratios for sub-sectors, including residential versus commercial real estate, information processing equipment versus software, and pharmaceutical research versus medical services. The final output utilizes the Plotly library to construct interactive Sankey diagrams that visualize the transition of liquidity through the financial system, highlighting how money moves from central sources to diverse economic pillars.

import pandas as pd
import requests
from datetime import datetime
FRED_API_KEY = '2548a719cdd51baaa5e013839926fccc'
start_date = '2019-01-01'
end_date = '2025-01-01'
def fetch_fred_series(series_id, start_date, end_date):
    series_id = series_id  
    url = f"https://api.stlouisfed.org/fred/series/observations?series_id={series_id}&api_key={FRED_API_KEY}&file_type=json&observation_start={start_date}&observation_end={end_date}"
    response = requests.get(url)
    data = response.json()
    df = pd.DataFrame(data['observations'])
    df['value'] = df['value'].astype(float)
    return df

def fetch_world_bank_indicators(series_id, start_year, end_year):
    url = f"http://api.worldbank.org/v2/country/USA/indicator/{series_id}?format=json&date={start_year}:{end_year}"
    response = requests.get(url)
    data = response.json()
    df = pd.DataFrame(data[1])
    df['value'] = df['value'].astype(float)
    return df

# Function to fetch money supply data from FRED
def fetch_money_supply(start_date, end_date):
    return fetch_fred_series('M2SL', start_date, end_date)

def fetch_real_estate_investment(start_date, end_date):
    res_date = fetch_fred_series('A012RC1Q027SBEA', start_date, end_date)
    nonres_data = fetch_fred_series('B009RC1Q027SBEA', start_date, end_date)
    return res_date['value'].sum() + nonres_data['value'].sum()

def fetch_tech_investment(start_date, end_date):
    # Real Gross Private Domestic Investment: Fixed Investment: Nonresidential: Intellectual Property Products (Y001RX1Q020SBEA)
    direct_investment_ip_data = fetch_fred_series('Y001RX1Q020SBEA', start_date, end_date)

    # Private fixed investment in information processing equipment and software
    direct_investment_tech_data = fetch_fred_series('A679RC1Q027SBEA', start_date, end_date)

    # # Households and Nonprofit Organizations; Corporate Equities; Asset, Level/1000 (HNOCEAQ027S)
    # indirect_retail_investment = fetch_fred_series('HNOCEAQ027S', start_date, end_date)

    return direct_investment_ip_data['value'].sum() + direct_investment_tech_data['value'].sum()

def fetch_healthcare_investment(start_date, end_date):
    start_year = datetime.strptime(start_date, '%Y-%m-%d').year
    end_year = datetime.strptime(end_date, '%Y-%m-%d').year
    return fetch_world_bank_indicators('SH.XPD.CHEX.GD.ZS', start_year, end_year)

0.1 Step 2: Fetching Sector Investment Data from FRED and World Bank

For fetching sector-specific investment data, we will use series IDs from FRED and the World Bank API. Here are some examples:

money_supply_data = fetch_money_supply(start_date, end_date)
total_money_supply = money_supply_data['value'].sum()
print(f"Total Money Supply: {total_money_supply}")
Total Money Supply: 1419632.0
real_estate_data = fetch_real_estate_investment(start_date, end_date)
print(f"Total Real Estate Investment: {real_estate_data}")
Total Real Estate Investment: 45236.283
total_tech_investment = fetch_tech_investment(start_date, end_date)
print(f"Total Tech Investment: {total_tech_investment}")
Total Tech Investment: 58251.611000000004
# healthcare_data = fetch_healthcare_investment(start_date, end_date)
# total_healthcare_investment = healthcare_data['value'].sum()
# print(f"Total Healthcare Investment: {total_healthcare_investment}")

pharmaceuticals_data = fetch_fred_series('Y009RC1A027NBEA', start_date, end_date)  # Example series for pharmaceuticals

# Private fixed investment in equipment and software: Nonresidential: Information processing equipment and software: Medical equipment and instruments (W176RC1A027NBEA)
medical_devices_data = fetch_fred_series('W176RC1A027NBEA', start_date, end_date)  # Example series for medical devices

# Private fixed investment: Nonresidential: Structures: Commercial and health care (W001RC1Q027SBEA)
services_data = fetch_fred_series('W001RC1Q027SBEA', start_date, end_date)  # Example series for healthcare services

# Calculate total investments for pharmaceuticals, medical devices, and services
total_pharmaceuticals_investment = pharmaceuticals_data['value'].sum()
total_medical_devices_investment = medical_devices_data['value'].sum()
total_services_investment = services_data['value'].sum()
total_healthcare_investment = total_pharmaceuticals_investment + total_medical_devices_investment + total_services_investment
print(f"Total Healthcare Investment: {total_healthcare_investment}")
Total Healthcare Investment: 7629.786999999999

0.2 Step 3: Sector Breakdowns

0.2.1 Real Estate


# Total Private Construction Spending: Residential in the United States (PRRESCONS)
# Private fixed investment: Residential: Structures (A012RC1Q027SBEA)
residential_data = fetch_fred_series('A012RC1Q027SBEA', start_date, end_date)

# Total Private Construction Spending: Nonresidential in the United States (PNRESCONS)
# Private fixed investment: Nonresidential: Structures (B009RC1Q027SBEA)
commercial_data = fetch_fred_series('B009RC1Q027SBEA', start_date, end_date)

# Calculate total investments for residential and commercial real estate
total_residential_investment = residential_data['value'].sum()
total_commercial_investment = commercial_data['value'].sum()
total_real_estate_investment = total_residential_investment + total_commercial_investment

# Calculate the ratios
residential_ratio = total_residential_investment / total_real_estate_investment
commercial_ratio = total_commercial_investment / total_real_estate_investment

print(f"Residential Ratio: {residential_ratio}")
print(f"Commercial Ratio: {commercial_ratio}")
Residential Ratio: 0.5777855576683876
Commercial Ratio: 0.4222144423316124

0.2.2 Tech Investments

# Fetching data for Direct Investment in Technology and Tech Stocks

# Real Gross Private Domestic Investment: Fixed Investment: Nonresidential: Intellectual Property Products (Y001RX1Q020SBEA)
direct_investment_ip_data = fetch_fred_series('Y001RX1Q020SBEA', start_date, end_date)

# Real Gross Private Domestic Investment: Fixed Investment: Nonresidential: Equipment (Y033RX1Q020SBEA)
direct_investment_eqp_data = fetch_fred_series('Y033RX1Q020SBEA', start_date, end_date)

# Private fixed investment in information processing equipment and software
direct_investment_tech_data = fetch_fred_series('A679RC1Q027SBEA', start_date, end_date)

# Calculate total investments for direct investment and tech stocks
total_direct_investment = direct_investment_ip_data['value'].sum() + direct_investment_tech_data['value'].sum()

# Calculate the ratios
tech_and_ip_ratio = direct_investment_tech_data['value'].sum() / total_direct_investment
ip_ratio = 1 - tech_and_ip_ratio


print(f"Tech & IP Ratio: {tech_and_ip_ratio}")
print(f"IP Ratio: {ip_ratio}")
Tech & IP Ratio: 0.44079311385911707
IP Ratio: 0.559206886140883
# Quarterly Financial Report: U.S. Corporations: Pharmaceuticals and Medicines: Net Sales, Receipts, and Operating Revenues (QFR101385USNO)

# Fetching data for Pharmaceuticals, Medical Devices, and Healthcare Services

# Private Fixed Investment in Intellectual Property Products: Research and development: Business: Manufacturing: Pharmaceutical and medicine manufacturing (Y009RC1A027NBEA)
pharmaceuticals_data = fetch_fred_series('Y009RC1A027NBEA', start_date, end_date)  # Example series for pharmaceuticals

# Private fixed investment in equipment and software: Nonresidential: Information processing equipment and software: Medical equipment and instruments (W176RC1A027NBEA)
medical_devices_data = fetch_fred_series('W176RC1A027NBEA', start_date, end_date)  # Example series for medical devices

# Private fixed investment: Nonresidential: Structures: Commercial and health care (W001RC1Q027SBEA)
services_data = fetch_fred_series('W001RC1Q027SBEA', start_date, end_date)  # Example series for healthcare services

# Calculate total investments for pharmaceuticals, medical devices, and services
total_pharmaceuticals_investment = pharmaceuticals_data['value'].sum()
total_medical_devices_investment = medical_devices_data['value'].sum()
total_services_investment = services_data['value'].sum()
total_healthcare_investment = total_pharmaceuticals_investment + total_medical_devices_investment + total_services_investment

# Calculate the ratios
pharmaceuticals_ratio = total_pharmaceuticals_investment / total_healthcare_investment
medical_devices_ratio = total_medical_devices_investment / total_healthcare_investment
services_ratio = total_services_investment / total_healthcare_investment

print(f"Pharmaceuticals Ratio: {pharmaceuticals_ratio}")
print(f"Medical Devices Ratio: {medical_devices_ratio}")
print(f"Services Ratio: {services_ratio}")
Pharmaceuticals Ratio: 0.101622758276214
Medical Devices Ratio: 0.09037329613526564
Services Ratio: 0.8080039455885203

0.3 Step 4: Aggregate Data with Calculated Ratios

sector_data = {
    'Real Estate': total_real_estate_investment,
    'Residential': total_real_estate_investment * residential_ratio,
    'Commercial': total_real_estate_investment * commercial_ratio,
    'Tech': total_tech_investment,
    'Tech & Software': total_tech_investment * tech_and_ip_ratio,
    'IP': total_tech_investment * ip_ratio,
    'Healthcare': total_healthcare_investment,
    'Pharmaceuticals': total_healthcare_investment * pharmaceuticals_ratio,
    'Medical Devices': total_healthcare_investment * medical_devices_ratio,
    'Services': total_healthcare_investment * services_ratio
}
sector_data
{'Real Estate': 45236.283,
 'Residential': 26136.871000000003,
 'Commercial': 19099.412,
 'Tech': 58251.611000000004,
 'Tech & Software': 25676.909,
 'IP': 32574.70200000001,
 'Healthcare': 7629.786999999999,
 'Pharmaceuticals': 775.3599999999999,
 'Medical Devices': 689.529,
 'Services': 6164.897999999999}

0.4 Step 5: Create the Sankey Diagram

import plotly.graph_objects as go
import plotly.io as pio
pio.renderers.default = "notebook_connected"
#pio.renderers.default = "notebook_connected" # Or "iframe_connected"

# Define nodes
nodes = [
    'Central Banks',
    'Real Estate',
    'Residential',
    'Commercial',
    'Tech',
    'Tech & Software',
    'IP',
    'Healthcare',
    'Pharmaceuticals',
    'Medical Devices',
    'Services'
]
# Define links based on fetched data and calculated ratios
links = [
    {'source': 'Central Banks', 'target': 'Real Estate', 'value': sector_data['Real Estate']},
    {'source': 'Central Banks', 'target': 'Tech', 'value': sector_data['Tech']},
    {'source': 'Central Banks', 'target': 'Healthcare', 'value': sector_data['Healthcare']},
    {'source': 'Real Estate', 'target': 'Residential', 'value': sector_data['Residential']},
    {'source': 'Real Estate', 'target': 'Commercial', 'value': sector_data['Commercial']},
    {'source': 'Tech', 'target': 'Tech & Software', 'value': sector_data['Tech & Software']},
    {'source': 'Tech', 'target': 'IP', 'value': sector_data['IP']},
    {'source': 'Healthcare', 'target': 'Pharmaceuticals', 'value': sector_data['Pharmaceuticals']},
    {'source': 'Healthcare', 'target': 'Medical Devices', 'value': sector_data['Medical Devices']},
    {'source': 'Healthcare', 'target': 'Services', 'value': sector_data['Services']}
]

# Convert node names to indices for plotly
node_indices = {node: i for i, node in enumerate(nodes)}

sankey_links = {
    'source': [node_indices[link['source']] for link in links],
    'target': [node_indices[link['target']] for link in links],
    'value': [link['value'] for link in links]
}

# Create Sankey diagram
fig = go.Figure(go.Sankey(
    node=dict(
        pad=15,
        thickness=20,
        line=dict(color="black", width=0.5),
        label=nodes
    ),
    link=dict(
        source=sankey_links['source'],
        target=sankey_links['target'],
        value=sankey_links['value']
    )
))

fig.update_layout(title_text="Follow the Money: Central Banks to Various Sectors (2019-2024)", font_size=10)
fig.show()
# Define links based on fetched data and calculated ratios
links = [
    #{'source': 'Central Banks', 'target': 'Real Estate', 'value': sector_data['Real Estate']},
    {'source': 'Central Banks', 'target': 'Tech', 'value': sector_data['Tech']},
    {'source': 'Central Banks', 'target': 'Healthcare', 'value': sector_data['Healthcare']},
    #{'source': 'Real Estate', 'target': 'Residential', 'value': sector_data['Residential']},
    #{'source': 'Real Estate', 'target': 'Commercial', 'value': sector_data['Commercial']},
    {'source': 'Tech', 'target': 'Tech & Software', 'value': sector_data['Tech & Software']},
    {'source': 'Tech', 'target': 'IP', 'value': sector_data['IP']},
    {'source': 'Healthcare', 'target': 'Pharmaceuticals', 'value': sector_data['Pharmaceuticals']},
    {'source': 'Healthcare', 'target': 'Medical Devices', 'value': sector_data['Medical Devices']},
    {'source': 'Healthcare', 'target': 'Services', 'value': sector_data['Services']}
]

# Convert node names to indices for plotly
node_indices = {node: i for i, node in enumerate(nodes)}

sankey_links = {
    'source': [node_indices[link['source']] for link in links],
    'target': [node_indices[link['target']] for link in links],
    'value': [link['value'] for link in links]
}

# Create Sankey diagram
fig = go.Figure(go.Sankey(
    node=dict(
        pad=15,
        thickness=20,
        line=dict(color="black", width=0.5),
        label=nodes
    ),
    link=dict(
        source=sankey_links['source'],
        target=sankey_links['target'],
        value=sankey_links['value']
    )
))

fig.update_layout(title_text="Follow the Money (w/o RE): Central Banks to Various Sectors (2019-2024)", font_size=10)
fig.show()