Question about Log files and algorithm

I am having two problems at the moment.

1) I decided to write an algorithm that would buy when the SPY 15 day MA crosses over its 126 day MA and sell when it crosses below. The code is below. For the entire backtest period, the ratio of 15 day to 126 day MA was 1, exactly. So I'm not sure why this isn't working correctly.

2) I like to use "print" statements when debugging my algorithms to ensure they are producing the correct results. The log of the backtest (when I'm doing a build) seems to print the print statements but if I do more than 1 build I see print statements from the previous build intermixed with the print statements from the new build. Is it possible to clear the log files from one build to the next to avoid this problem?

#Buy and sell SPY when 15 day MA is above 126 day MA

def initialize(context):
#initiate the global i
#    global i
#    i=0
context.SPY = sid(8554)

#Set min/max notional
context.max_notional = 10000.0
context.min_notional = -10000.0

def handle_data(context, data):
#    global i
#    i=i+1
#    print(str(i))

#compute the notional portfolio value
notional = context.portfolio.positions[context.SPY].amount * data[context.SPY].price
#compute a notional value where short positions require 2x cash
#notional =
#test the market MA
MAR_SPY = data[context.SPY].vwap(15) / data[context.SPY].vwap(126)
print(str(data[context.SPY].vwap(15))+" "+str(data[context.SPY].vwap(126))+" "+str(MAR_SPY))
if MAR_SPY > 1 and notional < context.max_notional:
order(context.SPY,+100)
print("Notional="+str(notional))
elif MAR_SPY < 1 and notional > context.min_notional:
order(context.SPY,-100)
print("Notional="+str(notional))
6 responses

In a backtest the vwap() function isn't warmed up with data prior to the backtest period (unlike papertrading).

So for the first 15 days both vwap() functions will be returning the same number. And "some number" divided by itself is always one.

After the first 15 days the ratio changes as you are then using a different number in the numerator and denominator.

3
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
#Buy and sell SPY when 15 day MA is above 126 day MA

def initialize(context):
#initiate the global i
#    global i
#    i=0
context.SPY = sid(8554)

#Set min/max notional
context.max_notional = 10000.0
context.min_notional = -10000.0

def handle_data(context, data):
#    global i
#    i=i+1
#    print(str(i))

#compute the notional portfolio value
notional = context.portfolio.positions[context.SPY].amount * data[context.SPY].price
#compute a notional value where short positions require 2x cash
#notional =
#test the market MA
V15_SPY = data[context.SPY].vwap(15)
V126_SPY = data[context.SPY].vwap(126)
MAR_SPY = V15_SPY / V126_SPY
#print(str(data[context.SPY].vwap(15))+" "+str(data[context.SPY].vwap(126))+" "+str(MAR_SPY))
log.info( 'MAR = {:.4f} V15 = {:.3f} V126 = {:.3f}'.format(MAR_SPY, V15_SPY, V126_SPY))
record( MAR_SPY = MAR_SPY )
#record( V15_SPY = V15_SPY )
#record( V126_SPY = V126_SPY )

if MAR_SPY > 1 and notional < context.max_notional:
order(context.SPY,+100)
print("Notional="+str(notional))
elif MAR_SPY < 1 and notional > context.min_notional:
order(context.SPY,-100)
print("Notional="+str(notional))
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Hi Daniel:

Sorry about the issue regarding some log output from previous builds intermingling with log output from the current build. We're aware of that intermittent issue and it's on our queue to fix. It just moved up in priority.

thanks,
Jean

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.

@ Dennis - That makes sense. So, if the longest MA I am using is 126 days, I essentially want to delay trading until day 127. Is there a way to pause the backtest until the vwap function IS "warmed up"? Can I pause both the algorithm and benchmark? If not, I can work around that. You said in paper trading everything is "warmed up". Is papertrading the same thing as walk-forward testing or is it a more sophisticated backtester? If the latter, how do I load my algorithm into the papertrader?

@ Jean - Thanks and no worries, i can work around it for now. Just wanted to make sure I wasn't doing something foolish.

You will have to build your own work around for the 126 day delay. The backtester doesn't do that for you.

Papertrading on Quantopian is a live walk-forward test. I haven't done it myself so you should double-check the "warm up" assumption if you do it.

Got it. Thanks again.

So what I wanted to do (as a first effort) was to simply buy SPY if my MA ratio was equal to 1. This was easily accomplished by changing '>' to '>=' and by printing what the program is doing I can verify that it is doing what I want:

#Buy and sell SPY when 15 day MA is above 126 day MA

def initialize(context):
#initiate the global i
#    global i
#    i=0
context.SPY = sid(8554)

#Set min/max notional
context.max_notional = 10000.0
context.min_notional = -10000.0

def handle_data(context, data):
#    global i
#    i=i+1
#    print(str(i))

#compute the notional portfolio value
notional = context.portfolio.positions[context.SPY].amount * data[context.SPY].price
#compute a notional value where short positions require 2x cash
#notional =
#test the market MA
MAR_SPY = data[context.SPY].vwap(15) / data[context.SPY].vwap(126)
if MAR_SPY >= 1.0 and notional < context.max_notional:
order(context.SPY,+100)
print("MAR_SPY>=1 and Notional="+str(notional))
elif MAR_SPY < 1.0 and notional > context.min_notional:
order(context.SPY,-100)
print("MAR_SPY<1 and Notional="+str(notional))
else:
print("MAR_SPY="+str(MAR_SPY)+" ; Notional="+str(notional) )

2012-01-03PRINTMAR_SPY>=1 and Notional=0.0
2012-01-03PRINTMAR_SPY=1.0 ; Notional=12784.0
2012-01-03PRINTMAR_SPY=1.0 ; Notional=12788.0

But then in the backtest, it looks like the algorithm isnt doing anything until one month into the backtest (it should just be in spy until 6 months into the backtest) and after the one month period it looks like it isnt doing much of anything. Any ideas?

EDIT: The backtest is based on a $1,000,000 portfolio whereas the algorithm was limiting notional to$10,000. Problem solved. Sort of. The algorithm should have bought and held SPY for the first 6 months but the algorithm opens down 0.4% and the benchmark opens up 1.4%. Strange....

26
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
#Buy and sell SPY when 15 day MA is above 126 day MA

def initialize(context):
#initiate the global i
#    global i
#    i=0

context.SPY = sid(8554)

#Set min/max notional
context.max_notional = 10000.0
context.min_notional = -10000.0

def handle_data(context, data):
#    global i
#    i=i+1
#    print(str(i))

#compute the notional portfolio value
notional = context.portfolio.positions[context.SPY].amount * data[context.SPY].price

#compute a notional value where short positions require 2x cash
#notional =

#test the market MA
MAR_SPY = data[context.SPY].vwap(15) / data[context.SPY].vwap(126)

if MAR_SPY >= 1.0 and notional < context.max_notional:
order(context.SPY,+100)
print("MAR_SPY>=1 and Notional="+str(notional))
elif MAR_SPY < 1.0 and notional > context.min_notional:
order(context.SPY,-100)
print("MAR_SPY<1 and Notional="+str(notional))
else:
print("MAR_SPY="+str(MAR_SPY)+" ; Notional="+str(notional) )
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.