Waterfall Chart

Monthly Cash Flow Analysis

Dark-themed waterfall chart showing monthly cash flow movements including operating, investing, and financing activities.

Output
Monthly Cash Flow Analysis
Python
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch

# Monthly cash flow (in thousands)
categories = ['Opening\nBalance', 'Sales\nReceipts', 'Service\nIncome', 'Payroll', 
              'Rent', 'Suppliers', 'Utilities', 'Marketing', 'Closing\nBalance']
values = [0, 185, 42, -95, -25, -68, -12, -18, 0]

# Calculate running total
initial = 120
running_total = initial
bottoms = []
heights = []
colors = []

for i, (cat, val) in enumerate(zip(categories, values)):
    if cat == 'Opening\nBalance':
        bottoms.append(0)
        heights.append(initial)
        colors.append('#27D3F5')
    elif cat == 'Closing\nBalance':
        bottoms.append(0)
        heights.append(running_total)
        colors.append('#6CF527' if running_total > initial else '#F5276C')
    elif val > 0:
        bottoms.append(running_total)
        heights.append(val)
        colors.append('#27F5B0')
        running_total += val
    else:
        bottoms.append(running_total + val)
        heights.append(abs(val))
        colors.append('#F5276C')
        running_total += val

# Create figure
fig, ax = plt.subplots(figsize=(14, 8), facecolor='#ffffff')
ax.set_facecolor('#ffffff')

x = np.arange(len(categories))
bars = ax.bar(x, heights, bottom=bottoms, color=colors, width=0.65, edgecolor='#e5e7eb', linewidth=1)

# Add value labels
for i, (bar, val, bot, height) in enumerate(zip(bars, values, bottoms, heights)):
    y_pos = bot + height / 2
    if categories[i] in ['Opening\nBalance', 'Closing\nBalance']:
        label = f"${height}K"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, 
                ha='center', va='center', fontsize=10, fontweight='bold', color='#0a0a0f')
    else:
        label = f"+${val}K" if val > 0 else f"-${abs(val)}K"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, 
                ha='center', va='center', fontsize=9, fontweight='bold', color='#374151')

# Connect bars
for i in range(len(x) - 1):
    if i == 0:
        y = initial
    else:
        y = bottoms[i] + heights[i]
    ax.plot([x[i] + 0.35, x[i+1] - 0.35], [y, y], 
            color='#9ca3af', linestyle='--', linewidth=1.5, alpha=0.7)

# Styling
ax.set_xlim(-0.6, len(categories) - 0.4)
ax.set_ylim(0, max(bottoms[i] + heights[i] for i in range(len(heights))) * 1.1)
ax.set_xticks(x)
ax.set_xticklabels(categories, fontsize=9, color='#374151')
ax.set_ylabel('Cash ($ Thousands)', fontsize=12, color='#374151', fontweight='500')
ax.set_title('Monthly Cash Flow Waterfall', fontsize=16, color='#374151', fontweight='bold', pad=20)

ax.tick_params(axis='y', colors='#e2e8f0', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.3, color='#e5e7eb')
ax.set_axisbelow(True)

for spine in ax.spines.values():
    spine.set_color('#334155')

# Legend outside plot
legend_elements = [
    Patch(facecolor='#27D3F5', label='Opening Balance'),
    Patch(facecolor='#27F5B0', label='Cash Inflows'),
    Patch(facecolor='#F5276C', label='Cash Outflows'),
    Patch(facecolor='#6CF527', label='Closing Balance')
]
ax.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0, -0.12), 
          ncol=4, fontsize=9, facecolor='white', edgecolor='#e5e7eb', labelcolor='#374151')

plt.tight_layout()
plt.subplots_adjust(bottom=0.18)
plt.show()
Library

Matplotlib

Category

Financial

Did this help you?

Support PyLucid to keep it free & growing

Support