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

Relative Volume for Non-time-based Barstypes

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

    Relative Volume for Non-time-based Barstypes

    I'm trying to create a new Relative volume indicator for barstypes that might not necessarily have a bar at the current date/time on the previous days. I programmed it how I believe it should work and I'm trying to test it, but it doesn't even show up on the list of indicators after a compile. I can't even export it as an indicator because it doesn't show up in the list. There are no errors in the log, or output. The code is below. I'd love some help figuring this out.

    note: I do have an indicator folder named RadIndicators for my custom indicators.

    Code:
    //
    // Copyright (C) 2019, NinjaTrader LLC <www.ninjatrader.com>.
    // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
    //
    #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.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion
    
    // This namespace holds indicators in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Indicators.RadIndicators
    {
        /// <summary>
        /// Plots the relative volume at the current time of day
        /// To be used with bars that arent time based.
        /// </summary>
        public class RadRelativeVolume : Indicator
        {
            private DateTime sessionStartTime;
            private double cumulativeVolume = 0;
            private TimeSpan startTime = new TimeSpan(4, 0, 0); // Default start time at 4 AM
            private double initialVolume = 100; // Default initial volume to avoid divide by zero
            private int historicalDays = 5; // Default: look back 5 days
    
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description = @"Indicator for VPS with daily and historical average.";
                    Name = "CustomVPSIndicator";
                    Calculate = Calculate.OnEachTick; // Necessary for VPS calculation
                    IsOverlay = false; // This indicator does not overlay on the price chart
                    MaximumBarsLookBack        = MaximumBarsLookBack.Infinite;
    
                    AddPlot(Brushes.DodgerBlue, "DailyVPS"); // Plot 1
                    AddPlot(Brushes.Coral, "AverageVPS"); // Plot 2
                    AddPlot(Brushes.Green, "RelativeVolume"); // Plot 2
                }
                else if (State == State.DataLoaded)
                {
                }
            }
    
            protected override void OnBarUpdate()
            {
                // Ensure the session start time and cumulative volume are correctly initialized
                if (Bars.IsFirstBarOfSession || CurrentBar == 0)
                {
                    sessionStartTime = Time[0].Date.Add(startTime);
                    cumulativeVolume = initialVolume;
                }
    
                cumulativeVolume += Volume[0];
    
                // Update Daily VPS plot
                TimeSpan elapsedSinceStart = Time[0] - sessionStartTime;
                Values[0][0] = cumulativeVolume / Math.Max(elapsedSinceStart.TotalSeconds, 1); // Avoid division by zero
    
                // Calculate and update Average VPS plot continuously
                Values[1][0] = CalculateMonteCarloAverageVPS(Time[0]);
    
                // Update the ratio plot only if averageVPS is not zero to avoid division by zero
                if (Values[1][0] != 0)
                    Values[2][0] = Values[0][0] / Values[1][0];
            }
    
            // Placeholder for calculating average VPS from previous 5 days using Monte Carlo method
            private double CalculateMonteCarloAverageVPS(DateTime currentTime)
            {
                // List to hold VPS values from the previous days for the same time
                List<double> previousVPSValues = new List<double>();
            
                // Assuming we're calculating for the current time each day
                DateTime targetTime = Time[0];
            
                // Calculate and store VPS for each of the historical days
                for (int daysBack = 1; daysBack <= historicalDays; daysBack++)
                {
                    DateTime historicalTime = targetTime.AddDays(-daysBack);
                    int barIndex = Bars.GetBar(historicalTime);
            
                    if (barIndex > 0 && barIndex < CurrentBar)
                    {
                        // Approximate the VPS for this historical day at the target time
                        double historicalVolume = Volume[barIndex]; // Simplified, consider using a better approximation
                        double vps = historicalVolume; // This is a simplification, adjust according to your actual VPS calculation logic
                        
                        previousVPSValues.Add(vps);
                    }
                }
            
                // Now, apply the Monte Carlo method to the collected VPS values
                // Sort the list to prepare for removing the highest and lowest values
                previousVPSValues.Sort();
            
                if (previousVPSValues.Count >= 5)
                {
                    // Remove the highest and lowest VPS values to apply Monte Carlo smoothing
                    previousVPSValues.RemoveAt(0); // Remove the lowest
                    previousVPSValues.RemoveAt(previousVPSValues.Count - 1); // Remove the highest
                }
            
                // Calculate and return the average of the remaining VPS values
                return previousVPSValues.Any() ? previousVPSValues.Average() : 0; // Ensure there's data to average
            }
            
            #region Properties
            [Browsable(false)]
            [XmlIgnore]
            public Series<double> Daily_Total_Volume
            {
                get { return Values[0]; }
            }
    
            [Browsable(false)]
            [XmlIgnore]
            public Series<double> AverageVPS
            {
                get { return Values[1]; }
            }
            
            [Browsable(false)]
            [XmlIgnore]
            public Series<double> RelativeVolume
            {
                get { return Values[2]; }
            }
            
            [Range(1, int.MaxValue), NinjaScriptProperty]
            public int HistoricalDays
            {
                get { return historicalDays; }
                set { historicalDays = Math.Max(1, value); } // Ensure at least 1 day
            }
            #endregion
        }
    }
    
    #region NinjaScript generated code. Neither change nor remove.
    
    namespace NinjaTrader.NinjaScript.Indicators
    {
        public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
        {
            private RadIndicators.RadRelativeVolume[] cacheRadRelativeVolume;
            public RadIndicators.RadRelativeVolume RadRelativeVolume(int historicalDays)
            {
                return RadRelativeVolume(Input, historicalDays);
            }
    
            public RadIndicators.RadRelativeVolume RadRelativeVolume(ISeries<double> input, int historicalDays)
            {
                if (cacheRadRelativeVolume != null)
                    for (int idx = 0; idx < cacheRadRelativeVolume.Length; idx++)
                        if (cacheRadRelativeVolume[idx] != null && cacheRadRelativeVolume[idx].HistoricalDays == historicalDays && cacheRadRelativeVolume[idx].EqualsInput(input))
                            return cacheRadRelativeVolume[idx];
                return CacheIndicator<RadIndicators.RadRelativeVolume>(new RadIndicators.RadRelativeVolume(){ HistoricalDays = historicalDays }, input, ref cacheRadRelativeVolume);
            }
        }
    }
    
    namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
    {
        public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
        {
            public Indicators.RadIndicators.RadRelativeVolume RadRelativeVolume(int historicalDays)
            {
                return indicator.RadRelativeVolume(Input, historicalDays);
            }
    
            public Indicators.RadIndicators.RadRelativeVolume RadRelativeVolume(ISeries<double> input , int historicalDays)
            {
                return indicator.RadRelativeVolume(input, historicalDays);
            }
        }
    }
    
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
        {
            public Indicators.RadIndicators.RadRelativeVolume RadRelativeVolume(int historicalDays)
            {
                return indicator.RadRelativeVolume(Input, historicalDays);
            }
    
            public Indicators.RadIndicators.RadRelativeVolume RadRelativeVolume(ISeries<double> input , int historicalDays)
            {
                return indicator.RadRelativeVolume(input, historicalDays);
            }
        }
    }
    
    #endregion
    ​

    #2
    Hello RaddiFX,

    Thanks for your post.

    Typically if the script is not appearing in the Indicators window, this indicates that there is an issue in your script's code. The error is usually in the OnStateChange() section of the script.

    I see that the Name property is not the same as the indicator script in the code you shared. The indicator will display in the Indicators window based on the 'Name' property you define in the script.

    This means that the indicator would appear as 'CustomVPSIndicator', not as 'RadRelativeVolume'. As a best practice, we recommend setting the Name property to the same name as the indicator file.

    To clarify, if you open the Indicators window, do you see an indicator called 'CustomVPSIndicator' appearing? This would appear in the 'RadIndicators' subfolder since you mentioned the indicator is placed within a subfolder.

    Otherwise, to locate the exact line of code causing the behavior you would need to reduce the code of your script. Comment out code in the script line by line and test to see if the behavior persists. If at any point you comment out a line of code and the indicator starts appearing in the Indicators window, the last commented-out line of code is likely causing the behavior.
    Last edited by NinjaTrader_BrandonH; 04-07-2024, 02:01 PM.
    Brandon H.NinjaTrader Customer Service

    Comment


      #3
      That was it precisely. Thank you!

      Comment

      Latest Posts

      Collapse

      Topics Statistics Last Post
      Started by bc24fl, 08-30-2019, 01:58 PM
      4 responses
      258 views
      0 likes
      Last Post PaulMohn  
      Started by sugalt, Today, 04:02 AM
      0 responses
      4 views
      0 likes
      Last Post sugalt
      by sugalt
       
      Started by tradingnasdaqprueba, 04-09-2024, 09:52 AM
      6 responses
      29 views
      0 likes
      Last Post tradingnasdaqprueba  
      Started by PaulMohn, Today, 02:06 AM
      1 response
      3 views
      0 likes
      Last Post PaulMohn  
      Started by Mindset, Today, 01:27 AM
      0 responses
      5 views
      0 likes
      Last Post Mindset
      by Mindset
       
      Working...
      X