ANOVA Violin Plot

Portfolio Returns ANOVA Analysis

Comparing annual returns distribution across different investment strategies.

Output
Portfolio Returns ANOVA Analysis
Python
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

np.random.seed(456)

# Annual returns (%) for different strategies over 50 years simulation
conservative = np.random.normal(5.2, 3.5, 50)
balanced = np.random.normal(7.8, 6.2, 50)
aggressive = np.random.normal(10.5, 12.0, 50)
crypto_heavy = np.random.normal(15.0, 35.0, 50)

F_stat, p_value = stats.f_oneway(conservative, balanced, aggressive, crypto_heavy)

fig, ax = plt.subplots(figsize=(12, 7), facecolor='#0d1117')
ax.set_facecolor('#0d1117')

colors = ['#27F5B0', '#27D3F5', '#F5B027', '#F5276C']

parts = ax.violinplot([conservative, balanced, aggressive, crypto_heavy], 
                       positions=[1, 2, 3, 4], showmeans=True, showmedians=True, widths=0.8)

for i, pc in enumerate(parts['bodies']):
    pc.set_facecolor(colors[i])
    pc.set_alpha(0.6)
    pc.set_edgecolor(colors[i])
    pc.set_linewidth(2)

parts['cmeans'].set_color('#F5D327')
parts['cmeans'].set_linewidth(2)
parts['cmedians'].set_color('white')
for partname in ['cbars', 'cmins', 'cmaxes']:
    parts[partname].set_color('#444444')

# Risk-adjusted stats
sharpe_ratios = [1.49, 1.26, 0.88, 0.43]
labels = ['Conservative', 'Balanced', 'Aggressive', 'Crypto-Heavy']

# Annotate Sharpe ratios at bottom
for i, (sr, color) in enumerate(zip(sharpe_ratios, colors)):
    ax.text(i+1, -55, f'Sharpe: {sr:.2f}', ha='center', fontsize=9, color=color, fontweight='bold')

# Stats annotation - bottom right corner
stats_box = f"ANOVA: F={F_stat:.2f}, p={p_value:.4f}"
bbox = dict(boxstyle="round,pad=0.3", facecolor='#1a1a2e', edgecolor='#27D3F5', alpha=0.95)
ax.text(0.98, 0.02, stats_box, transform=ax.transAxes, fontsize=10, color='white',
        ha='right', va='bottom', fontfamily='monospace', bbox=bbox)

ax.axhline(y=0, color='#ef4444', linestyle='--', alpha=0.5, linewidth=1)
ax.text(0.5, 2, 'Break-even', fontsize=9, color='#ef4444', va='bottom')

ax.set_xticks([1, 2, 3, 4])
ax.set_xticklabels(labels, fontsize=11, color='white')
ax.set_ylabel('Annual Return (%)', fontsize=12, color='white', fontweight='500')
ax.set_title('Investment Strategy Performance Comparison\n50-Year Monte Carlo Simulation', 
             fontsize=14, color='white', fontweight='bold', pad=15)

ax.tick_params(colors='#888888')
for spine in ax.spines.values():
    spine.set_color('#333333')
ax.yaxis.grid(True, color='#1e293b', linewidth=0.5)
ax.set_axisbelow(True)
ax.set_ylim(-65, 90)

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support