运用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分析公募基金【量化投资】相关推荐

  1. 量化金融投资及其python应用_量化投资:用Python实现金融数据的获取与整理

    小编说:数据可以说是量化投资的根本,一切投资策略都是建立在数据基础上的.本文以优矿网为例,带领大家用Python实现金融数据的获取与整理. 本文选自<Python与量化投资:从基础到实战> ...

  2. 金融统计分析python论文_Python量化投资远程班

    2017年6月10-11,17-18日四天 讲师介绍: 王小川,同济大学管理学博士,MATLAB技术论坛管理团队核心成员,经管之家(原人大经济论坛)数据分析与挖掘课程培训Python主讲导师,证券从业 ...

  3. 数据分析常用的python包_量化投资数据分析之常用的python包(附代码)

    小伙伴们都知道python功能强大,在金融量化分析中运用广泛,python常用的数据分析包很多,下面先给大家简单列举一些(如果您刚开始学python觉得这东西很烦看不懂,那么请不要担心,直接忽视跳到第 ...

  4. 同花顺python面试_量化投资面试集锦

    2019年的秋招的尾声快到,来总结一下经历过的私募笔试和面试.一开始采取的是海投的形式,第一份是来自上海持赢投资的笔试题.二选一, NO.1熟悉现有量化回测框架的使用 对pywinauto库的使用 实 ...

  5. python量化投资必背代码-重磅!我把自己耗费两年用Python写的量化投资代码开源了!...

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU4ODcyMTI1Nw==&mid=2247483842&idx=1&sn=024de1af0 ...

  6. python股票量化交易入门到实践_量化资料学习《Python与量化投资从基础到实战》+《量化交易之路用Python做股票量化分析》+《组织与管理研究的实证方法第2版》...

    我们需要利用Python进行数据分析的指南,有大量的关于数据处理分析的应用,重点学习如何高效地利用Python解决投资策略问题,推荐学习<Python与量化投资从基础到实战>等电子资料. ...

  7. python 策略回测期货_量化投资实战教程(1)—基于backtrader的简单买入卖出策略

    都说Python可以用于量化投资,但是很多人都不知道该怎么做,甚至觉得是非常高深的知识,其实并非如此,任何人都可以在只有一点Python的基础上回测一个简单的策略. Backtrader是一个基于Py ...

  8. 【转】Python 量化投资实战教程(1) — Backtrader 教程

    都说 Python 量化投资 非常好用,但是很多人都不知道该怎么做,甚至觉得是非常高深的知识,其实并非如此,任何人都可以在只有一点Python的基础上回测一个简单的策略. Backtrader是一个基 ...

  9. python量化实战_Python与量化投资 从基础到实战.pdf

    作 者 :王小川 出版发行 : 北京:电子工业出版社 , 2018.03 ISBN号 :978-7-121-33857-1 页 数 : 408 原书定价 : 99.00 开本 : 16开 主题词 : ...

最新文章

  1. Sublime Text 3 及Package Control 安装(附上一个3103可用的Key)
  2. 看不懂代码?AI给你做翻译,说人话的那种
  3. html标签ref,HTML: param 标签
  4. js php c语言for循环,小蚂蚁学习C语言(8)——C语言for循环
  5. ie11不识别html5影片,IE11无法显示flash?IE11无法播放视频的解决方法
  6. python部分引入total值的问题_Python数据分析基础与过程综述,关键数据预处理异常点的发现与处理,python,及,流程,回顾,重点,之,值...
  7. 内存管理:Linux Memory Management:MMU、段、分页、PAE、Cache、TLB
  8. PAT 1011 A+B 和 C(C语言)
  9. 【STL源码剖析读书笔记】自己实现stack之MyStack(底层用MyList)
  10. python中reversed函数,Python3
  11. python中tqdm的用法
  12. android TTS语音播报
  13. html拷贝图片不显示,【原创软件小知识】——拷贝cad文件中光栅图片不显示的问题...
  14. java面试题--算法集锦(建议收藏)
  15. 通用mrp手机必备新手安装包
  16. freeswitch对接阿里语音识别(非mrcp方式)+简单asr空号检测
  17. 15个经典营销激励小故事
  18. 备赛全国阳光健身健美大赛训练记录(粗略)
  19. 黑苹果13.0.1驱动RTL 8125B 2.5G网卡失败故障排查
  20. 杨校老师课堂之Spring框架面试题【开发工程师面试前必看】

热门文章

  1. SAP 批次管理(批次层级--异常处理)
  2. 说说,博客,贴吧评论设计问题
  3. 手把手教你在C++中配置Gurobi
  4. 书都买回来了,必须要努力的去学习了!
  5. 高考数学数列题目解题技巧(全新的思路)
  6. python图像识别马路_使用Python和OpenCV在道路上找到车道线
  7. ubuntu 无线网卡 断网重连 教程
  8. Username for ‘https://github.com‘:
  9. 郑州大学WEB实训课程体系
  10. Oralce 函数例子