Ridgeline Plot

Crypto Trading Volume by Hour

Hourly trading activity with gradient neon fills and glow effect

Output
Crypto Trading Volume by Hour
Python
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
from matplotlib.colors import LinearSegmentedColormap

np.random.seed(42)

hours = ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00']
# Neon gradient colors for each ridge
gradient_colors = [
    ['#0a0a0f', '#4927F5', '#27D3F5'],
    ['#0a0a0f', '#F5276C', '#F5B027'],
    ['#0a0a0f', '#6CF527', '#27F5B0'],
    ['#0a0a0f', '#F54927', '#F5D327'],
    ['#0a0a0f', '#5314E6', '#F527B0'],
    ['#0a0a0f', '#276CF5', '#6CF527']
]

data = {
    '00:00': np.random.gamma(3, 15, 500),
    '04:00': np.random.gamma(2, 10, 500),
    '08:00': np.random.gamma(5, 12, 500),
    '12:00': np.random.gamma(6, 14, 500),
    '16:00': np.random.gamma(7, 13, 500),
    '20:00': np.random.gamma(5, 15, 500)
}

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

overlap = 1.8
x_range = np.linspace(0, 180, 300)

for i, (hour, volume) in enumerate(data.items()):
    kde = stats.gaussian_kde(volume, bw_method=0.25)
    y = kde(x_range) * 4
    baseline = i * overlap
    
    # Create gradient mesh for fill
    cmap = LinearSegmentedColormap.from_list('grad', gradient_colors[i], N=256)
    
    # Glow effect - plot thick line with alpha first
    ax.plot(x_range, y + baseline, color=gradient_colors[i][2], linewidth=8, alpha=0.3)
    ax.plot(x_range, y + baseline, color=gradient_colors[i][2], linewidth=4, alpha=0.5)
    ax.plot(x_range, y + baseline, color=gradient_colors[i][2], linewidth=2, alpha=1)
    
    # Gradient fill using imshow
    Y = np.linspace(baseline, y.max() + baseline, 100)
    X, Y_mesh = np.meshgrid(x_range, Y)
    Z = np.zeros_like(X)
    for j, xi in enumerate(x_range):
        Z[:, j] = np.linspace(0, 1, 100) * (y[j] / y.max() if y.max() > 0 else 0)
    
    ax.imshow(Z, extent=[x_range.min(), x_range.max(), baseline, y.max() + baseline],
              aspect='auto', cmap=cmap, alpha=0.7, origin='lower')
    ax.fill_between(x_range, baseline, y + baseline, alpha=0, edgecolor='none')
    
    ax.text(-5, baseline + 0.15, hour, fontsize=11, color='white',
            ha='right', va='bottom', fontweight='600')

ax.set_xlim(-25, 180)
ax.set_ylim(-0.3, len(hours) * overlap + 2)
ax.set_xlabel('Volume ($M)', fontsize=12, color='#888888', fontweight='500')
ax.set_title('Crypto Trading Volume by Hour', fontsize=16, color='white', fontweight='bold', pad=20)

ax.tick_params(axis='x', colors='#666666', labelsize=10)
ax.tick_params(axis='y', left=False, labelleft=False)
for spine in ax.spines.values():
    spine.set_visible(False)

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support