Python金融分析实战:Apple股价趋势可视化与预测
1. 从零开始:获取与准备Apple股价数据
做金融数据分析的第一步永远是获取可靠的数据源。对于Apple股价数据,我们有几个主流选择:
- 雅虎财经历史数据:直接通过
yfinance库下载,这是最方便的方式 - 本地CSV文件:比如课程提供的1980-2014年数据集
- 专业金融数据API:如Alpha Vantage(需注册API key)
我强烈推荐新手先用本地CSV文件练手。这里分享一个我处理数据时的经验:永远先做数据质量检查。下面是完整的初始化代码:
import pandas as pd import matplotlib.pyplot as plt # 读取数据 apple = pd.read_csv('appl_1980_2014.csv') # 基础检查三连 print(apple.head()) # 看前5行 print(apple.info()) # 看数据类型和缺失值 print(apple.describe()) # 统计摘要处理时间序列数据有个关键步骤:正确转换日期格式。很多新手会忽略时区问题,导致后续分析出现诡异偏差。这是我踩过的坑:
# 最佳实践:明确指定日期格式和时区 apple['Date'] = pd.to_datetime(apple['Date'], format='%Y-%m-%d', utc=True) apple.set_index('Date', inplace=True)2. 数据清洗的实战技巧
原始金融数据往往存在各种问题。根据我的经验,Apple股价数据需要特别注意以下几点:
- 处理缺失值:股市休市日没有数据
- 异常值检测:股价突然暴涨暴跌是否合理
- 重复数据:交易所可能重复推送数据
这是我常用的数据清洗组合拳:
# 检查重复数据 print(f"重复行数: {apple.duplicated().sum()}") # 前向填充缺失值(用前一天的数据填充) apple.fillna(method='ffill', inplace=True) # 检测异常值(3个标准差以外的数据) def detect_outliers(series): z_scores = (series - series.mean()) / series.std() return series[abs(z_scores) > 3] print(detect_outliers(apple['Close']))特别注意:金融数据清洗不能简单删除异常值!股价暴涨暴跌可能是重大事件(如财报发布),需要人工确认。
3. 时间序列分析核心操作
3.1 重采样与滚动计算
金融分析最常用的两个操作:
- 重采样(resample):将日线数据转为周线/月线
- 滚动计算(rolling):计算移动平均等指标
# 周线数据(取每周最后一个交易日) weekly = apple.resample('W-FRI').last() # 20日移动平均 apple['MA20'] = apple['Close'].rolling(window=20).mean() # 布林带指标(Bollinger Bands) apple['Upper'] = apple['MA20'] + 2*apple['Close'].rolling(20).std() apple['Lower'] = apple['MA20'] - 2*apple['Close'].rolling(20).std()3.2 收益率计算
金融分析的核心是收益率而非绝对价格。常用计算方法:
# 日收益率 apple['Daily_Return'] = apple['Close'].pct_change() # 对数收益率(更适合建模) apple['Log_Return'] = np.log(apple['Close']/apple['Close'].shift(1)) # 累计收益率 apple['Cumulative_Return'] = (1 + apple['Daily_Return']).cumprod()4. 专业级股价可视化
4.1 基础K线图实现
用mplfinance库可以轻松绘制专业K线图:
import mplfinance as mpf # 准备数据格式 ohlc = apple.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']] # 绘制K线图+成交量 mpf.plot(ohlc, type='candle', volume=True, style='charles', title='Apple Stock Price', mav=(20,50))4.2 交互式可视化
静态图表不够用?试试Plotly的交互图表:
import plotly.graph_objects as go fig = go.Figure(data=[go.Candlestick( x=apple.index, open=apple['Open'], high=apple['High'], low=apple['Low'], close=apple['Close'] )]) fig.update_layout(title='Apple Stock Price', yaxis_title='Price ($)') fig.show()进阶技巧:添加技术指标到交互图表中:
# 添加移动平均线 fig.add_trace(go.Scatter( x=apple.index, y=apple['MA20'], line=dict(color='blue', width=1), name='20日均线' )) # 添加布林带 fig.add_trace(go.Scatter( x=apple.index, y=apple['Upper'], line=dict(color='red', width=1), name='布林带上轨' ))5. 股价预测实战:ARIMA模型
5.1 时间序列平稳性检验
预测前必须先检验序列的平稳性:
from statsmodels.tsa.stattools import adfuller result = adfuller(apple['Close'].dropna()) print(f'ADF Statistic: {result[0]}') print(f'p-value: {result[1]}')如果p值>0.05(非平稳),需要进行差分处理:
apple['Close_diff'] = apple['Close'].diff().dropna()5.2 ARIMA建模与预测
from statsmodels.tsa.arima.model import ARIMA # 划分训练集/测试集 train = apple['Close'][:-30] test = apple['Close'][-30:] # 建立ARIMA(1,1,1)模型 model = ARIMA(train, order=(1,1,1)) results = model.fit() # 预测未来30天 forecast = results.get_forecast(steps=30) predicted_values = forecast.predicted_mean confidence_intervals = forecast.conf_int()5.3 预测结果可视化
plt.figure(figsize=(12,6)) plt.plot(train.index, train, label='训练集') plt.plot(test.index, test, label='真实值') plt.plot(predicted_values.index, predicted_values, label='预测值', color='red') plt.fill_between(confidence_intervals.index, confidence_intervals.iloc[:,0], confidence_intervals.iloc[:,1], color='pink', alpha=0.3) plt.legend() plt.title('Apple股价30日预测') plt.show()6. 机器学习预测:LSTM实战
6.1 数据预处理
LSTM需要特殊的数据格式:
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() scaled_data = scaler.fit_transform(apple[['Close']]) # 创建时间步长数据 def create_dataset(data, time_step=60): X, y = [], [] for i in range(len(data)-time_step-1): X.append(data[i:(i+time_step), 0]) y.append(data[i+time_step, 0]) return np.array(X), np.array(y) X, y = create_dataset(scaled_data)6.2 构建LSTM模型
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense model = Sequential() model.add(LSTM(50, return_sequences=True, input_shape=(X.shape[1],1))) model.add(LSTM(50)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam')6.3 训练与预测
model.fit(X, y, epochs=20, batch_size=32) # 预测未来30天 last_60_days = scaled_data[-60:] forecast = [] for _ in range(30): X_test = last_60_days[-60:].reshape(1,60,1) pred = model.predict(X_test) forecast.append(pred[0,0]) last_60_days = np.append(last_60_days, pred)7. 分析结果解读与投资建议
完成分析后,如何解读结果才是关键。根据我的经验:
- 技术指标交叉:当短期均线上穿长期均线(金叉),可能是买入信号
- 布林带收窄:通常预示即将出现大幅波动
- 预测模型评估:用RMSE、MAE等指标衡量预测精度
from sklearn.metrics import mean_squared_error # 计算预测误差 rmse = np.sqrt(mean_squared_error(test, predicted_values)) print(f'RMSE: {rmse:.2f}') # 计算方向准确性 direction_acc = np.mean(np.sign(test.diff().dropna()) == np.sign(predicted_values.diff().dropna())) print(f'方向预测准确率: {direction_acc:.2%}')实际投资决策中,技术分析只是参考。建议结合基本面分析和市场情绪,形成综合判断。我在实际回测中发现,单纯依赖技术指标的策略在震荡市中表现不佳,需要配合止损机制。
