Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Confused... Please help

So I'm new to python and started coding my first algo. It is going pretty well, but i tried to make an algo that simply bought when the stock price went over the opening price subtracted by .02, and sold once the stock price went lower than or equal to the opening price subtracted by .02. I thought that it would reduce my losses, but instead it had crazy negative returns.

Please tell me what I did wrong, and how to fix my prob or even if I can fix it
Thanks

12 responses

Looks correct to me. It just doesn't work very well! Don't forget your orders will get executed at the close of the following bar.

@Simon what do you mean when you say that my orders will be executed at the close of the following bar?

Jonathan, instead of the order method, you might want to use order_target_percent, so that you don't end up with enormous leverage.

Also, by putting your code in handle_data, you're potentially trading every minute, which will cause high transaction costs. Instead, you could use a scheduled function to trade less often.

Finally, if you replace your stock by a more liquid one such as SPY, you'll incur less slippage.

The attached backtest incorporates those suggestions.

Hello Jonathan,

This is kinda nifty, and addresses the potential problem that Simon is alluding to:

https://www.quantopian.com/posts/trade-at-the-open-slippage-model

Without Anony's special slippage model, the execution price will be at the close of the following bar, which for daily bars is a delay of a whole trading day, which may be more inherent slippage than you want.

Grant

Food for thought

Why do you divide cash by len(data)?

Just equal allocations for every stock. By the way congratulations on your #1 ranking in the contest.

Ok, well I for one won't speak to the theory, but as for your code:
Line 4 doesn't do anything at all. You can delete that.
In your if statements, unless you are VERY familiar with how Python evaluates order of operations, use parentheses.
current_price > open_price is a logical comparison and will return True or False. True (usually) = 1 and False (usually) = 0. But when going the other way to evaluate a numerical expression in a logical context, non-zero values are usually considered to be True, I'm not sure about negative values...but again this would be moot if you used parentheses
So...
Your if statements will evaluate to one of the following:
current_price > open_price = True, then: 1 - 0.2 = 0.8 (Will always be true; a positive number)
current_price > open_price = False, then: 0 - 0.2 = -0.2 (Will be either True or False depending on how the system "understands" negative numbers in a logical context)

Unless, it does as you intend and it actually evaluates the statement as: current_price > (open_price - 0.2) (unlikely, but possible. I am somewhat new to Python myself...)

Oh yeah, I still get that confused, assuming that data[] is shaped like a time series. Thanks - I never expected this algo to do well, it was more of a lark. Given the way the contest is a simple average including several quotients with volatility/drawdown in the denominator, I suspect the weighting scheme is skewed in favor of extremely low volatility algorithms.

Crazy amount of boilerplate code in your summary function, too bad there are not libraries!

Subtraction is definitely higher precedence than logical operators.

Thank you. Of course you are correct. Still...
I like parentheses

Normally len(data) will return an integer of the number of stocks in data during that bar/frame/period, basically counting the number of keys in the data dictionary (where the keys are security objects), EXCEPT when fetcher is involved. Fetcher injects new keys for any bar where incoming fetcher (csv) data is present and they are strings rather than security objects. Seems that maybe fetcher data could have been placed under any particular security key in a 'fetcher' subkey. Wind up having to do isinstance(sec, basestring) to sort them out. So anyway, for a simple algo, context.portfolio.cash / len(data) is a fast way to divy out the available capital (in part to try to avoid too much negative cash due to slippage [fill price winding up higher than order price, on the buy side]). In the algo above, if 8 more stocks are added to the two in symbols() then they would each be working with 1/10th the available cash automatically, for example, however I'm still struggling with trying to find a dynamic and really smart routine for cash management, I currently have around 20 lines and am not happy with it.