Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Updating Stop Loss and Profit Targets dynamically

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

    Updating Stop Loss and Profit Targets dynamically

    Hi, I am trying to create a strategy which enters long with two contracts, setting a stop loss a bit below the entry and setting a couple of profit targets.

    When the first profit target is hit, I want to move the stop loss to the entry price and then move the second profit target to the current price plus 10 points.

    Whatever I try though it doesn't work, it doesn't set the initial stop loss and profit targets.

    Using different coding I was able to set them initially, but then I could not move them them through code

    Please could you help?

    Thank you




    Code:
    [#region Using declarations
    using System;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui.Tools;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Data;
    #endregion
    
    namespace NinjaTrader.NinjaScript.Strategies
    {
    public class DynamicProfitTargetExample : Strategy
    {
    private double entryPrice;
    private bool isBreakEvenSet;
    private bool targetsMoved;
    private Order stopLossOrder;
    private Order profitTargetOrder1;
    private Order profitTargetOrder2;
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"Strategy example to set a break-even stop loss and move it 4 points higher.";
    Name = "DynamicProfitTargetExample";
    Calculate = Calculate.OnEachTick;
    IsInstantiatedOnEachOptimizationIteration = false;
    EntriesPerDirection = 1;
    EntryHandling = EntryHandling.AllEntries;
    IsExitOnSessionCloseStrategy = true;
    ExitOnSessionCloseSeconds = 30;
    StopTargetHandling = StopTargetHandling.ByStrategyPosition;
    IsFillLimitOnTouch = false;
    MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
    StartBehavior = StartBehavior.WaitUntilFlat;
    TimeInForce = TimeInForce.Gtc;
    TraceOrders = false;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
    StopTargetHandling = StopTargetHandling.PerEntryExecution;
    BarsRequiredToTrade = 20;
    }
    else if (State == State.Configure)
    {
    // Configure your strategy here
    }
    }
    
    protected override void OnBarUpdate()
    {
    // Ensure we have enough bars to proceed
    if (CurrentBar < BarsRequiredToTrade)
    return;
    
    // Example entry condition (you would replace this with your own logic)
    if (CrossAbove(Close, SMA(14), 1))
    {
    // Enter a long position
    EnterLong(2);
    
    // Set the entry price
    entryPrice = Close[0];
    
    // Set the initial profit targets
    profitTargetOrder1 = ExitLongLimit(0, true, Position.Quantity / 2, entryPrice + 7, "Profit target 1", "Entry");
    profitTargetOrder2 = ExitLongLimit(0, true, Position.Quantity / 2, entryPrice + 15, "Profit target 2", "Entry");
    
    // Set the stop loss
    stopLossOrder = ExitLongStopMarket(0, true, Position.Quantity, entryPrice - 2, "Stop loss", "Entry");
    
    // Reset the flags
    isBreakEvenSet = false;
    targetsMoved = false;
    }
    
    // Adjust stop loss profit targets if price moves 5 points above the entry price
    if (Position.MarketPosition == MarketPosition.Long && Close[0] >= entryPrice + 5 && !targetsMoved)
    {
    stopLossOrder = ExitLongStopMarket(0, true, Position.Quantity, entryPrice, "Stop loss", "Entry");
    profitTargetOrder1 = ExitLongLimit(0, true, Position.Quantity / 2, entryPrice + 10, "Profit target 1", "Entry");
    profitTargetOrder2 = ExitLongLimit(0, true, Position.Quantity / 2, entryPrice + 20, "Profit target 2", "Entry");
    targetsMoved = true;
    }
    
    // Determine if the current position is in profit or loss
    if (Position.MarketPosition == MarketPosition.Long)
    {
    if (Close[0] > entryPrice)
    {
    Print("The position is in profit.");
    }
    else
    {
    Print("The position is in loss.");
    }
    }
    else if (Position.MarketPosition == MarketPosition.Short)
    {
    if (Close[0] < entryPrice)
    {
    Print("The position is in profit.");
    }
    else
    {
    Print("The position is in loss.");
    }
    }
    }
    
    protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
    {
    if (execution.Order.OrderState == OrderState.Filled)
    {
    // Check if the execution was for a profit target or stop loss
    if (execution.Order.Name == "Profit target 1" || execution.Order.Name == "Profit target 2" || execution.Order.Name == "Stop loss")
    {
    CancelStopLossAndProfitTarget();
    }
    }
    }
    
    private void CancelStopLossAndProfitTarget()
    {
    // Cancel the stop loss order
    if (stopLossOrder != null)
    {
    CancelOrder(stopLossOrder);
    stopLossOrder = null;
    }
    
    // Cancel the profit target orders
    if (profitTargetOrder1 != null)
    {
    CancelOrder(profitTargetOrder1);
    profitTargetOrder1 = null;
    }
    
    if (profitTargetOrder2 != null)
    {
    CancelOrder(profitTargetOrder2);
    profitTargetOrder2 = null;
    }
    }
    }
    }
    ​

    #2
    Hello,

    To create a strategy that enters long with two contracts, sets a stop loss, and manages two profit targets with adjustments based on reaching the first target, you need to ensure proper handling of orders and state updates. The code below should help you achieve the desired behavior:
    1. Enter a long position with two contracts.
    2. Set an initial stop loss and two profit targets.
    3. Move the stop loss to breakeven when the first profit target is hit.
    4. Adjust the second profit target when the first target is hit.

    Here is the updated code:

    Code:
    #region Using declarations
    using System;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui.Tools;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Data;
    #endregion
    
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public class DynamicProfitTargetExample : Strategy
        {
            private double entryPrice;
            private bool isBreakEvenSet;
            private bool targetsMoved;
            private Order stopLossOrder;
            private Order profitTargetOrder1;
            private Order profitTargetOrder2;
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description = @"Strategy example to set a break-even stop loss and move it higher.";
                    Name = "DynamicProfitTargetExample";
                    Calculate = Calculate.OnEachTick;
                    EntriesPerDirection = 1;
                    EntryHandling = EntryHandling.AllEntries;
                    IsExitOnSessionCloseStrategy = true;
                    ExitOnSessionCloseSeconds = 30;
                    StopTargetHandling = StopTargetHandling.ByStrategyPosition;
                    IsFillLimitOnTouch = false;
                    MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
                    StartBehavior = StartBehavior.WaitUntilFlat;
                    TimeInForce = TimeInForce.Gtc;
                    TraceOrders = false;
                    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
                    BarsRequiredToTrade = 20;
                }
                else if (State == State.Configure)
                {
                    // Configure your strategy here
                }
            }
    
            protected override void OnBarUpdate()
            {
                // Ensure we have enough bars to proceed
                if (CurrentBar < BarsRequiredToTrade)
                    return;
    
                // Example entry condition (you would replace this with your own logic)
                if (CrossAbove(Close, SMA(14), 1))
                {
                    // Enter a long position
                    EnterLong(2);
    
                    // Set the entry price
                    entryPrice = Close[0];
    
                    // Set the initial stop loss and profit targets
                    SetProfitTarget("Profit target 1", CalculationMode.Price, entryPrice + 7);
                    SetProfitTarget("Profit target 2", CalculationMode.Price, entryPrice + 15);
                    SetStopLoss(CalculationMode.Price, entryPrice - 2);
    
                    // Reset the flags
                    isBreakEvenSet = false;
                    targetsMoved = false;
                }
            }
    
            protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
            {
                if (execution.Order.OrderState == OrderState.Filled)
                {
                    // Check if the execution was for the first profit target
                    if (execution.Order.Name == "Profit target 1" && !isBreakEvenSet)
                    {
                        // Move stop loss to breakeven
                        SetStopLoss(CalculationMode.Price, entryPrice);
    
                        // Move the second profit target
                        SetProfitTarget("Profit target 2", CalculationMode.Price, Close[0] + 10);
                        
                        isBreakEvenSet = true;
                    }
                }
            }
        }
    }
    ​
    Explanation:
    1. Initial Orders:
      • EnterLong(2): Enters a long position with two contracts.
      • SetProfitTarget and SetStopLoss: Sets the initial profit targets and stop loss.
    2. Order Management:
      • OnExecutionUpdate handles updates when orders are filled.
      • When the first profit target is hit, it moves the stop loss to breakeven and adjusts the second profit target.
    • Ensure the Calculate property is set to Calculate.OnEachTick for real-time updates.
    • The OnExecutionUpdate method is used to manage order states and make necessary adjustments after the first profit target is hit.


    Please let us know if you have any other questions.

    Comment


      #3
      Hi Thanks for this, I have tried it but it doesn't work reliably unfortunately.

      I think I need to start back on a smaller scale, get it working and then add features to it.

      I removed some of the code to simplify it but what I find is that:

      - The stop loss is added which is great, but when the bar updates it sometimes moves the stop loss and enters more longs until it errors. I think it needs something adding to say if it is already in a long position, don't try the entry logic.

      - When it enters an order, I can see the stop loss on the chart, but I cant see the profit targets, sometimes I may want to adjust them manually, should we use a different order like a buy stop market?



      Code:
      #region Using declarations
      using System;
      using NinjaTrader.Cbi;
      using NinjaTrader.Gui.Tools;
      using NinjaTrader.NinjaScript;
      using NinjaTrader.Data;
      #endregion
      
      namespace NinjaTrader.NinjaScript.Strategies
      {
          public class DynamicProfitTargetExample : Strategy
          {
              private double entryPrice;
              private Order stopLossOrder;
              private Order profitTargetOrder1;
              private Order profitTargetOrder2;
      
              protected override void OnStateChange()
              {
                  if (State == State.SetDefaults)
                  {
                      Description = @"Strategy example to set a break-even stop loss and move it higher.";
                      Name = "DynamicProfitTargetExample2";
                      Calculate = Calculate.OnEachTick;
                      EntriesPerDirection = 1;
                      EntryHandling = EntryHandling.AllEntries;
                      IsExitOnSessionCloseStrategy = true;
                      ExitOnSessionCloseSeconds = 30;
                      StopTargetHandling = StopTargetHandling.ByStrategyPosition;
                      IsFillLimitOnTouch = false;
                      MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
                      StartBehavior = StartBehavior.WaitUntilFlat;
                      TimeInForce = TimeInForce.Gtc;
                      TraceOrders = false;
                      RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
                      BarsRequiredToTrade = 20;
                  }
                  else if (State == State.Configure)
                  {
                      // Configure your strategy here
                  }
              }
      
              protected override void OnBarUpdate()
              {
                  // Ensure we have enough bars to proceed
                  if (CurrentBar < BarsRequiredToTrade)
                      return;
      
                  // Example entry condition (you would replace this with your own logic)
                  if (CrossAbove(Close, SMA(14), 1))
                  {
                      // Enter a long position
                      EnterLong(2);
      
                      // Set the entry price
                      entryPrice = Close[0];
      
                      // Set the initial stop loss and profit targets
                      SetProfitTarget("Profit target 1", CalculationMode.Price, entryPrice + 2);
                      SetProfitTarget("Profit target 2", CalculationMode.Price, entryPrice + 4);
                      SetStopLoss(CalculationMode.Price, entryPrice - 2);
                  }
              }
      
              
          }
      }
      ​

      Comment


        #4
        Hello danieldunn2024,

        You can check the Position.MarketPosition is flat in the entry condition to prevent multiple entries when in a position. Note, when using Calculate.OnEachTick its possible for multiple orders to be submitted before the position changes, in which case we recommend assiging the entry order to a variable from OnOrderUpdate() and checking the order is null, filled, or cancelled before placing a new entry.

        With placing an order that can be modified manually, exit orders, such as ExitLongStopMarket() / ExitLongLimit(), with isLiveUntilCancelled as true can be used, or the unmanaged approach with SubmitOrderUnmanaged() can be used. The orders will be submitted once, and then not updated again from the script. This will allow manually modifying the orders without them reverting back to the strategy managed price.

        https://ninjatrader.com/support/foru...269#post802269
        https://ninjatrader.com/support/help...stopmarket.htm

        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          I use ATMStrategyCreate() to achieve this.

          Comment


            #6
            Hi, I am attempting to use this strategy. I compiled and used the example unchanged posted by Ninjatrader_RyanS and the profit targets are not triggering:

            SetProfitTarget("Profit target 1", CalculationMode.Price, entryPrice + 7);
            SetProfitTarget("Profit target 2", CalculationMode.Price, entryPrice + 15);​

            Is there a reason?

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by NullPointStrategies, Yesterday, 05:17 AM
            0 responses
            58 views
            0 likes
            Last Post NullPointStrategies  
            Started by argusthome, 03-08-2026, 10:06 AM
            0 responses
            133 views
            0 likes
            Last Post argusthome  
            Started by NabilKhattabi, 03-06-2026, 11:18 AM
            0 responses
            73 views
            0 likes
            Last Post NabilKhattabi  
            Started by Deep42, 03-06-2026, 12:28 AM
            0 responses
            45 views
            0 likes
            Last Post Deep42
            by Deep42
             
            Started by TheRealMorford, 03-05-2026, 06:15 PM
            0 responses
            50 views
            0 likes
            Last Post TheRealMorford  
            Working...
            X