import numpy as np
import matplotlib.pyplot as plt
# Set seed for reproducibility
np.random.seed(42)
time = np.arange(1, 201)
# --- 1. Stationary Series (Constant Mean, Variance, and Autocovariance) ---
noise_stationary = np.random.normal(0, 1, len(time))
series_stationary = np.zeros(len(time))
# Create a stationary AR(1) process: y_t = 0.5 * y_{t-1} + e_t
for t in range(1, len(time)):
series_stationary[t] = 0.5 * series_stationary[t-1] + noise_stationary[t]
# --- 2. Non-Stationary: Changing Mean (Trend exists) ---
series_trend = 0.1 * time + np.random.normal(0, 1, len(time))
# --- 3. Non-Stationary: Changing Variance (Heteroscedasticity) ---
# Spread increases exponentially or linearly over time
variance_scale = 0.03 * time
series_variance = np.random.normal(0, 1, len(time)) * variance_scale
# --- 4. Non-Stationary: Changing Covariance (Structural Change) ---
# Low frequency dependency in first half, high frequency in second half
series_covariance = np.zeros(len(time))
for t in range(1, len(time)):
if t < 100:
series_covariance[t] = 0.9 * series_covariance[t-1] + np.random.normal(0, 0.5)
else:
series_covariance[t] = -0.8 * series_covariance[t-1] + np.random.normal(0, 0.5)
# --- Plotting the grid comparing Stationary vs. Non-Stationary ---
fig, axes = plt.subplots(2, 2, figsize=(16, 10))
# Subplot 1: Stationary
axes[0, 0].plot(time, series_stationary, color='forestgreen', alpha=0.85)
axes[0, 0].axhline(y=0, color='black', linestyle='--', alpha=0.7, label='Constant Mean (0)')
axes[0, 0].set_title('Stationary: Constant Mean & Constant Spread', fontsize=12, fontweight='bold')
axes[0, 0].set_ylabel('Value')
axes[0, 0].legend(loc='upper left')
axes[0, 0].grid(True, linestyle=':', alpha=0.6)
# Subplot 2: Non-Stationary - Changing Mean
axes[0, 1].plot(time, series_trend, color='darkorange', alpha=0.85)
axes[0, 1].plot(time, 0.1 * time, color='black', linestyle='--', label='Changing Mean (Trend)')
axes[0, 1].set_title('Non-Stationary: Changing Mean (Trend)', fontsize=12, fontweight='bold')
axes[0, 1].legend(loc='upper left')
axes[0, 1].grid(True, linestyle=':', alpha=0.6)
# Subplot 3: Non-Stationary - Changing Variance
axes[1, 0].plot(time, series_variance, color='crimson', alpha=0.85)
axes[1, 0].plot(time, 2 * variance_scale, color='black', linestyle=':', label='+2 Std Dev')
axes[1, 0].plot(time, -2 * variance_scale, color='black', linestyle=':', label='-2 Std Dev')
axes[1, 0].set_title('Non-Stationary: Changing Variance (Unstable Spread)', fontsize=12, fontweight='bold')
axes[1, 0].set_xlabel('Time')
axes[1, 0].set_ylabel('Value')
axes[1, 0].legend(loc='upper left')
axes[1, 0].grid(True, linestyle=':', alpha=0.6)
# Subplot 4: Non-Stationary - Changing Covariance
axes[1, 1].plot(time, series_covariance, color='purple', alpha=0.85)
axes[1, 1].axvline(x=100, color='red', linestyle='--', label='Structural Change Point')
axes[1, 1].set_title('Non-Stationary: Changing Autocovariance', fontsize=12, fontweight='bold')
axes[1, 1].set_xlabel('Time')
axes[1, 1].legend(loc='upper left')
axes[1, 1].grid(True, linestyle=':', alpha=0.6)
plt.suptitle('Stationary vs. Non-Stationary Behaviors', fontsize=16, fontweight='bold', y=0.98)
plt.tight_layout()
plt.show()