2021年第二届“大湾区杯”粤港澳金融建模竞赛B题解题思路和部分代码

概要:

金融建模类的竞赛难度真的很大,其数据处理程度堪比大数据类比赛;其建模能力要求堪比深圳杯,编程能力要求堪比含金量普通或中上的算法比赛。还需要有及其扎实的金融知识背景(没错,我不会。我就一计算机专业的)。**此比赛不推荐单人参赛、不推荐建模小白参赛。**这次博主单人完成的作品是B题的本科组三等奖。

使用的编程语言和工具:PYTHON,MATLAB,聚宽量化平台
关键词:特征工程 多因子选股模型 BP神经网络 历史数据法

题目回顾:

首先,这个金融建模的题目就已经吊打国内大部分数学建模比赛了,8天的比赛。B题光题目打印出来就整整3页。A题更多。。
概括来说,B题的问题是这样的:
券商研报(卖方研报)是指证券公司的研究人员对证券及相关产品的价值, 戒者影响其市场价格的因素迚行分析,所作出的研究报告。完整的券商研报,包含对证券迚行综合分析,总结出关于上市公司、行业戒宏观政策的看法,并对相关股票迚行投资评级等。
商提供的典型公司研报可能会包括:公司的相关数据、经营情况、重大事件、重要信息,以及关于公司的盈利预测与投资建议,公司的财务预测数据、估值结果与风险提示等。还可能会给出相关报告评级、历史推荐等级和目标价等。
综合研究券商研报和外部环境对证券公司股票走势的影响,请建立数学模型完成下列仸务:
(1)请在湾区指数的 30 支股票中,选取 10 支湾区股票的券商研报,提取研报的特征指标。
(2)对选择的 10 支湾区指数股票,建模分析研报特征指标对股票走势的影响, 并提出明确的投资策略。
(3)建模研究突发事件的闪现、舆情和自然灾害因素等对选择的 10 支湾区指数股票行情的影响。
(4)综合建模分析券商研报和外界环境因素对证券公司股票走势的影响,修改仸务(2)的投资策略,并提出新的投资策略。

说实话,8天8夜的比赛,我花了3天研究题目。导致后期发力不足直接投资策略直接放到上证上跑的效果不是很好。

咳咳,下面是解题思路了!

解题思路:

问题一:

问题一要求在题目提供的30支股票中,选取10支股票并对它们各自的研报进行特征指标的提取。首先,鉴于研究券商研报对股票走势的影响的合理性以及后续模型建立的普适性,随机选取10支股票,其名称及股票代码分别为:分众传媒(002027)、亿纬锂能(300014)、生益科技(600183)、华侨城A(000069)、中国平安(601318)、瀚蓝环境(600323)、格力电器(000651)、粤水电(002060)、中顺洁柔(002511)、白云山(600332)。其次,对于研报的选取,因为不同证券公司撰写的研报,其对股票研究的侧重点以及对股票走势预测建立、使用的模型也迥然不同。经思考,可得:券商研报的内容可以帮助投资者更好地掌握市场动态,和新闻媒体一样,具有一定的实时性。那么,发布日期最新的研报,其内容和给出的特征指标无疑对后续未来投资策略的制定有着最有代表性的参考意义,因此,选取本文撰写日期(2021年11月2日)之前以上10支股票最新发布的研报为研究对象,进行特征指标的提取。然后,根据题意可知,典型研报可以提供如市盈率、市净率、毛利率等特征因子的信息,但我们不认为这是研报的专属的“特征指标”,一般来说,研报中的词语出现的频率在一定程度上会反映撰写者对该词语的重视程度(“你”,“我”等常用词除外),词语出现的频率越高,说明该词语一定程度上蕴含了更多的撰写者想要表达的信息和思想。综上所述,提出研报的特征指标的定义:
1.特征指标是券商研报中出现一定频率的词语。
2.特征指标也是典型研报可以提供的特征因子。
对研报进行基于特征工程的文本特征提取,获得研报的特征指标。
对研报进行特征提取的代码如下(PYTHON,只给个例子,10支股票都贴出来估计过不了审,研报来源:发现报告)

# coding=utf-8
import jieba
from sklearn.feature_extraction.text import CountVectorizer
def cut_word(text):                                   #进行分词处理
    text = ' '.join ( list ( jieba.cut ( text ) ) )
    return text
def cut_chinese_demo2(data):                              #进行简单的词频统计,粗略地反映研报中最有特征性的词汇

    data_new = []
    for sen in data:
        data_new.append ( cut_word ( sen ) )
    transfer = CountVectorizer ()
    data_final = transfer.fit_transform ( data_new )
    print ( "data_new:\n", data_final.toarray () )
    print ( "特征名字:\n", transfer.get_feature_names () )

data7=["亿纬锂能 (300014)——储能电芯获关键测试突破,持续完善上游布局"
"事件:2021 年前三季度,公司实现营业收入 114.48 亿元,同比增长 114.39%;实现归母净利润 22.16 亿元,同比增长 134.18%;实现基本每股收益 1.17 元/股,同比增长 129.41%。"
"投资要点:业绩略低于市场预期, 累计营收突破百亿大关。2021 年前三季度,公司实现营业收入"
"114.48 亿元,同比增长 114.39%,主要系随着新建产能持续释放,为满足客户需求,公司电池出货规模增长较大所致;实现归母净利润 22.16 亿元,同比增长 134.18%;实现基本每股收益 1.17 元/股,同比增长 129.41%。2021 年第三季度,公司实现归母净利润 7.21 亿元,同比增长 23.70%,环比下降 14.98%;单季度销售毛利率为 21.55%,环比下降 2.4 个百分点,我们认为主要系原材料涨价带来的成本压力所致。"
"国内领先的动力电池厂商,储能电芯获关键测试突破。根据中国汽车动力电池产业创新联盟统计,2021 年 1-9 月,我国动力电池累计装机量为 92.03GWh,其中亿纬锂能装机量为 1.70GWh,市占率为 1.8%,位居国内第七;2021 年 9 月,我国动力电池装机量为15.69GWh,其中亿纬锂能装机量为 0.26GWh,市占率为 1.6%。2021 年 5 月,公司子公司亿纬动力 LF280K 储能电芯获得了祐力(中国)投资有限公司出具的 UL9540A 测试报告,该报告是北美储能项目开发商或业主在提交相关项目审批流程时所需的一份关键第三方报告,本次获得报告有望助力亿纬动力更好地开拓国际储能市场,对扩大产品国际影响力和海外市场业务具有积极作用。"
"相关研究 证券分析师 张雷 A0230519100003 [email protected] 研究支持 陈明雨 A0230120040001 [email protected] 黄华栋 A0230120050002"
"[email protected]"
"联系人"
"黄华栋(8621)23297818×转"
"[email protected]"
"0%"
"-50%"
"拟与中科电气设立合资公司,持续完善上游布局。公司拟与中科电气签署《合资经营协议》拟合作设立合资公司,其中公司认缴 40,000 万元,持有合资公司 40%股权;中科电气认缴 60,000 万元,持有合资公司 60%股权。该合资公司将专注于为负极材料制造,并优先向公司及其子公司供应。项目计划投资总额为人民币 25 亿元,负极材料年产能 10 万吨, 采用分期建设模式,一期和二期产能规模各为 5 万吨/年。本次合作有利于公司持续完善上游电池原材料产业链布局,稳定原材料供应,降低采购成本,打造更具技术、成本竞争优势的锂电池产品。"
"维持盈利预测,维持“买入”评级:公司是优质的锂电池科技公司,动力电池快速放量, 储能电池有望形成新的增长曲线。我们预计 21-23 年公司归母净利润分别为 32.20、44.81、"
"57.40 亿元,对应 EPS 分别为 1.70、2.36、3.02 元/股,当前股价对应的 PE 分别为 64 倍46 倍和 36 倍。维持“买入”评级。"
"风险提示:全球电动化进展不达预期;动力电池价格下跌超出预期。财务数据及盈利预测"
"注:“市盈率”是指目前股价除以各年每股收益;“净资产收益率”是指摊薄后归属于母公司所有者的 ROE"
"请务必仔细阅读正文之后的各项信息披露与声明"
"财务摘要"
"百万元,百万股	2019A	2020A	2021E	2022E	2023E"
"营业总收入	6,412	8,162	15,741	22,881	29,238"
"其中:营业收入	6,412	8,162	15,741	22,881	29,238"
"减:营业成本	4,506	5,794	11,350	16,559	21,188"
"减:税金及附加	47	39	75	110	140"
"主营业务利润	1,859	2,329	4,316	6,212	7,910"
"减:销售费用	175	226	441	641	819"
"减:管理费用	189	270	519	686	877"
"减:研发费用	459	684	1,198	1,373	1,462"
"减:财务费用	95	60	95	80	48"
"经营性利润	941	1,089	2,063	3,432	4,704"
"加:信用减值损失(损失以“-”填列)	-89	-82	0	0	0"
"加:资产减值损失(损失以“-”填列)	-86	-22	36	-60	-60"
"加:投资收益及其他	867	944	1,500	1,701	1,900"
"营业利润	1,634	1,929	3,598	5,074	6,545"
"加:营业外净收入	-7	-11	-8	-8	-8"
"利润总额	1,626	1,918	3,590	5,066	6,537"
"减:所得税	77	237	314	505	696"
"净利润	1,549	1,681	3,277	4,561	5,841"
"少数股东损益	27	29	57	79	102"
"归属于母公司所有者的净利润	1,522	1,652	3,220	4,481	5,740"
"全面摊薄总股本	969	1,889	1,898	1,898	1,898"
"每股收益(元)	0.86	0.89	1.70	2.36	3.02"]

cut_chinese_demo2(data7)

得出提取结果:(以粤水电为例)
2021年第二届“大湾区杯”粤港澳金融建模竞赛B题解题思路和部分代码_第1张图片

问题二:

问题二要求建立数学模型研究问题一提取出的特征指标对选定的10支股票走势的影响,并制定投资策略。问题一选取股票对应的公司的业务范围较广:科技行业、地产行业、消费服务行业等。影响这10支股票的走势的因素也不尽相同。出于对本问题建立的数学模型的泛化能力以及鲁棒性考虑,建立多因子选股模型研究特征指标对股票走势的影响,并制定投资策略。
首先,常见的股市指数有上证综指、深证成指等,本问题以上证综指为基准进行后续的研究。选取2014~2020年的股票相关数据等作为样本并进行因子筛选以及检验。
从问题一中对选定的10支股票的最新券商研报提取出的特征指标可分为以下四类用于构建多因子选股模型的因子:
1.价值类因子:市盈率(PE),市净率(PB),市销率(PS)。
2.成长类因子:毛利率(Gross Profit Margin)。
3.规模类因子:净利润(net_profit),营业收入(operating_revenue),资产负债率(L/A)。
4.交投类因子:换手率(turnover_ratio)。
以10支选定的股票为股票池,首先,通过聚宽量化平台提供的数据接口,采用排序法对以上特征指标的进行有效性进行验证:因为净利润这个因子在多支目标股票中被提取出来,根据净利润的大小将10支目标股票进行排序,其排序结果如下(从小到大):粤水电(002060.XSHE),中洁柔顺(002511.XSHE),瀚蓝环境(600323.XSHG),生益科技(600183.XSHG),亿纬锂能(300014.XSHE),白云山(600332.XSHG),华侨城A(000069.XSHE),分众传媒(002027.XSHE),格力电器(000651.XSHE),中国平安(601318.XSHG)。
将其分为5等份,每份为一个股票组合。出于对后续制定的投资策略的时效性和实际意义性考虑,且对股票走势的预测本身有一定的滞后性,使用Python计算5个组合在2021年9月初内的收益情况,得5个股票组合的收益虽然都跑赢了大盘,但都为0。显然地,要构建因子组合并计算不同组合的月收益率。
鉴于计算数据的精确性,使用聚宽量化平台以2014年到2020年为时间范围,计算1~5组以及大盘组合的月收益率及总收益情况。
为了提高后续建立的模型的性能和精确性,提出因子检验量化指标并建模,使用聚宽量化平台进行实测,结果还不错。
多因子选股模型的基本python程序如下:

import pandas as pd
import numpy as np
import statsmodels.api as sm
import scipy.stats as scs
import matplotlib.pyplot as plt
from pandas import Series,DataFrame
from jqdatasdk import *
auth('18128233820','20001115wanLZK')       #接入聚宽量化平台
#1.将问题一提取的8个特征指标的名称枚举出来
factors=['PE','PB','PS',
         'Gross Profit Margin',
         'net_profit','operating reveune','L/A',
         'turnover_ratio']
#2.每到月初的时候需要取出因子的值
def get_factors(fdate, factors):
    stock_set = get_index_stocks('000001.XSHG', fdate)           #读取上证综指
    q = query (
        valuation.code,
        valuation.pe_ratio,
        valuation.pb_ratio,
        valuation.ps_ratio,
        indicator.gross_profit_margin,
        income.net_profit,
        income.total_profit / income.operating_revenue,
        balance.total_liability / balance.total_assets,
        valuation.turnover_ratio
    ).filter (

        valuation.circulating_market_cap
    )
    fdf = get_fundamentals ( q, date=fdate )
    fdf.index = fdf['code']
    return fdf.iloc[:,-9:]

fdf = get_factors('2021-09-01', factors)    #于2021年9月1日取出所有因子数值
#2.对每个因子大小排序(以净利润为例,因为10所股票提取出来的特征指标中大部分都有净利润)
score=fdf['net_profit'].sort_values()
startdate='2021-09-01'
enddate='2021-10-01'
nextdate='2021-11-01'
fdf.to_csv("data2.csv",index=False)                #将挖取数据转化为csv文件,通过排序找出10支股票在序列中的位置(在xls文件中处理)
df = {}
netprofit= fdf['net_profit']
port1=list(score.index)[3167:3265+1:3265-3167];#将10支股票作为股票池,按净利润大小分为5组。
port2=list(score.index)[3886:4144+1:4144-3886];
port3=list(score.index)[4150:4158+1:4158-4150];
port4=list(score.index)[4240:4257+1:4257-4240];
port5=list(score.index)[4384:4418+1:4418-4384];
#按净利润加权计算组合月收益(以2021年11月、10月、9月为例)
def calculate_port_momthly1():
    net_profit=fdf['net_profit']
    close1=get_price(port1,startdate,enddate,'daily',['close'],panel=False)
    close2=get_price(port1,enddate,nextdate,'daily',['close'],panel=False)
    weighted_m=(((close2['close'].iloc[:]/close1['close'].iloc[:]-1)*net_profit).sum())/(net_profit.iloc[3167:3265+1:3265-3167].sum())
    return weighted_m
def calculate_port_momthly2():
    net_profit=fdf['net_profit']
    close1=get_price(port2,startdate,enddate,'daily',['close'],panel=False)
    close2=get_price(port2,enddate,nextdate,'daily',['close'],panel=False)
    weighted_m=(((close2['close'].iloc[:]/close1['close'].iloc[:]-1)*net_profit).sum())/(net_profit.iloc[3886:4144+1:4144-3886].sum())
    return weighted_m
def calculate_port_momthly3():
    net_profit=fdf['net_profit']
    close1=get_price(port3,startdate,enddate,'daily',['close'],panel=False)
    close2=get_price(port3,enddate,nextdate,'daily',['close'],panel=False)
    weighted_m=(((close2['close'].iloc[:]/close1['close'].iloc[:]-1)*net_profit).sum())/(net_profit.iloc[4150:4158+1:4158-4150].sum())
    return weighted_m
def calculate_port_momthly4():
    net_profit=fdf['net_profit']
    close1=get_price(port4,startdate,enddate,'daily',['close'],panel=False)
    close2=get_price(port4,enddate,nextdate,'daily',['close'],panel=False)
    weighted_m=(((close2['close'].iloc[:]/close1['close'].iloc[:]-1)*net_profit).sum())/(net_profit.iloc[4240:4257+1:4257-4240].sum())
    return weighted_m

def calculate_port_momthly5():
    net_profit=fdf['net_profit']
    close1=get_price(port5,startdate,enddate,'daily',['close'],panel=False)
    close2=get_price(port5,enddate,nextdate,'daily',['close'],panel=False)
    weighted_m=(((close2['close'].iloc[:]/close1['close'].iloc[:]-1)*net_profit).sum())/(net_profit.iloc[4384:4418+1:4418-4384].sum())
    return weighted_m

#计算基准月收益
def calculate_benchmark_monthly_return(startdate, enddate, nextdate):
    close1 = get_price (['000001.XSHG'], startdate, enddate, 'daily', ['close'],panel=False )['close']
    close2 = get_price (['000001.XSHG'], enddate, nextdate, 'daily', ['close'],panel=False )['close']
    benchmark_return = (close2.iloc[:]/close1.iloc[:]-1).sum ()
    return benchmark_return
#观察5个组合在2021年9月初一个月内的收益情况(因为对股票走势的研究、预测有一定的时间滞后性,因此为9月份)

benchmark_return = calculate_benchmark_monthly_return('2021-09-01', '2021-10-01', '2021-11-01')
df['port1'] = calculate_port_momthly1()
df['port2'] = calculate_port_momthly2()
df['port3'] = calculate_port_momthly3()
df['port4'] = calculate_port_momthly4()
df['port5'] = calculate_port_momthly5()
print(Series(df))
print('benchmark_return %s'%benchmark_return)

PS;其实iwind的金融终端是更好的对于量化分析来说,奈何家境贫寒。

问题三:

问题三要求建立数学模型研究自然灾害、突发社会事件等对股票走势的影响,由于突发事件、灾害等外部环境因素对于不同业务领域的公司的股票走势的影响是不同的,而且此类外部环境因素对股票行情产生影响的时间跨度长短是无法通过简单的数学关系来表示的。经思考,得:可通过股票的大量历史数据构建BP神经网络研究外部环境因素对目标股票的影响。
首先,给出突发事件的闪现、舆情和自然灾害等外部条件的定义:
1.是股票的行情历史上极少发生的事件。
2.是对不同股票影响程度不同的事件。
明显地,不同的特殊事件对同一支股票的影响程度是不同的,同一特殊事件对于不同的股票的影响程度也是不同的。特殊事件对目标股票的影响是难以用数学模型进行诠释的。经思考,得:可以基于目标股票的大量历史数据,对选定的10支股票分别建立BP神经网络模型,研究突发事件的闪现、舆情和自然灾害等外部条件对股票行情的影响。
BP神经网络是一种多层前馈神经网络,是无需事先确定输入输出之间映射关系的数学模型,仅通过自身训练,学习某种规则,在给定输入值时得到最接近期望输出值的结果。
以中国平安(601318.XSHG)为例,2008年5月12日汶川地震对中国平安这一保险股的走势是产生了极大影响的。因为特殊事件对目标股票产生影响的持续时间的长短是难以确定的,是会受社会,公司内部等多重因素的影响的,所以视特殊事件从发生到结束这段时间的跨度为该事件对目标股票产生影响的持续时间的长短。若以突发事件开始的日期到结束的日期这段时间股票的各项常见价格指数标为“1”(正类),其他时间股票的各项常见价格指数标为“0”(负类),该问题便转化为无监督学习的二分类问题。对中国平安这一股票建立BP神经网络模型,研究特殊事件对该股走势的影响,具体如下所示:
2021年第二届“大湾区杯”粤港澳金融建模竞赛B题解题思路和部分代码_第2张图片
使用中国平安的特征因子(问题二建立的多因子选股模型中挑选出的3个因子)以及常见的价格指数的历史数据(通过聚宽量化平台获得)为输入变量,输出变量为类标签(正类1或负类0)。训练集为历史数据的70%,测试集定为历史数据的30%。使用MATLAB工具箱中的分类学习器,BP神经网络的全连接层数定为2,两层大小都为10,使用ReLU函数为激活函数,迭代限制为1000次,进行求解。
对于其他9支股票,建立模型的方法和求解过程和上述一致,在此不详细一一展开叙述。

问题四:

问题四要求综合建模分析券商研报和外界因素对证券公司股票行情的影响,通过给予券商研报对证券公司股票行情影响和外界因素对证券公司股票行情影响相同的权重,建立综合影响数学模型,对问题二提出的投资策略进行修改,提出新的投资策略。

这种问题常见的思路就是AHP分析法、熵权法等赋不同模型不同的权重,建立综合的模型。由于券商研报对证券公司股票行情的影响和外界因素对证券公司股票行情的影响的度量标准和方式是不同的,经思考,可认为:两者对证券公司股票行情走势起着同样重要的影响,将前两问的两个模型分别赋予相同权重。对10支目标股票分别建立综合影响数学模型即可。

思考:

嗯我建的模型放到股市收益率不是很好,就是买进和买入之类的操作并不够精确,我认为是我本身缺乏金融专业知识导致的,不过,单推嘛,还是有很大收获的。

你可能感兴趣的:(笔记,机器学习,数学建模)