运用Python分析公募基金【量化投资】
运用Python分析公募基金
1、背景
学校财富管理课程的期末论文是分析中国各种投资标的的收益,笔者分配到的研究的细分类别为:通过大集合转公募基金的方式,成立的公募基金的收益分析。Python在量化投资,尤其是投资的分析、策略回测等方面有着广泛的运用,所以笔者结合在政胤老师课程中学习的知识,运用Python对基金的收益进行分析。
2、数据来源
“巧妇难为无米之炊”,寻找高质量的数据是分析的第一步。本文的数据来自于Wind客户端。数据分为两个:
链接:https://pan.baidu.com/s/1JzJWxM9CyxTotldu5BjbjA 提取码:clki
3、数据分析
3.1 导入数据
def day_data(self):day_data = pd.read_csv(root_path+'/data/大集合转公募基金复权净值day.CSV', encoding='gbk')day_data.rename(columns={'Unnamed: 0': '交易日期'}, inplace=True)day_data['交易日期'] = pd.to_datetime(day_data['交易日期'])#day_rtn.set_index('交易日期', inplace=True)day_data.dropna(axis=1, how='any', inplace=True)return day_datadef index_day_data(self):index_day_rtn = pd.read_csv(root_path+'/data/中国基金加权指数day.csv',encoding='gbk')index_day_rtn.rename(columns={'Unnamed: 0': '交易日期'}, inplace=True)index_day_rtn['交易日期'] = pd.to_datetime(index_day_rtn['交易日期'])index_day_rtn['中国基金加权总指数'] = index_day_rtn['中国基金加权总指数'].pct_change()return index_day_rtn
在导入数据时,我们发现有许多缺失值,这是因为大部分大集合在2021年才转为公募基金,所以仅有几个月的收益。我们在此处采取最简单的数据清洗方式:将含有缺失值的基金删除。
这是整理后的数据:
3.2数据信息提取
观察数据,发现这些公募基金的名字既长又复杂,分析的时候一个一个输入名字肯定非常费时间。通过观察发现,这些基金的名字有个特点:基金名字的前两个或多个字,为基金公司的名字。如:海通的基金就命名为:海通量化价值精选一年持有B、海通海升六个月持有A等。
那么我们运用正则表达式,实现输入证券资管的名称,就得到其旗下的公募基金的名称。
def get_col_name(self):day_data = self.day_data()# 匹配正则表达式pattern = re.compile('^%s'% self.company)col_name = day_data.columns.tolist()choose_name = []for name in col_name:if pattern.match(name):choose_name.append(name)print(choose_name)return choose_namedef col_num(self):choose_name = self.get_col_name()num = len(choose_name)# print(num)return num
3.3 指数信息和基金信息按日期合并
def choose_data(self):choose_name = self.get_col_name()day_data = self.day_data()day_data = day_data[['交易日期', choose_name[self.fund_num]]]day_data[choose_name[self.fund_num]] = day_data[choose_name[self.fund_num]].pct_change()day_rtn = day_data# 和指数信息合并index_day_rtn = self.index_day_data()equity_day = pd.merge(day_rtn, index_day_rtn, on='交易日期', how='left' )equity_day.dropna(axis=0, how='any', inplace=True)equity_day.rename(columns={choose_name[self.fund_num]: '涨跌幅', '中国基金加权总指数': '指数涨跌幅'}, inplace=True)return equity_day
此处计算基金收益时运用了dataframe.pct_change()函数(Pandas dataframe.pct_change()函数计算当前元素与之前元素之间的百分比变化。默认情况下,此函数计算前一行的百分比变化)。
此处我们使用的是环比增长,假如想用对数收益率,则不可以使用dataframe.pct_change()函数。
3.4画收益率曲线
为了能够在以后的研究中,方便调用绘画收益率曲线的函数,我们新建一个专门存放自建函数的文档,将函数保存。
# ===绘制收益率曲线
# 绘制策略曲线
def draw_equity_curve(df, data_dict, time=None, pic_size=[16, 9], dpi=72, font_size=25, save_path='fig.jpg'):plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# plt.style.use('dark_background')plt.figure(figsize=(pic_size[0], pic_size[1]), dpi=dpi)plt.xticks(fontsize=font_size)plt.yticks(fontsize=font_size)for key in data_dict:if time:plt.plot(df[time], df[data_dict[key]], label=key)else:plt.plot(df.index, df[data_dict[key]], label=key)plt.legend(fontsize=font_size)plt.grid()#plt.show(plt.savefig(save_path)
在主程序中调用绘画收益率曲线的函数:
def yield_curve(self):equity = self.choose_data()equity['equity_curve'] = (equity['涨跌幅'] + 1).cumprod()equity['benchmark'] = (equity['指数涨跌幅'] + 1).cumprod()equity = equity[['交易日期', 'equity_curve', 'benchmark', '涨跌幅', '指数涨跌幅']]return equitydef draw_curve(self, save_path = r'fig.jpg'):choose_name = self.get_col_name()equity = self.yield_curve()equity = equity.reset_index(drop=True)equity['交易日期'] = pd.to_datetime(equity['交易日期'])draw_equity_curve(equity, time='交易日期', data_dict={choose_name[self.fund_num]: 'equity_curve', '中国基金加权总指数': 'benchmark'},save_path=save_path)
3.5 评价指标
对于基金的收益,仅仅看收益率曲线,获得的评价较为主观,要客观比较收益的好坏,还要借助指标,比如:年化收益率、最大回撤等,更加复杂的还有夏普比率、Jensen指数等,需要的评价指标加入一下自定义的函数strategy_evaluate()即可。
# 计算策略评价指标
def strategy_evaluate(equity):# ===新建一个dataframe保存回测指标results = pd.DataFrame()# ===计算累积净值results.loc[0, '累积净值'] = round(equity['equity_curve'].iloc[-1], 2)# ===计算年化收益annual_return = (equity['equity_curve'].iloc[-1]) ** ('1 days 00:00:00' / (equity['交易日期'].iloc[-1] - equity['交易日期'].iloc[0]) * 365) - 1results.loc[0, '年化收益'] = str(round(annual_return * 100, 2)) + '%'# 计算当日之前的资金曲线的最高点equity['max2here'] = equity['equity_curve'].expanding().max()# 计算到历史最高值到当日的跌幅,drowdwonequity['dd2here'] = equity['equity_curve'] / equity['max2here'] - 1# 计算最大回撤,以及最大回撤结束时间end_date, max_draw_down = tuple(equity.sort_values(by=['dd2here']).iloc[0][['交易日期', 'dd2here']])# 计算最大回撤开始时间start_date = equity[equity['交易日期'] <= end_date].sort_values(by='equity_curve', ascending=False).iloc[0]['交易日期']# 将无关的变量删除equity.drop(['max2here', 'dd2here'], axis=1, inplace=True)results.loc[0, '最大回撤'] = format(max_draw_down, '.2%')results.loc[0, '最大回撤开始时间'] = str(start_date)results.loc[0, '最大回撤结束时间'] = str(end_date)return results.T
在主程序中调用业绩评价函数
def evaluate(self):equity = self.yield_curve()choose_name = self.get_col_name()# ===计算策略评价指标rtn_data= strategy_evaluate(equity)rtn_data.rename(columns={0: choose_name[self.fund_num]}, inplace=True)#print(rtn_data)return rtn_data
3.6运行程序
在运行程序前,要在目录里面建好保存收益率曲线和收益率评价的文件夹,如图所示:
在company_name处输入基金公司的简称,num即返回基金公司下的基金数量,程序自动遍历其旗下基金,并将其收益曲线图存入chart,将其收益评价指标合并后存入sheet。
if __name__ == '__main__':company_name = '光大'analyse = Analyse(company=company_name, fund_num = 0)num = analyse.col_num()df_ret_analyse = pd.DataFrame()for i in range(num):name = analyse.get_col_name()[i]try:analyse = Analyse(company=company_name, fund_num=i)analyse.draw_curve(save_path = root_path + r'/result\chart/%s.jpg' % name)df = analyse.evaluate()df_ret_analyse = pd.concat([df_ret_analyse, df], axis=1)except:print(name + '数据错误')print(df_ret_analyse)df_ret_analyse.to_csv(root_path + f'/result\sheet\{company_name}retns.csv')
4、运行效果展示
在company_name处输入'光大',查看光大资管的公募基金收益情况。运行后,收益率曲线已经全部保存至/result/chart
点开其中一个查看:
收益指标则保存到了/result/sheet下:
5、完整代码
5.1 函数
import os
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np# ===获取项目根目录
_ = os.path.abspath(os.path.dirname(__file__)) # 返回当前文件路径
root_path = os.path.abspath(os.path.join(_, '..')) # 返回根目录文件夹# ===绘制收益率曲线
# 绘制策略曲线
def draw_equity_curve(df, data_dict, time=None, pic_size=[16, 9], dpi=72, font_size=25, save_path='fig.jpg'):plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# plt.style.use('dark_background')plt.figure(figsize=(pic_size[0], pic_size[1]), dpi=dpi)plt.xticks(fontsize=font_size)plt.yticks(fontsize=font_size)for key in data_dict:if time:plt.plot(df[time], df[data_dict[key]], label=key)else:plt.plot(df.index, df[data_dict[key]], label=key)plt.legend(fontsize=font_size)plt.grid()#plt.show(plt.savefig(save_path)# 计算策略评价指标
def strategy_evaluate(equity):# ===新建一个dataframe保存回测指标results = pd.DataFrame()# ===计算累积净值results.loc[0, '累积净值'] = round(equity['equity_curve'].iloc[-1], 2)# ===计算年化收益annual_return = (equity['equity_curve'].iloc[-1]) ** ('1 days 00:00:00' / (equity['交易日期'].iloc[-1] - equity['交易日期'].iloc[0]) * 365) - 1results.loc[0, '年化收益'] = str(round(annual_return * 100, 2)) + '%'# 计算当日之前的资金曲线的最高点equity['max2here'] = equity['equity_curve'].expanding().max()# 计算到历史最高值到当日的跌幅,drowdwonequity['dd2here'] = equity['equity_curve'] / equity['max2here'] - 1# 计算最大回撤,以及最大回撤结束时间end_date, max_draw_down = tuple(equity.sort_values(by=['dd2here']).iloc[0][['交易日期', 'dd2here']])# 计算最大回撤开始时间start_date = equity[equity['交易日期'] <= end_date].sort_values(by='equity_curve', ascending=False).iloc[0]['交易日期']# 将无关的变量删除equity.drop(['max2here', 'dd2here'], axis=1, inplace=True)results.loc[0, '最大回撤'] = format(max_draw_down, '.2%')results.loc[0, '最大回撤开始时间'] = str(start_date)results.loc[0, '最大回撤结束时间'] = str(end_date)return results.T
5.2主程序
import pandas as pd
import re
from 基金收益分析.func.myfunc import *
class Analyse(object):def __init__(self, company='海通', fund_num = 0):self.company = companyself.fund_num = fund_numpassdef day_data(self):day_data = pd.read_csv(root_path+'/data/大集合转公募基金复权净值day.CSV', encoding='gbk')day_data.rename(columns={'Unnamed: 0': '交易日期'}, inplace=True)day_data['交易日期'] = pd.to_datetime(day_data['交易日期'])#day_rtn.set_index('交易日期', inplace=True)day_data.dropna(axis=1, how='any', inplace=True)return day_datadef index_day_data(self):index_day_rtn = pd.read_csv(root_path+'/data/中国基金加权指数day.csv',encoding='gbk')index_day_rtn.rename(columns={'Unnamed: 0': '交易日期'}, inplace=True)index_day_rtn['交易日期'] = pd.to_datetime(index_day_rtn['交易日期'])index_day_rtn['中国基金加权总指数'] = index_day_rtn['中国基金加权总指数'].pct_change()return index_day_rtndef get_col_name(self):day_data = self.day_data()# 匹配正则表达式pattern = re.compile('^%s'% self.company)col_name = day_data.columns.tolist()choose_name = []for name in col_name:if pattern.match(name):choose_name.append(name)print(choose_name)return choose_namedef col_num(self):choose_name = self.get_col_name()num = len(choose_name)# print(num)return numdef choose_data(self):choose_name = self.get_col_name()day_data = self.day_data()day_data = day_data[['交易日期', choose_name[self.fund_num]]]day_data[choose_name[self.fund_num]] = day_data[choose_name[self.fund_num]].pct_change()day_rtn = day_data# 和指数信息合并index_day_rtn = self.index_day_data()equity_day = pd.merge(day_rtn, index_day_rtn, on='交易日期', how='left' )equity_day.dropna(axis=0, how='any', inplace=True)equity_day.rename(columns={choose_name[self.fund_num]: '涨跌幅', '中国基金加权总指数': '指数涨跌幅'}, inplace=True)return equity_daydef yield_curve(self):equity = self.choose_data()equity['equity_curve'] = (equity['涨跌幅'] + 1).cumprod()equity['benchmark'] = (equity['指数涨跌幅'] + 1).cumprod()equity = equity[['交易日期', 'equity_curve', 'benchmark', '涨跌幅', '指数涨跌幅']]return equitydef draw_curve(self, save_path = r'fig.jpg'):choose_name = self.get_col_name()equity = self.yield_curve()equity = equity.reset_index(drop=True)equity['交易日期'] = pd.to_datetime(equity['交易日期'])draw_equity_curve(equity, time='交易日期', data_dict={choose_name[self.fund_num]: 'equity_curve', '中国基金加权总指数': 'benchmark'},save_path=save_path)def evaluate(self):equity = self.yield_curve()choose_name = self.get_col_name()# ===计算策略评价指标rtn_data= strategy_evaluate(equity)rtn_data.rename(columns={0: choose_name[self.fund_num]}, inplace=True)#print(rtn_data)return rtn_dataif __name__ == '__main__':company_name = '光大'analyse = Analyse(company=company_name, fund_num = 0)num = analyse.col_num()df_ret_analyse = pd.DataFrame()for i in range(num):name = analyse.get_col_name()[i]try:analyse = Analyse(company=company_name, fund_num=i)analyse.draw_curve(save_path = root_path + r'/result\chart/%s.jpg' % name)df = analyse.evaluate()df_ret_analyse = pd.concat([df_ret_analyse, df], axis=1)except:print(name + '数据错误')print(df_ret_analyse)df_ret_analyse.to_csv(root_path + f'/result\sheet\{company_name}retns.csv')
6、结语
此处的分析作为分析的一个框架,可以添加更多的有趣的研究内容,比如:对基金的收益数据可以计算其期望,方差,峰度,偏度等指标,对收益率也可以计算夏普比率等指标。可以更加深入的分析基金的收益的变动。
最后强烈推荐。政胤老师的python课程,科班程序员出生的帅帅老师,代码写的非常规范,初学者可以少走弯路。并且政胤老师的答疑非常及时,仔细回复每个问题,笔者每次遇到网上查询不到答案的问题时,都会马上请教政胤老师,节省了许多自己debug的时间!(友情推送)
总之,无论是初学者从头学习,还是老手查漏补缺,找一位专家答疑,政胤的课程都物超所值。
运用Python分析公募基金【量化投资】相关推荐
- 量化金融投资及其python应用_量化投资:用Python实现金融数据的获取与整理
小编说:数据可以说是量化投资的根本,一切投资策略都是建立在数据基础上的.本文以优矿网为例,带领大家用Python实现金融数据的获取与整理. 本文选自<Python与量化投资:从基础到实战> ...
- 金融统计分析python论文_Python量化投资远程班
2017年6月10-11,17-18日四天 讲师介绍: 王小川,同济大学管理学博士,MATLAB技术论坛管理团队核心成员,经管之家(原人大经济论坛)数据分析与挖掘课程培训Python主讲导师,证券从业 ...
- 数据分析常用的python包_量化投资数据分析之常用的python包(附代码)
小伙伴们都知道python功能强大,在金融量化分析中运用广泛,python常用的数据分析包很多,下面先给大家简单列举一些(如果您刚开始学python觉得这东西很烦看不懂,那么请不要担心,直接忽视跳到第 ...
- 同花顺python面试_量化投资面试集锦
2019年的秋招的尾声快到,来总结一下经历过的私募笔试和面试.一开始采取的是海投的形式,第一份是来自上海持赢投资的笔试题.二选一, NO.1熟悉现有量化回测框架的使用 对pywinauto库的使用 实 ...
- python量化投资必背代码-重磅!我把自己耗费两年用Python写的量化投资代码开源了!...
原文地址:https://mp.weixin.qq.com/s?__biz=MzU4ODcyMTI1Nw==&mid=2247483842&idx=1&sn=024de1af0 ...
- python股票量化交易入门到实践_量化资料学习《Python与量化投资从基础到实战》+《量化交易之路用Python做股票量化分析》+《组织与管理研究的实证方法第2版》...
我们需要利用Python进行数据分析的指南,有大量的关于数据处理分析的应用,重点学习如何高效地利用Python解决投资策略问题,推荐学习<Python与量化投资从基础到实战>等电子资料. ...
- python 策略回测期货_量化投资实战教程(1)—基于backtrader的简单买入卖出策略
都说Python可以用于量化投资,但是很多人都不知道该怎么做,甚至觉得是非常高深的知识,其实并非如此,任何人都可以在只有一点Python的基础上回测一个简单的策略. Backtrader是一个基于Py ...
- 【转】Python 量化投资实战教程(1) — Backtrader 教程
都说 Python 量化投资 非常好用,但是很多人都不知道该怎么做,甚至觉得是非常高深的知识,其实并非如此,任何人都可以在只有一点Python的基础上回测一个简单的策略. Backtrader是一个基 ...
- python量化实战_Python与量化投资 从基础到实战.pdf
作 者 :王小川 出版发行 : 北京:电子工业出版社 , 2018.03 ISBN号 :978-7-121-33857-1 页 数 : 408 原书定价 : 99.00 开本 : 16开 主题词 : ...
最新文章
- Sublime Text 3 及Package Control 安装(附上一个3103可用的Key)
- 看不懂代码?AI给你做翻译,说人话的那种
- html标签ref,HTML: param 标签
- js php c语言for循环,小蚂蚁学习C语言(8)——C语言for循环
- ie11不识别html5影片,IE11无法显示flash?IE11无法播放视频的解决方法
- python部分引入total值的问题_Python数据分析基础与过程综述,关键数据预处理异常点的发现与处理,python,及,流程,回顾,重点,之,值...
- 内存管理:Linux Memory Management:MMU、段、分页、PAE、Cache、TLB
- PAT 1011 A+B 和 C(C语言)
- 【STL源码剖析读书笔记】自己实现stack之MyStack(底层用MyList)
- python中reversed函数,Python3
- python中tqdm的用法
- android TTS语音播报
- html拷贝图片不显示,【原创软件小知识】——拷贝cad文件中光栅图片不显示的问题...
- java面试题--算法集锦(建议收藏)
- 通用mrp手机必备新手安装包
- freeswitch对接阿里语音识别(非mrcp方式)+简单asr空号检测
- 15个经典营销激励小故事
- 备赛全国阳光健身健美大赛训练记录(粗略)
- 黑苹果13.0.1驱动RTL 8125B 2.5G网卡失败故障排查
- 杨校老师课堂之Spring框架面试题【开发工程师面试前必看】