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