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

Adding Tick Data Series Not Working on Strategy

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

    Adding Tick Data Series Not Working on Strategy

    Hello,

    I have a relatively simply strategy that I would to backtest.

    I want to place orders conditionally upon the primary data series, which is NQ 12-18 3000 tick bars.
    I want my trailing stop orders to be called on the secondary data series, which is NQ 12-18 1 tick data.

    This, if I understand correctly, will add intraday granularity so that my trail stop is updated on each tick of the 3000 tick bars, essentially giving me close to real time results, similar to playback connection replay.

    The code is running smoothly. Although, for some reason, the trail stops are clearly not accurate, and are still waiting until the next bar opens to trigger, rather than triggered within the tick data of each bar.

    I have CalculateSetOnEachTick = true
    I have added both data series.
    And I called the position orders based on the corresponding data series.

    I don't understand why my orders are not showing results based on tick data.

    I'll post the code below, please let me know if Im missing something silly, or if what I am trying to achieve is not possible.

    namespace NinjaTrader.NinjaScript.Strategies

    {

    public class SMARTT : Strategy

    {

    private double V;

    private double R;

    private bool FirstTime;

    private bool setBE;

    private double stopLevel;









    protected override void OnStateChange()

    {

    if (State == State.SetDefaults)

    {

    Description = @"Start";

    Name = "SMARTT";

    Calculate = Calculate.OnEachTick;

    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;

    V = 1;

    R = 1;

    FirstTime = true;

    setBE =false;

    stopLevel =1;

    }

    else if (State == State.Configure)

    {

    AddDataSeries("NQ 12-18", Data.BarsPeriodType.Tick, 3000, Data.MarketDataType.Last);

    AddDataSeries("NQ 12-18", Data.BarsPeriodType.Tick, 1, Data.MarketDataType.Last);







    }

    else if (State == State.DataLoaded);

    }








    protected override void OnBarUpdate()

    {

    if (Position.MarketPosition == MarketPosition.Flat)

    {

    setBE = false;

    FirstTime = true;

    }



    {

    if (BarsInProgress == 0)

    {





    }



    if (CurrentBars[0] < 2)

    return;



    // Set 3

    if (((R - (Low[0])) > (2.3 * (V - R)) )

    && ((R - (Low[0])) > (2.7 * (High[0] - (V))))

    && ((High[0] - (Low[0])) > 2.5)

    && (Low[0] < Low[1])

    && (Low[0] < Low[2])

    && (Low[0] < Low[3])

    && (Low[0] < Low[4])

    && (Low[0] < Low[5]))



    {

    EnterLong(Convert.ToInt32(1), @"LONG");



    }




    // Set 4

    if (((High[0] - (V)) > (2.3 * (V - R)))

    && ((High[0] - (V)) > (2.7 * (R - (Low[0]))))

    && ((High[0] - (Low[0])) > 2.5)

    && (High[0] > High[1])

    && (High[0] > High[2])

    && (High[0] > High[3])

    && (High[0] > High[4])

    && (High[0] > High[5]))

    {

    EnterShort(Convert.ToInt32(1), @"SHORT");



    }







    if (BarsInProgress == 1)




    if (Positions[0].MarketPosition == MarketPosition.Long)



    {

    if (FirstTime)

    {

    Print (Times[0][0]+" FirstTime"+" Init stop at: "+(Positions[0].AveragePrice - 4 * TickSize).ToString());

    ExitLongStopMarket(0, true, 1, Positions[0].AveragePrice - 4 * TickSize, "","LONG");

    FirstTime = false;

    }




    if (!FirstTime && !setBE)

    {

    if (Closes[0][0] >= Positions[0].AveragePrice + 4 * TickSize);

    {

    Print (Times[0][0]+ " set BE");

    ExitLongStopMarket(0, true, 1, Positions[0].AveragePrice, "","LONG");

    setBE = true;

    stopLevel = Positions[0].AveragePrice;

    }

    }

    if (!FirstTime && setBE)

    {

    if (Closes[0][0] > stopLevel + .25 * TickSize)

    {

    Print (Times[0][0] + " adjusting stop to: "+ stopLevel);

    stopLevel = stopLevel + .25 * TickSize; // increment 5 to 1

    ExitLongStopMarket(0, true, 1, stopLevel, "","LONG");

    }

    }

    }




    if (Positions[0].MarketPosition == MarketPosition.Short)

    {

    if (FirstTime)

    {

    Print (Times[0][0]+" FirstTime"+" Init stop at: "+(Positions[0].AveragePrice + 4 * TickSize).ToString());

    ExitShortStopMarket(0, true, 1, Positions[0].AveragePrice + 4 * TickSize, "","SHORT");

    FirstTime = false;

    }




    if (!FirstTime && !setBE)

    {

    if (Closes[0][0] <= Positions[0].AveragePrice - 4 * TickSize);

    {

    Print (Times[0][0]+ " set BE");

    ExitShortStopMarket(0, true, 1, Positions[0].AveragePrice, "","SHORT");

    setBE = true;

    stopLevel = Positions[0].AveragePrice;

    }

    }

    if (!FirstTime && setBE)

    {

    if (Closes[0][0] < stopLevel - .25 * TickSize)

    {

    Print (Times[0][0] + " adjusting stop to: "+ stopLevel);

    stopLevel = stopLevel - .25 * TickSize; // increment 5 to 1

    ExitShortStopMarket(0, true, 1, stopLevel, "","SHORT");

    }

    }

    }

    }

    }

    }}

    #2
    To sum up my question.. I want to call the primary data series, 3000 tick data, to enter a long or short position.

    Then I want to call the secondary tick data to exit my positions using a custom stop loss.

    Am I missing some sort of input, I feel like its a silly error that I cannot seem to catch.

    Comment


      #3
      Hello murraym324,

      Thank you for your note.

      In the following two samples which are multi series strategies, you'll see how logic is within (BarsInProgress == 1) or if (BarsInProgress == 0), which restricts that logic so its only analyzed by that bar series. In your case you would want to put your entry logic in BIP==1, for the 3000 tick series, and put your stop logic within BIP2 for your tick series. I see your set 3 and set 4 are not contained within a BIp.

      I suggest seeing the following examples, moving code blocks within BIP if statements.



      You can submit orders to different Bars objects. This allows you the flexibility of submitting orders to different timeframes. Like in live trading, taking entry conditions from a 5min chart means executing your order as soon as possible instead of waiting until the next 5min bar starts building. You can achieve this by


      I’ve provided a link to a youtube video which covers an example of using prints to understand behavior:
      Dive into manipulating C# code from within an unlocked NinjaScript strategy using the NinjaScript Editor.NinjaTrader 7 is an award winning end to end online ...


      I’ve provided a link covering debugging which you may find helpful.
      Debugging: http://ninjatrader.com/support/forum...ead.php?t=3418

      Please let us know if you need further assistance.
      Alan P.NinjaTrader Customer Service

      Comment


        #4
        I understand your point. To be clear, there is only 1 additional data series to this strategy. The primary series, which is selected in strategy analyzer, is NQ 3000 tick data.. The secondary data is NQ 1 tick bars.

        If Im not mistaken, this would only warrant BarsInProgress == 0 for the primary logic, entry.
        and BarsInProgress == 1 for the secondary logic, the trail stop exit.

        I have reviewed the debugging tutorials and made adjustments to the code. However, the trail stops still do not seem to be working on the tick data.

        For example, when I run the strategy and view the chart, there are exits happening BEFORE any constraints have been met.

        In the code, (I added captions), you can see that my initial stop is placed at 20 ticks below position entry price. This logic is within BarsInProgress == 1.
        You can also see the first adjustment to that stop is only made once 25 ticks of profit has been reached, therefore moving the stop to 2 ticks above entry price.

        So why am I seeing entries and exits within a single bar that does not reach 20 ticks loss or 25 ticks profit?


        namespace NinjaTrader.NinjaScript.Strategies

        {

        public class T : Strategy

        {

        private double V;

        private double R;

        private bool firstTime;

        private bool setBE;

        private double stopLevel;







        protected override void OnStateChange()

        {

        if (State == State.SetDefaults)

        {

        Description = @"Start";

        Name = "T";

        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;

        BarsRequiredToTrade = 20;

        // Disable this property for performance gains in Strategy Analyzer optimizations

        // See the Help Guide for additional information

        IsInstantiatedOnEachOptimizationIteration = true;

        V = 1;

        R = 1;

        firstTime = true;

        setBE =false;

        stopLevel =1;

        }

        if (State == State.Configure)

        {

        AddDataSeries("NQ 12-18", Data.BarsPeriodType.Tick, 1);

        }

        }




        protected override void OnBarUpdate()

        {



        if (Positions[0].MarketPosition == MarketPosition.Flat) //Reset control bool variables when flat



        {

        firstTime = true;

        setBE =false;

        }



        if (BarsInProgress == 0)

        {






        // Set 1

        if (Close[0] < Open[0])

        {

        V = Open[0];

        R = Close[0];

        }




        // Set 2

        if (Close[0] >= Open[0])

        {

        V = Close[0];

        R = Open[0];

        }




        // Set 3

        if (((R - (Low[0])) > (2.3 * (V - R)))

        && ((R - (Low[0])) > (2.7 * (High[0] - (V))))

        && ((High[0] - (Low[0])) > 2.5)

        && (Low[0] < Low[1])

        && (Low[0] < Low[2])

        && (Low[0] < Low[3])

        && (Low[0] < Low[4])

        && (Low[0] < Low[5]))



        {

        EnterLong(0,1, @"LONG");



        }

        }





        if (BarsInProgress == 1)



        {



        if (Positions[0].MarketPosition == MarketPosition.Long)



        if (firstTime)

        {

        Print (Times[0][0]+" firstTime"+" Init stop at: "+(Positions[0].AveragePrice - 20 * TickSize).ToString());

        ExitLongStopMarket(1, true, 1, Positions[0].AveragePrice - 20 * TickSize, "","LONG"); //Set inital stop

        firstTime = false;

        }




        if (!firstTime && !setBE)

        {

        if (Closes[1][0] >= Positions[0].AveragePrice + 25 * TickSize);

        {

        Print (Times[0][0]+ " set BE");

        ExitLongStopMarket(1, true, 1, Positions[0].AveragePrice + 2 * TickSize, "","LONG"); // Set stop to breakeven + 2 ticks after 25 ticks profit

        setBE = true;

        stopLevel = Positions[0].AveragePrice + 2 * TickSize;

        }

        }



        if (!firstTime && setBE)

        {

        if (Closes[1][0] > stopLevel + 5 * TickSize)

        {

        Print (Times[0][0] + " adjusting stop to: "+stopLevel);

        stopLevel = stopLevel + 4 * TickSize; // Trail increment 5 to 4 until close position

        ExitLongStopMarket(1, true, 1, stopLevel, "","LONG");

        }}}
        }}}
        Last edited by murraym324; 11-06-2018, 08:29 AM.

        Comment


          #5
          Hello murraym324,

          The first script you shared had 3 data series, the one in which you pass via the strategy analyzer, being BIP=0, then the following two BIP1, BIP2,

          Code:
          AddDataSeries("NQ 12-18", Data.BarsPeriodType.Tick, 3000, Data.MarketDataType.Last);
          AddDataSeries("NQ 12-18", Data.BarsPeriodType.Tick, 1, Data.MarketDataType.Last);
          In the new version you’ve uploaded, could you please add prints to the script and if you’re still having difficultly, please leave the prints in the script and upload it using the following format,

          To export a NinjaScript from NinjaTrader 8 do the following:
          From the Control Center window select Tools -> Export -> NinjaScript...
          Click Add>Select the indicator>OK>Export.
          Then attach that file you saved; under My Docs>NT8>Bin>Custom>Select the downloaded .zip file.

          I look forward to your reply.
          Alan P.NinjaTrader Customer Service

          Comment


            #6
            Sure, here is the file.
            Attached Files

            Comment


              #7
              This one, sorry.
              Attached Files

              Comment


                #8
                Hello murraym324,

                Both these if statements are going to refer to the last close of the primary bar series, which depending on what market, could be a while ago.
                Code:
                [B]if (Closes[0][0] > stopLevel + 5 * TickSize)+
                if (Closes[0][0] >= Positions[0].AveragePrice + 10 * TickSize);[/B]
                If you use Closes[1][0] to refer to the current bar of the tick series, do you get the behavior you desire?

                I have also attached a strategy sample which updates the trailing stop in OnMarketData.

                I look forward to your reply.
                Attached Files
                Alan P.NinjaTrader Customer Service

                Comment


                  #9
                  Hi,

                  Thanks for the reply.

                  Unfortunately that solution does not solve the error. I have made adjustments and attached the latest script. If you run this in strategy analyzer you will see the largest losing trade is $60.
                  It doesn't make sense because my initial stop is set at 20 ticks below entry, which is $100 on NQ futures.

                  Aside from that, the average time in market I am seeing is -0.83. Im not sure how this can be negative. Even on the chart it shows certain exits before entries.
                  Attached Files

                  Comment


                    #10
                    Hello murraym324,

                    I ran your strategy in the strategy analyzer and see the largest losing trade to be $35 over the period of the last month.

                    On the day of this loss you're seeing, I suggest you analyze if the larger looser was related to holding a position into the close and seeing a gap open or a big spike on data. I suggest going to the trades tab, the executions tab, and digging into the occurrence you're seeing. I would also confirm the trade didn't take place around roll, or prior to dec being the top step.

                    Please let us know if you need further assistance.

                    Attached Files
                    Alan P.NinjaTrader Customer Service

                    Comment


                      #11
                      I understand.. I am not saying the largest loser is too large, but rather the opposite. My initial stop is set 20 ticks below entry. 20 ticks on the NQ is $100.

                      So how can my largest loser be less than $100?

                      Additionally, the average time in market is a negative number, meaning my exits are happening before entry?

                      Comment


                        #12
                        Hello,

                        I made some changes to your strategy and attached the file.

                        Since you are using NQ for both the primary and secondary series, you should submit your orders to the most granular series, ie the 1 tick series. See note 3 Entering,Exiting and Retrieving Position information.



                        I changed Positions[0] to Position because the instrument is the same on both series.

                        How does the attached script perform relative to your expectations?

                        Attached Files
                        Alan P.NinjaTrader Customer Service

                        Comment


                          #13
                          Thank you for the reply.

                          I have actually already tried submitting the first entry order to the secondary series, but produced no different results.

                          I ran your script, using NQ 3000 tick data, testing from 10/1 to 10/29. The largest losing trade is now $3,705. Checking the chart and seeing no gaps or session close for that trade. It is also the only losing trade. 93 winners and 1 loser.

                          After reviewing your script, I see you switched the order exit conditions, placing if (firstTime) below if (!firstTime and setBE).

                          Assuming this was an unintentional error, I switched them back. And the strategy now produces similar results to before. Showing my exits before entries. Largest losing trade at $20. Same things that didn't make sense before.

                          Could it be that I am not properly resetting the bools firstTime and setBE after each trade?

                          I attached the script you sent with the order under if (BarsInProgress == 1) switched back, (firstTime) on top. Everything else was left the same.

                          The maximum loser should be around $100. Average loser should be around $100. This is because my initial stop is set 20 ticks below entry, which is $100 on NQ futures.

                          The first time my stop is adjusted is after 25 ticks profit, in which case my stop would be moved to entry price plus 2 ticks. This is all labeled in the script.
                          Based on the logic I just explained, the only losing trades will be around $100. because if my profit target is hit, 25 ticks, the stop will be moved to a slight profit.

                          I hope this makes sense.



                          ​​​​​​​
                          Attached Files

                          Comment


                            #14
                            Hello murraym324,

                            When you make a EnterLong call, that order needs to be sent to the exchange/broker, filled, and returned or if a sim order needs to be sent to the fill algorithm filled and returned. When your first bool is read, its true, but your exitlong call is ignored because ninjatrader does not know its in a position yet, which is why I switched the operation order.

                            I am unable to get your results.

                            When you go to the trades tab and investigate this 3705 loss, have you compared entry price to exit price to the chart to determine what the issue is?

                            I look forward to your reply.
                            Alan P.NinjaTrader Customer Service

                            Comment


                              #15
                              Are you saying I would need to change the override to OnOrderUpdate?

                              Meaning something like

                              protected override void OnOrderUpdate(Cbi.Order order, double limitPrice, double stopPrice,
                              int quantity, int filled, double averageFillPrice,
                              Cbi.OrderState orderState, DateTime time, Cbi.ErrorCode error, string comment)

                              To be clear, and since I do not really understand your point:

                              1. I have a simple strategy testing 3000 tick bars on NQ futures.
                              2. If a bar closes meeting my conditions, I will enter long 1 contract.
                              3. My initial stop is placed 20 ticks below entry price.
                              4. My first target is at 25 ticks above entry price, in which case my stop will be moved up to 2 ticks above entry price, ensuring a small profit.
                              5. After 25 ticks above entry, every 5 ticks higher will result in my stop moving up 4 ticks.

                              The exitlongstopmarket orders will be updated on each tick of the secondary series, essentially mimicking a live trailing stop that updates every tick.

                              Im not sure what Im doing wrong, but I would think since Im submitting the EnterLong(1,1,"LONG"), that would be enough to register a long position during backtest.

                              I do not have a live account currently with NinjaTrader, so when you mention submitting an order to a broker Im a bit confused.

                              The chart shows my entires as desired, so there is no problem getting the order filled. The exits are not processing correctly.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by frankthearm, Today, 09:08 AM
                              8 responses
                              32 views
                              0 likes
                              Last Post frankthearm  
                              Started by NRITV, Today, 01:15 PM
                              2 responses
                              9 views
                              0 likes
                              Last Post NRITV
                              by NRITV
                               
                              Started by maybeimnotrader, Yesterday, 05:46 PM
                              5 responses
                              26 views
                              0 likes
                              Last Post NinjaTrader_ChelseaB  
                              Started by quantismo, Yesterday, 05:13 PM
                              2 responses
                              20 views
                              0 likes
                              Last Post quantismo  
                              Started by adeelshahzad, Today, 03:54 AM
                              5 responses
                              33 views
                              0 likes
                              Last Post NinjaTrader_BrandonH  
                              Working...
                              X