Welcome to NexusFi: the best trading community on the planet, with over 150,000 members Sign Up Now for Free
Genuine reviews from real traders, not fake reviews from stealth vendors
Quality education from leading professional traders
We are a friendly, helpful, and positive community
We do not tolerate rude behavior, trolling, or vendors advertising in posts
We are here to help, just let us know what you need
You'll need to register in order to view the content of the threads and start contributing to our community. It's free for basic access, or support us by becoming an Elite Member -- see if you qualify for a discount below.
-- Big Mike, Site Administrator
(If you already have an account, login at the top of the page)
I was about to post in the Hire a Programmer section, but thought I would post here in case anyone has tried this since the original posting.
I am looking to do the same thing as the original poster. I am not concerned much with performance since the optimization period and parameters would all be within a narrow range... like the past week.
According to NinjaTrader it is 'technically possible' to optimize a strategy within the strategy while it is running. Does anyone have any idea at all how this might be accomplished? NinjaTrader of course is not supporting this and the lack of documentation is a little frustrating.
I am doing this now. The most desirable approach would be the method mentioned above by bnichols. What I am doing works and is stable, but will win no speed records.
If you want to do it my way, here is what you need to do:
1. Write your strategy to work on bar N instead of the current bar. This means using Close[N] instead of Close[0]. Either pass to each function, or make as globals, the current bar N and a flag to denote if you are running "for real" or in your virtual environment.
2. Write a wrapper around the event functions in NT. This is a lot easier if you write dumb strategies like me and do everything synchronously around OnBarUpdate. I use a surrogate called OnBarUpdateVirtual. OnBarUpdateVirtual functions exactly like OnBarUpdate normally would. This way, I can call OnBarUpdateVirtual from the strategy itself. My actual OnBarUpdate function is a one-liner that merely calls OnBarUpdateVirtual.
3. Write your own backtest and fill algorithm. This is fairly easy. Just handle conditions for stops, targets, and specified trade exits, and make up logic to estimate a fill and slippage. If you know your starting date, you can find how many bars back it is. A backtesting algorithm will simply loop through bars, calling OnBarUpdateVirtual. You'll also have to keep track of stats, trades, and profits and losses. This sounds harder than it is.
4. Write your own optimization algorithm. I use particle swarm optimization. Pick your flavor. You'll also have to write your own performance metric to gauge your virtual backtest results.
That's it. My strategies are set for a periodic self-optimization, or if performance falls below a threshold. At a given time, the strategy optimizes itself, automatically adjusting whatever strategy parameters I specified. It actually works quite well.
If the above doesn't scare you, then you can do it. I have a background in optimization and engineering. But not programming. There may be a more elegant or smarter way. But, this method works for me.
Please note. For some strategies, periodic reoptimization works great. For others, very much not. You can do a lot of first-order testing by using the built in Walk-Forward tool in NT.
thanks a lot for those details serac, it really helps. Quite an interesting approach too: simple and effective.. just how it should be.
the logic seems straight forward... although I'm thinking the implementation might be another story.... for example, I'm assuming during optimization/backtest you can't test a trade in the traditional way using Enter/xitLong() because you wouldn't want your optimization to submit live orders during backtesting, which means you can't use the TradeCollection or systemperformance to analyze your metrics, which, as you say, means all those calculations for things like MAE/MFE, fill prices, stop losses, etc. would need to be scoped and programmed... if done from scratch, the QA testing on this alone would be quite protracted to ensure there are no bugs.
I was secretly hoping that the existing optimizer/backfill classes in NinjaTrader could be called somehow from within a strategy or other class, but it appears this is not the case (?) it would be a lot easier to use the existing optimizer types and methods and keep everything tidy, but hey at least there's a way to do it, so may as well get started. I'd just really hate to see this implemented in NinjaTrader 8 after spending 80 hours to code and test
Wrappers around everything. I am passing a "isReal" Boolean to almost every function. Ideally, you want to minimize the forking in logic between the real and virtual trades. But, when you actually implement it, the forking is all over the place: anywhere you call a NT specific function, you likely need a fork.
Honestly, I find the concept of a strategy calling itself somewhat elegant. The actual implementation is cumbersome, but not complex.Ideally, this could be put into a nice overloaded package by someone like NJAMC. This is not a project for me.
I pushed NT support pretty hard about exactly what I could and could not do with leveraging NT's built-in backtesting capabilities. The answer was a definite "no." Backtesting cannot be invoked within a strategy (perhaps, explicitly so to avoid runaway recursion).
The real downer is the NT disables distributed for/while loops. So, anything you run (i.e. an optimization) runs on one processor. Stuff like this is highly parallel, and would shine if you could utilize more than one processor. Maybe NT8? One can hope...
I`ve also been trying to include some form of optimisation in my strategy but can`t get it to work.
Conceptually I understand your method of writing a wrapper around the event functions in NT.
However, I am not sure how to program this. Especially the part of the OnBarUpdateVirtual puzzles me, how do you program this in NT? Second thing is that I am not known with a backtest and fill algorithm code that I can use.
So, I was hoping you could maybe post some example code in order to learn how this would look like. Can understand if you do not want to post your exact code but an example would help.
Unfortunately, it would be very difficult for me to post example code. I'm not sure how helpful it would be anyway. This method results in very confusing code.
Basically, you need to write replacements for almost all the NinjaTrader functions your strategy uses. Everything - EnterLong, SetStopLoss, even Close[0]. Your new replacement functions have two branches. One branch calls the original NT function, the other branch calls some surrogate function you have written. You will have a master Boolean that controls each branch. If your strategy is running in "real life," it will use the actual NT functions. If it is backtesting/optimizing itself, it is calling the surrogate functions. If you are careful, you minimize the differences between each branch, so that the surrogate functionality is as close to the NT functionality as possible.
Next, you will need to write backtesting and optimization functions. Optimization functions can be lifted from many good sources on the net. I prefer Particle Swarm optimization, but this is by no means a holy grail. A backtesting function is remarkably simple - simply loop from a starting bar to and ending bar, and call OnBarUpdate. But remember, you have written a wrapper around OnBarUpdate. So, when your backtesting loop calls the OnBarUpdate surrogate, your entire strategy is executed, not in real life, but in an imaginary backtest.
There are lots of intricacies, such as a fill model for your backtest. My fill model is fairly crude. It cheats by looking ahead to the next bar (that hasn't happened yet). It then takes the worst fill of either the enter bar or the next bar. You can chose your model.
I am not a sophisticated coder. There is nothing I haven't described. The idea is straightforward, but it get complicated very quickly because your strategy is calling itself. I've tried more sophisticated approaches, such as breaking the strategy off into another thread. NT always locks up when I try to do this (which would be nice, because then you could run the optimization on multiple threads - something all optimizations cry out for).
I've implemented this approach on several strategies. On a fairly simple moving average crossover strategy, the total number of code lines was well above 1000. Not because of any inherent complexity, but because so much has to be written to take care of what NT usually does.
So, do answer your question, I approached OnBarUpdate such as this:
To walk you through it, the first if statement returns if I am running real time and the date are historical. The Boolean isBacktest is set by a #define. I have to recompile to switch between running real time and backtesting in NT. The second line simply takes care of the nasty MBTrading rollover time. I prefer to go brain-dead during this period, and do not trade. The third line allows me to only run on the main/primary bar. ProcessScrewUp() is a fail-safe function that looks for overfills. Finally, the last branch of the if/then statement directs me to OnBarUpdateInternal(). The function OnBarUpdateInternal() contains the backbone of the strategy. Notice that I am passing "true" and "0" to OnBarUpdateInternal. The "true" means that I am telling OnBarUpdateInternal() to run for real life (not self-optimization). The "0" means that OnBarUpdateInternal is to use the 0th, or current bar. Additional functions within the strategy periodically kick off the optimization routine, which calls the backtesting function. This backtesting function calls OnBarUpdateInternal(false, backtestBarNum), for a loop of: "backtestBarNum = initBacktestBar; backtestBarNum >= 0; backtestBarNum--". When OnBarUpdateInternal is called with "false", it uses the surrogate functions, and not the NT functions.
Wow... hard to believe a year has passed since I tackled this based on Serac's original suggestions (thanks Serac!) I've been meaning to post my results so good job digging up this thread.
I tried to implement it close to your approach Serac... I'm sure there's a wrong turn somewhere.
Anyway, here are my notes on the subject... hopefully to the benefit of anyone attempting this...
1) My implementation uses brute-force optimization... the reason is because i wanted to test within a narrow range of parameters which wouldn't require much processing power, and my coding skills aren't good enough to implement PSO or similar optimization algorithms... (at least not within a reasonable amount of time or within my patience threshold : )
2) My strategies are mainly cross-over strategies that use custom bars and a series of custom predictive moving averages. With cross-over strategies, with real-time optimization, you can actually see the difference between trending patterns and distribution selling (sideways trading) within your profit (equity) curve.
3) The only way I personally benefited from real time optimization is I became a better code, and it helped me understand the patterns that evolve over certain periods of an instrument.
4) Is real time optimization feasible? For me, I would say yes, insofar as your strategy requires it. It's no secret here that over-optimization can lead to 'curve fitting', and this real time approach is no different. What could make it feasible is to either a) incorporate a walk-forward step to mitigate the curve fitting and/or b) choose a strategy that benefits from curve fitting, such as historical pattern recognition.
Here is my optimize/backtest routine for a simple moving average strategy (excluding variable declarations and onbarupdate code)... I worked on this off/on for the past year... hopefully it helps save time for anyone else trying to do the same thing...
Hello -
I have the same objective as the posters on this thread, I think it is beyond the scope of most retail traders because the technology has to be home built, except potentially in one case. I wonder if anyone on this thread has used/considered a product called Dakota by Biocomp (google it)? The product does walk forward swarm adaption for trading signals.
I am in no way associated with this company and certainly do not want to promote it. I am considering using it as an avenue to achieve what the posters in this thread are attempting and would value opinions.
If the moderator sees this as spam (hopefully not) then feel free to remove it.
Thanks