NexusFi: Find Your Edge


Home Menu

 





Calling an Optimization in a Strategy


Discussion in NinjaTrader

Updated
      Top Posters
    1. looks_one serac with 6 posts (8 thanks)
    2. looks_two d416 with 3 posts (5 thanks)
    3. looks_3 Trader.Jon with 2 posts (1 thanks)
    4. looks_4 Big Mike with 1 posts (0 thanks)
      Best Posters
    1. looks_one bnichols with 2 thanks per post
    2. looks_two d416 with 1.7 thanks per post
    3. looks_3 serac with 1.3 thanks per post
    4. looks_4 Trader.Jon with 0.5 thanks per post
    1. trending_up 9,896 views
    2. thumb_up 16 thanks given
    3. group 10 followers
    1. forum 17 posts
    2. attach_file 0 attachments




 
Search this Thread

Calling an Optimization in a Strategy

  #11 (permalink)
 d416 
Toronto, Canada
 
Experience: Intermediate
Platform: NinjaTrader, IB
Trading: what's liquid, trending, and predictable
Posts: 34 since Aug 2011
Thanks Given: 15
Thanks Received: 36

Hi,

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.


cheers -Dave

Visit my NexusFi Trade Journal Reply With Quote
Thanked by:

Can you help answer these questions
from other members on NexusFi?
NexusFi Journal Challenge - May 2024
Feedback and Announcements
Trade idea based off three indicators.
Traders Hideout
Pivot Indicator like the old SwingTemp by Big Mike
NinjaTrader
Exit Strategy
NinjaTrader
ZombieSqueeze
Platforms and Indicators
 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Spoo-nalysis ES e-mini futures S&P 500
48 thanks
Just another trading journal: PA, Wyckoff & Trends
35 thanks
Tao te Trade: way of the WLD
24 thanks
Bigger Wins or Fewer Losses?
24 thanks
GFIs1 1 DAX trade per day journal
22 thanks
  #12 (permalink)
 
serac's Avatar
 serac 
Arizona, USA
 
Experience: Intermediate
Platform: NinjaTrader
Broker: MB Trading
Trading: Cello
Posts: 116 since Jan 2011
Thanks Given: 321
Thanks Received: 138


d416 View Post
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 completely forgot about this thread...

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.

Good luck!

Started this thread Reply With Quote
Thanked by:
  #13 (permalink)
 d416 
Toronto, Canada
 
Experience: Intermediate
Platform: NinjaTrader, IB
Trading: what's liquid, trending, and predictable
Posts: 34 since Aug 2011
Thanks Given: 15
Thanks Received: 36


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


Thanks again!!

Visit my NexusFi Trade Journal Reply With Quote
Thanked by:
  #14 (permalink)
 
serac's Avatar
 serac 
Arizona, USA
 
Experience: Intermediate
Platform: NinjaTrader
Broker: MB Trading
Trading: Cello
Posts: 116 since Jan 2011
Thanks Given: 321
Thanks Received: 138

Exactly.

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...

Started this thread Reply With Quote
Thanked by:
  #15 (permalink)
majansen
Rotterdam, Netherlands
 
Posts: 1 since Jul 2013
Thanks Given: 0
Thanks Received: 0

Hi Serec,

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.

Regards,
Michel

Reply With Quote
  #16 (permalink)
 
serac's Avatar
 serac 
Arizona, USA
 
Experience: Intermediate
Platform: NinjaTrader
Broker: MB Trading
Trading: Cello
Posts: 116 since Jan 2011
Thanks Given: 321
Thanks Received: 138

Michel,

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:
 
Code
        // The real OnBarUpdate.
        protected override void OnBarUpdate()
        {
			if      ( Historical && !isBacktest)                   { return;                                  }
			else if (!Historical && IsMBTradingRollover()) { return;                                  }
                        else if (BarsInProgress != 0)                        { return;                                  }
			else if (panicMode)                                      { ProcessScrewUp();                 }
			else                                                           { OnBarUpdateInternal(true, 0); }
        }
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.

Does this all make sense?

Started this thread Reply With Quote
Thanked by:
  #17 (permalink)
 d416 
Toronto, Canada
 
Experience: Intermediate
Platform: NinjaTrader, IB
Trading: what's liquid, trending, and predictable
Posts: 34 since Aug 2011
Thanks Given: 15
Thanks Received: 36

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...

-Dave


 
Code
private void optimize()  //========OPTIMIZEr
	{

		//========================== OPTIMIZE ============================= start
			bestProfit = 0; // tracking best profit for the optimization
		
	
   for (int Period1idx = 2; Period1idx <= Period1;   Period1idx+=incrementPeriod1)  //  OUTER LOOP - Period1 optimization
	{			
		for (int Period2idx = 2; Period2idx <= Period2; Period2idx+=incrementPeriod2)  // inner loop - Period2 optimization
		{
			// reset all cumulative variables before each backfill
			PnL = 0; //  PnL for the trade
			cumulativeProfit = 0; // total profit for the parameters backtested
			longshort=0; // used to track the position of the virtual trade. 1=long, 2=short, 0=flat
		
			indicatorOPT1 = SMA(Period1idx); // set up the SMA and assign it the two values currently in the loop 
			indicatorOPT2 = SMA(Period2idx);
			
			for (int idx = lookBackPeriod; idx <= CurrentBar; idx++) // backtest/fill loop:  traversing along the lookback period
			{
				golong = (indicatorOPT1[idx-2] < indicatorOPT2[idx-2] && indicatorOPT1[idx-1] > indicatorOPT2[idx-1] ); // similates NT's CrossAbove() function
				goshort = (indicatorOPT1[idx-2] > indicatorOPT2[idx-2] && indicatorOPT1[idx-1] < indicatorOPT2[idx-1] );// simulates NT's CrossBelow() function

				if (golong)				
				{
					if (longshort != 1) // if 'flat' (i.e. first trade) then take position but don't run through profit calculation
					{
						PnL = ((Open[EntryBar] - slippage) - (Open[idx] + slippage));
						cumulativeProfit += PnL;
					}
					EntryBar = idx;  // the bar that the virtual position is taken
					longshort = 1; // trade is long

				} // end long logic
				
				else if (goshort)	
				{
						if (longshort != 2)
						{
							PnL = ((Open[idx] - slippage) - (Open[EntryBar] + slippage));
							cumulativeProfit += PnL;
						}
						
						EntryBar = idx;
						longshort = 2;  // virtual trade now short
						
				} //end short logic
					
				
				// close out final position and add to PnL - similar to NT's 'exit on close' on a backtest
				
				if (longshort == 2)
				{
						PnL = (Open[EntryBar] - Close[idx] + slippage);
						cumulativeProfit += PnL;
				}
				else if (longshort == 1)
				{
							PnL = (Open[idx] - Close[EntryBar] - slippage);
							cumulativeProfit += PnL;
				}
				
				
				
			} //--- END backtest/fill
		
				/// Store parameters based on best net profit of the backtest
				if (cumulativeProfit > bestProfit)
				{
					bestProfit = cumulativeProfit;
					bestPeriod1 = Period1idx;
					bestPeriod2 = Period2idx;
				}

		}//=== END Inner Loop (Period1 optimization)
	} // END OUTER LOOP -  Period2 optimization
				

		} //--end optimize() =========================== OPTIMIZE ============ end

Visit my NexusFi Trade Journal Reply With Quote
Thanked by:
  #18 (permalink)
 waveslider 
Victoria, BC
 
Experience: Master
Platform: Tradestation Multicharts
Trading: es
Posts: 18 since Oct 2011
Thanks Given: 6
Thanks Received: 13

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

Reply With Quote




Last Updated on September 2, 2015


© 2024 NexusFi™, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Privacy Policy - Downloads - Top
no new posts