Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Updating Custom Indicator on Multi Timeframe Strategy

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

    Updating Custom Indicator on Multi Timeframe Strategy

    Hi Traders,
    I have some specific questions and didn't find the answers in the documentation and also not in the forum.

    I would be really thankful if somebody could give me some advice.

    My goal is to develop a multi timeframe strategy with several indicators which provide data for each timeframe so I can use these informations for entry decissions.

    My Indicator
    I delevoped a complex market trend indicator which scans for trends and saves seperatly informations to up and down trends in two sorted dictionaries. So for every bar I have a lot of information about the current up and down trend. The indicator works well when used on a chart.

    My Strategy
    I want to trade one instrument and use my indicator on different timeframes. I want to trade on a low minute timeframe intraday. My exit logic is fast and needs tick level.

    Settings
    • Primary Series: 1 Tick
    • several Secondary Series (1 Min, 5 Min, 10 Min, ...)
      • Initializing the Indicators each with a BarsArray overload
    • Calculate.OnEachTick
    Questions & Problems

    1.
    I experienced, that I don*t have update the indicators manually with

    if (BarsInProgress == Index10Min)
    {
    MarketTrendIndicator.Update();
    }​

    because it seems, that NinjaTrader is automatically updating the indicators when initialized it with an overload with BarsArray?

    When I update manually, then I get weird data in the logs, looks like the indicator is updated multiple times on one bar object.

    2.
    When I let the indicator run automatically and then place some actions depending on timeframe it seems that the events are not synchronized.

    if (BarsInProgress == Index10Min)
    {
    // for example log MarketTrendData or look for signals
    }​
    The object is always null. But when I look into the logs I see, that all the BarsInProgress ruled actions are done before the indicators runs. Looks like a sequence, first OnBarUpdate until finished and then the indicators until finished or maybe async?


    What is the bestpractice for such a usecase? My actions are based on the information from the indicator, so I need more control over the update of the indicator.

    Thanks for your help!




    #2
    Hello AlgoLuke,

    The update method is only utilized when you need to update an indicator that does not have a plot. If your indicator has a plot, you only need to call the plot in OnBarUpdate to update it.

    Regarding your second question, I am not entirely sure what you attempted to determine the cause of your result. I would need to see an example of how you were printing and what conditions you had for the bars in progress conditions.​

    Comment


      #3
      Hi Jesse,
      thx for the fast reply.

      My indicator has no plot. I integrated some manual drawing methods for testing purpose only. But in a multi timeframe strategy on tick level I only see the tick level in the strategy analyzer. Because of that I didn't focus on visuals. Is there a better way to test multi timeframe strategys in the strategy analyser?

      However, maybe I can explain the indicator and wanted workflow better. I have my own logging method. I shortend the code to focus on the relevant parts:

      // I use several parameters to activate certain timeframes and a dictionary for all the indicators running

      else if (State == State.Configure)
      {
      timeframeDataDict = new Dictionary<int, TimeframeData>();

      AddDataSeries(BarsPeriodType.Minute, 1); // Index 1
      AddDataSeries(BarsPeriodType.Minute, 5); // Index 2
      AddDataSeries(BarsPeriodType.Minute, 10); // Index 3
      AddDataSeries(BarsPeriodType.Minute, 30); // Index 4
      AddDataSeries(BarsPeriodType.Minute, 60); // Index 5
      AddDataSeries(BarsPeriodType.Minute, 120); // Index 6
      AddDataSeries(BarsPeriodType.Minute, 240); // Index 7
      AddDataSeries(BarsPeriodType.Minute, 480); // Index 8
      AddDataSeries(BarsPeriodType.Day, 1); // Index 9
      }

      else if (State == State.DataLoaded)
      {
      InitializeTimeframeIndicators();
      }
      ...

      // for every active timeframe an indicator is initialized in a dictionary

      private void InitializeTimeframeIndicators()
      {
      // Initialisieren der Indikatoren für jeden aktiven Timeframe
      foreach (var tfData in timeframeDataDict.Values)
      {
      // Indikator initialisieren und zuweisen
      tfData.MarketTrendIndicator = MarketTrendIndicator(
      BarsArray[tfData.BarsInProgressIndex],
      tfData.MaxPullbackPercent,
      tfData.MaxPullbackTotal,
      tfData.MinPriceChangeTotalForTrendStart,
      MinBarsRequired,
      DownTrendVisuals,
      UpTrendVisuals,
      IsDebuggingEnabled);

      tfData.UpTrendData = tfData.MarketTrendIndicator.UpTrendData;
      tfData.DownTrendData = tfData.MarketTrendIndicator.DownTrendData;
      }
      }


      protected override void OnBarUpdate()
      {
      if (Use10M && BarsInProgress == Index10Min)
      {
      data10Min = GetTimeframeData(Index10Min);
      }
      }



      private TimeframeData GetTimeframeData(int index)
      {
      if (timeframeDataDict.TryGetValue(index, out var tfData))
      {
      Logging.LogMessage($"{TimeHelper.GetCurrentTimeFor matted(this, isLiveTrading)} GetTimeframeData for Index: {index}.", this);

      tfData.UpdateData();
      if (tfData.CurrentUpTrend != null)
      {
      LogMarketTrendData2(tfData.CurrentUpTrend);
      }
      // MarketTrendData currentUpTrend = tfData.GetLatestMarketTrendData(true);

      if (tfData.CurrentUpTrend != null)
      {
      LogMarketTrendData2(tfData.CurrentDownTrend);
      }

      return tfData;
      }
      else
      {
      Logging.DebugMessage($"{TimeHelper.GetCurrentTimeF ormatted(this, isLiveTrading)} GetTimeframeData failed for Index: {index}.", this, basicParameter.IsDebuggingEnabled);

      return null;
      }
      }

      In the logging all the OnBarUpdates are done befor the indicator even starts. So the MarkeTrenData Object in the TimeFrame Dictionary is always null. In the example log 2024-05-10 13:00:00.000 is the last bar from historical data.
      Example Logging:

      ​2024-05-10 10:40:00.000 GetTimeframeData for Index: 3.
      2024-05-10 10:50:00.000 GetTimeframeData for Index: 3.
      2024-05-10 11:00:00.000 GetTimeframeData for Index: 3.
      2024-05-10 11:10:00.000 GetTimeframeData for Index: 3.
      2024-05-10 11:20:00.000 GetTimeframeData for Index: 3.
      2024-05-10 11:30:00.000 GetTimeframeData for Index: 3.
      2024-05-10 11:40:00.000 GetTimeframeData for Index: 3.
      2024-05-10 11:50:00.000 GetTimeframeData for Index: 3.
      2024-05-10 12:00:00.000 GetTimeframeData for Index: 3.
      2024-05-10 12:10:00.000 GetTimeframeData for Index: 3.
      2024-05-10 12:20:00.000 GetTimeframeData for Index: 3.
      2024-05-10 12:30:00.000 GetTimeframeData for Index: 3.
      2024-05-10 12:40:00.000 GetTimeframeData for Index: 3.
      2024-05-10 12:50:00.000 GetTimeframeData for Index: 3.
      2024-05-10 13:00:00.000 GetTimeframeData for Index: 3.
      2024-11-20 21:25:15.010 OnBarUpdate called.
      2024-11-20 21:25:15.010 HasEnoughBarsChecker: TimeFrame: 5 Minute, CurrentBar: 0, RequiredBarIndex: 4, HasEnoughBars: False
      2024-11-20 21:25:15.010 Waiting for more bars. CurrentBar: 0
      2024-11-20 21:25:15.010 OnBarUpdate called.
      2024-11-20 21:25:15.010 HasEnoughBarsChecker: TimeFrame: 5 Minute, CurrentBar: 1, RequiredBarIndex: 4, HasEnoughBars: False
      2024-11-20 21:25:15.010 Waiting for more bars. CurrentBar: 1
      2024-11-20 21:25:15.010 OnBarUpdate called.
      2024-11-20 21:25:15.010 HasEnoughBarsChecker: TimeFrame: 5 Minute, CurrentBar: 2, RequiredBarIndex: 4, HasEnoughBars: False
      2024-11-20 21:25:15.010 Waiting for more bars. CurrentBar: 2
      2024-11-20 21:25:15.010 OnBarUpdate called.
      2024-11-20 21:25:15.010 HasEnoughBarsChecker: TimeFrame: 5 Minute, CurrentBar: 3, RequiredBarIndex: 4, HasEnoughBars: False
      2024-11-20 21:25:15.010 Waiting for more bars. CurrentBar: 3
      2024-11-20 21:25:15.010 OnBarUpdate called.
      2024-11-20 21:25:15.010 HasEnoughBarsChecker: TimeFrame: 5 Minute, CurrentBar: 4, RequiredBarIndex: 4, HasEnoughBars: True
      2024-11-20 21:25:15.011 MarketAnalysisEngine OnBarUpdate called for Up Trend
      2024-11-20 21:25:15.012 No active Up trend detected.
      2024-11-20 21:25:15.012 New Up Trend detected


      Does this help or do you need more information?​

      Comment


        #4
        Hello AlgoLuke,

        If the indicator has no plot you would need to use the Update method to have it update with OnBarUpdate correctly if you need to access any values in the script.

        From the given sample I cant tell how the prints should look because you have an extra method in use there that is not shown, I would suggest making a much more simple test with only a standard print inside OnBarUpdate to explicitly show what you are trying to describe is the problem.

        Comment

        Latest Posts

        Collapse

        Topics Statistics Last Post
        Started by NullPointStrategies, Yesterday, 05:17 AM
        0 responses
        58 views
        0 likes
        Last Post NullPointStrategies  
        Started by argusthome, 03-08-2026, 10:06 AM
        0 responses
        133 views
        0 likes
        Last Post argusthome  
        Started by NabilKhattabi, 03-06-2026, 11:18 AM
        0 responses
        73 views
        0 likes
        Last Post NabilKhattabi  
        Started by Deep42, 03-06-2026, 12:28 AM
        0 responses
        45 views
        0 likes
        Last Post Deep42
        by Deep42
         
        Started by TheRealMorford, 03-05-2026, 06:15 PM
        0 responses
        50 views
        0 likes
        Last Post TheRealMorford  
        Working...
        X