Hi, I'm fairly new to quantopian and I'm experimenting with a mean reversion type algorithm. However, I'm seeing runtime errors and can't figure out what could be causing them. I'm trying to use pipeline to filter in those companies from the Q500US with common shares and EBITDA . If anyone could help me figure out where I'm going wrong and perhaps some provide any general pointers I would be very grateful. I've included my workings below.
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.data import morningstar
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.filters.morningstar import Q500US
Strategy
Prices that deviate from the mean eventually move back to the mean
Overpriced stocks will Fall
Underpriced stocks will rise
If 10d SMA is below 30d SMA = Price will go up/Open long position
If 10d SMA is above 30d SMA = Price will go down/Open short position
The bigger the difference between 10d and 30d SMA = The more likely stock will return to mean/Open bigger position
def initialize(context):
## Rebalance once a week, Begining of week, At market Open
##...................................................................................
schedule_function(rebalance, date_rules.week_start(), time_rules.market_open(hours=1))
## Record every day, At market close
##..................................................................................
schedule_function(record_vars, date_rules.every_day(), time_rules.market_close(hours=1))
attach_pipeline(make_pipeline(), 'my_pipeline')
def make_pipeline():
# Create a pipeline object.
pipe = Pipeline()
## Get latest Revenue Value
##..............................................................................
ebitda = morningstar.income_statement.ebitda.latest
pipe.add(ebitda, 'ebitda')
## Get share class (If we only want primary shares)
##..............................................................................
share_class = morningstar.share_class_reference.is_primary_share.latest
## Rank the companies based on (Revenue)
ranked_ebitda = ebitda.rank(ascending=False)
ranked_ebitda = ebitda > 1
pipe.add(ranked_ebitda, 'ebitda_rank')
## Rank the companies based on (primary shares)
ranked_shares = share_class
pipe.add(ranked_shares, 'primary_shares')
## Create a sfilter to narrow down securities which are given back to pipe (shareclass=boolean)
pipe = pipe.set_screen(Q500US & (ebitda > 1) & (share_class==True))
return pipe
def before_trading_start(context, data):
## Pipeline_output returns a pandas DataFrame with the results of our factors
## and filters.
context.output = pipeline_output('my_pipeline')
# Keep a list reference and a set reference to all of our pipeline securities
# (set has much faster lookup)
context.security_list = context.output
context.security_set = set(context.security_list)
Decide whether to take long or short position
Decide size of the position
def compute_weights(context, data):
## Get 30 day window of close prices
hist = data.history(context.security_list, 'price', 30, '1d')
## Store price history
prices_10 = hist[-10:]
prices_30 = hist[-30:]
## Store Avg prices
sma_10 = prices_10.mean()
sma_30 = prices_30.mean()
## Define relative difference between 10d and 30d SMA
raw_weights = (sma_10 - sma_30) / sma_30
normalized_weights = raw_weights / raw_weights.abs().sum()
return normalized_weights
Places Orders
def rebalance(context, data):
weights = compute_weights(context, data)
for security in context.security_list:
if data.can_trade(security):
order_target_percent(security, weights[security])
Count how many Long and Short positions each day
def record_vars(context, data):
longs = shorts = 0
positions = context.portfolio.positions
long_count = 0
short_count = 0
for position in context.portfolio.positions.itervalues():
if position.amount > 0:
longs += 1
elif position.amount < 0:
shorts += 1
## Record leverage, number of songs, number of shorts
record(leverage = context.account.leverage, long_count=longs, short_count = shorts)