我来用一个完整的股票价格预测案例,展示如何利用历史大数据进行建模预测。

完整案例:股票价格预测
数据准备与加载
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import yfinance as yf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout, GRU
from tensorflow.keras.optimizers import Adam
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 下载股票数据(以苹果公司为例)
print("正在下载股票数据...")
stock_data = yf.download('AAPL',
start='2018-01-01',
end='2023-12-31',
progress=False)
print(f"数据形状: {stock_data.shape}")
print(stock_data.head())
数据探索与特征工程
# 数据探索
def explore_data(df):
"""数据探索分析"""
print("="*50)
print("数据基本信息:")
print(df.info())
print("\n统计数据:")
print(df.describe())
# 检查缺失值
print("\n缺失值统计:")
print(df.isnull().sum())
# 检查是否有重复
print(f"\n重复行数: {df.duplicated().sum()}")
explore_data(stock_data)
# 特征工程
def create_features(df):
"""创建技术指标特征"""
df = df.copy()
# 价格变化
df['Price_Change'] = df['Close'].pct_change()
# 移动平均线
df['MA5'] = df['Close'].rolling(window=5).mean()
df['MA20'] = df['Close'].rolling(window=20).mean()
df['MA60'] = df['Close'].rolling(window=60).mean()
# 波动率
df['Volatility'] = df['Price_Change'].rolling(window=20).std()
# RSI指标
delta = df['Close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
rs = gain / loss
df['RSI'] = 100 - (100 / (1 + rs))
# MACD指标
exp1 = df['Close'].ewm(span=12, adjust=False).mean()
exp2 = df['Close'].ewm(span=26, adjust=False).mean()
df['MACD'] = exp1 - exp2
df['Signal'] = df['MACD'].ewm(span=9, adjust=False).mean()
df['MACD_Hist'] = df['MACD'] - df['Signal']
# 交易量特征
df['Volume_MA'] = df['Volume'].rolling(window=20).mean()
df['Volume_Ratio'] = df['Volume'] / df['Volume_MA']
# 价格范围
df['High_Low_Ratio'] = (df['High'] - df['Low']) / df['Close']
df['Close_Open_Ratio'] = (df['Close'] - df['Open']) / df['Open']
# 清除NaN值
df = df.dropna()
return df
# 创建特征
featured_data = create_features(stock_data)
print(f"\n特征工程后的数据形状: {featured_data.shape}")
print(featured_data[['Close', 'MA5', 'MA20', 'RSI', 'MACD']].tail())
数据可视化
def visualize_data(df):
"""数据可视化分析"""
fig, axes = plt.subplots(4, 2, figsize=(15, 15))
fig.suptitle('股票数据分析', fontsize=16, fontweight='bold')
# 1. 收盘价走势
axes[0, 0].plot(df.index, df['Close'], label='Close Price', linewidth=2)
axes[0, 0].plot(df.index, df['MA20'], label='MA20', alpha=0.7)
axes[0, 0].plot(df.index, df['MA60'], label='MA60', alpha=0.7)
axes[0, 0].set_title('股票价格走势')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)
# 2. 交易量
axes[0, 1].bar(df.index, df['Volume'], alpha=0.6, color='orange')
axes[0, 1].set_title('交易量')
axes[0, 1].grid(True, alpha=0.3)
# 3. RSI指标
axes[1, 0].plot(df.index, df['RSI'], color='purple')
axes[1, 0].axhline(y=70, color='r', linestyle='--', alpha=0.5)
axes[1, 0].axhline(y=30, color='g', linestyle='--', alpha=0.5)
axes[1, 0].set_title('RSI指标')
axes[1, 0].grid(True, alpha=0.3)
# 4. MACD指标
axes[1, 1].plot(df.index, df['MACD'], label='MACD', color='blue')
axes[1, 1].plot(df.index, df['Signal'], label='Signal', color='red')
axes[1, 1].fill_between(df.index, df['MACD_Hist'], alpha=0.3)
axes[1, 1].set_title('MACD指标')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
# 5. 收益率分布
axes[2, 0].hist(df['Price_Change'].dropna(), bins=50, edgecolor='black', alpha=0.7)
axes[2, 0].set_title('收益率分布')
axes[2, 0].set_xlabel('收益率')
axes[2, 0].set_ylabel('频数')
# 6. 价格相关性热图
correlation = df[['Open', 'High', 'Low', 'Close', 'Volume', 'RSI', 'MACD']].corr()
sns.heatmap(correlation, annot=True, cmap='coolwarm', center=0, ax=axes[2, 1])
axes[2, 1].set_title('相关性热图')
# 7. 波动率
axes[3, 0].plot(df.index, df['Volatility'], color='green')
axes[3, 0].set_title('价格波动率')
axes[3, 0].grid(True, alpha=0.3)
# 8. 收盘价分布
axes[3, 1].hist(df['Close'], bins=50, edgecolor='black', alpha=0.7)
axes[3, 1].set_title('收盘价分布')
axes[3, 1].set_xlabel('价格')
axes[3, 1].set_ylabel('频数')
plt.tight_layout()
plt.show()
visualize_data(featured_data)
数据预处理
def prepare_data(df, feature_cols, target_col, lookback=60):
"""
准备LSTM训练数据
参数:
- df: 数据框
- feature_cols: 特征列
- target_col: 目标列
- lookback: 历史窗口大小
返回:
- X_train, y_train, X_test, y_test, scaler
"""
# 选择特征和标签
data = df[feature_cols].values
# 标准化
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
# 准备序列数据
X, y = [], []
for i in range(lookback, len(scaled_data)):
X.append(scaled_data[i-lookback:i])
y.append(scaled_data[i, feature_cols.index(target_col)])
X, y = np.array(X), np.array(y)
# 划分训练集和测试集
train_size = int(len(X) * 0.8)
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]
print(f"训练集形状: {X_train.shape}")
print(f"测试集形状: {X_test.shape}")
return X_train, y_train, X_test, y_test, scaler
# 定义特征和目标
feature_cols = ['Open', 'High', 'Low', 'Close', 'Volume',
'MA5', 'MA20', 'RSI', 'MACD', 'Volatility']
target_col = 'Close'
# 准备数据
lookback = 60 # 使用过去60天的数据
X_train, y_train, X_test, y_test, scaler = prepare_data(
featured_data, feature_cols, target_col, lookback
)
构建LSTM预测模型
def build_lstm_model(input_shape):
"""构建LSTM模型"""
model = Sequential()
# 第一层LSTM
model.add(LSTM(units=128, return_sequences=True, input_shape=input_shape))
model.add(Dropout(0.2))
# 第二层LSTM
model.add(LSTM(units=128, return_sequences=True))
model.add(Dropout(0.2))
# 第三层LSTM
model.add(LSTM(units=64, return_sequences=False))
model.add(Dropout(0.2))
# 全连接层
model.add(Dense(units=32, activation='relu'))
model.add(Dropout(0.1))
# 输出层
model.add(Dense(units=1))
# 编译模型
model.compile(
optimizer=Adam(learning_rate=0.001),
loss='mse',
metrics=['mae']
)
return model
# 创建模型
print("构建LSTM模型...")
model = build_lstm_model((X_train.shape[1], X_train.shape[2]))
model.summary()
# 训练模型
print("开始训练模型...")
history = model.fit(
X_train, y_train,
validation_data=(X_test, y_test),
epochs=50,
batch_size=32,
verbose=1
)
# 保存模型
model.save('lstm_stock_model.h5')
print("模型已保存!")
模型评估与预测
def evaluate_and_predict(model, X_test, y_test, scaler, feature_cols, target_col):
"""模型评估和预测"""
# 预测
y_pred = model.predict(X_test)
# 反标准化预测值
y_pred_original = scaler.inverse_transform(
np.concatenate([np.zeros((len(y_pred), len(feature_cols) - 1)),
y_pred.reshape(-1, 1)], axis=1)
)[:, -1]
# 反标准化实际值
y_test_original = scaler.inverse_transform(
np.concatenate([np.zeros((len(y_test), len(feature_cols) - 1)),
y_test.reshape(-1, 1)], axis=1)
)[:, -1]
# 计算评估指标
mse = mean_squared_error(y_test_original, y_pred_original)
mae = mean_absolute_error(y_test_original, y_pred_original)
r2 = r2_score(y_test_original, y_pred_original)
print("="*50)
print("模型评估指标:")
print(f"均方误差 (MSE): {mse:.4f}")
print(f"平均绝对误差 (MAE): {mae:.4f}")
print(f"R² 决定系数: {r2:.4f}")
print(f"RMSE: {np.sqrt(mse):.4f}")
return y_pred_original, y_test_original
# 预测和评估
y_pred_original, y_test_original = evaluate_and_predict(
model, X_test, y_test, scaler, feature_cols, target_col
)
# 绘制结果
fig, axes = plt.subplots(3, 1, figsize=(15, 12))
# 1. 训练损失
axes[0].plot(history.history['loss'], label='Training Loss')
axes[0].plot(history.history['val_loss'], label='Validation Loss')
axes[0].set_title('模型损失曲线')
axes[0].set_xlabel('Epoch')
axes[0].set_ylabel('Loss')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 2. 预测结果对比
axes[1].plot(y_test_original, label='Actual Prices', alpha=0.7)
axes[1].plot(y_pred_original, label='Predicted Prices', alpha=0.7)
axes[1].set_title('股票价格预测 vs 实际价格')
axes[1].set_xlabel('Days')
axes[1].set_ylabel('Price')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
# 3. 预测误差
axes[2].plot(y_test_original - y_pred_original, color='red')
axes[2].axhline(y=0, color='black', linestyle='-', linewidth=0.5)
axes[2].set_title('预测误差')
axes[2].set_xlabel('Days')
axes[2].set_ylabel('Error')
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
未来价格预测
def predict_future(model, last_sequence, scaler, feature_cols, target_col, days=30):
"""
预测未来价格
参数:
- model: 训练好的模型
- last_sequence: 最近的历史数据序列
- days: 预测天数
"""
future_predictions = []
current_sequence = last_sequence.copy()
for _ in range(days):
# 预测下一个值
next_pred = model.predict(current_sequence.reshape(1, current_sequence.shape[0], current_sequence.shape[1]))
# 创建新序列
new_sequence = current_sequence[1:]
# 将预测值添加到序列中(使用Close列的位置)
# 这里需要根据feature_cols中Close的位置调整
close_idx = feature_cols.index('Close')
new_point = np.zeros((1, current_sequence.shape[2]))
new_point[0, close_idx] = next_pred[0, 0]
# 更新其他特征(简化处理)
new_sequence = np.append(new_sequence, new_point, axis=0)
current_sequence = new_sequence
# 存储预测值
future_predictions.append(next_pred[0, 0])
# 反标准化
future_predictions = np.array(future_predictions)
future_prices = scaler.inverse_transform(
np.concatenate([np.zeros((len(future_predictions), len(feature_cols) - 1)),
future_predictions.reshape(-1, 1)], axis=1)
)[:, -1]
return future_prices
# 预测未来30天价格
future_days = 30
last_sequence = X_test[-1] # 使用最后一段测试数据
future_prices = predict_future(
model, last_sequence, scaler, feature_cols, target_col, days=future_days
)
# 绘制未来预测
fig, ax = plt.subplots(figsize=(12, 6))
# 画出历史价格(最后100天)
historical_days = 100
historical_prices = featured_data['Close'][-historical_days:].values
# 预测日期
last_date = featured_data.index[-1]
future_dates = pd.date_range(start=last_date + timedelta(days=1),
periods=2*future_days,
freq='D')
# 实际价格和预测价格的连接
combined_prices = np.concatenate([historical_prices, future_prices])
# 绘制
ax.plot(range(historical_days), historical_prices, label='历史价格', color='blue')
ax.plot(range(historical_days-1, historical_days-1+len(future_prices)),
future_prices, label='预测价格', color='red', linestyle='--')
ax.set_title('股票价格预测')
ax.set_xlabel('天数')
ax.set_ylabel('价格')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"future_days}天预测价格:")
for i, price in enumerate(future_prices, 1):
print(f"第{i}天: ${price:.2f}")
模型部署示例
class StockPredictor:
"""股票价格预测器"""
def __init__(self, model_path):
"""初始化预测器"""
self.model = tf.keras.models.load_model(model_path)
self.scaler = None
self.feature_cols = ['Open', 'High', 'Low', 'Close', 'Volume',
'MA5', 'MA20', 'RSI', 'MACD', 'Volatility']
self.lookback = 60
def load_data(self, symbol, start_date, end_date):
"""加载并准备数据"""
data = yf.download(symbol, start=start_date, end=end_date, progress=False)
featured = create_features(data)
return featured
def predict_next(self, data):
"""预测下一天价格"""
try:
# 准备数据
scaled_data = self.scaler.transform(data[self.feature_cols].values)
last_sequence = scaled_data[-self.lookback:]
# 预测
prediction = self.model.predict(last_sequence.reshape(1, self.lookback, len(self.feature_cols)))
# 反标准化
predicted_price = self.scaler.inverse_transform(
np.concatenate([np.zeros((1, len(self.feature_cols) - 1)),
prediction.reshape(-1, 1)], axis=1)
)[0, -1]
return predicted_price
except Exception as e:
print(f"预测失败: {e}")
return None
# 使用示例
try:
predictor = StockPredictor('lstm_stock_model.h5')
print("预测器初始化成功!")
# 预测示例
# predictor.predict_next(featured_data)
except Exception as e:
print(f"初始化失败: {e}")
数据处理流程
- 数据清洗:处理缺失值、异常值
- 特征工程:技术指标、市场指标、时间序列特征
- 数据标准化:避免不同量纲的影响
模型选择建议
| 模型类型 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| LSTM | 序列预测 | 擅长捕捉长期依赖 | 训练时间较长 |
| GRU | 简单序列预测 | 计算效率高 | 表达能力略弱 |
| XGBoost | 特征预测 | 处理非线性 | 不擅长序列 |
| ARIMA | 简单时间序列 | 统计基础好 | 线性假设较强 |
优化建议
# 使用早停法防止过拟合
from tensorflow.keras.callbacks import EarlyStopping
early_stop = EarlyStopping(monitor='val_loss',
patience=10,
restore_best_weights=True)
# 使用学习率调度
from tensorflow.keras.callbacks import ReduceLROnPlateau
reduce_lr = ReduceLROnPlateau(monitor='val_loss',
factor=0.2,
patience=5,
min_lr=0.0001)
注意事项
- ⚠️ 股票预测具有高度不确定性
- 历史数据不等于未来表现
- 建议结合基本面分析
- 定期重新训练模型
- 监控模型漂移
这个完整案例展示了如何从数据准备到模型部署的完整流程,实际应用中需要根据具体需求调整参数和模型结构,同时要注意风险控制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播