SpearmanRankCorr
Download scriptThis script is designed to analyze price movements by focusing on the relative "ranking" of data rather than just the raw numerical values. By using a statistical method known as Spearman’s Rank Correlation, it helps identify the strength and consistency of trends regardless of how volatile or large the actual price fluctuations are.
Core Logic Overview
The script operates through three primary logical stages to process market data:
1. Data Normalization (Ranking)
Instead of looking at the literal price (e.g., $1.1052), the script converts prices into a ranked list within a specific lookback window (defined by the rangeN parameter). It compares the prices in that window to one another to determine their relative positions. For example, it identifies which price was the highest, second-highest, and so on. If multiple identical prices occur, the script intelligently averages their ranks to ensure the mathematical integrity of the data remains intact.
2. Directional Sorting The tool allows you to choose the "direction" of this ranking. It can be configured to rank prices in descending order (identifying which prices were highest to lowest) or ascending order. This flexibility allows users to tailor how the relationship between sequential price points is interpreted by the algorithm.
3. Correlation Calculation Once the prices are converted into ranks, the script applies a specific mathematical formula to measure the correlation between these ranks over time. It calculates how closely the sequence of rankings follows a consistent pattern.
Key Objectives and Behavior
- Trend Consistency: The primary goal is to determine if price movements are moving in a predictable direction. Because it uses "ranks," the indicator is less likely to be distracted by sudden, isolated "spikes" or "noise" that don't reflect the overall trend of the period.
- Relative Performance: By focusing on rank rather than raw value, the script excels at showing how well the price is performing relative to its recent history.
- Visual Output: The final result is plotted in a separate window as a visual line. This allows traders to see the "strength" of the current correlation, making it easier to identify periods of stable trending behavior versus periods of erratic, non-correlated movement.
//+------------------------------------------------------------------+
//| SpearmanRankCorrelation.mq4 |
//| Copyright © 2007, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
// http://www.improvedoutcomes.com/docs/WebSiteDocs/Clustering/
// Clustering_Parameters/Spearman_Rank_Correlation_Distance_Metric.htm
// http://www.infamed.com/stat/s05.html
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
//----
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 DarkBlue
//---- input parameters
extern int rangeN = 14;
extern int CalculatedBars = 0;
extern int Maxrange = 30;
extern bool direction = true;
//---- buffers
double ExtMapBuffer1[];
double R2[];
double multiply;
int PriceInt[];
int SortInt[];
//+------------------------------------------------------------------+
//| calculate RSP function |
//+------------------------------------------------------------------+
double SpearmanRankCorrelation(double Ranks[], int N)
{
//----
double res,z2;
int i;
for(i = 0; i < N; i++)
{
z2 += MathPow(Ranks[i] - i - 1, 2);
}
res = 1 - 6*z2 / (MathPow(N,3) - N);
//----
return(res);
}
//+------------------------------------------------------------------+
//| Ranking array of prices function |
//+------------------------------------------------------------------+
void RankPrices(int InitialArray[])
{
//----
int i, k, m, dublicat, counter, etalon;
double dcounter, averageRank;
double TrueRanks[];
ArrayResize(TrueRanks, rangeN);
ArrayCopy(SortInt, InitialArray);
for(i = 0; i < rangeN; i++)
TrueRanks[i] = i + 1;
if(direction)
ArraySort(SortInt, 0, 0, MODE_DESCEND);
else
ArraySort(SortInt, 0, 0, MODE_ASCEND);
for(i = 0; i < rangeN-1; i++)
{
if(SortInt[i] != SortInt[i+1])
continue;
dublicat = SortInt[i];
k = i + 1;
counter = 1;
averageRank = i + 1;
while(k < rangeN)
{
if(SortInt[k] == dublicat)
{
counter++;
averageRank += k + 1;
k++;
}
else
break;
}
dcounter = counter;
averageRank = averageRank / dcounter;
for(m = i; m < k; m++)
TrueRanks[m] = averageRank;
i = k;
}
for(i = 0; i < rangeN; i++)
{
etalon = InitialArray[i];
k = 0;
while(k < rangeN)
{
if(etalon == SortInt[k])
{
R2[i] = TrueRanks[k];
break;
}
k++;
}
}
//----
return;
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(0, ExtMapBuffer1);
ArrayResize(R2, rangeN);
ArrayResize(PriceInt, rangeN);
ArrayResize(SortInt, rangeN);
if(Maxrange <= 0)
Maxrange = 10;
if(rangeN > Maxrange)
IndicatorShortName("Decrease rangeN input!");
else
IndicatorShortName("Spearman(" + rangeN + ")");
if(CalculatedBars < 0)
CalculatedBars = 0;
multiply = MathPow(10, Digits);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars = IndicatorCounted();
//----
if(rangeN > Maxrange)
return(-1);
int i, k, limit;
if(counted_bars == 0)
{
if(CalculatedBars == 0)
limit = Bars - rangeN;
else
limit = CalculatedBars;
}
if(counted_bars > 0)
limit = Bars - counted_bars;
for(i = limit; i >= 0; i--)
{
for(k = 0; k < rangeN; k++)
PriceInt[k] = Close[i+k]*multiply;
RankPrices(PriceInt);
ExtMapBuffer1[i] = SpearmanRankCorrelation(R2,rangeN);
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments