Hey John,
You gave my developer and I access to Quantopian earlier this year and we built an algo based off a technical analysis oscillator, Williams %R. At that time it back tested well, however I tried to run it again and it gave me an error due to my code. I wanted to know if you can help. Look forward to spending more time on Quantopian. Thanks!
Jason
This example algorithm tracks the volume weighted daily average
price for all stocks, buying when the stock's price is above the
vwap, and selling when the stock's price is below. This is known
as a momentum investment strategy (buy on the way up, sell on the
way down).
The algorithm exposes two parameters - buymargin and sellmargin.
These parameters control how far above/below the vwap the price
must move in order to trigger orders.
In this example, the trading logic is in the main body of the
script, while a helper class for daily vwap is defined below.
Also notice the use of a dict object to hold algorithm state.
In this case it is a map of security id -> dailyVWAP objects,
but it is a common pattern you can use in almost all algos.
Finally, the example defines two parameters for use in
optimization.
import logging
logger.setLevel(logging.DEBUG)
set_filter('symbol',['AAPL'])
define_parameter('buymargin',value_range=(0.0,1.0), default=0.005)
define_parameter('sellmargin',value_range=(0.0,1.0), default=0.005)
rMap = {}
def handle_events(eventQueue):
for curTick in eventQueue:
r = getWilliamsR(curTick)
if(r == None):
continue
if r < -75:
order(curTick.sid,-10000000)
elif r > -20:
order(curTick.sid,5000000)
def getWilliamsR(curTick):
if curTick.sid not in rMap:
rMap[curTick.sid] = WilliamsR()
rMap[curTick.sid].update(curTick)
return rMap[curTick.sid].value
class WilliamsR:
"""A class that calculates Williams %R."""
def init(self):
self.ticks = []
self.williamsR = None
self.daysInAvg = 28
self.value = None
def update(self,curTick):
"""curTick is expected to be an event object from
the quantopian simulator, as is passed to
handle_events"""
if len(self.ticks) > 0 and (self.ticks[-1].dt.day != curTick.dt.day):
close = self.ticks[-1].price
high = max([x.price for x in self.ticks])
low = min([x.price for x in self.ticks])
self.value = ((high - close) / (high - low)) * -100
#logger.debug("Current Williams R value: %f" % self.value)
else:
self.value = None
self.ticks.append(curTick)
#use a list comprehension to filter the ticks to those within
#desired day range. The dt properties are full datetime object
#and provide overloads for arithmetic operations.
self.ticks = [x for x in self.ticks if (x.dt - curTick.dt).days <= self.daysInAvg]