Author: Copyright � 2006, Doji Starr
_i_FXGauge

This tool functions as a multi-timeframe visual dashboard designed to provide a comprehensive overview of market structure and momentum. Instead of looking at a single price point, it aggregates data from four different timeframes simultaneously, allowing you to see how different market speeds interact with one another.

Core Mechanics

Multi-Timeframe Integration The script monitors four specific timeframes (defaulting to 1, 5, 15, and 60 minutes). For each of these periods, it calculates a series of "Momentum Lines" based on moving averages. This allows the tool to visualize the trend and price action across various scales at a single glance.

Dynamic Grid and Shading To help identify key zones of interest, the script generates a visual grid composed of blue shades:

  • Upward/Downward Zones: It calculates levels extending above and below the highest and lowest momentum lines for each timeframe.
  • Overlapping Detection: The logic is smart enough to detect where these zones overlap. If different timeframes suggest similar price boundaries, the tool adjusts the display to avoid visual clutter while still highlighting those high-confluence areas.
  • Visual Hierarchy: The colors of these shades vary in intensity, providing a "heat map" effect that helps identify where price action is most likely to encounter resistance or support.

Momentum Visuals Specific bars are plotted for each timeframe to indicate the current momentum relative to the actual market price:

  • Positioning: These bars show exactly where the momentum lines sit in relation to the current price.
  • Color Coding: The tool uses color changes (such as Red/Green or Lime/FireBrick) to quickly signal whether the momentum is currently leading the price or trailing behind it, providing an immediate visual cue of market strength.

Smart Support and Resistance (S&R) One of the most sophisticated parts of the logic is the automatic identification of "Significant Gaps":

  • Data Collection: The script compiles every relevant price level—including all momentum lines, the shaded zone boundaries, and the current price—into a single sorted list for each timeframe.
  • Gap Analysis: It scans this list to find gaps between levels that are 10 pips or larger. These gaps represent "voids" in the price action where significant historical movement may have occurred.
  • Visual Markers: These gaps are marked with vertical lines. The colors of these lines (Green or Red) indicate whether the gap is sitting above or below the current market price, highlighting potential areas where price might react or "stick."

Summary for the User

Essentially, this script transforms raw data from multiple timeframes into a structured visual map. It highlights where different trends agree (confluence), shows you the current strength of the momentum (color-coded bars), and identifies significant structural gaps in the market that could act as future price magnets or barriers.

11 Views
0 Downloads
0 Favorites
_i_FXGauge
//+------------------------------------------------------------------+
//|                                                   _i_FXGauge.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] = {9, 16, 26, 42, 68, 110, 178, 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 = Close[0];
    
    for (tf=0; tf<4; tf++)
    {
//        bar = 0;
        bar = iBarShift(NULL, tfa[tf], curTime, false);

        // populating the fml array...
        for (i=0; i<7; i++)
            fml[tf][i] = iCustom(NULL, tfa[tf], "_i_FXGaugeMAs", 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