Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Adjusting Stop Loss using multiple timeframes

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Adjusting Stop Loss using multiple timeframes

    Hi Ninja Support,

    I've tried everything i can think of, but cannot get this to work! I think mostly because i'm using multiple timeframes, and the OnExecution override has little documentation compared to OnOrderUpdate.

    I'm using a simple strategy, which uses a custom indicator. This indicator simply generates values for _longSignal and _shortSignal, and the strategy places stop orders based on those signals (for example, a buy stop at the value of _longSignal or a short stop at the value of _shortSignal).

    All that works fine. Once in a trade, i'd like to adjust my stop loss as i get closer to my target. Specifically once i hit an intermediate target called T1, I'd like to adjust my stop loss to S1. For instance, with these settings my full target is 10 ticks, my full stop-loss is 5 ticks. Once i am onside 7 ticks (T1) i'd like to move the stop loss up to +2 ticks (S1). I'd like to monitor my second, smaller timeframe, to determine when to adjust my stops (and have them effective on that smaller timeframe as well) - using the larger chart is completely impractical for obvious reasons.

    How can i accomplish this?

    Your help is greatly appreciated!!!

    Mr. Orange

    Here's my code so far:

    Code:
    #region Using declarations
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Data;
    using NinjaTrader.Indicator;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Strategy;
    #endregion
    
    
    {
        [Description("Enter the description of your strategy here")]
        public class MyCustomStrategy : Strategy
        {
            #region Variables
            // Wizard generated variables
            private int target = 10; // Default setting for Target
            private int stop = 5; // Default setting for Stop
    		private int volumePeriod = 500;
    		private int T1 = 7;
    		private int T2 = 9;
    		private int S1 = 2;
    		private int S2 = 4;
    		private int stopAdjusted = 0;
    		
    		private TimeSpan startTime = new TimeSpan(6,00,00);
    		private TimeSpan endTime = new TimeSpan(14,00,00);
    		
    		private IOrder 	longSignal			= null; // This variable holds an object representing our long entry order.
    		private IOrder 	shortSignal 		= null; // This variable holds an object representing our short entry order.	
    		private IOrder 	stopOrder 			= null; // This variable holds an object representing our stop loss order.
    		private IOrder 	targetOrder 		= null; // This variable holds an object representing our profit target order.
    		private IOrder	mar****rder			= null; // This variable holds an object representing our market EnterLong() order.
           
    		// User defined variables (add any user defined variables below)
            #endregion
    
            /// <summary>
            /// This method is used to configure the strategy and is called once before any strategy method is called.
            /// </summary>
            protected override void Initialize()
            {
    			Add(MyCustomIndicator());
    			Add(EMA(Close,10));
    			Add(EMA(Close,40));
    			Add(PeriodType.Volume, volumePeriod);
    			Add(PeriodType.Volume, 50);
                CalculateOnBarClose = true;
    			
            }
    
            /// <summary>
            /// Called on each bar update event (incoming tick)
            /// </summary>
    		/// 
    
    				protected override void OnExecution(IExecution execution)
            {
    			/* We advise monitoring OnExecution() to trigger submission of stop/target orders instead of OnOrderUpdate() since OnExecution() is called after OnOrderUpdate()
    			which ensures your strategy has received the execution which is used for internal signal tracking.
    			
    			This first if-statement is in place to deal only with the long limit entry. */
    			if (longSignal != null && longSignal == execution.Order)
    			{
    				
    				// This second if-statement is meant to only let fills and cancellations filter through.
    				if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
    				{
    					
    					// Simple stop and target
    					
    					stopOrder = ExitLongStop(2, true, 1, execution.Price - Stop * TickSize, "stop", "longEntry");
    					targetOrder = ExitLongLimit(2, true, 1, execution.Price + Target * TickSize, "target", "longEntry");
    					
    					
    					
    					//Resets the longSignal object to null after the order has been filled
    					if (execution.Order.OrderState != OrderState.PartFilled)
    					{
    						longSignal 	= null;		
    					}
    					
    					// Reset our stop order and target orders' IOrder objects after our position is closed.
    					if ((stopOrder != null && stopOrder == execution.Order) || (targetOrder != null && targetOrder == execution.Order))
    					{
    						if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
    						{
    						//	stopAdjusted = 0;
    							stopOrder = null;
    							targetOrder = null;
    						}
    					}
    				}
    			}
    			
    			//This first if-statement is in place to deal only with the long limit entry. */
    			if (shortSignal != null && shortSignal == execution.Order)
    			{
    				
    				// This second if-statement is meant to only let fills and cancellations filter through.
    				if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
    				{
    					// Simple stop and target
    						stopOrder = ExitShortStop(2, true, 1, execution.Price + Stop * TickSize, "stop", "shortEntry");
    						targetOrder = ExitShortLimit(2, true, 1, execution.Price - Target * TickSize, "target", "shortEntry");
    					
    					//Resets the shortSignal object to null after the order has been filled
    					if (execution.Order.OrderState != OrderState.PartFilled)
    					{
    						shortSignal 	= null;		
    					}
    					
    					// Reset our stop order and target orders' IOrder objects after our position is closed.
    					if ((stopOrder != null && stopOrder == execution.Order) || (targetOrder != null && targetOrder == execution.Order))
    					{
    						if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
    						{
    							stopOrder = null;
    							targetOrder = null;
    						}
    					}
    				}
    			}
    			
    			
    		}
    		
            protected override void OnBarUpdate()
            {
    			if(CurrentBar < 50)
    				return;
    			
    		  if(BarsInProgress == 1)
    		  {
    			            
    			if(shortSignal != null && EMA(10)[0] > EMA(40)[0]) 
    				{
    					CancelOrder(shortSignal);  //cancel current short signal
    			    	shortSignal = null;  //cancel further short signals for now	
    				}
    				
    			if(longSignal != null && EMA(10)[0] < EMA(40)[0])
    				{
    					CancelOrder(longSignal);  //cancel current long signal
    			    	longSignal = null;  //cancel further long signals for now
    				}
    			
    			// Condition set 1
                if (MyCustomIndicator()._longSignal[0] > High[0] && EMA(10)[0] > EMA(40)[0] && Time[0].TimeOfDay.CompareTo(startTime) >= 0 && Time[0].TimeOfDay.CompareTo(endTime) <= 0)
    				
                {
    			    longSignal = EnterLongStopLimit(2, true, 1, MyCustomIndicator()._longSignal[0], MyCustomIndicator()._longSignal[0], "longEntry");
    			}
    
                // Condition set 2
                if (MyCustomIndicator()._shortSignal[0] < Low[0] && EMA(10)[0] < EMA(40)[0] && Time[0].TimeOfDay.CompareTo(startTime) >= 0 && Time[0].TimeOfDay.CompareTo(endTime) <= 0)
                {				
    			    shortSignal = EnterShortStopLimit(2, true, 1, MyCustomIndicator()._shortSignal[0], MyCustomIndicator()._shortSignal[0], "shortEntry");	
    			}
    			
    		  }
    		
    		
    		
    		
    	// THIS SEEMS TO MAKE THE STRATEGY COMPLETELY IGNORE STOP ORDERS...	
    	//				if(stopAdjusted == 0) 
    	//				{
    	//					stopOrder = ExitLongStop(2, true, 1, Position.AvgPrice - Stop * TickSize, "stop", "longEntry");
    	//				}
    	//				if(stopAdjusted == 0 && High[0] > Position.AvgPrice + T1*TickSize)
    	//				{
    	//					Print("Adjust Stop 1");
    	//					stopOrder = ExitLongStop(2, true, 1, Position.AvgPrice + S1 * TickSize, "stop", "longEntry");
    	//					stopAdjusted = 1;
    	//				}
    	//				if(stopAdjusted < 2 && High[0] > Position.AvgPrice + T2*TickSize)
    	//				{
    	//					Print("Adjust Stop 2");
    	//					stopOrder = ExitLongStop(2, true, 1 ,Position.AvgPrice + S2 * TickSize, "stop", "longEntry");
    	//					stopAdjusted = 2;
    	//				}
    		
            }
    	
        }
    }

    #2
    MrOrange, first of all : to monitor / debug your order behavior seen you would best work with the TraceOrders option in NT - http://www.ninjatrader.com/support/f...ead.php?t=3627

    The OnExecution() would not be tied to any bars object update timing, which you would need here to update stops in different timeframes, so you would place the initial stop for example from OnExecution() right as your entry fills and then monitor / update the stop as needed from each BarsInProgress.

    For example as your target 1 fills, you would then move to the next lower frame to monitor / update the stop, but you would need to ensure the modifications only come from this frame, so calls to the base timeframe would not reset your stop value in anyway when conditions become true in this code part, this flow needed could be accomplished for example with boolean flags that you set and reset (comparable to the user variables in the Strategy Wizard).

    For this more complex project the best advice would be going slow and only adding more parts / timeframes if the basics are working out as you would expect - verify with Prints that the conditions trigger and values report back as expected.

    When working out stop adjustments / trails a often used method is to Draw a dot for example at the current OnBarUpdate() stopvalue so you can visually see where it would be for comparison.

    Comment

    Latest Posts

    Collapse

    Topics Statistics Last Post
    Started by Geovanny Suaza, 02-11-2026, 06:32 PM
    0 responses
    648 views
    0 likes
    Last Post Geovanny Suaza  
    Started by Geovanny Suaza, 02-11-2026, 05:51 PM
    0 responses
    369 views
    1 like
    Last Post Geovanny Suaza  
    Started by Mindset, 02-09-2026, 11:44 AM
    0 responses
    108 views
    0 likes
    Last Post Mindset
    by Mindset
     
    Started by Geovanny Suaza, 02-02-2026, 12:30 PM
    0 responses
    572 views
    1 like
    Last Post Geovanny Suaza  
    Started by RFrosty, 01-28-2026, 06:49 PM
    0 responses
    574 views
    1 like
    Last Post RFrosty
    by RFrosty
     
    Working...
    X