目标:
本系列开始重点研究量化,逐步改善模型,改善策略,然后评估各个策略的优劣。 本文是第一篇,也是最容易最无脑投资的一篇,每周三定投,收益还不错。内容:
如果工作太忙没法投资,闲钱无处放,不妨看看这这种方式。
学金融的都知道最简单靠谱的投资方式:定投。
是否真有效?假期封在家,做了下实验。
假设每周,通过支付宝线下买基金定投1000,从15年元旦开始。就投创业板吧,亏钱了就当给科技做贡献。要知道15年可是股灾年,19年也是,经历了2次股灾还能有收益吗?一起来看看到今天2020-02-07,收益如何?
图1为指数行情,证明数据没有错。
图2为定投VS年化5%无风险收益的对比图。可见,定投确实收益超过存定期。
图3为定投选星期几呢?国外有个著名的“周四效应”,而在创业板中,最好的却是周三!国外的月亮比一定在国内元。最差周一、周五。差值能达到20000元。
图4为定投的纯收益,亏损最多的是在19年初那次股灾。
图5为收益率曲线,也可以看出周三的收益率最好。
图6为收益率,定投最多也能亏40%,让人有点崩溃吧。
为啥定投很少有人坚持?2016-2020年4年都在亏钱,好多人的心理早已崩溃,心理承受能力早已塌陷。但曙光就在后面。
这种机械式定投显然不是很好的办法。但确实也有赚钱机会。
股市有风险,投资需谨慎。
改进措施:
最大回撤=82% - (-39%) = 120%。策略波动太大。 亏钱源自于高价位买太多,低价位买太少,所以机械的每次买一样的金额,明显不好,可以考虑增加弹性,高价位买少,低价位买多。这样最大回撤能小很多。 下篇见。代码:
实验数据此处下载:链接:https://pan.baidu.com/s/1yVThgukzc3iXFhjHMLVONA
提取码:1234
# -*- coding:utf-8 -*-
"""
作者:luoji
日期:2022年02月06日
"""
import pandas as pd
import time
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.ticker import FuncFormatter
# 设置显示为中文
mpl.rcParams['font.sans-serif'] = ['KaiTi']
mpl.rcParams['font.serif'] = ['KaiTi']
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题,或者转换负号为字符串
# dateTOBegin = '2018-01-01'
dateTOBegin = '2015-01-01' # 定投开始时间
data = pd.read_csv('C:\\LuojiPythonProject\\AGuquant\\data\\399006.csv', encoding='UTF-8', index_col=0) # 加载数据,去掉第一列
print(data.head(5))
data['trade_date'] = pd.to_datetime(data['trade_date'], format='%Y%m%d') # 把字符日期转换为日期格式
print(data['trade_date'])
data = data[data['trade_date'] >= dateTOBegin] # 筛选定投开始以后的数据
data = data.set_index('trade_date') # 把日期设置为index,方便存取和画图,原地更改data
print(data.head(5))
print(data.index)
print(data.columns) # 这里trade_date在列中被删除了,排了序之后,再补回来
data = data.sort_values(['trade_date'], ascending=True) # 按照日期从大到小排序
print(data.head(5))
figure = plt.figure(1) # 画图1
data['close'].plot(title='创业板指数价格', xlabel='交易日期', ylabel='价格', legend='收盘价', grid=True) # 按 收盘价画指数图
# plt.show()
print(data.columns)
# print(data['trade_date'].head(5))
data['trade_date'] = data.index # 新增一列trade_date,之前那个trade_date设置为了index,并排序。现在还原回来,
listWeekDay = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'] # 星期1-5
data['day_of_week'] = data['trade_date'].dt.dayofweek # 获得星期几的序号,从0开始,到6,表示星期一到星期天
# def conver2weekDay(x):
# return listWeekDay[x]
#
# data['weekDay'] = data['weekDay'].map(conver2weekDay) # 等效为:
data['day_of_week'] = data['day_of_week'].map(lambda x: listWeekDay[x]) # 把day_of_week转换成英语的星期,用了匿名函数
print(data.head(5))
baseCapital = 1000 # 每周初始定投资金
for i in range(5):
principal = 'principal_on_' + listWeekDay[i] # 本金 principal
data[principal] = 0 # 新建本金 principal列并初始化
bugAmount = 'bug_amount_on_' + listWeekDay[i] # 购买数量,也即是定投的股数
data[bugAmount] = 0 # 初始化定投的股数
for i in range(5):
day = listWeekDay[i] # 获取星期几
bugAmount = 'bug_amount_on_' + listWeekDay[i] # 购买数量
principal = 'principal_on_' + listWeekDay[i] # 本金 principal
data.loc[data['day_of_week'] == day, principal] = baseCapital # 本金字段,写到具体星期几做的定投
# 计算定投时的股数,也就是用本金除以收盘价,得到当天购买的股数
data.loc[data['day_of_week'] == day, bugAmount] = baseCapital / data[data['day_of_week'] == day]['close']
# print(data.head(5))
print(data.head(10))
print(data.columns)
for i in range(5):
accumulateAmount = 'accumulate_amount_' + listWeekDay[i] # 累积购买股数
bugAmount = 'bug_amount_on_' + listWeekDay[i] # 购买数量
data[accumulateAmount] = data[bugAmount].cumsum() # 购买数量累加,即可得到累积购买的股数
marketValue = 'market_value_on_' + listWeekDay[i] # 当前持有股数的市值
data[marketValue] = data['close'] * data[accumulateAmount] # 收盘价乘以累积购买股数,即可得到市值
figure = plt.figure(2)
for i in range(5):
marketValue = 'market_value_on_' + listWeekDay[i] # 画市值图形
data[marketValue].plot(title='定投市值', xlabel='交易日期', ylabel='市值', legend=marketValue, grid=True)
# no risk profit 无风险收益曲线,作为对照,进行对比投资是否有效,无风险利率5%
data['no_risk_principal'] = 0
data.loc[data['day_of_week'] == 'Monday', 'no_risk_principal'] = baseCapital # 无风险定投选在每周1
data['no_risk_accumulate_principal'] = data['no_risk_principal'].cumsum() # 无风险累积成本
no_risk_rate = 0.05 # 无风险收益率5%
no_risk_rate_daily = no_risk_rate / 200 # 交易天数按200天计算,得到每天的无风险收益率
data['no_risk_profit_everyday'] = data['no_risk_accumulate_principal'] * no_risk_rate_daily # 每天的无风险收益
data['no_risk_profit'] = data['no_risk_profit_everyday'].cumsum() # 每天的无风险收益累加,即可得到累积的收益
data['no_risk_market_value'] = data['no_risk_accumulate_principal'] + data['no_risk_profit'] # 无风险收益加本金,得到市值
data['no_risk_market_value'].plot(xlabel='交易日期', ylabel='市值', legend='5%_no_risk_market_value', grid=True)
data['no_risk_accumulate_principal'].plot(xlabel='交易日期', ylabel='市值', legend='无风险本金', grid=True) # 画本金
# plt.show()
# 减去本金,计算纯收益
for i in range(5):
principal = 'principal_on_' + listWeekDay[i] #本金
accumulate_principal = 'accumulate_principal_' + listWeekDay[i] #累积本金
data[accumulate_principal] = data[principal].cumsum() # 累积成本=本金相加
marketValue = 'market_value_on_' + listWeekDay[i] # 市值
profit = 'profit_on_' + listWeekDay[i] # 纯收益
data[profit] = data[marketValue] - data[accumulate_principal] # 市值减去累计本金,得到纯收益
profit_rate = 'profit_rate_on_' + listWeekDay[i] # 收益率
data[profit_rate] = data[profit] / data[accumulate_principal] # 收益率 = 收益/累积本金
figure = plt.figure(3) # 画收益曲线
for i in range(5):
profit = 'profit_on_' + listWeekDay[i]
data[profit].plot(title='定投收益', xlabel='交易日期', ylabel='收益(元)', legend=profit, grid=True)
data['no_risk_profit_rate'] = data['no_risk_profit'] / data['no_risk_accumulate_principal'] #无风险收益/无风险本金=无风险收益率
data['no_risk_profit'].plot(title='定投收益', xlabel='交易日期', ylabel='收益(元)', legend='5% no_risk_profit', grid=True)
# plt.show()
figure = plt.figure(4) # 画定投收益率
for i in range(5):
profit_rate = 'profit_rate_on_' + listWeekDay[i]
data[profit_rate].plot(title='定投收益率', xlabel='交易日期', ylabel='收益率', legend=profit_rate, grid=True)
data['no_risk_profit_rate'].plot(xlabel='交易日期', ylabel='收益率', legend='5% no_risk_profit_rate', grid=True)
def to_percent(temp, position): # 转换画收益图的Y轴为百分数。
return '%1.0f' % (100 * temp) + '%'
plt.gca().yaxis.set_major_formatter(FuncFormatter(to_percent))
plt.show()
产出:
如果资金有计划近期不会使用,可以考虑研究一下如何投资。
修改一下代码,如果我们2018-01-01年开始定投,会怎么样?
收益更好,能达到50%。