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

OnRender Performance Questions

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

    OnRender Performance Questions

    Hello,

    I'm facing performance issues with my `OnRender` implementation in NinjaTrader, specifically when scrolling/zooming through the chart. The performance noticeably degrades, and I'm trying to understand the root cause.

    I've implemented a dictionary to map bar indexes to pattern IDs, which I then iterate through in `OnRender` to render pattern IDs relative to their candles. Here's a simplified version of my approach:

    Code:
    // Dictionary holding bar index and Pattern IDs
    private Dictionary<int, List<int>> erkannteMusterProIndex_Long = new Dictionary<int, List<int>>();
    
    // OnRender implementation
    protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
            {
              
                base.OnRender(chartControl, chartScale);
              
                int fromIndex = ChartBars.FromIndex;
                int toIndex = ChartBars.ToIndex;
                // Durchlaufe alle Einträge im Dictionary
                foreach (var entry in erkannteMusterProIndex_Long.Where(e => e.Key >= toIndex -25 && e.Key <= toIndex))
                {
                    int barIndex = entry.Key; // Der Index der Kerze
                    List<int> musterListe = entry.Value; // Die Liste der Muster für diese Kerze
                  
                    // Schriftart und Stil
                    SharpDX.DirectWrite.TextFormat textFormat = new SharpDX.DirectWrite.TextFormat(
                        NinjaTrader.Core.Globals.DirectWriteFactory,
                        "Arial",
                        SharpDX.DirectWrite.FontWeight.Bold, // Hier setzen wir den Text auf fett
                        SharpDX.DirectWrite.FontStyle.Normal,
                        14
                    );
                    SharpDX.Direct2D1.SolidColorBrush brush = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Green);
                  
                    float baseYPosition = 0; // Initialisieren der Basis-Y-Position; // Initialisieren der Basis-Y-Position
                    for (int i = 0; i < musterListe.Count; i++)
                    {
                        int musterNummer = musterListe[i];
                        string text = musterNummer.ToString();
                      
                        SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory, text, textFormat, 100, 100 );
                      
                        // Berechne die X-Position der aktuellen Bar im Chart
                        double barWidth = chartControl.BarWidth;
                        int  xPosition = chartControl.GetXByBarIndex(ChartBars, barIndex) ;
                      
                        // Berechne die Y-Position für das Zeichnen des Musters, basierend auf dem Low der Kerze plus einem Offset
                        // Die Verwendung von Low[barIndex] funktioniert in OnRender nicht direkt. Du musst den Wert umrechnen:
                        if ( i == 0 )
                        {
                            baseYPosition = chartScale.GetYByValue(Low.GetValueAt(barIndex)) + 5; // Offset nach unten für jedes Muster
                        }
                      
                        float yPosition = baseYPosition + (textLayout.Metrics.Height * i);
                      
                        // create a rectangle which will automatically resize to the width/height of the textLayout
    textLayout.Metrics.Height);
                      
                        // execute the render target draw rectangle with desired values
                                          
                        SharpDX.Vector2 startPoint = new SharpDX.Vector2(xPosition - 4, yPosition);
                        // Zeichne den Text bei den ersten sichtbaren Bar-Koordinaten als Beispiel      
                        RenderTarget.DrawTextLayout(startPoint, textLayout, brush);
                        textLayout.Dispose();
                      
                    }
                    // Aufräumen
                    textFormat.Dispose();
                    brush.Dispose();
                }
              
              
                      
            }​
    This implementation seems to cause performance issues, particularly during chart interactions like zooming and scrolling, even though `OnRender` is being called frequently (about 4 times per second).

    Is there a more performance-optimized way to manage and render these pattern IDs for visible bars only? How can I improve the efficiency of this rendering logic to mitigate the scrolling/zooming performance impact?

    Any insights or suggestions would be greatly appreciated!

    #2
    Hello lakman184,

    Some obvious reasons would be that you are using a linq expression to search the dictionary which will use resources for each loop iteration to find an element, if possible I would suggest not using a dictionary and instead use a Series or other type which natively supports indexing and then just use the bar index directly on the Series GetValueAt method.

    Another item is that you are creating a new brush and TextFormat for each iteration, those don't appear to change so those should be defined out of the loops or in OnRenderTargetChanged. https://ninjatrader.com/support/help...rTargetChanged

    You have an additional loops within your first loop which could cause extra usage, if possible I would suggest trying to simplify what you are doing to be index based instead of using loops.

    In most cases the suggested approach is to prepare all of your data in a Series<double> from OnBarUpdate, the result should be ready before using it in OnRender. If you do the processing at a less frequent interval from OnBarUpdate and then record the result in a Series<double> you can use GetValueAt on the series and just render the result for each bar. That would be similar to the sample in the following page which only gets a value for the currently visible bars from the series which you can then render. https://ninjatrader.com/support/help...ghtsub=toindex
    JesseNinjaTrader Customer Service

    Comment

    Latest Posts

    Collapse

    Topics Statistics Last Post
    Started by pibrew, Today, 06:37 AM
    0 responses
    4 views
    0 likes
    Last Post pibrew
    by pibrew
     
    Started by rbeckmann05, Yesterday, 06:48 PM
    1 response
    14 views
    0 likes
    Last Post bltdavid  
    Started by llanqui, Today, 03:53 AM
    0 responses
    6 views
    0 likes
    Last Post llanqui
    by llanqui
     
    Started by burtoninlondon, Today, 12:38 AM
    0 responses
    11 views
    0 likes
    Last Post burtoninlondon  
    Started by AaronKoRn, Yesterday, 09:49 PM
    0 responses
    16 views
    0 likes
    Last Post AaronKoRn  
    Working...
    X