Abstract
The Dual Thrust trading algorithm is a famous strategy developed by Michael Chalek. It has been commonly used in Futures, Forex and Equity markets. The idea of Dual Thrust is similar to a typical breakout system, however dual thrust uses the historical price to construct update the look back period - theoretically making it more stable in any given period.
In this tutorial we give a brief introduction to the strategy and show how to implement this algorithm on QuantConnect. After pulling in the historical price of the chosen stock, the range is calculated based on the close, high, and low over the most recent days. A position is opened when the market moves a certain range from the opening price. We tested the strategy on individual stocks under two market states: a trending market and range bound market. The results suggest this momentum trading system works better in trending market but will trigger some fake buy and sell signals in much more volatile market. Under the range bound market, we can adjust the parameters to get better return. As a comparison of individual stocks, we also implemented the strategy on SPY. The result suggested that the strategy beat the market.
Method
Step 1 : Initialization of algorithm
Firstly we need to initialize the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must be initialized.
def initialize(self):
self.set_start_date(2004, 1, 1)
self.set_end_date(2017, 8, 30)
self.set_cash(100000)
equity = self.add_security(SecurityType.EQUITY, "SPY", Resolution.HOUR)
self.syl = equity.symbol
Although this is an intraday strategy, we still want to test the strategy within a long period not just within one day. The Scheduled Events methods sets up an function to fire at a specific date or time.
self.schedule.on(self.date_rules.every_day(self.syl),self.time_rules.after_market_open(self.syl,0),Action(self.set_signal))
Here Schedule.on(DateRules, TimeRules, Action())
, will trigger every trading day for our stock, at market open. Events are scheduled using date and time rules. Date rules specify on what dates and event will fire. Time rules specify at what time on those dates the event will fire. Inside of the scheduled function, we can pull the recent historical data and current open price each trading day.
Step 2: Implementation of algorithm
In order to calculate the range, each trading day we need the close, high, and low price data over the most recent days. In addition, the open price of the current day is required in order to generate the signals. QuantConnect provides a History(Symbol, TimeSpan, Resolution)
method to get the history data like open, close, high, and low for all configured securities over the requested -days time span. Then the range is calculated by
In this implementation, we choose . It is less than one week and the range would reflect the recent price change.
self.high = []
self.low = []
self.close = []
history = self.history(4, Resolution.DAILY)
for slice in history:
bar = slice[self.syl]
self.high.append(bar.high)
self.low.append(bar.low)
self.close.append(bar.close)
Step 3: Trading Implementation
The long signal is calculated by
The short signal is calculated by
where and are the parameters. When , it is much easier to trigger the long signal and vice versa. For demonstration, here we choose . In live trading, we can still use historical data to optimize those parameters or adjust the parameters according to the market trend. should be small than if you are bullish on the market and should be much bigger if you are bearish on the market.
This system is a reversal system, so if the investor holds a short position when the price breaks the cap line, the short margin should be liquidated first before opening a long position. If the investor holds a long position when the price breaks the floor line, the long margin should be liquidated first before opening a new short position.
holdings = self.portfolio[self.syl].quantity
if self.portfolio[self.syl].price >= self.selltrig:
if holdings >= 0:
self.set_holdings(self.syl, 1)
else:
self.liquidate(self.syl)
self.set_holdings(self.syl, 1)
elif self.portfolio[self.syl].price < self.selltrig: if holdings >= 0:
self.liquidate(self.syl)
self.set_holdings(self.syl, -1)
else:
self.set_holdings(self.syl, -1)
Conclusion
We tested this strategy on the S&P 500 ETF SPY from 2004 to 2017. During the backtesting period, SPY resulted in a Sharpe Ratio of -0.17 and the drawdown is 41.1%. This is just a basic implementation and the parameters and are fixed. The strategy can be further extended to Futures and Forex markets. When , buy signals are prone to trigger and vice versa. To improve the model we can apply technical indicators to judge the trend of price and adjust the value of two parameters dynamically and apply risk control in the position sizing.
Reference
- Gang Wei(May 2012). Dual Thrust Intraday Strategy, Online Copy (Chinese)
Derek Melchin
See the attached backtest for an updated version of the algorithm in PEP8 style.
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Lars Klawitter
To Yuri's earlier point of there being a difference between backtests and live trading as to when the stop orders are placed:
I've been running the strategy (using a larger universe and shorter opening range as per my previous post) on IBKR paper trading (i.e. on an actual IBKR account, not via QC paper trading) and as Yuri suggested, the stop orders are at times placed within the same minute. Mostly 20-40 seconds after the entry:
in one case the stop order was placed the same instance as the entry:
I tried second resolution, but that seems impractical given the large universe size.
So this is my attempt at an artificially delayed stop order placement:
I'm not a C# coder, so I definitely don't know what I'm doing. Backtests with this code produce by and large comparable results with the original code, so I'll try paper trading next.
Would the above code change make sense to you?
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Yuri Lopukhov
So far I can see two issues:
I can't fix the first issue in C#, so I guess I will switch to Python version unless somebody else fixes the C# version and share it. Not sure if fixing it will improve results as well.
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Jack Pizza
define: “does really well with 1 minute” ….. 2000-2002 still utterly collapses fail to see well really well fits in….
or does really well when overfitting super hard?
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Quant Stratege
These backtests are not representative of live performance. When adding slippage, it can be significant at the open due to volatility, small-cap stocks, and using stop orders, making the results much less appealing.
Just add this line when adding securities:
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Lars Klawitter
You're right. I had previously only simulated very small constant slippages, but MarketImpactSlippage has quite a savage effect…
If it looks too good to be true…
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
AleNoc
I noticed a difference between the backtest and the selection with live data (data provider QuantConnect). What data provider do you use for live trading?
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Evan lightner
I don't know where to start, I'll have to write a whole post and how I'm planning to implement this strategy. But first of all thank you @derek for sharing this (and of course for everything you've done with QC -its been a game changer for me).
But first of all, I just want to comment with one simple non-coding question….
Why are a good amount of people HATING on this strategy? I understand the backtest cherry pick , but for a bare bones boiler plate ( i messed around with some variables like holdings and percent risk and still got good results) , this is the best algo I've seen in a while, especially for being shared so freely - not to mention brand new piece of research in the community.
Is there just some sort of deep skepticism in the quant community at large I guess, inherently? I suppose that fits!
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Kevin Patterson
Does anyone else end up with very different symbols when running the exact same algo in backtesting vs live (IBKR paper trading)? For example when it is set to choose 20 symbols, I'll see maybe only half overlap –- and of course the ones going positive for the day in the backtest are the ones not picked up live 😅. Seems the relative volume calculations aren't exactly the same and it doesn't take much to move the symbols you get. This is my first foray in to large universe algo's, is this type discrepancy common with large universe backtests or is there settings to help make it line up better with live? S
Some folks were asking about sized nodes: after trying the python version on IBKR (with a few mods) an L1-2 node will make it through one day (it crashes after close though, so likely you need the next level up if you dont want to restart daily)
Thanks for all the python related posts, even if I don't end up trading it, the algo has been super helpful for learning more about the QC code and had some good recipes in it that I think would be helpful for any algorithm.
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 QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!