笔记
由于历史原因,保留此帖子。指针和示例已在源代码中更新, PivotPoint
现在可以自动耦合,删除用户代码的样板。
将写一篇新的帖子来引用这个帖子。同时,请检查源中的更新示例。
一个有趣的请求出现了:
- 中心点
这很有趣,因为指针是如何定义的。文献可以在StockCharts 的 PivotPoint找到。 PivotPoints 使用过去时间框架的close
价、 high
价和low
。例如对于每日时间范围:
- 日线图的枢轴点使用上个月的数据
这可能看起来很麻烦,因为对于每个时间范围都需要定义必须使用的其他时间范围。查看公式会引发另一个问题:
Pivot Point (P) = (High + Low + Close)/3 Support 1 (S1) = (P x 2) - High Support 2 (S2) = P - (High - Low) Resistance 1 (R1) = (P x 2) - Low Resistance 2 (R2) = P + (High - Low)
即使文本充满了对前期和过去的引用……这些公式似乎引用了当前时间点。让我们按照文本的建议,在我们第一次尝试 PivotPoint 时使用以前的方法。但首先让我们通过这样做来解决不同时间框架的问题:
- 指针无法解决问题
尽管这可能看起来令人困惑,但必须考虑到指针必须尽可能愚蠢并由实际公式组成。问题将解决如下:
data = btfeeds.ADataFeed(..., timeframe=bt.TimeFrame.Days) cerebro.adddata(data) cerebro.resampledata(data, timeframe=bt.TimeFrame.Months)
后来在战略中:
class MyStrategy(bt.Strategy): def __init__(self): self.pp = PivotPoint(self.data1) # the resampled data
现在很清楚了。系统将拥有数据,以及重新采样到所需时间范围的额外输入。 PivotPoint
指针将与重新采样的数据一起使用,这些数据已经在所需的每月时间范围内,而原始数据时间范围是每天。
可以开发指针。让我们从遵循文本指示而不是公式开始,然后回顾 1 个句点。
class PivotPoint1(bt.Indicator): lines = ('p', 's1', 's2', 'r1', 'r2',) def __init__(self): h = self.data.high(-1) # previous high l = self.data.low(-1) # previous low c = self.data.close(-1) # previous close self.lines.p = p = (h + l + c) / 3.0 p2 = p * 2.0 self.lines.s1 = p2 - h # (p x 2) - high self.lines.r1 = p2 - l # (p x 2) - low hilo = h - l self.lines.s2 = p - hilo # p - (high - low) self.lines.r2 = p + hilo # p + (high - low)
该策略将查看参数usepp1
以使用此PivotPoint1
def __init__(self): if self.p.usepp1: self.pp = PivotPoint1(self.data1) else: self.pp = PivotPoint(self.data1)
并且输出由一个简单的next
方法控制
def next(self): txt = ','.join( ['%04d' % len(self), '%04d' % len(self.data0), '%04d' % len(self.data1), self.data.datetime.date(0).isoformat(), '%.2f' % self.pp[0]]) print(txt)
让我们运行:
./ppsample --usepp1
和输出:
0041,0041,0002,2005-02-28,2962.79 0042,0042,0002,2005-03-01,2962.79 ...
马上就清楚了:索引 41 已经属于第 2个月。这意味着我们已经跳过了 1 个月的指针计算。现在很清楚为什么 StockCharts 中的文本总是提到计算发生在上个月,但公式似乎引用了当前时刻。
开发人员可能面临相同的设计决策,其中包含多个时间范围内的多个数据。
在当前每日点,只能交付上个月的关闭柱。
这就是为什么next
方法是查看索引[0]
的原因。所有这一切都有一个非常简单的解决方法,那就是编写公式,就像 StockCharts 记录它们一样。
class PivotPoint(bt.Indicator): lines = ('p', 's1', 's2', 'r1', 'r2',) plotinfo = dict(subplot=False) def __init__(self): h = self.data.high # current high l = self.data.low # current high c = self.data.close # current high self.lines.p = p = (h + l + c) / 3.0 p2 = p * 2.0 self.lines.s1 = p2 - h # (p x 2) - high self.lines.r1 = p2 - l # (p x 2) - low hilo = h - l self.lines.s2 = p - hilo # p - (high - low) self.lines.r2 = p + hilo # p + (high - low)
没有usepp1
的运行:
./ppsample
新的输出是:
0021,0021,0001,2005-01-31,2962.79 0022,0022,0001,2005-02-01,2962.79 ...
瞧!第 1个月有20
个交易日,一旦完成,指针计算值并可以交付。唯一打印的行是p
,如果 2行中的值相同,是因为该值在整个下个月保持不变。引用股票图表:
Once Pivot Points are set, they do not change and remain in play throughout ...
该指针已经可以使用。让我们去绘图吧。已设置绘图参数
plotinfo = dict(subplot=False)
计算值与数据比例一致,就像移动平均线一样,它可以沿着数据绘制(因此subplot= False
)
使用--plot
运行:
./ppsample --plot
起泡的藤壶再次攻击。该指针已绘制在月度数据(其来源)上,这在日线图上没有提供任何视觉指示,这将非常有用。
但是backtrader
支持从一个数据到另一个数据的交叉绘图。尽管需要在1.2.8.88
中进行少量添加以支持对不同时间范围的数据进行交叉绘图。
这是通过让plotmaster
说出绘图目标是什么来实现的,方法是将其添加到指针的plotinfo
属性中:
./ppsample --plot --plot-on-daily
视觉反馈现在有助于了解PivotPoint
提供的内容。
脚本代码和用法
在backtrader
的来源中作为示例提供:
$ ./ppsample.py --help usage: ppsample.py [-h] [--data DATA] [--usepp1] [--plot] [--plot-on-daily] Sample for pivot point and cross plotting optional arguments: -h, --help show this help message and exit --data DATA Data to be read in (default: ../../datas/2005-2006-day-001.txt) --usepp1 Have PivotPoint look 1 period backwards (default: False) --plot Plot the result (default: False) --plot-on-daily Plot the indicator on the daily data (default: False)
PivotPoint
的代码
from __future__ import (absolute_import, division, print_function,) # unicode_literals) import backtrader as bt class PivotPoint1(bt.Indicator): lines = ('p', 's1', 's2', 'r1', 'r2',) def __init__(self): h = self.data.high(-1) # previous high l = self.data.low(-1) # previous low c = self.data.close(-1) # previous close self.lines.p = p = (h + l + c) / 3.0 p2 = p * 2.0 self.lines.s1 = p2 - h # (p x 2) - high self.lines.r1 = p2 - l # (p x 2) - low hilo = h - l self.lines.s2 = p - hilo # p - (high - low) self.lines.r2 = p + hilo # p + (high - low) class PivotPoint(bt.Indicator): lines = ('p', 's1', 's2', 'r1', 'r2',) plotinfo = dict(subplot=False) def __init__(self): h = self.data.high # current high l = self.data.low # current high c = self.data.close # current high self.lines.p = p = (h + l + c) / 3.0 p2 = p * 2.0 self.lines.s1 = p2 - h # (p x 2) - high self.lines.r1 = p2 - l # (p x 2) - low hilo = h - l self.lines.s2 = p - hilo # p - (high - low) self.lines.r2 = p + hilo # p + (high - low)
脚本的代码。
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import backtrader as bt import backtrader.feeds as btfeeds import backtrader.utils.flushfile from pivotpoint import PivotPoint, PivotPoint1 class St(bt.Strategy): params = (('usepp1', False), ('plot_on_daily', False)) def __init__(self): if self.p.usepp1: self.pp = PivotPoint1(self.data1) else: self.pp = PivotPoint(self.data1) if self.p.plot_on_daily: self.pp.plotinfo.plotmaster = self.data0 def next(self): txt = ','.join( ['%04d' % len(self), '%04d' % len(self.data0), '%04d' % len(self.data1), self.data.datetime.date(0).isoformat(), '%.2f' % self.pp[0]]) print(txt) def runstrat(): args = parse_args() cerebro = bt.Cerebro() data = btfeeds.BacktraderCSVData(dataname=args.data) cerebro.adddata(data) cerebro.resampledata(data, timeframe=bt.TimeFrame.Months) cerebro.addstrategy(St, usepp1=args.usepp1, plot_on_daily=args.plot_on_daily) cerebro.run() if args.plot: cerebro.plot(style='bar') def parse_args(): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description='Sample for pivot point and cross plotting') parser.add_argument('--data', required=False, default='../../datas/2005-2006-day-001.txt', help='Data to be read in') parser.add_argument('--usepp1', required=False, action='store_true', help='Have PivotPoint look 1 period backwards') parser.add_argument('--plot', required=False, action='store_true', help=('Plot the result')) parser.add_argument('--plot-on-daily', required=False, action='store_true', help=('Plot the indicator on the daily data')) return parser.parse_args() if __name__ == '__main__': runstrat()