Waterfall Chart
Free Cash Flow Bridge Analysis
FCF waterfall bridging from net income through operating and investing activities.
Output
Python
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch
# FCF bridge (in millions)
categories = ['Net\nIncome', 'D&A', 'Stock-Based\nComp', 'Working\nCapital',
'Deferred\nTaxes', 'CapEx', 'Acquisitions', 'Free\nCash Flow']
values = [0, 85, 42, -38, 15, -120, -45, 0]
# Calculate running total
initial = 280
running_total = initial
bottoms = []
heights = []
colors = []
for i, (cat, val) in enumerate(zip(categories, values)):
if cat == 'Net\nIncome':
bottoms.append(0)
heights.append(initial)
colors.append('#276CF5')
elif cat == 'Free\nCash Flow':
bottoms.append(0)
heights.append(running_total)
colors.append('#6CF527' if running_total > 0 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 ['Net\nIncome', 'Free\nCash Flow']:
label = f"${height}M"
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label,
ha='center', va='center', fontsize=11, fontweight='bold', color='#374151')
else:
label = f"+${val}M" if val > 0 else f"-${abs(val)}M"
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label,
ha='center', va='center', fontsize=10, 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=10, color='#374151')
ax.set_ylabel('Value ($ Millions)', fontsize=12, color='#374151', fontweight='500')
ax.set_title('Free Cash Flow Bridge: Net Income to FCF', 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='#276CF5', label='Net Income'),
Patch(facecolor='#27F5B0', label='Non-Cash Add-backs'),
Patch(facecolor='#F5276C', label='Cash Uses'),
Patch(facecolor='#6CF527', label='Free Cash Flow')
]
ax.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0, -0.1),
ncol=4, fontsize=9, facecolor='white', edgecolor='#e5e7eb', labelcolor='#374151')
plt.tight_layout()
plt.subplots_adjust(bottom=0.15)
plt.show()
Library
Matplotlib
Category
Financial
More Waterfall Chart examples
☕