Indicator returns error: NaN

Created at 06 Jun 2023, 09:40
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
WM

wmclennan77

Joined 29.06.2021

Indicator returns error: NaN
06 Jun 2023, 09:40


Hi,

I have an indicator that seems to be creating the following error: Crashed in Calculate with ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: Y1. Actual value was: NaN.

What is Y1?

Here is the code:

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Linq;
using System.Diagnostics;


namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class CombinedArrows : Indicator
    {
        [Parameter("Aroon Periods", Group = "Aroon", DefaultValue = 5, MinValue = 1)]
        public int AroonPeriods { get; set; }

        [Parameter("Max Doji Body Percentage", Group = "Dojis", DefaultValue = 25.00, MinValue = 1.00, MaxValue = 100.00, Step = 1)]
        public double BodyMax { get; set; }

        [Parameter("Min Doji Bigger Wick Pips", Group = "Dojis", DefaultValue = 3.5, MinValue = 0.1, Step = 0.5)]
        public double WickMin { get; set; }

        [Parameter("EMA Period 1", Group = "EMAs", DefaultValue = 12, MinValue = 1)]
        public int EMA_Period1 { get; set; }

        [Parameter("EMA Period 2", Group = "EMAs", DefaultValue = 26, MinValue = 1)]
        public int EMA_Period2 { get; set; }

        [Parameter("EMA Period 3", Group = "EMAs", DefaultValue = 50, MinValue = 1)]
        public int EMA_Period3 { get; set; }

        [Parameter("Arrow Offset (Pips)", Group = "Visual Settings", DefaultValue = 2.0, MinValue = 0.1, Step = 0.1)]
        public double Offset { get; set; }

        bool Buy, Sell;
        double Body, Candle, LowerWick, UpperWick, BodyPercent;
        string BuyArrow, SellArrow, BuyText, SellText;

        Aroon AroonI;
        ExponentialMovingAverage EMA1, EMA2, EMA3;

        protected override void Initialize()
        {
            Offset *= Symbol.PipSize;
            WickMin *= Symbol.PipSize;
            BodyMax /= 100;

            AroonI = Indicators.Aroon(AroonPeriods);
            EMA1 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EMA_Period1);
            EMA2 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EMA_Period2);
            EMA3 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EMA_Period3);
        }

        public override void Calculate(int index)
        {
            BuyArrow = string.Format("Buy_Arrow_{0}", index.ToString());
            BuyText = string.Format("Buy_Obj_{0}", index.ToString());
            SellArrow = string.Format("Sell_Arrow_{0}", index.ToString());
            SellText = string.Format("Sell_Obj_{0}", index.ToString());

            Buy = GetBuy();
            Sell = GetSell();

            if (Buy)
            {
                Chart.DrawIcon(BuyArrow, ChartIconType.UpTriangle, Bars.OpenTimes.LastValue, Bars.LowPrices.LastValue - Offset, Color.Lime);
                Chart.DrawText(BuyText, "BUY", Bars.OpenTimes.LastValue, Bars.LowPrices.LastValue - (Offset * 2), Color.White);
            }

            if (Sell)
            {
                Chart.DrawIcon(SellArrow, ChartIconType.DownTriangle, Bars.OpenTimes.LastValue, Bars.HighPrices.LastValue + Offset, Color.Red);
                Chart.DrawText(SellText, "SELL", Bars.OpenTimes.LastValue, Bars.HighPrices.LastValue + (Offset * 2), Color.White);
            }

            if (!Buy)
            {
                Chart.RemoveObject(BuyArrow);
                Chart.RemoveObject(BuyText);
            }

            if (!Sell)
            {
                Chart.RemoveObject(SellArrow);
                Chart.RemoveObject(SellText);
            }
        }

        private bool GetBuy()
        {
            bool EMARejection = GetEMARejection();
            bool IsDragonfly = GetIsDragonfly();
            bool IsAroonBuy = AroonI.Down.LastValue == 100;

            if (EMARejection && IsDragonfly && IsAroonBuy) return true;
            return false;
        }

        private bool GetSell()
        {
            bool EMARejection = GetEMARejection();
            bool IsGravestone = GetIsGravestone();
            bool IsAroonSell = AroonI.Up.LastValue == 100;

            if (EMARejection && IsGravestone && IsAroonSell) return true;
            return false;
        }

        private bool GetEMARejection()
        {
            int Direction = 0;
            Direction = EMA1.Result.LastValue > EMA2.Result.LastValue && EMA2.Result.LastValue > EMA3.Result.LastValue ? 1 : 0;
            Direction = EMA1.Result.LastValue < EMA2.Result.LastValue && EMA2.Result.LastValue < EMA3.Result.LastValue ? 2 : 0;
            double[] ChartInfo = {
                Bars.OpenPrices.LastValue, //0
                Bars.HighPrices.LastValue, //1
                Bars.LowPrices.LastValue, //2
                Bars.ClosePrices.LastValue, //3
                EMA1.Result.LastValue, //4
                EMA2.Result.LastValue, //5
                EMA3.Result.LastValue //6
            };


            if (Direction == 1) //buy
            {
                bool[] BuyChecks = {
                    ChartInfo[3] > ChartInfo[4] && ChartInfo[0] > ChartInfo[4] && ChartInfo[2] < ChartInfo[4],
                    ChartInfo[3] < ChartInfo[4] && ChartInfo[0] < ChartInfo[4] && ChartInfo[3] > ChartInfo[5] && ChartInfo[0] > ChartInfo[5] && ChartInfo[2] < ChartInfo[5],
                    ChartInfo[3] < ChartInfo[5] && ChartInfo[0] < ChartInfo[5] && ChartInfo[3] > ChartInfo[6] && ChartInfo[0] > ChartInfo[6] && ChartInfo[2] < ChartInfo[6],
                };

                if (BuyChecks.Any(Is => Is)) return true;
            }

            if (Direction == 2) //sell
            {
                bool[] SellChecks = {
                    ChartInfo[3] < ChartInfo[4] && ChartInfo[0] < ChartInfo[4] && ChartInfo[1] > ChartInfo[4],
                    ChartInfo[3] > ChartInfo[4] && ChartInfo[0] > ChartInfo[4] && ChartInfo[3] < ChartInfo[5] && ChartInfo[0] < ChartInfo[5] && ChartInfo[1] > ChartInfo[5],
                    ChartInfo[3] > ChartInfo[5] && ChartInfo[0] > ChartInfo[5] && ChartInfo[3] < ChartInfo[6] && ChartInfo[0] < ChartInfo[6] && ChartInfo[1] > ChartInfo[6],
                };

                if (SellChecks.Any(Is => Is)) return true;
            }

            return false;
        }

        private bool GetIsDragonfly()
        {
            Body = Bars.ClosePrices.LastValue > Bars.OpenPrices.LastValue ? Bars.ClosePrices.LastValue - Bars.OpenPrices.LastValue : Bars.OpenPrices.LastValue - Bars.ClosePrices.LastValue;
            Candle = Bars.HighPrices.LastValue - Bars.LowPrices.LastValue;
            LowerWick = Bars.ClosePrices.LastValue > Bars.OpenPrices.LastValue ? Bars.OpenPrices.LastValue - Bars.LowPrices.LastValue : Bars.ClosePrices.LastValue - Bars.LowPrices.LastValue;
            UpperWick = Bars.ClosePrices.LastValue > Bars.OpenPrices.LastValue ? Bars.HighPrices.LastValue - Bars.ClosePrices.LastValue : Bars.HighPrices.LastValue - Bars.OpenPrices.LastValue;
            bool IsWickMin = LowerWick >= WickMin;
            BodyPercent = Math.Round(Body / Candle, 2);

            if (BodyPercent < BodyMax && LowerWick > UpperWick && IsWickMin) return true;
            else return false;
        }

        private bool GetIsGravestone()
        {
            Body = Bars.ClosePrices.LastValue > Bars.OpenPrices.LastValue ? Bars.ClosePrices.LastValue - Bars.OpenPrices.LastValue : Bars.OpenPrices.LastValue - Bars.ClosePrices.LastValue;
            Candle = Bars.HighPrices.LastValue - Bars.LowPrices.LastValue;
            LowerWick = Bars.ClosePrices.LastValue > Bars.OpenPrices.LastValue ? Bars.OpenPrices.LastValue - Bars.LowPrices.LastValue : Bars.ClosePrices.LastValue - Bars.LowPrices.LastValue;
            UpperWick = Bars.ClosePrices.LastValue > Bars.OpenPrices.LastValue ? Bars.HighPrices.LastValue - Bars.ClosePrices.LastValue : Bars.HighPrices.LastValue - Bars.OpenPrices.LastValue;
            bool IsWickMin = UpperWick >= WickMin;
            BodyPercent = Math.Round(Body / Candle, 2);

            if (BodyPercent < BodyMax && UpperWick > LowerWick && IsWickMin) return true;
            else return false;
        }
    }
}

 


@wmclennan77
Replies

firemyst
07 Jun 2023, 03:39

Y1 is typically the first parameter that specifies a value along the Y-axis of the chart.

However, looking at your code, I didn't see anything wrong.

I then ran it in Visual Studio and there were no crashes or faults among 5 forex pairs and the US30 charts.

So what symbol and timeframe were you running this on?


@firemyst

wmclennan77
07 Jun 2023, 09:00

RE:

firemyst said:

Y1 is typically the first parameter that specifies a value along the Y-axis of the chart.

However, looking at your code, I didn't see anything wrong.

I then ran it in Visual Studio and there were no crashes or faults among 5 forex pairs and the US30 charts.

So what symbol and timeframe were you running this on?

Hi, the error seems to have disappeared when I added: if (Direction == 0) return;

I don't know why, but that seems to have solved it.


@wmclennan77

... Deleted by UFO ...