_i_FXGauge_lite
Download scriptThe following description outlines the logic and functionality of the FXGauge_lite script. It is designed to provide a visual representation of market structure and momentum by analyzing multiple timeframes simultaneously.
Core Concept: Multi-Timeframe Market Mapping
The script functions as a comprehensive visual "gauge" for price action. Instead of looking at just one chart, it processes data from four different timeframes (defined by the user) to create a synchronized grid of support, resistance, and momentum zones on your current screen.
Key Logic Components
1. Momentum Analysis
The script identifies specific price levels based on an external Moving Average indicator. It pulls seven different moving average values for each of the four timeframes. These are used to determine:
- Highs and Lows: The logic finds the highest and lowest moving average values for every timeframe.
- Momentum Bars: It draws horizontal bars representing these specific price levels. Depending on whether the current market price is above or below these levels, the bars change color (e.g., Green or Red) to indicate relative strength or weakness.
2. The "Blue Shade" Grid (Zones of Interest)
The script generates a series of "shades" (rectangles and bars) extending both upward and downward from the calculated momentum boundaries.
- Dynamic Scaling: These shades are not fixed; they are calculated as specific distances from the highest and lowest moving averages identified in the previous step.
- Overlapping Logic: To ensure the chart remains clean, the script includes logic to detect where these zones overlap. If the upward and downward "shades" meet or cross, it intelligently hides the redundant objects to prevent visual clutter.
- Visual Weight: The center of this grid is highlighted as a "MidShade," representing the primary area of interest where various price actions converge.
3. Support and Resistance (S&R) Detection
One of the script's most sophisticated features is its ability to automatically identify significant price gaps.
- Price Gap Analysis: The script gathers all relevant price levels—including momentum lines, boundary shades, and the current market price—and sorts them into a single chronological list.
- Significant Volatility Identification: It calculates the distance between these sorted levels. If it finds a gap of 10 pips or more, it identifies this as a significant zone.
- Visual Signaling: These gaps are marked with vertical lines. The color of these lines shifts based on whether the price is currently trading above or below that specific gap, helping traders identify "voids" in liquidity or potential areas of price rejection.
User Experience Summary
For a trader, this script transforms a standard chart into a multi-dimensional map. It visualizes:
- Timeframe Harmony: By showing four timeframes at once, it helps you see if short-term and long-term trends are aligned.
- Price Boundaries: The blue shades provide a "heat map" of where price might interact with established historical momentum.
- Structural Gaps: The vertical lines highlight empty spaces in the market that often lead to rapid price movements or significant reactions.
//+------------------------------------------------------------------+
//| _i_FXGauge_lite.mq4 |
//| Copyright © 2006, Doji Starr |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Doji Starr"
#property indicator_chart_window
#define NBSL 8 // number of blue shade levels
#define NSVR 17 // number of solid vertical lines
// input params
extern int TF1 = 1;
extern int TF2 = 5;
extern int TF3 = 15;
extern int TF4 = 60;
int Shift = 2;
int Spacing = 7;
int Width = 6;
// vars
int counted_bars, startBar, bar, i;
int tf, c, offset, xUnit;
int shift, spacing, width;
int tfa[4];
double fml[4][7]; // momentum lines
double bsl_up[4][NBSL]; // blue shades levels to the up side
double bsl_down[4][NBSL]; // blue shades levels to the down side
double _bsl[NBSL] = {8, 11, 16, 27, 43, 75, 100, 144, 244};
// blue shades distances
double bsl[NBSL]; // blue shades distances ('Point' adjusted)
double tmpArray[7], lowestMA, highestMA;
double srl[24]; // support/resistance levels (total = 2*NBSL + 7 + 1(Bid) )
double price;
string objName;
datetime curTime;
//color blueShade[NBSL] = {LightBlue, LightSkyBlue, CornflowerBlue, RoyalBlue, Blue};
color blueShade[NBSL] = {C'216,239,255', C'167,224,254', C'96,215,255', C'1,191,223', C'16,137,218', C'0,0,255', C'0,0,255'};
color col;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
tfa[0] = TF1;
tfa[1] = TF2;
tfa[2] = TF3;
tfa[3] = TF4;
xUnit = Period() * 60;
shift = Shift * xUnit;
spacing = Spacing * xUnit;
width = Width * xUnit;
for (i=0; i<NBSL; i++)
bsl[i] = _bsl[i]*Point;
// creating the objects for drawing the grid
for (tf=0; tf<4; tf++)
{
// blue shade rectangles and bars
for (i=0; i<NBSL; i++)
{
objName = "bsl_up_rect_"+tf+"_"+i;
ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_COLOR, blueShade[i]);
objName = "bsl_down_rect_"+tf+"_"+i;
ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_COLOR, blueShade[i]);
objName = "bsl_up_bar_"+tf+"_"+i;
ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_COLOR, Black);
ObjectSet(objName, OBJPROP_RAY, false);
ObjectSet(objName, OBJPROP_WIDTH, 2);
objName = "bsl_down_bar_"+tf+"_"+i;
ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_COLOR, Black);
ObjectSet(objName, OBJPROP_RAY, false);
ObjectSet(objName, OBJPROP_WIDTH, 2);
}
objName = "MidShade_"+tf;
ObjectCreate(objName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_COLOR, White);
// S&R boxes
objName = "Box1_"+tf;
ObjectCreate(objName, OBJ_ARROW, 0, 0, 0);
ObjectSet(objName, OBJPROP_ARROWCODE, 1);
objName = "Box2_"+tf;
ObjectCreate(objName, OBJ_ARROW, 0, 0, 0);
ObjectSet(objName, OBJPROP_ARROWCODE, 1);
// momentum lines bars
// for (i=0; i<7; i++)
{
objName = "fml_bar_"+tf+"_"+i;
ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_COLOR, Black);
ObjectSet(objName, OBJPROP_RAY, false);
if (i<2)
ObjectSet(objName, OBJPROP_WIDTH, 5);
else
ObjectSet(objName, OBJPROP_WIDTH, 2);
}
// solid vertical lines (of 10 pips or more)
for (i=1; i<=NSVR; i++)
{
objName = "svr_"+tf+"_"+i;
ObjectCreate(objName, OBJ_TREND, 0, 0, 0, 0, 0);
ObjectSet(objName, OBJPROP_RAY, false);
ObjectSet(objName, OBJPROP_WIDTH, 3);
}
}
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
// deleting the drawing objects
for (tf=0; tf<4; tf++)
{
for (i=0; i<NBSL; i++)
{
ObjectDelete("bsl_up_rect_"+tf+"_"+i);
ObjectDelete("bsl_down_rect_"+tf+"_"+i);
ObjectDelete("bsl_up_bar_"+tf+"_"+i);
ObjectDelete("bsl_down_bar_"+tf+"_"+i);
}
ObjectDelete("MidShade_"+tf);
ObjectDelete("Box1_"+tf);
ObjectDelete("Box2_"+tf);
for (i=0; i<7; i++)
ObjectDelete("fml_bar_"+tf+"_"+i);
for (i=1; i<=NSVR; i++)
ObjectDelete("svr_"+tf+"_"+i);
}
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
/*
if (Bars-IndicatorCounted() > 2)
return;
*/
// curTime = TimeCurrent();
curTime = Time[0];
// price = Bid;
price = iClose(Symbol(),0,0);
for (tf=0; tf<4; tf++)
{
// bar = 0;
bar = iBarShift(Symbol(), tfa[tf], curTime, false);
// populating the fml array...
for (i=0; i<7; i++)
fml[tf][i] = iCustom(Symbol(), tfa[tf], "_i_FXGaugeMAs_lite", i, bar);
// finding the highest and lowest MAs from the 7 fml's
for (i=0; i<7; i++)
tmpArray[i] = fml[tf][i]; // copying the MAs levels of this TF to one dim array to feed ArrayBsearch
ArraySort(tmpArray);
lowestMA = tmpArray[0];
highestMA = tmpArray[6];
// populating the bsl arrays...
for (i=0; i<NBSL; i++)
{
bsl_up[tf][i] = lowestMA + bsl[i];
bsl_down[tf][i] = highestMA - bsl[i];
}
}
// OK... now drawing
for (tf=0; tf<4; tf++)
{
// drawing the blue shades of the grid from top to bottom
// find the number of overlapping shades
offset = 0;
for (i=offset; i<NBSL-1; i++)
if (bsl_up[tf][i] <= bsl_down[tf][i])
offset++;
//Print(offset);
// hide the objects of the first level of overlapping so they wont be left as 'ghosts'
if (offset > 0)
{
objName = "bsl_up_rect_"+tf+"_"+(NBSL-2-offset+1);
ObjectSet(objName, OBJPROP_TIME1, 0);
ObjectSet(objName, OBJPROP_TIME2, 0);
ObjectSet(objName, OBJPROP_PRICE1, 0);
ObjectSet(objName, OBJPROP_PRICE2, 0);
objName = "bsl_up_bar_"+tf+"_"+(NBSL-2-offset+1);
ObjectSet(objName, OBJPROP_TIME1, 0);
ObjectSet(objName, OBJPROP_TIME2, 0);
ObjectSet(objName, OBJPROP_PRICE1, 0);
ObjectSet(objName, OBJPROP_PRICE2, 0);
}
for (i=NBSL-2; i>=offset; i--)
{
objName = "bsl_up_rect_"+tf+"_"+(i-offset);
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+width);
ObjectSet(objName, OBJPROP_PRICE1, bsl_up[tf][i]);
ObjectSet(objName, OBJPROP_PRICE2, bsl_up[tf][i+1]);
objName = "bsl_up_bar_"+tf+"_"+(i-offset);
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+xUnit);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+width-xUnit);
ObjectSet(objName, OBJPROP_PRICE1, bsl_up[tf][i]);
ObjectSet(objName, OBJPROP_PRICE2, bsl_up[tf][i]);
}
objName = "MidShade_"+tf;
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+width);
ObjectSet(objName, OBJPROP_PRICE1, bsl_up[tf][offset]);
ObjectSet(objName, OBJPROP_PRICE2, bsl_down[tf][offset]);
// hide the objects of the first level of overlapping so they wont be left as 'ghosts'
if (offset > 0)
{
objName = "bsl_down_rect_"+tf+"_"+(NBSL-2-offset+1);
ObjectSet(objName, OBJPROP_TIME1, 0);
ObjectSet(objName, OBJPROP_TIME2, 0);
ObjectSet(objName, OBJPROP_PRICE1, 0);
ObjectSet(objName, OBJPROP_PRICE2, 0);
objName = "bsl_down_bar_"+tf+"_"+(NBSL-2-offset+1);
ObjectSet(objName, OBJPROP_TIME1, 0);
ObjectSet(objName, OBJPROP_TIME2, 0);
ObjectSet(objName, OBJPROP_PRICE1, 0);
ObjectSet(objName, OBJPROP_PRICE2, 0);
}
for (i=0; i<NBSL-1; i++)
{
objName = "bsl_down_rect_"+tf+"_"+(i-offset);
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+width);
ObjectSet(objName, OBJPROP_PRICE1, bsl_down[tf][i]);
ObjectSet(objName, OBJPROP_PRICE2, bsl_down[tf][i+1]);
objName = "bsl_down_bar_"+tf+"_"+(i-offset);
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+xUnit);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+width-xUnit);
ObjectSet(objName, OBJPROP_PRICE1, bsl_down[tf][i]);
ObjectSet(objName, OBJPROP_PRICE2, bsl_down[tf][i]);
}
/*
// drawing the boxes
objName = "Box1_"+tf;
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+xUnit);
ObjectSet(objName, OBJPROP_PRICE1, fml[tf][0]);
if (fml[tf][0] > price+Point/2) col = FireBrick;
else if (fml[tf][0] < price-Point/2) col = Green;
else col = Orange;
ObjectSet(objName, OBJPROP_COLOR, col);
objName = "Box2_"+tf;
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+xUnit);
ObjectSet(objName, OBJPROP_PRICE1, fml[tf][1]);
if (fml[tf][1] > price+Point/2) col = FireBrick;
else if (fml[tf][1] < price-Point/2) col = Green;
else col = Orange;
ObjectSet(objName, OBJPROP_COLOR, col);
*/
// drawing the momentum lines bars
for (i=0; i<7; i++)
{
objName = "fml_bar_"+tf+"_"+i;
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+xUnit);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+width-xUnit);
ObjectSet(objName, OBJPROP_PRICE1, fml[tf][i]);
ObjectSet(objName, OBJPROP_PRICE2, fml[tf][i]);
/*
if (i<2)
{
if (fml[tf][i] > price+Point/2) col = FireBrick;
else if (fml[tf][i] < price-Point/2) col = Green;
else col = Orange;
ObjectSet(objName, OBJPROP_COLOR, col);
}
*/
if (i==1)
{
if (fml[tf][i] >= price) col = IndianRed;
else if (fml[tf][i] < price) col = LimeGreen;
ObjectSet(objName, OBJPROP_COLOR, col);
}
else if (i==0)
{
if (fml[tf][i] >= price) col = FireBrick;
else if (fml[tf][i] < price) col = Green;
ObjectSet(objName, OBJPROP_COLOR, col);
}
}
// drawing the solid vertical lines:
// arranging all the bars levels in a single sorted array
ArrayInitialize(srl, -1) ;
for (i=0; i<7; i++)
srl[i] = fml[tf][i];
for (i=offset; i<NBSL; i++)
{
srl[7+i] = bsl_down[tf][i];
srl[7+NBSL+i] = bsl_up[tf][i];
}
srl[7+2*NBSL] = price;
ArraySort(srl);
// looking for a gap of 10 pips or more
c = 0;
for (i=0; i<7+2*NBSL+2; i++)
{
if (-1 == srl[i])
continue;
if (srl[i+1]-srl[i] >= 10*Point)
{
c++;
objName = "svr_"+tf+"_"+c;
ObjectSet(objName, OBJPROP_TIME1, curTime+shift+tf*spacing+3*xUnit);
ObjectSet(objName, OBJPROP_TIME2, curTime+shift+tf*spacing+3*xUnit);
ObjectSet(objName, OBJPROP_PRICE1, srl[i]+Point);
ObjectSet(objName, OBJPROP_PRICE2, srl[i+1]-Point);
if (srl[i+1] <= price)
ObjectSet(objName, OBJPROP_COLOR, FireBrick);
else
ObjectSet(objName, OBJPROP_COLOR, Green);
}
}
if (c >= NSVR)
Print("Warning: NSVR exceeded");
else
{
// hide the (only the first) unused vertical lines objects so they wont be left as 'ghosts'
// for (sr=c; sr<NSVR; sr++)
{
objName = "svr_"+tf+"_"+(c+1);
ObjectSet(objName, OBJPROP_TIME1, 0);
ObjectSet(objName, OBJPROP_TIME2, 0);
ObjectSet(objName, OBJPROP_PRICE1, 0);
ObjectSet(objName, OBJPROP_PRICE2, 0);
}
}
}
return(0);
}
Comments