Author: Copyright 2015, fxborg
tangoline

The Tango Line is a technical analysis tool designed to provide traders with a visual representation of price dynamics by identifying and smoothing out significant market ranges. Instead of simply following the immediate price action, this script looks at historical data over a user-defined period to establish a clearer picture of the "middle ground" of price movement.

How the Logic Works

1. Dynamic Range Identification The script scans the market to identify specific high and low points within a set lookback period (the "Period"). It isn't just looking for the highest or lowest point on the chart; it specifically monitors how these peaks and valleys shift over time. By calculating the maximum highs and minimum lows, it creates a boundary of where the price has recently fluctuated.

2. Filtering Market Noise To ensure the indicator doesn't react to every tiny fluctuation (which can create "messy" lines), the logic includes a "Min Spread" filter. This acts as a buffer, requiring a significant enough move in price before the script acknowledges a new high or low. This helps the tool ignore minor market noise and focus on meaningful structural shifts in price.

3. Pivot Point Detection The core of the logic involves a "hook" mechanism. When the script detects that a previous low has dropped significantly or a previous high has risen significantly (beyond the minimum spread), it resets its internal markers. This allows the indicator to "anchor" itself to the most relevant recent price extremes, rather than getting stuck on outdated data.

4. The Tango Line Calculation Once the script has identified the current significant range (the floor and the ceiling of recent price action), it calculates the midpoint.

  • The Main Line: The primary visual output is a solid line representing the average of the high and low boundaries. This serves as a central equilibrium point for the market.
  • The Boundary Bands: The script also plots two dotted lines representing the upper and lower boundaries of the range.

Summary for Traders

Essentially, this script helps you visualize the "heart" of the current market trend. By providing a smoothed midpoint (the Tango Line) flanked by its boundaries, it allows you to see where price is gravitating. It is designed to help identify equilibrium zones, where the market may be consolidating or preparing for the next major move, filtering out the distractions of small, insignificant price ticks.

Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
14 Views
0 Downloads
0 Favorites
tangoline
//+------------------------------------------------------------------+
//|                                                    tangoline.mq4 |
//|                                           Copyright 2015, fxborg |
//|                                  http://blog.livedoor.jp/fxborg/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, fxborg"
#property link      "http://blog.livedoor.jp/fxborg/"
#property version   "1.02"
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "TangoLine"
#property indicator_width1  2
//--- input parameters
input  int InpPeriod=20;   // Period
input  double MinSpread = 5;     // Min Spread 
input  color LineColor=DeepPink; // Line Color
input  color BandColor=DarkViolet; // Band Color
//--- indicator buffers
double LineBuffer[];
//---- for calc 
double HighesBuffer[];
double LowesBuffer[];
double HighBuffer[];
double LowBuffer[];
//---
int CalcBarCount=2;     // Calc Bar Count
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   string short_name;
//--- indicator buffers mapping
   IndicatorBuffers(5);
   SetIndexBuffer(0,LineBuffer);
   SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,EMPTY,LineColor);
//---
   SetIndexBuffer(1,HighBuffer);
   SetIndexStyle(1,DRAW_LINE,STYLE_DOT,EMPTY,BandColor);
//---
   SetIndexBuffer(2,LowBuffer);
   SetIndexStyle(2,DRAW_LINE,STYLE_DOT,EMPTY,BandColor);
//---
   SetIndexBuffer(3,HighesBuffer);
   SetIndexBuffer(4,LowesBuffer);
   if(InpPeriod<2)
     {
      Alert("InpPeriod is too small.");
      return(INIT_FAILED);
     }
//---
   short_name="Tango Line("+IntegerToString(InpPeriod)+")";
   IndicatorShortName(short_name);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| De-initialization                                                |
//+------------------------------------------------------------------+
int deinit()
  {
   string short_name="Tango Line("+IntegerToString(InpPeriod)+")";
   IndicatorShortName(short_name);
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   int i,k,pos;
//--- check for bars count
   if(rates_total<=InpPeriod)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(HighesBuffer,false);
   ArraySetAsSeries(LowesBuffer,false);
   ArraySetAsSeries(HighBuffer,false);
   ArraySetAsSeries(LowBuffer,false);
   ArraySetAsSeries(LineBuffer,false);
//---
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(high,false);
//---
   pos=InpPeriod-1;
   if(pos+1<prev_calculated)
      pos=prev_calculated-2;
   else
     {
      for(i=0; i<pos; i++)
        {
         LowesBuffer[i]=0.0;
         HighesBuffer[i]=0.0;
         HighBuffer[i]=0.0;
         LowBuffer[i]=0.0;
         LineBuffer[i]=0.0;
        }
     }
//--- calculate HighesBuffer[] and ExtHighesBuffer[]
   int btm_bar=pos-InpPeriod+1;
   int top_bar=pos-InpPeriod+1;
// i < rates_total - 1 
   for(i=pos; i<rates_total-1 && !IsStopped(); i++)
     {
      //--- calculate range spread
      double dmin=1000000.0;
      double dmax=-1000000.0;
      for(k=i-InpPeriod+1; k<=i; k++)
        {
         if(dmin>low[k]) dmin=low[k];
         if(dmax<high[k]) dmax=high[k];
        }
      //--- hook
      if((LowesBuffer[i-2]-MinSpread*Point)>LowesBuffer[i-1]
         && LowesBuffer[i-1]==dmin)
        {
         top_bar=i-1;
         btm_bar=i-1;
        }
      if((HighesBuffer[i-2]+MinSpread*Point)<HighesBuffer[i-1]
         && HighesBuffer[i-1]==dmax)
        {
         btm_bar=i-1;
         top_bar=i-1;
        }
      LowesBuffer[i]=dmin;
      HighesBuffer[i]=dmax;
      if(MathMax(top_bar,btm_bar)>i-InpPeriod+1)
        {
         //--- calculate range spread
         dmin=1000000.0;
         dmax=-1000000.0;
         //---
         for(k=i-InpPeriod+1; k<=i; k++)
           {
            //---
            if(k>=btm_bar)
               if(dmin>low[k]) dmin=low[k];
            if(k>=top_bar)
               if(dmax<high[k]) dmax=high[k];
           }
        }
      LowBuffer[i+1]=dmin;
      HighBuffer[i+1]=dmax;
      LineBuffer[i+1]=(dmax+dmin)/2;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Comments