Akshare指数定投
import pandas as pd import numpy as np from scipy import stats import matplotlib.pyplot as plt import akshare as ak from pyecharts.charts import Bar from pyecharts.charts import Grid from pyecharts.charts import WordCloud from pyecharts.charts import Pie from pyecharts.charts import Map from pyecharts.charts import Line # from pyecharts import Overlap from datetime import datetime, timedelta from pyecharts import * # 正常显示画图时出现的中文和负号 from pylab import mpl mpl.rcParams['font.sans-serif'] = ['SimHei'] mpl.rcParams['axes.unicode_minus'] = False # 获取数据并计算对数收益率 def get_index_data(code): df = pd.DataFrame() index_zh_a_hist_df = ak.index_zh_a_hist(symbol=code, period="daily", start_date="19700101", end_date="22220101") df[code] = index_zh_a_hist_df['收盘'] df.index = pd.to_datetime(index_zh_a_hist_df['日期']) df = df.sort_index() df['logret'] = np.log(df / df.shift(1)) return df.iloc[1:, :] # A股常用的八个指数 common_index = {'上证综指': '000001', '深证成指': '399001', '沪深300': '000300', '创业板指': '399006', '上证50': '000016', '中证500': '000905', '中小板指': '399005', '上证180': '000010'} # 获取指数收盘价和日对数收益率 index_data = {} for name, code in common_index.items(): index_data[name] = get_index_data(code) # 对股价走势进行可视化 names = list(common_index.keys()) codes = list(common_index.values()) plot_pos = [421, 422, 423, 424, 425, 426, 427, 428] # 每个子图的位置 new_colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'] fig = plt.figure(figsize=(16, 18)) fig.suptitle('国内股指走势', fontsize=18) for i in np.arange(len(plot_pos)): ax = fig.add_subplot(plot_pos[i]) y_data = index_data[names[i]][codes[i]] b = ax.plot(y_data, color=new_colors[i]) ax.set_title(names[i]) plt.show() # 股指自发行以来累积收益率情况 fig = plt.figure(figsize=(16, 18)) fig.suptitle('国内股指累积收益率', fontsize=18) for i in np.arange(len(plot_pos)): ax = fig.add_subplot(plot_pos[i]) y_data = index_data[names[i]]['logret'].cumsum() b = ax.plot(y_data, color=new_colors[i]) ax.set_title(names[i]) plt.show() def cum_return(start_date, end_date='2018-12-24'): df = pd.DataFrame() for name, data in index_data.items(): df[name] = data.loc[start_date:end_date]['logret'].cumsum() return df cum_return('2013-01-01', '2015-06-12').plot(figsize=(16, 6)) cum_return('2011-01-01').plot(figsize=(16, 6)) cum_return('2018-01-01').plot(figsize=(16, 6)) attr = list(common_index) n = [1 / 28, 1 / 27, 1 / 13, 1 / 8, 1 / 14, 1 / 13, 1 / 12, 1 / 22] r = cum_return('1990-12-20').iloc[-1] v1 = list((r.values * 100).round(2)) v2 = ((np.power(1 + r.values, n) - 1) * 100).round(2) print("累计收益率",attr) print("累计收益率",v1) print("年化平均收益率",attr) print("年化平均收益率",v2) # 指数定投函数 def index_strategy(code, start_date, end_date, first=1): ##步骤一:获取数据 ##通过自定义函数get_index_data获取指数数据 df = get_index_data(code) df = df.loc[start_date:end_date] # 累计收益率 df['累计收益率'] = df.logret.cumsum() # 假设定投无风险理财产品收益率为4% df['无风险收益率'] = (4.0 / 100 + 1) ** (1.0 / 250) - 1 df['无风险收益_净值'] = (df['无风险收益率'] + 1).cumprod() ##步骤二:设定定投日并计算份额和累计资金 # 每月第一个交易日或最后一个交易日定投 # first==1表示每个月第一个交易日定投 if first == 1: by_month = df.resample('M', kind='period').first() else: by_month = df.resample('M', kind='period').last() # 定投购买指数基金 trade_log = pd.DataFrame(index=by_month.index) # 假设每月投入3000元 trade_log['基金净值'] = by_month[code] / 3000 trade_log['money'] = 3000 trade_log['基金份额'] = trade_log['money'] / trade_log['基金净值'] trade_log['总基金份额'] = trade_log['基金份额'].cumsum() trade_log['累计定投资金'] = trade_log['money'].cumsum() ##步骤三:计算定投保本理财份额和资金 trade_log['理财份额'] = trade_log['money'] / by_month['无风险收益_净值'] trade_log['总理财份额'] = trade_log['理财份额'].cumsum() temp = trade_log.resample('D').ffill() df = df.to_period('D') ##步骤三:计算每个交易日的资产(等于每天的基金份额乘以单位基金净值)和累计收益率 daily_data = pd.concat([df, temp[['总基金份额', '总理财份额', '累计定投资金']]], axis=1, join='inner') daily_data['指数定投资金'] = daily_data[code] / 3000 * daily_data['总基金份额'] daily_data['理财定投资金'] = daily_data['无风险收益_净值'] * daily_data['总理财份额'] daily_data['指数定投收益率'] = (daily_data['指数定投资金'] - daily_data['累计定投资金']) / daily_data['累计定投资金'] daily_data['理财定投收益率'] = (daily_data['理财定投资金'] - daily_data['累计定投资金']) / daily_data['累计定投资金'] # 返回后面分析需要的变量 return daily_data[[code, '累计收益率', '累计定投资金', '指数定投资金', '理财定投资金', '指数定投收益率', '理财定投收益率']] # 将画图过程封装成函数 def plot_index_ret(code, name, start_date, end_date): df = index_strategy(code, start_date, end_date, first=1) df1 = index_strategy(code, start_date, end_date, first=0) print(f'月初开始定投:\n{df.iloc[-1]}') print('\n') print(f'月末开始定投:{df1.iloc[-1][5]}') ax1 = df[['累计收益率', '指数定投收益率', '理财定投收益率']].plot(figsize=(16, 6)) ax1.legend(loc=2) plt.title(name + '定投收益率情况\n ' + start_date + ':' + end_date, fontsize=15) ax2 = ax1.twinx() df[code].plot(figsize=(16, 6), color='r', label=name) ax2.legend(loc=1) plt.show() def plot_index_fund(code, name, start_date, end_date): # 每月定投3000元,期间累计资金情况 df = index_strategy(code, start_date, end_date, first=1) ax1 = df[['指数定投资金', '理财定投资金']].plot(figsize=(16, 6)) ax2 = ax1.twinx() df[code].plot(figsize=(16, 6), color='r', label=name) ax2.legend(loc=1) plt.title(f'累计定投资金情况\n {start_date}:{end_date}', fontsize=15) plt.show() plot_index_ret('000001', '上证综指', '2007-10-17', '2015-6-12') attr = ["累计收益率 ", "月初指数定投收益率", "月底指数定投收益率", "理财定投收益率"] v1 = [-16.48, 101.03, 102.02, 16.28] bar = Bar("上证综指定投收益率情况(%)", "2007.10.17—2015.06.12'") bar.add("", attr, v1, is_label_show=True) bar plot_index_ret('000001.SH', '上证综指', '2007-10-17', '2009-07-20') attr = ["累计收益率 ", "月初指数定投收益率", "月底指数定投收益率", "理财定投收益率"] v1 = [-62.31, 15.64, 17.96, 3.62] bar = Bar("上证指数定投收益率情况(%)", "2007.10-2009.9") bar.add("", attr, v1, is_label_show=True) bar
风雨兼程,前程可待!