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

 

posted @ 2022-04-04 14:12  星涅爱别离  阅读(150)  评论(0编辑  收藏  举报