基于Python的指数基金量化投资 - 正三角和倒三角投资模型

基于Python的指数基金量化投资 - 正三角和倒三角投资模型,第1张

普通投资者的投资方式中,有两种非常常见:

追涨杀跌式:涨了跟着买,跌了赶紧卖。

低买高卖式:跌了就买入,涨了就卖出。

第一种方式长期来看肯定是要亏钱的,长期追高难免不站岗,而第二种方式是比较正确的投资方式,但低买高卖要根据固定的指标来进行量化才能形成有效的模式。

如果把这两种投资方式进行量化,第一种称为倒三角投资模式,第二种称为正三角模式。

下面举两个例子来说明两种模式的差别(下面每一份代表买入1000元)。

倒三角模式就是指数高位的时候买得多,越高买得越多,而低位的时候买得少,越低买得越少,最后份额累积起来就形成了一个倒三角。最终的投资成本较高。

上图中是倒三角模式的一个例子,在指数低位的时候2700只买入了2份,随着指数向上,买入的份额越来越多,到指数变成3300时,买入了8份,这样算下来,买入的成本是3068.73。

正三角模式刚好和倒三角相反,指数高位的时候买得少,越高买得越少,而低位的时候买得多,越低买得越多。最终的投资成本较低。

上图中是正三角模式的一个例子,在指数低位的时候2700只买入了8份,随着指数向上,买入的份额越来越少,到指数变成3300时,只买入了2份,这样算下来,买入的成本是2908.79。

倒三角投资是不稳的,指数下跌的时候,份额集中在高位,下跌带来的亏损会被放大;而指数上涨的时候,由于成本较高,获得的收益也非常有限。

当指数上涨到3300点的时候,获得收益是(3300-3068.73)/3068.73=7.54%;而当指数下跌到2700点的时候,回撤亏损是(2700-3068.73)/3068.73=-12.02%

正三角投资就非常稳健,由于份额集中在低位,整个拉低了投资成本,指数下跌亏损有限,而指数如果上涨到和倒三角同样的指数点位会带来的更多的收益。

当指数上涨到3300点的时候,获得收益是(3300-2908.79)/2908.79=13.41%;而当指数下跌到2700点的时候,回撤亏损是(2700-2908.79)/2908.79=-7.18%

对比起来看,正三角和倒三角投资模式的区别是非常明显的,上涨到高位3300点,正三角会比倒三角将近多6个百分点的收益;而下跌到低位2700点,正三角会比倒三角将近少5个百分点的亏损。

下面来看看上证红利通过倒三角和正三角的投资比较,数据取上证红利指数成立以来的所有数据(2005年到目前的所有数据),而投资的区间取1300点到4000点之间,下图是上证红利的指数曲线,其中蓝线是1300点的位置,红线是4000点的位置。

投资过程中每隔300点增加或减少一份投入(一份投入=1000块钱)

根据定好的模式,来看看正三角和倒三角买入的过程。

下面先给出具体的图例,具体的源码贴在后面,感兴趣大家可以参考。

图中红圈是买入的份额,红圈越大表示买入越多,越小买入越少。可以看出正三角是低位买得多高位买得少,而倒三角正好相反,低位买得少高位买得多。

接着来看看两种方式的投资成本。

其中灰色曲线是上证红利的指数点位,很明显的能看出红线(正三角)低于蓝线(倒三角),除了成本低以外,红线(正三角)低于指数点位的区间是比蓝线(倒三角)多的,说明不仅收益高而且回撤小。下面比较下两者的收益走势。

正三角的投资收益(正收益)在整个投资过程中是100%大于倒三角模式的,而且在某些时间点上会高出几十个百分点,同时回撤(负收益)也更低。

正三角投资是一种有效的投资方式,但真正 *** 作起来却很困难,因为它是反人性的,需要克服周围的干扰和个人情绪的影响,越跌越买需要具备强大的情绪控制能力和极强的耐心。

源码
import pandas as pd
import numpy as np
import math as math
import matplotlib.pyplot as plt

name_index = 'sh.000015'
all_data_index = pd.read_csv('./exportfile/indexDataAll/' + name_index + '.csv')

calc_range = 0
calc_gap = 5
data_index_p = all_data_index['close'].values[0:len(all_data_index['close']):calc_gap]

def triangleDown(val_data_p, buy_cost, invest_count):
    thd_price   = [1300, 1600, 1900, 2200, 2500, 2800, 3100, 3400, 3700, 4000]
    each_invest = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    if thd_price[0] < val_data_p <= thd_price[1]:
        each_ratio_todo = each_invest[0]
    elif thd_price[1] < val_data_p <= thd_price[2]:
        each_ratio_todo = each_invest[1]
    elif thd_price[2] < val_data_p <= thd_price[3]:
        each_ratio_todo = each_invest[2]
    elif thd_price[3] < val_data_p <= thd_price[4]:
        each_ratio_todo = each_invest[3]
    elif thd_price[4] < val_data_p <= thd_price[5]:
        each_ratio_todo = each_invest[4]
    elif thd_price[5] < val_data_p <= thd_price[6]:
        each_ratio_todo = each_invest[5]
    elif thd_price[6] < val_data_p <= thd_price[7]:
        each_ratio_todo = each_invest[6]
    elif thd_price[7] < val_data_p <= thd_price[8]:
        each_ratio_todo = each_invest[7]
    elif thd_price[8] < val_data_p <= thd_price[9]:
        each_ratio_todo = each_invest[8]
    else:
        each_ratio_todo = 0
    buy_each_invest = invest_count * each_ratio_todo
    plot_y = 0
    plot_x = 0
    plot_mark = 0
    if buy_each_invest != 0:
        buy_each_share = buy_each_invest / val_data_p
        buy_cost = buy_cost + buy_each_invest
        plot_y = val_data_p
        plot_x = i
        plot_mark = buy_each_invest
    else:
        buy_each_share = 0

    return buy_each_share, buy_cost, [plot_x, plot_y, plot_mark]

def triangleUp(val_data_p, buy_cost, invest_count):
    thd_price   = [1300, 1600, 1900, 2200, 2500, 2800, 3100, 3400, 3700, 4000]
    each_invest = [9, 8, 7, 6, 5, 4, 3, 2, 1]
    if thd_price[0] < val_data_p <= thd_price[1]:
        each_ratio_todo = each_invest[0]
    elif thd_price[1] < val_data_p <= thd_price[2]:
        each_ratio_todo = each_invest[1]
    elif thd_price[2] < val_data_p <= thd_price[3]:
        each_ratio_todo = each_invest[2]
    elif thd_price[3] < val_data_p <= thd_price[4]:
        each_ratio_todo = each_invest[3]
    elif thd_price[4] < val_data_p <= thd_price[5]:
        each_ratio_todo = each_invest[4]
    elif thd_price[5] < val_data_p <= thd_price[6]:
        each_ratio_todo = each_invest[5]
    elif thd_price[6] < val_data_p <= thd_price[7]:
        each_ratio_todo = each_invest[6]
    elif thd_price[7] < val_data_p <= thd_price[8]:
        each_ratio_todo = each_invest[7]
    elif thd_price[8] < val_data_p <= thd_price[9]:
        each_ratio_todo = each_invest[8]
    else:
        each_ratio_todo = 0
    buy_each_invest = invest_count * each_ratio_todo
    plot_y = 0
    plot_x = 0
    plot_mark = 0
    if buy_each_invest != 0:
        buy_each_share = buy_each_invest / val_data_p
        buy_cost = buy_cost + buy_each_invest
        plot_y = val_data_p
        plot_x = i
        plot_mark = buy_each_invest
    else:
        buy_each_share = 0

    return buy_each_share, buy_cost, [plot_x, plot_y, plot_mark]

cnt = 0
invest_count = 1000
buy_each_triangel_up = np.zeros((len(data_index_p), 1))
buy_total_share_list_triangel_up = np.zeros((len(data_index_p), 1))
buy_total_cost_money_list_triangel_up = np.zeros((len(data_index_p), 1))
buy_total_invest_money_list_triangel_up = np.zeros((len(data_index_p), 1))
buy_cost_triangel_up = 0
plot_triangel_up = np.zeros((len(data_index_p), 3))
invest_income_rate_up = np.zeros((len(data_index_p), 1))

buy_each_triangel_down = np.zeros((len(data_index_p), 1))
buy_total_share_list_triangel_down = np.zeros((len(data_index_p), 1))
buy_total_cost_money_list_triangel_down = np.zeros((len(data_index_p), 1))
buy_total_invest_money_list_triangel_down = np.zeros((len(data_index_p), 1))
buy_cost_triangel_down = 0
plot_triangel_down = np.zeros((len(data_index_p), 3))
invest_income_rate_down = np.zeros((len(data_index_p), 1))

for i in range(len(data_index_p)):

    buy_each_triangel_up[i], buy_cost_triangel_up, plot_triangel_up[i] = triangleUp(data_index_p[i],buy_cost_triangel_up, invest_count)
    buy_total_share_list_triangel_up[i] = sum(buy_each_triangel_up)
    buy_total_invest_money_list_triangel_up[i] = buy_total_share_list_triangel_up[i] * data_index_p[i]
    buy_total_cost_money_list_triangel_up[i] = buy_cost_triangel_up

    buy_each_triangel_down[i], buy_cost_triangel_down, plot_triangel_down[i] = triangleDown(data_index_p[i],buy_cost_triangel_down, invest_count)
    buy_total_share_list_triangel_down[i] = sum(buy_each_triangel_down)
    buy_total_invest_money_list_triangel_down[i] = buy_total_share_list_triangel_down[i] * data_index_p[i]
    buy_total_cost_money_list_triangel_down[i] = buy_cost_triangel_down

invest_cost_triangel_up = buy_total_cost_money_list_triangel_up[-1]/buy_total_share_list_triangel_up[-1]
invest_cost_triangel_down = buy_total_cost_money_list_triangel_down[-1]/buy_total_share_list_triangel_down[-1]

for i in range(len(buy_total_cost_money_list_triangel_up)):
    invest_income_rate_up[i] = (buy_total_invest_money_list_triangel_up[i] - buy_total_cost_money_list_triangel_up[i]) / buy_total_cost_money_list_triangel_up[i]
    invest_income_rate_down[i] = (buy_total_invest_money_list_triangel_down[i] - buy_total_cost_money_list_triangel_down[i]) / buy_total_cost_money_list_triangel_down[i]

size_title = 28
size_label = 23
size_line = 3
size_rotation = 20
plt_gap = 10

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.plot(buy_total_cost_money_list_triangel_up,color='cornflowerblue',linewidth=size_line)
plt.plot(buy_total_invest_money_list_triangel_up,color='tomato',linewidth=size_line)
plt.legend(["投资成本", "持仓总和"], loc='upper left', prop={'size':size_label})
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)
plt.title('正三角模型走势',size=size_title)

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.plot(buy_total_cost_money_list_triangel_down,color='cornflowerblue',linewidth=size_line)
plt.plot(buy_total_invest_money_list_triangel_down,color='tomato',linewidth=size_line)
plt.legend(["投资成本", "持仓总和"], loc='upper left', prop={'size':size_label})
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)
plt.title('倒三角模型走势',size=size_title)

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.plot(invest_income_rate_up,color='tomato',linewidth=size_line)
plt.plot(invest_income_rate_down,color='cornflowerblue',linewidth=size_line)
plt.legend(["正三角收益", "倒三角收益"], loc='upper right', prop={'size':size_label})
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)
plt.title('收益曲线 | %',size=size_title)

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.title('正三角投资模型',size=size_title)
for i in range(len(plot_triangel_up)):
    if plot_triangel_up[i][0] != 0:
        plt.plot(plot_triangel_up[i][0], plot_triangel_up[i][1],color='tomato',marker='o',ms=(8*(0.001*plot_triangel_up[i][2])**2)**0.5+0.5)
plt.plot(data_index_p,color='cornflowerblue',linewidth=size_line)
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.title('倒三角投资模型',size=size_title)
for i in range(len(plot_triangel_down)-1,-1,-2):
    if plot_triangel_down[i][0] != 0:
        plt.plot(plot_triangel_down[i][0], plot_triangel_down[i][1],color='tomato',marker='o',ms=(8*(0.001*plot_triangel_down[i][2])**2)**0.5+0.5)
        # plt.scatter(plot_triangel_down[i][0], plot_triangel_down[i][1], color='', marker='o', edgecolors='tomato',s=(8 * (0.005 * plot_triangel_down[i][2]) ** 2) ** 0.5)
plt.plot(data_index_p,color='cornflowerblue',linewidth=size_line)
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)

invest_cost_each_triangel_up = np.zeros((len(buy_total_cost_money_list_triangel_up), 1))
invest_cost_each_triangel_down = np.zeros((len(buy_total_cost_money_list_triangel_down), 1))
for i in range(len(buy_total_cost_money_list_triangel_up)):
    invest_cost_each_triangel_up[i] = buy_total_cost_money_list_triangel_up[i]/buy_total_share_list_triangel_up[i]
    invest_cost_each_triangel_down[i] = buy_total_cost_money_list_triangel_down[i]/buy_total_share_list_triangel_down[i]

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.plot(data_index_p,color='darkgray',linewidth=size_line)
plt.plot(invest_cost_each_triangel_up,color='tomato',linewidth=size_line)
plt.plot(invest_cost_each_triangel_down,color='cornflowerblue',linewidth=size_line)
plt.legend(["指数点位", "正三角投资成本", "倒三角投资成本"], loc='upper right', prop={'size':size_label})
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)
plt.title('成本分布',size=size_title)

plt.figure()
plt.rcParams["axes.grid"] = True
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams["grid.linestyle"] = (3, 5)
plt.plot(data_index_p,color='darkgray',linewidth=size_line)
plt.plot([0,len(data_index_p)],[4000,4000],color='tomato',linewidth=size_line)
plt.plot([0,len(data_index_p)],[1300,1300],color='cornflowerblue',linewidth=size_line)
plt_xticks = all_data_index['date'].values[1:len(all_data_index['date']):calc_gap].tolist()
plt.xticks(range(len(plt_xticks),0,-math.floor(len(plt_xticks)/plt_gap)),plt_xticks[len(plt_xticks):0:-math.floor(len(plt_xticks)/plt_gap)],rotation=size_rotation)
plt.tick_params(labelsize=size_label)
plt.title('投资的点位区间',size=size_title)

plt.show()

文中用到的两个文件下载链接: https://pan.baidu.com/s/1yF9hv-Kv_BtAbM8LjIbEdg?pwd=3uqe 提取码: 3uqe

程序中用到的数据如果有问题,大家可以留言获取也可以添加小将前行的微信xjqx_666进行获取,欢迎大家一起交流沟通

课程参考:基于Python的量化指数基金投资

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/917981.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存