It it possible to setup a time based exit, ie. Exit all positions after 5 days? Or stated another way, exit 5 days after opening a position...
It it possible to setup a time based exit, ie. Exit all positions after 5 days? Or stated another way, exit 5 days after opening a position...
Hello Beau,
The short answer is yes, but do you mean 5 calendar days, or 5 trading days? Also, are you planning to write an algorithm to run on daily data, or minutely?
Grant
Beau,
Here's an example:
from pytz import timezone
def initialize(context):
context.trading_day_counter = 0
context.order_submitted = False
def handle_data(context, data):
context.trading_day_counter += 1
if not context.order_submitted:
order(sid(24), 50)
context.order_submitted = True
context.trading_day_counter = 0
print 'buy order submitted ' + str(get_datetime().astimezone(timezone('US/Eastern')))
if context.trading_day_counter == 5:
order(sid(24), -50)
print 'sell order submitted ' + str(get_datetime().astimezone(timezone('US/Eastern')))
The log output is:
2014-02-10 PRINT buy order submitted 2014-02-09 19:00:00-05:00
2014-02-18 PRINT sell order submitted 2014-02-17 19:00:00-05:00
The transactions list:
2014-02-10 19:00:00 AAPL BUY 50 $535.99 $26,799.50
2014-02-18 19:00:00 AAPL SELL -50 $537.32 ($26,866.00)
I don't understand why get_datetime() is returning dates that are shifted by a day...hmm?
In any case, perhaps this provides some guidance.
Grant
Here's the same backtest, except run on minute data. Timestamps are correct. It seems that something has changed in the daily backtester that shifts that timestamps...I've submitted a question via the Feedback button. In any case, the code I posted should still work for backtesting on daily data. --Grant
Hello Grant,
I'm sure I've read something about your 'shifted' day in the zipline group but I can't find it. This is in the right area (see: https://github.com/quantopian/zipline/pull/208 )
+def canonicalize_datetime(dt):
+ # Strip out any HHMMSS or timezone info in the user's datetime, so that
+ # all the datetimes we return will be 00:00:00 UTC.
+ return datetime(dt.year, dt.month, dt.day, tzinfo=pytz.utc)
I'm thinking your datetime is stripped to 00:00:00 UTC.and your UTC -5 hours offset is then applied to time your transaction at 19:00 the day before.
P.
Yeah, this behavior may have been in place all along and I just didn't pick up on it. It certainly is confusing, though. If I am interpreting things correctly, all of the datetime stamps of the daily bars are set to 00:00:00 UTC, even though the bar is aggregated at EOD. --Grant
Hi Grant, Peter,
I implemented your code for multiple sids. It does NOT seem to work correctly.
I wanted to buy stocks and hold for given days (e.g. 25 trading days here) and sell them.
It does not have to buy all together and sell them all together. But in this example, I just wanted to see if it holds for given days per each stock.
For example, on 1/2/2013, it is supposed to buy all three stocks in my codes. But as you can see in the transaction details, it buys one and then buy others on a different day. Selling is also not based on the 25 trading days.
Can you correct my codes?
Thank you.
Thanks Kyu, this is where I was eventually heading. I wanted to see how a simple system might work using the following rules:
This is really just an experiment to test out something Finviz published (http://elite.finviz.com/help/technical-analysis/backtests.ashx). I think this page is only available to paying members but the jist is they tested a bunch of indicators using simple rules using the indicator to signal an entry and holding for X days between 5 and 20. The system above does well according to their research and I wanted to see how it might play out here.
Thanks,
Beau
Kyu,
if you want Grant's code to work, you need to re-initialize the variable context.order_submitted to False when you sell
Hi Kyu,
I took a look at your code and there were a couple issues that prevented it from running correctly. Here is what I found:
if exchange_time.hour != 15 or exchange_time.minute !=58:
This code will run anytime that the exchange hour is not 3PM or the minute is not 58. I think what you intended is to run this once a day (at 3:58PM EST) to check if it's time to exit the position. In that case you would want:
if exchange_time.hour == 15 and exchange_time.minute ==58:
Also, your "long" position was only entered once - the first time the algorithm ran. Then it oscillates between "sell" and "long2". I'm not sure if this is your intended behavior, but I wanted to bring it to your attention.
If you (and @Beau) are looking for a basic algo that enters a position once and holds for X days, attached is a simple example. It buys the basket of stocks and holds for 25 days. Keep in mind the stocks are not all bought at once because of the default commission and slippage models. You can turn these off (by setting to zero) if you want to force a different behavior.
I used order_target_percent instead of order_target_value because it is more robust to changes in portfolio size. In this example I allocated 33% to FAS, 33% to Apple, and 33% to Amazon.
Hope that helps!
Alisa
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 Grant,
I saw your feedback email and thought I'd share my response here for everyone to see. Your question was about the timestamp in the logs. Particularly, why there's an apparent time discrepancy in the logs:
2013-01-04 PRINT buy order submitted 2013-01-03 19:00:00-05:00
@Peter was correct in his explanation. When you run a backtest in daily mode, the timestamp for the bar is midnight UTC or 00:00:00 of that day. However, when you convert this to the US Eastern timezone, it becomes 19:00:00 EST (7PM) the previous day.
Although this is a cosmetic issue, if we could do this over again, I agree it'd be better to use the timestamp at the close of the market.
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 Alisa,
Thank you. But transaction details show odd results as below.
2013-01-02 19:00:00 AAPL BUY 601 $542.41 $325,988.41
2013-01-02 19:00:00 AMZN BUY 1283 $258.54 $331,706.82
2013-01-02 19:00:00 FAS BUY 7640 $43.19 $329,994.52
2013-01-28 19:00:00 AAPL SELL -601 $458.40 ($275,498.40)
2013-01-28 19:00:00 AMZN SELL -1283 $268.13 ($344,010.79)
2013-01-28 19:00:00 FAS SELL -7639 $47.98 ($366,488.66)
2013-01-29 19:00:00 FAS SELL -1 $47.43 ($47.43)
Over the past 14 months, there were only 7 transactions. It does not look working correctly.
My (and Beau's) intention was to buy stocks and hold them for given days and then sell.
In my code, it should buy all stocks on 1/2/2013 and sell all of them 25 trading days later. And buy them right next day (or same day) after selling. In other words, roughly saying, this sample algo should buy stocks once every month and sell once every month (or any given days).
The reason I want to code with minute data is that we can add a lot more conditions on this sample algo as Beau wanted. With daily data, all the orders will be filled at the next day close, which I think very unrealistic and odd. And thus, it should be based on minute data. The time to buy or sell is various. I just wanted to buy and sell based on daily close price (near daily close at 15:59), which is very common in real world.
I will work on this and get back later.
Thank you.
Just add the last line to Alisa's code:
order_target_percent(stock,0.0)
log.info('Exiting position in %s' % (stock.symbol))
context.last_rebalance = None
Hi all,
I corrected my code as below.
This sample algo buys stocks once at the close of day (15:59 E.T.) and hold for given days (25 trading days here) and sell them all on the day. And the next day this algo restarts buying. There's no other logics here as this is just a sample code. BTW, I need to simplify some of this code especially by using loop, which I will do later.
This is a little different from those of rebalancing models. Because if we want to struct our algo with a lot of various factors and apply them to each stocks differently, we need to rebalance each stock on different time frame rather than on the same day. This is a kind of those structures. There will be a lot of corrections and adjustment needed later but at this point, this is a good start.
@Beau, I will get back to you later with RSI model. You know Quantopian has set universe.
set_universe(universe.DollarVolumeUniverse(floor_percentile=98.0,ceiling_percentile=100.0))
The maximum percentile with minute data we can have is 2%, which I think is about 160 stocks only. You can use this or your own universe upto 100 stocks.
Thank you.