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

Setting Take Profit error

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

    Setting Take Profit error

    Hi, I'm creating a strategy where I define some zones, and then if the price goes through one of these zones, place an order.

    I've tryied to set up the SL and TP. I was able to set up the SL, but when i try to place the TP I'm getting some errors as value 0 or values without sense. Also as you can see on the screenshot, I've tryied to make a backtest on the strategy, and when and order is being placed, it tries to place it several times with different TP values (thing that I don't understand).

    Note: I'm trying to place the TP on a 1:1 ratio, same distance to the entryPrice as the SL

    Here I provide the code that I'm using.

    Code:
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public class Zone {
            public double Max { get; set; }
            public double Min { get; set; }
            public double long_or_short { get; set; } // 1 long and 0 short
            public DateTime timestamp { get; set; }
            public double middleCandleMax { get; set; }
            public double middleCandleMin { get; set; }
        }
    
        public class FVGStrategy : Strategy
        {
            private double stopLossTicks = 2;               // Default value, should be dynamically calculated
            private double takeProfitFactor = 1.5;          // Default R:R ratio;
            private double riskPercentage = 1.0;            // Default risk percentage
            double candleCounter = 0;
            double SL;
            double entryPrice;
            List<Zone> zones = new List<Zone>();
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                 = @"Enter the description for your new custom Strategy here.";
                    Name                                        = "FVGStrategy";
                    Calculate                                   = Calculate.OnBarClose;
                    EntriesPerDirection                         = 1;
                    EntryHandling                               = EntryHandling.AllEntries;
                    IsExitOnSessionCloseStrategy                = true;
                    ExitOnSessionCloseSeconds                   = 30;
                    IsFillLimitOnTouch                          = false;
                    MaximumBarsLookBack                         = MaximumBarsLookBack.TwoHundredFiftySix;
                    OrderFillResolution                         = OrderFillResolution.Standard;
                    Slippage                                    = 0;
                    StartBehavior                               = StartBehavior.WaitUntilFlat;
                    TimeInForce                                 = TimeInForce.Gtc;
                    TraceOrders                                 = false;
                    RealtimeErrorHandling                       = RealtimeErrorHandling.StopCancelClose;
                    StopTargetHandling                          = StopTargetHandling.PerEntryExecution;
                    BarsRequiredToTrade                         = 4;
                    // Disable this property for performance gains in Strategy Analyzer optimizations
                    // See the Help Guide for additional information
                    IsInstantiatedOnEachOptimizationIteration   = true;
                }
                else if (State == State.Configure)
                {
                }
            }
    
            protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment){
                Print("----------------------------------------------");
                Print(Time[0]);
                Print("Entry --> " + entryPrice);
                Print("SL --> "+ SL);
    
                SetStopLoss(CalculationMode.Price, SL);
    
                if (order.IsLong){
                    double distance = (entryPrice - stopPrice) * 1; // ratio 1:1
                    double takeProfitPrice = entryPrice + distance;
                    SetProfitTarget(CalculationMode.Price, takeProfitPrice);
                    Print("TP --> "+ takeProfitPrice);
    
                }
                else if (order.IsShort){
                    double distance = (entryPrice - stopPrice) * 1; // ratio 1:1
                    double takeProfitPrice = entryPrice - distance;
                    SetProfitTarget(CalculationMode.Price, takeProfitPrice);
                    Print("TP --> "+ takeProfitPrice);
                }
            }
            // Called on each bar update event
            protected override void OnBarUpdate()
            {
                // Ensure that at least 5 candles have occurred
                if (CurrentBar < 4)
                {
                    return; // Skip the rest of the code if fewer than 5 bars have formed
                }
    
                // CLEAR ZONES IF END OF DAY
                if (Time[0].TimeOfDay == new TimeSpan(00, 00, 00)){
                    for(int i = 0; i < zones.Count; i++){
                        Print(zones[i].timestamp + " --> ZONA" + zones[i].long_or_short);
                    }
                    zones.Clear();              
                    return;
                }
    
                // DEFINING THE ZONES
                full_FVG();
                reversal_FVG();
                opposite_Reversal_SVG();
                hesitant_FVG();
    
                // CHECKING IF THERE'S AN ENTRY
                for (int i = 0; i < zones.Count; i++){
    
                    if((High[0] > zones[i].Min) || (Low[0] < zones[i].Max)){
    
                        if(zones[i].long_or_short == 0){
                            EnterTrade(0, zones[i]);
                        }
    
                        else if(zones[i].long_or_short == 1){
                            EnterTrade(1, zones[i]);
                        }
                        // we remove the zone
                        zones.RemoveAt(i);
                    }
                }
    
            }
            // Logic for entering a trade
            private void EnterTrade(int BuyOrSell, Zone zones)
            {
                // Determine trade size based on risk and stop loss
                double tradeSize = CalculateTradeSize();
                entryPrice = Close[0];
    
                // long
                if(BuyOrSell == 1){
                    SL = zones.middleCandleMin - (2*TickSize);
                    EnterLong(1);  
                }
    
                // short
                if(BuyOrSell == 0){
                    SL = zones.middleCandleMax + (2*TickSize);
                    EnterShort(1);
                }
            }
            // Calculate trade size based on risk management
            private double CalculateTradeSize()
            {
                // Calculate the size of the trade based on the risk percentage and account size
                //double accountRisk = AccountSize * riskPercentage / 100;
                double accountRisk = 10000 * riskPercentage / 100;
                double tradeRisk = stopLossTicks * TickSize;
                return accountRisk / tradeRisk;
            }
        }
    }​
    Here's the output:

    Click image for larger version

Name:	image.png
Views:	139
Size:	179.9 KB
ID:	1283482

    Any idea on how can I solve the issue?

    Thanks in advance for your time.​

    #2
    Hello speedytrade02,

    Thanks for your post.

    This error message indicates that your target order price was smaller or equal to 0.

    It is generally advised to reset the Profit Target when it is in a flat position and then to update the Profit Target with SetProfitTarget() once you see that the order has been placed and you are in a position.

    From the help guide:
    Should you call this method to dynamically change the target price in the strategy OnBarUpdate() method, you should always reset the target price / offset value when your strategy is flat otherwise, the last price/offset value set will be used to generate your profit target order on your next open position

    As a solution, you could reset your Profit Target when in a flat position, and then when you are no longer in a flat position, you can update the profit target.

    Position.MarketPosition can be used to tell if you are long, short, or flat​.

    Order objects may be used as well to track fill prices for orders to be used later in the strategy.

    SetProfitTarget(): https://ninjatrader.com/support/help...ofittarget.htm
    Position.MarketPosition: https://ninjatrader.com/support/help...etposition.htm
    Order objects - https://ninjatrader.com/support/help...n-us/order.htm

    SamplePriceModification: https://ninjatrader.com/support/help...of_stop_lo.htm
    Brandon H.NinjaTrader Customer Service

    Comment


      #3
      Hi Brandon.

      I've just tryied the modifications you've said. But I'm not sure if they're correct. C​ould you please tell me if I'm doing it correctly?

      Here's the updated code:

      Code:
      //This namespace holds Strategies in this folder and is required. Do not change it.
      namespace NinjaTrader.NinjaScript.Strategies
      {
          public class Zone {
              public double Max { get; set; }
              public double Min { get; set; }
              public double long_or_short { get; set; } // 1 long and 0 short
              public DateTime timestamp { get; set; }
              public double middleCandleMax { get; set; }
              public double middleCandleMin { get; set; }
          }
      
          public class FVGStrategy : Strategy
          {
              private double stopLossTicks = 2;               // Default value, should be dynamically calculated
              private double takeProfitFactor = 1.5;          // Default R:R ratio;
              private double riskPercentage = 1.0;            // Default risk percentage
              double candleCounter = 0;
              double SL;
              double entryPrice;
              List<Zone> zones = new List<Zone>();
      
              protected override void OnStateChange()
              {
                  if (State == State.SetDefaults)
                  {
                      Description                                 = @"Enter the description for your new custom Strategy here.";
                      Name                                        = "FVGStrategy";
                      Calculate                                   = Calculate.OnBarClose;
                      EntriesPerDirection                         = 1;
                      EntryHandling                               = EntryHandling.AllEntries;
                      IsExitOnSessionCloseStrategy                = true;
                      ExitOnSessionCloseSeconds                   = 30;
                      IsFillLimitOnTouch                          = false;
                      MaximumBarsLookBack                         = MaximumBarsLookBack.TwoHundredFiftySix;
                      OrderFillResolution                         = OrderFillResolution.Standard;
                      Slippage                                    = 0;
                      StartBehavior                               = StartBehavior.WaitUntilFlat;
                      TimeInForce                                 = TimeInForce.Gtc;
                      TraceOrders                                 = false;
                      RealtimeErrorHandling                       = RealtimeErrorHandling.StopCancelClose;
                      StopTargetHandling                          = StopTargetHandling.PerEntryExecution;
                      BarsRequiredToTrade                         = 4;
                      // Disable this property for performance gains in Strategy Analyzer optimizations
                      // See the Help Guide for additional information
                      IsInstantiatedOnEachOptimizationIteration   = true;
                  }
                  else if (State == State.Configure)
                  {
                  }
              }
      
      
              protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment){
      
                  //double percentage = 1 - (stopPrice / entryPrice);
      
                  if (Position.MarketPosition != MarketPosition.Flat){
                      Print("----------------------------------------------");
                      Print(Time[0]);
                      Print("Entry --> " + Position.AveragePrice);
                      Print("SL --> "+ SL);
      
                      SetStopLoss(CalculationMode.Price, SL);
      
                      if (Position.MarketPosition == MarketPosition.Long){
                          double distance = (Position.AveragePrice - SL) * 1; // ratio 1:1
                          double takeProfitPrice = Position.AveragePrice + distance;
                          SetProfitTarget(CalculationMode.Price, takeProfitPrice);
                          Print("TP --> "+ takeProfitPrice);
      
                      }
                      else if (Position.MarketPosition == MarketPosition.Short){
                          double distance = (SL - Position.AveragePrice) * 1; // ratio 1:1
                          double takeProfitPrice = Position.AveragePrice - distance;
                          SetProfitTarget(CalculationMode.Price, takeProfitPrice);
                          Print("TP --> "+ takeProfitPrice);
                      }
                  }
              }
              // Called on each bar update event
              protected override void OnBarUpdate()
              {
                  // Ensure that at least 5 candles have occurred
                  if (CurrentBar < 4)
                  {
                      return; // Skip the rest of the code if fewer than 5 bars have formed
                  }
      
                  // CLEAR ZONES IF END OF DAY
                  if (Time[0].TimeOfDay == new TimeSpan(00, 00, 00)){
                      for(int i = 0; i < zones.Count; i++){
                          Print(zones[i].timestamp + " --> ZONA" + zones[i].long_or_short);
                      }
                      zones.Clear();              
                      return;
                  }
      
                  // DEFINING THE ZONES
      
                  full_FVG();
                  reversal_FVG();
                  opposite_Reversal_SVG();
                  hesitant_FVG();
      
                  // CHECKING IF THERE'S AN ENTRY
                  for (int i = 0; i < zones.Count; i++){
      
                      if((High[0] > zones[i].Min) || (Low[0] < zones[i].Max)){
      
                          if(zones[i].long_or_short == 0){
                              EnterTrade(0, zones[i]);
                              //EnterTrade_with_SL_TP(0, zones[i]);
                          }
      
                          else if(zones[i].long_or_short == 1){
                              EnterTrade(1, zones[i]);
                              //EnterTrade_with_SL_TP(1, zones[i]);
                          }
                          // we remove the zone
                          zones.RemoveAt(i);
                      }
                  }
      
              }
      
              private void EnterTrade(int BuyOrSell, Zone zones)
              {
                  // Determine trade size based on risk and stop loss
                  double tradeSize = CalculateTradeSize();
                  entryPrice = Close[0];
      
                  // long
                  if(BuyOrSell == 1){
                      SL = zones.middleCandleMin - (2*TickSize);
                      EnterLong(1);            
                  }
      
                  // short
                  if(BuyOrSell == 0){
                      SL = zones.middleCandleMax + (2*TickSize);
                      EnterShort(1);  
                  }
              }
              // Calculate trade size based on risk management
              private double CalculateTradeSize()
              {
                  // Calculate the size of the trade based on the risk percentage and account size
                  //double accountRisk = AccountSize * riskPercentage / 100;
                  double accountRisk = 10000 * riskPercentage / 100;
                  double tradeRisk = stopLossTicks * TickSize;
                  return accountRisk / tradeRisk;
              }
          }
      }
      ​
      I'm not sure if i have to set the take profit and stoploss on the function that I'm doing it "OnOrderUpdate".

      Thanks again in advance and Merry Christmas!

      Comment


        #4
        Hello speedytrade02,

        Thanks for your notes.

        Currently, SetProfitTarget() is only being called when order.IsLong or order.IsShort is true in OnOrderUpdate().

        It is possible to call SetProfitTarget() and SetStopLoss() in OnOrderUpdate() but if you want to use OnOrderUpdate() then I would recommend following this reference sample that uses OnOrderUpdate() and OnExecutionUpdate() to enter protective orders.

        SampleOnOrderUpdate: https://ninjatrader.com/support/help...and_onexec.htm

        Based on the logic you shared, you may be better off using Exit methods for submitting your profit target and stop loss orders in OnOrderUpdate(), such as ExitLongLimit() and ExitLongStopLimit(), as seen in the reference sample linked above.

        You may also consider making 'takeProfitPrice' a class-level variable instead of re-creating the variable each time your condition is true.

        And, add further debugging prints one line above your profit target order method that prints out the price the order is being submitted to understand exactly how that logic is behaving. Also, to print out the all the values being used in the condition (one line above the condition) to see how that logic is evaluating.
        Brandon H.NinjaTrader Customer Service

        Comment


          #5
          Hi Brandon.

          I've just updated my "OnBarUpdate" function this way:

          Code:
                  protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment){
          
                      if (Position.MarketPosition != MarketPosition.Flat){
                          Print("----------------------------------------------");
                          Print(Time[0]);
                          Print("Entry --> " + Position.AveragePrice);
                          Print("SL --> "+ SL);
          
                          if (Position.MarketPosition == MarketPosition.Long){
                              double distance = (Position.AveragePrice - SL) * 1; // ratio 1:1
                              double takeProfitPrice = Position.AveragePrice + distance;
          
                              ExitLongStopMarket(SL);
                              ExitLongLimit(takeProfitPrice);
          
                              Print("TP --> "+ takeProfitPrice);
          
                          }
                          else if (Position.MarketPosition == MarketPosition.Short){
                              double distance = (SL - Position.AveragePrice) * 1; // ratio 1:1
                              double takeProfitPrice = Position.AveragePrice - distance;
          
                              ExitShortStopMarket(SL);
                              ExitShortLimit(takeProfitPrice);
          
                              Print("TP --> "+ takeProfitPrice);
                          }
                      }
                  }​
          But when i perform the backtest, and it tryies to open a trade, it enters on an infinite loop showing this all the time:

          Click image for larger version

Name:	image.png
Views:	41
Size:	36.8 KB
ID:	1283802


          What could be causing this error?

          Comment


            #6
            Hello speedytrade02,

            Thanks for your notes.

            You would need to reduce and debug your code to determine what is causing the loop to occur.

            Reducing code means commenting out sections of code and retesting the script to see if the behavior persists. If the behavior stops after commenting out a section of code, it would likely be that section of commented-out code that was causing the behavior. Further reducing that section of code and adding prints could further help narrow down the offending code.

            Typically, a position will not be both Flat and Long or Short at the same time. The position would either be Flat, or Long, or Short.

            You should move your Position.MarketPosition == MarketPosition.Long and Position.MarketPosition == MarketPosition.Short conditions outside of the condition that checks if Position.MarketPosition == MarketPosition.Flat.

            I also suggest studying the SampleOnOrderUpdate() reference sample linked in post # 4 to see how to use OnOrderUpdate() and OnExecutionUpdate() to submit protective orders when a strategy enters a position and implement similar logic in your script.

            SampleOnOrderUpdate: https://ninjatrader.com/support/help...and_onexec.htm
            Brandon H.NinjaTrader Customer Service

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by lightsun47, Today, 03:51 PM
            0 responses
            5 views
            0 likes
            Last Post lightsun47  
            Started by 00nevest, Today, 02:27 PM
            1 response
            10 views
            0 likes
            Last Post 00nevest  
            Started by futtrader, 04-21-2024, 01:50 AM
            4 responses
            46 views
            0 likes
            Last Post futtrader  
            Started by Option Whisperer, Today, 09:55 AM
            1 response
            14 views
            0 likes
            Last Post bltdavid  
            Started by port119, Today, 02:43 PM
            0 responses
            10 views
            0 likes
            Last Post port119
            by port119
             
            Working...
            X