01_指标
指标是一个汉语词语,读音是zhǐ biāo,意思是衡量目标的参数;预期中打算达到的指数、规格、标准,一般用数据表示。
统计学术语
指标是说明总体数量特征的概念及其数值的综合,故又称为综合指标。在实际的统计工作和统计理论研究中,往往直接将说明总体数量特征的概念称为指标。
简单理解,概念+数值 = 指标。
在工作上,可以有验收指标,评价指标,销售指标等。因此股票研究中,会产生各种不同的指标,比如MA(移动平均值),比如30天最高,也可以出现许多的组合或者复杂指标,比如KDJ, MACD。更可以叠加成各种不同的战法指标。注意指标的概念,指标可以是有效的,也可以的错误的。
001_均线类指标
A_平均值与中位数
首先,平均值与中位数是两个概念,需要把它们的差别理解清楚。
平均值(Mean)和中位数(Median)都是描述数据集中趋势的统计量,但它们的定义和计算方式不同,适用于不同类型的数据分布。
平均值(Mean):
- 定义:所有数值加起来的总和除以数值的数量。
- 计算公式:平均值
- 其中Xi 表示数据集中的每一个数值,n是数值的总数。
- 特点:容易受到极端值(非常高或非常低的数值)的影响。
中位数(Median):
- 定义:将数据集从小到大排序后位于中间位置的数值。如果数据集中的数值个数是奇数,中位数就是中间的那个数;如果是偶数,则是中间两个数的平均值。
- 计算方法:首先将数据集排序,然后找到中间的数值。
- 特点:不受极端值的影响,更能反映数据的中心位置。
- 敏感性:平均值对极端值敏感,中位数则不敏感。
- 计算方式:平均值是所有数值的总和除以数值的数量,中位数是排序后位于中间位置的数值。
- 数据分布:如果数据分布是对称的,平均值和中位数通常很接近;如果数据分布是偏斜的,两者可能会相差很大。
- 应用场景:在数据分布不均或包含极端值的情况下,中位数通常是一个更稳健的中心趋势度量。
我们用一个简单的例子来说明它们之间的差别,通过python代码随机产生31(中位数是排序后第16个)个介于50~100之间数(某个班的考试成绩),然后计算它们的平均值和中位数,然后在图中绘制散点图作为1号情况;接着我们更改这31个数里的索引为0和1的数值为10和15,打个比方有两个学生生病了,只做了几道题就交卷了,这样的情况下,计算平均值和中位数作为2号情况。
import matplotlib.pyplot as plt
import numpy as np
# 生成31个随机数据(奇数的中位数)
np.random.seed(0) # 设置随机种子以确保结果可复现
data = np.random.normal(70, 6, 31) # 生成31个数据
data2 = np.copy(data) # 第二组数据改动2个值
data2[0] = 10
data2[1] = 20
# 计算平均值和中位数
mean_value = np.mean(data)
median_value = np.median(data)
print('平均值=%.2f,中位数=%.2f'%(mean_value,median_value))
# 对数据进行排序
sorted_data = np.sort(data)
print(sorted_data)
# 绘制散点图
plt.scatter(range(len(data)), data, color='blue', label='Data Points')
# 绘制平均值和中位数的线
plt.axhline(y=mean_value, color='red', linestyle='--', label=f'Mean: {mean_value:.2f}')
plt.axhline(y=median_value, color='green', linestyle='-', label=f'Median: {median_value:.2f}')
# 标记平均值和中位数
plt.scatter(len(data)*1.05, mean_value, color='red', label='Mean')
plt.scatter(len(data)*1.05, median_value, color='green', label='Median')
plt.ylim(50,90)
所以,要提高平均分的方法很简单,那两个生病的不计入,可见极值对平均值的影响有多大,这个在K线上其实也有同样的问题,某些日子的K线它就不是一个正常值,计算到平均值里就会产生一定的误导,如果我们使用中位数则极值的影响就非常小,它只看排在中间的那个的数值就行了。
B_平均值与正态分布
正态分布(Normal Distribution),也称为高斯分布,是连续概率分布的一种,其概率密度函数的形状是对称的钟形曲线,这种分布广泛存在于自然科学和社会科学中。
在正态分布中,平均值是分布的中心,也是分布的峰值所在的位置。正态分布的曲线是关于平均值对称的,这意味着平均值将数据集分为两个相等的部分。
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
mean_value = np.mean(data)
std_value = np.std(data)
print(mean_value,std_value)
mean_value2 = np.mean(data2)
std_value2 = np.std(data2)
print(mean_value2,std_value2)
# 绘制正态分布曲线
x = np.linspace(0, 120, 120)
y = norm.pdf(x,mean_value,std_value)
plt.plot(x, y, 'k', linewidth=2)
# 绘制正态分布曲线
y2 = norm.pdf(x,mean_value2,std_value2)
plt.plot(x, y2, 'r', linewidth=3)
# 设置图例
plt.legend()
# 设置图表标题和坐标轴标签
plt.title('Normal Distribution')
plt.xlabel('Value')
plt.ylabel('Probability Density')
# 显示图表
plt.show()
我们把上面的2组数据分别计算后绘制正态分布图在一起,就可以发现,原数据平均值72.6,标准差为6.39,而添加了离谱的10,15的数据后,平均值变到了68.63,标准差增大到了15.45,图形上可以看到原数据(黑线)分布范围小,也就是大家的成绩都差不多,而更改了分布(红线)范围就非常大,也就表示有某些人的成绩跟大家差得太远。
A股市场有5000多支股票,也会遵循着正态分布的规律,所以我们的策略本身应用于这些股票的时候,就会出现偏差,有的股票上表现特别的好,大多数表现一般,某些股票上表现的极差。
在正态分布中,大约68%的数据位于均值(μ)的一个标准差(σ)范围内,大约95%的数据位于两个标准差范围内,大约99.7%的数据位于三个标准差范围内。这些百分比是正态分布的属性,也称为68-95-99.7规则或经验法则。
具体来说:
- 约68%的数据值落在 μ−σ 到 μ+σ之间。
- 约95%的数据值落在 μ−2σ 到 μ+2σ 之间。
- 约99.7%的数据值落在 μ−3σ到 μ+3σ 之间。
对于股票来说,大多数的情况下都在2个标准差之内运行,只有少数情况下会跳到2个标准差之外,但是另外一个帕累托原则(Pareto Principle),简称2-8规律却告诉我们在任何一组事物中,最重要的只占一小部分,约20%,而其余80%尽管是多数,却往往是次要的。联想一下,看看是不是大多数情况下行情都是小涨小跌,只有极少数的情况下会有大行情?再想一下,是不是在大行情里才能赚取超额利润?
布林线指标就是根据正态分布进行计算的指标,对它的理解也可以这样认为,大多数情况下股价会在2个标准差之间波动,极少数情况穿出2个标准差可能就是极致行情。
C_移动平均线
关于移动平均线的定义,可以直接问AI得到:
移动平均线(Moving Average,简称MA)是技术分析中的一种常用工具,它有助于平滑价格数据,展现价格趋势的方向和强度。“移动”这个词在这里有两层含义:
数据的滚动性:移动平均线不是固定不变的,它随着时间的推移而“移动”。在计算移动平均值时,你会选择一个特定的时间周期(如5天、10天、30天等),然后计算这个周期内的平均价格。随着新的数据点加入和旧的数据点退出,移动平均线会相应地更新,从而“移动”。
平均的计算方式:移动平均线是对过去某个特定时间周期内的价格数据进行平均。随着新的交易日的结束,最旧的数据点会被新的数据点替换,然后重新计算平均值。这个过程就像是计算平均的过程在时间序列上“移动”。
移动平均线可以帮助交易者识别市场趋势,因为它们可以过滤掉短期的价格波动,使主要趋势更加明显。当价格在移动平均线之上时,通常被视为上升趋势;当价格在移动平均线之下时,通常被视为下降趋势。
移动平均线有几种不同的类型,包括简单移动平均线(SMA)、指数移动平均线(EMA)和加权移动平均线(WMA)。每种类型都有其特定的计算方法,但它们的核心目的都是提供对市场趋势的洞察。
其中我们使用最多的SMA和EMA,关于它们的区别也可以直接问AI
计算方法:
SMA(简单移动平均线): SMA是通过计算特定时间周期内的数值的平均值来得到的。例如,如果你计算10天的SMA,你会将过去10天的收盘价相加然后除以10。随着时间的推移,你会移动这个窗口一天,再次计算平均值,这样你就得到了一个SMA的数据点。SMA给予所有数据点相同的权重。
EMA(指数移动平均线): EMA也计算平均值,但它使用指数衰减的方式,给予最近的数据点更大的权重。EMA的计算稍微复杂一些,它使用一个平滑因子(通常是周期的倒数加一的一半,例如对于10天EMA,平滑因子是2/(10+1))来确定最近数据点的权重。EMA的计算需要一个初始值,通常取为第一天的值或周期内的平均值。
对价格变化的响应:
- SMA对价格变化的响应比较慢,因为它给予所有数据点相同的权重,所以它对最近的价格变动不太敏感。
- EMA对价格变化的响应更快,因为它给予最近的价格更大的权重,所以它能够更快地适应价格的变化。
趋势跟踪:
- 由于SMA的滞后性,它更适用于识别已经确立的趋势。
- EMA由于其敏感性,更适用于捕捉趋势的早期变化。
可以用excel的公式来了解: MA5相当于C2:C6的累加再除以5,EMA5相当于C6*2/(5+1) + F5*(1-2/(5+1)) ,这里2/(N+1)就是平滑因子,1-2/(N+1) = 1- 2/6 = 4/6
002_双均线策略的简单实现
在基本了解了移动平均线这类指标后,我们在不使用backtrader的前提下,自己动手实现一个双均线策略,也通过这个实践过程,去对应感受backtrader的功能。
A_数据获取
一支股票的数据获取在第一篇里有详细的过程,这里直接用第二篇里准备好的代码
# Notebook 数据准备
import akshare as ak
import pandas as pd
def get_df_from_stock(code1):
stock_df = ak.stock_zh_a_hist(symbol=code1, period="daily", start_date="20220901", adjust="qfq")
stock_df.rename(columns={
'日期':'date', '开盘':'open', '收盘':'close',
'最高':'high', '最低':'low', '成交量':'volume',
},inplace=True)
stock_df.index = pd.to_datetime(stock_df.date)
stock_df['openinterest'] = 0
stock_df = stock_df[['open','high','low','close','volume','openinterest']]
return stock_df
myStockList = ['001287','002179','600860','300233','002774']
df_stock_list = []
for x in myStockList:
df_tmp = get_df_from_stock(x)
df_stock_list.append(df_tmp)
df = df_stock_list[1]
df
-----------------------
open high low close volume openinterest
date
2022-09-01 45.90 47.12 45.64 46.75 96128 0
2022-09-02 46.90 47.90 46.55 47.18 59848 0
2022-09-05 47.15 47.86 46.75 46.98 42456 0
2022-09-06 46.98 48.40 46.82 48.19 71577 0
2022-09-07 48.18 48.58 47.88 48.37 56144 0
... ... ... ... ... ... ...
2024-09-19 37.31 37.42 36.30 36.92 47857 0
2024-09-20 36.99 37.19 36.30 36.82 52096 0
2024-09-23 36.60 37.69 36.58 36.87 68754 0
2024-09-24 36.87 38.31 36.65 38.16 93653 0
2024-09-25 38.16 39.05 37.39 37.79 160848 0
501 rows × 6 columns
B_简单数据处理_in_pandas
1) SMA数据
SMA的数据由rolling(滚动)和mean(平均)两个部分组成,pandas里也的确是这么用的
import pandas as pd
import numpy as np
df['Short_MA'] = df['close'].rolling(window=5).mean() # 例如5天移动平均线
df['Long_MA'] = df['close'].rolling(window=10).mean() # 例如10天移动平均线
df.head(20)
-------------------------
open high low close volume op Short_MA Long_MA
date
2022-09-01 45.90 47.12 45.64 46.75 96128 0 NaN NaN
2022-09-02 46.90 47.90 46.55 47.18 59848 0 NaN NaN
2022-09-05 47.15 47.86 46.75 46.98 42456 0 NaN NaN
2022-09-06 46.98 48.40 46.82 48.19 71577 0 NaN NaN
2022-09-07 48.18 48.58 47.88 48.37 56144 0 47.494 NaN
2022-09-08 48.08 49.04 48.08 48.80 61370 0 47.904 NaN
2022-09-09 48.98 49.05 47.53 48.37 56915 0 48.142 NaN
2022-09-13 48.21 49.07 47.90 48.78 50211 0 48.502 NaN
2022-09-14 48.59 50.98 48.22 50.45 113593 0 48.954 NaN
2022-09-15 50.28 50.67 48.38 48.99 68075 0 49.078 48.286
2022-09-16 48.98 50.90 48.75 49.15 85685 0 49.148 48.526
2022-09-19 49.16 50.13 48.35 48.88 58896 0 49.250 48.696
2022-09-20 49.36 49.96 48.73 49.38 55072 0 49.370 48.936
2022-09-21 49.06 49.46 47.88 47.94 50475 0 48.868 48.911
2022-09-22 47.90 49.26 47.65 48.73 67467 0 48.816 48.947
2022-09-23 49.36 50.93 48.49 49.11 136230 0 48.808 48.978
2022-09-26 48.73 48.82 47.29 47.63 74714 0 48.558 48.904
2022-09-27 47.67 47.82 46.94 47.23 61429 0 48.128 48.749
2022-09-28 47.23 47.86 45.13 45.32 109959 0 47.604 48.236
2022-09-29 45.32 46.36 44.83 45.02 76422 0 46.862 47.839
我们看到,SMA的特点就在于N-1日是没有计算数据的,比如5日均线前4天为NaN,10日均线则前9天为NaN。有些时候我们会把NaN用close的值替代掉或者去掉N-1天的数据,这也是上一节看到在股票软件评测系统中有增加100天数据用于计算的选项。增加100天就可以避免做这些操作。
df["Long_MA"][:9] = df['close'][:9]
# 或者
df = df.loc[9:,:]
2)同列当天与前一天比较
这个最典型的就是日收益的计算,拿今天收盘价减去昨天收盘价,在pandas里用shift(x)来实现,
df['c_prev'] = df.close.shift(1)
df['c_next'] = df.close.shift(-1)
df['day_change'] = df.close - df.close.shift(1) # 当天收盘价 - 昨日收盘价
df = df.tail(120)
df.head(10)
---------------------
open high low close volume o Short_MA Long_MA c_prev c_next day_change
date
2024-04-01 33.88 34.35 33.78 34.08 151838 0 33.912 34.982 33.81 33.40 0.27
2024-04-02 34.09 34.10 33.23 33.40 125136 0 33.632 34.651 34.08 32.82 -0.68
2024-04-03 33.21 33.30 32.61 32.82 141144 0 33.552 34.300 33.40 32.83 -0.58
2024-04-08 32.68 32.96 32.25 32.83 118979 0 33.388 34.033 32.82 32.65 0.01
2024-04-09 32.83 33.05 32.48 32.65 92947 0 33.156 33.668 32.83 32.35 -0.18
2024-04-10 32.50 32.58 31.84 32.35 98752 0 32.810 33.361 32.65 31.70 -0.30
2024-04-11 32.00 32.33 31.61 31.70 137972 0 32.470 33.051 32.35 30.79 -0.65
2024-04-12 31.61 31.86 30.61 30.79 224733 0 32.064 32.808 31.70 32.27 -0.91
2024-04-15 30.70 32.33 30.58 32.27 251100 0 31.952 32.670 30.79 32.07 1.48
2024-04-16 32.29 32.80 32.01 32.07 206348 0 31.836 32.496 32.27 32.51 -0.20
3) Cross判断
有了移动平均线,又有了上一个,下一个数据的比较,我们就可以制作cross判断了。
从之前的基础中我们知道,cross交叉是由2组条件相与得到的,无论是股票软件的cross(line1,line2)还是backtrader中的crossover(line1,line2)都需要2条线的数据,这里以5日和10日平均线为例,MA5上穿MA10就是意味着当天的MA5>MA10,而且昨天的MA5.shift(1)<MA10.shift(1) ,所以我们可以得到上穿(金叉)买点和下穿(死叉)卖点。
df['crs_up'] = (df['Short_MA'] > df['Long_MA']) & (df['Short_MA'].shift(1) < df['Long_MA'].shift(1))
df['crs_dn'] = (df['Short_MA'] < df['Long_MA']) & (df['Short_MA'].shift(1) > df['Long_MA'].shift(1))
从输出的数据可以看到,当前一天的MA5<MA10,而当天的MA5>MA10时,crs_up就会置True,表示这里发生了金叉,我们的买卖策略在这里做买入,买入价格使用当天的收盘价。
之后,当前一天的MA5>MA10,而当天的MA5<MA10,crs_dn就会置True,这里就是卖出。
4) EMA的计算及使用上一个值
EMA的计算在上面已经学习过了,它要使用到前一天的EMA和当天的close并根据平滑因子计算,因此EMA不管是多少(5或者10),都只需要计算当天的close和前一天的ema,不像MA5那样前4个都是NaN。
在pandas中可以直接使用ewm和mean()来计算得到:
df['EMA_5'] = df['close'].ewm(span=5, adjust=False).mean()
df[['close','volume','EMA_5']]
-----------------
close volume EMA_5
date
2022-09-01 46.75 96128 46.750000
2022-09-02 47.18 59848 46.893333
2022-09-05 46.98 42456 46.922222
2022-09-06 48.19 71577 47.344815
2022-09-07 48.37 56144 47.686543
... ... ... ...
2024-09-20 36.82 52096 37.085958
2024-09-23 36.87 68754 37.013972
2024-09-24 38.16 93653 37.395981
2024-09-25 37.79 160848 37.527321
2024-09-26 37.69 72755 37.581547
如果没有这么一个函数,我们可以尝试自己来制作。由于是当天的值需要使用到前一天的值,这个比较适合用循环来做,类似于backtrader里的next()中来完成,而不太合适直接用DataFrame的列计算的直接方式。
calc_days = 5
smooth_factor = 2.0/(calc_days + 1)
print('smooth_factor',smooth_factor)
df['calc_ema5'] = 0
# 计算累积值
for i in range(len(df)):
if i == 0:
# 第一个元素就是当天的Close值
df.at[df.index[i], 'calc_ema5'] = df.at[df.index[i], 'close']
else:
# 从第二个元素开始,累加当天的Close值和前一天的累加值
df.at[df.index[i], 'calc_ema5'] = df.at[df.index[i], 'close'] * smooth_factor + df.at[df.index[i - 1], 'calc_ema5'] * (1-smooth_factor)
df[['close','volume','EMA_5','calc_ema5']]
---------------------------
close volume EMA_5 calc_ema5
date
2022-09-01 46.75 96128 46.750000 46.750000
2022-09-02 47.18 59848 46.893333 46.893333
2022-09-05 46.98 42456 46.922222 46.922222
2022-09-06 48.19 71577 47.344815 47.344815
2022-09-07 48.37 56144 47.686543 47.686543
... ... ... ... ...
2024-09-20 36.82 52096 37.085958 37.085958
2024-09-23 36.87 68754 37.013972 37.013972
2024-09-24 38.16 93653 37.395981 37.395981
2024-09-25 37.79 160848 37.527321 37.527321
2024-09-26 37.69 72755 37.581547 37.581547
从输出结果上看,我们自己做的calc_ema5与使用ewm和mean()得到的EMA5的值是一模一样的。
C_绘图与收益计算
对于一个双均线的策略,前面已经计算得到了短均线 SMA5和长均线SMA10,然后根据金叉买入死叉卖出(Cross的计算)得到的买点和卖点,在这样的基础上已经可以计算策略的收益了,也可以使用绘图的模块来绘制K线和买卖位置。
参考文档:
- Python的mpl_finance模块从2020年已经提醒弃用,新mplfinance模块详解(一)-CSDN博客
1)Mpl_finance模块简单绘图
在backtrader里我们都不需要去考虑绘图的问题。这里简单过一下怎么使用mpl_finance模板进行快速绘图。
使用mpl_finance进行K线图绘制非常的简单,只要把dataframe的数据传进去就行了。
import mplfinance as mpf
mpf.plot(df, type='candle',style='charles',volume=True)
需要注意,mpf绘图的df是有格式要求的,但它又恰好与我们制作的准备给backtrader的数据格式相同,即 open,high,low,close,volume五个数据必须按顺序来
open high low close volume
date
2022-09-01 45.90 47.12 45.64 46.75 96128
2022-09-02 46.90 47.90 46.55 47.18 59848
2022-09-05 47.15 47.86 46.75 46.98 42456
2022-09-06 46.98 48.40 46.82 48.19 71577
2022-09-07 48.18 48.58 47.88 48.37 56144
... ... ... ... ... ...
2)添加均线
这里添加上SMA5和SMA10的均线,添加线或点都用addplot,这里数据有点多,添加的图线会看不清,于是数据量截取只保留80天的K线来显示。addplot可以是一个数据,也可以是个list(list里也可以只有一个数据)
import mplfinance as mpf
add_plot= [mpf.make_addplot(df.Long_MA,color='r'),
mpf.make_addplot(df.Short_MA,color='g'),]
mpf.plot(df,addplot=add_plot, type='candle',style='charles',volume=True)
这样就把K线和SMA5/SMA10的线都画出来了。
3)添加买卖点图标
在买点和卖点位置画图标,则需要买点的最低价和卖点的最高价进行图标绘制,数据可以是list,也可以直接是np.ndarray类型。
基于前面已经有了crs_up和crs_dn的列,先通过np.where的使用得到买点和卖点的数据,以买点buy_list为例,当df['crs_up']为True的时候,取df['low']的值,否则就是空。
# 画图标需要有价格,买画在low下,卖画在high上
buy_list = list(np.where(df['crs_up'], df['low'], np.nan)) # list
sell_list = np.where(df['crs_dn'], df['high'], np.nan) # np.ndarray
print(type(buy_list))
print(type(sell_list))
----------------------------
<class 'list'>
<class 'numpy.ndarray'>
然后,把买卖点图标加入到addplot中,就能绘制出带买点卖点的图了。
import mplfinance as mpf
add_plot= [mpf.make_addplot(df.Long_MA,color='r'),
mpf.make_addplot(df.Short_MA,color='g'),
mpf.make_addplot(buy_list,scatter=True,marker='^',markersize=80,color='r'),
mpf.make_addplot(sell_list,scatter=True,marker='v',markersize=80)]
mpf.plot(df,addplot=add_plot, type='candle',style='charles',volume=True)
4)计算收益和成功率
收益计算采用在买点的位置记录close价格,在卖点的位置的close减去买点的价格,最后再乘上一个股票数量(假设为1200股,接近5W);而成功次数用一次买卖计数加1,如果收益为正则成功次数加1的方式计算。
def calcu_profit(df):
df.loc[:,'profit'] = 0.0
total_times = 0
win_times = 0
buyPrice = 0
for index, row in df.iterrows():
if row.crs_up == True:
buyPrice = row.close
if row.crs_dn == True and buyPrice!=0:
total_times += 1
df.loc[index,'profit'] = round(row.close - buyPrice,2)
if row.close -buyPrice >0:
win_times +=1
pct = (win_times/total_times)*100
profit = round(df['profit'].sum(),2)
print('总交易次数', total_times)
print('成功次数', win_times)
print('胜率 %.2f%%'%pct)
print('收益',profit*1200)
calcu_profit(df)
------------------
总交易次数 4
成功次数 2
胜率 50.00%
收益 -3108.0
D_使用ta-lib的指标
双均线比较简单,用pandas直接可以实现,但有些指标像KDJ,MACD,BOLL,RSI等就不是那么容易的实现,我们也不需要重复造轮子,可以直接用ta-lib中的指标。
ta-lib直接pip install安装容易出问题,可以在网站上搜索ta-lib找到通用的离线安装包下载安装
- 【免费】TA-Lib-0.4.26-cp*-cp*m-win*.whlTA-Lib库离线安装文件打包资源-CSDN文库
使用起来也非常方便,以布林线指标为例,直接调用talib.BBANDS即可
import talib
df['Upper'], df['Middle'], df['Lower'] = talib.BBANDS(df['close'],
timeperiod=20,
nbdevup=2,
nbdevdn=2, matype=0)
003_手工实现与backtrader的对比
A_数据获取
数据获取方面,都是需要借助第三方库或者爬虫等,步骤上没什么差别。
手工实现上,直接使用pandasData就可以了,而在backtrader中,还需要通过feeds把pandasData处理成backtrader自己的结构,我们在第二篇里详细介绍了关于Datas,Data,lines等内容,这些是手工简单实现所没有的,也是比较复杂的部分。
B_交易系统设置
手工实现最关键的是没有backtrader的交易系统设置的部分。
持仓position判断,交易规模sizer,手工的代码里没有。
交易手续费与滑点计算,手工的代码里也没有。
交易时机管理,backtrader以第二日开盘价成交,如果要以当日收盘价则为cheat-on_close。
手工代码没有订单的概念,订单的类型,撤单等。
C_观测器与绘图
backtrader有观测器模块observers,可以统计回测信息并进行可视化展示,手工代码没有。
D_参数优化
手工代码没有参数优化功能。
E_评价
手工代码没有内置评价模块,虽然也可以自己计算日收益然后交给第三方库例如quantstats进行评价。
F_绘图增强
手工代码的绘图还处于比较初级的阶段,远远没有backtrader的图形那样实用,不过这些都不是大问题,毕竟股票软件有着更好的视觉体验,我们可以结合着股票软件来进行图形显示。
G_内置指标
backtrader有很多的内置指标,可以直接使用,指标这一块也没有太大的问题,因为手工代码也可以借助ta-lib的库来获取指标计算数据,并且backtrader也内置了ta-lib指标的调用。
小结
手工做一个双均线策略,或者再来一个布林线策略,能让我们对策略实现的流程有更深刻的理解,也细致的复习了关于pandas的典型应用。同时我们也看到了,我们所有想到的和没有想到的,backtrader基本上已经全部帮我们实现了,所以借助backtrader,我们就不需要把时间和精力放在重复造轮子这件事上,而是在弄清楚它的运行机制和原理后,好好利用它去得到适合的标的、适合的策略、适合的时机,赚取相对而言较好的收益。