LSMA_Channelv2_v1
Download scriptThis script is designed to create a visual Regression Channel on your trading chart. Rather than just following the price point-by-point, it uses mathematical modeling to determine the overall trend and volatility of an asset over a specific period.
Here is a breakdown of how the logic works:
Core Trend Calculation
The script looks at a set number of past bars (defined by the user) and performs a statistical calculation known as "Least Squares Regression."
In simple terms, it treats the price movement like a series of dots on a graph and attempts to draw the straightest possible line that passes through the middle of those dots. This line represents the "fair value" or the primary direction of the trend:
- The Slope: Determines how steeply the price is rising or falling.
- The Intercept: Establishes where that trend sits relative to the current price.
The script then draws this main regression line on your chart, providing a clear visual of the underlying momentum.
Volatility and Boundaries (The Channels)
Beyond just finding the middle trend, the script calculates Standard Deviation. This is a measure of how much the price "wiggles" or deviates away from that center regression line. By understanding this deviation, the script creates three distinct zones:
- Inside Zone: These are the tightest boundaries. They represent the area where the price most commonly fluctuates. When the price stays within these lines, it is following the normal expected behavior of the current trend.
- Outside Zone: These wider boundaries capture more significant price swings. They help identify when the market is moving with more intensity but may still be within a recognizable trend.
- Outside 2 Zone: This is the widest boundary provided by the script. It acts as an "extreme" limit. When the price pushes toward or beyond these lines, it often indicates that the asset is becoming overextended—potentially signaling that the current move is reaching its limit and a reversal or significant correction might occur.
User Customization
The logic allows you to choose which price data the script uses as its "foundation." You can set it to analyze:
- Closing Prices: The standard price at the end of a candle.
- Low Prices: The lowest point reached during a period.
- High Prices: The highest peak reached during a period.
Summary of Behavior
Essentially, this script acts as a dynamic "tunnel" for price action. The center line tells you which way the wind is blowing (the trend), while the various colored boundaries tell you how far that wind is pushing the price. It allows traders to see at a glance whether the current price action is "normal" (Inside), "active" (Outside), or "extreme" (Outside 2).
//+------------------------------------------------------------------+
//| LSMA_Channel.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net/"
#property indicator_chart_window
//---- indicator parameters
extern int IdNum = 1;
extern int RPeriod = 28;
extern color MidColor = Red;
extern int LineWeight = 1;
extern int PriceVal = 0; // 0 = Close, 1 = Low, 2 = High
extern double StDevOutside2 = 2.55;
extern color Outside2 = Red;
extern double StDevOutside = 1.618;
extern color Outside = Brown;
extern double StDevInside = 0.809;
extern color Inside = Green;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
ObjectCreate("Reg_line"+IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_line"+IdNum, OBJPROP_COLOR, MidColor);
ObjectSet("Reg_line"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_line"+IdNum, OBJPROP_WIDTH, LineWeight);
ObjectCreate("Reg_Outside_upper" +IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_COLOR, Outside);
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_WIDTH, LineWeight);
ObjectCreate("Reg_Outside_lower" +IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_COLOR, Outside);
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_WIDTH, LineWeight);
ObjectCreate("Reg_Inside_upper" +IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_COLOR, Inside);
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_WIDTH, LineWeight);
ObjectCreate("Reg_Inside_lower" +IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_COLOR, Inside);
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_WIDTH, LineWeight);
ObjectCreate("Reg_Outside2_upper" +IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_COLOR, Outside2);
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_WIDTH, LineWeight);
ObjectCreate("Reg_Outside2_lower" +IdNum, OBJ_TREND, 0, 0,0, 0,0);
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_COLOR, Outside2);
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_WIDTH, LineWeight);
Comment("Regression channel");
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
void deinit() {
ObjectDelete("Reg_line"+IdNum);
ObjectDelete("Reg_Outside_upper" +IdNum);
ObjectDelete("Reg_Outside_lower" +IdNum);
ObjectDelete("Reg_Inside_upper" +IdNum);
ObjectDelete("Reg_Inside_lower" +IdNum);
ObjectDelete("Reg_Outside2_upper" +IdNum);
ObjectDelete("Reg_Outside2_lower" +IdNum);
Comment("");
}
//+------------------------------------------------------------------+
//| Regression Line |
//+------------------------------------------------------------------+
int start()
{
double y1,y2, price;
double sum_xy, sum_x, sum_y, sum_x2, a, b;
double stddiv, tmp_div;
double x_n_upOut, x_1_upOut, x_n_downOut, x_1_downOut;
double x2_n_upOut, x2_1_upOut, x2_n_downOut, x2_1_downOut;
double x_n_upIn, x_1_upIn, x_n_downIn, x_1_downIn;
int x, n;
//----
if(Bars<=RPeriod) return(0);
// Initialize summations
sum_xy = 0;
sum_x = 0;
sum_y = 0;
sum_x2 = 0;
a = 0;
b = 0;
y1 = 0;
y2 = 0;
tmp_div = 0;
n = RPeriod;
// Calculate sums
for(x=RPeriod;x>0;x--)
{
switch (PriceVal)
{
case 0: price = Close[x];
break;
case 1: price = Low[x];
break;
case 2: price = High[x];
break;
}
sum_xy = sum_xy + x*price;
sum_x = sum_x + x;
sum_y = sum_y + price;
sum_x2 = sum_x2 + x*x;
}
// Calculate slope b and intercept a
b = (n*sum_xy - sum_x*sum_y)/(n*sum_x2 - sum_x*sum_x);
a = (sum_y - b*sum_x)/n;
// Calculate endpoints for least squares line
y1 = a + b*n;
y2 = a + b;
// Plot the line
ObjectSet("Reg_line"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_line"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_line"+IdNum, OBJPROP_PRICE1, y1);
ObjectSet("Reg_line"+IdNum, OBJPROP_PRICE2, y2);
// Calculate the standard deviations of the line
for (x=RPeriod; x>0; x--) {
switch (PriceVal)
{
case 0: price = Close[x];
break;
case 1: price = Low[x];
break;
case 2: price = High[x];
break;
}
tmp_div = tmp_div + (price - (a + b*x))*(price - (a + b*x));
}
stddiv = MathSqrt(tmp_div/n);
x_n_upOut = y1 + StDevOutside*stddiv;
x_1_upOut = y2 + StDevOutside*stddiv;
x_n_downOut = y1 - StDevOutside*stddiv;
x_1_downOut = y2 - StDevOutside*stddiv;
x_n_upIn = y1 + StDevInside*stddiv;
x_1_upIn = y2 + StDevInside*stddiv;
x_n_downIn = y1 - StDevInside*stddiv;
x_1_downIn = y2 - StDevInside*stddiv;
x2_n_upOut = y1 + StDevOutside2*stddiv;
x2_1_upOut = y2 + StDevOutside2*stddiv;
x2_n_downOut = y1 - StDevOutside2*stddiv;
x2_1_downOut = y2 - StDevOutside2*stddiv;
// Plot the standard deviation lines
// OUTSIDE
//upper
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_PRICE1, x_n_upOut);
ObjectSet("Reg_Outside_upper"+IdNum, OBJPROP_PRICE2, x_1_upOut);
//lower
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_PRICE1, x_n_downOut);
ObjectSet("Reg_Outside_lower"+IdNum, OBJPROP_PRICE2, x_1_downOut);
// OUTSIDE2
//upper
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_PRICE1, x2_n_upOut);
ObjectSet("Reg_Outside2_upper"+IdNum, OBJPROP_PRICE2, x2_1_upOut);
//lower
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_PRICE1, x2_n_downOut);
ObjectSet("Reg_Outside2_lower"+IdNum, OBJPROP_PRICE2, x2_1_downOut);
//INSIDE
//upper
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_PRICE1, x_n_upIn);
ObjectSet("Reg_Inside_upper"+IdNum, OBJPROP_PRICE2, x_1_upIn);
//lower
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_TIME1, Time[RPeriod]);
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_TIME2, Time[0]);
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_PRICE1, x_n_downIn);
ObjectSet("Reg_Inside_lower"+IdNum, OBJPROP_PRICE2, x_1_downIn);
return(0);
}
//+------------------------------------------------------------------+
Comments