需要完成的任务
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
带着问题继续盘…