Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Williams %R

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]  
1 response

Hi @Jason,

We have modified our API pretty substantially since last year when we were in private alpha. The new API is documented here: https://www.quantopian.com/help. I did a quick refactoring of your code from above to make it pass our validation. Running a backtest, it seems the code isn't ordering, so you'll need to do a bit more work on this code sample!

thanks,
fawce

def initialize(context):  
    # apple  
    context.sid_list = [sid(24)]  
    context.buymargin = 0.005  
    context.sellmargin = 0.005  
    context.rMap = {}

def handle_data(data, context):  
    for cur_sid in context.sid_list:  
        curTick = data[cur_sid]  
        r = getWilliamsR(curTick, context)  
        if(r == None):  
            continue  
        if r < -75:  
            order(curTick.sid,-10000000)  
        elif r > -20:  
            order(curTick.sid,5000000)

def getWilliamsR(curTick, context):  
    if curTick.sid not in context.rMap:  
        context.rMap[curTick.sid] = WilliamsR()

    context.rMap[curTick.sid].update(curTick)  
    return context.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  
            #log.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.datetime - curTick.datetime).days <= self.daysInAvg]  
Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.