solve line slope issue?

Created at 07 Jul 2024, 09:11
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!
TU

tuuguu177

Joined 22.05.2024

solve line slope issue?
07 Jul 2024, 09:11


Hello developers could you please help at my indicator? I am moving from MT5 to Ctrader. I use regression line for my trading. 

First code is working correctly but regression line slope is different from code at MT5. I really want to make first code's calculation of regression same as calculation of indicator of MT5. Please help. The second code is the code which I tried to make correct calculation of regression. But the second code can not draw regression lines.

The third code is the correct calculation of regression line of MT5 indicator. Please help

first code:

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

#pragma warning disable

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class LinearRegressionChannel : Indicator
    {
        [Parameter("Projection Length", DefaultValue = 0)]
        public int ProjLength { get; set; }

        [Parameter("Center", DefaultValue = true)]
        public bool ShowCenter { get; set; }

        [Parameter("Channel", DefaultValue = true)]
        public bool ShowChannel { get; set; }

        [Parameter("Standard deviation", DefaultValue = true)]
        public bool ShowDeviantion { get; set; }

        public Dictionary<string, LR> LRs = new Dictionary<string, LR>();

        protected override void Initialize()
        {
            ///Add the button in the topleft corner
            Border border = new Border 
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Right,
                Margin = "20 40 20 20",
                Width = 50,
                Child = new Toolbar(this)
            };

            Chart.AddControl(border);

            ///Events for calculating and drawing
            Chart.ObjectUpdated += OnChartObjectUpdated;
            Chart.ObjectRemoved += OnChartObjectRemoved;

            foreach (ChartObject o in Chart.Objects)
                if (o.Name.Length > 24 && o.Name.Substring(0, 24) == "LinearRegressionChannel " && o.IsInteractive && o.ObjectType == ChartObjectType.TrendLine)
                {
                    LRs.Add(o.Name, new LR((ChartTrendLine)o));
                    o.IsInteractive = false;
                    o.IsInteractive = true;
                }
        }

        void OnChartObjectRemoved(ChartObjectRemovedEventArgs obj)
        {
            try
            {
                if (IsCleaning)
                    return;
                RemoveAllObjectsConnectedWith(obj.ChartObject);
                if (LRs.ContainsKey(obj.ChartObject.Name))
                    LRs.Remove(obj.ChartObject.Name);
            } catch (Exception e)
            {
                Print(e);
                Print("Errore nella rimozione dell'oggetto");
            }
        }

        bool IsCleaning = false;

        void RemoveAllObjectsConnectedWith(ChartObject o)
        {
            if (LRs.ContainsKey(o.Name))
            {
                IsCleaning = true;
                for (int i = 0; i < LRs[o.Name].Children.Count; ++i)
                {
                    try
                    {
                        Chart.RemoveObject(LRs[o.Name].Children[i].Name);
                    } catch (Exception e)
                    {
                        Print(e);
                        continue;
                    }
                }
            }
            LRs[o.Name].Children.Clear();
            IsCleaning = false;
        }


        public override void Calculate(int index)
        {
        }

        void OnChartObjectUpdated(ChartObjectUpdatedEventArgs obj)
        {
            try
            {
                RemoveAllObjectsConnectedWith(obj.ChartObject);
                ///Check if object is a rectangle and if it's part of this indicator
                if (!LRs.ContainsKey(obj.ChartObject.Name))
                    return;

                ChartTrendLine lr = (ChartTrendLine)obj.ChartObject;

                // Linear regresion
                double sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0, x_avg=0, x=0,x_sum_squared=0,stdDeviation=0;

                int start = Bars.OpenTimes.GetIndexByTime(lr.Time1);
                int end = Bars.OpenTimes.GetIndexByTime(lr.Time2);

                int length = Math.Abs(end - start);

                if (start > end)
                {
                    start = Bars.OpenTimes.GetIndexByTime(lr.Time2);
                    end = Bars.OpenTimes.GetIndexByTime(lr.Time1);
                }

                for (int i = start; i < end; i++)
                {
                    sum_x += 1.0 * i;
                    sum_x2 += 1.0 * i * i;
                    sum_y += Bars[i].Close;
                    sum_xy += Bars[i].Close * i;
                }

                double a = (length * sum_xy - sum_x * sum_y) / (length * sum_x2 - sum_x * sum_x);
                double b = (sum_y - a * sum_x) / length;

                // Calculate maximum and standard devaitions

                double maxUpperDeviation = 0, maxLowerDeviation = 0;
                double sumDevation = 0;

                for (int i = start; i < end; i++)
                {
                    double price = a * i + b;
                    x = Math.Abs(Bars[i].Close - price);
                    x_avg=(x_avg+x)/i;
                    x_sum_squared += (x - x_avg) * (x - x_avg);
                    maxUpperDeviation = Math.Max(Bars[i].Close - price, maxUpperDeviation);
                    maxLowerDeviation = Math.Min(Bars[i].Close - price, maxLowerDeviation);
                    stdDeviation=Math.Sqrt(x_sum_squared/(length - 1));
                    
                }

                //double stdDeviation = Math.Sqrt(sumDevation / (length - 1));

                // draw in future
                end += (int)(length * 0.01 * ProjLength);

                double pr1 = a * start + b;
                double pr2 = a * end + b;

                if (ShowCenter)
                {
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Center " + lr.Name, start, pr1, end, pr2, Color.Blue, 1, LineStyle.DotsRare));
                }

                if (ShowChannel)
                {
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Top " + lr.Name, start, pr1 + stdDeviation*2, end, pr2 + stdDeviation*2, Color.Blue, 1, LineStyle.DotsRare));
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Bottom " + lr.Name, start, pr1 - stdDeviation*2, end, pr2 - stdDeviation*2, Color.Blue, 1, LineStyle.DotsRare));
                }

                if (ShowDeviantion)
                {
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Dev-Top " + lr.Name, start, pr1 + stdDeviation, end, pr2 + stdDeviation, Color.Blue, 1, LineStyle.DotsRare));
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Dev-Bottom " + lr.Name, start, pr1 - stdDeviation, end, pr2 - stdDeviation, Color.Blue, 1, LineStyle.DotsRare));
                }
            } catch (Exception)
            {
            }
        }
    }

    public class Toolbar : CustomControl
    {
        LinearRegressionChannel LR;

        public Toolbar(LinearRegressionChannel lr)
        {
            LR = lr;
            var AddButton = new Button 
            {
                Text = "Add",
                Style = new Style(DefaultStyles.ButtonStyle),
                Height = 25
            };

            AddButton.Click += AddArea;

            AddChild(AddButton);
        }

        void AddArea(ButtonClickEventArgs e)
        {
            double Y = (LR.Chart.TopY - LR.Chart.BottomY) * 0.6 + LR.Chart.BottomY;
            string name = "LinearRegressionChannel " + LR.Time;
            LR.LRs.Add(name, new LR(LR.Chart.DrawTrendLine(name, LR.Chart.LastVisibleBarIndex - 2, Y, (int)(LR.Chart.LastVisibleBarIndex - (LR.Chart.LastVisibleBarIndex - LR.Chart.FirstVisibleBarIndex) * 0.2), Y, Color.DarkSlateGray)));
            LR.LRs[name].Parent.IsInteractive = true;
        }
    }

    public class LR
    {
        public ChartTrendLine Parent;
        public List<ChartTrendLine> Children = new List<ChartTrendLine>();

        public LR(ChartTrendLine cr)
        {
            Parent = cr;
        }
    }
}

second code:

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

#pragma warning disable

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class LinearRegressionChannel2 : Indicator
    {
        [Parameter("Projection Length", DefaultValue = 50)]
        public int ProjLength { get; set; }

        [Parameter("Center", DefaultValue = true)]
        public bool ShowCenter { get; set; }

        [Parameter("Channel", DefaultValue = true)]
        public bool ShowChannel { get; set; }

        [Parameter("Standard deviation", DefaultValue = true)]
        public bool ShowDeviantion { get; set; }

        public Dictionary<string, LR> LRs = new Dictionary<string, LR>();

        protected override void Initialize()
        {
            ///Add the button in the topleft corner
            Border border = new Border 
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Right,
                Margin = "20 40 20 20",
                Width = 50,
                Child = new Toolbar(this)
            };

            Chart.AddControl(border);

            ///Events for calculating and drawing
            Chart.ObjectUpdated += OnChartObjectUpdated;
            Chart.ObjectRemoved += OnChartObjectRemoved;

            foreach (ChartObject o in Chart.Objects)
                if (o.Name.Length > 24 && o.Name.Substring(0, 24) == "LinearRegressionChannel2 " && o.IsInteractive && o.ObjectType == ChartObjectType.TrendLine)
                {
                    LRs.Add(o.Name, new LR((ChartTrendLine)o));
                    o.IsInteractive = false;
                    o.IsInteractive = true;
                }
        }

        void OnChartObjectRemoved(ChartObjectRemovedEventArgs obj)
        {
            try
            {
                if (IsCleaning)
                    return;
                RemoveAllObjectsConnectedWith(obj.ChartObject);
                if (LRs.ContainsKey(obj.ChartObject.Name))
                    LRs.Remove(obj.ChartObject.Name);
            } catch (Exception e)
            {
                Print(e);
                Print("Errore nella rimozione dell'oggetto");
            }
        }

        bool IsCleaning = false;

        void RemoveAllObjectsConnectedWith(ChartObject o)
        {
            if (LRs.ContainsKey(o.Name))
            {
                IsCleaning = true;
                for (int i = 0; i < LRs[o.Name].Children.Count; ++i)
                {
                    try
                    {
                        Chart.RemoveObject(LRs[o.Name].Children[i].Name);
                    } catch (Exception e)
                    {
                        Print(e);
                        continue;
                    }
                }
            }
            LRs[o.Name].Children.Clear();
            IsCleaning = false;
        }


        public override void Calculate(int index)
        {
        }

        void OnChartObjectUpdated(ChartObjectUpdatedEventArgs obj)
        {
            try
            {
                RemoveAllObjectsConnectedWith(obj.ChartObject);
                ///Check if object is a rectangle and if it's part of this indicator
                if (!LRs.ContainsKey(obj.ChartObject.Name))
                    return;

                ChartTrendLine lr = (ChartTrendLine)obj.ChartObject;

                // Linear regresion
                double sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0, x=0, x_avg=0, x_sum_squared=0, stdDeviation=0;

                int start = Bars.OpenTimes.GetIndexByTime(lr.Time1);
                int end = Bars.OpenTimes.GetIndexByTime(lr.Time2);

                //int length = Math.Abs(end - start) + 1;
                int length = (end - start)+1;
                int n = end - start;
                if (start > end)
                {
                    start = Bars.OpenTimes.GetIndexByTime(lr.Time2);
                    end = Bars.OpenTimes.GetIndexByTime(lr.Time1);
                }

                for (int i = 1; i < n; i++)
                {
                    sum_x += 1.0 * i;
                    sum_x2 += 1.0 * i * i;
                    sum_y += Bars[i].Close;
                    sum_xy += Bars[i].Close * i;
                }

                double a = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x);
                //double b = (sum_y - a * sum_x) / length;
                double b = (sum_y - a * sum_x) / n;

                // Calculate maximum and standard devaitions

                double maxUpperDeviation = 0, maxLowerDeviation = 0;
                double sumDevation = 0;

                for (int i = start; i < end; i++)
                {
                    double price = a * i + b;
                    x = Math.Abs(Bars[i].Close - price);
                    if (i>0)
                    {
                        x_avg=(x_avg + x) / i;
                        x_sum_squared += (x - x_avg) * (x - x_avg);
                        stdDeviation = Math.Sqrt(x_sum_squared / (n - 1));
                    }
                    //maxUpperDeviation = Math.Max(Bars[i].Close - price, maxUpperDeviation);
                    //maxLowerDeviation = Math.Min(Bars[i].Close - price, maxLowerDeviation);
                    //sumDevation += Math.Pow(Bars[i].Close - price, 2.0);
                }

                //double stdDeviation = Math.Sqrt(sumDevation / n - 1);                                
                
                // draw in future
                end += (int)(length * 0.01 * ProjLength);

                //double pr1 = a * start + b;
                //double pr2 = a * end + b;
                
                double pr1 = b + a * (n);
                double pr2 = b;
                Print(pr1);
                
                if (ShowCenter)
                {
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Center " + lr.Name, start, pr1, end, pr2, Color.Blue,1,LineStyle.DotsRare));
                }

                if (ShowChannel)
                {
                    //LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Top " + lr.Name, start, pr1 + maxUpperDeviation, end, pr2 + maxUpperDeviation, lr.Color));
                    //LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Bottom " + lr.Name, start, pr1 + maxLowerDeviation, end, pr2 + maxLowerDeviation, lr.Color));
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Top " + lr.Name, start, pr1 + (stdDeviation*2), end, pr2 + (stdDeviation*2), Color.Blue,1,LineStyle.DotsRare));
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Bottom " + lr.Name, start, pr1 - (stdDeviation*2), end, pr2 - (stdDeviation*2), Color.Blue,1,LineStyle.DotsRare));
                }

                if (ShowDeviantion)
                {
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Dev-Top " + lr.Name, start, pr1 + stdDeviation, end, pr2 + stdDeviation, Color.Blue, 1, LineStyle.DotsRare));
                    LRs[lr.Name].Children.Add(Chart.DrawTrendLine("Dev-Bottom " + lr.Name, start, pr1 - stdDeviation, end, pr2 - stdDeviation, Color.Blue, 1, LineStyle.DotsRare));
                }
            } catch (Exception)
            {
            }
        }
    }

    public class Toolbar : CustomControl
    {
        LinearRegressionChannel2 LR;

        public Toolbar(LinearRegressionChannel2 lr)
        {
            LR = lr;
            var AddButton = new Button 
            {
                Text = "Add",
                Style = new Style(DefaultStyles.ButtonStyle),
                Height = 25
            };

            AddButton.Click += AddArea;

            AddChild(AddButton);
        }

        void AddArea(ButtonClickEventArgs e)
        {
            double Y = (LR.Chart.TopY - LR.Chart.BottomY) * 0.6 + LR.Chart.BottomY;
            string name = "LinearRegressionChannel2 " + LR.Time;
            LR.LRs.Add(name, new LR(LR.Chart.DrawTrendLine(name, LR.Chart.LastVisibleBarIndex - 2, Y, (int)(LR.Chart.LastVisibleBarIndex - (LR.Chart.LastVisibleBarIndex - LR.Chart.FirstVisibleBarIndex) * 0.2), Y, Color.DarkSlateGray)));
            LR.LRs[name].Parent.IsInteractive = true;
        }
    }

    public class LR
    {
        public ChartTrendLine Parent;
        public List<ChartTrendLine> Children = new List<ChartTrendLine>();

        public LR(ChartTrendLine cr)
        {
            Parent = cr;
        }
    }
}

third code:

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])
{
 
    if(IsNewBar()){
      Print("shine bar shuu",i);
      int LR_length = LR_length+i;
      int end_bar = end_bar+i;
      int start_bar=start_bar +i;
      Print("LR_length=",LR_length);
      i=i+1;
      
      //LR_length = LR_length + i;
      //end_bar = end_bar + i;       
       //---- declarations of local variables 
       double value, a, b, c, sumy, sumx, sumxy, sumx2, iClose[];
       datetime iTime[], start_time, end_time;
   
       //--- copy newly appeared data in the arrays
       if (CopyClose(NULL, period, 0, to_copy, iClose) <= 0)
           return (RESET);
       if (CopyTime(NULL, period, 0, to_copy, iTime) <= 0)
           return (RESET);
   
       //---- indexing elements in arrays as time series  
       ArraySetAsSeries(iClose, true);
       ArraySetAsSeries(iTime, true);
       
       Print("LR_length",LR_length);
       Print("end_bar",end_bar);
       Print("start_bar",start_bar);  
       
       start_time = iTime[start_bar];
       end_time = iTime[end_bar];
       Print("end_time",end_time);
       Print("start_time",start_time);  
   
       value = iClose[end_bar];
       sumy = value;
       sumx = 0.0;
       sumxy = 0.0;
       sumx2 = 0.0;
   
       for (int iii = 1; iii < n2; iii++)
       {
           value = iClose[end_bar+iii];
           sumy += value;
           sumxy += value * iii;
           sumx += iii;
           sumx2 += iii * iii;
       }
   
       c = sumx2 * n2 - sumx * sumx;
       if (!c)
           return (rates_total);
   
       b = (sumxy * n2 - sumx * sumy) / c;
       a = (sumy - sumx * b) / n2;
   
       double LR_price_2 = a;
       double LR_price_1 = a + b * n2;
   
       //---- maximal deviation calculation (not used)
       double max_dev = 0;
       double deviation = 0;
       double dvalue = a;
   
       for (int iii = 0; iii < n; iii++)
       {
           value = iClose[end_bar + iii];
           dvalue += b;
           deviation = MathAbs(value - dvalue);
           if (max_dev <= deviation)
               max_dev = deviation;
       }
   
       //---- Linear regression trendline    
       SetTline(0, LR_name, 0, start_time, LR_price_1, end_time, LR_price_2, clr_tline, LR_style, LR_width, LR_name);
   
       //---- ...standard deviation...
       double x = 0, x_sum = 0, x_avg = 0, x_sum_squared = 0, std_dev = 0, price1, price2;
   
       for (int iii = end_bar; iii < start_bar; iii++)
       {
           x = MathAbs(iClose[iii] - ObjectGetValueByTime(0, LR_name, iTime[iii], 0));
           x_sum += x;
   
           if (iii > 0)
           {
               x_avg = (x_avg + x) / iii;
               x_sum_squared += (x - x_avg) * (x - x_avg);
               std_dev = MathSqrt(x_sum_squared / (n2-1));
           }
       }
   
       //---- ...standard deviation channels...
       price1 = LR_price_1 + std_dev * std_channel_1;
       price2 = LR_price_2 + std_dev * std_channel_1;
       SetTline(0, CH1P_name, 0, start_time, price1, end_time, price2, clr_tline, style_1, width_1, CH1P_name);
   
       price1 = LR_price_1 - std_dev * std_channel_1;
       price2 = LR_price_2 - std_dev * std_channel_1;
       SetTline(0, CH1M_name, 0, start_time, price1, end_time, price2, clr_tline, style_1, width_1, CH1M_name);
       //----   
       price1 = LR_price_1 + std_dev * std_channel_2;
       price2 = LR_price_2 + std_dev * std_channel_2;
       SetTline(0, CH2P_name, 0, start_time, price1, end_time, price2, clr_tline, style_2, width_2, CH2P_name);
   
       price1 = LR_price_1 - std_dev * std_channel_2;
       price2 = LR_price_2 - std_dev * std_channel_2;
       SetTline(0, CH2M_name, 0, start_time, price1, end_time, price2, clr_tline, style_2, width_2, CH2M_name);
       //----  
       //price1 = LR_price_1 + std_dev * std_channel_3;
       //price2 = LR_price_2 + std_dev * std_channel_3;
       //SetTline(0, CH3P_name, 0, start_time, price1, end_time, price2, c_3, style_3, width_3, CH3P_name);
   
       //price1 = LR_price_1 - std_dev * std_channel_3;
       //price2 = LR_price_2 - std_dev * std_channel_3;
       //SetTline(0, CH3M_name, 0, start_time, price1, end_time, price2, c_3, style_3, width_3, CH3M_name);
       //----   
       }
       return (rates_total);
       

}

@tuuguu177
Replies

tuuguu177
07 Jul 2024, 12:12

is there anyone to help?


@tuuguu177

firemyst
07 Jul 2024, 12:56 ( Updated at: 07 Jul 2024, 16:00 )

Have you tried looking at the code to any indicators that are already available?

https://ctrader.com/algos/search/indicators?query=linear+regression+channel

 

 


@firemyst

tuuguu177
07 Jul 2024, 16:07 ( Updated at: 08 Jul 2024, 04:51 )

RE: solve line slope issue?

firemyst said: 

Have you tried looking at the code to any indicators that are already available?

https://ctrader.com/algos/search/indicators?query=linear+regression+channel

 

 

Hello, yes of course. I modified one of them. Code looks like big. Do not worry

It has little slope coefficient calculation problem on it. I can not find it.

I attached picture of modified indicator.

Thank you

 


@tuuguu177