Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

negative latency

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

    negative latency

    Hi. Following code results in negative latency, why (my PC time had time set via ntp, just prior to running the code)?
    PHP Code:
                    lastTickTime = marketDataUpdate.Time;
                    
                    // Calculate latency in milliseconds
                    DateTime currentTime = Core.Globals.Now;
                    currentLatencyMs = (currentTime - lastTickTime).TotalMilliseconds;​ 
    

    #2
    Hello MiCe1999

    Thanks for your message.



    To first understand why you're receiving a negative value for the latency, we need to first understand the values of your variables and how they are applied in your logic.

    You are subtracting the LastTickTime variable from the currentTime variable.

    This behavior can happen even if NTP is used — exchange clocks are not guaranteed to be exactly in sync with NTP. They're often on exchange-specific timing sources.

    Also, when calling the marketDataUpdate property, ensure it's being called inside OnMarketData()



    I have created a test script on my end, working with the same properties and values from marketDataUpdate.Time and Core.Globals.Now.

    The link below has a video demonstrating the output of the variables as well as the results of the calculation.





    As you can see in the video, I do not receive any negative latency values. This indicates that the issue is likely with your computer clock, which can be slightly out of sync.

    The link below contains an example of how to sync your computer clock. Note that the article is for a different issue, but the steps to sync your clock are the same

    How to sync your clock



    MarketDataEventArg

    Print()

    OnMarketData()

    Comment


      #3
      Thank you for looking into it. Same code gives me following output:
      Instrument: NQ JUN25, LastTick: 13:03:52.716, Current: 13:03:52.611, Latency: -104.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.716, Current: 13:03:52.611, Latency: -104.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.716, Current: 13:03:52.611, Latency: -104.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.716, Current: 13:03:52.611, Latency: -104.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.720, Current: 13:03:52.611, Latency: -108.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.720, Current: 13:03:52.611, Latency: -108.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.720, Current: 13:03:52.611, Latency: -108.49ms
      Instrument: NQ JUN25, LastTick: 13:03:52.788, Current: 13:03:52.650, Latency: -137.86ms
      Instrument: NQ JUN25, LastTick: 13:03:52.788, Current: 13:03:52.650, Latency: -137.86ms
      Instrument: NQ JUN25, LastTick: 13:03:52.817, Current: 13:03:52.688, Latency: -128.84ms
      Instrument: NQ JUN25, LastTick: 13:03:52.817, Current: 13:03:52.688, Latency: -128.84ms​

      PHP Code:
      #region Using declarations
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.ComponentModel.DataAnnotations;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Xml.Serialization;
      using NinjaTrader.Cbi;
      using NinjaTrader.Gui;
      using NinjaTrader.Gui.Chart;
      using NinjaTrader.Gui.SuperDom;
      using NinjaTrader.Gui.Tools;
      using NinjaTrader.Data;
      using NinjaTrader.NinjaScript;
      using NinjaTrader.Core.FloatingPoint;
      using NinjaTrader.NinjaScript.DrawingTools;
      #endregion
      
      namespace NinjaTrader.NinjaScript.Indicators
      {
          public class MarketDataLatencyMonitor : Indicator
          {
              private System.Windows.Media.Brush textBrush;
              private System.Windows.Media.Brush latencyBrush;
              private string fontFamily;
              private double fontSize;
              
              protected override void OnStateChange()
              {
                  if (State == State.SetDefaults)
                  {
                      Description = "Monitors and displays market data latency";
                      Name = "Market Data Latency Monitor";
                      Calculate = Calculate.OnPriceChange;
                      IsOverlay = true;
                      DisplayInDataBox = false;
                      DrawOnPricePanel = false;
                      DrawHorizontalGridLines = false;
                      DrawVerticalGridLines = false;
                      PaintPriceMarkers = false;
                      ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                      IsSuspendedWhileInactive = true;
                      
                      // Default display settings
                      TickTimeColor = System.Windows.Media.Colors.Yellow;
                      CurrentTimeColor = System.Windows.Media.Colors.Cyan;
                      LatencyColor = System.Windows.Media.Colors.Orange;
                      FontSize = 12;
                      FontFamily = "Consolas";
                      
                      // Debug default setting
                      EnableDebug = false;
                  }
                  else if (State == State.Configure)
                  {
                      // No calculation is needed for this indicator
                  }
                  else if (State == State.DataLoaded)
                  {
                      DebugOutput("MarketDataLatencyMonitor initialized - Debug mode enabled");
                  }
              }
              
              public override void OnRenderTargetChanged()
              {
                  // Create resources tied to the current RenderTarget
                  if (RenderTarget != null)
                  {
                      textBrush = new System.Windows.Media.SolidColorBrush(TickTimeColor);
                      latencyBrush = new System.Windows.Media.SolidColorBrush(LatencyColor);
                      
                      // Debug output when render target changes
                      DebugOutput("RenderTarget changed");
                  }
              }
              
              protected override void OnMarketData(MarketDataEventArgs marketDataUpdate)
              {
                  DateTime lastTickTime = marketDataUpdate.Time;
                  DateTime currentTime = Core.Globals.Now;
                  
                  double currentLatencyMs = (currentTime - lastTickTime).TotalMilliseconds;
                  
                  // Store these values so they can be displayed in OnRender
                  LastTickTime = lastTickTime;
                  CurrentTime = currentTime;
                  LatencyMs = currentLatencyMs;
                  
                  // Debug output
                  DebugOutput(string.Format("Instrument: {0}, LastTick: {1}, Current: {2}, Latency: {3}ms",
                      Instrument.FullName,
                      lastTickTime.ToString("HH:mm:ss.fff"),
                      currentTime.ToString("HH:mm:ss.fff"),
                      currentLatencyMs.ToString("0.00")));
                  
                  // Force redraw to update the displayed values
                  ForceRefresh();
              }
              
              protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
              {
                  base.OnRender(chartControl, chartScale);
                  
                  if (Bars == null || Bars.Instrument == null || LastTickTime == default(DateTime))
                      return;
                      
                  // Set up the text formatting
                  SharpDX.DirectWrite.TextFormat textFormat = new SharpDX.DirectWrite.TextFormat(NinjaTrader.Core.Globals.DirectWriteFactory,
                      FontFamily, SharpDX.DirectWrite.FontWeight.Normal, SharpDX.DirectWrite.FontStyle.Normal,
                      SharpDX.DirectWrite.FontStretch.Normal, (float)FontSize);
                      
                  // Get the area to draw in
                  float startX = ChartPanel.X + 10;
                  float startY = ChartPanel.Y + 50;
                  float lineHeight = (float)FontSize * 1.5f;
                  
                  // Draw last tick time
                  SharpDX.DirectWrite.TextLayout tickTimeLayout = new SharpDX.DirectWrite.TextLayout(
                      NinjaTrader.Core.Globals.DirectWriteFactory,
                      "Last Tick Time: " + LastTickTime.ToString("HH:mm:ss.fff"),
                      textFormat, ChartPanel.W, textFormat.FontSize);
                      
                  RenderTarget.DrawTextLayout(
                      new SharpDX.Vector2(startX, startY),
                      tickTimeLayout,
                      new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Yellow));
                  tickTimeLayout.Dispose();
                  
                  // Draw current time
                  SharpDX.DirectWrite.TextLayout currentTimeLayout = new SharpDX.DirectWrite.TextLayout(
                      NinjaTrader.Core.Globals.DirectWriteFactory,
                      "Current Time: " + CurrentTime.ToString("HH:mm:ss.fff"),
                      textFormat, ChartPanel.W, textFormat.FontSize);
                      
                  RenderTarget.DrawTextLayout(
                      new SharpDX.Vector2(startX, startY + lineHeight),
                      currentTimeLayout,
                      new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Cyan));
                  currentTimeLayout.Dispose();
                  
                  // Draw latency
                  SharpDX.DirectWrite.TextLayout latencyLayout = new SharpDX.DirectWrite.TextLayout(
                      NinjaTrader.Core.Globals.DirectWriteFactory,
                      "Latency in Milliseconds: " + LatencyMs.ToString(),
                      textFormat, ChartPanel.W, textFormat.FontSize);
                      
                  RenderTarget.DrawTextLayout(
                      new SharpDX.Vector2(startX, startY + lineHeight * 2),
                      latencyLayout,
                      new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Orange));
                  latencyLayout.Dispose();
                  
                  // Dispose text format
                  textFormat.Dispose();
                  
                  // Debug output - render cycle
                  DebugOutput("OnRender called - Panel: " + ChartPanel.ToString());
              }
              
              // Helper method for debug output
              private void DebugOutput(string message)
              {
                  if (EnableDebug)
                      NinjaTrader.Code.Output.Process(message, PrintTo.OutputTab1);
              }
      
              #region Properties
              [Browsable(false)]
              [XmlIgnore]
              public DateTime LastTickTime { get; private set; }
              
              [Browsable(false)]
              [XmlIgnore]
              public DateTime CurrentTime { get; private set; }
              
              [Browsable(false)]
              [XmlIgnore]
              public double LatencyMs { get; private set; }
              
              [Display(Name = "Tick Time Color", Description = "Color for the tick time text", GroupName = "Display Settings", Order = 1)]
              public System.Windows.Media.Color TickTimeColor
              { get; set; }
              
              [Display(Name = "Current Time Color", Description = "Color for the current time text", GroupName = "Display Settings", Order = 2)]
              public System.Windows.Media.Color CurrentTimeColor
              { get; set; }
              
              [Display(Name = "Latency Color", Description = "Color for the latency text", GroupName = "Display Settings", Order = 3)]
              public System.Windows.Media.Color LatencyColor
              { get; set; }
              
              [Display(Name = "Font Size", Description = "Size of the display font", GroupName = "Display Settings", Order = 4)]
              [Range(8, 24)]
              public double FontSize
              { get; set; }
              
              [Display(Name = "Font Family", Description = "Font used for display", GroupName = "Display Settings", Order = 5)]
              [PropertyEditor("NinjaTrader.Gui.Tools.StringStandardValuesEditorKey")]
              public string FontFamily
              { get; set; }
              
              [Display(Name = "Enable Debug", Description = "Output debug information to console", GroupName = "Debug Settings", Order = 1)]
              public bool EnableDebug
              { get; set; }
              #endregion
          }
      }​ 
      

      Comment


        #4
        Hello MiCe1999,

        Thanks for your reply.


        The issue you're experiencing does not appear to be related to the script itself. It may be due to your computer's internal clock being behind or out-of-sync, which is affecting the timestamps. You can also check the https://time.gov/ website for any differences between your system clock and internet time.

        Here’s how to sync your computer clock on Windows:

        Steps:
        1. Right-click the clock in the taskbar.
        2. Select “Adjust date/time.”
        3. Under “Synchronize your clock,” click “Sync now.”

        Make sure “Set time automatically” and “Set time zone automatically” are turned ON.

        If “Sync now” is greyed out:
        • Scroll down and click “Additional settings” → “Date, time, & regional formatting.”
        • Go to Control Panel → Date and Time → Internet Time tab.
        • Click “Change settings…”
        • Check “Synchronize with an Internet time server.”
        • Pick a server like
        • time.windows.com
        • and click “Update now.”

        Let us know if we can further assist you

        Comment


          #5
          I changed ntp server to 0.pool.ntp.org run w32tm /resync and...latency is fine now. I'm not sure if that's a coincidence or not - time will tell

          Click image for larger version

Name:	image.png
Views:	102
Size:	39.5 KB
ID:	1341371

          Comment

          Latest Posts

          Collapse

          Topics Statistics Last Post
          Started by Geovanny Suaza, 02-11-2026, 06:32 PM
          0 responses
          656 views
          0 likes
          Last Post Geovanny Suaza  
          Started by Geovanny Suaza, 02-11-2026, 05:51 PM
          0 responses
          371 views
          1 like
          Last Post Geovanny Suaza  
          Started by Mindset, 02-09-2026, 11:44 AM
          0 responses
          109 views
          0 likes
          Last Post Mindset
          by Mindset
           
          Started by Geovanny Suaza, 02-02-2026, 12:30 PM
          0 responses
          574 views
          1 like
          Last Post Geovanny Suaza  
          Started by RFrosty, 01-28-2026, 06:49 PM
          0 responses
          579 views
          1 like
          Last Post RFrosty
          by RFrosty
           
          Working...
          X