python数据分析实例1-基金定投

本文通过量化分析,探讨了对沪深300指数基金进行定期定额投资(定投)的策略效果,包括不同时间段内的收益率计算与可视化,以及不同定投周期对收益的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需要完成的任务

1. 假设定投的金额是500元,每周定投一次,据此计算2019年对**沪深300指数**基金进行定投的收益率
2. 假设定投的金额是500元,每周定投一次,据此**分别**计算从2002年开始到2019年,每年定投**沪深300指数基金**的收益率并将结果可视化
3. 探索不同的定投策略,看看你能否得到更好的定投收益呢?

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

建议和流程:

1. 加载模块 - 常见的numpy/pandas/datetime/matplotlib等
2. 定义参数 - 用于基金定投的一些参数;比如定投金额,定投周期等
3. 数据获取 - 定义get_data()函数用于获取数据 (hint: pandas的read_csv()函数) 
4. 数据预处理 - 调用pandas对象的head()方法预览少量数据
5. 数据可视化 - 调用pandas对象的plot()方法进行简单的数据可视化
6. 数据分析 - 定义invest()函数实现定投功能
7. 结果评估 - 输出分析结果并可视化

这里所使用的接口:

  • 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分别表示涨跌额,涨跌幅,成交量,成交金额。
一.计算2019年对沪深300指数基金进行定投的收益
# -*- coding: UTF-8 -*-
import operator as op
from datetime import datetime,timedelta
import matplotlib.pyplot as plt
import pandas as pd

'''
加载数据
input:
    index_no: 指数编号,比如沪深300指数的编号为 000300
    start_date:开始日期,格式为 2018-04-03
    end_date:结束日期,格式为 2018-04-03
output:
    指数列表,只包含日期和收盘价    
'''
def load(index_no, start_date, end_date):
    file = './数据/' + index_no + '.csv'
    f = open(file,'r')
    indices = {}
    for line in f.readlines():
        arr = line.strip().split(',')
        dt = arr[0]
        if op.lt(start_date,dt) and op.lt(dt,end_date) :
            indices[arr[0]] = arr[3]
    return indices    


'''
购买
input:
    date: 投日日期
    amount: 投资金额
    data: 指数数据
output:
    获得基金份数
'''
def purchase(date, amount, data):
    index_value = data[date]
    return amount/float(index_value)

def getIndexValue(date,data):
    return data[date]

'''
定投
input:
    start_date: 起投日期
    end_date: 终止日期
    amount: 每次投资金额
    freq: 投资频率(每几天投资一次)
output:
    投资总额,收益总额
'''
def invest(index_no,start_date, end_date, amount, feq):
    data = load(index_no,start_date,end_date) 
    sd = datetime.strptime(start_date, '%Y-%m-%d')
    ed = datetime.strptime(end_date, '%Y-%m-%d')
    curr = sd
    total_share = 0; total_amount = 0;total_profit=0
    last_index = 0
    while True:
        #如果当天不是交易日,则往后延一天.
        while curr.strftime('%Y-%m-%d') not in data.keys():
            curr += timedelta(days = 1)
            if curr > ed: break
        if curr > ed: # 超过结束日期则停止
            break

        last_index = float(getIndexValue(curr.strftime('%Y-%m-%d'),data))  
        #购买基金
        shares = purchase(curr.strftime('%Y-%m-%d'), amount, data)
        total_share += shares
        total_amount += amount
        #计算下一个投资日期
        curr = curr + timedelta(days = feq)
    total_profit = last_index*total_share - total_amount    
    return total_amount,total_profit

# 1.计算2019年对沪深300指数基金进行定投的收益率
start_date = '2019-01-01'
end_date = '2019-12-31'
total_amount,total_profit = invest('000300',start_date, end_date,500,7)

print('起投日期',start_date)
print('结束日期',end_date)
print('总投资额',total_amount)
print('总收益',round(total_profit))
print('投资收益率',round(total_profit/total_amount*100,2),"%")
二.分别计算从2002年开始到2019年,每年定投沪深300指数基金的收益率并将结果可视化.

def change_year(start_year, end_year):

    total_amount,total_profit = invest('000300',start_year, end_year,500,7)
    
    print('起投日期',start_year)
    print('结束日期',end_year)
    print('总投资额',total_amount)
    print('总收益',round(total_profit))
    print('投资收益率', round(total_profit/total_amount*100,2),"%") 

    return round(total_profit/total_amount*100,2)

# 2002年到2019年之间的年收益率
str_year_begin =  '2002-01-01'
str_year_end = '2003-01-01'
list_year_begin = list(str_year_begin)
list_year_end = list(str_year_end)
# dic = {}
numbers_list = []
year_list = []

for i in range(2, 19):
    if i < 10:
        list_year_begin[3] = str(i)
        list_year_end[3] = str(i+1)
        if i == 9:
            list_year_end[2] = "1"
            list_year_end[3] = "0"
    elif i == 10:
        list_year_begin[2] = "1"
        list_year_begin[3] = "0"
        list_year_end[3] = "1"
        
    else:
        list_year_begin[3] = str(i%10)
        list_year_end[3] = str(i%10 + 1)
        
    str_year_begin = ''.join(list_year_begin)
    str_year_end = ''.join(list_year_end)
    
    print("{0:=>25}-{1:=<50}".format(str_year_begin, str_year_end))
    
    # 准备绘图数据 按年投资,并把收益率存在number_list中。
    numbers_list.append(change_year(str_year_begin, str_year_end))
    year_list.append(str_year_begin)
2.2对这17年每年的投资收益率进行可视化
# 2002年到2018年 变化率可视化
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.plot(year_list, numbers_list)
plt.gcf().autofmt_xdate()
plt.ylabel("收益率(百分比)", fontproperties='SimHei', fontsize=15)
plt.xlabel("年份", fontproperties='SimHei', fontsize=15)

plt.title("2002年-2018年的收益率变化")

plt.show()
三.探索不同的定投策略,看看你能否得到更好的定投收益呢?

答:在25000 左右的本金,以及不考虑交易手续费的理想情况下,
改变定投周期,得出一个结论:
周期越短,收益率越大。

总结:

技术不行,这里先学习前人代码,力所能及的做一些操作.
问题(已解决):

  • 字符串的修改方法:

    1.字符串变列表 list()
    2.指定位置修改值
    3.通过"".join再合并列表为字符串

  • dataframe类型数据画图时候如何让行画?

    dataframe.T 转置

  • 对datatime库很陌生.

    里面有个方法可以实现x轴按照实时时间绘制

  • plotx轴为年份的方法.

    1.由于对numpy和series类型还未熟练掌握
    2.使用一个列表不断append新元素
    3.这里的元素是时间字符串,上面代码有操作.
    4.然后plot的时候直接整个list作为x轴绘制

  • 如何循环给list类型添加元素?

    for + append 方法

  • 如何循环给dict类型添加元素?

    循环中不断给新的key 和 value值 两个都作为变量.不断执行
    dict[key] = value

未解决问题:

  • datetime库学习
  • 对numpy,和series,以及plot绘图训练
  • 对数据的爬取
  • 数据的读取
  • 数据的取其精华
  • 数据的存储, 不同结构的数据,适合用什么样的数据类型存储?
  • 对于不同的数据类型,快速选择适合的画图方式,以及画什么样的图


注:
参考:https://my.oschina.net/stanleysun/blog/222255

带着问题继续盘…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值