文章目录

  • 一、关于基金定投
    • 数据来源
    • 接口规范
    • 常见指数基金/股票代码
  • 二、分析目标
  • 三、代码实现
    • 1、定义获取数据、清洗数据的函数
    • 2、定义定投策略函数
    • 3、计算2019年对沪深300指数基金进行定投的收益率
    • 4、假设定投的金额是500元,每周定投一次,据此分别计算从2002年开始到2019年,每年定投沪深300指数基金的收益率并将结果可视化
    • 5、实现"慧定投"(支付宝中的智能定投策略)
  • 定义定投策略(对于每个交易日前一日的收盘价)
  • 四、可视化普通定投与智能定投策略收益率
  • 五、文末福利(完整代码)

基于Python的基金定投分析

通过获取过去10年的股市数据分析基金定投的收益率。

一、关于基金定投

基金定投,就是按照固定的频率和固定的金额,不停分批次小额买入金融市场上的基金。为什么要这么麻烦,这样做有什么好处吗?我们本次“数据分析和挖掘”的第四次作业就指数基金定投的效果来分析一下。

注:定投可以选择任何种类的基金。我们以指数基金为例,因为大部分传说中无脑定投的案例都是以指数基金的定投方式

数据来源

  • 通过API接口从网易财经上进行调取

接口规范

  • http://quotes.money.163.com/service/chddata.html?code=003833&start=19901219&end=20200228&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;VOTURNOVER;VATURNOVER

其中

  • code参数后面的7位整数代表了股票代码;比如0000001指的是上证指数。注意这串数字要分0和000001两部分看。0代表sh,1代表sz。所以0000001其实是sh000001的意思。同理,0 000300也就是sh000300 沪深300的代码。
  • start和end参数后面的8位整数代表年(xxxx)月(xx)日(xx)
  • fields选项中,TCLOSE,HIGH,LOW,TOPEN分别表示当日的收盘,最高,最低,开盘价;LCLOSE表示昨日收盘价。CHG,PCHG,VOTURNOVER,VAT分别表示涨跌额,涨跌幅,成交量,成交金额。

常见指数基金/股票代码

  • 0000300 - 沪深300
  • 0000001 - 上证指数
  • 0000016 - 上证50
  • 399005 - 中小板指
  • 399673 - 创业板50
  • 000903 - 中证100

二、分析目标

  1. 假设定投的金额是500元,每周定投一次,据此计算2019年对沪深300指数基金进行定投的收益率
  2. 假设定投的金额是500元,每周定投一次,据此分别计算从2002年开始到2019年,每年定投沪深300指数基金的收益率并将结果可视化
  3. 探索不同的定投策略。这里以支付宝的“慧定投”智能定投策略为例

注:不同的定投策略可以是改变定投周期(比如从每周定投到每月定投),改变定投金额(比如从固定金额到固定比例),设定止损或者止盈策略等等。

三、代码实现

1、定义获取数据、清洗数据的函数

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests
import warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.family']='SimHei'
plt.rcParams['axes.unicode_minus']=False
plt.rcParams['figure.figsize']=(12,8)def get_data(code,start,end):'''获取指定时间范围的股票数据:param code: 指数代码:param start: 起始日期:param end: 截止日期:return: DataFrame'''url='http://quotes.money.163.com/service/chddata.html?code={}&start={}&end={}&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;VOTURNOVER;VATURNOVER'.format(code,start,end)name=code+'_'+start+"-"+endf=open(name,'wb')f.write(requests.get(url).content)f.close()data=pd.read_csv(name,encoding='gbk')return datadef clean_data(data):'''1、将日期转换为时间序列并设置为索引2、将数据按时间序列升序排序3、删除缺失值4、将涨跌幅的单位转换为小数'''data['日期']=pd.to_datetime(data['日期'])data=data.set_index("日期")data=data.sort_index()data.drop(data[data["涨跌幅"]=="None"].index,axis=0,inplace=True)data["涨跌幅"]=data['涨跌幅'].astype('float')data['涨跌幅']/=100return data

获取沪深300的数据,并查看

df1=get_data('0000300','20190102','20191231')
df1=clean_data(df1)

2、定义定投策略函数


def invest(df1,frequence,invest_money,start_time):'''定投计算:param df1: 数据集:param frequence: 定投频率:param invest_money: 每次定投金额:param start: 定投起始日期:return (amount,invest_log): (收益数据DataFrame,定投记录dict)'''invest_log={}#每次定投的日期记录(日期:大盘指数)invest_day=start_time#每次投资的时间invest_amount=0#总投资金额profile=0#总投资收益amount=0#账户总资产profile_log=[]#总收益日志invest_amount_log=[]#账户投资金额日志amount_log=[]#总资产日志Yield=[]#收益率日志for date,quote_change,index in zip(df1.index,df1['涨跌幅'],df1['收盘价']):profile+=quote_change*amount#计算当天收益率profile_log.append(profile)#判断是否为定投日if date==invest_day:invest_amount+=invest_moneyinvest_log[invest_day]=index#记录定投当日的指数#判断7天后是否为交易日,如果不是则往后加1天直到找到交易日invest_day+=np.timedelta64(frequence,'D')flag=0while(True):if(df1[df1.index==invest_day].index==invest_day):breakelse:invest_day+=np.timedelta64(1,'D')flag+=1if(flag==100):breakinvest_amount_log.append(invest_amount)amount=invest_amount+profile#更新账户总资产amount_log.append(amount)try:Yield.append(profile/invest_amount*100)#更新收益率except:Yield.append(0)print("总投资:",invest_amount)print("总收益:",profile)print("收益率: ",profile/invest_amount*100,"%")over=pd.DataFrame({"日期":df1.index,"收益率":Yield,"账户资产":amount_log,"投资金额":invest_amount_log})over=over.set_index("日期")return over,invest_log

3、计算2019年对沪深300指数基金进行定投的收益率

frequence=7#定投频率
invest_money=500#每次定投金额
start=np.datetime64("2019-01-02")
print("2019年定投结果显示:")
res,buy=invest(df1,frequence,invest_money,start)def myplot(df1,res,buy,titlename):'''绘制定投结果图'''plt.figure()df1['收盘价'].plot(label="大盘指数")plt.scatter(buy.keys(),buy.values(),color="brown",marker=".",label="定投记录")plt.legend(loc='best')plt.ylabel("指数")plt.twinx()res['账户资产'].plot(color="red")res['投资金额'].plot(color="orange")plt.ylabel("元")plt.legend()plt.title(titlename+":{:.2f}%".format(res.tail(1)["收益率"][0]))plt.show()
titlename="2019年沪深300定投收益率"
myplot(df1,res,buy,titlename)

4、假设定投的金额是500元,每周定投一次,据此分别计算从2002年开始到2019年,每年定投沪深300指数基金的收益率并将结果可视化

df2=get_data('0000300','20020101','20191231')
df2=clean_data(df2)df2['收盘价'].plot()
plt.title("2002年-2019年沪深300指数")frequence=7#定投频率
invest_money=500#每次定投金额
print("从2002年开始定投到2019年结束的收益情况:")
start=np.datetime64("2002-01-07")
res,buy=invest(df2,frequence,invest_money,start)x=[str(i) for i in range(2002,2020)]
y=[]for year in range(2002,2020):'''每年的收益率:年末收益率-年初收益率'''each_year=res[res.index.year==year].tail(1)["收益率"][0]-res[res.index.year==year].head(1)["收益率"][0]y.append(each_year)plt.title("2002年-2019年 沪深300 年定投收益率")
plt.ylabel("收益率(%)")
plt.xlabel("年")plt.plot(x,y,label="年收益率")
plt.plot(x,[res.tail(1)["收益率"][0] for i in range(len(x))],ls="--",alpha=0.5,label="总投资收益率")
plt.plot(x,[0 for i in range(len(x))],color="gray",ls="--",alpha=0.3)
plt.xlim("2002","2019")
plt.legend()

5、实现"慧定投"(支付宝中的智能定投策略)

定义定投策略(对于每个交易日前一日的收盘价)

  • 高于均线15%以内,扣款90%
  • 高于均线15-50%,扣款80%
  • 高于均线50-100% 扣款70%
  • 高于均线 100%以上 扣款60%

  • 近10日振幅小于5%

    • 低于均线5%以内,扣款180%
    • 低于均线5-10%以内,扣款190%
    • 低于均线10-20%以内,扣款200%
    • 低于均线20-30%以内,扣款210%
    • 低于均线30-40%以内,扣款220%
    • 低于均线40%以上,扣款230%
  • 近10日振幅大于5%

    • 低于均线5%以内,扣款60%
    • 低于均线5-10%以内,扣款70%
    • 低于均线10-20%以内,扣款80%
    • 低于均线20-30%以内,扣款90%
    • 低于均线30-40%以内,扣款100%
    • 低于均线40%以上,扣款110%

所以在这个过程中我们需要定义几个函数,由于要考虑到均线与振幅的问题,所以首先需要定义均线、振幅函数,获取基金n日收益与m日振幅

def mean_days(df,days,wave):'''获取n日均线,最近m日振幅:param df: 数据集:param days: 均线天数:params wave:最近m日振幅:return average,wavelength:均线、近m日振幅'''average=[]wavelength=[]start=df.head(1).index-np.timedelta64(days+1,"D")start=start.astype('str')[0].replace("-","")#转换为字符串df4=get_data('0000300',start,'20191231')#获得原始数据前days天的数据用以求均值df4=clean_data(df4)for i in df3.index:start_date=i-np.timedelta64(days+1,"D")ave=df4[(df4.index>start_date) & (df4.index<i)]['收盘价'].mean()average.append(ave)########求振幅#######start2=df.head(1).index-np.timedelta64(wave+1,"D")start2=start2.astype('str')[0].replace("-","")#转换为字符串df5=get_data('0000300',start2,'20191231')df5=clean_data(df5)for i in df3.index:start_date=i-np.timedelta64(wave+1,"D")interval=df5[(df5.index>start_date) & (df5.index<i)]['收盘价']length=interval.max()/interval.min()-1#最大涨跌幅wavelength.append(length)return average,wavelength

智能定投策略计算收益率

def stratege(ml,wl,T_1):'''定投策略:param ml:均线:param wl:振幅:param T_1:前1日收盘价'''cal=T_1/ml-1#大于0,则高于均线if(cal>=0 and cal<0.15):return 0.9elif(cal>0.15 and cal<0.5):return 0.8elif(cal>=0.5 and cal<1):return 0.7elif(cal>=1):return 0.6elif(wl>0.05):if(cal>=-0.05 and cal<0):return 0.6elif(cal>=-0.1 and cal<-0.05):return 0.7elif(cal>=-0.2 and cal<-0.1):return 0.8elif(cal>=-0.3 and cal<-0.2):return 0.9elif(cal>=-0.4 and cal<-0.3):return 1.0elif(cal<-0.4):return 1.1else:if(cal>=-0.05 and cal<0):return 1.8elif(cal>=-0.1 and cal<-0.05):return 1.9elif(cal>=-0.2 and cal<-0.1):return 2.0elif(cal>=-0.3 and cal<-0.2):return 2.1elif(cal>=-0.4 and cal<-0.3):return 2.2elif(cal<-0.4):return 2.3

完整策略实现

def smart_invest(df1,frequence,invest_money,start_time,days,wave):'''定投计算:param df1: 数据集:param frequence: 定投频率:param invest_money: 每次定投金额:param start: 定投起始日期:param days: 参考均线天数:return (amount,invest_log): (收益数据DataFrame,定投记录dict)'''invest_log={}#每次定投的日期记录(日期:大盘指数)invest_day=start_time#每次投资的时间invest_amount=0#总投资金额profile=0#总投资收益amount=0#账户总资产profile_log=[]#总收益日志invest_amount_log=[]#账户投资金额日志amount_log=[]#总资产日志Yield=[]#收益率日志df1["均线"]=mean_days(df1,days,wave)[0]#获取均线df1["振幅"]=mean_days(df1,days,wave)[1]#获取振幅for date,quote_change,index,ml,wl in zip(df1.index,df1['涨跌幅'],df1['收盘价'],df1["均线"],df1["振幅"]):profile+=quote_change*amount#计算当天收益率profile_log.append(profile)#判断是否为定投日if date==invest_day:if(invest_day==start_time):T_1=start_timeelse:formal_day=1while(True):T_1=date-np.timedelta64(formal_day,"D")#前1天的收盘价if(T_1 in df1.index.tolist()):breakelse:formal_day+=1T_1=df1[df1.index==T_1]["收盘价"][0]rate=stratege(ml,wl,T_1)invest_amount+=invest_money*rate#定投invest_log[invest_day]=index#记录定投当日的指数#判断7天后是否为交易日,如果不是则往后加1天直到找到交易日invest_day+=np.timedelta64(frequence,'D')flag=0while(True):if(df1[df1.index==invest_day].index==invest_day):breakelse:invest_day+=np.timedelta64(1,'D')flag+=1if(flag==100):breakinvest_amount_log.append(invest_amount)amount=invest_amount+profile#更新账户总资产amount_log.append(amount)try:Yield.append(profile/invest_amount*100)#更新收益率except:Yield.append(0)print("总投资:",invest_amount)print("总收益:",profile)print("收益率: ",profile/invest_amount*100,"%")over=pd.DataFrame({"日期":df1.index,"收益率":Yield,"账户资产":amount_log,"投资金额":invest_amount_log})over=over.set_index("日期")return over,invest_log

四、可视化普通定投与智能定投策略收益率

frequence=30#定投频率
invest_money=5000#每次定投金额
start=np.datetime64("2018-01-02")
print("优化后的定投策略(参考500日均线,近5日振幅的月定投):")
res1,buy1=smart_invest(df3,frequence,invest_money,start,500,5)
print("======================================\n普通定投策略:")
res2,buy2=invest(df3,frequence,invest_money,start)
myplot(df3,res1,buy1,"2018-2019年沪深300 优化定投 收益率")
myplot(df3,res2,buy2,"2018-2019年沪深300 普通定投 收益率")


五、文末福利(完整代码)

关注以下公众号回复"0003"获取完整源码

Python数据分析——基金定投收益率分析,以及支付宝“慧定投”智能定投实现相关推荐

  1. Python数据分析初学之分析表格

    文章目录 Python数据分析初学之分析表格 任务要求 代码实现 Python数据分析初学之分析表格 任务要求 1)使用 pandas 读取文件 data.csv 中的数据 ,创建 DataFrame ...

  2. 【详解】Python数据分析第三方库分析

    Python数据分析第三方库分析 目录 Python数据分析第三方库分析 @常用库下载地址 1 Numpy 2 Matplotlib 3 Pandas 4 SciPy 5 Scikit-Learn 6 ...

  3. python数据分析的交叉分析和分组分析 -第三次笔记

    python数据分析 -第三次笔记 –1.交叉分析 –2.分组分析 1.交叉分析 交叉分析的含义是在纵向分析法和横向分析法的基础上,从交叉.立体的角度出发,由浅入深.由低级到高级的一种分析方法.这种方 ...

  4. python数据比例_#python# #数据分析# 性别比例分析

    手头有一份性别比例的样本数据,清洗后只保留了性别信息,做了一个数据分析. 数据清洗和数据统计的代码就不贴了,贴性别比例pie图和性别比例趋势图的代码. 性别比例pie图: def _plot_gend ...

  5. Python数据分析之探索性分析(多因子复合分析)

    目录 一.假设检验: 二.交叉分析 1.分析属性与属性之间关系的方法 2.透视表 三.分组与钻取: 四.相关分析 1.相关系数分析 2.熵:条件熵:互信息(熵增益):增益率:基尼系数: 3.衡量离散数 ...

  6. python数据分析之对比分析

    对比分析 概念:两个互相联系的指标进行比较 类型:绝对数比较(相减) .相对数比较(相除) 其中相对数比较分析也包括:结构分析.比例分析.动态对比分析 1.绝对数比较 a.对比的指标在量级上不能差别过 ...

  7. Python数据分析项目:分析世界五百强企业数据

    前言 嗨喽!大家好,这里是魔王~ 哪个国家的世界五百强企业数量最多? 今天带你用python来处理数据,并实现数据可视化,解决对现有数据产生的疑问. 本次代码是在 Jupyter Notebook 里 ...

  8. Python数据分析之股票分析

    股票分析 使用tushare包获取某股票的历史行情数据 输出该股票所有收盘比开盘上涨3%以上的日期 输出该股票所有开盘比前日收盘跌幅超过2%的日期 假如从2010年1月1日开始,每月第一个交易日买入1 ...

  9. python数据分析练习——姓名分析US_Baby_names_right.csv

    第一步:导入相关模块 import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt p ...

最新文章

  1. 《大数据时代》----重要理念摘抄
  2. 网页快照是什么?对SEO优化有什么作用?
  3. TP5 使用IN查询时如何限制条数
  4. 数据中心网络性能:新应用下的新需求
  5. 简单说下COALESCE这个日常使用的函数
  6. getMeasuredWidth和getWidth的区别
  7. # 异运算_小学数学运算三要点:定律、法则与顺序(解析)
  8. pandas的自带数据集_用Python和Pandas进行数据清理:检测丢失值
  9. 排除“使用主题 css 文件要求页上有标头控件。(例如 head runat=server /)”错误...
  10. docker镜像和容器的导出导入
  11. 用unity制作能量护盾(3)
  12. ITIL4定义的四大价值维度
  13. c语言打码软件官方下载,触动精灵人工打码软件
  14. 查看挂载阵列卡下的磁盘SMART
  15. python 除法符号_python的除法运算符是什么
  16. Java发送mail报错“java.util.ServiceConfigurationError: com.sun.mail.imap.IMAPProvider not a subtype”
  17. 【leetcode刷题】[简单]441. 排列硬币(arranging coins)-java
  18. 给服务器上传文件高并发,基于容器实现高并发网站
  19. GMap.NET使用过程的一些笔记
  20. php关键词替换的类(避免重复替换_保留与还原原始链接),浅析PHP关键词替换的类(避免重复替换,保留与还原原始链接)...

热门文章

  1. 分布式理论:2pc与3pc
  2. 在上传文件时限制上传文件的大小,并捕捉超过文件大小限制的异常
  3. nginx(二)服务优化与防盗链
  4. Nginx 部署前端项目dist文件
  5. ElesticSearch对接python
  6. 塞翁失马又得马,福祸循环,人生如此相似
  7. 中继器的使用方法~~
  8. Nodeway--基于node.js的轻量级前后端分离框架
  9. 5个高清视频素材网站,免费商用,建议收藏~
  10. vue 分步引导组件_引导卡组件:完整介绍