Cash vs Returns

I am trying to get familiar with quantopian. I cloned an algorithm and I would like to understand differences between cash and returns. Why in this algorithm cash is almost 0 and returns goes up?

9
Backtest from to with initial capital
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
# P/E Ratio mean reversion

from collections import deque
import pandas as pd

def initialize(context):
# Import a CSV containing the reported and operational earnings per share of the S&P 500
# This is only updated quarterly since that's when earnings announcements occur
# I'm just using reported EPS, but I've included operational EPS for those interested
# 45 day delay to account for announcement delay
fetch_csv('https://gist.githubusercontent.com/gusgordon/eda583be659f6f38c243/raw/110c1955cd864b2edd652b897922eeb691325f25/gistfile1.txt', symbol='eps')

context.stock = sid(8554) # S&P 500

# Store past PE ratios, have some finite limit on the amount of past day's ratios to keep
context.recent_PE_ratios = deque(maxlen=2000)

def handle_data(context, data):
# Get the most recent earnings per share
try:
eps = data['eps']['eps'].split('|')
recent_reported_EPS = float(eps[0][1:])
#recent_operational_EPS = float(eps[1][1:])

active = 1
except:
active = 0

if active == 1:
# Calculate price/earnings
PE_ratio = data[context.stock].price / recent_reported_EPS

# Calculate the average past P/E ratio to use for reference
avg_PE_ratio = pd.Series(context.recent_PE_ratios).mean()

# Store today's PE ratio to use in future averages
context.recent_PE_ratios.append(PE_ratio)

# Buy if the PE ratio is low, sell if the PE ratio is high
# Use a leverage of 1
if  PE_ratio < avg_PE_ratio:
order_target_percent(context.stock, 1) # Long
elif PE_ratio > avg_PE_ratio:
order_target_percent(context.stock, -1) # Short

#record(avg_PE_ratio=avg_PE_ratio,
#current_PE_ratio=PE_ratio)
record(cash = context.portfolio.cash)

# If we don't have an EPS, don't take any position
else:
order_target_percent(context.stock, 0)
There was a runtime error.
7 responses

One day and no replies. Is my question too stupid?

Hi Emanuele,

The reason is the simulated broker calculates returns based on the total value of all your holdings - cash plus stock. Your algo used all your starting cash to buy stock, so your cash is 0. But the value of the stock you bought has increased, so your returns are positive. These are "unrealized gains" - gains from the stock price changing. If your algo manged to sell at the same price, your returns would be unchanged but they would be "realized gains" in the form of cash.

Another confusing bit: The simulator also allows you to borrow cash and buy more stock. This approximates a margin account, where your broker allows you to borrow cash to buy stock. If you start with $1M and buy$2M in stock, your cash balance would be negative: ($1M). Your equity value would be$2M in stock minus ($1M) in cash loans, or$1M. Your returns at this point would be 0%: (current equity - starting equity) / starting equity

Our simulator allows borrowing, but a real broker caps the amount you can borrow. The way to track your borrowing is to track your leverage via context.account.leverage. We track gross leverage there. A 2-3x leverage is a reasonable limit in simulation.

Thanks,
fawce

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.

Edited 2015-09-02

Want to chime in here. Above it was said (current equity - starting equity) / starting equity

It can be pretty helpful to realize that Quantopian is unfortunately ignoring unused cash and margin in chart and Returns values calculations.

A different route would be (portfolio - maxspent) / maxspent [profit in relation to cash put into play].

The original algo above doesn't involve negative cash so this might not be the best place to highlight this point, it is a fairly common problem tho. Of 15 of the most recent algos posted that I checked, 12 of them (80%) had negative cash and as a result the charts and Returns values were more positive than would happen in the real world.
Then there's also the flipside, not using all of starting capital. If you start with $1M and spend only$1000 and wind up with $2M all in cash, Q would consider it to be only 100% Returns currently, however that is$1000 turned into 2M for nearly 200,000%. If addressed, then I wonder if we will also find that Alpha, Beta, Sharpe et al will also better indicate the merits of the algo. Currently those change with different input capital specified in the UI even if actual amount spent is the same. Thanks. 3 Loading... Backtest from to with initial capital 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 ''' Here's a simple example of how it can be if Quantopian makes the change in calculating chart values and Returns. The Quantopian Returns value is often wildly wrong like this and users wind up confused. This code ventures into negative cash, still makes money. The custom chart is close to reality or accurate. The Quantopian chart is incorrect because it **ignores negative cash**. That creates false optimism in users sometimes where the real market could then bite them. In my opinion it is a terrible bug and should be high priority. This points in the direction of the fix. Add two zeros to the initial capital and charts will align better because no negative cash. The custom chart remains the same no matter what input capital. Once fixed, then I think everyone will find that suddenly Alpha, Beta, Sharpe et al will consistently reflect the true nature of an algo. Currently they change wildly with different input capital and can't be trusted. With this change Q could make more certain and reliable determinations in the Hedge Fund Managers Program, and members will know better how they are really doing. ''' def initialize(context): context.stock = symbol('AAPL') schedule_function(buy, date_rule=date_rules.month_start()) def handle_data(context, data): true_returns(context) def true_returns(context): csh_strt = context.portfolio.starting_cash csh_now = context.portfolio.cash if 'cash_low' not in context: context.cash_low = csh_strt shares_val = context.portfolio.positions_value cash_val = csh_now - csh_strt # cash_val can be negative values = shares_val + cash_val drawdown = csh_strt - context.cash_low returns = 0 if drawdown: returns = 100 * values / drawdown # Q is doing this instead, uncomment to see #returns = 100 * (context.portfolio.portfolio_value - csh_strt) / csh_strt record(TrueReturns = returns) if csh_now < context.cash_low: context.cash_low = csh_now if csh_now < 0: log.info('Cash low: ' + str(int(csh_now))) def buy(context, data): order(context.stock, 9) There was a runtime error. I think that there is no reason to complain about how Q calculates returns. Notice how it says "100 initial CAPITAL", and the performance is percentage "return on capital". If you were given a million in capital and only deployed \$100 of it, your return on capital would be pretty poor. Their nomenclature is correct.

Also edited 2015-09-02 because my thoughts have evolved on this.

I think a lot of folks are thinking if they have a million in the account at Interactive Brokers, it is invested and tied up.
However, today, you can transfer money from there to your home bank quickly, maybe 1 minute, and back again.
In the example, whether it sits unused at your bank, or at IB, either way it is not invested and not really part of a portfolio in my opinion, at least not an active part, or not yet.

I can see others' point of view, just that what's most useful to a developer is to know output vs input that led to that output, then he or she can know the real effect of iterations.

A matter of theoretical value (current) or real/used value (proposed). I'm suggesting basing on cash put at risk, put into use, traded, activated.

Outflow
Inflow