JB Center of Gravity
Download scriptThe JB Center of Gravity is a sophisticated technical analysis tool designed to identify the "true" equilibrium point of price action by applying advanced mathematical modeling to historical data. Unlike simple moving averages that give equal weight to all recent prices, this script seeks to find the underlying structural trend of the market.
Core Logic and Methodology
The indicator operates through a multi-stage process to filter out market noise and determine where the "center" of price movement actually lies:
1. Data Accumulation & Weighting
The script looks back over a specific period of historical data (defined by the bars_back parameter). Instead of just looking at the current price, it calculates various sums of these historical prices. It creates a matrix of values that represents how price behaves relative to time, preparing the data for complex polynomial analysis.
2. Polynomial Regression Modeling The heart of this script lies in its use of Gaussian elimination—a mathematical method used to solve systems of linear equations. The logic works as follows:
- It treats the relationship between time and price as a mathematical curve (a polynomial).
- By constructing a matrix of historical data, it attempts to "fit" a smooth curve that passes as close as possible to all the actual price points within the look-back period.
- This allows the indicator to ignore temporary spikes or "wicks" and focus on the underlying path the market is taking.
3. Determining the Center of Gravity Once the mathematical curve is established, the script calculates the primary trend line (the "Center of Gravity"). This represents the most probable path of price movement based on the weighted historical data. It essentially answers the question: "If we remove all the noise, where is the balance point of this price action?"
4. Dynamic Volatility Bands To provide a visual sense of market stability, the script calculates two types of deviation bands around the Center of Gravity:
- Standard Deviation Bands: These use a standard statistical approach to show the typical "swing" of the price.
- Square Root Variance Bands: The script performs a unique calculation using the square root of the variance from the calculated curve.
Visual Output and Interpretation
The indicator produces multiple lines on your chart:
- The Central Trend: This is the primary "Center of Gravity" line, showing the smoothed equilibrium.
- Upper and Lower Bounds: These provide a visual "channel." When price stays within these bounds, it suggests the market is behaving normally relative to its current trend. If price breaks significantly outside these bands, it can signal that a new trend is forming or that the current move is overextended.
In summary, this script is not just a trailing average; it is a mathematical curve-fitting tool that attempts to find the most statistically significant path of price movement by analyzing the structural "gravity" of historical data.
//+------------------------------------------------------------------+
//| JB Center of Gravity.mq4 |
//| |
//| Original Code from NG3110@latchess.com |
//| Modification written by Jürgen Bouché |
//| This is the no repainting variant of the COG indicator. |
//| |
//| http://juergen.bouche.de |
//+------------------------------------------------------------------+
#property copyright "ANG3110@latchess.com and Jürgen Bouché"
#property link "http://juergen.bouche.de"
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 RoyalBlue
#property indicator_color2 LimeGreen
#property indicator_color3 LimeGreen
#property indicator_color4 Goldenrod
#property indicator_color5 Goldenrod
extern int bars_back = 240;
extern int m = 4;
extern int i = 0;
extern double kstd = 1;
double fx[], sqh[], sql[], stdh[], stdl[];
double ai[10,10], b[10], x[10], sx[20];
double sum;
int p, n, f;
double qq, mm, tt;
int ii, jj, kk, ll, nn;
double sq, std;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorShortName("JB Center of Gravity");
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(0, fx);
SetIndexBuffer(1, sqh);
SetIndexBuffer(2, sql);
SetIndexBuffer(3, stdh);
SetIndexBuffer(4, stdl);
nn = m + 1;
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
int mi;
p = bars_back;
sx[1] = p + 1;
int iBarsToCalculate = 0;
int iCountedBars = IndicatorCounted();
if(iCountedBars < 0) return(-1);
if(iCountedBars > 0) iCountedBars--;
iBarsToCalculate = Bars - iCountedBars;
for(i = 0;i < iBarsToCalculate;i++)
{
// +-----+ SX +-----+
for(mi = 1; mi <= nn * 2 - 2; mi++)
{
sum = 0;
for(n = i; n <= i + p; n++)
{
sum += MathPow(n, mi);
}
sx[mi + 1] = sum;
}
// +-----+ SYX +-----+
for(mi = 1; mi <= nn; mi++)
{
sum = 0.00000;
for(n = i; n <= i + p; n++)
{
if(mi == 1)
sum += Close[n];
else
sum += Close[n] * MathPow(n, mi - 1);
}
b[mi] = sum;
}
// +-----+ MATRIX +-----+
for(jj = 1; jj <= nn; jj++)
{
for(ii = 1; ii <= nn; ii++)
{
kk = ii + jj - 1;
ai[ii, jj] = sx[kk];
}
}
// +-----+ GAUSS +-----+
for(kk = 1; kk <= nn - 1; kk++)
{
ll = 0; mm = 0;
for(ii = kk; ii <= nn; ii++)
{
if(MathAbs(ai[ii, kk]) > mm)
{
mm = MathAbs(ai[ii, kk]);
ll = ii;
}
}
if(ll == 0)
return(0);
if(ll != kk)
{
for(jj = 1; jj <= nn; jj++)
{
tt = ai[kk, jj];
ai[kk, jj] = ai[ll, jj];
ai[ll, jj] = tt;
}
tt = b[kk]; b[kk] = b[ll]; b[ll] = tt;
}
for(ii = kk + 1; ii <= nn; ii++)
{
qq = ai[ii, kk] / ai[kk, kk];
for(jj = 1; jj <= nn; jj++)
{
if(jj == kk)
ai[ii, jj] = 0;
else
ai[ii, jj] = ai[ii, jj] - qq * ai[kk, jj];
}
b[ii] = b[ii] - qq * b[kk];
}
}
x[nn] = b[nn] / ai[nn, nn];
for(ii = nn - 1; ii >= 1; ii--)
{
tt = 0;
for(jj = 1; jj <= nn - ii; jj++)
{
tt = tt + ai[ii, ii + jj] * x[ii + jj];
x[ii] = (1 / ai[ii, ii]) * (b[ii] - tt);
}
}
/*for(n = i; n <= i + p; n++)
{
sum = 0;
for(kk = 1; kk <= m; kk++)
{
sum += x[kk + 1] * MathPow(n, kk);
}
fx[n] = x[1] + sum;
}*/
sum = 0;
for(kk = 1; kk <= m; kk++)
{
sum += x[kk + 1] * MathPow(i, kk);
}
fx[i] = x[1] + sum;
sq = 0.0;
/*for(n = i;n <= i + p;n++)
{
sq += MathPow(Close[n] - fx[n], 2);
}*/
for(n = i;n <= i + p;n++)
{
sum = 0;
for(kk = 1; kk <= m; kk++)
{
sum += x[kk + 1] * MathPow(n, kk);
}
sq += MathPow(Close[n] - (x[1] + sum), 2);
}
sq = MathSqrt(sq / (p + 1)) * kstd;
std = iStdDev(NULL,0,p,MODE_SMA,0,PRICE_CLOSE,i) * kstd;
/*for(n = i; n <= i + p; n++)
{
sqh[n] = fx[n] + sq;
sql[n] = fx[n] - sq;
stdh[n] = fx[n] + std;
stdl[n] = fx[n] - std;
}*/
sqh[i] = fx[i] + sq;
sql[i] = fx[i] - sq;
stdh[i] = fx[i] + std;
stdl[i] = fx[i] - std;
}
return(0);
}
//+------------------------------------------------------------------+^
Comments