最近在分析基金的相关数据,曾一度为找不到基金数据而发愁。目前我常用的数据平台有两个,一个是Tushare平台,但是我的积分不够,因此无法调取基金数据。另一个是优矿平台,但是优矿平台不能在本地调取数据,只能在优矿平台上面调取,然后保存到本地。
后来在网上发现了天天基金的数据接口,该接口返回的是文本数据,需要对原始数据进一步处理才可以使用。网上许多大佬都只是给了调用链接,并没有进一步分享数据处理的步骤。在这里,分享一下我的数据处理步骤,以方便大家直接调用基金数据。
1、当前基金净值获取
001186为基金代码,想要调取其他基金数据,替换掉该代码即可;
?rt=1463558676006为时间戳,避免浏览器缓存数据,其实没有这一部分也可以。
在浏览器中输入上面的数据接口,可以得到下面的返回结果:
jsonpgz({"fundcode":"001186","name":"富国文体健康股票","jzrq":"2022-09-20","dwjz":"1.9300","gsz":"1.9187","gszzl":"-0.58","gztime":"2022-09-21 15:00"});
fundcode | name | jzrq | dwjz | gsz | gszzl | gztime |
基金代码 | 基金名称 | 净值日期 | 单位净值 | 估计净值 | 估计涨幅 | 估计时间 |
上面返回的数据是文本数据,我们无法进行分析,因此需要进行数据处理工作,将文本字符转化为字典、dataframe等格式的数据。
通过观察文本,我们可以看到jsonpgz()里面是一窜符合字典格式的文本,因此我们可以通过json,将该文本转换成字典格式,下面是具体的代码:
import requests
import pandas as pd
import json
import re
import time
def realtmfundinfo(fundcode):
'''
Parameters
----------
fundcode : str
基金代码.
Returns
-------
fund_info : dict
返回基金最近一个交易日的单位净值(dwjz)、基金名称(name)、净值日期(jzrq)、估计净值(gsz)、估计增长率%(gszzl)、估计日期(gztime).
'''
fund_id=fundcode
real_time_url=str("http://fundgz.1234567.com.cn/js/"+fund_id+".js?rt=1463558676006")
#?rt=1463558676006为时间戳,不写该部分也可以
org_content = requests.get(real_time_url)#向网站发起请求
fund_info = org_content.text#获取网站返回的文本,即上文中的文本字符串
fund_info = re.findall(r"\{.+\}", fund_info)#运用正则表达式获取除去jsonpgz()之外的文本数据,即jsonpgz()中的文本
fund_info = json.loads(fund_info[0])#使用json方法,将该字符串转化为字典格式
return fund_info
fund_info = realtmfundinfo("001186")
print(type(fund_info),fund_info)
看一下输出结果:
<class 'dict'> {'fundcode': '001186', 'name': '富国文体健康股票A', 'jzrq': '2022-09-20', 'dwjz': '1.9300', 'gsz': '1.9187', 'gszzl': '-0.58', 'gztime': '2022-09-21 15:00'}
变成了我们期望的字典格式。
2、历史基金净值获取
001186为基金代码,想要调取其他基金数据,替换掉该代码即可;
?v=20160518155842为时间戳,避免浏览器缓存数据,其实没有这一部分也可以。
在浏览器中输入上面的数据接口,便可以得到该基金的申购费率、持仓股票、历史单位净值、历史累计净值等多个信息,由于返回的数据较多,这里就不一一列明。有兴趣的,可以点进该链接查看,数据有中文备注。
下面直接看文本处理代码:
def htrfundinfo(fundcode):
'''
Parameters
----------
fundcode : str
基金代码.
Returns
-------
fund_nav : DataFrame
返回基金的净值日期(date)、单位净值(nav)、累计净值(cumnav)、净值回报率(equityReturn)、每份派送金(unitMoney).
'''
fund_id = fundcode
history_tmurl="http://fund.eastmoney.com/pingzhongdata/"+fund_id+".js?v=20160518155842"
#?v=20160518155842为时间戳,避免浏览器缓存
org_content = requests.get(history_tmurl)#向网站发起请求
fund_info = org_content.text#获取网站返回的文本,即我们在浏览器中看到的全部文本数据
temp_nav = re.findall(r"Data_netWorthTrend\s\=\s(\[\{.+\}\]);\/\*累计净值走势\*\/", fund_info)[0]#运用正则表达式,提取单位净值
temp_nav = json.loads(temp_nav)#将文本数据,转化为字典格式
temp_nav = pd.DataFrame(temp_nav)#将字典转化为dataframe格式
temp_nav.rename(columns= {"x": "date", "y":"nav"}, inplace=True)#修改列名称,x修改为date,y修改为nav
n = len(temp_nav["date"])
for i in range(n):
temp_nav["date"][i] = time.strftime('%Y-%m-%d',time.localtime(temp_nav["date"][i]/1000.))#因为返回的时间是个时间戳,所以需要将其转化为正常的时间
temp_nav=temp_nav.set_index('date')#将时间设置为索引
temp_cumnav = re.findall(r"Data_ACWorthTrend\s\=\s(\[.+\]);\/\*累计收益率走势\*\/", fund_info)[0]#运用正则表达式,提取累计净值
temp_cumnav = eval(temp_cumnav)#累计净值的文本不是字典格式,是list格式,因此使用eval函数,将文本转化为list
temp_cumnav = pd.DataFrame(temp_cumnav)#将list转化为dataframe
temp_cumnav.rename(columns= {0: "date", 1:"cumnav"}, inplace=True)#从新修改列名
m = len(temp_cumnav["date"])
for i in range(m):
temp_cumnav["date"][i] = time.strftime('%Y-%m-%d',time.localtime(temp_cumnav["date"][i]/1000.))#因为返回的时间是个时间戳,所以需要将其转化为正常的时间
temp_cumnav = temp_cumnav.set_index('date')#将时间设置为索引
fund_nav = pd.concat([temp_nav, temp_cumnav],axis=1,join="inner")#将两个dataframe表格按照index进行合并
return fund_nav
fund_info = htrfundinfo("001186")
print(type(fund_info))
print(fund_info.head())
看一下输出结果:
<class 'pandas.core.frame.DataFrame'>
nav equityReturn unitMoney cumnav
date
2015-05-06 1.000 0.0 1.000
2015-05-08 1.004 0.0 1.004
2015-05-15 1.021 0.0 1.021
2015-05-22 1.078 0.0 1.078
2015-05-29 1.112 0.0 1.112
变成了我们想要的dataframe数据格式。
3、基金名称列表获取
在浏览器中输入上面的数据接口,就可以得到所有基金的基金代码、基金名称、基金类型这些信息。
下面是文本处理代码:
def getfundlist():
'''
Returns
-------
fund_list : DataFrame
所有基金列表.
'''
list_url="http://fund.eastmoney.com/js/fundcode_search.js"
org_content = requests.get(list_url)#向网站发起请求
temp_list = org_content.text#获取请求结构,即我们在浏览器中观看到的文本数据
temp_list = re.findall(r"\[.+\]",temp_list)[0]#运用正则表达式提取所需数据
temp_list = eval(temp_list)#因为该文本是list格式,所有要用eval函数
fund_list = pd.DataFrame(temp_list)#转化为dataframe格式
fund_list.rename(columns= {0: "fundcode", 1:"jiancheng",2:"name",3:"type",4:"pingyinquangcheng"}, inplace=True)#重新命名列名
fund_list = fund_list.set_index("fundcode")#设置基金代码作为索引
return fund_list
fund_info = getfundlist()
print(type(fund_info))
print(fund_info.head())
查看返回结果:
<class 'pandas.core.frame.DataFrame'>
jiancheng name type pingyinquangcheng
fundcode
000001 HXCZHH 华夏成长混合 混合型-灵活 HUAXIACHENGZHANGHUNHE
000002 HXCZHH 华夏成长混合(后端) 混合型-灵活 HUAXIACHENGZHANGHUNHE
000003 ZHKZZZQA 中海可转债债券A 债券型-可转债 ZHONGHAIKEZHUANZHAIZHAIQUANA
000004 ZHKZZZQC 中海可转债债券C 债券型-可转债 ZHONGHAIKEZHUANZHAIZHAIQUANC
000005 JSZQXYDQZQ 嘉实增强信用定期债券 债券型-长债 JIASHIZENGQIANGXINYONGDINGQIZHAIQUAN
变成了我们想要的dataframe数据格式。
4、文件打包
我将上述文件保存为了.py格式的文本,大家可以将该文本放入到代码文件夹中,然后通过import
的方式直接调用,例如:
import fund_api as fa
fundlist = fa.getfundlist()
print(fundlist.head())
查看一下输出结果:
jiancheng name type pingyinquangcheng
fundcode
000001 HXCZHH 华夏成长混合 混合型-灵活 HUAXIACHENGZHANGHUNHE
000002 HXCZHH 华夏成长混合(后端) 混合型-灵活 HUAXIACHENGZHANGHUNHE
000003 ZHKZZZQA 中海可转债债券A 债券型-可转债 ZHONGHAIKEZHUANZHAIZHAIQUANA
000004 ZHKZZZQC 中海可转债债券C 债券型-可转债 ZHONGHAIKEZHUANZHAIZHAIQUANC
000005 JSZQXYDQZQ 嘉实增强信用定期债券 债券型-长债 JIASHIZENGQIANGXINYONGDINGQIZHAIQUAN
可以正常调用。