backtrader.indicators.williams 源代码
#!/usr/bin/env python
"""Williams Indicator Module - Williams %R indicator.
This module provides the WilliamsR indicator developed by Larry
Williams to show overbought/oversold conditions.
Classes:
WilliamsR: Williams %R indicator.
Example:
class MyStrategy(bt.Strategy):
def __init__(self):
self.williamsr = bt.indicators.WilliamsR(self.data, period=14)
def next(self):
# Williams %R above -20 indicates overbought
if self.williamsr.percR[0] > -20:
self.sell()
# Williams %R below -80 indicates oversold
elif self.williamsr.percR[0] < -80:
self.buy()
"""
import math
from . import DownDay, Highest, Indicator, Lowest, TrueHigh, TrueLow, UpDay
[文档]
class WilliamsR(Indicator):
"""
Developed by Larry Williams to show the relation of closing prices to
the highest-lowest range of a given period.
Known as Williams %R (but % is not allowed in Python identifiers)
Formula:
- num = highest_period - close
- den = highestg_period - lowest_period
- percR = (num / den) * -100.0
See:
- http://en.wikipedia.org/wiki/Williams_%25R
"""
lines = ("percR",)
params = (
("period", 14),
("upperband", -20.0),
("lowerband", -80.0),
)
plotinfo = dict(plotname="Williams R%")
plotlines = dict(percR=dict(_name="R%"))
def _plotinif(self):
self.plotinfo.plotyhlines = [self.p.upperband, self.p.lowerband]
def __init__(self):
"""Initialize the Williams %R indicator.
Creates Highest and Lowest indicators for calculation.
"""
super().__init__()
self.highest = Highest(self.data.high, period=self.p.period)
self.lowest = Lowest(self.data.low, period=self.p.period)
[文档]
def next(self):
"""Calculate Williams %R for the current bar.
%R = -100 * (highest - close) / (highest - lowest)
Returns 0.0 if denominator is 0 to avoid division by zero.
"""
h = self.highest[0]
low = self.lowest[0]
c = self.data.close[0]
den = h - low
if den != 0:
self.lines.percR[0] = -100.0 * (h - c) / den
else:
self.lines.percR[0] = 0.0
[文档]
def once(self, start, end):
"""Calculate Williams %R in runonce mode.
Computes %R values across all bars.
"""
h_array = self.highest.lines[0].array
l_array = self.lowest.lines[0].array
c_array = self.data.close.array
larray = self.lines.percR.array
while len(larray) < end:
larray.append(0.0)
for i in range(start, min(end, len(h_array), len(l_array), len(c_array))):
h = h_array[i] if i < len(h_array) else 0.0
low = l_array[i] if i < len(l_array) else 0.0
c = c_array[i] if i < len(c_array) else 0.0
if isinstance(h, float) and math.isnan(h):
larray[i] = float("nan")
elif isinstance(low, float) and math.isnan(low):
larray[i] = float("nan")
else:
den = h - low
if den != 0:
larray[i] = -100.0 * (h - c) / den
else:
larray[i] = 0.0
[文档]
class WilliamsAD(Indicator):
"""
By Larry Williams. It does cumulatively measure if the price is
accumulating (upwards) or distributing (downwards) by using the concept of
UpDays and DownDays.
Prices can go upwards but do so in a fashion that no longer shows
accumulation because updays and downdays are canceling out each other,
creating a divergence.
See:
- http://www.metastock.com/Customer/Resources/TAAZ/?p=125
- http://ta.mql4.com/indicators/trends/williams_accumulation_distribution
"""
lines = ("ad",)
def __init__(self):
"""Initialize the Williams A/D indicator.
Creates up/down day and true high/low indicators.
"""
super().__init__()
self.upday = UpDay(self.data.close)
self.downday = DownDay(self.data.close)
self.truelow = TrueLow(self.data)
self.truehigh = TrueHigh(self.data)
self._accum = 0.0
[文档]
def next(self):
"""Calculate Williams A/D for the current bar.
Accumulates based on up days and down days using true range.
"""
upday_val = self.upday[0]
downday_val = self.downday[0]
if upday_val > 0:
adup = self.data.close[0] - self.truelow[0]
else:
adup = 0.0
if downday_val > 0:
addown = self.data.close[0] - self.truehigh[0]
else:
addown = 0.0
self._accum += adup + addown
self.lines.ad[0] = self._accum
[文档]
def once(self, start, end):
"""Calculate Williams A/D in runonce mode.
Accumulates values across all bars.
"""
upday_array = self.upday.lines[0].array
downday_array = self.downday.lines[0].array
truelow_array = self.truelow.lines[0].array
truehigh_array = self.truehigh.lines[0].array
c_array = self.data.close.array
larray = self.lines.ad.array
while len(larray) < end:
larray.append(0.0)
accum = 0.0
for i in range(start, min(end, len(upday_array), len(downday_array), len(c_array))):
upday_val = upday_array[i] if i < len(upday_array) else 0.0
downday_val = downday_array[i] if i < len(downday_array) else 0.0
close = c_array[i] if i < len(c_array) else 0.0
tl = truelow_array[i] if i < len(truelow_array) else 0.0
th = truehigh_array[i] if i < len(truehigh_array) else 0.0
if upday_val > 0:
adup = close - tl
else:
adup = 0.0
if downday_val > 0:
addown = close - th
else:
addown = 0.0
accum += adup + addown
larray[i] = accum