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

EnterLongLimit delays EnterLong by a bar?

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

    EnterLongLimit delays EnterLong by a bar?

    Below is some simple code I am testing to understand the behavior of EnterLongLimit and EnterShortLimit in conjunction with EnterLong and EnterShort.

    In the example, the RSI is used to determine an entry and exit. If the RSI is over 70 say, then I enter a short a certain number of ticks above the market for the next bar. However, if I don't get filled, I want to EnterShort (at the market) on the next bar. What appears to be happening, is that the EnterShortLimit is delaying the market entry by an extra bar.

    Could someone offer some guidance? For instance, I can run on example data, and see the following in output.

    Click image for larger version

Name:	SS #1.png
Views:	275
Size:	10.0 KB
ID:	1130819

    When I comment out the EnterShortLimit line of the code, then the entry is a bar earlier, as expected. It's as if the EnterShortLimit is delaying the entry by a bar, even though that code is not evaluated on Bar#63 as shown in the example output above? Please advise. Thanks.

    Click image for larger version

Name:	SS #2.png
Views:	193
Size:	9.5 KB
ID:	1130820




    Code:
    #region Using declarations
    using NinjaTrader.Cbi;
    using NinjaTrader.NinjaScript.Indicators;
    using System;
    #endregion
    
    //This namespace holds Strategies in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Strategies.MyStrategies
    {
    public class RSITest : Strategy
    {
    private RSI RSI1;
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"Enter the description for your new custom Strategy here.";
    Name = "RSITest";
    Calculate = Calculate.OnBarClose;
    EntriesPerDirection = 1;
    EntryHandling = EntryHandling.AllEntries;
    IsExitOnSessionCloseStrategy = true;
    ExitOnSessionCloseSeconds = 30;
    IsFillLimitOnTouch = false;
    MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
    OrderFillResolution = OrderFillResolution.Standard;
    Slippage = 0;
    StartBehavior = StartBehavior.WaitUntilFlat;
    TimeInForce = TimeInForce.Gtc;
    TraceOrders = false;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
    StopTargetHandling = StopTargetHandling.PerEntryExecution;
    BarsRequiredToTrade = 20;
    // 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)
    {
    RSI1 = RSI(Close, 14, 3);
    AddChartIndicator(RSI1);
    }
    }
    
    protected override void OnBarUpdate()
    {
    if (BarsInProgress != 0)
    return;
    
    if (CurrentBars[0] < 1)
    return;
    
    // Set 1
    Print(Position.MarketPosition.ToString());
    
    if (RSI1.Avg[0] > 70 && RSI1.Avg[1] < 70)
    {
    // EnterShort(Convert.ToInt32(DefaultQuantity), "");
    Print("TOP, bar#: " + CurrentBar.ToString());
    Print("RSI Values: 0: " + RSI1.Avg[0].ToString() + " 1: " + RSI1.Avg[1].ToString() + " 2: " + RSI1.Avg[2].ToString());
    
    EnterShortLimit(0, false, 1, GetCurrentBid() + (1000060 * TickSize), "S");
    }
    if (RSI1.Avg[1] > 70)
    {
    Print("BOTTOM, bar#: " + CurrentBar.ToString());
    Print("RSI Values: 0: " + RSI1.Avg[0].ToString() + " 1: " + RSI1.Avg[1].ToString() + " 2: " + RSI1.Avg[2].ToString());
    EnterShort("S");
    }
    
    
    // Set 2
    if (RSI1.Avg[0] < 30)
    {
    // EnterLong(Convert.ToInt32(DefaultQuantity), "");
    EnterLongLimit(0, false, Convert.ToInt32(DefaultQuantity), GetCurrentBid() - (40 * TickSize), "");
    }
    
    }
    }
    }

    #2
    Hello mohawkTrader, thanks for writing in.

    It looks like there is a delay because the EnterShortLimit order has not yet canceled. In the managed approach, if you have an existing entry order and call another entry method in the same direction, the second entry order will be ignored.

    https://ninjatrader.com/support/help...antedPositions

    Methods that generate orders to enter a position will be ignored if:
    ...
    The entry signal name is not unique


    You will need to change this to save the entry order and cancel it at the next bar "manually". My example here works:

    Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.


    Please let me know if I can provide any more information.



    Chris L.NinjaTrader Customer Service

    Comment


      #3
      Thanks Chris,

      I still am having some issues though. First, if the {bool isLiveUntilCancelled} flag is set to false, the order should be cancelled at the conclusion of the next bar. So I'm just trying to verify that is the cause of the delay. This could be by design to prevent an overfill situation so it waits for an extra bar to confirm the cancel (on last bar close) went through.

      Related to this, in the code that you sent, is there an overfill condition in which both the commands would be filled. Both RSIEntry = EnterShortLimit and the EnterShort command. Or does the CancelOrder, confirm the cancel first? For example, if the CancelOrder command is sent, and a fill is coming back at the same time the EnterShort order is sent to the exchange (which would also be filled), there would be an overfill condition (filled on both orders). I'm wondering if this is possible, both with Ninja as brokerage, and then if it's different with the outside broker connections (IB as an example). The CancelOrder documentation doesn't seem to offer guidance on this question.

      Also, if and when RSIEntry is filled, should I reset RSIEntry to null, or do I need to maintain the order for future use? This could be complicated in the event of partial fills as well.

      Thanks for your guidance. Still trying to wrap my head around the best way to do this. Basically, I want to try to get a better price for one bar using the Limit order methods, and if I don't get a fill, to just take the market on the next bar. If you have another suggestion for a way to better achieve this functionality, please advise.

      Comment


        #4
        Hello mohawkTrader, thanks for your reply.

        If the order is required to be canceled on a condition we should keep IsLiveUntilCanceled = true to keep things 100% in the programmer's control. There is no overfill protection when using CancelOrder. The script would need to override OnOrderUpdate and look for the OrderState.Canceled to come back, then submit the other short entry to 100% ensure the order is canceled before submitting the market order entry. We have a full example of using CancelOrder here:



        Canceling the order, setting it to null, and submitting the market order in OnBarUpdate is sufficient if the market order just needs to be submitted after the order is canceled on the next bar, not necessarily at the exact moment it gets canceled.

        In the example I posted, the only cancelation requirement I followed was the fact that the order needs to be canceled if it has not filled within the bar it was submitted on, if that is the case (CurrentBar > OrderBar) then cancel the order and submit the market order. The order object should only be set to null when the order is in a terminal state (canceled, filled, rejected). The OnOrderUpdate method can be used to check how much of an order filled as well. The OrderState will be PartFilled and the "Filled" property will be the number of contracts that were filled.

        The best way of testing this and fine tuning the behavior will be using the Playback connection to find a bar where the strategy submits the limit order. Once you find that you can pause and replay the data so it submits the order, then you can test what happens on the subsequent bars. If it does not work the way you expected, make changes to the script and test the same data again.

        Please let me know if I can provide any further information.
        Chris L.NinjaTrader Customer Service

        Comment


          #5
          Thanks for pointing me to the example.

          A couple things: I noticed that there is a scenario, where a market order is entered right at the close, so it is immediately cancelled, so I catch that and set mar****rder back to null.

          There seems to be another scenario, where the stop order is immediately cancelled (but not because of market time). When would a ExitShortStopMarket be immediately cancelled? It's not that it is ignored, as I see the stop in the OnOrderUpdate method go from Submitted, Accepted, Working, but then immediately continues to CancelPending, CancelSubmitted, Cancelled.

          I looked at this in the guide, but didn't see any scenario, and the other known from testing is the outside of market hours condition mentioned above.


          Thanks.

          Comment


            #6
            Hello mohawkTrader, thanks for your reply.

            For the limit order that is canceling immediately, is the CancelOrder method being called in the same OnBarUpdate call as the limit order? It sounds like it's hitting EnterShortStopMarket() then immediately after that is submitted its hitting CancelOrder(). This can be found using Print statements after every line in OnBarUpdate:
            https://ninjatrader.com/support/help...nt8/?print.htm

            Kind regards,
            -ChrisL
            Chris L.NinjaTrader Customer Service

            Comment


              #7
              Hi, I do not call CancelOrder() for the stop order, so that's not the case. I also checked for an error coming back from the OnOrderUpdate for the stop that was cancelled: it's showing no error throughout the life.

              Attached is the code, it appears that it happens after the next OnBarUpdate call.

              Attached Files

              Comment


                #8
                Thanks for your help. Here's some sample logs from this particular run. Note, that sometimes the stop does work as expected, so this behavior is not consistent.


                OOU entry: Entry = null
                OOU start: orderId='NT-00857-38757' account='Backtest' name='stop' orderState=Working instrument='NQ 12-20' orderAction=BuyToCover orderType='Stop Market' limitPrice=0 stopPrice=12510 quantity=0 tif=Gtc oco='' filled=0 averageFillPrice=0 onBehalfOf='' id=-1 time='2020-12-04 00:10:00' gtd='2099-12-01' statementDate='2020-12-09'
                NoError

                OOU entry: Entry = null
                EUP end: orderId='NT-00856-38757' account='Backtest' name='market entry' orderState=Filled instrument='NQ 12-20' orderAction=SellShort orderType='Market' limitPrice=0 stopPrice=0 quantity=1 tif=Gtc oco='' filled=1 averageFillPrice=12505 onBehalfOf='' id=-1 time='2020-12-04 00:10:00' gtd='2099-12-01' statementDate='2020-12-09'
                12505
                CB: 31757 MP: Short // this is the next OnBarUpdateCall
                // Now the stop is cancelled, but can't figure out why it's getting the cancel call

                OOU start: orderId='NT-00857-38757' account='Backtest' name='stop' orderState=CancelPending instrument='NQ 12-20' orderAction=BuyToCover orderType='Stop Market' limitPrice=0 stopPrice=12510 quantity=0 tif=Gtc oco='' filled=0 averageFillPrice=0 onBehalfOf='' id=-1 time='2020-12-04 00:10:00' gtd='2099-12-01' statementDate='2020-12-09'
                NoError

                OOU entry: Entry = null
                OOU start: orderId='NT-00857-38757' account='Backtest' name='stop' orderState=CancelSubmitted instrument='NQ 12-20' orderAction=BuyToCover orderType='Stop Market' limitPrice=0 stopPrice=12510 quantity=0 tif=Gtc oco='' filled=0 averageFillPrice=0 onBehalfOf='' id=-1 time='2020-12-04 00:10:00' gtd='2099-12-01' statementDate='2020-12-09'
                NoError

                Comment


                  #9
                  Hello mohawkTrader, thanks for your reply.

                  The ExitLong/ShortStopMarket orders do not use IsLiveUntilCanceled, so if they are not resubmitted each bar they will be canceled. Try using this override instead:

                  Code:
                  ExitLongStopMarket(int barsInProgressIndex, bool isLiveUntilCancelled, int quantity, double stopPrice, string signalName, string fromEntrySignal)
                  Please let me know if I can assist any further.
                  Chris L.NinjaTrader Customer Service

                  Comment


                    #10
                    Thanks. That should explain it.

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by bortz, 11-06-2023, 08:04 AM
                    47 responses
                    1,606 views
                    0 likes
                    Last Post aligator  
                    Started by jaybedreamin, Today, 05:56 PM
                    0 responses
                    8 views
                    0 likes
                    Last Post jaybedreamin  
                    Started by DJ888, 04-16-2024, 06:09 PM
                    6 responses
                    18 views
                    0 likes
                    Last Post DJ888
                    by DJ888
                     
                    Started by Jon17, Today, 04:33 PM
                    0 responses
                    4 views
                    0 likes
                    Last Post Jon17
                    by Jon17
                     
                    Started by Javierw.ok, Today, 04:12 PM
                    0 responses
                    13 views
                    0 likes
                    Last Post Javierw.ok  
                    Working...
                    X