SRCma
Download scriptThis script is designed to analyze price movements by focusing on the relative ranking of prices rather than their absolute numerical values. By using a statistical method known as Spearman’s Rank Correlation, it identifies the strength and direction of trends based on the "order" of price changes over a specific period.
Core Logic and Process
1. Price Ranking System Unlike standard indicators that simply track whether a price is going up or down in terms of dollars or pips, this logic converts price data into a sequence of ranks. It looks at a defined window of recent history (the "range") and determines the position of each price relative to the others in that set. If a price is the highest in the window, it receives the top rank; if it is the lowest, it receives the bottom rank.
2. Handling Identical Prices The script includes a sophisticated mechanism to handle "ties"—situations where two or more prices are exactly the same. In these instances, it calculates an average rank for those specific positions to ensure the correlation data remains accurate and balanced.
3. Correlation Calculation Once the prices are converted into ranks, the script applies a mathematical formula to determine the correlation coefficient. This value tells you how closely the price sequence follows a consistent pattern over time:
- A high positive value indicates a strong, consistent upward trend in ranking.
- A low negative value indicates a strong, consistent downward trend in ranking.
- A value near zero suggests that prices are moving randomly or without a clear directional preference.
4. Smoothing and Visualization To make the data easier for a human to read, the script performs two final steps:
- Primary Line: It plots the raw correlation results, which show the immediate trend strength.
- Secondary Line: It applies a Simple Moving Average (SMA) to those correlation values. This smooths out minor "noise" or erratic fluctuations, allowing you to see the broader underlying trend more clearly.
Summary of Purpose
The goal of this logic is to filter out market noise by focusing on the relative behavior of price. By looking at the order of prices rather than just their raw numbers, it aims to provide a clearer picture of momentum and trend reliability, helping to distinguish between meaningful directional moves and minor fluctuations.
//+------------------------------------------------------------------+
//| 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"
//----
// Bookkeeper: Äîáàâèë áóôåð ExtMapBuffer2 - ñãëàæèâàíèå ìóâèíãîì
//----
#property indicator_separate_window
#property indicator_maximum 1.4
#property indicator_minimum -1.4
#property indicator_level1 1
#property indicator_level2 -1
#property indicator_level3 0.6
#property indicator_level4 -0.6
#property indicator_levelcolor DimGray
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue
//---- input parameters
extern int CalculatedBars = 500;
extern int rangeN = 14;
extern int MAPeriod = 5;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double R2[];
double multiply;
int PriceInt[];
int SortInt[];
int Maxrange = 30;
bool direction = true;
//----
//+------------------------------------------------------------------+
//| 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);
SetIndexStyle(1, DRAW_LINE);
SetIndexBuffer(1, ExtMapBuffer2);
ArrayResize(R2, rangeN);
ArrayResize(PriceInt, rangeN);
ArrayResize(SortInt, rangeN);
if(Maxrange <= 0)
Maxrange = 10;
if(rangeN > Maxrange)
IndicatorShortName("Decrease rangeN input!");
else
IndicatorShortName("SRCma(" + 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);
}
for(i = limit; i >= 0; i--)
{
ExtMapBuffer2[i] = iMAOnArray(ExtMapBuffer1,0,MAPeriod,0,MODE_SMA,i);
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments