Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Strategy with multiple entry signals and orders?

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

    Strategy with multiple entry signals and orders?

    Hello,

    I have currently created a strategy which has:
    • 2 different longs signal
    • 2 different shorts signal
    For each one of the 4 signals I have created a specific identifier tag, so to have specific profit and stops target, and then set the option entry handling equal to Unique Entries.

    I am testing the strategy in playback and for one of my long signal, the strategy works as expected, but for the other long signal as soon as the strategy enter the position it closes it istantaneusly, without placing the stop and target orders.

    So my question is do you have some sort of example templates where there is a strategy that handles multiple entry signals, so that I can learn from it?

    thank you very much

    David





    #2
    Hi David,
    I had that same problem. https://youtu.be/r_E68M30hgg watch how TradeSaber fixes that issue. Go to about 3:30 in the video It worked for me. Hope this helps
    Matt

    Comment


      #3
      Hello Matt,

      Thank you for your message and for the help. Unfortunately, I am looking for another thing.
      I am able to set Profit and Stops, but those are only working for my first entry signal long. When the other condition to go long turns true, NinjaExecutes the order, but then it closes it out immediately without placing the stop and target orders.

      Comment


        #4
        Sorry man. I found the routine doesn't do anything but prevent multiple errant orders and it doesn't really effect anything. I just misunderstood your question. I really know just enough to be dangerous at this point in my strategy builder knowledge. Good luck sir

        Comment


          #5
          Hello NorwegianCat92,

          Print the order.ToString() in OnOrderUpdate() to see which order is closing the position.

          Below is a link to a support article on adding debugging prints to understand behavior.


          Save the output text file and attach this to your next post.
          Chelsea B.NinjaTrader Customer Service

          Comment


            #6
            Hello Chelsea,

            I hope you are well. Thank you very much for the help. The strategy that I was testing was buying when price crossed above a FastEMA and then buying when price crossed above SlowEMA.
            For each of these scenario there should have been an individual Profit and Stop for each entry.

            I was able to solve my issue and now the profit and target orders are placed independently for the strategy, but I wanted to clarify if the behaviour that I observed with the prints was correct.

            What I have done was:

            Set State Default:

            Entry Handling = Unique Entries.
            Stop and Target Submission = Per Entry Execution.


            Then within protected override void OnExecutionUpdate:


            if (execution.Order.Name == CrossAboveSlowEMA
            && _currentPosition == CurrentPos.Long)
            {
            FilledPriceSlowEMA = execution.Price;​ (This variable was created to store the execution price to then determine from it SL and PT).

            (Here I changed the variable to execution.Price from execution.Order.AverageFillPrice. Please can you clarify if this is correct, because my assumption was that if I was already in another position, Ninja would add the new filled order and store the variable as the average of the two, while I want the specific fill of the entry based on the SlowEMA.)

            if (execution.Order.Name == CrossAboveFastEMA
            && _currentPosition == CurrentPos.Long)
            {
            FilledPriceFastEMA = execution.Price;​

            Now I tested the strategy in Playback and I observed these two instances (attached) and I would like to ask you if it is fine.

            In the first photo at about 8:44 Candle the strategy enters as expected as both conditions happen to be true, and then it gets stopped out. In the Print section however does not print the value of the orders for the FastEMA even if they have been submitted. Same for the second photo.
            The orders were submitted correctly, they just did not print. Otherwise, in all the other tests of the strategy Ninja Output windows always prints the values correctly. Is this ok?

            Thank you very much and sorry for the long post Click image for larger version

Name:	NinjaForum1.png
Views:	187
Size:	149.3 KB
ID:	1319350 Click image for larger version

Name:	NinjaForum2.png
Views:	166
Size:	125.5 KB
ID:	1319351

            Comment


              #7
              Hello NorwegianCat92,

              This would likely indicate an issue with the print code or order of operations.

              Chelsea B.NinjaTrader Customer Service

              Comment


                #8
                Hello Chelsea,

                Thanks for the reply. Sorry I did not understand, does it mean that the issue might be in the Print Code? But why does it work then in the vast majority of the time?
                What does it mean order of operation?

                Sorry if my questions might not make sense, but I am just trying to understand.
                Thank you

                Comment


                  #9
                  Hello NorwegianCat92,

                  Unfortunately, the code that produces that output was not included with your post, so I wouldn't be able to say specifically.

                  But if there is no value appearing, either the print is not including the value, or the value is coming from a variable that is holding an empty string.

                  Order of operations means the sequence that events are happening in.

                  For example, you may call EnterLong() and this submits an entry order.
                  However, it takes time for the object to be constructed and for the order to be submitted, received, accepted, become accepted, and then filled, and for the order to update.
                  This means if you call EnterLong() and immediately try and use a value

                  So, it depends on what is in the code, and if there are variables being printed, when those variables were assigned values.
                  Chelsea B.NinjaTrader Customer Service

                  Comment


                    #10
                    Hello Chelsea,

                    Thank you for your reply and availability.

                    I am going to post the code, so maybe you can check:

                    Thanks for your help.


                    Code:
                    public class UnderstandingMultiPositions : Strategy
                    {
                    
                    private EMA FastEMA;
                    private EMA SlowEMA;
                    private ATR DavideATR;
                    
                    private string CrossAboveFastEMA = "CrossAboveFastEMA";
                    private string CrossAboveSlowEMA = "CrossAboveSlowEMA";
                    private string TargetFastEMA = "Target Fast EMA";
                    private string StopFastEMA = "Stop Loss Fast EMA";
                    private string TargetSlowEMA = "Target Slow EMA";
                    private string StopSlowEMA = "Stop Loss Slow EMA";
                    
                    private CurrentPos _currentPosition;
                    
                    public enum CurrentPos
                    {
                    Long,
                    Short,
                    None
                    }
                    
                    protected override void OnStateChange()
                    {
                    if (State == State.SetDefaults)
                    {
                    Description = @"Enter the description for your new custom Strategy here.";
                    Name = "UnderstandingMultiPositions";
                    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.ByStrategyPosition;
                    // Disable this property for performance gains in Strategy Analyzer optimizations
                    // See the Help Guide for additional information
                    IsInstantiatedOnEachOptimizationIteration = true;
                    }
                    else if (State == State.Configure)
                    {
                    }
                    else if (State == State.DataLoaded)
                    {
                    FastEMA = EMA(8);
                    SlowEMA = EMA(20);
                    DavideATR = ATR(10);
                    
                    }
                    }
                    
                    protected override void OnBarUpdate()
                    {
                    if (State != State.Realtime) //Only trades realtime. Ignores historical trades.
                    {
                    return;
                    }
                    
                    if (BarsInProgress != 0)
                    return;
                    
                    if (CurrentBars[0] < 20)
                    return;
                    
                    
                    SetEntrySignal1();
                    Trade1();
                    SetEntrySignal2();
                    Trade2();
                    
                    }
                    
                    private void Trade2()
                    {
                    if (_LongEntry2)
                    EnterLong(1, CrossAboveSlowEMA);
                    }
                    
                    private bool _LongEntry2;
                    private void SetEntrySignal2()
                    {
                    _LongEntry2 = Close[0] > SlowEMA[0];
                    _LongEntry2 &= Low[0] < SlowEMA[0];
                    if (_LongEntry2)
                    BackBrush = Brushes.Red;
                    }
                    
                    
                    private void Trade1()
                    {
                    if (_LongEntry1)
                    EnterLong(1, CrossAboveFastEMA);
                    }
                    
                    private bool _LongEntry1;
                    private void SetEntrySignal1()
                    {
                    _LongEntry1 = Close[0] > FastEMA[0];
                    _LongEntry1 &= Low[0] < FastEMA[0];
                    if (_LongEntry1)
                    BackBrush = Brushes.Teal;
                    }
                    
                    protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
                    {
                    if (EntryOrderFastFilled(execution))
                    {
                    IdentifyDirectionFastEMA(execution);
                    SetStopProfitFastEMA(execution);
                    }
                    if (EntryOrderSlowFilled (execution))
                    {
                    IdentifyDirectionSlowEMA(execution);
                    SetStopProfitSlowEMA(execution);
                    }
                    
                    
                    }
                    
                    private Order ProfitOrderSlowEMA;
                    private Order StopOrderSlowEMA;
                    
                    private double _stopSlowEMA;
                    private double _profitSlowEMA;
                    private double FilledPriceSlowEMA;
                    
                    
                    private void SetStopProfitSlowEMA(Execution execution)
                    {
                    
                    if (execution.Order.Name == CrossAboveSlowEMA
                    && _currentPosition == CurrentPos.Long)
                    {
                    FilledPriceSlowEMA = execution.Price;
                    Print("------------------------------------");
                    Print("Filled Price SLOW EMA :" + FilledPriceSlowEMA);
                    _stopSlowEMA = FilledPriceSlowEMA - DavideATR[0];
                    Print("Stop SLOW EMA :" + _stopSlowEMA);
                    _profitSlowEMA = FilledPriceSlowEMA + DavideATR[0] * 2;
                    Print("Profit SLOW EMA : " + _profitSlowEMA);
                    
                    ProfitOrderSlowEMA = ExitLongLimit(0, true, 1, _profitSlowEMA, TargetSlowEMA, CrossAboveSlowEMA);
                    Print("Profit Order SLOW EMA set at: " + ProfitOrderSlowEMA);
                    StopOrderSlowEMA = ExitLongStopMarket(0, true, 1, _stopSlowEMA, StopSlowEMA, CrossAboveSlowEMA);
                    Print("Stop Order SLOW EMA set at: " + StopOrderSlowEMA);
                    Print("-------------------------------------");
                    }
                    else
                    {
                    
                    
                    }
                    
                    
                    
                    }
                    
                    private void IdentifyDirectionSlowEMA(Execution execution)
                    {
                    if (execution.Order.Name == CrossAboveSlowEMA)
                    _currentPosition = CurrentPos.Long;
                    }
                    
                    private bool EntryOrderSlowFilled(Execution execution)
                    {
                    return execution.Order.OrderState == OrderState.Filled && IsEntryOrder2(execution.Order.Name);
                    
                    }
                    
                    private bool IsEntryOrder2(string name)
                    {
                    return name == CrossAboveSlowEMA;
                    }
                    
                    private Order ProfitOrderFastEMA;
                    private Order StopOrderFastEMA;
                    
                    private double _stopFastEMA;
                    private double _profitFastEMA;
                    private double FilledPriceFastEMA;
                    
                    
                    private void SetStopProfitFastEMA(Execution execution)
                    {
                    
                    if(execution.Order.Name == CrossAboveFastEMA
                    && _currentPosition == CurrentPos.Long)
                    {
                    FilledPriceFastEMA = execution.Price;
                    Print("----------------------------------------------");
                    Print("Filled Price FAST EMA :" + FilledPriceFastEMA);
                    _stopFastEMA = FilledPriceFastEMA - DavideATR[0];
                    Print(" Stop FAST EMA: " + _stopFastEMA);
                    _profitFastEMA = FilledPriceFastEMA + DavideATR[0] * 2;
                    Print("Target FAST EMA: " + _profitFastEMA);
                    
                    ProfitOrderFastEMA = ExitLongLimit(0, true, 1, _profitFastEMA, TargetFastEMA, CrossAboveFastEMA);
                    Print("Profit Order FAST EMA :" + ProfitOrderSlowEMA);
                    StopOrderFastEMA = ExitLongStopMarket(0, true, 1, _stopFastEMA, StopFastEMA, CrossAboveFastEMA);
                    Print("Stop Order FAST EMA :" + StopOrderSlowEMA);
                    Print("---------------------------------------------");
                    
                    }
                    else
                    {
                    
                    
                    }
                    
                    
                    }
                    
                    private void IdentifyDirectionFastEMA(Execution execution)
                    {
                    if (execution.Order.Name == CrossAboveFastEMA)
                    _currentPosition = CurrentPos.Long;
                    }
                    
                    private bool EntryOrderFastFilled(Execution execution)
                    {
                    return execution.Order.OrderState == OrderState.Filled && IsEntryOrder1(execution.Order.Name);
                    }
                    
                    private bool IsEntryOrder1(string name)
                    {
                    return name == CrossAboveFastEMA;
                    }
                    
                    }​

                    Comment


                      #11
                      Hello NorwegianCat92,

                      StopOrderSlowEMA is an order variable and appears to be assigned directly from an order method call, which is advised against in the help guide for this reason.

                      "OnOrderUpdate() will run inside of order methods such as EnterLong() or SubmitOrderUnmanaged(), therefore attempting to assign an order object outside of OnOrderUpdate() may not return as soon as expected. If your strategy is dependent on tracking the order object from the very first update, you should try to match your order objects by the order.Name (signal name) from during the OnOrderUpdate() as the order is first updated."


                      Orders must be assigned to variables from the order object parameter of OnOrderUpdate().

                      The help guide provides sample code.

                      The order variable is likely an empty object as the order doesn't exist yet by the time the next line of code is executed. It takes time for the order to be constructed (initialized), submitted, accepted, become working, and then become filled. Further, it takes time for communication through internet (when sending live orders).

                      The order will update OnOrderUpdate() as it changes states throughout time.

                      I would recommend you assign the order to the variable and print information about the order from OnOrderUpdate() after the order.OrderState is OrderState.Working or OrderState.Accepted.
                      Chelsea B.NinjaTrader Customer Service

                      Comment


                        #12
                        Hello Chelsea,

                        Thank you very much for the explanation. I will follow your guidelines.

                        Thank you

                        Comment

                        Latest Posts

                        Collapse

                        Topics Statistics Last Post
                        Started by argusthome, 03-08-2026, 10:06 AM
                        0 responses
                        110 views
                        0 likes
                        Last Post argusthome  
                        Started by NabilKhattabi, 03-06-2026, 11:18 AM
                        0 responses
                        59 views
                        0 likes
                        Last Post NabilKhattabi  
                        Started by Deep42, 03-06-2026, 12:28 AM
                        0 responses
                        37 views
                        0 likes
                        Last Post Deep42
                        by Deep42
                         
                        Started by TheRealMorford, 03-05-2026, 06:15 PM
                        0 responses
                        41 views
                        0 likes
                        Last Post TheRealMorford  
                        Started by Mindset, 02-28-2026, 06:16 AM
                        0 responses
                        78 views
                        0 likes
                        Last Post Mindset
                        by Mindset
                         
                        Working...
                        X