How could it be that my algorithm buying Facebook stocks is outperforming itself if I set Facebook itself as a benchmark (Total Returns 0.77 vs. Benchmark returns 0.58)?

2
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
import numpy as np

# Called once at the start of the simulation.
def initialize(context):
# Reference to the AAPL security.
set_benchmark(sid(42950))
context.stock = sid(42950)
context.counter = 0
context.seed = [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,
1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
0,  0,  1,  1,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,]
# Rebalance every day, an hour and a half after market open.
schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open())

# This function was scheduled to run once per day at 11AM ET.
def my_rebalance(context, data):
# Take a 100% long position in AAPL. Readjusts each day to
# account for price fluctuations.
if should_buy == 0:
#order_target_percent(context.fb, 1.00)
#order(context.fb, 100)
order_percent(context.stock, -0.01)
else:
order_percent(context.stock, 0.01)
else:
print('Non posso comprare!')
context.counter += 1

There was a runtime error.
6 responses

It's an example of the achilles heel: Margin becomes illusory profit.

Notice in the beginning the returns curve is below bench. That's because not all of the initial capital had been spent yet.
Then when cash goes negative, returns appear to rise above the benchmark, however the broker is owed then, so the profits are not real.

If you negate commissions you'll see the pure version of that.

set_commission(commission.PerTrade(cost = 0.0))


The simplest way to protect from letting accidental margin lead one to believe that a change is positive when it really isn't (and visa-versa) would be to always record cash:

record(cash = context.portfolio.cash)


To illustrate the point in terms that might be easier to understand, this backtest appears to be a terrific strategy at 20% profit in 20 days.
Take a look at the code by clicking on the 'Source Code' tab.

65
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
# https://www.quantopian.com/posts/misleading-results?utm_campaign=misleading-results

def initialize(context):

order(sid(8554), 3)

#record(cash = context.portfolio.cash)    # uncomment to reveal the margin

There was a runtime error.

Simply recording cash, while advisable, has some limitations. A precise solution and more info can be found here and maybe start with the minimal version. This adds something like that to your code (hover over the custom chart) and commissions are off. I would have expected the two traces in the main chart to cross over at the point where all capital was used, not sure why it isn't so. Note however, when 100% of initial capital is used, pvr matches the Algorithm trace. It is at all times indicating what I would call risk-adjusted returns except that term appears to be taken already in the industry and tied to benchmarks.

It is incredibly useful to be able to see when a change is good or bad. My real money algo has more than doubled in 5 months. Perhaps the tool has something to do with that, being able to see clearly.

0
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
import numpy as np

# Called once at the start of the simulation.
def initialize(context):
# Reference to the AAPL security.
set_benchmark(sid(42950))
context.stock = sid(42950)
context.counter = 0
context.seed = [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,
1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
0,  0,  1,  1,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,]
# Rebalance every day, an hour and a half after market open.
schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open())

for i in range(1, 391):
schedule_function(
pvr,        date_rules.every_day(), time_rules.market_open(minutes=i))
schedule_function(
_pvr_chart,     date_rules.every_day(), time_rules.market_open())

# This function was scheduled to run once per day at 11AM ET.
def my_rebalance(context, data):
# Take a 100% long position in AAPL. Readjusts each day to
# account for price fluctuations.
if should_buy == 0:
#order_target_percent(context.fb, 1.00)
#order(context.fb, 100)
order_percent(context.stock, -0.01)
else:
order_percent(context.stock, 0.01)
else:
print('Non posso comprare!')
context.counter += 1

def pvr(context, data):
''' Minimal custom chart of profit_vs_risk returns
'''
c = context  # Brevity, readability
if 'pvr' not in c:
# For real money, you can modify this to total cash input minus any withdrawals
manual_cash = c.portfolio.starting_cash
c.pvr = {
'chart_pvr'      : 1,
'chart_cash_low' : 1,
'chart_max_shrt' : 0,
'chart_max_risk' : 1,
'start'          : manual_cash,
'cash_low'       : manual_cash,
'max_shrt'       : 0,
'max_risk'       : 0,
}
c.pvr['cash_low'] = min(c.pvr['cash_low'], c.portfolio.cash)
c.pvr['max_shrt'] = max(c.pvr['max_shrt'], abs(sum([z.amount * z.last_sale_price for s, z in c.portfolio.positions.items() if z.amount < 0])))
c.pvr['max_risk'] = max(0, c.pvr['max_risk'], c.pvr['start'] - c.pvr['cash_low'], c.pvr['max_shrt'])

def _pvr_chart(context, data):
# Profit_vs_Risk returns based on max amount actually invested, risked, long or short
c = context
if c.pvr['max_risk'] != 0: # Avoid zero-divide
if c.pvr['chart_pvr']:  record(PvR = 100 * (c.portfolio.portfolio_value - c.pvr['start']) / c.pvr['max_risk'])
if c.pvr['chart_cash_low']: record(CashLow = c.pvr['cash_low'])
if c.pvr['chart_max_shrt']: record(MxShrt  = c.pvr['max_shrt'])
if c.pvr['chart_max_risk']: record(MxRisk  = c.pvr['max_risk'])


There was a runtime error.

Thank you Blue, that was crystal clear!

I limited the amount of stock to buy so that I never go below zero with cash and resell just the stock I already have in my portfolio. Still my system outperforms the benchmark itself.

1
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
import numpy as np

# Called once at the start of the simulation.
def initialize(context):
context.counter = 0
context.stock = sid(42950)
set_benchmark(context.stock)
context.signals = [ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,
1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
0,  0,  1,  1,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,]
# Rebalance every day, an hour and a half after market open.
schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open())

# This function was scheduled to run once per day at 11AM ET.
def my_rebalance(context, data):
n = 5
# Take a 100% long position in AAPL. Readjusts each day to
# account for price fluctuations.
if data.can_trade(context.stock) and context.portfolio.cash >= data.current(context.stock, 'price')*n:
if should_buy == 0:
#order_value(context.stock, -context.portfolio.cash*0.1)
order(context.stock, -n)
else:
#order_value(context.stock, context.portfolio.positions_value*0.1)
order(context.stock, n)
elif data.can_trade(context.stock) and context.portfolio.cash < data.current(context.stock, 'price')*n:
if should_buy == 0:
#order_value(context.stock, -context.portfolio.cash*0.1)
order(context.stock, -n)
else:
pass
else:
context.counter += 1
record(Cash = context.portfolio.cash,
Portfolio_Value = context.portfolio.portfolio_value,
Profit = context.portfolio.portfolio_value - context.portfolio.starting_cash,
Positions_value = context.portfolio.positions_value,
#Price = data.current(context.stock, 'price'),
)


There was a runtime error.

Some comments in the code. This adds a loop so you can experiment with more than one stock to some degree. Think toward pipeline.
You'll want to direct future questions to the community as my personal fitness haha trainer fee is market. :|
The scheduling of cash_low is time-consuming so you can turn that off by uncommenting the break, to prevent that, the other loop.
Hopefully you'll find some of this exercise educational, useful.

1
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
import numpy as np

def initialize(context):    # Called once at the start of the backtest.
context.counter  = 0
context.cash_low = context.portfolio.starting_cash
context.stocks   = [sid(42950), sid(39840)]   # [sid(42950), sid(39840)]
context.signals  = signals()
set_benchmark(context.stocks[0])    # first one listed
schedule_function(balance, date_rules.every_day(), time_rules.market_open())

''' An alternative to run something every minute instead of handle_data.
This is easier to turn off. The 391 is necessary to include minute 390. '''
for i in range(1, 391):
#break         # comment to turn this ON
schedule_function(
cash_low, date_rules.every_day(), time_rules.market_open(minutes=i))

'''
Couple of notes you can delete (of course) ...
Whenever I see "my_rebalance" it always makes me think, wait a second,
excuse me sirs, if it isn't your rebalance, who's is it?
You mean I can't just assume that it is yours?
Does "my_rebalance" mean I'm not allowed to look at it?
Too many questions are raised by "my"-anything.
Anyway ...
Next, the first time rebalance runs, the "re" part of that doesn't apply,
so technically "rebalance" is a misconception. So I call that "balance".
Besides the fact that it requires less typing and has fewer syllables,
"balance" keeps the uber-nerd-perfectionist in my head from bouncing off the walls so much.
'''

def balance(context, data):
c = context  # huh?
''' I know. The first time I saw c = context, I had the same reaction.
The first time I saw that was in an example from a Quantopian representative.
I made it beyond that first reaction and gave it a try and now I love c = context.
Merely a matter of habit.
One-seventh the amount of typing.
Makes code far easier to read also.
'''
cash = c.portfolio.cash / len(c.stocks)     # equally divided cash
n = 5

# Take a proportional long position in stocks. Readjusts each day to
#   account for price fluctuations.
for s in c.stocks:
# Only happens if sid isn't listed yet or has delisted ...
continue    # skip. "continue" is Python for don't continue, eh-hem
if cash >= data.current(s, 'price') * n:
order(s, n)
#order_value(s, c.portfolio.positions_value*0.1)
else:
order(s, -n)
#order_value(s, -cash*0.1)
else:
order(s, -n)
#order_value(s, -cash*0.1)

c.counter += 1
record(
Cash      = cash,
PnL       = c.portfolio.pnl,
Portfolio = c.portfolio.portfolio_value,
Positions = c.portfolio.positions_value,
)

def signals():
return [
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,
0,  0,  0,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,
1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
0,  0,  1,  1,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
]

def cash_low(context, data):
if context.portfolio.cash < context.cash_low:
context.cash_low = context.portfolio.cash
record(CashLow = context.cash_low)

There was a runtime error.

Thanks man, really appreciate that!