#property show_inputs
#define TWO_SYMBOLS 2
#define DEPTH 0
#define MEAN 1
#define STDEV 2
#define CORRELATION 0
#define NUM 1
#define MAX_POINTS 1000000
extern datetime StartTime = D'2011.01.01';
extern int StartDepth = 12;
extern int EndDepth = 576;
extern int StepDepth = 12;
extern int Shift = 0;
extern int Method = 2;
string SymbolsAll[], Symbols[TWO_SYMBOLS], SymbolsDescription[];
double BaseMatrix[TWO_SYMBOLS][MAX_POINTS], MOMatrix[TWO_SYMBOLS][MAX_POINTS];
double CvarMatrix[TWO_SYMBOLS][TWO_SYMBOLS];
double Means[TWO_SYMBOLS], SVector[TWO_SYMBOLS];
int Times[MAX_POINTS], Shifts[TWO_SYMBOLS];
int AmountSymbols, MatrixRows;
int CurrPos, CurrTime;
string StrOut[];
double Data[][3], Corr[][2];
int Amount, AmountDepth, Count = 0;
datetime GetStartTime( datetime StartTime )
{
  datetime Tmp;
  int Pos;
  for (int i = 0; i < TWO_SYMBOLS; i++)
  {
    Pos = iBarShift(Symbols[i], Period(), StartTime);
    Tmp = iTime(Symbols[i], Period(), Pos);
    if (Tmp > StartTime)
      StartTime = Tmp;
  }
  return(StartTime);
}
double GetPrice( string Symb, int time )
{
  double Price;
  Price = iClose(Symb, Period(), iBarShift(Symb, Period(), time));
  return(Price);
}
int GetNextTime( int CurrTime )
{
  static int Pos[TWO_SYMBOLS];
  int i, MinTime, Tmp = -1;
  for (i = 0; i < TWO_SYMBOLS; i++)
  {
    Pos[i] = iBarShift(Symbols[i], Period(), CurrTime) - 1;
    if (Pos[i] >= 0)
      Tmp = i;
  }
  if (Tmp < 0)
    return(Time[0]);
  MinTime = iTime(Symbols[Tmp], Period(), Pos[Tmp]);
  i = Tmp - 1;
  while (i >= 0)
  {
    if (Pos[i] >= 0)
    {
      Tmp = iTime(Symbols[i], Period(), Pos[i]);
      if (Tmp < MinTime)
        MinTime = Tmp;
    }
    i--;
  }
  return(MinTime);
}
void GetBaseMatrix()
{
  int i, NextTime;
  NextTime = GetNextTime(CurrTime);
  while (NextTime < Time[0])
  {
    CurrTime = NextTime;
    for (i = 0; i < TWO_SYMBOLS; i++)
      BaseMatrix[i][MatrixRows + Shifts[i]] = MathLog(GetPrice(Symbols[i], CurrTime));
    Times[MatrixRows] = CurrTime;
    MatrixRows++;
    NextTime = GetNextTime(CurrTime);
  }
  return;
}
void GetMeans( int Pos, int Len)
{
  int i, j;
  double Sum;
  for (i = 0; i < TWO_SYMBOLS;, i++)
  {
    Sum = 0;
    for (j = Pos; j > Pos - Len; j--)
      Sum += BaseMatrix[i][j];
    Means[i] = Sum / Len;
  }
  return;
}
void GetMOMatrix( int Pos, int Len)
{
  int i, j;
  for (i = 0; i < TWO_SYMBOLS;, i++)
    for (j = Pos; j > Pos - Len; j--)
      MOMatrix[i][j] = BaseMatrix[i][j] - Means[i];
  return;
}
void GetCvarMatrix( int Pos, int Len )
{
  int i, j, k;
  double Cvar;
  GetMeans(Pos, Len);
  GetMOMatrix(Pos, Len);
  for (i = 0; i < TWO_SYMBOLS; i++)
  {
     Cvar = 0;
     for (k = Pos; k > Pos - Len; k--)
       Cvar += MOMatrix[i][k] * MOMatrix[i][k];
     CvarMatrix[i][i] = Cvar / Len;
  }
  Cvar = 0;
  for (k = Pos; k > Pos - Len; k--)
    Cvar += MOMatrix[0][k] * MOMatrix[1][k];
  Cvar /= Len;
  CvarMatrix[0][1] = Cvar;
  return;
}
string iIF( bool Cond, string Str1, string Str2 )
{
  if (Cond)
    return(Str1);
  return(Str2);
}
void GetNextMeans( int Pos, int Len )
{
  int Pos2 = Pos - Len;
  for (int i = 0; i < TWO_SYMBOLS; i++)
  {
    SVector[i] = (BaseMatrix[i][Pos2] - BaseMatrix[i][Pos]) / Len;
    Means[i] -= SVector[i];
  }
  return;
}
void GetNextCvarMatrix2( int Pos, int Len )
{
  int i, j;
  int Pos2 = Pos - Len;
  double Tmp1[TWO_SYMBOLS], Tmp2[TWO_SYMBOLS], Tmp3[TWO_SYMBOLS];
  GetNextMeans(Pos, Len);
  for (i = 0; i < TWO_SYMBOLS; i++)
  {
    Tmp1[i] = SVector[i];
    Tmp2[i] = BaseMatrix[i][Pos] - Means[i];
    Tmp3[i] = BaseMatrix[i][Pos2] - Means[i];
    CvarMatrix[i][i] += Tmp1[i] * Tmp1[i] + (Tmp2[i] * Tmp2[i] - Tmp3[i] * Tmp3[i]) / Len;
    if (CvarMatrix[i][i] < 0)
      CvarMatrix[i][i] = 0;
  }
  CvarMatrix[0][1] += Tmp1[0] * Tmp1[1] + (Tmp2[0] * Tmp2[1] - Tmp3[0] * Tmp3[1]) / Len;
  return;
}
double GetCorrelation()
{
  double Res = 0;
  double Var = MathSqrt(CvarMatrix[0][0] * CvarMatrix[1][1]);
  if (Var != 0)
    Res = CvarMatrix[0][1] / Var;
  return(Res);
}
void GetVectorData1( double &Vector[], double &Mean, double &StDev )
{
  int i, Amount = ArraySize(Vector);
  double Tmp;
  Mean = 0;
  StDev = 0;
  for (i = 0; i < Amount; i++)
    Mean += Vector[i];
  Mean /= Amount;
  for (i = 0; i < Amount; i++)
  {
    Tmp = Vector[i] - Mean;
    StDev += Tmp * Tmp;
  }
  StDev = MathSqrt(StDev / Amount);
  return;
}
void GetVectorData2( double &Vector[], double &Mean, double &StDev )
{
  int i, Amount = ArraySize(Vector);
  int Amount2 = 0;
  double Tmp;
  Mean = 0;
  StDev = 0;
  for (i = 0; i < Amount; i++)
    Mean += Vector[i];
  Mean /= Amount;
  if (Mean > 0)
    for (i = 0; i < Amount; i++)
    {
      Tmp = Vector[i] - Mean;
      if (Tmp < 0)
      {
        StDev += Tmp * Tmp;
        Amount2++;
      }
    }
  else
    for (i = 0; i < Amount; i++)
    {
      Tmp = Vector[i] - Mean;
      if (Tmp > 0)
      {
        StDev += Tmp * Tmp;
        Amount2++;
      }
    }
  if (Amount2 > 0)
    StDev = MathSqrt(StDev / Amount2);
  return;
}
void InitCorrelation2( string &Symbol1, string &Symbol2 )
{
  Symbols[0] = iIF(Shift < 0, Symbol2, Symbol1);
  Symbols[1] = iIF(Shift < 0, Symbol1, Symbol2);
  Shifts[0] = 0;
  Shifts[1] = MathAbs(Shift);
  CurrTime = GetStartTime(iTime(Symbol1, Period(), iBarShift(Symbol1, Period(), StartTime) + EndDepth));
  MatrixRows = 0;
  CurrPos = EndDepth;
  GetBaseMatrix();
  while (Times[CurrPos] < StartTime)
    CurrPos++;
  return;
}
void GetData()
{
  int i, j, Depth;
  int StartCurrPos = CurrPos;
  static double Correlations[];
  double Mean, StDev;
  ArrayResize(Correlations, MatrixRows - CurrPos);
  StartCurrPos = CurrPos;
  for (i = 0; i < AmountDepth; i++)
  {
    Depth = Data[i][DEPTH];
    GetCvarMatrix(CurrPos - 1, Depth);
    j = 0;
    while (CurrPos < MatrixRows)
    {
      GetNextCvarMatrix2(CurrPos, Depth);
      Correlations[j] = GetCorrelation();
      j++;
      CurrPos++;
    }
    if (Method == 1)
      GetVectorData1(Correlations, Mean, StDev);
    else
      GetVectorData2(Correlations, Mean, StDev);
    Data[i][MEAN] = Mean;
    Data[i][STDEV] = StDev;
    CurrPos = StartCurrPos;
  }
  return;
}
void SaveData( string FileName )
{
  int handle =FileOpen(FileName, FILE_CSV|FILE_WRITE);
  for (int i = 0; i < AmountDepth; i++)
    FileWrite(handle, DoubleToStr(Data[i][DEPTH], 0) + " " + DoubleToStr(Data[i][MEAN], 8) + " " + DoubleToStr(Data[i][STDEV], 8));
  FileClose(handle);
  return;
}
double GetCorrelation2( string &Symbol1, string &Symbol2, string &StrOut )
{
  int i, iMax;
  double Mean, StDev, Max = -2, Tmp;
  int Len = StringLen(DoubleToStr(EndDepth, 0));
  InitCorrelation2(Symbol1, Symbol2);
  GetData();
  for (i = 0; i < AmountDepth; i++)
  {
    Mean = Data[i][MEAN];
    StDev = Data[i][STDEV];
    if (Mean < 0)
      Mean = -Mean;
    if (Mean - StDev > Max)
    {
      Max = Mean - StDev;
      iMax = i;
    }
  }
  SaveData(WindowExpertName() + "\\" + Symbol1 + " - " + Symbol2 + ".prn");
  if (Max > 0)
  {
    if (Data[iMax][MEAN] > 0)
      StrOut = "Corr2 =  " + DoubleToStr(Max, 4) + " (Goo";
    else
      StrOut = "Corr2 = " + DoubleToStr(-Max, 4) + " (Goo";
  }
  else if (Data[iMax][MEAN] > 0)
    StrOut = "Corr2 = " + DoubleToStr(Max, 4) + "  (Ba";
  else
    StrOut = "Corr2 =  " + DoubleToStr(-Max, 4) + "  (Ba";
  StrOut = StrOut + "d), Depth = " + StrNumToLen(DoubleToStr(Data[iMax][DEPTH], 0), Len, TRUE);
  return(Max);
}
int SymbolsList( string &Symbols[] )
{
   int Offset, SymbolsNumber;
   int hFile = FileOpenHistory("symbols.sel", FILE_BIN|FILE_READ);
   SymbolsNumber = (FileSize(hFile) - 4) / 128;
   Offset = 116;
   ArrayResize(Symbols, SymbolsNumber);
   FileSeek(hFile, 4, SEEK_SET);
   for(int i = 0; i < SymbolsNumber; i++)
   {
      Symbols[i] = FileReadString(hFile, 12);
      FileSeek(hFile, Offset, SEEK_CUR);
   }
   FileClose(hFile);
   return(SymbolsNumber);
}
//+------------------------------------------------------------------+
//| Ôóíêöèÿ âîçâðàùàåò ðàñøèôðîâàííîå íàçâàíèå ñèìâîëà               |
//+------------------------------------------------------------------+
string SymbolDescription(string SymbolName)
{
   string SymbolDescription = "";
// Îòêðûâàåì ôàéë ñ îïèñàíèåì ñèìâîëîâ
   int hFile = FileOpenHistory("symbols.raw", FILE_BIN|FILE_READ);
   if(hFile < 0) return("");
// Îïðåäåëÿåì êîëè÷åñòâî ñèìâîëîâ, çàðåãèñòðèðîâàííûõ â ôàéëå
   int SymbolsNumber = FileSize(hFile) / 1936;
// Èùåì ðàñøèôðîâêó ñèìâîëà â ôàéëå
   for(int i = 0; i < SymbolsNumber; i++)
   {
      if(FileReadString(hFile, 12) == SymbolName)
      {
         SymbolDescription = FileReadString(hFile, 64);
         break;
      }
      FileSeek(hFile, 1924, SEEK_CUR);
   }
   FileClose(hFile);
   return(SymbolDescription);
}
//+------------------------------------------------------------------+
//| Ôóíêöèÿ îïðåäåëÿåò òèï èíñòðóìåíòà                               |
//+------------------------------------------------------------------+
string SymbolType( string SymbolName )
{
   int GroupNumber = -1;
   string SymbolGroup = "";
// Îòêðûâàåì ôàéë ñ îïèñàíèåì ñèìâîëîâ
   int hFile = FileOpenHistory("symbols.raw", FILE_BIN|FILE_READ);
   if(hFile < 0) return("");
// Îïðåäåëÿåì êîëè÷åñòâî ñèìâîëîâ, çàðåãèñòðèðîâàííûõ â ôàéëå
   int SymbolsNumber = FileSize(hFile) / 1936;
// Èùåì ñèìâîë â ôàéëå
   for(int i = 0; i < SymbolsNumber; i++)
   {
      if(FileReadString(hFile, 12) == SymbolName)
      {
      // Îïðåäåëÿåì íîìåð ãðóïïû
         FileSeek(hFile, 1936*i + 100, SEEK_SET);
         GroupNumber = FileReadInteger(hFile);
         break;
      }
      FileSeek(hFile, 1924, SEEK_CUR);
   }
   FileClose(hFile);
   if(GroupNumber < 0) return("");
// Îòêðûâàåì ôàéë ñ îïèñàíèåì ãðóïï
   hFile = FileOpenHistory("symgroups.raw", FILE_BIN|FILE_READ);
   if(hFile < 0) return("");
   FileSeek(hFile, 80*GroupNumber, SEEK_SET);
   SymbolGroup = FileReadString(hFile, 16);
   FileClose(hFile);
   return(SymbolGroup);
}
void init()
{
  int i;
  Comment(WindowExpertName() + " (StartTime = " + TimeToStr(StartTime) + ":\nStarting (wait) ...");
  AmountSymbols = SymbolsList(SymbolsAll);
  ArrayResize(SymbolsDescription, AmountSymbols);
  Amount = AmountSymbols * (AmountSymbols - 1) / 2;
  ArrayResize(Corr, Amount);
  ArrayResize(StrOut, Amount);
  for (i = 0; i < AmountSymbols; i++)
    SymbolsDescription[i] = /*SymbolType(SymbolsAll[i]) + "\\" + */SymbolDescription(SymbolsAll[i]);
  ArrayResize(Data, EndDepth);
  for (i = StartDepth; i <= EndDepth; i += StepDepth)
  {
    Data[AmountDepth][DEPTH] = i;
    AmountDepth++;
  }
  ArrayResize(Data, AmountDepth);
  return;
}
string StrNumToLen( string Num, int Len, bool Space = FALSE )
{
  string Str;
  if (Space)
    Str = " ";
  else
    Str = "0";
  Len -= StringLen(Num);
  while (Len > 0)
  {
    Num = Str + Num;
    Len--;
  }
  return(Num);
}
void SaveCorr( string FileName )
{
  int Pos, handle = FileOpen(FileName, FILE_CSV|FILE_WRITE);
  int Len = StringLen(DoubleToStr(Count, 0));
  Comment(WindowExpertName() + " (StartTime = " + TimeToStr(StartTime) + ":\nSaving data...");
  ArraySort(Corr, WHOLE_ARRAY, 0, MODE_DESCEND);
  for (int i = 0; i < Count; i++)
  {
    Pos = Corr[i][NUM];
    FileWrite(handle, StrNumToLen(i + 1, Len) + ". " + StrOut[Pos]);
  }
  FileClose(handle);
  return;
}
void SetComment( int TimeInterval, int Count )
{
  string Str = WindowExpertName() + " (StartTime = " + TimeToStr(StartTime) + "):\n";
  Str = Str + "Amount = " + Amount + " pairs\n";
  Str = Str + "Ready: " + DoubleToStr(100.0 * Count / Amount, 2) + "%\n";
  if (TimeInterval != 0)
    Str = Str + "Performance = "  + DoubleToStr(Count * 1000.0 / TimeInterval, 2) + " pairs/sec.\n";
  Str = Str + "Elapsed time: " + TimeToStr(TimeInterval / 1000, TIME_SECONDS) + "\n";
  Str = Str + "Remaining time: " + TimeToStr(1.0 * (Amount - Count) * TimeInterval / (1000 * Count), TIME_SECONDS);
  Comment(Str);
  return;
}
void deinit()
{
  ArrayResize(Corr, Count);
  SaveCorr(WindowExpertName() + ".txt");
  Comment("");
  return;
}
void start()
{
  int i, j;
  double Correlation;
  int Start, CurrentTime, PrevTime = 0;
  int BeginTime, EndTime;
  int Len = StringLen(DoubleToStr(Amount, 0));
  string Symbol1, Symbol2, Str;
  Start = GetTickCount();
  for (i = 0; i < AmountSymbols - 1; i++)
  {
    Symbol1 = SymbolsAll[i];
    for (j = i + 1; j < AmountSymbols; j++)
    {
      Symbol2 = SymbolsAll[j];
      RefreshRates();
      Corr[Count][NUM] = Count;
      Corr[Count][CORRELATION] = GetCorrelation2(Symbol1, Symbol2, Str);
      BeginTime = Times[CurrPos];
      EndTime = Times[MatrixRows - 1];
      MatrixRows -= CurrPos;
      StrOut[Count] = Str + ", " + Symbol1 + " - " + Symbol2 +  ", bars = " + MatrixRows +
                            " (" + TimeToStr(BeginTime) + " - " + TimeToStr(EndTime) +
                            "), " + SymbolsDescription[i] + " - " + SymbolsDescription[j];
      Print(StrNumToLen(Count + 1, Len) + "/" + Amount + ": " + StrOut[Count]);
      Count++;
      CurrentTime = GetTickCount();
      if ((CurrentTime - PrevTime > 1000) || (CurrentTime - PrevTime < -1000))
      {
        PrevTime = CurrentTime;
        SetComment(CurrentTime - Start, Count);
      }
      if (IsStopped())
        return;
    }
  }
  return;
}
             
            
            
            
            
Comments