使用 LSTM 对股票涨跌额进行预测(仅适合作业示例)


前言

在机器学习和深度学习中,时间序列预测是一项常见且具有挑战性的任务。LSTM(Long Short-Term Memory)是一种常用的循环神经网络(RNN)结构,善于处理序列数据与长期依赖问题。因此,许多教程会以 LSTM 为例对股票价格或涨跌进行预测。

然而,需要明确的一点是:本篇教程中的模型仅为示例用途,不具备实际预测价值。实际股市预测需要考虑极其复杂的因素,包括宏观经济、市场情绪、政策风险、突发事件等。本教程简化了许多环节,结果仅能作为参考代码与学习对象,并不建议将其用于真实的投资决策。

教程目标

使用 Pandas 读取本地股票历史数据(CSV 格式)。
使用 MinMaxScaler 对数据进行归一化。
构建简单的 LSTM 模型对股票的“收盘价”进行预测。
训练模型并可视化预测结果。
强调此模型对实际预测的局限性与滞后性,仅作为课程作业或研究演示。

数据准备

在本教程中,我们假设你已经有一份本地 CSV 文件,其中包含股票的历史交易数据。该文件应至少包含如下列:

股票代码|交易日期|开盘价|最高价|最低价|收盘价|昨收价|涨跌额|成交额(千元)
例如:000001.SZ.csv

股票代码,交易日期,开盘价,最高价,最低价,收盘价,昨收价,涨跌额,成交额(千元)
000001.SZ,2019-01-02,8.53,8.60,8.46,8.50,8.53,-0.03,1234567

请根据自己的数据进行相应调整。

代码示例

下面的代码展示了如何使用 LSTM 对股票涨跌额进行预测的基础流程。其中包含数据读取、数据预处理、模型定义与训练、以及预测结果的可视化与误差评估。

import numpy as np
import pandas as pd
import torch
from sklearn.metrics import mean_squared_error, mean_absolute_error
from sklearn.preprocessing import MinMaxScaler
from torch import nn
from torch.utils.data import DataLoader, TensorDataset
import matplotlib.pyplot as plt

# 读取本地 CSV 文件
pandas_df = pd.read_csv("000001.SZ.csv", header=0)

# 转换 '交易日期' 为 datetime 类型并按日期排序
pandas_df['交易日期'] = pd.to_datetime(pandas_df['交易日期'], errors='coerce')
pandas_df.sort_values('交易日期', inplace=True)

# 去除空值行
pandas_df = pandas_df.dropna()

# 选择用于训练的特征列
features = ['开盘价', '最高价', '最低价', '收盘价', '昨收价', '涨跌额', '成交额(千元)']
data = pandas_df[features]

# 使用 MinMaxScaler 对特征进行归一化
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
scaled_df = pd.DataFrame(scaled_data, columns=features, index=pandas_df['交易日期'])

# 将数据按时间分割
train_data = scaled_df[scaled_df.index < '2020-01-01']
test_data = scaled_df[scaled_df.index >= '2020-01-01']

# 创建时间序列数据集的函数,使用过去 N 天的数据来预测未来的收盘价
def create_dataset_for_profit(df, _time_step=60):
    X, y = [], []
    for i in range(len(df) - _time_step - 1):
        X.append(df.iloc[i:(i + _time_step)].values)  # 特征
        y.append(df.iloc[i + _time_step, 3])  # 预测目标,选择收盘价("收盘价"的索引是 3)
    return np.array(X), np.array(y)

# 创建时间序列数据集
time_step = 20  # 使用过去 60 天的数据来预测未来一天的收盘价

# 创建训练集和测试集的数据集
X_train, y_train = create_dataset_for_profit(train_data, time_step)
X_test, y_test = create_dataset_for_profit(test_data, time_step)

# 检查训练集和测试集的形状
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)


# 将数据转换为 PyTorch 张量
X_train_tensor = torch.tensor(X_train, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train, dtype=torch.float32).view(-1, 1)
X_test_tensor = torch.tensor(X_test, dtype=torch.float32)
y_test_tensor = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)

# 创建训练集和测试集的 DataLoader
train_data = TensorDataset(X_train_tensor, y_train_tensor)
test_data = TensorDataset(X_test_tensor, y_test_tensor)

train_loader = DataLoader(train_data, batch_size=32, shuffle=False)
test_loader = DataLoader(test_data, batch_size=32, shuffle=False)


class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_layer_size, output_size):
        super(LSTMModel, self).__init__()

        # 第一层 LSTM
        self.lstm1 = nn.LSTM(input_size, hidden_layer_size, batch_first=True)

        # 第二层 LSTM
        self.lstm2 = nn.LSTM(hidden_layer_size, hidden_layer_size, batch_first=True)

        # 全连接层
        self.fc = nn.Linear(hidden_layer_size, output_size)

    def forward(self, x):
        # 第一层 LSTM
        out, (hn, cn) = self.lstm1(x)

        # 第二层 LSTM
        out, (hn, cn) = self.lstm2(out)

        # 只取最后一时刻的输出
        out = self.fc(out[:, -1, :])
        return out

# 模型超参数
input_size = len(features)  # 特征数量
hidden_layer_size = 32  # 隐藏层神经元个数
output_size = 1  # 预测收盘价

# 初始化模型
model = LSTMModel(input_size=input_size, hidden_layer_size=hidden_layer_size, output_size=output_size)

# 打印模型结构
print(model)

# 定义损失函数和优化器
criterion = nn.MSELoss()  # 由于目标是预测连续数值(收盘价),我们使用 MSELoss
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# 训练模型
epochs = 100
for epoch in range(epochs):
    model.train()
    running_loss = 0.0
    for inputs, labels in train_loader:
        # 清零梯度
        optimizer.zero_grad()

        # 前向传播
        outputs = model(inputs)

        # 计算损失
        loss = criterion(outputs, labels)

        # 反向传播
        loss.backward()

        # 更新参数
        optimizer.step()

        # 累积损失
        running_loss += loss.item()

    # 每 5 个 epoch 输出一次损失
    if (epoch + 1) % 5 == 0:
        print(f'Epoch [{epoch + 1}/{epochs}], Loss: {running_loss / len(train_loader)}')


# 测试模型
model.eval()
predictions = []
real_values = []

with torch.no_grad():
    for inputs, labels in test_loader:
        outputs = model(inputs)
        predictions.append(outputs.numpy())
        real_values.append(labels.numpy())

# 将预测结果转换为 numpy 数组
predictions = np.concatenate(predictions)
real_values = np.concatenate(real_values)

# 可视化预测结果


# 创建图形,设置图形大小
plt.figure(figsize=(12, 6))

# 绘制真实值和预测值
plt.plot(real_values, color='blue', label='真正的收盘价', linewidth=2, linestyle='-', marker='o', markersize=6, alpha=0.8)
plt.plot(predictions, color='red', label='预测的收盘价', linewidth=2, linestyle='--', marker='x', markersize=6, alpha=0.8)

# 添加标题
plt.title('股票收盘价预测 (LSTM)', fontsize=16, fontweight='bold')

# 设置 x 和 y 轴的标签
plt.xlabel('时间', fontsize=14)
plt.ylabel('收盘价 ', fontsize=14)

# 添加网格,设置透明度
plt.grid(True, which='both', linestyle='--', linewidth=0.5, alpha=0.6)

# 设置 x 轴为时间格式
plt.xticks(rotation=45, fontsize=12)
plt.yticks(fontsize=12)

# 添加图例
plt.legend(fontsize=12)

# 显示图表
plt.tight_layout()  # 自动调整布局
plt.show()

# 计算均方误差(MSE)
mse = mean_squared_error(real_values, predictions)
print(f'Mean Squared Error (MSE): {mse}')

# 计算均方根误差(RMSE)
rmse = np.sqrt(mse)
print(f'Root Mean Squared Error (RMSE): {rmse}')

# 计算平均绝对误差(MAE)
from sklearn.metrics import mean_absolute_error
mae = mean_absolute_error(real_values, predictions)
print(f'Mean Absolute Error (MAE): {mae}')


结果展示

在这里插入图片描述

Mean Squared Error (MSE): 6.731566827511415e-05
Root Mean Squared Error (RMSE): 0.008204612880945206
Mean Absolute Error (MAE): 0.006247698795050383

从图像可以看出:
股票价格变化复杂且多变,仅使用过去的价格数据难以捕捉未来的行情变动。模型在实际使用中通常会表现出滞后性与不稳定性,预测结果往往与现实走势有较大偏差。

<think>我们正在讨论如何使用Python进行股票预测,包括涨跌判断和持仓分析。根据引用内容,我们可以结合AI技术(如机器学习模型)和爬虫技术来获取数据并构建预测模型。步骤概述:1.数据获取:使用爬虫从金融网站获取股票/基金历史数据(引用[2]和[3]提供了爬虫示例)。2.数据预处理:清洗数据,处理缺失值,特征工程等。3.构建预测模型:使用机器学习算法(如引用[4]中的支持向量机)进行涨跌预测。4.持仓分析:分析基金或股票的持仓情况(引用[3]提到了基金持仓抓取)。5.模型评估与优化:评估模型性能,调整参数(引用[4]提到网格搜索优化参数)。下面我们分步骤详细说明,并提供代码示例。###1.数据获取使用爬虫获取股票历史数据。以下是一个从东方财富网抓取基金数据的示例(参考引用[3]):```pythonimportrequestsimportredefcrawler_front_page():headers={'Referer':'http://fund.eastmoney.com/data/fundranking.html','User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/96.0.4664.45Safari/537.36','Cookie':'xxxx'#需要填写有效的Cookie}#注意:实际URL需要根据情况调整,这里是一个示例URLurl='http://fund.eastmoney.com/data/rankhandler.aspx?op=ph&dt=kf&ft=all&rs=&gs=0&sc=6yzf&st=desc&sd=2020-11-18&ed=2021-11-18&qdii=&tabSubtype=,,,,,&pi=1&pn=10000&dx=1'response=requests.get(url,headers=headers)response.encoding='utf-8'returnresponse.textdefparse_front_page(html):#提取基金代码(6位数字)fund_codes=re.findall(r"\d{6}",html)returnfund_codes#调用函数html=crawler_front_page()fund_codes=parse_front_page(html)print(fund_codes[:10])#打印前10个基金代码```对于股票数据,我们可以使用Tushare、AkShare等库,或者使用YahooFinance的API(通过`yfinance`库)。安装yfinance:`pipinstallyfinance`示例代码:```pythonimportyfinanceasyf#下载股票历史数据data=yf.download('600519.SS',start='2020-01-01',end='2021-12-31')print(data.head())```###2.数据预处理通常包括:-处理缺失值:填充或删除缺失数据。-特征工程:构造技术指标(如移动平均线、MACD、RSI等)作为特征。示例:计算移动平均线```pythondata['MA5']=data['Close'].rolling(window=5).mean()data['MA20']=data['Close'].rolling(window=20).mean()```###3.构建预测模型使用机器学习算法预测股票涨跌。这里以支持向量机(SVM)为例(参考引用[4])。首先,定义目标变量:我们预测第二天的涨跌(1表示上涨,0表示下跌)。```pythonimportnumpyasnp#计算每日涨跌幅data['Return']=data['Close'].pct_change()#创建目标变量:如果次日回报为正则为1,否则为0(注意:这里使用次日回报,所以需要后移一天)data['Target']=np.where(data['Return'].shift(-1)>0,1,0)#删除缺失值data=data.dropna()```然后,划分训练集和测试集,并训练SVM模型:```pythonfromsklearn.svmimportSVCfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportaccuracy_score#选择特征(这里只用了两个移动平均线,实际中可以加入更多特征)features=data[['MA5','MA20']]target=data['Target']#划分数据集X_train,X_test,y_train,y_test=train_test_split(features,target,test_size=0.2,shuffle=False)#创建SVM模型并训练model=SVC(C=0.6,gamma=0.001)#参数参考引用[4]中优化后的值model.fit(X_train,y_train)#预测predictions=model.predict(X_test)#评估准确率accuracy=accuracy_score(y_test,predictions)print(f"模型准确率:{accuracy:.2f}")```###4.持仓分析对于基金持仓分析,我们可以爬取基金持仓的股票信息(参考引用[3])。然后,我们可以分析基金持仓的行业分布、重仓股等。示例:获取某只基金的持仓信息(以东方财富网为例)```pythondefget_fund_holdings(fund_code):url=f'http://fundf10.eastmoney.com/FundArchivesDatas.aspx?type=jjcc&code={fund_code}'headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/96.0.4664.45Safari/537.36'}response=requests.get(url,headers=headers)response.encoding='utf-8'#解析返回的数据(返回的数据是JavaScript代码,包含在varapidata=...中)#这里需要解析出持仓信息(通常是HTML表格)#由于解析复杂,此处展示思路,实际解析可能需要正则或BeautifulSoup#提取HTML表格并转换为DataFrame#这里省略具体解析过程returnholdings_df#假设我们已经有一个基金代码fund_holdings=get_fund_holdings('000001')#以000001基金为例print(fund_holdings.head())```###5.模型评估与优化我们可以使用网格搜索来优化模型参数(参考引用[4]):```pythonfromsklearn.model_selectionimportGridSearchCV#定义参数网格param_grid={'C':[0.1,0.5,1,2,5,10],'gamma':[0.001,0.01,0.1,1]}#创建网格搜索对象grid_search=GridSearchCV(SVC(),param_grid,cv=5,scoring='accuracy')grid_search.fit(X_train,y_train)#输出最佳参数print("最佳参数:",grid_search.best_params_)print("最佳准确率:",grid_search.best_score_)```###注意事项-股票预测具有挑战性,模型准确率可能不高(如引用[4]中准确率0.5),实际应用中需要谨慎。-爬虫时注意遵守网站规则,避免频繁请求。以上是一个基本的股票预测流程,包括数据获取、预处理、模型构建、持仓分析和模型优化。根据需求,可以尝试其他模型(如随机森林、LSTM等)和更复杂的特征工程。§§相关问题§§1.如何提高股票预测模型的准确率?2.除了SVM,还有哪些机器学习模型适合股票预测?3.如何获取实时股票数据并实现自动化交易?4.如何分析基金持仓的行业分布和风险?</think>## 如何使用Python进行股票预测涨跌判断+持仓分析) 我将结合引用内容,分步骤介绍使用Python实现股票预测的方法,包含涨跌预测和持仓分析的核心技术。 ### 一、数据获取与预处理 #### 1. 股票数据爬取(参考引用[2][3]) ```python import requests import re import pandas as pd from datetime import datetime def get_stock_data(stock_code, start_date, end_date): """获取股票历史数据""" url = f"https://query1.finance.yahoo.com/v7/finance/download/{stock_code}" params = { 'period1': int(datetime.strptime(start_date, '%Y-%m-%d').timestamp()), 'period2': int(datetime.strptime(end_date, '%Y-%m-%d').timestamp()), 'interval': '1d', 'events': 'history' } response = requests.get(url, params=params) data = pd.read_csv(io.StringIO(response.text)) return data def get_fund_holdings(fund_code): """获取基金持仓数据(参考引用[3])""" headers = { 'Referer': 'http://fund.eastmoney.com/data/fundranking.html', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...' } url = f'http://fundf10.eastmoney.com/FundArchivesDatas.aspx?type=jjcc&code={fund_code}' response = requests.get(url, headers=headers) # 解析HTML获取持仓数据 soup = BeautifulSoup(response.text, 'html.parser') holdings_table = soup.find('table', {'class': 'w782 comm jjcc'}) return pd.read_html(str(holdings_table))[0] ``` ### 二、涨跌预测模型(参考引用[1][4]) #### 1. 特征工程 ```python def create_features(data): """创建技术指标特征""" # 移动平均线 data['MA5'] = data['Close'].rolling(window=5).mean() data['MA20'] = data['Close'].rolling(window=20).mean() # 相对强弱指数(RSI) delta = data['Close'].diff() gain = delta.where(delta > 0, 0) loss = -delta.where(delta < 0, 0) avg_gain = gain.rolling(window=14).mean() avg_loss = loss.rolling(window=14).mean() rs = avg_gain / avg_loss data['RSI'] = 100 - (100 / (1 + rs)) # MACD exp12 = data['Close'].ewm(span=12, adjust=False).mean() exp26 = data['Close'].ewm(span=26, adjust=False).mean() data['MACD'] = exp12 - exp26 data['Signal'] = data['MACD'].ewm(span=9, adjust=False).mean() # 目标变量:次日涨跌(1=涨, 0=跌) data['Target'] = (data['Close'].shift(-1) > data['Close']).astype(int) return data.dropna() ``` #### 2. 支持向量机预测模型(参考引用[4]) ```python from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV from sklearn.metrics import accuracy_score def train_predict_model(data): """训练并预测股票涨跌""" X = data[['MA5', 'MA20', 'RSI', 'MACD', 'Signal']] y = data['Target'] # 划分训练集和测试集 split = int(0.8 * len(data)) X_train, X_test = X[:split], X[split:] y_train, y_test = y[:split], y[split:] # 网格搜索优化参数(参考引用[4]) param_grid = { 'C': [0.1, 0.5, 1, 2, 5], 'gamma': [0.001, 0.01, 0.1, 0.5, 1] } grid_search = GridSearchCV(SVC(), param_grid, cv=5) grid_search.fit(X_train, y_train) # 最佳模型 best_model = grid_search.best_estimator_ predictions = best_model.predict(X_test) # 评估准确率 accuracy = accuracy_score(y_test, predictions) print(f"模型准确率: {accuracy:.2f}, 最佳参数: {grid_search.best_params_}") return best_model ``` ### 三、持仓分析(参考引用[3]) ```python def analyze_holdings(holdings_data): """分析基金持仓""" # 行业分布分析 industry_dist = holdings_data['所属行业'].value_counts(normalize=True) # 重仓股分析 top_holdings = holdings_data.nlargest(5, '持仓占比') # 风险分散度 herfindahl = (holdings_data['持仓占比']**2).sum() # 赫芬达尔指数 return { 'industry_distribution': industry_dist, 'top_holdings': top_holdings, 'concentration_index': herfindahl } ``` ### 四、完整工作流程 ```python # 1. 获取数据 stock_data = get_stock_data('600519.SS', '2020-01-01', '2023-12-31') # 2. 特征工程 processed_data = create_features(stock_data) # 3. 训练预测模型 model = train_predict_model(processed_data) # 4. 最新预测 latest_features = processed_data.iloc[-1][['MA5', 'MA20', 'RSI', 'MACD', 'Signal']] prediction = model.predict([latest_features]) print(f"明日预测: {'上涨' if prediction[0] == 1 else '下跌'}") # 5. 持仓分析 fund_holdings = get_fund_holdings('000001') holding_analysis = analyze_holdings(fund_holdings) print("行业分布:\n", holding_analysis['industry_distribution']) print("\n前五大重仓股:\n", holding_analysis['top_holdings']) ``` ### 关键技术说明 1. **特征工程**:使用移动平均线(MA)、相对强弱指数(RSI)、MACD等技术指标作为预测特征[^1] 2. **机器学习模型**:采用支持向量机(SVM)分类器,通过网格搜索优化超参数[^4] 3. **持仓分析**: - 行业分布:计算各行业持仓比例 - 重仓股分析:识别持仓占比最高的股票 - 风险分散度:赫芬达尔指数衡量持仓集中度[^3] ### 注意事项 1. 股票预测准确率受市场波动影响较大,引用[4]中模型准确率为0.5 2. 实际应用需考虑更多特征:市场情绪、宏观经济指标等[^1] 3. 爬虫需遵守网站规则,避免频繁请求[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值