本题目来自于第三届“中青杯”大学生数学建模竞赛B组
tushare id:353995
题目:
问题一:投资者购买目标指数中的资产,如果购买全部,从理论上讲能够完美跟踪指数,但是当指数成分股较多时,购买所有资产的成本过于高昂,同时也需要很高的管理成本,在实际中一般不可行。
(1)在附件数据的分析和处理的过程中,请对缺损数据进行补全。
(2)投资者购买成分股时,过多过少都不太合理。对于附件的成分股数据,请您通过建立模型,给出合理选股方案和投资组合方案。
问题二:尝试给出合理的评价指标来评估问题一中的模型,并给出您的分析结果。
还有第三问,不过和本模型关系不大。我们就不写了。
分析题目,我们可以看到,解决本题的关键是建立一个合理有效的分布和评估模型,且主要评估其稳定性与收益的关系。且最后我们需要使用除题目所给数据之外进行评估,这里,我们采用tushare提供的每日交易数据接口。
模型建立:参考数据中共有五个参数及一个时间维数,参数中开盘与收盘价代表着当日 盈利,同时又和最高价与最低价代表着其波动性。而成交量和极值股价又是一对 相互依赖的变量。综合考虑,这里我们分为两个部分,当日开收盘价组成收益与 波动的一部分,而极值股价与成交量作为另一个部分。从而形成一种类似与物理 学中能动量关系的预测模型。同时,我们考虑对投资收益的度量方法,这里主要 的影响是投资的周期及周期买入卖出方法。考虑到指数的特点,这里我们采用每 三个月评估一次和整个数据表评估两种方式来评价股票。
对于一只股票,我们定义其基本收益单元ο为每日开盘价与收盘价之差。 而基本波动单元ߜʹ则定义为周期内的收益单元的方差。即:
݊为了方便确定投资策略,我们希望把收益和险化为一个归一化系数Q来描述。 这里我们计算一个时期内的总收益 Sum,并将其与方差相乘。又考虑到我们希望 该系数和股价之间存在递减的一次或反比例关系,使用其绝对值的根式即:
而正负收益自然是不同的。我们这里引入符号函数 sign(),将原式改写为:
带入符号量便是
这是模型的第一部分 模型的第二部分曳引系数t
由极值股价和成交量变化组成。这一部分便是我 们所说的动量部分。考虑成交量代表着交易的活力,而极值股价则是当日某一个 交易方向(买入或卖出)的顶峰。这里定义交易量比率߬为:
同时,像前面一样,我们定义一日的极值价格差为∇,同时,将他们相乘得到
为待定系数 进一步的,我们还要考虑的是一段时间内的。对其简单求平均即可,因为 自身就已经包含了每一日的特异值,不必再加权平均。 写出:
至此,我们的模型已经基本成型了。
代码:
算法部分的实现其实十分简单,numpy为我们以上的操作都写好了函数。我们这里重点展示如何把tushare提供的数据洗成我们需要的数据格式:
import tushare as ts
import time
pro=ts.pro_api('your torken')
import pandas as pd
import numpy as np
def imfor(name,ps):
pro = ts.pro_api('your torken')
#df = pro.daily(ts_code=name, start_date='20100101', end_date='20200701')#,fields='ts_code,trade_date,open,high,low,close,vol,amount')
df=pro.daily(ts_code='000001.SH', start_date='20000101', end_date='20200325')
print(df)
df.drop(['ts_code'], axis=1, inplace=True)
df.drop(['pre_close'], axis=1, inplace=True)
df.drop(['change'], axis=1, inplace=True)
df.drop(['pct_chg'], axis=1, inplace=True)
df.drop(['amount'], axis=1, inplace=True)
df['trade_date'] = pd.to_datetime(df.trade_date, format='%Y%m%d')
df.index =df['trade_date']
df.drop(['trade_date'], axis=1, inplace=True)
df.drop(['trade_date'], axis=1, inplace=True)
df.rename(columns={'open': 'start', 'close': 'end', 'vol': 'number'}, inplace=True)
df.drop(['start'], axis=1, inplace=True)
df.drop(['end'], axis=1, inplace=True)
df.drop(['number'], axis=1, inplace=True)
df=df.iloc[::-1]
bool=df.empty
if(bool!=True):
df.to_csv(ps)
print(df)
return df
这样,我们得到的数据就是包含了最高价最低价,开盘收盘和交易笔数的数据,并且是使用日期作为索引的。
附注:https://waditu.com 这是tushare的官方地址,目前,即使是免费的积分数量也能获取很多数据。