Replies

daniel.agg
26 Mar 2019, 18:09

Hi, the problem is solved (using a different indicator). Can you please delete this post?

Thanks in advance,
Dan


@daniel.agg

daniel.agg
08 Mar 2019, 10:07

That's strange, the .cs files should have been in the corresponding subfolders.

Anyway, here's the bot:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.Internet)]
    public class MACDTestBot : Robot
    {
        #region indicator parameters


        [Parameter("Divergence Ledge", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)]
        public int Divergence_Ledge { get; set; }

        [Parameter("Divergence Extremums", DefaultValue = false)]
        public bool Divergence_Extremums { get; set; }

        [Parameter("Divergence Min Length", DefaultValue = 6, MinValue = 4, MaxValue = 10, Step = 1)]
        public int Divergence_Min_Length { get; set; }

        [Parameter("Last Points", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)]
        public int Last_Points { get; set; }

        [Parameter("MACD:  Short Cycle", DefaultValue = 12)]
        public int MACD_Short_Cycle { get; set; }

        [Parameter("MACD:  Long Cycle", DefaultValue = 26)]
        public int MACD_Long_Cycle { get; set; }

        [Parameter("MACD:  Signal Period", DefaultValue = 9)]
        public int MACD_Signal_Period { get; set; }

        [Parameter("MACD:  Reverse", DefaultValue = false)]
        public bool MACD_Reverse { get; set; }

        #endregion

        private MACDDivergence indicator;

        private int indicatorDataCount;

        protected override void OnStart()
        {
            indicator = Indicators.GetIndicator<MACDDivergence>(
                Divergence_Ledge,
                Divergence_Extremums,
                Divergence_Min_Length,
                Last_Points,
                MACD_Short_Cycle,
                MACD_Long_Cycle,
                MACD_Signal_Period,
                MACD_Reverse);

            indicatorDataCount = indicator.Data.Count();
        }

        protected override void OnTick()
        {
            if(indicatorDataCount != indicator.Data.Count())
            {
                // do something
            }
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

And here's the indicator:

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
//using System.Linq;
using System.Collections.Generic;


namespace cAlgo.Indicators
{
    [Indicator(TimeZone = TimeZones.UTC, IsOverlay = false, AutoRescale = true, ScalePrecision = 7, AccessRights = AccessRights.None)]
    public class MACDDivergence : Indicator
    {



        [Parameter("Divergence Ledge", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)]
        public int Divergence_Ledge { get; set; }

        [Parameter("Divergence Extremums", DefaultValue = false)]
        public bool Divergence_Extremums { get; set; }

        [Parameter("Divergence Min Length", DefaultValue = 6, MinValue = 4, MaxValue = 10, Step = 1)]
        public int Divergence_Min_Length { get; set; }

        [Parameter("Last Points", DefaultValue = 3, MinValue = 1, MaxValue = 10, Step = 1)]
        public int Last_Points { get; set; }

        [Parameter("MACD:  Short Cycle", DefaultValue = 12)]
        public int MACD_Short_Cycle { get; set; }

        [Parameter("MACD:  Long Cycle", DefaultValue = 26)]
        public int MACD_Long_Cycle { get; set; }

        [Parameter("MACD:  Signal Period", DefaultValue = 9)]
        public int MACD_Signal_Period { get; set; }

        [Parameter("MACD:  Reverse", DefaultValue = false)]
        public bool MACD_Reverse { get; set; }

        [Output("Main", PlotType = PlotType.Histogram, Color = Colors.DeepSkyBlue)]
        public IndicatorDataSeries Result { get; set; }




        /// Indicator

        private MacdHistogram I_MACD;




        /// Properties

        string Chart_Object_Title = "MACD Divergence";

        private DivergenceType HIGH = DivergenceType.High;
        private DivergenceType LOW = DivergenceType.Low;

        private ExtremumActionType for_Update = ExtremumActionType.Update;
        private ExtremumActionType for_New = ExtremumActionType.New;


        /// Data to use in Bot

        private List<Label> High_Extremums = new List<Label>();
        private List<Label> Low_Extremums = new List<Label>();

        public List<Divergence> Data = new List<Divergence>();
        public List<TrendType> Trend = new List<TrendType>();




        /// Models

        public struct Divergence
        {
            public DivergenceType T;
            public Label A;
            public Label B;

            public Divergence(DivergenceType _Type = DivergenceType.None, Label Label_A = new Label(), Label Label_B = new Label())
            {
                T = _Type;
                A = Label_A;
                B = Label_B;
            }

            public string Text
            {
                get { return string.Format("- A -  {0}      - B -  {1}", A.Text, B.Text); }
            }

            public Colors Color
            {
                get
                {
                    switch (T)
                    {
                        case DivergenceType.High:
                            return Colors.SpringGreen;
                            break;
                        case DivergenceType.Low:
                            return Colors.DeepPink;
                            break;
                        default:
                            return Colors.Yellow;
                            break;
                    }
                }
            }
        }

        public struct Label
        {
            public Point MACD;
            public Point MS;

            public Label(Point M1 = new Point(), Point M2 = new Point())
            {
                MACD = M1;
                MS = M2;
            }

            public string Text
            {
                get { return string.Format("MACD = {0}    MS = {1}", MACD.Text, MS.Text); }
            }
        }

        public struct Point
        {
            public int Index;
            public double Value;

            public Point(int I = 0, double V = 0)
            {
                Index = I;
                Value = V;
            }

            public string Text
            {
                get { return string.Format("{0} ({1})", Value.ToString("N6"), Index); }
            }
        }

        public enum ExtremumActionType
        {
            Update,
            New
        }

        public enum DivergenceType
        {
            High,
            Low,
            None
        }

        public enum TrendType
        {
            Up,
            Down,
            None
        }





        /// TODO: Init

        protected override void Initialize()
        {
            I_MACD = Indicators.MacdHistogram(MACD_Short_Cycle, MACD_Long_Cycle, MACD_Signal_Period);
            Print("MACD Divergence Calculator is initialized.     Results = {0}     Data = {1}     Data_Trend = {2}", Result.Count, Data.Count, Trend.Count);
        }




        /// TODO: Indicator

        public override void Calculate(int index)
        {
            /// MACD Calc

            Result[index] = MACD_Reverse ? I_MACD.Histogram[index] - I_MACD.Signal[index] : I_MACD.Signal[index] - I_MACD.Histogram[index];





            /// MACD Divergence

            if (index <= Divergence_Ledge)
                return;



            /// TODO: High Divergence

            Point MACD_Max = Max_MACD(From: index - 1, For_Last_Bars: Divergence_Ledge);
            Point MS_Max = Max_MS(From: index - 1, For_Last_Bars: Divergence_Ledge);

            Label Max = new Label(MACD_Max, MS_Max);


            if (High_Extremums.Count == 0)
            {
                if (Is_Max(L: Max, At: index))
                    Update_Data(Stage: "1 Step: FIRST", _Type: HIGH, New_Extremum: Max, At: index, Action: for_New);

            }
            else
            {
                Label Last = High_Extremums[High_Extremums.Count - 1];

                if (Math.Max(Max.MACD.Index, Max.MS.Index) - Last.MACD.Index <= Divergence_Min_Length)
                {
                    //if (Last.MACD.Value < MACD(index) && Last.MACD.Index == index - 1 && Max.MACD.Index - Last.MACD.Index <= Divergence_Ledge)
                    //{
                    //    Max.MACD.Value = MACD(index);
                    //    Max.MACD.Index = index;
                    //    Update_Data(Stage: "3 Step: update NOW", _Type: HIGH, New_Extremum: Max, At: index, Action: for_Update);
                    //}

                    if (Allow_To_Update_High(L: Last, New: Max, At: index))
                        Update_Data(Stage: "3 Step: update LAST", _Type: HIGH, New_Extremum: Max, At: index, Action: for_Update);
                }
                else if (Is_Next_High_Wave(A: Last, B: Max, At: index))
                    Update_Data(Stage: "4 Step: NEW", _Type: HIGH, New_Extremum: Max, At: index, Action: for_New);

            }






            /// TODO: Low Divergence

            Point MACD_Min = Min_MACD(From: index - 1, For_Last_Bars: Divergence_Ledge);
            Point MS_Min = Min_MS(From: index - 1, For_Last_Bars: Divergence_Ledge);

            Label Min = new Label(MACD_Min, MS_Min);

            if (Low_Extremums.Count == 0)
            {
                if (Is_Min(L: Min, At: index))
                    Update_Data(Stage: "1 Step: FIRST", _Type: LOW, New_Extremum: Min, At: index, Action: for_New);
            }
            else
            {
                Label Last = Low_Extremums[Low_Extremums.Count - 1];

                if (Math.Max(Min.MACD.Index, Min.MS.Index) - Last.MACD.Index <= Divergence_Min_Length)
                {
                    //if (Last.MACD.Value < MACD(index) && Last.MACD.Index == index - 1 && Min.MACD.Index - Last.MACD.Index <= Divergence_Ledge)
                    //{
                    //    Min.MACD.Value = MACD(index);
                    //    Min.MACD.Index = index;
                    //    Update_Data(Stage: "3 Step: update NOW", _Type: LOW, New_Extremum: Min, At: index, Action: for_Update);
                    //}

                    if (Allow_To_Update_Low(L: Last, New: Min, At: index))
                        Update_Data(Stage: "3 Step: update LAST", _Type: LOW, New_Extremum: Min, At: index, Action: for_Update);
                }
                else if (Is_Next_Low_Wave(A: Last, B: Min, At: index))
                    Update_Data(Stage: "4 Step: NEW", _Type: LOW, New_Extremum: Min, At: index, Action: for_New);

            }





            /// Update Trend List

            if (Trend.Count == 0)
                while (Trend.Count < index)
                    Trend.Add(TrendType.None);

            if (Data.Count > 0)
            {
                Divergence D = Data[Data.Count - 1];

                bool T_High = D.T == DivergenceType.High;
                bool T_Low = D.T == DivergenceType.Low;

                TrendType T = T_High ? TrendType.Down : (T_Low ? TrendType.Up : TrendType.None);

                if (Trend.Count < index)
                    Trend.Add(T);
                else if (Trend.Count - 1 == index)
                    Trend[index] = T;
            }
            else
            {
                TrendType T = TrendType.None;

                if (Trend.Count < index)
                    Trend.Add(T);
                else if (Trend.Count - 1 == index)
                    Trend[index] = T;
            }

        }





        /// Methods

        /// Info

        private void Info(string Stage, Label Last, Label Extremum, int At, DivergenceType _Type)
        {
            //if (IsBacktesting)
            //    return;

            Print("{0} - {1} - {2} - {3} - {4} -  Last  {5}  -  Extremum  {6}", At, MarketSeries.OpenTime[At].Date.ToShortDateString(), Data.Count, _Type.ToString(), Stage, Last.Text, Extremum.Text);
        }

        /// Update list Data_Divergence

        private void Update_Data(string Stage, DivergenceType _Type, Label New_Extremum, int At, ExtremumActionType Action)
        {
            if (_Type == HIGH ? High_Extremums.Count > 0 : Low_Extremums.Count > 0)
            {
                Label Previous_Extremum = _Type == HIGH ? High_Extremums[High_Extremums.Count - 1] : Low_Extremums[Low_Extremums.Count - 1];
                Info(Stage: Stage, Last: Previous_Extremum, Extremum: New_Extremum, At: At, _Type: _Type);

                if (Action == for_New)
                    if (_Type == HIGH)
                        High_Extremums.Add(New_Extremum);
                    else if (_Type == LOW)
                        Low_Extremums.Add(New_Extremum);

                Label Last_Extremum = _Type == HIGH ? High_Extremums[High_Extremums.Count - 1] : Low_Extremums[Low_Extremums.Count - 1];

                int N_Extremums = _Type == HIGH ? High_Extremums.Count - 1 : Low_Extremums.Count - 1;

                for (int Index = Math.Max(N_Extremums - Last_Points, 0); Index < N_Extremums; Index++)
                {
                    Label Current_Extremum = _Type == HIGH ? High_Extremums[Index] : Low_Extremums[Index];

                    Divergence Last = new Divergence(_Type: _Type, Label_A: Current_Extremum, Label_B: Last_Extremum);
                    Divergence New = new Divergence(_Type: _Type, Label_A: Current_Extremum, Label_B: New_Extremum);

                    if (No_Obstacles(D: New) && Is_Divergence(D: New))
                    {
                        if (Data.Contains(Last))
                        {
                            int D_Index = Data.IndexOf(Last);
                            Data[D_Index] = New;
                            Info(Stage: "7 Step:  update DATA", Last: Current_Extremum, Extremum: New_Extremum, At: At, _Type: _Type);
                            Draw(D: New, Prefix: D_Index.ToString());

                        }
                        else if (!Data.Exists(D => D.B.MACD.Index == New.B.MACD.Index))
                        {
                            Data.Add(New);
                            Info(Stage: "7 Step:  new DATA", Last: Current_Extremum, Extremum: New_Extremum, At: At, _Type: _Type);
                            Draw(D: New, Prefix: (Data.Count - 1).ToString());
                        }
                    }
                    else if (Data.Contains(Last))
                    {
                        Info(Stage: "7 Step:  remove DATA", Last: Current_Extremum, Extremum: New_Extremum, At: At, _Type: _Type);
                        Remove(D: Last, Prefix: Data.IndexOf(Last).ToString());
                        Data.Remove(Last);
                    }
                }
            }
            else
            {
                if (Action == for_New)
                    if (_Type == HIGH)
                        High_Extremums.Add(New_Extremum);
                    else if (_Type == LOW)
                        Low_Extremums.Add(New_Extremum);
            }

            if (Action == for_Update)
                if (_Type == HIGH)
                    High_Extremums[High_Extremums.Count - 1] = New_Extremum;
                else if (_Type == LOW)
                    Low_Extremums[Low_Extremums.Count - 1] = New_Extremum;
        }


        /// Draw and remove chart objects

        private void Draw(Divergence D, string Prefix)
        {
            //if (IsBacktesting)
            //    return;

            string Name = Prefix + Chart_Object_Title + D.T.ToString() + D.A.MACD.Index.ToString();
            int Index_1 = D.A.MACD.Index;
            int Index_2 = D.B.MACD.Index;
            double Value_1 = D.A.MACD.Value;
            double Value_2 = D.B.MACD.Value;
            Colors Color = D.Color;

            ChartObjects.DrawLine(Name, Index_1, Value_1, Index_2, Value_2, Color);
            ChartObjects.DrawText(Name + "A", "•", Index_1, Value_1, VerticalAlignment.Center, HorizontalAlignment.Center, Color);
            ChartObjects.DrawText(Name + "B", "•", Index_2, Value_2, VerticalAlignment.Center, HorizontalAlignment.Center, Color);

            Info(Stage: "Draw Divergence:", Last: D.A, Extremum: D.B, At: D.A.MACD.Index, _Type: D.T);
        }

        private void Remove(Divergence D, string Prefix)
        {
            //if (IsBacktesting)
            //    return;

            string Name = Prefix + Chart_Object_Title + D.T.ToString() + D.A.MACD.Index.ToString();

            ChartObjects.RemoveObject(Name);
            ChartObjects.RemoveObject(Name + "A");
            ChartObjects.RemoveObject(Name + "B");
        }





        /// Helpers

        private double MACD(int Index)
        {
            return Result[Index];
        }

        private bool Is_Divergence(Divergence D)
        {
            bool T1 = D.A.MACD.Value >= D.B.MACD.Value && D.A.MS.Value < D.B.MS.Value;
            bool T2 = D.A.MACD.Value <= D.B.MACD.Value && D.A.MS.Value > D.B.MS.Value;

            bool T_P = D.T == HIGH ? D.A.MACD.Value > 0 : D.A.MACD.Value < 0;

            return (T1 || T2) && T_P;
        }



        /// Is Max

        private bool Is_Max(Label L, int At)
        {
            return (MACD_Is_Max(P: L.MACD, At: At) && MS_Is_Max(P: L.MS, At: At));
        }

        private bool MACD_Is_Max(Point P, int At)
        {
            return P.Value > 0 && P.Value > MACD(At) && P.Value > MACD(P.Index - 1);
        }

        private bool MS_Is_Max(Point P, int At)
        {
            return P.Value > MS_High(At) && P.Value > MS_High(P.Index - 1);
        }



        /// Is Min

        private bool Is_Min(Label L, int At)
        {
            return (MACD_Is_Min(P: L.MACD, At: At) && MS_Is_Min(P: L.MS, At: At));
        }

        private bool MACD_Is_Min(Point P, int At)
        {
            return P.Value < 0 && P.Value < MACD(At) && P.Value < MACD(P.Index - 1);
        }

        private bool MS_Is_Min(Point P, int At)
        {
            return P.Value < MS_High(At) && P.Value < MS_High(P.Index - 1);
        }




        /// Allow to update

        private bool Allow_To_Update_High(Label L, Label New, int At)
        {
            if (New.MACD.Index == At)
                return false;

            if ((L.MACD.Value < New.MACD.Value && MACD_Is_Max(P: New.MACD, At: At)) || (L.MS.Value < New.MS.Value && MS_Is_Max(P: New.MS, At: At)))
                return true;

            return false;
        }

        private bool Allow_To_Update_Low(Label L, Label New, int At)
        {
            if (New.MACD.Index == At)
                return false;

            if ((L.MACD.Value > New.MACD.Value && MACD_Is_Min(P: New.MACD, At: At)) || (L.MS.Value > New.MS.Value && MS_Is_Min(P: New.MS, At: At)))
                return true;

            return false;
        }



        /// Next Wave

        private bool Is_Next_High_Wave(Label A, Label B, int At)
        {
            bool Was_Lower = MACD_Was_Lower(From: A.MACD.Index, To: B.MACD.Index);

            bool B_MACD_Max = MACD_Is_Max(P: B.MACD, At: At);
            bool B_MS_Max = MS_Is_Max(P: B.MS, At: At);

            bool T1 = A.MACD.Value > 0 && B.MACD.Value > 0 && Was_Lower && B_MACD_Max && B_MS_Max;
            bool T2 = A.MACD.Value < 0 && B.MACD.Value > 0 && Was_Lower && B_MACD_Max && B_MS_Max;
            bool T3 = A.MACD.Value > 0 && B.MACD.Value < 0 && A.MS.Value < B.MS.Value && B_MS_Max && MACD(Index: B.MS.Index) < 0;

            return (T1 || T2 || T3);
        }

        private bool Is_Next_Low_Wave(Label A, Label B, int At)
        {
            bool Was_Higher = MACD_Was_Higher(From: A.MACD.Index, To: B.MACD.Index);

            bool B_MACD_Min = MACD_Is_Min(P: B.MACD, At: At);
            bool B_MS_Min = MS_Is_Min(P: B.MS, At: At);

            bool T1 = A.MACD.Value < 0 && B.MACD.Value < 0 && Was_Higher && B_MACD_Min && B_MS_Min;
            bool T2 = A.MACD.Value > 0 && B.MACD.Value < 0 && Was_Higher && B_MACD_Min && B_MS_Min;
            bool T3 = A.MACD.Value < 0 && B.MACD.Value > 0 && A.MS.Value > B.MS.Value && B_MS_Min && MACD(Index: B.MS.Index) > 0;

            return (T1 || T2 || T3);
        }



        /// Нет препятсвий

        private bool No_Obstacles(Divergence D)
        {
            bool T_MACD = D.T == HIGH ? MACD_Was_Not_Higher(D: D) : MACD_Was_Not_Lower(D: D);
            bool T_MS = D.T == HIGH ? MS_Was_Not_Higher(D: D) : MS_Was_Not_Lower(D: D);


            //Info(Stage: string.Format("No O:  MACD = {0}  MS = {1}", T_MACD, T_MS), D: D, At: D.B.MACD.Index);

            return (T_MACD && T_MS);
        }




        /// MS Not higher or lower than

        private bool MACD_Was_Not_Higher(Divergence D)
        {
            return MACD_Was_Not_Higher(From: D.A.MACD.Index, To: D.B.MACD.Index, Value: Math.Max(D.A.MACD.Value, D.B.MACD.Value));
        }

        private bool MACD_Was_Not_Lower(Divergence D)
        {
            return MACD_Was_Not_Lower(From: D.A.MACD.Index, To: D.B.MACD.Index, Value: Math.Min(D.A.MACD.Value, D.B.MACD.Value));
        }

        private bool MACD_Was_Not_Higher(int From, int To, double Value)
        {
            if (From + 1 > To)
                return false;

            for (int Index = From + 1; Index < To; Index++)
                if (MACD(Index) > Value)
                    return false;

            return true;
        }

        private bool MACD_Was_Not_Lower(int From, int To, double Value)
        {
            if (From + 1 > To)
                return false;

            for (int Index = From + 1; Index < To; Index++)
                if (MACD(Index) < Value)
                    return false;

            return true;
        }



        /// MACD: was lower or higher 2 points

        private bool MACD_Was_Lower_Zero(int From, int To)
        {
            if (From > To)
                return false;

            for (int Index = From + 1; Index < To; Index++)
                if (MACD(Index) < 0)
                    return true;

            return false;
        }

        private bool MACD_Was_Lower(int From, int To)
        {
            if (From + 1 > To)
                return false;

            double From_Value = MACD(From);
            double To_Value = MACD(To);

            for (int Index = From + 1; Index < To; Index++)
                if (MACD(Index) < From_Value && MACD(Index) < To_Value)
                    return true;

            return false;
        }




        /// MACD: was higher or lower 0

        private bool MACD_Was_Higher_Zero(int From, int To)
        {
            if (From > To)
                return false;

            for (int Index = From + 1; Index < To; Index++)
                if (MACD(Index) > 0)
                    return true;

            return false;
        }

        private bool MACD_Was_Higher(int From, int To)
        {
            if (From + 1 > To)
                return false;

            double From_Value = MACD(From);
            double To_Value = MACD(To);

            for (int Index = From + 1; Index < To; Index++)
                if (MACD(Index) > From_Value && MACD(Index) > To_Value)
                    return true;

            return false;
        }



        // MS: high & low

        private double MS_High(int Index)
        {
            return Divergence_Extremums ? MarketSeries.High[Index] : MarketSeries.Close[Index];
        }

        private double MS_Low(int Index)
        {
            return Divergence_Extremums ? MarketSeries.Low[Index] : MarketSeries.Close[Index];
        }




        /// MS Not higher or lower than

        private bool MS_Was_Not_Higher(Divergence D)
        {
            return MS_Was_Not_Higher(From: D.A.MS.Index, To: D.B.MS.Index, Value: Math.Max(D.A.MS.Value, D.B.MS.Value));
        }

        private bool MS_Was_Not_Lower(Divergence D)
        {
            return MS_Was_Not_Lower(From: D.A.MS.Index, To: D.B.MS.Index, Value: Math.Min(D.A.MS.Value, D.B.MS.Value));
        }

        private bool MS_Was_Not_Higher(int From, int To, double Value)
        {
            if (From + 1 > To)
                return false;

            for (int Index = From + 1; Index < To; Index++)
                if (MS_High(Index) > Value)
                    return false;

            return true;
        }

        private bool MS_Was_Not_Lower(int From, int To, double Value)
        {
            if (From + 1 > To)
                return false;

            for (int Index = From + 1; Index < To; Index++)
                if (MS_Low(Index) < Value)
                    return false;

            return true;
        }




        /// MS: max & min points 

        private Point Max_MS(int From, int For_Last_Bars)
        {
            int Index = From;
            double Value = MS_High(Index);

            for (int Bar = 1; Bar <= For_Last_Bars; Bar++)
            {
                int New_Index = From - Bar;
                double New_Value = MS_High(New_Index);

                if (New_Value > Value)
                {
                    Value = New_Value;
                    Index = New_Index;
                }
            }

            return new Point(Index, Value);
        }

        private Point Min_MS(int From, int For_Last_Bars)
        {
            int Index = From;
            double Value = MS_Low(Index);

            for (int Bar = 1; Bar <= For_Last_Bars; Bar++)
            {
                int New_Index = From - Bar;
                double New_Value = MS_Low(New_Index);

                if (New_Value < Value)
                {
                    Value = New_Value;
                    Index = New_Index;
                }
            }

            return new Point(Index, Value);
        }




        /// MACD: max & min points

        private Point Max_MACD(int From, int For_Last_Bars)
        {
            int Index = From;
            double Value = MACD(Index);

            for (int Bar = 1; Bar <= For_Last_Bars; Bar++)
            {
                int New_Index = From - Bar;
                double New_Value = MACD(New_Index);

                if (New_Value < 0)
                    return new Point(Index, Value);

                if (New_Value > Value)
                {
                    Value = New_Value;
                    Index = New_Index;
                }
            }

            return new Point(Index, Value);
        }

        private Point Min_MACD(int From, int For_Last_Bars)
        {
            int Index = From;
            double Value = MACD(Index);

            for (int Bar = 1; Bar <= For_Last_Bars; Bar++)
            {
                int New_Index = From - Bar;
                double New_Value = MACD(New_Index);

                if (New_Value > 0)
                    return new Point(Index, Value);

                if (New_Value < Value)
                {
                    Value = New_Value;
                    Index = New_Index;
                }
            }
            return new Point(Index, Value);
        }
    }
}

 


@daniel.agg

daniel.agg
07 Mar 2019, 21:51

Sorry, seems like the link to the source code is broken. Reuploaded:
https://drive.google.com/file/d/1CuMe7hKGLAK3XJW0HDQ9RucmDDiEps0S/view?usp=sharing


@daniel.agg