solve line slope issue?
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);
}
Replies
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
tuuguu177
07 Jul 2024, 12:12
is there anyone to help?
@tuuguu177