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

How to set stop loss below low of signal bar within an ATM strategy?

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

    How to set stop loss below low of signal bar within an ATM strategy?

    Hi, I notice in the sample ATM strategy, there's code to change the ATM stop price. How can I modify this to change the stop to, say, 4 ticks below the low of the signal bar or lowest low of the two bars prior to the signal bar, whichever is lower. Here's the existing code in the sample ATM strategy. Couldn't find any answers from searching the forum. Appreciate any help.


    if (atmStrategyId.Length > 0)
    {
    if (GetAtmStrategyMarketPosition(atmStrategyId) != MarketPosition.Flat)
    AtmStrategyChangeStopTarget(0, Low[0] - 3 * TickSize, "STOP1", atmStrategyId);

    }




    #2
    Hello mkt_anomalies,

    Thanks for your long time member 1st post on the forums!

    In your code that determines the signal bar, you would save the value of Low[0] - 4 * TickSize into a double type variable (that you previously create) at that time. If you wanted to use the lowest of 3 bars including the signal bar then you could use the MIN() method like this MIN(Low, 3)[0]; // provide the lowest low of last 3 bars.

    Reference: https://ninjatrader.com/support/help...inimum_min.htm

    Once your order has filled and the ATM is active you can change the ATMs default stop with the AtmStrategyChangeStopTarget().

    In this line: AtmStrategyChangeStopTarget(0, Low[0] - 3 * TickSize, "STOP1", atmStrategyId);, you would replace Low[0] - 3 * TickSize with the name of the double variable.

    Paul H.NinjaTrader Customer Service

    Comment


      #3
      Thank you. I followed your guidance by creating a double type variable named "stopPrice" and inserted the line "stopPrice = MIN(Low, 3)[0];" in the part of the strategy that also submits the entry order. That works.

      I then added a second condition to set the stop price to MIN(Low, 3)[0] only if unrealized profit is less than 20 ticks and to shift the stop price to Position.AveragePrice (i.e. breakeven) if unrealized profit is equal to or greater than 20 ticks. This kinda works in testing... I see the stop price shift up from the the entry bar's recent low to breakeven after a 20 tick gain, but then the stop seems to shift back down again to the entry bar low on the next bar. Any ideas what might be causing this and how it can be fixed?


      if (atmStrategyId.Length > 0)
      {
      if (GetAtmStrategyMarketPosition(atmStrategyId) != MarketPosition.Flat)
      {
      if (Position.GetUnrealizedProfitLoss(PerformanceUnit. Ticks, Close[0]) < 20)
      AtmStrategyChangeStopTarget(0, stopPrice, "STOP1", atmStrategyId);
      else if (Position.GetUnrealizedProfitLoss(PerformanceUnit. Ticks, Close[0]) >= 20)
      AtmStrategyChangeStopTarget(0, Position.AveragePrice, "STOP1", atmStrategyId);
      }
      }



      Comment


        #4
        Hello mkt_anomalies,

        Thanks for your reply.

        You would need to create a bool variable (a bool is either true of false) that you can use to control when stop is moved to breakeven so that the previous stop level is no longer applied.

        For example, assume you create a bool called BEbool and it is initially set to false.

        if (Position.GetUnrealizedProfitLoss(PerformanceUnit. Ticks, Close[0]) < 20 && BEbool == false)
        {
        AtmStrategyChangeStopTarget(0, stopPrice, "STOP1", atmStrategyId);
        }
        else if (Position.GetUnrealizedProfitLoss(PerformanceUnit. Ticks, Close[0]) >= 20 && BEBool == false)
        {
        AtmStrategyChangeStopTarget(0, Position.AveragePrice, "STOP1", atmStrategyId);
        BEBool = true; // set bool to true here so that stop is not changed anymore
        }


        The first time through the bool is false and the stop is placed according to the bool stopPrice. When it is 20 ticks in profit, the BE stop is placed and the bool is now set to true and that prevents the stop from being moved again

        Note: You would need to reset the bool back to false when the trade is over. Probably the best place to do that would be where you have your entry actions as you need it set to false for the next order.

        Paul H.NinjaTrader Customer Service

        Comment


          #5
          Thanks Paul. I've gone about it slightly differently from the way you suggested. I created a bool to make sure the strategy only adjusts the stop once after the position is opened, and then I configured the ATM strategy to move the stop to breakeven after price moves 8 ticks in favour of the trade. The problem now is that if the ATM strategy is configured to enter 3 contracts, each with different profit targets, the strategy will only adjust the stop for first of the three contracts, leaving the other two stops at the level set by the ATM strategy.

          What needs to change in the code to get the strategy to adjust the stops for the entire position? I've pasted the code for the strategy below, which simply enters long when buys price crosses an SMA.

          The ATM strategy is configured to enter 3 contracts, with 8 tick, 16 tick, and 40 tick profit targets and 25 tick initial stop. For the second and third contracts, the stops are configured to rise to breakeven after an 8 tick gain (when the first target is hit) .




          Code:
          namespace NinjaTrader.NinjaScript.Strategies
          {
              public class anATM : Strategy
              {
                  private SMA SMA1;
                  private string  atmStrategyId            = string.Empty;
                  private string  orderId                    = string.Empty;
                  private bool    isAtmStrategyCreated    = false;
                  double stopPrice                        = 0;
                  bool breakevenStatus                            = false;
          
                  protected override void OnStateChange()
                  {
                      if (State == State.SetDefaults)
                      {
                          Description                                    = @"ATM strategy";
                          Name                                        = "anATM";
                          Calculate                                    = Calculate.OnBarClose;
                          EntriesPerDirection                            = 1;
                          EntryHandling                                = EntryHandling.UniqueEntries;
                          IsExitOnSessionCloseStrategy                = true;
                          ExitOnSessionCloseSeconds                    = 300;
                          IsFillLimitOnTouch                            = false;
                          MaximumBarsLookBack                            = MaximumBarsLookBack.TwoHundredFiftySix;
                          OrderFillResolution                            = OrderFillResolution.Standard;
                          Slippage                                    = 0;
                          StartBehavior                                = StartBehavior.WaitUntilFlat;
                          TimeInForce                                    = TimeInForce.Gtc;
                          TraceOrders                                    = false;
                          RealtimeErrorHandling                        = RealtimeErrorHandling.StopCancelClose;
                          StopTargetHandling                            = StopTargetHandling.ByStrategyPosition;
                          BarsRequiredToTrade                            = 20;
                          // Disable this property for performance gains in Strategy Analyzer optimizations
                          // See the Help Guide for additional information
                          IsInstantiatedOnEachOptimizationIteration    = false;
                          SMAperiod                                    = 10;
                      }
                      else if (State == State.Configure)
                      {
                      }
                      else if (State == State.DataLoaded)
                      {                
                          SMA1                = SMA(Close, Convert.ToInt32(SMAperiod));
                          SMA1.Plots[0].Brush = Brushes.DodgerBlue;
                          AddChartIndicator(SMA1);    
                      }
                  }
          
                  protected override void OnBarUpdate()
                  {
          
                      if (BarsInProgress != 0) 
                          return;
          
                      if (CurrentBar < BarsRequiredToTrade)
                          return;
          
                      //if (GetAtmStrategyMarketPosition(atmStrategyId) == MarketPosition.Flat)
          
          
                      // HELP DOCUMENTATION REFERENCE: Please see the Help Guide section "Using ATM Strategies" under NinjaScript--> Educational Resources--> http://ninjatrader.com/support/helpGuides/nt8/en-us/using_atm_strategies.htm
          
                      // Make sure this strategy does not execute against historical data
                      if(State == State.Historical)
                          return;
          
                      // Submits an entry limit order at the current low price to initiate an ATM Strategy if both order id and strategy id are in a reset state
                      // **** YOU MUST HAVE AN ATM STRATEGY TEMPLATE NAMED 'AtmStrategyTemplate' CREATED IN NINJATRADER (SUPERDOM FOR EXAMPLE) FOR THIS TO WORK ****
                      if (orderId.Length == 0 && atmStrategyId.Length == 0 
                          && (CrossBelow(SMA1, Close, 1))
                         )
                      {
          
                          isAtmStrategyCreated = false;  // reset atm strategy created check to false
                          stopPrice = MIN(Low, 3)[0]; // provide the lowest low of last 3 bars.
                          atmStrategyId = GetAtmStrategyUniqueId();
                          orderId = GetAtmStrategyUniqueId();
                          AtmStrategyCreate(OrderAction.Buy, OrderType.Market, 0, 0, TimeInForce.Day, orderId, "AtmStrategyTemplate", atmStrategyId, (atmCallbackErrorCode, atmCallBackId) => {
                          //check that the atm strategy create did not result in error, and that the requested atm strategy matches the id in callback
                          if (atmCallbackErrorCode == ErrorCode.NoError && atmCallBackId == atmStrategyId)
                              isAtmStrategyCreated = true;
                          });
                      }
          
          
          
                      // Check that atm strategy was created before checking other properties
                      if (!isAtmStrategyCreated)
                          return;
          
                      // Check for a pending entry order
                      if (orderId.Length > 0)
                      {
                          string[] status = GetAtmStrategyEntryOrderStatus(orderId);
          
                          // If the status call can't find the order specified, the return array length will be zero otherwise it will hold elements
                          if (status.GetLength(0) > 0)
                          {
                              // Print out some information about the order to the output window
                              Print("The entry order average fill price is: " + status[0]);
                              Print("The entry order filled amount is: " + status[1]);
                              Print("The entry order order state is: " + status[2]);
          
                              // If the order state is terminal, reset the order id value
                              if (status[2] == "Filled" || status[2] == "Cancelled" || status[2] == "Rejected")
                                  orderId = string.Empty;
                          }
                      } // If the strategy has terminated reset the strategy id
                      else if (atmStrategyId.Length > 0 && GetAtmStrategyMarketPosition(atmStrategyId) == Cbi.MarketPosition.Flat)
                          atmStrategyId = string.Empty;
          
                      if (atmStrategyId.Length > 0)
                      {
                          // You can change the stop price
                          if (GetAtmStrategyMarketPosition(atmStrategyId) != MarketPosition.Flat)
                          {
                              if (breakevenStatus == false)
                              {
                                  AtmStrategyChangeStopTarget(0, stopPrice, "STOP1", atmStrategyId);
                                  breakevenStatus = true; 
                              }
          
                          }
          
                          // Print some information about the strategy to the output window, please note you access the ATM strategy specific position object here
                          // the ATM would run self contained and would not have an impact on your NinjaScript strategy position and PnL
                          Print("The current ATM Strategy market position is: " + GetAtmStrategyMarketPosition(atmStrategyId));
                          Print("The current ATM Strategy position quantity is: " + GetAtmStrategyPositionQuantity(atmStrategyId));
                          Print("The current ATM Strategy average price is: " + GetAtmStrategyPositionAveragePrice(atmStrategyId));
                          Print("The current ATM Strategy Unrealized PnL is: " + GetAtmStrategyUnrealizedProfitLoss(atmStrategyId));
                      }
                  }
          
                  #region Properties
          
                  [NinjaScriptProperty]
                  [Range(1, int.MaxValue)]
                  [Display(Name="SMAperiod", Order=0, GroupName="Parameters")]
                  public int SMAperiod
                  { get; set; }
          
                  #endregion
              }
          }

          Comment


            #6
            Hello mkt_anomalies,

            Thanks for your reply.

            When you run your strategy and the entry order is filled with 3 contracts, check the "Orders tab". I suspect you will see 3 stops labeled Stop1, Stop2, and Stop3.
            If so, this would suggest that you will need to have 3 AtmStrategyChangeStopTarget(, each named for its unique stop name.

            For example:
            AtmStrategyChangeStopTarget(0, stopPrice, "Stop1", atmStrategyId);
            AtmStrategyChangeStopTarget(0, stopPrice, "Stop2", atmStrategyId);
            AtmStrategyChangeStopTarget(0, stopPrice, "Stop3", atmStrategyId);

            Paul H.NinjaTrader Customer Service

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by PaulMohn, Today, 03:49 AM
            0 responses
            6 views
            0 likes
            Last Post PaulMohn  
            Started by inanazsocial, Today, 01:15 AM
            1 response
            8 views
            0 likes
            Last Post NinjaTrader_Jason  
            Started by rocketman7, Today, 02:12 AM
            0 responses
            10 views
            0 likes
            Last Post rocketman7  
            Started by dustydbayer, Today, 01:59 AM
            0 responses
            4 views
            0 likes
            Last Post dustydbayer  
            Started by trilliantrader, 04-18-2024, 08:16 AM
            5 responses
            23 views
            0 likes
            Last Post trilliantrader  
            Working...
            X