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

interested in collaboration with other users to refine some code.

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

    interested in collaboration with other users to refine some code.





    users of nt,




    regards to all.


    i have been developing automated strategies for some time and have been able to develop some very solid algorithms. these are just two samples:


    Click image for larger version

Name:	20210801 m2k sample share nt fora 002.JPG
Views:	631
Size:	126.3 KB
ID:	1166009



    Click image for larger version

Name:	20210801 m2k sample share nt fora 003.JPG
Views:	546
Size:	128.2 KB
ID:	1166010



    i have been interested in adding a second position using onorderupdate and onexecutionupdate to my strategies to better manage risk but have not been able to accomplish this. i have asked for support from nt but have not made much progress towards this objective:


    people with nt, i have several trend following strategies that are very simple. in the case of a downtrend, the strategy will sell 1 contract short (of having it) and attach stop loss and breakeven stop orders to the position. this works well, the position will be held until it is stopped or until the downtrend condition



    i know that adding a position with minimal incremental risk would generate great results so it is code that i'm determined to make work. therefore, if any user is proficient coding with the onorderupdate and onexecutionupdate methods and can help me to create strategies which can manage two positions with stop loss orders in parallel i would offer to share advice regarding creating trend following strategies. please send a private message if interested.



    very well, thanks, regards.

    #2
    Hello rtwave,

    To confirm you are wanting to scale in contracts to an existing position, is this correct?
    Do you have EntriesPerDirection set to the number of entries you would like to allow in a direction?


    This thread will remain open for any community members that would like to build this script as a convenience to you.

    You can also contact a professional NinjaScript Consultant who would be eager to create or modify this script at your request or assist you with your script. The NinjaTrader Ecosystem has affiliate contacts who provide educational as well as consulting services. Please let me know if you would like our NinjaTrader Ecosystem team follow up with you with a list of affiliate consultants who would be happy to create this script or any others at your request or provide one on one educational services.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3




      people with nt,



      regards.



      i have developed multiple trend following strategies, i want to add a second position only if price is made to pull back to a certain extent. i have managed to make this work, however, i want to have stop loss orders active for every position and if multiple positions have been opened, i want the stop loss orders for all positions to be calculated and managed in parallel. that is what i have not been able to make work. when evaluating in backtests, the first position works very well, but when the strategy opens a second, concurrent position then it seems like the stop loss orders will not work anymore and the strategy will not close these larger positions when it should. and this defeats the purpose of opening an additional position only under certain conditions, if my strategies cannot manage risk efficiently over multiple positions, it would be better to just have one single position and increase the number of contracts to trade.


      in many backtests i run, there are much larger losing trades than the stop loss i use, which should definitely not happen. and the reply i receive from nt is the typical - you need to print and debug - which i think cannot be done with backtests.



      and yes, i know that nt keeps a directory of non affiliated individuals who could be knowledgeable about these matters. however, i have taken a look at that directory and it is not helpful, there are hundreds of companies in there and it is not easy to know who could be proficient with the methods that interest me or to have an approximate idea of the rates they charge. i still could have to resort to that option if there are no other alternatives, but it has not been my preferred choice.



      very well, i will continue to work on this code for multiple positions and report if i can make important breakthroughs. regards.
      Last edited by rtwave; 08-02-2021, 06:03 PM.

      Comment


        #4
        Hello rtwave,

        Do you have TraceOrders enabled and a print of the order object in OnOrderUpdate()?


        Are you seeing that the orders are being submitted and become working at the submitted prices?
        Are you seeing any ignored messages?
        May we have the output from the output window?

        Is this the managed or unmanaged approach?
        Do the entries have unique signal names?

        When you refer to additional positions are you referring to different instruments added with AddDataSeries?
        Or are you referring to a single position with multiple contracts?
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5



          this is the situation: i have known for a long time that numerous strategies i have developed are very solid because i have traded some of them automated on a crappy platform (tradestation).


          my single position strategies work fine, i decided to also program them in nt because, supposedly, i can add a second position, manage risk better, have much better restrictions on the trading hours and the results from nt's backtesting - optimizing engine are much more reliable and credible. therefore, all the evaluations i have been doing in nt are backtests, i am not executing the strategies automated or evaluating them in any other way. i work on different versions on the ninjascript editor and only test the results on the strategy analyzer. therefore, i don't have any logs or any traces from real time execution.


          - i think i'm using the unmanaged approach. the stop loss orders look like this (the entire strategy i'm working on can be found on the other thread i linked previously):


          Code:
          if (orshpoor != null && orshpoor == execution.Order)
          {
          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
          {
          // We sum the quantities of each execution making up the entry order
          sumFilled += execution.Quantity;
          
          // Submit exit orders for partial fills
          if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
          {
          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");
          
          }
          // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
          {
          // Stop-Loss order for OrderState.Filled
          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");
          
          }
          
          // Resets the orshpoor object and the sumFilled counter to null / 0 after the order has been filled
          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
          {
          orshpoor = null;
          sumFilled = 0;
          }
          }
          }
          
          if (pushpoor != null && pushpoor == execution.Order)
          {
          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
          {
          sumFilled += execution.Quantity;
          
          if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
          {
          pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
          }
          
          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
          {
          pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
          }
          
          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
          {
          pushpoor = null;
          sumFilled = 0;
          }
          }
          }

          - and all my strategies deal with one symbol only, by multiple positions i mean opening different positions in one same instrument.

          Comment


            #6
            Hello rtwave,

            There is only 1 position per instrument and account pair. If the position is flat and a buy order is placed the single position becomes Long 1. If another buy order is placed the single position will be Long 2. This is scaling into a position.
            If you place a sell order, the position becomes Long 1 again, scaling out.
            In other words, you would not be able to have two positions, such as a long position and a short position on the same instrument on the same account.

            Please see the forum post below that details this.


            If there are two instruments, these would be separate positions. One could be long, one could be short. If there are two accounts on the same instrument, each account will have its own position, one can be long, one can be short.

            A NinjaScript Strategy is able to add a secondary series using a different instrument. This will populate the Positions collection.
            Below is a link to the help guide on the Positions collection.

            From the help guide:
            "This property should only be used when your strategy is executing orders against multiple instruments."

            Multiple orders on the same instrument and same account do not make multiple positions. These will scale into and out of a single position.

            Entry and Exit methods are the managed approach. The manage approach has internal order handling rules.

            Below is a link to the help guide on the managed approach.

            ExitShortStopMarket

            And the internal order handling rules.


            The unmanaged approach uses SubmitOrderUnmanaged and does not have internal order handling rules.
            Below is a link to the help guide on the unmanaged approach.

            And SubmitOrderUnmanaged


            Also, below are links to examples with each approach.


            As well an example of scaling out.
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7



              this is the latest version of the very elementary strategy where i try to use onorderupdate and onexecutionupdate (which i have been recommended to do) to open a second position as i call it (or scale in) and have parallel stop loss orders for all positions at all times.



              [ATTACH]n1166442[/ATTACH]




              and these are the issues that i have been reporting:


              Click image for larger version

Name:	20210803 stops not working 0001.JPG
Views:	449
Size:	362.3 KB
ID:	1166443


              Click image for larger version

Name:	20210803 stops not working 0002.JPG
Views:	376
Size:	359.4 KB
ID:	1166444



              the biggest losing trades are highlighted in those screengrabs and it should be obvious that it makes no sense to have losing trades multiple times larger than the stop loss order for the ordinary position (70 usd plus slippage and commissions) and also for the pullback positions (30 usd plus slippage and commissions). the strategy has been optimized using the exit on session close setting, so these sizable losing trades cannot be attributed to prices being made to gap, this is simply the case that stop losses are not working at all.


              what i have in mind is:


              if downtrend

              open ordinary short position

              stop loss for ordinary short position at -200 ticks from average entry price for ordinary short position


              if pullback

              open pullback short position

              stop loss for ordinary short position at -60 ticks from new average entry price for both positions combined

              stop loss for pullback short position at -60 ticks from new average entry price for both positions combined


              if downtrend ends


              liquidate all short positions

              cancel all stop orders



              these are the issues i have been reporting and this is why i'm looking for assistance using those methods.

              Comment


                #8
                Hello rtwave,

                Ok, you would like to scale in to a single position and not have multiple positions on multiple instruments or accounts.

                I recommend you start with a simple script to understand first, and then add complexity from there.

                Below is a link to an example script that has multiple entries with unique signal names and scales out of the position using the from entry signal of the entries signal names with EntryHandling set to UniqueEntries or the EntriesPerDirection set to 2.



                If you feel the exit is filled at the wrong price, check the price submitted as the order stop price.

                Enable TraceOrders, print the order object in OnOrderUpdate(), and print the price supplied to the order along with the time of the bar.

                Below is a link to a forum post that demonstrates how to use prints to understand behavior.


                Save the output from the output window and please include this with your next post.
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9




                  this is the same strategy i shared previously, using only one single position and nt standard stop loss orders:


                  SetStopLoss(@"orsp01", CalculationMode.Ticks, Instlonuti, false);
                  SetStopLoss(@"orlp01", CalculationMode.Ticks, Instlonuti, false);


                  and these are the results. the biggest losing trade is 72 usd.


                  Click image for larger version

Name:	20210804 standard stops 0001.JPG
Views:	451
Size:	355.4 KB
ID:	1166479



                  these are the kind of results i want when using two positions (scaling in), i want a stop loss order for every position at all times to set a maximum monetary value that the strategy can lose on any one trade.



                  the standard stop loss orders work well, but it is self evident that this code that i want to use to set stop loss orders for every position is not working, as there are tens of trades in the optimizations i posted previously that lose several times over the value of the stop loss order.


                  protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
                  {
                  /* 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. */
                  if (orshpoor != null && orshpoor == execution.Order)
                  {
                  if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                  {
                  // We sum the quantities of each execution making up the entry order
                  sumFilled += execution.Quantity;

                  // Submit exit orders for partial fills
                  if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
                  {
                  orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");

                  }
                  // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
                  else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
                  {
                  // Stop-Loss order for OrderState.Filled
                  orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");

                  }

                  // Resets the orshpoor object and the sumFilled counter to null / 0 after the order has been filled
                  if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                  {
                  orshpoor = null;
                  sumFilled = 0;
                  }
                  }
                  }

                  if (pushpoor != null && pushpoor == execution.Order)
                  {
                  if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                  {
                  sumFilled += execution.Quantity;

                  if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
                  {
                  pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
                  orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
                  }

                  else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
                  {
                  pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
                  orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
                  }

                  if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                  {
                  pushpoor = null;
                  sumFilled = 0;
                  }
                  }
                  }




                  i have provided sample code and all the instructions to replicate these malfunctions i am reporting over the two threads i have created. nt has to execute the tests i have described on nt's strategy analyzer so that it could then be possible to provide an explanation of why these stop loss orders above do not trigger when they should, and propose a solution.


                  there should be no need for prints, when there are tens and tens of trades that lose several times over what the stop loss should be, it is self evident that the stop loss orders are not working.

                  Comment


                    #10
                    Hello rtwave,

                    If the order is SetStopLoss(@"orsp01", CalculationMode.Ticks, Instlonuti, false); and not the other orders then this will shown in the TraceOrders output. Also, print the order object in OnOrderUpdate() to see where this becomes working and filled.

                    Are you mixing set methods with exit methods? If so, orders are going to be ignored which will be shown in the TraceOrders output.


                    Attached is a simple script that demonstrates SetStopLoss works and a video of testing it.


                    If you are having an issue, reduce and debug using prints and TraceOrders to find the issue.

                    Which specific order is question?
                    Was the order submitted or ignored?
                    What was the price supplied to the order method or set method?
                    What price did that order becoming ordering at?
                    Was the order cancelled at any point or modified to a new price?
                    Did the price meet the order?
                    Attached Files
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11



                      i have been able to perform some more tests.


                      the problem is the second entry.


                      in this version, i disabled the second or pullback entries and then the onexecutionupdate orders worked as stop loss orders as they are supposed to. the largest losing trades all were closed by stop loss orders and all lose the same maximum amount.



                      Click image for larger version

Name:	20210804 single position does work 0001.JPG
Views:	395
Size:	356.1 KB
ID:	1166521


                      i enabled the second entries again, and once again stop loss orders do not work anymore.


                      Click image for larger version

Name:	20210804 stops not working improved values 0002.JPG
Views:	380
Size:	360.0 KB
ID:	1166522




                      Comment


                        #12

                        this is the first half of strategy i have posted multiple times in a zip file. stop loss orders fail to work if the second entry has been executed.


                        the screengrabs with very large losing trades correspond to optimizations on this strategy.


                        Code:
                        namespace NinjaTrader.NinjaScript.Strategies
                        {
                        public class OnOrderUpdatetests : Strategy
                        {
                        
                        private EMA EMA1;
                        private bool Utc = false;
                        private bool Dtc = false;
                        private Order orshpoor = null;
                        private Order orshpostor = null;
                        private Order pushpoor = null;
                        private Order pushpostor = null;
                        private Order orlopoor = null;
                        private Order orlopostor = null;
                        private Order pulopoor = null;
                        private Order pulopostor = null;
                        private int sumFilled = 0;
                        
                        protected override void OnStateChange()
                        {
                        if (State == State.SetDefaults)
                        {
                        Description = @"OnOrderUpdatetests";
                        Name = "OnOrderUpdatetests";
                        Calculate = Calculate.OnBarClose;
                        EntriesPerDirection = 1;
                        EntryHandling = EntryHandling.UniqueEntries;
                        IsExitOnSessionCloseStrategy = true;
                        ExitOnSessionCloseSeconds = 20;
                        IsFillLimitOnTouch = false;
                        MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
                        OrderFillResolution = OrderFillResolution.Standard;
                        Slippage = 4;
                        StartBehavior = StartBehavior.WaitUntilFlat;
                        TimeInForce = TimeInForce.Gtc;
                        TraceOrders = true;
                        RealtimeErrorHandling = RealtimeErrorHandling.StopCancelCloseIgnoreRejects ;
                        StopTargetHandling = StopTargetHandling.ByStrategyPosition;
                        BarsRequiredToTrade = 256;
                        
                        
                        Positionsize = 1;
                        Pullbackpositionsize = 1;
                        Emap = 255;
                        Instlonuti = 100;
                        Punuti = 60;
                        Costlonuti = 80;
                        
                        }
                        else if (State == State.Configure)
                        {
                        AddDataSeries(Data.BarsPeriodType.Minute, 1);
                        }
                        else if (State == State.DataLoaded)
                        {
                        EMA1 = EMA(Close, Convert.ToInt32(Emap));
                        }
                        else if (State == State.Realtime)
                        {
                        // one time only, as we transition from historical
                        // convert any old historical order object references
                        // to the new live order submitted to the real-time account
                        if (orshpoor != null)
                        orshpoor = GetRealtimeOrder(orshpoor);
                        if (orshpostor != null)
                        orshpostor = GetRealtimeOrder(orshpostor);
                        if (pushpoor != null)
                        pushpoor = GetRealtimeOrder(pushpoor);
                        if (pushpostor != null)
                        pushpostor = GetRealtimeOrder(pushpostor);
                        if (orlopoor != null)
                        orlopoor = GetRealtimeOrder(orlopoor);
                        if (orlopostor != null)
                        orlopostor = GetRealtimeOrder(orlopostor);
                        if (pulopoor != null)
                        pulopoor = GetRealtimeOrder(pulopoor);
                        if (pulopostor != null)
                        pulopostor = GetRealtimeOrder(pulopostor);
                        
                        }
                        }
                        
                        protected override void OnBarUpdate()
                        {
                        
                        if(BarsInProgress == 0)
                        {
                        
                        if (CurrentBars[0] < BarsRequiredToTrade)
                        return;
                        
                        // Set 1
                        if (Close[0] < EMA1[0])
                        {
                        Dtc = true;
                        Utc = false;
                        if (orshpoor == null)
                        {
                        EnterShort(Convert.ToInt32(Positionsize), @"orsp01");
                        }
                        }
                        
                        
                        // Set 2
                        if (Close[0] > EMA1[0])
                        {
                        Utc = true;
                        Dtc = false;
                        if (orlopoor == null)
                        {
                        EnterLong(Convert.ToInt32(Positionsize), @"orlp01");
                        }
                        }
                        
                        }
                        else if(BarsInProgress == 1)
                        {
                        
                        if ( Position.MarketPosition == MarketPosition.Long && High[0] >= Position.AveragePrice + (200 * TickSize ) )
                        {
                        // Checks to see if our Stop Order has been submitted already
                        if (orlopostor != null && orlopostor.StopPrice < Position.AveragePrice)
                        {
                        // Modifies stop-loss to breakeven
                        orlopostor = ExitLongStopMarket(0, true, orlopostor.Quantity, Position.AveragePrice, "orstorlp01", "orlp01");
                        }
                        }
                        else if ( Position.MarketPosition == MarketPosition.Short && Low[0] <= Position.AveragePrice - (200 * TickSize ) )
                        {
                        // Checks to see if our Stop Order has been submitted already
                        if (orshpostor != null && orshpostor.StopPrice > Position.AveragePrice)
                        {
                        // Modifies stop-loss to breakeven
                        orshpostor = ExitShortStopMarket(0, true, orshpostor.Quantity, Position.AveragePrice, "orstorsp01", "orsp01");
                        }
                        }
                        
                        
                        if ( Dtc == true && High[0] > ( Position.AveragePrice + ( Punuti * TickSize ) ) )
                        {
                        EnterShort(Convert.ToInt32(Pullbackpositionsize), @"pusp01");
                        }
                        
                        
                        if ( Utc == true && Low[0] > ( Position.AveragePrice - ( Punuti * TickSize ) ) )
                        {
                        EnterLong(Convert.ToInt32(Pullbackpositionsize), @"pulp01");
                        }
                        
                        }
                        }

                        Comment


                          #13


                          this is the second half of the strategy.


                          Code:
                          protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string nativeError)
                          {
                          // Handle entry orders here. The orshpoor object allows us to identify that the order that is calling the OnOrderUpdate() method is the entry order.
                          // Assign orshpoor in OnOrderUpdate() to ensure the assignment occurs when expected.
                          // This is more reliable than assigning Order objects in OnBarUpdate, as the assignment is not gauranteed to be complete if it is referenced immediately after submitting
                          if (order.Name == "orsp01")
                          {
                          orshpoor = order;
                          
                          // Reset the orshpoor object to null if order was cancelled without any fill
                          if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                          {
                          orshpoor = null;
                          sumFilled = 0;
                          }
                          }
                          else if (order.Name == "pusp01")
                          {
                          pushpoor = order;
                          
                          // Reset the orshpoor object to null if order was cancelled without any fill
                          if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                          {
                          pushpoor = null;
                          sumFilled = 0;
                          }
                          }
                          else if (order.Name == "orlp01")
                          {
                          orlopoor = order;
                          
                          // Reset the orshpoor object to null if order was cancelled without any fill
                          if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                          {
                          orlopoor = null;
                          sumFilled = 0;
                          }
                          }
                          else if (order.Name == "pulp01")
                          {
                          pulopoor = order;
                          
                          // Reset the orshpoor object to null if order was cancelled without any fill
                          if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                          {
                          pulopoor = null;
                          sumFilled = 0;
                          }
                          }
                          }
                          
                          protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
                          {
                          /* 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. */
                          if (orshpoor != null && orshpoor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                          {
                          // We sum the quantities of each execution making up the entry order
                          sumFilled += execution.Quantity;
                          
                          // Submit exit orders for partial fills
                          if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
                          {
                          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");
                          
                          }
                          // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
                          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
                          {
                          // Stop-Loss order for OrderState.Filled
                          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");
                          
                          }
                          
                          // Resets the orshpoor object and the sumFilled counter to null / 0 after the order has been filled
                          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                          {
                          orshpoor = null;
                          sumFilled = 0;
                          }
                          }
                          }
                          
                          if (pushpoor != null && pushpoor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                          {
                          sumFilled += execution.Quantity;
                          
                          if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
                          {
                          pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
                          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
                          }
                          
                          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
                          {
                          pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
                          orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
                          }
                          
                          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                          {
                          pushpoor = null;
                          sumFilled = 0;
                          }
                          }
                          }
                          
                          if (orlopoor != null && orlopoor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                          {
                          sumFilled += execution.Quantity;
                          
                          if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Long)
                          {
                          orlopostor = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ( Instlonuti * TickSize ), "orstorlp01", "orlp01");
                          }
                          
                          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Long)
                          {
                          orlopostor = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ( Instlonuti * TickSize ), "orstorlp01", "orlp01");
                          }
                          
                          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                          {
                          orlopoor = null;
                          sumFilled = 0;
                          }
                          }
                          }
                          
                          if (pulopoor != null && pulopoor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                          {
                          sumFilled += execution.Quantity;
                          
                          if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Long)
                          {
                          pulopostor = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ( Costlonuti * TickSize ), "pustpulp01", "pulp01");
                          orlopostor = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ( Costlonuti * TickSize ), "pustorlp01", "orlp01");
                          }
                          
                          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Long)
                          {
                          pulopostor = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ( Costlonuti * TickSize ), "pustpulp01", "pulp01");
                          orlopostor = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ( Costlonuti * TickSize ), "pustorlp01", "orlp01");
                          }
                          
                          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                          {
                          pulopoor = null;
                          sumFilled = 0;
                          }
                          }
                          }
                          
                          // Reset our stop order and target orders' Order objects after our position is closed. (1st Entry)
                          if (orshpostor != null && orshpostor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
                          {
                          orshpostor = null;
                          }
                          }
                          if (pushpostor != null && pushpostor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
                          {
                          pushpostor = null;
                          }
                          }
                          if (orlopostor != null && orlopostor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
                          {
                          orlopostor = null;
                          }
                          }
                          if (pulopostor != null && pulopostor == execution.Order)
                          {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
                          {
                          pulopostor = null;
                          }
                          }
                          
                          }
                          
                          
                          #region Properties
                          
                          [NinjaScriptProperty]
                          [Range(1, int.MaxValue)]
                          [Display(Name="Emap", Description="emap.", Order=1, GroupName="Parameters")]
                          public int Emap
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Range(int.MinValue, int.MaxValue)]
                          [Display(Name="Instlonuti", Description="instlonuti.", Order=2, GroupName="Parameters")]
                          public int Instlonuti
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Range(int.MinValue, int.MaxValue)]
                          [Display(Name="Punuti", Description="punuti.", Order=3, GroupName="Parameters")]
                          public int Punuti
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Range(int.MinValue, int.MaxValue)]
                          [Display(Name="Costlonuti", Description="costlonuti.", Order=4, GroupName="Parameters")]
                          public int Costlonuti
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Range(int.MinValue, int.MaxValue)]
                          [Display(Name="Positionsize", Description="positionsize.", Order=5, GroupName="Parameters")]
                          public int Positionsize
                          { get; set; }
                          
                          [NinjaScriptProperty]
                          [Range(int.MinValue, int.MaxValue)]
                          [Display(Name="Pullbackpositionsize", Description="pullbackpositionsize.", Order=6, GroupName="Parameters")]
                          public int Pullbackpositionsize
                          { get; set; }
                          
                          #endregion
                          
                          }
                          }

                          Comment


                            #14


                            i created another version with "set" orders, everything is identical, i just added "set" orders and commented out everything inside the barsinprogress, onorderupdate and onexecutionupdate sections.


                            this version works without issue. i posted one screengrab where the largest losing trades are all 72 usd.


                            Code:
                            namespace NinjaTrader.NinjaScript.Strategies
                            {
                            public class OnOrderUpdatetestsstandardstops : Strategy
                            {
                            
                            private EMA EMA1;
                            private bool Utc = false;
                            private bool Dtc = false;
                            private Order orshpoor = null;
                            private Order orshpostor = null;
                            private Order pushpoor = null;
                            private Order pushpostor = null;
                            private Order orlopoor = null;
                            private Order orlopostor = null;
                            private Order pulopoor = null;
                            private Order pulopostor = null;
                            private int sumFilled = 0;
                            
                            protected override void OnStateChange()
                            {
                            if (State == State.SetDefaults)
                            {
                            Description = @"OnOrderUpdatetestsstandardstops";
                            Name = "OnOrderUpdatetestsstandardstops";
                            Calculate = Calculate.OnBarClose;
                            EntriesPerDirection = 1;
                            EntryHandling = EntryHandling.UniqueEntries;
                            IsExitOnSessionCloseStrategy = true;
                            ExitOnSessionCloseSeconds = 20;
                            IsFillLimitOnTouch = false;
                            MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
                            OrderFillResolution = OrderFillResolution.Standard;
                            Slippage = 4;
                            StartBehavior = StartBehavior.WaitUntilFlat;
                            TimeInForce = TimeInForce.Gtc;
                            TraceOrders = true;
                            RealtimeErrorHandling = RealtimeErrorHandling.StopCancelCloseIgnoreRejects ;
                            StopTargetHandling = StopTargetHandling.ByStrategyPosition;
                            BarsRequiredToTrade = 256;
                            
                            
                            Positionsize = 1;
                            Pullbackpositionsize = 1;
                            Emap = 255;
                            Instlonuti = 100;
                            Punuti = 60;
                            Costlonuti = 80;
                            
                            }
                            else if (State == State.Configure)
                            {
                            AddDataSeries(Data.BarsPeriodType.Minute, 1);
                            }
                            else if (State == State.DataLoaded)
                            {
                            EMA1 = EMA(Close, Convert.ToInt32(Emap));
                            SetStopLoss(@"orsp01", CalculationMode.Ticks, Instlonuti, false);
                            SetStopLoss(@"orlp01", CalculationMode.Ticks, Instlonuti, false);
                            
                            }
                            else if (State == State.Realtime)
                            {
                            // one time only, as we transition from historical
                            // convert any old historical order object references
                            // to the new live order submitted to the real-time account
                            if (orshpoor != null)
                            orshpoor = GetRealtimeOrder(orshpoor);
                            if (orshpostor != null)
                            orshpostor = GetRealtimeOrder(orshpostor);
                            if (pushpoor != null)
                            pushpoor = GetRealtimeOrder(pushpoor);
                            if (pushpostor != null)
                            pushpostor = GetRealtimeOrder(pushpostor);
                            if (orlopoor != null)
                            orlopoor = GetRealtimeOrder(orlopoor);
                            if (orlopostor != null)
                            orlopostor = GetRealtimeOrder(orlopostor);
                            if (pulopoor != null)
                            pulopoor = GetRealtimeOrder(pulopoor);
                            if (pulopostor != null)
                            pulopostor = GetRealtimeOrder(pulopostor);
                            
                            }
                            }
                            
                            protected override void OnBarUpdate()
                            {
                            
                            if(BarsInProgress == 0)
                            {
                            
                            if (CurrentBars[0] < BarsRequiredToTrade)
                            return;
                            
                            // Set 1
                            if (Close[0] < EMA1[0])
                            {
                            Dtc = true;
                            Utc = false;
                            
                            EnterShort(Convert.ToInt32(Positionsize), @"orsp01");
                            
                            }
                            
                            
                            // Set 2
                            if (Close[0] > EMA1[0])
                            {
                            Utc = true;
                            Dtc = false;
                            
                            EnterLong(Convert.ToInt32(Positionsize), @"orlp01");
                            
                            }

                            Comment


                              #15



                              and finally, i created a version identical to the OnOrderUpdatetests strategy i have shared as zip and as text. the only difference is that i commented out the second entries:



                              if ( Dtc == true && High[0] > ( Position.AveragePrice + ( Punuti * TickSize ) ) )
                              {
                              // EnterShort(Convert.ToInt32(Pullbackpositionsize), @"pusp01");
                              }


                              if ( Utc == true && Low[0] > ( Position.AveragePrice - ( Punuti * TickSize ) ) )
                              {
                              // EnterLong(Convert.ToInt32(Pullbackpositionsize), @"pulp01");
                              }



                              the stop loss orders in this strategy do work as intended, the screengrab with largest losing trades of 102 usd corresponds to this version.


                              therefore, it is the second entries that cause the stop loss orders to not work anymore and which lead to losing trades several times larger than they should be.



                              i have taken a look at all the resources that have been linked but nothing deals with scaling in - adding positions to a strategy and then managing multiple positions as one with stop loss orders in parallel.


                              i have never used prints or traces and i have no idea of how to do that, what i want is to have stop loss orders with every position in my strategies so that losses are capped and this does not happen in the strategies with two entries. i will now take a look at the directory of programmers to see if i can pay to have someone help me fix this issue.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by CortexZenUSA, Today, 12:53 AM
                              0 responses
                              1 view
                              0 likes
                              Last Post CortexZenUSA  
                              Started by CortexZenUSA, Today, 12:46 AM
                              0 responses
                              1 view
                              0 likes
                              Last Post CortexZenUSA  
                              Started by usazencortex, Today, 12:43 AM
                              0 responses
                              5 views
                              0 likes
                              Last Post usazencortex  
                              Started by sidlercom80, 10-28-2023, 08:49 AM
                              168 responses
                              2,266 views
                              0 likes
                              Last Post sidlercom80  
                              Started by Barry Milan, Yesterday, 10:35 PM
                              3 responses
                              13 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Working...
                              X