Having trouble creating trading signals with Pipeline

Hi,

I am trying to create a simple strategy that buys AAPL when the 50 day Simple Moving Average (SMA) crosses above the 100 day SMA (as much as possible with available cash) and sells AAPL (all positions) when the 50 day SMA crosses below the 100 day SMA. In the code below, the log output shows the correct calculations for the moving averages each day and shows that they barely cross each other, as expected. However, the algorithm is erroneously trading very frequently, every couple of days. I think that there is something wrong with the reference to the moving average calculations, which are calculated using Pipeline.

Looking at the log output of the attached backtest, the algorithm should create the following transactions; these are the only times that the moving averages cross:
Sell 8/5/15
Sell 1/15/16

Would anyone be able to help? Thank you! Much appreciated :)

-Tommy

17
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
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.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage

# Create custom factor subclass to calculate a market cap based on yesterday's
# close
class MarketCap(CustomFactor):

# Pre-declare inputs and window_length
inputs = [morningstar.valuation.market_cap]
window_length = 1

# Compute market cap value
def compute(self, today, assets, out, mkt_cap):
out[:] = mkt_cap[-1]

def initialize(context):

pipe = Pipeline()
attach_pipeline(pipe, 'example')

# Construct the custom factor
mkt_cap = MarketCap()

# Create and apply a filter representing the top 500 equities by MarketCap. Couldn't get this to work without narrowing down universe first.
mkt_cap_top_500 = mkt_cap.top(500)

# Narrow the universe
pipe.set_screen(mkt_cap_top_500)

context.stock=symbol('AAPL')
set_benchmark(sid(24))

context.sma_short= SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50)
context.sma_long= SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=100)

# get the output of my pipeline
context.output = pipeline_output('example')

# index into it searching for just the security I'm looking for
aapl = context.output.loc[symbols('AAPL')]
log.info(aapl)

update_universe(context.output.index)

#If SMA short crosses above SMA long, then buy as much as possible.
if context.sma_short > context.sma_long and                 context.portfolio.positions_value == 0:
order_value(context.stock, context.portfolio.cash)

#If SMA short crosses below SMA long, then sell everything.
if context.sma_short < context.sma_long and context.portfolio.positions_value>0:
order_target(context.stock, 0)
def handle_data(context, data):
record(positions=context.portfolio.positions_value,
cash=context.portfolio.cash)
There was a runtime error.
3 responses

You could also add record(SMA_diff=context.sma_short-context.sma_long) inside trading (not handle_data) and see when it crosses 0.

Hi Andre,

When I tried that, I got the following error:

ValueError: Record only supports numeric values. Non-numeric value passed for key 'SMA_diff'


I get the same error when trying to record context.sma_short and context.sma_long directly. I wonder if these are variables are arrays and I need to be referencing some element of the arrays?

Yes, you may have to use float(context.sma_short) and likewise with sma_long. Each factor in Pipeline output is a pandas.Series indexed by securities; when you only have one security, it's still a one-element Series, but you can convert it to a regular float as above.