Waterfall Chart
Insurance Premium Breakdown
Insurance premium waterfall showing base rate adjustments and final premium calculation.
Output
Python
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch
categories = ['Base\nPremium', 'Age\nFactor', 'Driving\nHistory', 'Vehicle\nType',
'Coverage\nLevel', 'Multi-Policy\nDiscount', 'Loyalty\nDiscount', 'Final\nPremium']
values = [0, 180, 95, 120, 85, -145, -65, 0]
initial = 850
running_total = initial
bottoms, heights, colors = [], [], []
for i, (cat, val) in enumerate(zip(categories, values)):
if 'Base' in cat:
bottoms.append(0)
heights.append(initial)
colors.append('#4927F5')
elif 'Final' in cat:
bottoms.append(0)
heights.append(running_total)
colors.append('#6CF527')
elif val > 0:
bottoms.append(running_total)
heights.append(val)
colors.append('#F5276C')
running_total += val
else:
bottoms.append(running_total + val)
heights.append(abs(val))
colors.append('#27F5B0')
running_total += val
fig, ax = plt.subplots(figsize=(14, 8), facecolor='#0a0a0f')
ax.set_facecolor('#0a0a0f')
x = np.arange(len(categories))
bars = ax.bar(x, heights, bottom=bottoms, color=colors, width=0.65, edgecolor='#1e293b', linewidth=1)
for i, (bar, val, bot, height) in enumerate(zip(bars, values, bottoms, heights)):
y_pos = bot + height / 2
if 'Base' in categories[i] or 'Final' in categories[i]:
label = str(height)
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, ha='center', va='center',
fontsize=11, fontweight='bold', color='white')
else:
label = '+' + str(val) if val > 0 else str(val)
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, ha='center', va='center',
fontsize=10, fontweight='bold', color='white')
for i in range(len(x) - 1):
y = initial if i == 0 else bottoms[i] + heights[i]
ax.plot([x[i] + 0.35, x[i+1] - 0.35], [y, y], color='#475569', linestyle='--', linewidth=1.5, alpha=0.7)
ax.set_xlim(-0.6, len(categories) - 0.4)
ax.set_ylim(0, max(b + h for b, h in zip(bottoms, heights)) * 1.1)
ax.set_xticks(x)
ax.set_xticklabels(categories, fontsize=9, color='#e2e8f0')
ax.set_ylabel('Annual Premium', fontsize=12, color='#e2e8f0', fontweight='500')
ax.set_title('Auto Insurance Premium Calculation', fontsize=16, color='white', fontweight='bold', pad=20)
ax.tick_params(axis='y', colors='#e2e8f0', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.3, color='#334155')
ax.set_axisbelow(True)
for spine in ax.spines.values():
spine.set_color('#334155')
change = running_total - initial
pct = (change / initial) * 100
ax.annotate('Net Adjustment: ' + ('+' if change > 0 else '') + str(change) + ' (' + str(round(pct, 1)) + ' pct)',
xy=(0.98, 0.95), xycoords='axes fraction',
fontsize=11, color='#6CF527' if change < initial * 0.5 else '#F5B027', ha='right', fontweight='bold',
bbox=dict(boxstyle='round,pad=0.4', facecolor='#1e293b', edgecolor='#6CF527', alpha=0.9))
legend_elements = [Patch(facecolor='#4927F5', label='Base Premium'), Patch(facecolor='#F5276C', label='Surcharges'),
Patch(facecolor='#27F5B0', label='Discounts'), Patch(facecolor='#6CF527', label='Final Premium')]
ax.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0, -0.1), ncol=4, fontsize=9,
facecolor='#1e293b', edgecolor='#334155', labelcolor='white')
plt.tight_layout()
plt.subplots_adjust(bottom=0.15)
plt.show()
Library
Matplotlib
Category
Financial
More Waterfall Chart examples
☕