筆記
由於歷史原因,保留此帖子。指標和示例已在源代碼中更新, 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()