|

Pandas 股票数据分析详解

1. 股票数据分析概述

Pandas 是进行股票数据分析的核心工具,它可以高效处理时间序列数据、计算技术指标、进行统计分析和可视化。典型流程包括:

  • 数据获取:从 CSV、API 或数据库加载股票数据。
  • 数据清洗:处理缺失值、异常值和格式转换。
  • 特征工程:计算移动平均、回报率、技术指标(如 RSI、MACD)。
  • 统计分析:相关性、波动率、风险指标。
  • 可视化:K 线图、趋势图、热力图。
  • 高级应用:回测策略、风险评估、多股比较。

本文使用模拟数据演示核心功能。实际应用中,可结合 yfinancepandas_datareader 获取真实数据(需安装相关库)。

2. 数据获取与准备

2.1 模拟股票数据

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保可重复
np.random.seed(42)

# 生成模拟股票数据(AAPL 示例)
dates = pd.date_range('2023-01-01', periods=365, freq='D')  # 一年数据
data = {
    'Date': dates,
    'Open': np.random.uniform(150, 160, len(dates)),
    'High': np.random.uniform(160, 170, len(dates)),
    'Low': np.random.uniform(140, 150, len(dates)),
    'Close': np.random.uniform(150, 160, len(dates)),
    'Volume': np.random.randint(1000000, 5000000, len(dates))
}

df = pd.DataFrame(data)
df.set_index('Date', inplace=True)

# 添加真实趋势模拟(假设向上趋势)
df['Close'] = df['Close'].cumsum() * 0.1 + 150 + np.random.randn(len(df)) * 5
df['Open'] = df['Close'] * np.random.uniform(0.98, 1.02, len(df))
df['High'] = df[['Open', 'Close']].max(axis=1) * np.random.uniform(1.01, 1.05, len(df))
df['Low'] = df[['Open', 'Close']].min(axis=1) * np.random.uniform(0.95, 0.99, len(df))

print("模拟股票数据预览:")
print(df.head())

2.2 真实数据获取示例

# 注意:需安装 yfinance(pip install yfinance)
# import yfinance as yf

# # 下载真实数据
# real_df = yf.download('AAPL', start='2023-01-01', end='2023-12-31')
# print("真实AAPL数据预览:")
# print(real_df.head())

3. 数据清洗

3.1 缺失值处理

# 检查缺失值
missing = df.isnull().sum()
print("缺失值统计:")
print(missing[missing > 0])

# 填充缺失值(例如,使用前向填充)
df = df.fillna(method='ffill')
df = df.fillna(method='bfill')  # 后向填充剩余

# 删除异常值(例如,薪资负值或体积异常)
df = df[(df['Close'] > 0) & (df['Volume'] > 0)]

print("清洗后数据形状:", df.shape)

3.2 异常值检测

# IQR 方法检测异常值
def detect_outliers(series):
    Q1 = series.quantile(0.25)
    Q3 = series.quantile(0.75)
    IQR = Q3 - Q1
    return (series < Q1 - 1.5 * IQR) | (series > Q3 + 1.5 * IQR)

outliers = detect_outliers(df['Close'])
print("Close价格异常值数量:", outliers.sum())

# 替换异常值为中位数
median_close = df['Close'].median()
df.loc[outliers, 'Close'] = median_close

4. 特征工程与技术指标

4.1 计算回报率

# 日回报率
df['daily_return'] = df['Close'].pct_change().fillna(0)

# 累计回报率
df['cum_return'] = (1 + df['daily_return']).cumprod() - 1

print("回报率预览:")
print(df[['Close', 'daily_return', 'cum_return']].head())

4.2 移动平均线(MA)

# 简单移动平均(SMA)
df['MA5'] = df['Close'].rolling(window=5).mean()
df['MA20'] = df['Close'].rolling(window=20).mean()
df['MA50'] = df['Close'].rolling(window=50).mean()

# 指数移动平均(EMA)
df['EMA5'] = df['Close'].ewm(span=5, adjust=False).mean()
df['EMA20'] = df['Close'].ewm(span=20, adjust=False).mean()

print("移动平均预览:")
print(df[['Close', 'MA5', 'EMA5']].head(10))

4.3 RSI(相对强弱指数)

def calculate_rsi(series, period=14):
    """计算RSI"""
    delta = series.diff()
    gain = delta.where(delta > 0, 0).rolling(window=period).mean()
    loss = -delta.where(delta < 0, 0).rolling(window=period).mean()
    rs = gain / loss
    return 100 - (100 / (1 + rs))

df['RSI'] = calculate_rsi(df['Close'])

print("RSI预览:")
print(df[['Close', 'RSI']].tail())

4.4 MACD(移动平均收敛散度)

def calculate_macd(series, short=12, long=26, signal=9):
    """计算MACD"""
    ema_short = series.ewm(span=short, adjust=False).mean()
    ema_long = series.ewm(span=long, adjust=False).mean()
    macd = ema_short - ema_long
    signal_line = macd.ewm(span=signal, adjust=False).mean()
    histogram = macd - signal_line
    return macd, signal_line, histogram

df['MACD'], df['Signal'], df['Histogram'] = calculate_macd(df['Close'])

print("MACD预览:")
print(df[['Close', 'MACD', 'Signal', 'Histogram']].tail())

5. 统计分析

5.1 描述性统计

print("股票数据统计摘要:")
print(df[['Close', 'Volume', 'daily_return']].describe())

# 分位数
quantiles = df['Close'].quantile([0.25, 0.5, 0.75])
print("\nClose价格分位数:")
print(quantiles)

5.2 波动率分析

# 日波动率(标准差)
df['volatility'] = df['daily_return'].rolling(window=30).std() * np.sqrt(252)  # 年化波动率

print("波动率预览:")
print(df[['daily_return', 'volatility']].tail())

# 历史波动率
historical_vol = df['daily_return'].std() * np.sqrt(252)
print("\n年化历史波动率:", round(historical_vol, 4))

5.3 相关性分析

# 简单相关性
corr_matrix = df[['Close', 'Volume', 'RSI', 'MACD']].corr()
print("相关系数矩阵:")
print(corr_matrix)

# 热力图可视化
import seaborn as sns
plt.figure(figsize=(8, 6))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')
plt.title('股票指标相关性热力图')
plt.show()

5.4 风险指标

# 最大回撤
def max_drawdown(returns):
    """计算最大回撤"""
    cum_returns = (1 + returns).cumprod()
    peak = cum_returns.cummax()
    drawdown = (cum_returns - peak) / peak
    return drawdown.min()

mdd = max_drawdown(df['daily_return'])
print("最大回撤:", round(mdd, 4))

# 夏普比率(年化)
risk_free_rate = 0.03  # 假设无风险利率
sharpe = (df['daily_return'].mean() * 252 - risk_free_rate) / (df['daily_return'].std() * np.sqrt(252))
print("夏普比率:", round(sharpe, 4))

6. 数据可视化

6.1 K线图

# 注意:需安装 mplfinance(pip install mplfinance)
# from mplfinance.original_flavor import candlestick_ohlc
# import matplotlib.dates as mdates

# df_ohlc = df[['Open', 'High', 'Low', 'Close']].reset_index()
# df_ohlc['Date'] = mdates.date2num(df_ohlc['Date'])

# fig, ax = plt.subplots(figsize=(12, 6))
# candlestick_ohlc(ax, df_ohlc.values, width=0.6, colorup='g', colordown='r')
# ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
# plt.title('股票K线图')
# plt.xticks(rotation=45)
# plt.show()

6.2 趋势图与指标

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), sharex=True)

# 价格趋势
ax1.plot(df.index, df['Close'], label='Close')
ax1.plot(df.index, df['MA20'], label='MA20')
ax1.plot(df.index, df['MA50'], label='MA50')
ax1.set_title('股票价格趋势')
ax1.legend()

# RSI与MACD
ax2.plot(df.index, df['RSI'], label='RSI')
ax2.axhline(70, color='r', linestyle='--', label='Overbought')
ax2.axhline(30, color='g', linestyle='--', label='Oversold')
ax2.set_title('RSI指标')
ax2.legend()

plt.tight_layout()
plt.show()

6.3 回报率分布

plt.figure(figsize=(10, 6))
df['daily_return'].hist(bins=50)
plt.title('日回报率分布')
plt.xlabel('回报率')
plt.ylabel('频数')
plt.show()

7. 高级分析

7.1 回测简单策略

# 移动平均交叉策略
df['signal'] = np.where(df['MA5'] > df['MA20'], 1, 0)
df['strategy_return'] = df['signal'].shift(1) * df['daily_return']

# 累计回报
df['strategy_cum'] = (1 + df['strategy_return']).cumprod() - 1

plt.figure(figsize=(12, 6))
df['cum_return'].plot(label='买入持有')
df['strategy_cum'].plot(label='MA交叉策略')
plt.title('策略回测')
plt.ylabel('累计回报')
plt.legend()
plt.show()

7.2 多股相关性分析

# 模拟多股数据
stocks = pd.DataFrame({
    'AAPL': df['Close'],
    'GOOG': df['Close'] * 1.2 + np.random.randn(len(df)) * 10,
    'MSFT': df['Close'] * 0.8 + np.random.randn(len(df)) * 5
})

# 相关性
multi_corr = stocks.corr()
print("多股相关性:")
print(multi_corr)

plt.figure(figsize=(8, 6))
sns.heatmap(multi_corr, annot=True, cmap='coolwarm')
plt.title('股票相关性热力图')
plt.show()

8. 性能考虑

  • 大数据处理:对于海量数据,使用 DaskModin 并行化 Pandas 操作。
  • 实时分析:结合 StreamlitDash 构建交互式仪表板。
  • 机器学习集成:使用 Scikit-learn 构建预测模型,例如基于 RSI 和 MACD 预测股价趋势。

Pandas 股票数据分析结合时间序列处理、统计计算和可视化,是量化投资的核心工具。通过实际项目练习,可以深入掌握其应用。建议结合真实 API 数据进行扩展。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注