-
2022-01-14 13:57:38
请直接参照函数:
def valuetounitcumulatedvalue(data): class result(object): def __init__(self): pass result.logreturn = np.log(data / data.shift(1)) result.unitcumaltedvalue = (result.logreturn.cumsum() + 1).dropna(axis=0, how='all') return result
其实这个函数没有写的很完整,因为可能还需要考虑到日期的排序方式,但是对我自己来说够用了。
相较于df自带的,计算对数收益率满足可加性可以直接用cumsum来累加。
如果你想用df写的话,类似于:
unitcumulatedvalue = df.pct_change().cumsum() + 1
但是这样子是错误的。
更多相关内容 -
给定一个净值序列,计算年化收益、最大回撤、夏普比率
2021-03-18 18:11:23给定一个净值序列,计算年化收益、最大回撤、夏普比率给定一个净值序列,计算年化收益、最大回撤、夏普比率
数据准备:净值序列
以HS300的收盘价,作为策略的净值
获取数据准备工作
-
安装JQDdata库,JQData使用说明。
-
在聚宽申请账号,并且申请开通JQData权限。
-
Python版本: Python3.7
# 从聚宽JQData获取HS300从2015至2018年底,每个交易日的收盘价 # 导入JQData库 from jqdatasdk import * import pandas as pd # ID是申请时所填写的手机号;Password为聚宽官网登录密码 auth('18800119212','Hsh19980121') pd.set_option('display.max_rows', 10) # 获取HS300每日收盘价,时间:2015-01-01至2018-12-31 df = get_price('000300.XSHG', start_date=&#
-
-
银行:银行理财净值化转型进展如何?.pdf
2021-08-22 19:05:16银行:银行理财净值化转型进展如何?.pdf -
银行理财2020年6月报:净值型理财迎“压力测试” 标准化债权资产认定规则落地.pdf
2021-08-22 19:06:01银行理财2020年6月报:净值型理财迎“压力测试” 标准化债权资产认定规则落地.pdf -
银行理财子月报:发行数量上升,净值化转型提速.pdf
2021-08-22 18:53:28银行理财子月报:发行数量上升,净值化转型提速.pdf -
银行理财双月报:净值化转型任重道远,理财收益率平稳.pdf
2021-08-22 18:55:20银行理财双月报:净值化转型任重道远,理财收益率平稳.pdf -
理财半年报点评:理财净值化转型持续,持续看好中报行情.pdf
2021-09-01 09:01:44理财半年报点评:理财净值化转型持续,持续看好中报行情.pdf -
银行理财周报:预期收益率平稳,大行净值化进度较慢.pdf
2021-08-22 18:57:28银行理财周报:预期收益率平稳,大行净值化进度较慢.pdf -
银行行业周报:转股型资本债登场,理财净值化更进一步.pdf
2021-08-22 18:56:56银行行业周报:转股型资本债登场,理财净值化更进一步.pdf -
银行理财3月报:净值化转型任重道远,理财收益率平稳.pdf
2021-08-22 18:53:30银行理财3月报:净值化转型任重道远,理财收益率平稳.pdf -
银行理财4月报:理财收益率平稳,净值化转型加快.pdf
2021-08-22 18:51:41银行理财4月报:理财收益率平稳,净值化转型加快.pdf -
银行理财周报:理财收益率环比下降,产品净值化再提速.pdf
2021-08-02 23:54:40银行理财周报:理财收益率环比下降,产品净值化再提速.pdf -
理财净值化下,金融机构可选择哪些替代的固收公募基金.pdf
2021-12-26 06:09:28理财净值化下,金融机构可选择哪些替代的固收公募基金.pdf -
银行理财周报:理财收益率环比下降,产品净值化进程提速.pdf
2021-07-17 09:11:17银行理财周报:理财收益率环比下降,产品净值化进程提速.pdf -
银行基本面周度跟踪:理财净值化持续推进,信用风险加速释放.pdf
2021-08-22 18:56:53银行基本面周度跟踪:理财净值化持续推进,信用风险加速释放.pdf -
银行业基本面周度跟踪:理财净值化持续推进,信用风险加速释放.rar
2021-09-09 18:44:23银行业基本面周度跟踪:理财净值化持续推进,信用风险加速释放 -
银行:资管新规十月记:银行理财净值化转型进展如何?.pdf
2021-08-22 22:45:43银行:资管新规十月记:银行理财净值化转型进展如何?.pdf -
基金数据可视化运用echarts模板
2020-11-12 14:31:32基金可视化基金数据随机生成可视化运用echarts模板,加入上证指数和业绩走势,比较简单,只提供思路 -
一二线城市银发族老年人数字化生活研究报告
2021-03-19 14:00:11我国老龄化整体呈现规模大、速度快的特点。国家统计局发布数据显示,2019年末我国65岁... 新中国成立后第二次“婴儿潮”(1962年-1973年)出生的人群逐渐步入50岁+的银发生活,将会有更多 的资产高净值人群带动银发产业 -
【爬虫】爬取天天基金历史净值数据&基金收益可视化~
2021-04-18 23:44:22一部分为爬虫,根据基金代码爬取历史净值数据; 一部分为可视化,通过pyecharts绘制基金收益图表; 爬虫 这边以诺安成长混合基金为例,其他基金也一样; 接口获取 打开...前言
如需转载请先私信联系!!!
全文分为两个部分:
- 一部分为爬虫,根据基金代码爬取历史净值数据;
- 一部分为可视化,通过pyecharts绘制基金收益图表;
爬虫
这边以诺安成长混合基金为例,其他基金也一样;
接口获取
-
打开http://fundf10.eastmoney.com/jjjz_320007.html,然后F12打开控制台,找到下面窗口进行翻页操作,注意顺序不要颠倒;
-
每次翻页操作在后台就会出现一个新的请求,点击preview可以发现,请求所返回的数据便是我们需要的基金净值数据!,如下所示:
-
接着我们来看下请求的参数信息,这就很容易看出了,
fundCode
为查询的基金代码,pageIndex
为对应的页码,其他几个参数我们保持不表即可;
-
构造请求参数;
params = { 'callback': 'jQuery18308909743577296265_1618718938738', 'fundCode': 320007, 'pageIndex': 2, 'pageSize': 20, }
-
测试几次发现
headers
中必须带如下参数,Referer
为上游页面地址,不能为空,这里我们设置为http://fundf10.eastmoney.com/jjjz_320007.html
headers = { 'Host': 'api.fund.eastmoney.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', 'Referer': 'http://fundf10.eastmoney.com/jjjz_320007.html' }
-
这样基本流程就算跑通了,写个循环一页一页的去采集数据即可;
-
整个过程还是很简单的,天天基金并除了
header
的验证之外,并未做什么反爬虫措施~
完整代码
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Author : AwesomeTang # @File : crawler.py # @Version : Python 3.7 # @Time : 2021-04-18 12:17 import requests import re import json import pandas as pd fundCode = 161725 class FundCrawler: def __init__(self, fund_code: int, page_range: int = None, file_name=None): """ :param fund_code: 基金代码 :param page_range: 获取最大页码数,每页包含20天的数据 """ self.root_url = 'http://api.fund.eastmoney.com/f10/lsjz' self.fund_code = fund_code self.session = requests.session() self.page_range = page_range self.file_name = file_name if file_name else '{}.csv'.format(self.fund_code) self.headers = { 'Host': 'api.fund.eastmoney.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', 'Referer': 'http://fundf10.eastmoney.com/jjjz_%s.html' % self.fund_code, } def fount_info(self): search_url = 'https://fundsuggest.eastmoney.com/FundSearch/api/FundSearchAPI.ashx' params = { "callback": "jQuery18309325043269513131_1618730779404", "m": 1, "key": self.fund_code, } res = self.session.get(search_url, params=params ) try: content = self.content_formatter(res.text) fields = ','.join([i['TTYPENAME'] for i in content['Datas'][0]['ZTJJInfo']]) print("{:*^30}".format(self.fund_code)) print("* 基金名称:{0:{1}>10} *".format(content['Datas'][0]['NAME'], chr(12288))) print("* 基金类型:{0:{1}>10} *".format(content['Datas'][0]['FundBaseInfo']['FTYPE'], chr(12288))) print("* 基金经理:{0:{1}>10} *".format(content['Datas'][0]['FundBaseInfo']['JJJL'], chr(12288))) print("* 相关领域:{0:{1}>10} *".format(fields, chr(12288))) print("*" * 30) return True except TypeError: print('Fail to pinpoint fund code, {}, please check.'.format(self.fund_code)) @staticmethod def content_formatter(content): params = re.compile('jQuery.+?\((.*)\)') data = json.loads(params.findall(content)[0]) return data def page_data(self, page_index): params = { 'callback': 'jQuery18308909743577296265_1618718938738', 'fundCode': self.fund_code, 'pageIndex': page_index, 'pageSize': 20, } res = self.session.get(url=self.root_url, headers=self.headers, params=params) content = self.content_formatter(res.text) return content def page_iter(self): for page_index in range(self.page_range): item = self.page_data(page_index + 1) yield item def get_all(self): total_count = float('inf') page_index = 0 while page_index * 20 <= total_count: item = self.page_data(page_index + 1) page_index += 1 total_count = item['TotalCount'] yield item def run(self): if self.fount_info(): df = pd.DataFrame() if self.page_range: for data in self.page_iter(): df = df.append(data['Data']['LSJZList'], ignore_index=True) print("\r{:*^30}".format(' DOWNLOADING '), end='') else: for data in self.get_all(): df = df.append(data['Data']['LSJZList'], ignore_index=True) print("\r{:*^30}".format(' DOWNLOADING '), end='') df.to_csv(self.file_name) print("\r{:*^30}".format(' WORK DONE ')) print("{:*^30}".format(' FILE NAME ')) print("*{:^28}*".format(self.file_name)) print("*" * 30) if __name__ == "__main__": c = FundCrawler(fundCode) c.run() '''运行日志 ************320007************ * 基金名称: 诺安成长混合 * * 基金类型: 混合型 * * 基金经理: 蔡嵩松 * * 相关领域: 半导体,光刻胶 * ****************************** ********* WORK DONE ********** ********* FILE NAME ********** * 320007.csv * ****************************** '''
数据可视化
效果如下:
-
诺安成长混合:
-
招商中证白酒指数:
包含两个图表,分别表示:
- 折线图:从2020年1月1日开始投入1W本金,到目前的收益曲线;
- 柱状图:从2020年1月1日开始投入1W本金,每日的收益数据;
完整代码
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Author : AwesomeTang # @File : data_viz.py # @Version : Python 3.7 # @Time : 2021-04-18 19:22 import pandas as pd from pyecharts.charts import * from pyecharts import options as opts def load_data(file): df = pd.read_csv(file) # 转换成时间格式 df['FSRQ'] = pd.to_datetime(df['FSRQ']) # 按时间排序 df.sort_values(by=['FSRQ'], inplace=True) # 日增长率填充0 df['JZZZL'].fillna(0, inplace=True) max_date = df['FSRQ'].max() min_date = pd.datetime(2020, 7, 15) df = df[df['FSRQ'].isin(pd.date_range(start=min_date, end=max_date))] data_x, data_y_day, data_y_total = [], [], [] money = 10000 for _, row in df.iterrows(): data_x.append(pd.to_datetime(row['FSRQ']).strftime('%Y-%m-%d')) money_diff = money * (float(row['JZZZL']) / 100) money = money + money_diff # print(diff_rate, money, money_diff) data_y_day.append(round(money_diff, 2)) data_y_total.append(round(money, 0)) return data_x, data_y_day, data_y_total class DataViz: def __init__(self, file, name): self.file = file self.name = name self.bar, self.line, self.grid = self.init_char() self.data_x, self.data_y_day, self.data_y_total = load_data(file) # print(self.data_x, self.data_y_day, self.data_y_total) @staticmethod def init_char(): bar = Bar() line = Line() grid = Grid( init_opts=opts.InitOpts( theme='white', # bg_color=JsCode(bg_color_js), width='1980px', height='1200px' ) ) return bar, line, grid def bar_viz(self): self.bar.add_xaxis(self.data_x) self.bar.add_yaxis( self.name, self.data_y_day, itemstyle_opts={ "normal": { 'shadowBlur': 10, 'shadowColor': 'rgba(0, 0, 0, 0.5)', 'shadowOffsetX': 10, 'shadowOffsetY': 10, 'borderColor': 'rgb(220,220,220)', 'borderWidth': 1 } }, gap='50%', tooltip_opts=opts.TooltipOpts(is_show=True, formatter='{b}<br>当日收益:{c}元'), label_opts=opts.LabelOpts(is_show=False) ) self.bar.set_global_opts( visualmap_opts=opts.VisualMapOpts( is_show=False, is_piecewise=True, pieces=[{"max": 0, "color": 'green'}, {"min": 1, "color": 'red'}, ] ), yaxis_opts=opts.AxisOpts( name='日收益/元', type_="value", # is_scale=True, splitline_opts=opts.SplitLineOpts( is_show=True, linestyle_opts=opts.LineStyleOpts( type_='dashed')) ), xaxis_opts=opts.AxisOpts( name='日期', splitline_opts=opts.SplitLineOpts( is_show=True, linestyle_opts=opts.LineStyleOpts( type_='dashed'))), legend_opts=opts.LegendOpts(is_show=False), ) return self def line_viz(self): self.line.add_xaxis(self.data_x) self.line.add_yaxis( self.name, self.data_y_total, is_symbol_show=True, symbol='circle', symbol_size=1, is_smooth=True, linestyle_opts={'shadowBlur': 5, 'shadowColor': 'rgba(0, 0, 0, 0.5)', 'shadowOffsetY': 10, 'shadowOffsetX': 10, 'width': 2, 'curve': 0.1, }, tooltip_opts=opts.TooltipOpts(is_show=False), label_opts=opts.LabelOpts(is_show=False) ) self.line.set_global_opts( visualmap_opts=opts.VisualMapOpts( is_show=False, is_piecewise=True, pieces=[{"max": 0, "color": 'green'}, {"min": 1, "color": 'red'}, ] ), yaxis_opts=opts.AxisOpts( name='持仓/元', type_="value", is_scale=True, splitline_opts=opts.SplitLineOpts(is_show=True, linestyle_opts=opts.LineStyleOpts( type_='dashed')) ), xaxis_opts=opts.AxisOpts( name='日期', splitline_opts=opts.SplitLineOpts(is_show=True, linestyle_opts=opts.LineStyleOpts( type_='dashed'))), legend_opts=opts.LegendOpts( is_show=False ), title_opts=opts.TitleOpts( title="1W元本金日收益趋势", pos_left='center', title_textstyle_opts=opts.TextStyleOpts( color='#08A05C', font_size=20, font_weight='bold'), subtitle='{}'.format(self.name), ), graphic_opts=[ opts.GraphicGroup( graphic_item=opts.GraphicItem(id_='1', left="250px", top="250px"), children=[ opts.GraphicRect( graphic_item=opts.GraphicItem( left="center", top="center", z=1 ), graphic_shape_opts=opts.GraphicShapeOpts( width=250, height=120 ), graphic_basicstyle_opts=opts.GraphicBasicStyleOpts( # 颜色配置,这里设置为黑色,透明度为0.5 fill="rgba(0,0,0,0.5)", line_width=4, stroke="#000", ), ), opts.GraphicText( graphic_item=opts.GraphicItem( left="center", top="center", z=100 ), graphic_textstyle_opts=opts.GraphicTextStyleOpts( # 要显示的文本 text='{}\n\n截止日期:{}\n\n持有收益:{}元\n\n持有收益率:{:.2%}'.format( self.name, self.data_x[-1], self.data_y_total[-1] - 10000, self.data_y_total[-1] / 10000 - 1), font="bold 14px Microsoft YaHei", graphic_basicstyle_opts=opts.GraphicBasicStyleOpts( fill="#fff" ), ), ) ], ), ] ) self.line.set_series_opts( label_opts=opts.LabelOpts(is_show=False), markline_opts=opts.MarkLineOpts( data=[ opts.MarkLineItem(type_="min", name="最小值"), opts.MarkLineItem(type_="max", name="最大值"), ], label_opts=opts.LabelOpts(is_show=True, position='left', formatter='{b}:\n{c}元'), ), markpoint_opts=opts.MarkPointOpts( data=[ opts.MarkPointItem( name="收益", coord=[self.data_x[-1], self.data_y_total[-1]], value=int(self.data_y_total[-1]), symbol_size=[80, 50] ) ] ) ) def run(self): self.line_viz() self.bar_viz() self.grid.add( self.line, is_control_axis_index=False, grid_opts=opts.GridOpts( pos_left='7%', pos_right='7%', pos_top='10%', pos_bottom='50%') ) self.grid.add( self.bar, is_control_axis_index=False, grid_opts=opts.GridOpts( pos_left='7%', pos_right='7%', pos_top='60%', pos_bottom='5%') ) self.grid.render(self.file.replace('csv', 'html')) if __name__ == "__main__": v = DataViz(file='320007.csv', name='诺安成长混合(320007)') v.run()
- 代码比较长,如有任何问题欢迎留言,私信~~
- 欢迎三连
- 作者:AwesomeTang
- 如需转载请先私信联系!!!
-
20210131-中泰证券-银行业基本面周度跟踪:理财净值化持续推进,信用风险加速释放.pdf
2021-06-20 00:14:3420210131-中泰证券-银行业基本面周度跟踪:理财净值化持续推进,信用风险加速释放.pdf -
python实现基金定投并可视化结果(及时止损)
2021-01-20 02:26:41每周定投一次,每次定投500,分别计算从2002年开始到2019年,每年定投沪深300指数基金的收益率 5.改变定投策略,获得更好的收益(以2018和2019的平均收益率分析) 改变定投周期(三月一次定投) 改变定投金额(设置投入... -
NettyTest:净值测试
2021-05-28 11:04:21HttpNettyServerInitializer.java-管道初始化程序 DuplexStatisticsHandler.java-统计信息收集处理程序 RequestHandler.java-处理Hello World并重定向 尚不涉及其他两个类: ChannelSpeedCheckHandler.java-处理... -
银行业理财产品专题研究之六:2021Q1银行理财回顾及展望,净值化初结果实,产品线多元布局.rar
2021-09-15 21:44:18银行业理财产品专题研究之六:2021Q1银行理财回顾及展望,净值化初结果实,产品线多元布局.rar -
国外程序员刷题-Personal-Finance-Net-Worth-Tracker:个人理财(净值追踪器)财富管理电子表格
2021-07-01 13:06:30国外程序员刷题个人理财(净值追踪)电子表格 一个简单易用的社区驱动的高级电子...,跟踪资产和负债,可视化趋势和增长/损失。 LA - 流动资产(现金及等价物) A - 资产(您拥有的东西) S&S - 股票和股票(您拥有的 -
银行业理财产品专题研究之六:2021Q1银行理财回顾及展望,净值化初结果实,产品线多元布局(26页).pdf
2022-02-10 14:00:54银行业理财产品专题研究之六:2021Q1银行理财回顾及展望,净值化初结果实,产品线多元布局(26页).pdf -
pandas_计算年化收益率
2022-01-20 14:44:31目录 一、当数据为净值,求年化收益率 二、当数据为收盘价,求年化收益率 一、当数据为净值,求年化收益率 前置: 文章中用到的数据 链接:https://pan.baidu.com/s/1rKLM45dq_xIKxcI54Nq0qg 提取码:c298 公式: ...目录
一、当数据为净值,求年化收益率
前置:
文章中用到的数据
链接:https://pan.baidu.com/s/1rKLM45dq_xIKxcI54Nq0qg
提取码:c298公式:
计算过程(jupyter notebook):
import pandas as pd df = pd.read_csv('./temptemp.csv',encoding='utf-8') df['o_date'] = df['date'] df['o_date'] = pd.to_datetime(df['o_date']) df.dropna(inplace=True) df.sort_values(by='o_date', ascending=True, inplace=True) df.head()
# value值从1开始,每一日的value是当日的净值 # 对应到公式,第一行的value为初始净值,最后一行的value为最终净值 first_one = df.iloc[0] last_one = df.iloc[-1] annual_profilt = pow(last_one['value']/first_one['value'],250/len(df))-1 annual_profilt
二、当数据为收盘价,求年化收益率
推导:
设,
1. 周期为p,例如p可以是日、周、月、季度等,对应的就是日收益率、周收益率、月收益率、季度收益率等;数据个数为N
2. 每期收益率为Rp,每期平均收益率为
,年化平均收益率为
3. 对应周期p,一年有m个周期p,例如:p为日,m为252;p为周,m为52;p为月,m为12等
求,
1. 每期平均收益率
2. 年化收益率
代码:
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline df_aapl = pd.read_csv('AAPL.csv',encoding='utf-8') df_aapl.head()
df_aapl['ret'] = df_aapl['Close'].pct_change() df_aapl.head()
df_aapl['ret'].plot(figsize=(8,4))
# 计算日平均收益率 # prod() 将所有数值乘起来 r_daily_mean = ((1+df_aapl['ret']).prod())**(1/df_aapl.shape[0])-1 r_daily_mean # out: 0.0006941719590121131 # 计算年收益率 annual_rets = (1+r_daily_mean)**252-1 annual_rets # out: 0.19109213356890775 # 适用不同周期收益率计算年化收益率函数 def annualize_rets(returns,n_periods): ''' 给定一系列的收益率和期数,算出年化收益率 ''' # 每一期的平均收益 r_periodic_mean = ((1+returns).prod())**(1/returns.shape[0])-1 return (1+r_periodic_mean)**n_periods-1 annualize_rets(df_aapl['ret'],252) # out: 0.19109213356890775
-
pandas计算年化收益波动率
2022-01-20 14:56:17年化收益波动率公式可以转换为【标准差的平方*250,再取平方根】 计算过程(jupyter notebook): import pandas as pd import math df = pd.read_csv('temptemp.csv',encoding='utf-8') df['o_dat..