Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Trailing Stop

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

    Trailing Stop

    I am not seeing my mistake, I guess I am coding it wrong. I have a trailing stop for longs that works perfect... heres a sample:

    -----
    if (Position.MarketPosition == MarketPosition.Flat)
    {
    currentStop = 0;
    trail = false;
    SetStopLoss(CalculationMode.Ticks, stoplossticks);
    }

    else if (Position.MarketPosition == MarketPosition.Long && trail == false)
    {
    // After 10 ticks set stop loss to BE-10
    if (Close[0] >= Position.AvgPrice + 10 * TickSize && Close[0] < Position.AvgPrice + 15 * TickSize && currentStop < Position.AvgPrice - 10 * TickSize)
    {
    currentStop = Position.AvgPrice - 10 * TickSize;
    SetStopLoss(CalculationMode.Price, currentStop);
    }
    -----

    Now when I try to reverse it for shorts, it ignores the short stop:

    -----
    if (Position.MarketPosition == MarketPosition.Flat)
    {
    currentStop = 0;
    trail = false;
    SetStopLoss(CalculationMode.Ticks, stoplossticks);
    }

    else if (Position.MarketPosition == MarketPosition.Short && trail == false)
    {
    // After 10 ticks set stop loss to BE-10
    if (Close[0] <= Position.AvgPrice - 10 * TickSize && Close[0] > Position.AvgPrice - 15 * TickSize && currentStop > Position.AvgPrice + 10 * TickSize)
    {
    currentStop = Position.AvgPrice + 10 * TickSize;
    SetStopLoss(CalculationMode.Price, currentStop);
    }
    -----

    I changed the MarketPosition.Long to MarketPosition.Short and changed greater to less than, switched + for -'s and such and it does not work. This should work correct? An example is it shorts at 1546, drops to 1540 (more than 10 ticks) and it doesnt update? I have TraceOrders = true; and checked the logs and it tells me nothing.

    Thanks for any help on this.
    Shawn

    #2
    Hello shawnkm,

    I think you may be using a sample I have created previously called CustomStopStrategyWithTrailExample to model your code after.

    For another forum member, I did create an example of this that works with shorts instead of longs.
    Attached Files
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Chelsea, do you have the reverse strategy for Long?

      Comment


        #4
        bughatti,

        http://ninjatrader.com/support/forum...326#post406326
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          I have followed both of ChelseaB's examples to set up protective and trailing stops for my strategy, but I am having a problem with it at the moment. The stops work ok on my Long entries and on the 1st short entry. However, on the next short entry, there is no protective stop or trailing stop being placed, and the entry just runs on until the end of the day in Market Replay mode. I cannot see what is wrong with the code and have pasted it here in the hope that someone can spot the problem.

          Code:
          protected override void Initialize()
          {
          	SetStopLoss(CalculationMode.Ticks, stoplossticks);
          }
          
           protected override void OnBarUpdate()			
          		
          {
          	if (Position.MarketPosition == MarketPosition.Flat)
          	{				
          		currentStop = 0;
          		trail = false;
          		SetStopLoss(CalculationMode.Ticks, stoplossticks);
          	}
          
          		//Set initial stop loss position - short entry	
          		if (Position.MarketPosition == MarketPosition.Short && trail == false 
          		&& Math.Abs(((MAX(High,3)[0] + TickSize) - Position.AvgPrice) * tickPriceMultiplier) > stoplossticks)
          		{ 
          			stoplossticks = (int) Math.Abs((MAX(High,3)[0] + TickSize) * tickPriceMultiplier); //(int) used in front due to CS0266 error 
          		}
          					
          		// If a short position is open, allow for stop loss modification to breakeven
          		else if (Position.MarketPosition == MarketPosition.Short && trail == false)
          		{									
          		// After 11 ticks set stop loss to BE+11 (I would want to set it to BE to keep 11ticks behind all the time)
          
          		if (Close[0] <= Position.AvgPrice - 11 * TickSize && currentStop > Position.AvgPrice)//My adjustment to remain 11 ticks behind 
          		{
          		currentStop = Position.AvgPrice; //My adjustment to remain 11 ticks behind
          		SetStopLoss(CalculationMode.Price, currentStop);
          		trail = true; // after the trail is set to true, the stop loss trail in OnMarketData will take over
          		}
          		}
          
          
          
          		//Set initial stop loss position - long entries	
          		if (Position.MarketPosition == MarketPosition.Long && trail == false 
          		&& Math.Abs(((MIN(Low,3)[0] - TickSize) - Position.AvgPrice) * tickPriceMultiplier) > stoplossticks)
          		{
          
          		stoplossticks = (int) Math.Abs((MIN(Low,3)[0] - TickSize) * tickPriceMultiplier);  //(int) used in front due to CS0266 error 
          		}
          
          		// If a long position is open, allow for stop loss modification to breakeven
          		else if (Position.MarketPosition == MarketPosition.Long && trail == false)
          		{
          		// After 11 ticks set stop loss to BE-11
          
          		if (Close[0] >= Position.AvgPrice + 11 * TickSize && currentStop < Position.AvgPrice - 11 * TickSize) //My adjustment to remain 11 ticks behind 
          		{
          		currentStop = Position.AvgPrice; //My adjustment to remain 11 ticks behind
          		SetStopLoss(CalculationMode.Price, currentStop);
          		trail = true; // after the trail is set to true, the stop loss trail in OnMarketData will take over
          
          		}
          		}
          
          
          
          }
          
          			protected override void OnMarketData(MarketDataEventArgs e)
          		{
          			// After 12 ticks set stop loss to CurrentPrice - 11 Ticks. Repeat every 2 ticks.
          			// This is done in OnMarketUpdate so that it happens intra-bar
          			if (Position.MarketPosition == MarketPosition.Short) 
          			if (e.MarketDataType == MarketDataType.Last && trail == true && e.Price < currentStop - 12 * TickSize)
          			{
          				currentStop = e.Price + 11 * TickSize;
          				SetStopLoss(CalculationMode.Price, currentStop);
          			}
          			
          			// After 12 ticks set stop loss to CurrentPrice - 11 Ticks. Repeat every 2 ticks.
          			// This is done in OnMarketUpdate so that it happens intra-bar
          			if (Position.MarketPosition == MarketPosition.Long) 
          			if (e.MarketDataType == MarketDataType.Last && trail == true && e.Price > currentStop + 12 * TickSize)
          			{
          				currentStop = e.Price - 11 * TickSize;
          				SetStopLoss(CalculationMode.Price, currentStop);
          			}
          		}


          Additionally, if I place
          Code:
          if (Historical) return;
          in the OnBarUpdate section, does that mean my strategy is only running on real-time data, and so this stops the strategy being out of sync with my account position if I start the strategy after trading has commenced, so I do not need to manually adjust for this or use the sync to account setting in the strategy parameters?

          Thank you!

          Comment


            #6
            Hello GeorgeW,

            I'm not quite sure whats going on in the script. The logic is very different than the logic in the example I have provided in post # 2.

            In the example I created, the currentStop is used to track the current price of the stop loss.
            In your script, what does setting stoplossticks do?

            currentStop in your script, is only set to Position.AvgPrice (the entry price) in OnBarUpdate, so I would expect that the exit would get moved to the break even point. It would not be moved until the code in OnMarketData begins to work.

            I am also not seeing any entry orders being made so I would not expect this script to take a position for either long or short orders.

            Also, the example I have provided is basically two examples. One to show how to move the exit order in OnBarUpdate and the other in OnMarketData. It is not required to have both, but my example has both so that I can demonstrate both ways.

            Last, what is the behavior that is not working? Does the move to breakeven never happen?
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Thanks for your help, ChelseaB. Your explanation has helped, and I have adjusted so that I am now only seeing one issue. I’ll work on it and report back, maybe tomorrow.

              In the meatime:

              I provided the part of the code without the entries for ease.

              Stoplossticks – I start at a Min of 6 ticks (in variables region definition), and on a short entry (for example), if the difference between the Max high of the previous 3 bars and the entry price is greater than 6 ticks, then that value becomes the stoplossticks. I have inserted the following below the stoplossticks calculation:

              Code:
              SetStopLoss(CalculationMode.Ticks, stoplossticks); 
              currentStop = Position.AvgPrice + stoplossticks * TickSize;
              Additionally, in the second part of the code, once price has moved 11 ticks in my favour, rather than recalculating the currentStop and resetting SetStopLoss, I have just set trail = true so that the trail in OnMarketData takes over.

              It all seemed to be working fine until a short entry where the trail did not kick in (although it did for earlier short and long entries).

              Comment


                #8
                Hello,
                I have posted the script below but left off some irrelevant array info, arguments and conditions. The only relevant parts for this purpose are the entries and the stop losses.

                Stop Losses:
                After I set the stoplossticks = 6 below OnBarUpdate, they mostly seem to work on 32 of 34 entries for a day that I have looked over. But for the 2 that did not work, one set the stop @ 6 ticks instead of 8 ticks required by my condition for resetting it on entry. The other saw price fall 29 ticks (7.25pts) on a short entry, and instead of the trail kicking in to trail it by 11ticks, price was allowed to pull back and close at a loss of 1 tick.

                Reverse Entries:
                If I set limit or stoplimit entries, Market Replay completes the day I am testing it on, but without any entries being reversed on a reverse signal. Entries all run until stopped out, and only on a signal after that will a new entry take place.

                When I use a market entry, the first few entries do reverse, although ignoring my requirement for BarsSinceEntry > 7. Then after only a few trades, I get the following error and the strategy shuts down: "submitted an order that generated the following e
                rror 'OrderRejected'. Strategy has sent cancel requests, attempted to close the position and terminated itself.
                "

                Any help would be welcome.

                Code:
                                         protected override void Initialize()
                        {			
                			SetStopLoss(CalculationMode.Ticks, stoplossticks);
                			SetProfitTarget(CalculationMode.Ticks, profittargetticks);
                			
                			DefaultQuantity = 1;
                			
                			EntriesPerDirection = 1;
                			EntryHandling = EntryHandling.AllEntries;
                            
                			CalculateOnBarClose = true;
                			Enabled = true; //This comes from the stop loss and profit target code
                			
                			tovBull = new double[length]; 
                			
                			/*Notice, that, since you did not initialise the tovBull "array elements" they will 
                			all be zero to start with. So you might have to do something like this: */
                			for (int i = 0; i < tovBull.Length; i++)
                    		tovBull[i] = double.MaxValue;			
                			
                			//SOV signals copied from SOVSignal02
                			sovBear = new double[lengthB];
                			for (int k = 0; k < sovBear.Length; k++)
                    		sovBear[k] = double.MaxValue;
                			
                			TraceOrders = true; 		
                        }
                
                		protected override void OnStartUp()
                		{
                			//To enable using a variable for the indicator	in computations below
                			myBsc = MyBuySellChange04 (arguments);			
                			myBsl = MyBuySell04(arguments);
                		}		
                
                     
                        protected override void OnBarUpdate()			
                		
                        {
                			if (CurrentBar < period) return;
                			
                			if (Historical) return; 
                			
                			// Resets the stop loss to the original value when all positions are closed
                			if (Position.MarketPosition == MarketPosition.Flat)
                			{
                				currentStop = 0;
                				stoplossticks = 6;
                				trail = false;
                				SetStopLoss(CalculationMode.Ticks, stoplossticks);
                			}
                			
                				// Reset the trade profitablity counter every day and get the number of trades taken in total.
                				if (Bars.FirstBarOfSession && FirstTickOfBar)
                			{
                				lastThreeTrades = 0;
                				priorSessionTrades = Performance.AllTrades.Count;
                			}
                			
                				/* Here, Performance.AllTrades.Count - priorSessionTrades checks to make sure there have been three trades today.
                				priorNumberOfTrades makes sure this code block only executes when a new trade has finished. */
                				if ((Performance.AllTrades.Count - priorSessionTrades) >= 5 && Performance.AllTrades.Count != priorNumberOfTrades)
                			{
                				// Reset the counter.
                				lastThreeTrades = 0;
                				
                				// Set the new number of completed trades.
                				priorNumberOfTrades = Performance.AllTrades.Count;
                				
                				// Loop through the last three trades and check profit/loss on each.
                				for (int idx = 1; idx <= 5; idx++)
                				{
                					/* The Performance.AllTrades array stores the most recent trade at the highest index value. */
                					Trade trade = Performance.AllTrades[Performance.AllTrades.Count - idx];
                
                					/* If the trade's profit is greater than 0, add one to the counter. If the trade's profit is less than 0, subtract one.*/
                					if (trade.ProfitCurrency > 0)
                						lastThreeTrades++;
                					else if (trade.ProfitCurrency < 0)
                						lastThreeTrades--;
                				}
                			}
                			
                			{
                			//the array now contains the number length of object references that need to be set to instances of objects
                			for (int count = 1; count<tovBull.Length; count++) //Think count = 1 here, because next line count - 1 cannot be smaller than 0
                			tovBull[count]=tovBull[count - 1]; //shuffle along by one
                			tovBull[0] = tovBullBar;//adds latest to front of the array, because you shuffled along by one, latest is always index 0		
                		
                			
                			//Bear TOV Calculation
                			if (conditions)
                			{
                					DrawArrowDown("Down Arrow" + CurrentBar, false, 0, High[0] + 2*TickSize, Color.Red);
                
                					if (firstTradeOccurred = false && (ToTime(Time[0]) >= 143000 && ToTime(Time[0]) < 210000))					
                					{	
                					
                					if (lastThreeTrades != -5)
                					
                					Print (Time.ToString()+" "+lastThreeTrades); 
                					EnterShortStopLimit(DefaultQuantity, Low[0] - 2 * TickSize, Low[0] - TickSize, "SE1");
                					firstTradeOccurred = true;
                					Print (Time.ToString()+" "+Position.AvgPrice);
                					}
                
                					if (firstTradeOccurred = true && (ToTime(Time[0]) >= 143000 && ToTime(Time[0]) < 210000)
                					&& ((Position.MarketPosition == MarketPosition.Long && BarsSinceEntry("LE1") > 7) || Position.MarketPosition == MarketPosition.Flat))
                					{	
                					
                					if (lastThreeTrades != -5)						
                
                //					EnterShortStopLimit(DefaultQuantity, Low[0] - 2 * TickSize, Low[0] - TickSize, "SE1");
                //					EnterShortLimit(DefaultQuantity, Low[0] - 2 * TickSize, "SE1");
                					EnterShort(DefaultQuantity, "SE1");
                					Print (Time.ToString()+" "+Position.AvgPrice);
                					}
                					
                					//Set initial stop loss position - short entry	
                					if (Position.MarketPosition == MarketPosition.Short && trail == false 
                					&& Math.Abs(((MAX(High,3)[0] + TickSize) - Position.AvgPrice) * tickPriceMultiplier) > stoplossticks)
                					{
                					stoplossticks = (int) Math.Abs(((MAX(High,3)[0] + TickSize) - Position.AvgPrice) * tickPriceMultiplier); 
                 
                					SetStopLoss(CalculationMode.Ticks, stoplossticks); //My insert
                					currentStop = Position.AvgPrice + stoplossticks * TickSize;
                					Print (Time.ToString()+" "+Close[0]+"Short - Initial Stop:"+currentStop);
                					}
                
                					if (Position.MarketPosition == MarketPosition.Short && trail == false 
                					&& Low[0] <= currentStop - 11 * TickSize)
                				{
                					trail = true; 
                				}
                
                				}
                								
                			}
                						
                			}
                
                			if (check && Time[0] >= firstSig.AddMinutes(maxSignalTime))
                			{
                			Array.Clear(tovBull,0,9); 
                			tovBullBar = 0; 
                			check = false; 
                			}
                			}		
                			
                			{
                			//SOV Signals 			
                			for (int countB = 1; countB<sovBear.Length; countB++)
                			sovBear[countB]=sovBear[countB - 1]; 
                			sovBear[0] = sovBearBar;
                			
                				
                			//Bull SOV Calculation 
                
                				if (conditions)
                					
                				{
                					DrawArrowUp("Up Arrow" + CurrentBar, false, 0, Low[0] - 2*TickSize, Color.Green);
                					
                					if ((firstTradeOccurred = false && (ToTime(Time[0]) >= 143000 && ToTime(Time[0]) < 210000)))
                					{
                					Print (Time.ToString()+" "+BarsSinceEntry("SE1")+" "+(ToTime(Time[0]) >= 143000 && ToTime(Time[0]) < 210000));
                					
                					if (lastThreeTrades != -5)
                					
                					EnterLongStopLimit(DefaultQuantity, High[0] + 2 * TickSize, High[0] + TickSize, "LE1");
                					firstTradeOccurred = true;						
                					Print (Time.ToString()+" "+Position.AvgPrice);
                					}
                					
                					if (firstTradeOccurred = true && (ToTime(Time[0]) >= 143000 && ToTime(Time[0]) < 210000)
                					&& ((Position.MarketPosition == MarketPosition.Short && BarsSinceEntry("SE1") > 7) || Position.MarketPosition == MarketPosition.Flat))
                					{
                					Print (Time.ToString()+" "+BarsSinceEntry("SE1")+" "+(ToTime(Time[0]) >= 143000 && ToTime(Time[0]) < 210000));
                					
                					if (lastThreeTrades != -5)
                					
                					EnterLong(DefaultQuantity,"LE1");
                					Print (Time.ToString()+" "+Position.AvgPrice);
                					}
                						
                					//Set initial stop loss position - long entry	
                					if (Position.MarketPosition == MarketPosition.Long && trail == false 
                					&& Math.Abs(((MIN(Low,3)[0] - TickSize) - Position.AvgPrice) * tickPriceMultiplier) > stoplossticks)
                					{
                					stoplossticks = (int) Math.Abs(((MIN(Low,2)[0] - TickSize) - Position.AvgPrice) * tickPriceMultiplier); 
                					SetStopLoss(CalculationMode.Ticks, stoplossticks); //My insert
                					currentStop = Position.AvgPrice - stoplossticks * TickSize;
                					Print (Time.ToString()+" "+Close[0]+"Long - Initial Stop:"+currentStop);
                					}
                
                					if (Position.MarketPosition == MarketPosition.Long && trail == false 
                					&& High[0] >= currentStop + 11 * TickSize)
                				{
                					trail = true; 
                					Print (Time.ToString()+" "+Close[0]+"Long - BE Stop if + 11:"+currentStop);
                				}
                				}
                			}
                			
                			}
                			if (checkB && Time[0] >= firstSigB.AddMinutes(maxSignalTime))
                			{
                			Array.Clear(sovBear,0,9); 
                			sovBearBar = 0; 
                			checkB = false; 
                
                			}
                			}
                			
                        }
                			protected override void OnMarketData(MarketDataEventArgs e)
                		{
                			if (Position.MarketPosition == MarketPosition.Short) 
                			if (e.MarketDataType == MarketDataType.Last && trail == true && e.Price <= currentStop - 11 * TickSize)
                			{
                				currentStop = e.Price + 11 * TickSize;
                				SetStopLoss(CalculationMode.Price, currentStop);
                				Print (Time.ToString()+" "+Close[0]+"Short - Trail Stop:"+currentStop);
                			}
                			
                			if (Position.MarketPosition == MarketPosition.Long) 
                			if (e.MarketDataType == MarketDataType.Last && trail == true && e.Price >= currentStop + 11 * TickSize)
                			{
                				currentStop = e.Price - 11 * TickSize;
                				SetStopLoss(CalculationMode.Price, currentStop);
                				Print (Time.ToString()+" "+Close[0]+"Long - Trail Stop:"+currentStop);
                			}
                		}

                Comment


                  #9
                  Stop Losses:
                  I have found another trailing stop loss that that did not kick in and so resulted in a loss instead of a profit. It has a similarity to the one I described in my previous post in that both positions were entered into on bars immediately following exits on the previous bar in the opposite direction. One of the entries is long, and within 1 tick of the previous bear close. The other entry 4 hours later is short and at the same price as a bull exit on the previous bar. It seems the close proximity of the exit and entries is causing a problem with the trailing stop kicking in.

                  Comment


                    #10
                    Stop Losses:
                    I have checked the problem ones by printing Position.AvgPrice to the output window. They all show 0, despite the fact that on the chart there is an entry price. This then seems to be the reason why the stop loss is not being calculated correctly. Is there any reason why the entry prices are not being picked up by NT?

                    Comment


                      #11
                      The trailing stop issue was resolved by moving the stop loss code in the OnBarUpdate section that was below the entries to above the entries immediately below the code for recalculating the stop loss when flat.

                      The recalculation of the stop losses immediately after an entry now seems mostly resolved by changing the entries from limit orders to stop limit orders.

                      Comment


                        #12
                        Hello,
                        My strategy using the code from the CustomStopStrategyWithTrailExample works in MarketReplay mode, but in the Strategy Analyzer Backtest mode, the trailing stops do not kick in. I have tested both the long and short strategy of the CustomStopStrategyWithTrailExample, and it is also the case that the trailing stops do not work in the Strategy Analyzer Backtest. ES 03-16 Backtesting 7 Jan 2016 for the short position, the trail should stop out a short entry between 10:50-11:00 hrs, but continues until stopped by the profit target. There are other examples. Is there a way of fixing this code for the backtest?

                        Thank you!

                        Comment


                          #13
                          Hello GeorgeW,

                          In what method are you performing the trailing action?

                          If this is in OnMarketData this would not work during a backtest.

                          From the help guide:
                          "This method is not called on historical data (backtest)"
                          http://ninjatrader.com/support/helpG...marketdata.htm
                          Chelsea B.NinjaTrader Customer Service

                          Comment


                            #14
                            Thank you, ChelseaB. I had just moved it to OnBarUpdate and made some adjustments which got it working.

                            Comment


                              #15
                              Hi GeorgeW,

                              As a tip, using a secondary series of 1 tick and performing the trailing logic in OnBarUpdate when BarsInProgress == 1, would be similar to when OnMarketData is triggered.
                              Chelsea B.NinjaTrader Customer Service

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by geddyisodin, Today, 05:20 AM
                              3 responses
                              20 views
                              0 likes
                              Last Post NinjaTrader_Gaby  
                              Started by lorem, Today, 09:18 AM
                              1 response
                              4 views
                              0 likes
                              Last Post lorem
                              by lorem
                               
                              Started by bmartz, Today, 09:30 AM
                              0 responses
                              3 views
                              0 likes
                              Last Post bmartz
                              by bmartz
                               
                              Started by GussJ, 03-04-2020, 03:11 PM
                              14 responses
                              3,245 views
                              0 likes
                              Last Post GussJ
                              by GussJ
                               
                              Started by ArkansasClint, Today, 09:28 AM
                              0 responses
                              2 views
                              0 likes
                              Last Post ArkansasClint  
                              Working...
                              X