2020年中青杯全国大学生数学建模竞赛题目【本科组】——纪念第一次训练模型!
一、题目:
B题(本科生组):股指与国家经济自1990年12月19日上海证券交易所挂牌成立,经过30年的快速发展,中国证券市场已经具有相当规模,在多方面取得了举世瞩目的成就,对国民经济的资源配置起着日益重要的作用。截至2019年年底,上海和深圳两个证券交易所交易的股票约4000种。目前,市场交易制度、信息披露制度和证券法规等配套制度体系已经建立起来,投资者日趋理性和成熟,机构投资者迅速发展已具规模,政府对证券市场交易和上市公司主体行为的监管已见成效。
随着近年来我国资本市场的发展和证券交易规模的不断扩大,越来越多的资金投资于证券市场,与此同时市场价格的波动也十分剧烈,而波动作为证券市场中最本质的属性和特征,市场的波动对于人们风险收益的分析、股东权益最大化和监管层的有效监管都有着至关重要的作用,因此研究证券市场波动的规律性,分析引起市场波动的成因,是证券市场理论研究和实证分析的重要内容,也可以为投资者、监管者和上市公司等提供有迹可循的依据。
问题一:投资者购买目标指数中的资产,如果购买全部,从理论上讲能够完美跟踪指数,但是当指数成分股较多时,购买所有资产的成本过于高昂,同时也需要很高的管理成本,在实际中一般不可行。
(1)在附件数据的分析和处理的过程中,请对缺损数据进行补全。
(2)投资者购买成分股时,过多过少都不太合理。对于附件的成分股数据,请您通过建立模型,给出合理选股方案和投资组合方案。
问题二:尝试给出合理的评价指标来评估问题一中的模型,并给出您的分析结果。
问题三:通过附件股指数据和您补充的数据,对当前的指数波动和未来一年的指数波动进行合理建模,并给出您合理的投资建议和策略。
附件:十支股票的相关重要参数。
二、代码分析:
①首先看一下我的文件夹目录:
大致说明一下:在这些文件及文件夹里面,本科生组放在的是桌面上!然后是整体在Pycharm里打开,所有生成的.idea是在第一级目录!只有【附件:十支股票参数.xlsx】是必须要的,另外的文件夹都是通过os模块创建的!
②因为是第一次要训练模型,百度了一波,发现股票的数据集都是csv,于是将这个Excel换成了csv!
"""1、将excel文件转化为:以各指数成分股票命名的csv文件,方便后面的pandas以及matplotlib和numpy的操作
"""# 步骤一:将excel文件转化为csv文件
import os
import csv
from openpyxl import load_workbook# 打开excel文件
wb = load_workbook('附件:十支股票参数.xlsx')
# 列出文件中所有的表名
sheets = wb.sheetnamespath = 'csv数据集'
if not os.path.exists(path):os.mkdir(path)def create_csvs(title,path):name = titlepath = pathf = open(path + '/' + name + '.csv',mode="a+",newline='',encoding="utf-8-sig")csv_write = csv.writer(f)csv_write.writerow(['Date', 'Open', 'High', 'Low','Close','Turnover'])f.close()for sheet in sheets:create_csvs(sheet,path)f = open(path + '/' + sheet + '.csv',mode="a+",newline='',encoding="utf-8-sig")csv_write = csv.writer(f)table = wb[sheet]rows = table.max_rowcols = table.max_columnfor row in range(5,rows+1):data = []for col in range(cols+1):data.append(str(table.cell(row,col+1).value).replace(r'/','-'))csv_write.writerow(data[:6])f.close()
代码很好理解:通过wb.sheetnames将Excel中的所有表名都显示出来,接着通过定义两个函数分别生成csv模板以及将我们的Excel中的几栏数据写入到对应的CSV文件中!最后是通过for循环,将10支股票生成的csv文件都放到一个文件夹【csv数据集】中!(这个文件夹是通过os模块创建的!)
csv数据集文件夹图片:
csv文件图片:
③初步使用LSTM模型进行预测:
# 数据预处理以及绘制图形需要的模块
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 构建长短时神经网络需要的方法
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM, BatchNormalization
import os# 需要之前50次的数据来预测下一次的数据
need_num = 50
# 训练数据的大小
training_num = 200
# 迭代10次
epoch = 10
batch_size = 32
path = 'pics'
if not os.path.exists(path):os.mkdir(path)
# 训练数据的处理,我们选取整个数据集的前200个数据作为训练数据,后面的数据为测试数据
# 从csv读取数据
csvs = ['csv数据集/abc001.csv','csv数据集/abc002.csv','csv数据集/abc003.csv','csv数据集/abc004.csv','csv数据集/abc005.csv','csv数据集/abc006.csv','csv数据集/abc007.csv','csv数据集/abc008.csv','csv数据集/abc009.csv','csv数据集/abc010.csv']
for j in csvs:dataset = pd.read_csv(j)# 我们需要预测开盘数据,因此选取所有行、第2列数据dataset = dataset.iloc[:, 4:5].values# 训练数据就是上面已经读取数据的前200行training_dataset = dataset[:training_num]# 因为数据跨度几十年,随着时间增长,人民币金额也随之增长,因此需要对数据进行归一化处理# 将所有数据归一化为0-1的范围sc = MinMaxScaler(feature_range=(0, 1))'''fit_transform()对部分数据先拟合fit,找到该part的整体指标,如均值、方差、最大值最小值等等(根据具体转换的目的),然后对该trainData进行转换transform,从而实现数据的标准化、归一化等等。'''training_dataset_scaled = sc.fit_transform(X=training_dataset)x_train = []y_train = []# 每10个数据为一组,作为测试数据,下一个数据为标签for i in range(need_num, training_dataset_scaled.shape[0]):x_train.append(training_dataset_scaled[i - need_num: i])y_train.append(training_dataset_scaled[i, 0])# 将数据转化为数组x_train, y_train = np.array(x_train), np.array(y_train)# 因为LSTM要求输入的数据格式为三维的,[training_number, time_steps, 1],因此对数据进行相应转化x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))# 构建网络,使用的是序贯模型model = Sequential()# return_sequences=True返回的是全部输出,LSTM做第一层时,需要指定输入shapemodel.add(LSTM(units=128, return_sequences=True, input_shape=[x_train.shape[1], 1]))model.add(BatchNormalization())model.add(LSTM(units=128))model.add(BatchNormalization())model.add(Dense(units=1))# 进行配置model.compile(optimizer='adam',loss='mean_squared_error')model.fit(x=x_train, y=y_train, epochs=epoch, batch_size=batch_size)# 进行测试数据的处理# 前200个为测试数据,但是将150,即200-50个数据作为输入数据,因为这样可以获取# 测试数据的潜在规律inputs = dataset[training_num - need_num:]inputs = inputs.reshape(-1, 1)# 这里使用的是transform而不是fit_transform,因为我们已经在训练数据找到了# 数据的内在规律,因此,仅使用transform来进行转化即可inputs = sc.transform(X=inputs)x_validation = []for i in range(need_num, inputs.shape[0]):x_validation.append(inputs[i - need_num:i, 0])x_validation = np.array(x_validation)x_validation = np.reshape(x_validation, (x_validation.shape[0], x_validation.shape[1], 1))# 这是真实的股票价格,是源数据的[200:]即剩下的80个数据的价格real_stock_price = dataset[training_num:279]# 进行预测predictes_stock_price = model.predict(x=x_validation)# 使用 sc.inverse_transform()将归一化的数据转换回原始的数据,以便我们在图上进行查看predictes_stock_price = sc.inverse_transform(X=predictes_stock_price)# 绘制数据图表,红色是真实数据,蓝色是预测数据plt.plot(real_stock_price, color='red', label='Real Stock Price')plt.plot(predictes_stock_price, color='blue', label='Predicted Stock Price')plt.title(label='Close Price Prediction')plt.xlabel(xlabel='Time')plt.ylabel(ylabel=j+'Close')plt.savefig(path + '/' + j.replace(r'csv数据集/','').replace(r'.csv','') + '-Close.png')plt.legend()plt.show()
其中呢,我们需要修改这个代码几次,因为上面的这个代码得出的是【10支股票收盘的预测价格】,我们需要将Close换成Open/High/Low/Tow/Turnover,以及dataset = dataset.iloc[:, 4:5].values所代表的切片的列数!
虽然结果有点差强人意,但是好歹是预测了:
④使用均值-方差模型进行波动评价:
数统的小姐姐提供的思路,我觉得可行,就写了一下代码:
import csv
import osfiles = os.listdir('csv数据集')
path = '处理后csv数据集'
if not os.path.exists(path):os.mkdir(path)
max_a = []
max_b = []
for file in files:Date = [row[0] for row in csv.reader(open('csv数据集' + '/' + file,mode="r",encoding="utf-8"))]Open = [row[1] for row in csv.reader(open('csv数据集' + '/' + file,mode="r",encoding="utf-8"))]High = [row[2] for row in csv.reader(open('csv数据集' + '/' + file,mode="r",encoding="utf-8"))]Low = [row[3] for row in csv.reader(open('csv数据集' + '/' + file,mode="r",encoding="utf-8"))]Close = [row[4] for row in csv.reader(open('csv数据集' + '/' + file,mode="r",encoding="utf-8"))]Turnover = [row[5] for row in csv.reader(open('csv数据集' + '/' + file,mode="r",encoding="utf-8"))]f = open(path + '/' + file,mode="a+",newline="",encoding="utf-8-sig")csv_write = csv.writer(f)csv_write.writerow(['Date','Open','High','Low','Close','Turnover','收盘-开盘(a)','最高-最低(b)'])sum_a = 0 # 求均值sum_b = 0variance_a = 0 # 求方差variance_b = 0for i in range(1,len(Date)-1):a = float(Close[i]) - float(Open[i])sum_a += ab = float(High[i]) - float(Low[i])sum_b += bfor j in range(1,len(Date)-1):a = float(Close[j]) - float(Open[j])b = float(High[j]) - float(Low[j])variance_a += ((a-sum_a/280)**2)variance_b += ((b-sum_b/280)**2)for k in range(1,len(Date)):a = float(Close[k]) - float(Open[k])b = float(High[k]) - float(Low[k])csv_write.writerow([Date[k],Open[k],High[k],Low[k],Close[k],Turnover[k],a,b])csv_write.writerow('\n')csv_write.writerow(['a的均值','a的方差','a(均值/方差)','b的均值','b的方差','b(均值/方差)'])max_a.append(sum_a/variance_a)max_b.append(sum_b/variance_b)csv_write.writerow([sum_a/279,variance_a/279,sum_a/variance_a,sum_b/279,variance_b/279,sum_b/variance_b])f.close()# 给10支股票打分
fp = open(path + '/'+'10支股票打分情况.txt',mode="w",encoding='utf-8')
fp.write("10支股票(均值/方差)最大值:"+"\n")
fp.write("\t"+"①收益(a)最高分:"+"\n")
fp.write("\t"+str(max(max_a)) + "\n")
fp.write("\t"+"②风险(b)最高分:"+"\n")
fp.write("\t"+str(max(max_b)) + "\n")
fp.write("*"*100+"\n")
fp.write("10支股票(均值/方差)所有数值:"+"\n")
fp.write("\t"+"①收益(a)数值情况:"+"\n")
fp.write("\t"+str(max_a) + "\n")
fp.write("\t"+"②风险(b)数值情况:"+"\n")
fp.write("\t"+str(max_b) + "\n")
fp.write("*"*100+"\n")
fp.write("下面是收益(a)相对最高分时的打分情况"+"\n")
sum_a_average = 0
sum_b_average = 0
for i in range(len(max_a)):fp.write("\t"+files[i].replace(r'.csv','')+":"+"\t"+str((max_a[i]/max(max_a))*100)+"\n")sum_a_average += (max_a[i]/max(max_a))*100
fp.write("\t"+"收益打分平均值:"+"\t"+str(sum_a_average/10)+"\n")
fp.write("*"*100+"\n")
fp.write("下面是风险(b)相对最高分时的打分情况"+"\n")
for i in range(len(max_b)):fp.write("\t"+files[i].replace(r'.csv','')+":"+"\t"+str((max_b[i]/max(max_b))*100)+"\n")sum_b_average += (max_b[i]/max(max_b))*100
fp.write("\t"+"风险打分平均值:"+"\t"+str(sum_b_average/10)+"\n")
思路是:计算收益(a) = 收盘-开盘,风险(b) = 最高-最低!然后呢得出10支股票的每一行的数据,写到新的csv文件的对应的列后面!接着,计算整列的a以及b分别对应的均值以及方差!写到csv文件的结尾处!然后,遍历10支股票的(均值/方差)最大值并设置成100分,分别得出10支股票的得分!
看一下打分情况:
后面的分析数统队友的事了,反正我也看不懂~~~
⑤新的模型测试:
# 根据股票历史的开盘价、收盘价和成交量等特征值,从数学角度来预测股票未来的收盘价
import pandas as pd
import numpy as np
import math
import os
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split# 从文中获取数据
files = os.listdir('csv数据集')
path = '第二种模型预测图片'
if not os.path.exists(path):os.mkdir(path)
for file in files:origDf = pd.read_csv('csv数据集'+'/'+file, encoding='utf-8-sig')df = origDf[['Close', 'High', 'Low', 'Open', 'Turnover']]featureData = df[['Open', 'High', 'Turnover','Low']]# 划分特征值和目标值feature = featureData.values"""设置了要预测的目标列是收盘价。在后续的代码中,需要将计算出开盘价、最高价、最低价和成交量这四个特征值和收盘价的线性关系,并在此基础上预测收盘价。"""target = np.array(df['Turnover'])# 划分训练集/测试集feature_train, feature_test, target_train, target_test = train_test_split(feature, target, test_size=0.05)"""通过调用train_test_split方法把包含在csv文件中的股票数据分成训练集和测试集,这个方法前两个参数分别是特征列和目标列,而第三个参数0.05则表示测试集的大小是总量的0.05。该方法返回的四个参数分别是特征值的训练集、特征值的测试集、要预测目标列的训练集和目标列的测试集。"""pridectedDays = int(math.ceil(0.05 * len(origDf))) # 预测天数lrTool = LinearRegression() # 建了一个线性回归预测的对象lrTool.fit(feature_train, target_train) # 调用fit方法训练特征值和目标值的线性关系,请注意这里的训练是针对训练集的# 用特征值的测试集来预测目标值(即收盘价)。也就是说,是用多个交易日的股价来训练lrTool对象,并在此基础上预测后续交易日的收盘价predictByTest = lrTool.predict(feature_test)# 组装数据index = 0# 在前95%的交易日中,设置预测结果和收盘价一致while index < len(origDf) - pridectedDays:# 把训练集部分的预测股价设置成收盘价df.ix[index, 'predictedVal'] = origDf.ix[index, 'Turnover']# 设置了训练集部分的日期df.ix[index, 'Date'] = origDf.ix[index, 'Date']index = index + 1predictedCnt = 0# 在后5%的交易日中,用测试集推算预测股价while predictedCnt < pridectedDays:df.ix[index, 'predictedVal'] = predictByTest[predictedCnt]# 把df中表示测试结果的predictedVal列设置成相应的预测结果,同时也在后面的程序语句逐行设置了每条记录中的日期df.ix[index, 'Date'] = origDf.ix[index, 'Date']predictedCnt = predictedCnt + 1index = index + 1plt.figure()# 分别绘制了预测股价和真实收盘价,在绘制的时候设置了不同的颜色,也设置了不同的label标签值df['predictedVal'].plot(color="red", label='predicted Data')df['Turnover'].plot(color="blue", label='Real Data')# 通过调用legend方法,根据收盘价和预测股价的标签值,绘制了相应的图例plt.legend(loc='best') # 绘制图例# 设置x坐标的标签# 设置了x轴显示的标签文字是日期,为了不让标签文字显示过密,设置了“每20个日期里只显示1个”的显示方式major_index = df.index[df.index % 20 == 0]major_xtics = df['Date'][df.index % 20 == 0]plt.xticks(major_index, major_xtics)plt.setp(plt.gca().get_xticklabels(), rotation=30)# 带网格线,且设置了网格样式plt.grid(linestyle='-.')plt.savefig(path + '/' + file.replace(r".csv",'-Turnover.png'))plt.show()"""预测股价和真实价之间有差距,但涨跌的趋势大致相同。而且在预测时没有考虑到涨跌停的因素,所以预测结果的涨跌幅度比真实数据要大"""
相对于之前的LSTM模型来说,这个训练和测试更直观一点!代码跟之前一样,也需要手动的修改几次!
这边的情况是:将数据集的95%作为训练集,剩下的5%作为测试集,然后分别用红线和蓝线表示!
然后,我们就可以根据这个进行预测第280行数据(原文件中280行数据可能是错的!所以要补全~)
⑥以上这么多是问题一以及问题二的解决思路!至于问题三,队友用SPSS预测的!说实话,我没思路~~~
三、总结
写下这篇博客的目的:
- 六一儿童节快乐~~~
- 纪念一下自己的第一次模型使用~~(为后面的学习找到理由)
- 代码写了几个小时,难道不能亮出来么~~~
本文代码及材料见Github仓库!(点击就可以实现跳转~)
微信公众号:【空谷小莜蓝】,一个普通985的精神小伙创建的公众号,大家可以关注一下哈~~~
2020年中青杯全国大学生数学建模竞赛题目【本科组】——纪念第一次训练模型!相关推荐
- 2010年高教社杯全国大学生数学建模竞赛题目B题解析及层次分析法AHP在其中的应用
2010年高教社杯全国大学生数学建模竞赛题目 B题 2010年上海世博会影响力的定量评估 2010年上海世博会是首次在中国举办的世界博览会.从1851年伦敦的"万国工业博览会"开始 ...
- 2018年高教社杯全国大学生数学建模竞赛题目
简单地说:数模竞赛就是对实际问题的一种数学表述. 具体一点说:数学模型是关于部分现实世界为某种目的的一个抽象的简化的数学结构. 更确切地说:数学模型就是对于一个特定的对象为了一个特定目标,根据特有的内 ...
- 2011高教社杯全国大学生数学建模竞赛题目(MATLAB)
问题描述 2011高教社杯全国大学生数学建模竞赛题目 (请先阅读"全国大学生数学建模竞赛论文格式规范") A题 城市表层土壤重金属污染分析 随着城市经济的快速发展和城市人口的不断增 ...
- 2019年高教社杯全国大学生数学建模竞赛 题目回顾及个人体会
本文目录 1. 校内初赛 2. 组织队伍 3. 国赛 4. 个人感受 1. 校内初赛 我们学校在每次国赛前有一个校内选拔赛,我们选的校赛题目是 "两江游"轮船的调度问题,个人感觉这 ...
- 2021 年高教社杯全国大学生数学建模竞赛题目(B 题 乙醇偶合制备 C4 烯烃)
B 题 乙醇偶合制备 C4 烯烃 C4 烯烃广泛应用于化工产品及医药的生产,乙醇是生产制备 C4 烯烃的原料.在制备过程中,催化剂组合(即:Co 负载量.Co/SiO2 和 HAP 装料比.乙醇浓度的 ...
- 2017年高教社杯全国大学生数学建模竞赛题目 B题 “拍照赚钱”的任务定价
"拍照赚钱"的任务定价分析 "拍照赚钱" 是一种需要会员在APP上领取任务,完成后赚取对任务所标定的酬金的自助服务模式,这种APP中任务定价是其核心要素.通过对 ...
- 2017年高教社杯全国大学生数学建模竞赛题目 B题 “拍照赚钱”的任务定价
这是自己参加比赛写的论文,成果归我和王晨曦所有 想要论文的请关注公众号: 在一起的足球 自动获取论文和数十种经典算法,帮助各位提升自己 之前留的是自己的qq号 感觉好多资源都不能让大家自行选择 本着开 ...
- matlab 电路频率响应_2020年中青杯全国大学生数学建模竞赛——A题 集成电路通道布线...
A题做完了. ------------------------------ 背景: 电路设计与实现需要借助专用计算机软件才能完成,该类软件统称为电子设计自动化工具. 电路设计的一个重要阶段称为&quo ...
- 2020“高教社”杯全国大学生数学建模竞赛——建模国赛优秀论文
[链接:https://pan.baidu.com/s/1bP_16tbcYGxQPoi05r6lRQ 提取码:zjxs]
最新文章
- MAML-Tracker: 目标跟踪分析:CVPR 2020(Oral)
- 1.2 - C#语言习惯 - 用运行时常量readonly而不是编译期常量const
- 安装网关报mysql服务ini_linux 操作系统下ORACLE数据库使用透明网关连接MYSQL
- 每天一个linux命令(46):vmstat命令
- vue-自定义过滤器--时间
- 最短路径Dijkstra讲解,工具包使用 python
- Mac 如何恢复出厂设置
- Eclipse中的Github Gists
- Luckysheet(在线表格) v2.1.12
- 【ios】在真实设备上运行
- 怎样成为一个优秀的领导?
- C#WinCE程序(.NET Compact Framework 3.5)项目重构面向抽象设计
- poythoncode-实战2--常用方式for、while、dict、list
- tesseract 字典下载_qq阅读官方下载-QQ阅读器下载V7.5.0.888官方最新版
- 计算机二进制乘法运算(原码,补码)
- sqlserver with 语法
- 2022年全球市场羊毛纱总体规模、主要生产商、主要地区、产品和应用细分研究报告
- 五千字!详细解读链家「难而正确的事」
- 在canvas上实现3D效果
- 【Spring AOP】@Aspect结合案例详解(二): @Pointcut使用@within和within(已附源码)
热门文章
- Ubuntu 升级 kernel 至 5.13.11(5.15.10)
- 推荐几个容易中的计算机EI源刊(基本百发百中)
- 【云原生】Docker容器详细讲解
- android支付宝支付微信支付封装,如何在Android App中集成支付宝和微信支付功能
- Linux 下配置vim
- [一键CV] Blazor 拖放上传文件转换格式并推送到浏览器下载
- 两句话说明白 MAC和HMAC的区别
- 2014年4月份第4周51Aspx源码发布详情
- Cross compiling Windows binaries from Linux
- oracle union wher,sql – UNION with WHERE子句