Author: Copyright 2014, MetaQuotes Software Corp.
correl8b

This script is designed as a multi-currency correlation indicator for the MetaTrader 4 platform. Its primary purpose is to visualize the relative strength and positioning of several major currencies (EUR, GBP, AUD, NZD, CHF, CAD, JPY, USD, and Gold) simultaneously on a single chart window.

Core Logic and Methodology

The script operates by calculating a "Percent Range Index" for multiple assets at once. Here is how the logic flows:

1. Relative Positioning (The Percent Range Index) Instead of looking at raw price numbers (which vary wildly between a currency like JPY and a metal like Gold), the script identifies a specific look-back period (e.g., 14 bars). It determines the highest high and the lowest low within that window to establish a "price range." It then calculates where the current price sits within that range as a percentage.

  • A value of 0 represents the absolute bottom of the recent range.
  • A value of +50 (or higher) represents the top of the range.
  • The script shifts this scale so that the "middle" of the range is 0, allowing users to see if an asset is overextended to the top or bottom relative to its recent history.

2. Currency Normalization To ensure that different currencies can be compared fairly on one graph, the script performs a normalization process. It takes the data from various currency pairs (most of which are paired against the USD) and mathematically adjusts them. This brings all assets into a unified scale so that their movements can be viewed side-by-side without one asset's price magnitude drowning out the others.

3. Relative Strength Calculation (The USD Factor) A unique feature of this script is how it handles the US Dollar (USD). Rather than just showing the USD as another independent line, the logic calculates the USD's position relative to all other tracked currencies. It aggregates the values of the other currencies and derives a "relative" value for the USD. This helps traders see which way the "broad market" is leaning against or with the dollar.

4. Visual Representation The script generates a dedicated window at the bottom of your chart featuring multiple lines, each assigned a specific color.

  • Automatic Detection: The script can automatically detect which currencies are in your current active pair and highlight them, or it can be set to show all major currencies at once.
  • Interactive Labels: It places text labels next to the lines so that users can easily identify which color belongs to which currency (e.g., identifying which line is GBP vs. CAD).

Summary for the User

In simple terms, this tool tells you "where is everything sitting right now?" By looking at the lines, you can quickly see if most currencies are moving up or down together, or if one specific currency is "breaking away" from the group. It converts complex, multi-asset price data into a simplified map of relative strength.

Price Data Components
Series array that contains close prices for each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each bar
Miscellaneous
Implements a curve of type %1
9 Views
0 Downloads
0 Favorites
correl8b
//+------------------------------------------------------------------+
//|                                                      Correl8.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 9
#property indicator_color1 clrRoyalBlue
#property indicator_color2 clrSilver
#property indicator_color3 clrDarkOrange
#property indicator_color4 clrDarkViolet
#property indicator_color5 clrFireBrick
#property indicator_color6 clrMagenta
#property indicator_color7 clrYellow
#property indicator_color8 clrLimeGreen
#property indicator_color9 clrGold

#property indicator_width1  2
#property indicator_width2  2
#property indicator_width3  2
#property indicator_width4  2
#property indicator_width5  2
#property indicator_width6  2
#property indicator_width7  2
#property indicator_width8  3
#property indicator_width9  3

#property indicator_level1  -50
#property indicator_level2  -26
#property indicator_level3  -12
#property indicator_level4    0
#property indicator_level5   12
#property indicator_level6   26
#property indicator_level7   50
#property indicator_levelcolor clrLightSlateGray
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_RANGEMODE
  {
   HIGH_LOW,
   CLOSE_CLOSE,
   HIGH_LOW_CLOSE,
  };
// Indicator parameters
extern int   iPRIPeriod=14;
input ENUM_APPLIED_PRICE iPrice = PRICE_CLOSE;
input ENUM_RANGEMODE  RangeMode = HIGH_LOW;
input ENUM_TIMEFRAMES TimeFrame = 0;
// Show currencies on chart
extern bool  ShowAuto=true;
// Show all currencies
extern bool  ShowAll = false;
extern bool  ShowEUR = false;
extern bool  ShowGBP = false;
extern bool  ShowAUD = false;
extern bool  ShowNZD = false;
extern bool  ShowCHF = false;
extern bool  ShowCAD = false;
extern bool  ShowJPY = false;
extern bool  ShowUSD = false;
extern bool  ShowXAU = false;
//---index buffers for drawing
double Idx1[],Idx2[],Idx3[],Idx4[],Idx5[],Idx6[],Idx7[],Idx8[],Idx9[];
//---currency variables for calculation
double EUR,GBP,AUD,NZD,CHF,CAD,JPY,USD,XAU;
double EURUSD,GBPUSD,AUDUSD,NZDUSD,/*USDCHF,USDCAD,USDJPY,*/XAUUSD;
//---currency names and colors
string Currencies[indicator_buffers]=
  {
   "EUR","GBP","AUD","NZD",
   "CHF","CAD","JPY","USD","XAU"
  };
string ShortName;
int    BarsWindow;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   IndicatorDigits(0);
   IndicatorBuffers(indicator_buffers);
   BarsWindow=WindowBarsPerChart()+iPRIPeriod;
//---set timeframes
/*   if(TimeFrame==0)
     {
      switch(Period())
        {
         case PERIOD_M30: iPRIPeriod*=2;break;
         case PERIOD_M15: iPRIPeriod*=4;break;
         case PERIOD_M5:  iPRIPeriod*=12;break;
         case PERIOD_M1:  iPRIPeriod*=60;break;
        }
     }
   if(TimeFrame>0)
     {
      switch(TimeFrame)
        {
         case PERIOD_M30: iPRIPeriod*=2;break;
         case PERIOD_M15: iPRIPeriod*=4;break;
         case PERIOD_M5:  iPRIPeriod*=12;break;
         case PERIOD_M1:  iPRIPeriod*=60;break;
        }
     }*/
   string sTimeFrame;
   switch(TimeFrame)
     {
      case PERIOD_MN1: sTimeFrame = "MN1 ";break;
      case PERIOD_W1:  sTimeFrame = "W1 "; break;
      case PERIOD_D1:  sTimeFrame = "D1 "; break;
      case PERIOD_H4:  sTimeFrame = "H4 "; break;
      case PERIOD_H1:  sTimeFrame = "H1 "; break;
      case PERIOD_M30: sTimeFrame = "M30 ";break;
      case PERIOD_M15: sTimeFrame = "M15 ";break;
      case PERIOD_M5:  sTimeFrame = "M5 "; break;
      case PERIOD_M1:  sTimeFrame = "M1 "; break;
      default:         sTimeFrame = "";    break;
     }
   ShortName="iCorrel8 "+sTimeFrame+"("+IntegerToString(iPRIPeriod)+") ";
   IndicatorShortName(ShortName);
//---currencies to show
   if(ShowAuto)
     {
      string Quote= StringSubstr(Symbol(),3,3);  //Quote currency name
      string Base = StringSubstr(Symbol(),0,3);  //Base currency name
      if(Quote == "EUR" || Base == "EUR")  ShowEUR = true;
      if(Quote == "GBP" || Base == "GBP")  ShowGBP = true;
      if(Quote == "AUD" || Base == "AUD")  ShowAUD = true;
      if(Quote == "NZD" || Base == "NZD")  ShowNZD = true;
      if(Quote == "CHF" || Base == "CHF")  ShowCHF = true;
      if(Quote == "CAD" || Base == "CAD")  ShowCAD = true;
      if(Quote == "JPY" || Base == "JPY")  ShowJPY = true;
      if(Quote == "USD" || Base == "USD")  ShowUSD = true;
      if(Quote == "XAU" || Base == "XAU")  ShowXAU = true;
      //ShowAll=false;
     }

   if(ShowAll)
     {
      //ShowAuto = false;
      ShowEUR = true;
      ShowGBP = true;
      ShowAUD = true;
      ShowNZD = true;
      ShowCHF = true;
      ShowCAD = true;
      ShowJPY = true;
      ShowUSD = true;
      ShowXAU = true;
     }

   int window=WindowFind(ShortName);
   int xStart=4;       //label coordinates
   int xIncrement=25;
   int yStart=16;
//---set buffer properties
   if(ShowEUR)
     {
      SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,indicator_width1);
      SetIndexLabel(0,Currencies[0]);
      SetIndexDrawBegin(0,iPRIPeriod);
      CreateLabel(Currencies[0],window,xStart,yStart,indicator_color1);
      xStart+=xIncrement;
     }
   if(ShowGBP)
     {
      SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,indicator_width2);
      SetIndexLabel(1,Currencies[1]);
      SetIndexDrawBegin(1,iPRIPeriod);
      CreateLabel(Currencies[1],window,xStart,yStart,indicator_color2);
      xStart+=xIncrement;
     }
   if(ShowAUD)
     {
      SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,indicator_width3);
      SetIndexLabel(2,Currencies[2]);
      SetIndexDrawBegin(2,iPRIPeriod);
      CreateLabel(Currencies[2],window,xStart,yStart,indicator_color3);
      xStart+=xIncrement;
     }
   if(ShowNZD)
     {
      SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,indicator_width4);
      SetIndexDrawBegin(3,iPRIPeriod);
      SetIndexLabel(3,Currencies[3]);
      CreateLabel(Currencies[3],window,xStart,yStart,indicator_color4);
      xStart+=xIncrement;
     }
   if(ShowCHF)
     {
      SetIndexStyle(4,DRAW_LINE,STYLE_SOLID,indicator_width5);
      SetIndexLabel(4,Currencies[4]);
      SetIndexDrawBegin(4,iPRIPeriod);
      CreateLabel(Currencies[4],window,xStart,yStart,indicator_color5);
      xStart+=xIncrement;
     }
   if(ShowCAD)
     {
      SetIndexStyle(5,DRAW_LINE,STYLE_SOLID,indicator_width6);
      SetIndexLabel(5,Currencies[5]);
      SetIndexDrawBegin(5,iPRIPeriod);
      CreateLabel(Currencies[5],window,xStart,yStart,indicator_color6);
      xStart+=xIncrement;
     }
   if(ShowJPY)
     {
      SetIndexStyle(6,DRAW_LINE,STYLE_SOLID,indicator_width7);
      SetIndexLabel(6,Currencies[6]);
      SetIndexDrawBegin(6,iPRIPeriod);
      CreateLabel(Currencies[6],window,xStart,yStart,indicator_color7);
      xStart+=xIncrement;
     }
   if(ShowUSD)
     {
      SetIndexStyle(7,DRAW_LINE,STYLE_SOLID,indicator_width8);
      SetIndexLabel(7,Currencies[7]);
      SetIndexDrawBegin(7,iPRIPeriod);
      CreateLabel(Currencies[7],window,xStart,yStart,indicator_color8);
      xStart+=xIncrement;
     }
   if(ShowXAU)
     {
      SetIndexStyle(8,DRAW_LINE,STYLE_SOLID,indicator_width9);
      SetIndexLabel(8,Currencies[8]);
      SetIndexDrawBegin(8,iPRIPeriod);
      CreateLabel(Currencies[8],window,xStart,yStart,indicator_color9);
      //xStart+=xIncrement;
     }
//---index buffers
   SetIndexBuffer(0,Idx1);
   SetIndexBuffer(1,Idx2);
   SetIndexBuffer(2,Idx3);
   SetIndexBuffer(3,Idx4);
   SetIndexBuffer(4,Idx5);
   SetIndexBuffer(5,Idx6);
   SetIndexBuffer(6,Idx7);
   SetIndexBuffer(7,Idx8);
   SetIndexBuffer(8,Idx9);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
// delete labels
//int window=WindowFind(ShortName);
   for(int i=0;i<indicator_buffers;i++)
      ObjectDelete(Currencies[i]);
   return;
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   BarsWindow=WindowBarsPerChart()+iPRIPeriod;
   int shift;
   int limit=rates_total-prev_calculated;
   if(prev_calculated==0)  limit=BarsWindow;
   if(prev_calculated>0)  limit++;
   if(prev_calculated>0 && NewBar()) limit++;
   for(int i=0; i<limit; i++)
     {
      shift=iBarShift(NULL,TimeFrame,time[i]);

      EUR = iPRI("EURUSD",TimeFrame,iPRIPeriod,iPrice,shift);
      GBP = iPRI("GBPUSD",TimeFrame,iPRIPeriod,iPrice,shift);
      AUD = iPRI("AUDUSD",TimeFrame,iPRIPeriod,iPrice,shift);
      NZD = iPRI("NZDUSD",TimeFrame,iPRIPeriod,iPrice,shift);
      CHF = iPRI("USDCHF",TimeFrame,iPRIPeriod,iPrice,shift);
      CAD = iPRI("USDCAD",TimeFrame,iPRIPeriod,iPrice,shift);
      JPY = iPRI("USDJPY",TimeFrame,iPRIPeriod,iPrice,shift);
      XAU = iPRI("XAUUSD",TimeFrame,iPRIPeriod,iPrice,shift);

      EURUSD = iClose("EURUSD",TimeFrame,shift);   //Get USD ratio      
      GBPUSD = iClose("GBPUSD",TimeFrame,shift);
      AUDUSD = iClose("AUDUSD",TimeFrame,shift);
      NZDUSD = iClose("NZDUSD",TimeFrame,shift);
      //USDCHF = iClose("USDCHF",TimeFrame,shift);
      //USDCAD = iClose("USDCAD",TimeFrame,shift);
      //USDJPY = iClose("USDJPY",TimeFrame,shift)/100;
      XAUUSD = iClose("XAUUSD",TimeFrame,shift)/1000;

      if(EURUSD)
         EUR*=1/EURUSD;
      if(GBPUSD)
         GBP*=1/GBPUSD;
      if(AUDUSD)
         AUD*=1/AUDUSD;
      if(NZDUSD)
         NZD*=1/NZDUSD;
      if(XAUUSD)
         XAU*=1/XAUUSD;

      CHF*=-1;
      CAD*=-1;
      JPY*=-1;
      
      USD=-(EUR+GBP+AUD+NZD+CHF+CAD+JPY+XAU)/(indicator_buffers-1);   //USD relative to other 
    /*EUR += -(GBP + AUD + NZD + CHF + CAD + JPY + XAU)/(indicator_buffers-2); //Currency relative to USD
      GBP += -(EUR + AUD + NZD + CHF + CAD + JPY + XAU)/(indicator_buffers-2);
      AUD += -(EUR + GBP + NZD + CHF + CAD + JPY + XAU)/(indicator_buffers-2);
      NZD += -(EUR + GBP + AUD + CHF + CAD + JPY + XAU)/(indicator_buffers-2);
      CHF += -(EUR + GBP + AUD + NZD + CAD + JPY + XAU)/(indicator_buffers-2);
      CAD += -(EUR + GBP + AUD + NZD + CHF + JPY + XAU)/(indicator_buffers-2);
      JPY += -(EUR + GBP + AUD + NZD + CHF + CAD + XAU)/(indicator_buffers-2);
    */
      if(ShowEUR)
         Idx1[i]=EUR;
      if(ShowGBP)
         Idx2[i]=GBP;
      if(ShowAUD)
         Idx3[i]=AUD;
      if(ShowNZD)
         Idx4[i]=NZD;
      if(ShowCHF)
         Idx5[i]=CHF;
      if(ShowCAD)
         Idx6[i]=CAD;
      if(ShowJPY)
         Idx7[i]=JPY;
      if(ShowUSD)
         Idx8[i]=USD;
      if(ShowXAU)
         Idx9[i]=XAU;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CreateLabel(string currency,
                 int window,
                 int x,
                 int y,
                 int clr)
  {
   int label=ObjectCreate(currency,OBJ_LABEL,window,0,0);
   ObjectSetText(currency,currency,8);
   ObjectSet(currency,OBJPROP_COLOR,clr);
   ObjectSet(currency,OBJPROP_XDISTANCE,x);
   ObjectSet(currency,OBJPROP_YDISTANCE,y);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool NewBar()
  {
   static datetime time_prev;
   if(iTime("EURUSD",TimeFrame,0) != time_prev &&
      iTime("GBPUSD",TimeFrame,0) != time_prev &&
      iTime("AUDUSD",TimeFrame,0) != time_prev &&
      iTime("NZDUSD",TimeFrame,0) != time_prev &&
      iTime("USDCHF",TimeFrame,0) != time_prev &&
      iTime("USDCAD",TimeFrame,0) != time_prev &&
      iTime("USDJPY",TimeFrame,0) != time_prev &&
      iTime("XAUUSD",TimeFrame,0) != time_prev)
     {
      time_prev = iTime("EURUSD",TimeFrame,0);
      time_prev = iTime("GBPUSD",TimeFrame,0);
      time_prev = iTime("AUDUSD",TimeFrame,0);
      time_prev = iTime("NZDUSD",TimeFrame,0);
      time_prev = iTime("USDCHF",TimeFrame,0);
      time_prev = iTime("USDCAD",TimeFrame,0);
      time_prev = iTime("USDJPY",TimeFrame,0);
      time_prev = iTime("XAUUSD",TimeFrame,0);
      return(true);
     }
   return(false);
  }
//+------------------------------------------------------------------+
//| Percent Range Index Function                                     |
//+------------------------------------------------------------------+
const int iPRI(const string symbol,
               const ENUM_TIMEFRAMES timeframe,
               const int period,
               const ENUM_APPLIED_PRICE price,
               const int idx)
  {
   int PRI;
   double Price;
   double Range;
   double MaxHigh;
   double MinLow;
   double HighHigh;
   double HighClose;
   double HighLow;
   double LowHigh;
   double LowClose;
   double LowLow;

   switch(RangeMode)
     {
      case HIGH_LOW:
        {
         MaxHigh=iHigh(symbol,timeframe,
                 iHighest(symbol,timeframe,MODE_HIGH,period,idx));
         MinLow=iLow(symbol,timeframe,
                iLowest(symbol,timeframe,MODE_LOW,period,idx));
         break;
        }
      case CLOSE_CLOSE:
        {
         MaxHigh=iClose(symbol,timeframe,
                 iHighest(symbol,timeframe,MODE_CLOSE,period,idx));
         MinLow=iClose(symbol,timeframe,
                iLowest(symbol,timeframe,MODE_CLOSE,period,idx));
         break;
        }
      case HIGH_LOW_CLOSE:
        {
         HighHigh=iHigh(symbol,timeframe,
                  iHighest(symbol,timeframe,MODE_HIGH,period,idx));
         HighClose=iClose(symbol,timeframe,
                   iHighest(symbol,timeframe,MODE_CLOSE,period,idx));
         HighLow=iLow(symbol,timeframe,
                 iHighest(symbol,timeframe,MODE_LOW,period,idx));
         LowHigh=iHigh(symbol,timeframe,
                 iLowest(symbol,timeframe,MODE_HIGH,period,idx));
         LowClose=iClose(symbol,timeframe,
                  iLowest(symbol,timeframe,MODE_CLOSE,period,idx));
         LowLow=iLow(symbol,timeframe,
                iLowest(symbol,timeframe,MODE_LOW,period,idx));
         MaxHigh=(HighHigh+HighClose+HighLow)/3;
         MinLow =(LowHigh+LowClose+LowLow)/3;
         break;
        }
     }

   switch(price)
     {
      case PRICE_CLOSE:    Price = iClose(symbol,timeframe,idx);    break;
      case PRICE_HIGH:     Price = iHigh(symbol,timeframe,idx);     break;
      case PRICE_LOW:      Price = iLow(symbol,timeframe,idx);      break;
      case PRICE_MEDIAN:   Price =(iHigh(symbol,timeframe,idx)+
                                   iLow(symbol,timeframe,idx))/2;   break;
      case PRICE_TYPICAL:  Price =(iHigh(symbol,timeframe,idx)+
                                   iLow(symbol,timeframe,idx)+
                                   iClose(symbol,timeframe,idx))/3; break;
      case PRICE_WEIGHTED: Price =(iHigh(symbol,timeframe,idx)+
                                   iLow(symbol,timeframe,idx)+
                                   iClose(symbol,timeframe,idx)+
                                   iClose(symbol,timeframe,idx))/4; break;
      default:             Price = iClose(symbol,timeframe,idx);
     }

   Range=MaxHigh-MinLow;

   if(NormalizeDouble(Range,3)!=0.0)
     {
      PRI=100*(Price-MinLow)/Range;
      PRI-=50;
     }
   else PRI=0;
//if(PRI >  50)   PRI =  50;
//if(PRI < -50)   PRI = -50;
   return(PRI);
  }
//+------------------------------------------------------------------+

Comments