I am sharing a few thoughts on risk management I had while developing trading algorithms for myself and my clients. Keep in mind my focus is mostly on Machine Learning based algorithms but these considerations are general enough apply also to all quants and even discretionary traders.
Most of the quants, or even traders, have the tendency to jump to the “sexy” part of the strategy definition, namely, using exotic datasets, crunching data via traditional analysis or Machine Learning to generate trading signals. Hours and resources are poured into squeezing the next 1% accuracy out of your signal generating model without acknowledging the elephant in the room: What happens when your signal is wrong?
This is not a hypothetical question, your model will be wrong at some point, maybe in a small way every day or in a big way during crashes. Therefore it is critical for you to adjust your trading framework accordingly.
I advocate for flipping the sequence of activities in trading algorithms’ development from:
- Analyze data and generate signals ideas
- Develop an algorithm to generate trading signals
- (Back)Test the trading signal
- Add a risk management layer
To:
- Define what is risk for you and how much you are willing to take
- Develop an infrastructure that targets the desired level of risk
- (Back)Test the risk infrastructure in the worst possible scenario (I like using a random model)
- Add a signal generation layer
While the concept of risk is very slippery (and its measurement even more), this change of perspective is certainly useful. You stop thinking that your signals are flawless and you start building contingency for when things will go against you.
To make things more practical you can find below a short algorithm that trades daily the SPY and that implements these concepts:
- A risk management framework: In this case I have used the Kelly Criterion which, together with the next day’s Up/Down prediction, defines the size of the position for that day.
- A signal generating model: Since the focus is on testing the risk management, I am using a DummyClassifier generating random 0/1 trading signals. I want to see how the algorithm behaves when a blindfolded monkey is on the steering wheel.
As you can see, the performance is by no means exceptional but, even with a totally random trading signal, the risk management still achieves reasonable returns and drawdown while squeezing out even a tiny alfa.
This is enlightening on the importance of this often overlooked component and my recommendation is to find your preferred risk management mechanism and test it under different conditions (tickers, asset classes, resolutions, …) with very bad or even random signals. In this way you can refine your own risk management layer so you can confidently release your real trading models.
Francesco
www.beawai.com
P.S. The considerations are inspired by several readings across Finance, Math and sometimes even Philosophy. I am sharing a few of these should you want to dig deeper:
Brandon Leonard
The longer I trade, the more this makes sense.
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.
Axist
This is really cool, and I could see being useful when combining with an In/Out or momentum based algo. Took a crack at trying to make this work for multiple tickers at once. While I am not getting an error, I think there is an issue with training multiple tickers? Curious if anyone's gotten it to function with a list:
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.
Jens.
Hi,
I really like the idea to use a random signal and I stumbled upon that myself. Thank you for your post and example. I figured that different monkeys (=different fixed seeds) get significantly different Sharpe Ratios. So I recommend employing a monkey gang to stress-test!
For me, risk management typically costs performance especially in the recent bull phase, but also makes the results more independent from the market. Do you have the same observation?
I will probably play around with your implementation to find out for myself, and post my assumptions later on.
Jens
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.
Francesco Baldisserri
Hi Axist,
You can definitely make it work with multiple tickers but the critical part is that, where you calculate the Kelly Criterion, you need to calculate the past win rate and returns for your trading strategy. I took a look at your code and the In/Out is used in the trading part but the Kelly Criterion is still being fed with the results of the Dummy Classifier which is never used to trade.
If you want to use the Kelly Criterion you need to calculate the signals for your In/Out strategy for the last X days and the related wins and returns.
Hope it helps!
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.
Francesco Baldisserri
Hi Jens. ,
You are totally right that a single backtest has limited information. I have made a few tweaks and added the parameter “seed” and “use_kelly” (0/1) so those parameters can be controlled and I ran a grid search over those.
Unfortunately I cannot share the grid search results like the backtests (feature request😊) but I am attaching one backtest with the new code, the screenshot of the grid search and the results in an excel (link).
Clearly this topic requires much more thought and analysis (the problem of induction has been debated for millenia) but the parameter “use_kelly” is positively correlated with the PSR, the Alfa and negatively correlated with Beta, Drawdown and Trades (to be fair it also has lower profit and annual returns, probably due to the limited trading during high risk situations).
PSR23%Sharpe Ratio-10%Net Profit-33%Drawdown-63%Total Trades-99%Alpha26%Compounding Annual Return-25%Beta-99%Annual Standard Deviation-99%
Thanks for the input and let me know if you have more insights!
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.
Sylvain Thibault
Great post, would be great to have the equivalent Python code.
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.
Petr Zurek
How does it perform from 2016 - 2024. Oh wait, I can test it myself ;-)
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.
Derek Melchin
Here is a Python implementation of the strategy. It's not exactly the same as the C# version above, so expect slightly different results. For instance, this version doesn't have the ATR filter and it relies on both daily and minute resolution data subscriptions, so indicators may not be accurate. For the most accurate results and execution speed, use the C# version above.
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.
Enjolras Leigh
The backtest doesn't look good for other years. Does it overfit?
Why so many KOL are teaching this pattern? did they do the backtest?
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
Thank's for the post, I was just trying to implement this strategy it in these weeks :) ; any further suggestions regarding order execution with possible slippage in real 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.
Jack Pizza
thing is how to get these trading costs under control…. 25% that's only trading 6 symbols….
You can argue the fees are covered if IBKR gives you price improvements, or can use a free broker that will probably get you worst fills… so you end up in the same boat.
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
This is my attempt at replicating it in Python, it is close, but not as good. Upon closer look, ATR in Python are 3x lower or so, also, on first entry ATR has ~7k samples, this looks insane for daily indicator. In C# code it has only 33 samples, which looks correct to me. It looks like for some reason it is being warmed up with minute resolution bars instead of daily. This looks similar to this bug I necountered before: IdentityDataConsolidator Does Not Handle Fill Forward Correctly · Issue #8392 · QuantConnect/Lean Or maybe I did something wrong…
Because of this, stop loss is too close and triggers far too often. Workaround shouldn't be too difficult, I just won't work on it today…
Backtesting time of Python version is 1588.03 seconds vs 730.75 seconds of C# version on B2-8 node. Definitely use C# for optimization or backtesting on larger date spans.
Overall, strategy looks good to me as long as the market is not crashing. Maybe add some filters to detect that. It has low win rate, but high profit ratio to accomodate for that. Stop loss triggers for most of the trades. Perhaps there is room to improvement in symbols selection, entry orders or risk management…
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
I actually found a mistake in my code, here is a fixed version. It's almost a match with C# version, except its a little bit better )))
It also took 1171.79 seconds vs 1588.03 from the previous Python version…
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.
.ekz. INVESTOR
Great to see this! i actually worked on this for python some months ago but it didnt seem to work too well on a single symbol so I doubted their reserarch was credible. Now i see i was wrong and i should i have tried harder :)
My goal was to create a system that uses the proven ORB entry, but trades options instead, based on IV Rank and Gamma exposure. I believe there is some alpha there.
Now i can do actually give my goal another shot. Thank you Derek Melchin and Yuri Lopukhov .
Including a link to my technical spec if anyone wants to give feedback or try building it as well!
The GEX-Enhanced Opening Range Options Breakout Strategy
( Sorry I tried to delete previous post where i pasted the whole thing, but I was too late. someone from QC team please help cc: Derek Melchin )
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
@yuri_lopukhov
I already tried with momentum filters, problem is the returns are just too painfully low already... adding that filter made them go down even more... as it would sit out of market. Also tried adding them individually to only trade long with positive momentum and only trade short with negative momentum same thing.
next step is maybe trying an MA filter... but suspect same results...
I tried hard coding MEGA stocks META, NVDA Ect. completely crashes in 08'
Also noticed if you raise the filter to stocks > $50 performance goes down the can too, so it seems like there might be some sort of bias because out of a universe of 1000 stocks there is plenty to choose from, so starting to think performance has more to do with the actual selected stock vs all the ATR selection process.
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
or i guess ATR makes sense with smaller stocks, as if it increases that much, it means some major news has happened and it will effect it more profoundly than say a mega cap… not sure.
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
Also completely collapses during dot com, for some reason it does decent in 07-08, and only around a 10% DD during covid…
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.
Mark Kust
Has anyone tried the contrarian trade? For example, when a stock is identified as having a long opening range breakout, flag it for shorting once it reverses below that same level. Vice versa for short opening range breakouts. The fact that the algorithm as written has a 17% win rate (83% loss rate), kind of makes this the obvious follow-up. Would then set the stop-out level to 1 ATR above the entry (and vice-versa for shorts). If no one has tried this yet, I may go ahead and implement it. Obviously, I don't know that this will work, but can't help thinking that I'd like to see it.
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
Which is the minimum RAM needed to deploy live this code? It could be nice to implement some control also to check if orders became invalid and not accepted by the broker, for example Alpaca in paper trading rejected me some stop orders as “Wash trade” invalidating the strategy
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
Just a heads up: this condition is really not working well on resolution lower than minute and most likely in live deployments:
Basically, on every new piece of data in this minute it will place entry orders. On live instance I believe it will run for every new group of ticks…
Easiest fix would be to add a variable to check if entries were already placed today and reset it at the end of the day or on the beginning. I might share updated C# code a bit later (not really working with Python version since C# is faster and most likely requires less RAM, which is important for live instance…)
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
Here is an updated C# version, also added some extra features and plots
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.
Projectedxyz
Given the fees, this strategy seems tailor made for TradeStation $0 commissions for equities, no?
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
Ok, so I've identified an issue with transferring backtesting results to live trading:
We place stop loss order after entry stop order is filled. In backtesting (or live trading with QC paper account) with minute resolution this means that stop order will be placed on the next minute after entry order is filled. In real-time or on lower resolution, e.g. second/tick, stop order will be placed as soon as entry was filled, so it can be on the next tick or second.
So for example, entry order may be filled at 9:35:01, and in real-time stop order will be placed at that time, while in backtesting it will be placed at 9:36:00. This creates quite a difference between backtesting and live trading.
There are two solution I can see here:
Any other thoughts?
P.S. I was able to run C# version on lowest tier node with 500 securities in universe with minute resolution and with 250 securities on second resolution. It may run out of RAM during warm up, but on the next attempt it usually succeeds.
P.P.S. if anyone feels risky, they can unleash full leverage by changing 1m to something up to 4m in this line:
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
In the backtest we could use something like this in public override void Initialize() to boost performance with seconds resolution:
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
Hi all,
Happy new year and many thanks to Derek and Yuri for the great work!
Having played with Yuri's implementation (both the python version and also the most recent C# version for performance reasons), I noticed that the risk adjusted returns increase significantly with larger universe sizes and with shorter opening ranges.
A universe of 2000 and openingRangeMinutes as short as 1 minute does really well:
This was based on a 2020-2022 three year backtest, but the above pattern (larger universeSizes and openingRangeMinutes of 1 or 2 minute doing significantly better than longer ranges and smaller universes) is consistent over all backtest periods between 2010 and today that I tried.
An L2-4 node will happily run a 2000 Universe.
The most significant improvement though, comes from the shortening of the openingRange to just one minute, which would make sense considering that both algorithmic trading and MOO orders would cause a lot of the breakout momentum described in the paper within the first minute after market open.
I'm paper trading with this set of parameters right now, as I'm not sure if this assumption holds up in reality…
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!