首頁 > QQ空間 > QQ空間日志 > 用Python抓取天天基金網基金歷史凈值數據

用Python抓取天天基金網基金歷史凈值數據

時間:2019-11-27 09:27 作者:QQ地帶 我要評論

玩基金的朋友應該都深有體會,2018是相當慘淡的一年,尤其下半年,能夠保本就不錯了。2019迎來了開門紅,從2月11日到14日,連續四個交易日整體翻紅,“逢九必漲”,2019是不是可以有些期待呢?
“天天基金”網站可以查詢基金歷史凈值信息,這里利用網站提供的數據接口,實現基金凈值查詢,并做一些簡單的分析。數據是否準確,分析是否到位,不care,就是做一個簡單的Python實現。
Python獲取基金數據
以下鏈接可以獲取基金數據:http://fund.eastmoney.com/f10/F10DataApi.aspx
提供適當參數,即可獲取指定基金在指定日期段內的凈值數據,例如:
http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=110022&page=1&sdate=2019-01-01&edate=2019-02-13&per=20
以上提供了代碼為110022的基金(易方達消費行業)在2019年1月1日到2月13日之間的基金凈值數據。如下圖:
 
 
 
 
 
 
鏈接中的各參數含義簡單說明:
 
code:指明基金代碼;
sdate:數據開始日期;
edate:數據結束日期;
per:指定每頁顯示的條數,如果不指定該參數,則默認值為10,如果指定該參數值在1-49之間,則每頁條數按照指定參數值顯示,如果指定該值大于等于50,則每頁顯示20條(很神奇的設定);
page:per指定了每頁的顯示條數,存在一頁顯示不完整的情況,該參數直接指定顯示第幾頁。
如上圖,底部有pages、curpage參數,分別指明總頁數和當前頁數,在抓取數據時,需要特別處理,否則只能獲取當頁數據。代碼非常的簡單,過程也很容易理解,不多介紹,后附完整代碼。
 
基金單位凈值、累計凈值
基金一般在每個工作日公布上一個工作日的凈值,單位凈值=總凈資產/基金份額,可以簡單理解為基金的價格。因此,凈值越高,一定程度上表示基金越“貴”,但也可能代表基金經理管理好。在交易日買入基金的時候,如果是當天15點之前購入,那么按照當天的基金凈值確認份額,購入份額=購買金額/當日基金凈值。如果是在當天15點之后購入,則按照下一工作日的基金凈值確認份額。因為基金凈值一般在第二個工作日(或者當天晚上)才公布,所以在買入基金的時候,是不知道買入確認的基金凈值是多少,也就不知道買入的份額是多少。
 
累計凈值就是基金凈值加上過往分紅,反映基金過往整體的收益情況。單位凈值提供基金即時交易價格的參考,但從基金業績的角度看,累計凈值是一個更重要的指標。
 
實例
抓取招商中證白酒指數分級(161725)2018年的基金數據進行分析。將基金單位凈值、累計凈值、日增長率數據作圖,如下:
 
 
 
 
 
 
可以看到,去年是比較慘淡的一年,尤其是下半年,整體是向下的走勢。這段時間關注過基金的應該都深有體會,“綠化”非常好的半年。日增長整理整體波動分布,下半年波動幅度比較大,尤其是11月份前后的幾個交易日,經歷過大幅的漲跌。全年245個交易日中,除兩個缺失值外,有106天日增長率為正,137天為負或者零。整體上跌的天數多于漲的天數。
 
我們再來看下“累計凈值-單位凈值”的變化。一般在發生分紅的時候,該差額會發生變動。作圖如下:
 
 
 
 
 
 
可以看到,2018年該差額發生過兩次變動,一次是發生在7月初,另一次發生在12月中旬。進一步確認,兩個試點分別是2018/07/05和2018/12/17.查詢天天基金網站,該基金在2018年并沒有具體的分紅信息,但是在2018/12/17這天發生過基金份額折算,在2018/07/05這天并沒有查詢到具體事項。作為一個只會基金定投的小白瓜,就理解到這里了。
 
代碼:
 
# 導入需要的模塊
import requests
from bs4 import BeautifulSoup
import re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
 
#指定默認字體
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['font.family']='sans-serif'
#解決負號'-'顯示為方塊的問題
matplotlib.rcParams['axes.unicode_minus'] = False
 
# 抓取網頁
def get_url(url, params=None, proxies=None):
    rsp = requests.get(url, params=params, proxies=proxies)
    rsp.raise_for_status()
    return rsp.text
 
# 從網頁抓取數據
def get_fund_data(code,per=10,sdate='',edate='',proxies=None):
    url = 'http://fund.eastmoney.com/f10/F10DataApi.aspx'
    params = {'type': 'lsjz', 'code': code, 'page':1,'per': per, 'sdate': sdate, 'edate': edate}
    html = get_url(url, params, proxies)
    soup = BeautifulSoup(html, 'html.parser')
 
    # 獲取總頁數
    pattern=re.compile(r'pages:(.*),')
    result=re.search(pattern,html).group(1)
    pages=int(result)
 
    # 獲取表頭
    heads = []
    for head in soup.findAll("th"):
        heads.append(head.contents[0])
 
    # 數據存取列表
    records = []
 
    # 從第1頁開始抓取所有頁面數據
    page=1
    while page<=pages:
        params = {'type': 'lsjz', 'code': code, 'page':page,'per': per, 'sdate': sdate, 'edate': edate}
        html = get_url(url, params, proxies)
        soup = BeautifulSoup(html, 'html.parser')
 
        # 獲取數據
        for row in soup.findAll("tbody")[0].findAll("tr"):
            row_records = []
            for record in row.findAll('td'):
                val = record.contents
 
                # 處理空值
                if val == []:
                    row_records.append(np.nan)
                else:
                    row_records.append(val[0])
 
            # 記錄數據
            records.append(row_records)
 
        # 下一頁
        page=page+1
 
    # 數據整理到dataframe
    np_records = np.array(records)
    data= pd.DataFrame()
    for col,col_name in enumerate(heads):
        data[col_name] = np_records[:,col]
 
    return data
 
 
# 主程序
if __name__ == "__main__":
    data=get_fund_data('161725',per=49,sdate='2018-01-01',edate='2018-12-31')
    # 修改數據類型
    data['凈值日期']=pd.to_datetime(data['凈值日期'],format='%Y/%m/%d')
    data['單位凈值']= data['單位凈值'].astype(float)
    data['累計凈值']=data['累計凈值'].astype(float)
    data['日增長率']=data['日增長率'].str.strip('%').astype(float)
    # 按照日期升序排序并重建索引
    data=data.sort_values(by='凈值日期',axis=0,ascending=True).reset_index(drop=True)
    print(data)
 
    # 獲取凈值日期、單位凈值、累計凈值、日增長率等數據并
    net_value_date = data['凈值日期']
    net_asset_value = data['單位凈值']
    accumulative_net_value=data['累計凈值']
    daily_growth_rate = data['日增長率']
 
    # 作基金凈值圖
    fig = plt.figure()
    #坐標軸1
    ax1 = fig.add_subplot(111)
    ax1.plot(net_value_date,net_asset_value)
    ax1.plot(net_value_date,accumulative_net_value)
    ax1.set_ylabel('凈值數據')
    ax1.set_xlabel('日期')
    plt.legend(loc='upper left')
    #坐標軸2
    ax2 = ax1.twinx()
    ax2.plot(net_value_date,daily_growth_rate,'r')
    ax2.set_ylabel('日增長率(%)')
    plt.legend(loc='upper right')
    plt.title('基金凈值數據')
    plt.show()
 
    # 繪制分紅配送信息圖
    bonus = accumulative_net_value-net_asset_value
    plt.figure()
    plt.plot(net_value_date,bonus)
    plt.xlabel('日期')
    plt.ylabel('累計凈值-單位凈值')
    plt.title('基金“分紅”信息')
    plt.show()
 
    # 日增長率分析
    print('日增長率缺失:',sum(np.isnan(daily_growth_rate)))
    print('日增長率為正的天數:',sum(daily_growth_rate>0))
    print('日增長率為負(包含0)的天數:',sum(daily_growth_rate<=0))

標簽: Python 基金
頂一下
(0)
0%
踩一下
(0)
0%

Google提供的廣告

股票配资选股