You don't need to use
data.can_trade when you are working with today's output of pipeline or
The two most common cases where
data.can_trade is necessary:
- When ordering a security that is manually referenced using
symbol, or fetcher.
- When ordering a security listed in context.portfolio.positions rather than the output of pipeline or
The question of when
data.can_trade should be used is a topic of much discussion here at Quantopian. I am going to do my best to explain all of the the details so you can make your own decision with full information.
The first thing to know is that when a security doesn't exist (either because it hasn't IPO'd yet or because it was delisted), Quantopian 2 returns NaN for price, open, high, low and close and 0 for the volume. This is different from Quantopian 1, where prices were forward-filled even after delisting. Quantopian 2 is more precise, and this behavior change drives much of what is below.
I'm going to explain how
data.can_trade is determined on IPO dates and delisting dates. Then I will cover what securities are returned from pipeline based on their IPOs and delistings. Finally, I'll cover some of the places where we have seen issues arise.
When a security IPOs, its first trade is rarely at at market open. The exchange gets everything together, prices the security, and sets the first trade price, generally a few hours after the market opens. Before the first trade, the price of the security is NaN and the volume is 0, so
data.can_trade returns false. Once the first trade has happened,
data.can_trade will return true.
With security delistings,
data.can_trade will return True before and through the delisting date. The delisting occurs at market close on the delisting date. Any day after the delisting,
data.can_trade will return false.
The tricky thing here is that your portfolio can hold securities on the delisting date. In order to protect algorithms from accidental delistings (which happens occasional due to bad data from our data providers) we have a 3-day buffer before automatically liquidating delisted securities from your holdings. If a security is held when it delists, it will remain in your portfolio for those 3 days, and then the position will be closed at the last known price. If you try to get the price or volume of the security after delisting, you will get NaN and 0, respectively.
On any given day, pipeline will only give you securities that can be traded on that day. Since your pipeline is generated based on yesterday's data, it will not include any securities that IPOed today, or have delisted. Pipeline will return securities on the delisting date itself, as they can be traded on that date. This means that if pipeline generated your security list today, you can buy and sell those securities without issue. You don't need
During our internal Quantopian 2 testing, we noticed a problem when users used pipeline to define their portfolio. After a security is delisted, the security is no longer included in the pipeline results. However, it is still possible for the security to be present in the portfolio during the 3-day window between the security delisting and the security being automatically removed from the portfolio. If the algorithm tried to close the position it would run into problems because it couldn't sell the delisted security.
Since many of our order functions rely on having a last known price and volume (which now return NaN and 0 respectively) if those prices don't exist, then the algorithm would blow up with an error. To prevent this exception, orders that are placed for delisted securities during this 3-day window will return
None, and the order will not be placed. The position will be automatically closed after the 3 days have passed.
Another way to run into a problem is to use a static list of securities, as it's very easy to order a security before its IPO date or after its delisted date. In these cases, order methods that rely on price or volume will result in an algorithm error. For this reason, you should use
data.can_trade whenever working with static lists.
I hope this explanation helps make the various use cases here more clear. Please let us know if you have any other questions.