I've been trying to write a similar algo to this one, but that uses the built-in RSI factor rather than returns. I keep getting the same error.
Here's the algo:
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import RSI
import math
# DollarVolume will calculate yesterday's dollar volume for each stock in the universe.
class DollarVolume(CustomFactor):
# We need close price and trade volume for this calculation.
inputs = [USEquityPricing.close, USEquityPricing.volume]
window_length = 1
# Dollar volume is volume * closing price.
def compute(self, today, assets, out, close, volume):
out[:] = (close[0] * volume[0])
def initialize(context):
# Define the other variables
context.long_leverage = 0.5
context.short_leverage = -0.5
context.rsi_lookback = 2
# Rebalance every Monday (or the first trading day if it's a holiday).
# At 11AM ET, which is 1 hour and 30 minutes after market open.
schedule_function(rebalance,
date_rules.every_day(),
time_rules.market_close())
# Create, register and name a pipeline in initialize.
pipe = Pipeline()
attach_pipeline(pipe, 'rsi_example')
# Create a dollar_volume factor using default inputs and window_length
dollar_volume = DollarVolume()
pipe.add(dollar_volume, 'dollar_volume')
# Define high dollar-volume filter
high_dollar_volume = dollar_volume.percentile_between(98, 100)
# Construct RSI factor.
rsi = RSI(inputs=[USEquityPricing.close], window_length=context.rsi_lookback)
# Define high and low RSI to be the bottom 10% and top 10% of
# securities in the high dollar volume group.
rsi_high = rsi.percentile_between(90, 100, mask=high_dollar_volume)
rsi_low = rsi.percentile_between(0, 10, mask=high_dollar_volume)
# Add RSI rank factor to our pipeline, using high dollar volume mask.
pipe.add(rsi.rank(mask=high_dollar_volume), 'rsi')
# Add a filter to the pipeline such that only high-RSI and low-RSI
# securities are kept.
pipe.set_screen(rsi_high | rsi_low)
# Add the rsi_high and rsi_low filters as columns to the pipeline so
# that when we refer to securities remaining in our pipeline later,
# we know which ones belong to which category.
pipe.add(rsi_low, 'rsi_low')
pipe.add(rsi_high, 'rsi_high')
# Called every day before market open. This is where we access the securities
# that made it through the pipeline.
def before_trading_start(context, data):
# Pipeline_output returns the constructed dataframe.
context.output = pipeline_output('rsi_example')
# Sets the list of securities we want to long as the securities with a 'True'
# value in the rsi_low column.
context.long_secs = context.output[context.output['rsi_low']]
# Sets the list of securities we want to short as the securities with a 'True'
# value in the rsi_high column.
context.short_secs = context.output[context.output['rsi_high']]
# Update our universe to contain the securities that we would like to long and short.
update_universe(context.long_secs.index.union(context.short_secs.index))
# This rebalancing is called according to our schedule_function settings.
def rebalance(context, data):
# Get any stocks we ordered last time that still have open orders.
open_orders = get_open_orders()
# Set the allocations to even weights in each portfolio.
long_weight = context.long_leverage / (len(context.long_secs) + len(open_orders)/2)
short_weight = context.short_leverage / (len(context.short_secs) + len(open_orders)/2)
# For each security in our universe, order long or short positions according
# to our context.long_secs and context.short_secs lists, and sell all previously
# held positions not in either list.
for stock in data:
# Guard against ordering too much of a given security if a previous order
# is still unfilled.
if stock not in open_orders:
if stock in context.long_secs.index:
order_target_percent(stock, long_weight)
elif stock in context.short_secs.index:
order_target_percent(stock, short_weight)
else:
order_target_percent(stock, 0)
# Log the long and short orders each week.
log.info("Todays's longs: "+", ".join([long_.symbol for long_ in context.long_secs.index]))
log.info("Todays's shorts: " +", ".join([short_.symbol for short_ in context.short_secs.index]))
# The handle_data function is run every bar.
def handle_data(context,data):
# Record and plot the leverage of our portfolio over time.
record(leverage = context.account.leverage)
# We also want to monitor the number of long and short positions
# in our portfolio over time. This loop will check our positition sizes
# and add the count of longs and shorts to our plot.
longs = shorts = 0
for position in context.portfolio.positions.itervalues():
if position.amount > 0:
longs += 1
if position.amount < 0:
shorts += 1
record(long_count=longs, short_count=shorts)
And here's the error:
ValueError: Unknown keyword argument 'locals_dict'
There was a runtime error on line 68.
Any help would be much appreciated.
Graham