Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Exiting at opening price greater than my entry price or stop out after 2.5% loss

I am trying to do the following: Buy everyday if I don't have a position. I want to exit if my opening price is greater than my entry price or I have 2.5% loss. The transactions coming out does not look right. What am I doing wrong ? I am guessing my limit order
order_target(context.security,0,style=LimitOrder(op), exchange=IBExchange.SMART))

or my use of return is not correct ?

8 responses

I believe you just want to order once at the beginning of the day, then keep running the rest of the code to check when to sell. I would change the algorithm to run in minute mode, then fix your code so context.date gets defined, because right now it stays as None. Then you'll have to move blocks around so that your selling code will still run if it isn't a new day. Right now, the way your code is positioned, the return will execute before, thereby preventing your selling code from running.

You may also want to look at schedule_function, because that is a more standard way of running different things at different points in the date.

Note this will take longer to backtest, because I think you want this to run in minute mode. Hope that helps!

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.

HI Gambulator,

As Gus pointed out, it would be more efficient to run this with

schedule_function(trade,  
                  date_rule=date_rules.day_only(),  
                  time_rule=time_rules.market_open(minutes=20))

def trade:
# code you want to execute once each day goes here

def handle_data(context, data):
# either "pass" or something like below to give you stats
leverage=context.account.leverage
exposure=context.account.net_leverage
record(leverage=leverage, exposure=exposure)

Meanwhile, to prevent your existing code from running again and again, you just need the statement
# Do nothing unless the date has changed and it's a new day.
if todays_date == context.date:
return
else:
context.date = todays_date

it will never evaluate to True as you want, preventing duplication of tasks.

let me try the scheduled function. thanks

Well, I actually want to stay on the daily time frame.... I have tried the schedule_function but on the daily timeframe, you can't really get the opening price.

With the code I have , after removing the return and rearranging the blocks; based on the log file, the problem I see is that sometimes (only sometimes), the code would sell the position, 900 shares( say 900 shares is all that I have bought). The next day, it still thinks that I have 900 shares so it sold another 900 shares and then sell another 900 shares again the next day...

Any idea if there is a bug that would be triggered so position held is not being reduced if someone operates on the daily timeframe ?

So you really want to switch to minute mode. The way orders are execute in Zipline, the engine that runs all backtests on Quantopian, is they are filled at the end of the next bar. Now when running in daily mode if you place an order one day, it is filled at the end of the next, so you end up filling your order a day later than you expect. Now with minute mode on the other hand the order is filled one minute after you place it, that is much more realistic. Now that is not to discount daily mode by any means, I use daily mode heavily as a way to do quick proof of concept of my ideas that aren't really time dependent. And as mentioned above, you can still run your logic every day with schedule_function

In regards to getting the day's open you can always use the history function in daily mode and get the last value:

last_open = history(1, "d", "open_price")[security][-1]  
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.

Thanks for everyone's help

(1) I have made the change to use the schedule_function. Now I have 3 sell conditions and 1 buy. For the buy condition, the attached backtest is still pretty fast but as soon as I put something a little more complicated, it becomes really really slow... Is there anything obvious in this code that can speed things up a bit ? For example, if the SellOpen runs, I don't need to run SellClose or SellStopLoss, is there any code I can place to stop the loop there ? (return does not seem to work)

(2) I was going to use yahoo data(I saw some postings before, it seems to be workable) to get more daily data back to the 90s. However, the daily timeframe as I see in my previous questions can't quite issue signals properly and now I must use minute timeframe, I can only go back to 2002. Any advice on what it might take to get the daily timeframe working perfectly either by some hack or have quantopian fix it ?

So I can enlighten you a bit to why your code is slow. It has to do with your use of the history() function. If you call the history function it request the specified number of bars of history for every sid in your universe and when you are using minute data this takes a while. Now looking at your code you have in total 10 calls to the history function, that is going to take a long time. I do see that you are only using one security so that will help for now, but makes your code impossible to scale.

Some tips on how to make it faster:

  1. You have some functions that get called the same time of day, consolidate those into one and call you history methods once and pass in the historical data as a parameter, i.e. let them share the one history call. Bttomline: reduce your calls to history()
  2. Eliminate your use of the mavg() transform. While this transform is super convenient it can also be really slow. Consider using something like price_history.tail(200).mean() instead.

To address your concern about daily mode backtesting, there isn't really anything that needs to be 'fixed'. Backtesting in daily mode performs how we intend it too. Furthermore, in real life there is no 'daily mode' everything moves fast, and thus minute mode is mcuh more realistic. It's also important to recognize the inherent flaws of backtesting and that the best way to test your code is too live trade it.

I see. I will fix the history calls. For daily, if I only try to exit @ the close, everything works fine. thanks