Given the code below, when I try to run it, as is, I get the following in Runtime Errors tab:
There was a runtime error. See the more detailed error below. If you
need help, please send us feedback.
And nothing else below giving any more detail. If i comment out line 55
sma=data[context.SPY].vwap(15)
then the code runs fine. But that line should not be causing a problem, I've used it in other algos. Anyone have any ideas why the error is getting thrown?
```
Use SPY 15 day MA to determine when to go to cash
When not in cash buy and hold the most undervalued sectors
import datetime
import math
import numpy
import pandas
def clean_col(df):
df = df.fillna(0)
df = df[['rank', 'sid']]
log.info(' \n %s % df.head()')
return df
def initialize(context):
#
#
#Variables for later
context.day=None
context.pauseUntil=63
context.timestep=0
context.margin_req=0
context.totalShorts=0
context.totalLongs=0
context.cash=0
context.oldRanks=None
context.timer=0
context.holdNmanyDays=63
context.liquid=1
#
#
#Set constraints on borrowing
context.pct_invested_threshold=1 #Set limit on percent invested (as a decimal)
context.init_margin=.01 #Set initial margin requirement
context.maint_margin=.01 #Set the maintenance margin requirement
#
#
#Read universe
context.SPY=sid(8554)
context.Sectors=[sid(19662), sid(19659), sid(19656), sid(19661), sid(19655), sid(19658), sid(19660), sid(19654), sid(19657)]
#Read the rankings
fetch_csv('https://dl.dropboxusercontent.com/s/7shk9xm1xi311at/Ranks_QuantopianTest.csv',
date_column='Date',
post_func=clean_col)
set_commission(commission.PerShare(cost=0.00))
set_slippage(slippage.FixedSlippage(spread=0.00))
def handle_data(context, data):
sma=data[context.SPY].vwap(15)
update_newFrame(context, data)
#Set Liquidate to false
Liquidate = 0
#If its before the pause time
if context.timestep == 1:
nshares=context.cash / data[sid(8554)].price
order(sid(8554), nshares)
context.liquid=0
return
elif context.timestep == (context.pauseUntil-1):
#log.debug ("Liquidating SPY because context.pauseUntil="+str(context.pauseUntil)+" and timestep = "+str(context.timestep))
Liquidate = 1
if context.timestep < (context.pauseUntil-1): #context.PauseUntil:
context.timer=0
return
if context.timer >= context.holdNmanyDays: #reset the timer to 0 after the specified holding period
#log.debug ("Liquidating and rotating sectors now because "+str(context.timer)+" indicates we have reached "+str(context.holdNmanyDays))
Liquidate = 1
context.timer=0
#
#
#Its time to trade!
if context.liquid == 1: #if we are in cash
ts1=None
tr1=-100
ts2=None
tr2=-100
ts3=None
tr3=-100
for stock in context.Sectors:
if 'rank' in data[stock]:
if data[stock]['rank']>tr1:
ts3=ts2
tr3=tr2
ts2=ts1
tr2=tr1
tr1=data[stock]['rank']
ts1=stock
elif data[stock]['rank']>tr2:
ts3=ts2
tr3=tr2
tr2=data[stock]['rank']
ts2=stock
# elif data[stock]['rank']>tr3:
# tr3=data[stock]['rank']
# ts3=stock
else:
log.debug ("WARNING: rank not found for ticker "+str(stock))
if ts1!=None:
nshares=context.cash*0.49/data[ts1].price
#log.debug ("Buying most undervalued stock "+str(ts1)+" with score of "+str(tr1))
generate_order(ts1, nshares, context, data)
context.liquid=0 #we are not in cash
if ts2!=None:
nshares=context.cash*0.49/data[ts2].price
#log.debug ("Buying second most undervalued stock "+str(ts2)+" with score of "+str(tr2))
generate_order(ts2, nshares, context, data)
context.liquid=0 #we are not in cash
if ts3!=None:
nshares=context.cash*0.3333/data[ts3].price
generate_order(ts3, nshares, context, data)
context.liquid=0 #we are not in cash
log.debug ("Changed context.liquid to "+str(context.liquid))
if Liquidate == 1:
for i in context.Sectors:
liquidate_position(i, context)
liquidate_position(context.SPY, context)
context.liquid=1
Supporting Functions
def update_newFrame(context, data):
#
context.cash = context.portfolio.cash
context.portvalue = context.portfolio.positions_value
context.totalShorts=0
for sym in data.keys():
if context.portfolio.positions[sym].amount < 0:
context.totalShorts += (context.portfolio.positions[sym].amount * data[sym].price)
else:
context.totalLongs += (context.portfolio.positions[sym].amount * data[sym].price)
update_portvals(context)
#Handle assigning the timestep number (1 day is 1 timestep)
if get_datetime().day <> context.day: #look for a new day
context.day=get_datetime().day
context.timestep += 1
context.timer += 1
#log.info ( "Cash: "+str(context.cash)+"; Margin Req: "+str(context.margin_req)+" Avail Cash:"+str(context.cash - context.margin_req) )
if context.timestep>context.pauseUntil:
if context.cash < context.margin_req: #check for margin calls daily
generate_marginCall(context, data)
def update_portvals(context):
#Update account information when this function is called
context.total_equity = context.cash + context.portvalue
context.pct_invested = (context.totalLongs-context.totalShorts) / context.total_equity
context.pct_cash = context.cash / context.total_equity
context.margin_req = abs(context.totalShorts * context.maint_margin)
def generate_order(sym, size, context, data):
#log.info("Call to generate_order")
if size>0: #Opening a long position
#log.info("Buy long "+str(size)+" shares "+str(sym) )
#log.info("Cash = "+str(context.cash)+"; Current Margin Req.="+str(context.margin_req) )
#Is there enough available cash to buy the position
if (context.cash-context.margin_req) < size * data[sym].price:
#log.info("Trade canceled : Insufficient funds.")
return
#Deduct price from cash and add to portfolio value
context.cash -= size * data[sym].price
context.portvalue += size * data[sym].price
context.totalLongs += size * data[sym].price
update_portvals(context)
#Abort the transaction if the percent invested is greater than the threshold
#before slippage and commissions
if context.pct_invested > context.pct_invested_threshold:
context.cash += size * data[sym].price
context.portvalue -= size * data[sym].price
context.totalLongs -= size * data[sym].price
update_portvals(context)
if size>100:
log.info("Re-generating order for "+str(size*context.pct_invested_threshold)+" instead of "+str(size))
generate_order(sym,size*context.pct_invested_threshold, context,data)
return
#Abort the transaction if the investment would generate a margin call
if context.cash < context.margin_req:
log.info("Invest would generate a margin call")
context.cash += size * data[sym].price
context.portvalue -= size * data[sym].price
context.totalLongs -= size * data[sym].price
update_portvals(context)
return
order(sym,size)
else: #Opening a short position
#log.info("Generating a short order for "+str(size)+" shares of "+str(sym)+" and context.cash="+str(context.cash)+" and context.margin_req="+str(context.margin_req) )
#Is there at least enough available cash to cover the initial maintenance margin
if (context.cash-context.margin_req) < abs(size * data[sym].price * context.init_margin):
#log.info("Trade canceled")
return
#Deduct price from cash and add to portfolio value (note that size is negative)
context.cash -= size * data[sym].price
context.portvalue += size * data[sym].price
context.totalShorts += size * data[sym].price
update_portvals(context)
#Abort the transaction if the percent invested is greater than the threshold
#before slippage and commission
if context.pct_invested > context.pct_invested_threshold:
context.cash += size * data[sym].price
context.portvalue -= size * data[sym].price
context.totalShorts -= size * data[sym].price
update_portvals(context)
#log.info("Trade canceled")
return
#Abort the transaction if the investment would generate a margin call
if context.cash < context.margin_req:
context.cash += size * data[sym].price
context.portvalue -= size * data[sym].price
context.totalShorts -= size * data[sym].price
update_portvals(context)
#log.info("Trade canceled")
return
order(sym,size)
def generate_marginCall(context,data):
#This function should be coded to address margin calls
#log.info("Margin call")
return(0)
def liquidate_position(sym,context):
if context.portfolio.positions[sym].amount is not 0:
#log.debug("Liquidating "+str(context.portfolio.positions[sym].amount)+" shares of position "+str(sym))
order(sym, -context.portfolio.positions[sym].amount)
```