//+------------------------------------------------------------------+
//|                                                 FXDataExport.mq4 |
//|                                                      Piotr Karaœ |
//+------------------------------------------------------------------+
#property indicator_chart_window
#define MAX 28

#import "Kernel32.dll"
   void GetSystemTime(int& a0[]);
   void OutputDebugStringA(string msg);
#import

// external variables

extern int       TimeFrame     = PERIOD_H4;
extern int       tfr           = PERIOD_M5; // refreshing interval

extern int       KPeriod       =  8;
extern int       Slowing       =  3;
extern int       DPeriod       =  3;
extern int       MAMethod      =  2;
extern int       PriceField    =  0;
extern int       RPeriod       =  1;
extern int       ShortMAPeriod = 60;
extern int       LongMAPeriod  = 360;
extern bool     Comments      = true;
extern string   OutputFile    = "";
extern int       DisplayDecimals = 3; //decimals to show for data that is not a price.
extern int       WaitTicks = 5; //number of ticks to wait after init/restart to run Export();
extern bool     WriteToDebugView = true;
//Currency Pairs
extern string    Pair1         = "EURUSD";
extern string    Pair2         = "EURCAD";
extern string    Pair3         = "EURGBP";
extern string    Pair4         = "EURAUD";
extern string    Pair5         = "EURNZD";
extern string    Pair6         = "GBPUSD";
extern string    Pair7         = "GBPCAD";
extern string    Pair8         = "GBPAUD";
extern string    Pair9         = "GBPNZD";
extern string    Pair10        = "AUDUSD";
extern string    Pair11        = "AUDCAD";
extern string    Pair12        = "AUDNZD";
extern string    Pair13        = "NZDUSD";
extern string    Pair14        = "NZDCAD";
extern string    Pair15        = "USDCAD";
extern string    Pair16        = "EURJPY";
extern string    Pair17        = "USDJPY";
extern string    Pair18        = "CADJPY";
extern string    Pair19        = "GBPJPY";
extern string    Pair20        = "AUDJPY";
extern string    Pair21        = "NZDJPY";
extern string    Pair22        = "CHFJPY";
extern string    Pair23        = "EURCHF";
extern string    Pair24        = "USDCHF";
extern string    Pair25        = "CADCHF";
extern string    Pair26        = "GBPCHF";
extern string    Pair27        = "AUDCHF";
extern string    Pair28        = "NZDCHF";

//---- indicator buffers
//double     Stochastic[];
double     StrengthST[];
double     StrengthLT[];
double     RateOfChange1[];
double     RateOfChange2[];
double     Volatility1[];
double     Volatility2[];

string     Pair_Name[MAX];
datetime   prev_time     = -9999;

int handle2;

int current = 0; // variable points to the current bar

int iTickCount;
bool bRetry;

//Debug variables
string sDebugLog;
string sLog_CreateFile;
string sLog_Export;
string sLog_Init;
string sLog_Start;
string sNL = " \n  "; //new line break. 



//+------------------------------------------------------------------+
int init()  {
//+------------------------------------------------------------------+
  RefreshRates();
  IndicatorBuffers(8);
  SetIndexBuffer(1, StrengthST);
  SetIndexBuffer(2, StrengthLT);
  SetIndexBuffer(3, RateOfChange1);
  SetIndexBuffer(4, RateOfChange2);
  SetIndexBuffer(5, Volatility1);
  SetIndexBuffer(6, Volatility2);

  Pair_Name[0] = Pair1;
  Pair_Name[1] = Pair2;
  Pair_Name[2] = Pair3;
  Pair_Name[3] = Pair4;
  Pair_Name[4] = Pair5;
  Pair_Name[5] = Pair6;
  Pair_Name[6] = Pair7;
  Pair_Name[7] = Pair8;
  Pair_Name[8] = Pair9;
  Pair_Name[9] = Pair10;
  Pair_Name[10] = Pair11;
  Pair_Name[11] = Pair12;
  Pair_Name[12] = Pair13;
  Pair_Name[13] = Pair14;
  Pair_Name[14] = Pair15;
  Pair_Name[15] = Pair16;
  Pair_Name[16] = Pair17;
  Pair_Name[17] = Pair18;
  Pair_Name[18] = Pair19;
  Pair_Name[19] = Pair20;
  Pair_Name[20] = Pair21;
  Pair_Name[21] = Pair22;
  Pair_Name[22] = Pair23;
  Pair_Name[23] = Pair24;
  Pair_Name[24] = Pair25;
  Pair_Name[25] = Pair26;
  Pair_Name[26] = Pair27;
  Pair_Name[27] = Pair28;
    
  prev_time = -9999;
  
  //log("test");
  
  
      
  iTickCount = 0;
  
  //Export();
  
  prev_time = 0;
  
  bRetry = true;
  
  
  
  return(0);
}

//+------------------------------------------------------------------+
int deinit()  {
//+------------------------------------------------------------------+
   Comment("");
   
   
   
   return(0);
}

//+------------------------------------------------------------------+
int start()  {
//+------------------------------------------------------------------+
  
  
  
  sLog_Start = "START - start()-------------------------------------";
  
  if (prev_time != iTime(Symbol(),tfr,0) || bRetry)   {
  
    sLog_Start = sLog_Start + sNL + "    New bar";
    sLog_Start = sLog_Start + sNL + "    prev_time=" + TimeToStr(prev_time);
    sLog_Start = sLog_Start + sNL + "    current time=" + TimeToStr(iTime(Symbol(),tfr,0));
        
    Export();
            
    if(iTickCount < WaitTicks) bRetry = true;
    
    prev_time = iTime(Symbol(),tfr,0); // the formula that makes the MT4 export the data at the tfr intervals - at the completion of the tfr bar
  }
    
    if(iTickCount <WaitTicks) iTickCount++;
    if(iTickCount>=WaitTicks) bRetry = false;
    
    sLog_Start = sLog_Start + sNL + "END - start()-------------------------------------";
    
    
    //Send debug data to DebugView---------------------------------
    static datetime lastSend;
    datetime now = TimeCurrent();
    if (now - lastSend > 5){ // 1 minute
           lastSend = now;
    
    if(WriteToDebugView) {
    
      
      sDebugLog = sDebugLog + sNL + sLog_Start;
      sDebugLog = sDebugLog + sNL + sLog_CreateFile;
      sDebugLog = sDebugLog + sNL + sLog_Export;
    
      log(sDebugLog);
    
    }//end if(WriteToDebugView) {
  
  }//end if (now - lastSend > 5){
  //--------------------------------------------------------------------
  
  
  sDebugLog = "";
  
  return(0);
}

//+------------------------------------------------------------------+
void Export()  {  
//+------------------------------------------------------------------+
  
  
  
  double dAsk, dBid, dMA_Short, dMA_Long, dStdev_Short, dStdev_Long;
  string sResultString;
  string sSep = ",";
  
 sLog_Export = "START - Export()-------------------------------------";

  if (OutputFile == "")
    OutputFile = "FXDataExport.csv";
  
  if (Comments)
    Comment("Starting data export to " + OutputFile);
  
  sLog_Export = sLog_Export + sNL + "    Open " + OutputFile;
  
  if(iTickCount<(WaitTicks-1)) {
    //CreateFile("Dummy.txt");
  
    Comment("Tick" + iTickCount +". Skip opening " + OutputFile);
    
    
    return(0);
  
  }
  
  
  handle2 = FileOpen(OutputFile,FILE_CSV|FILE_WRITE,","); 
  
  
  
  
   sLog_Export = sLog_Export + sNL + "    handle2=" + handle2;

  if(handle2 < 1)   {
    sLog_Export = sLog_Export + sNL + "    Open file failed";
    
    Comment("Unable to open output file");
    return(0); 
  }  
  
   sLog_Export = sLog_Export + sNL + "    Open file successful";
  
  sLog_Export = sLog_Export + sNL + "   start loop";
  
// MultiPair Loop
  for (int k=0; k<MAX; k++)   {
  
  
  
// Current Stochastic      
// Stochastic[k] = iStochastic(Pair_Name[k],TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,MODE_MAIN,0);

// Current Strength short-term

  dAsk = MarketInfo(Pair_Name[k],MODE_ASK);
  dBid = MarketInfo(Pair_Name[k],MODE_BID);
  dMA_Short = iMA(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
  dStdev_Short = iStdDev(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
  dMA_Long = iMA(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
  dStdev_Long = iStdDev(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
  
  
  if(dStdev_Short>0 && dStdev_Short!= EMPTY_VALUE && dMA_Short>0 && dMA_Short!= EMPTY_VALUE){
    //StrengthST[k]= 10*( (MarketInfo(Pair_Name[k],MODE_ASK) + MarketInfo(Pair_Name[k],MODE_BID)) / 2  - iMA(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0)) / iStdDev(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
      StrengthST[k]= 10*( (dAsk + dBid) / 2  - dMA_Short) / dStdev_Short;
    }else{
    
        StrengthST[k]=0;
    }
    
// Current Strength long-term
  if(dStdev_Long>0 && dStdev_Long != EMPTY_VALUE && dMA_Long>0 && dMA_Long != EMPTY_VALUE){
    //StrengthLT[k]= 10*( (MarketInfo(Pair_Name[k],MODE_ASK) + MarketInfo(Pair_Name[k],MODE_BID)) / 2  - iMA(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0)) / iStdDev(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
      StrengthLT[k]= 10*( (dAsk + dBid) / 2  - dMA_Long) / dStdev_Long;
    }else{
    
        StrengthLT[k]=0;
    }
    
    sLog_Export = sLog_Export + sNL + "   StrengthST[" + k + "]=" + DoubleToStr(StrengthST[k],Digits);
    sLog_Export = sLog_Export + sNL + "   StrengthLT[" + k + "]=" + DoubleToStr(StrengthLT[k],Digits);
    
//| Rate of Change of SMAs                                           |
    double ROC1, CurrentBar1, PrevBar1;
    double ROC2, CurrentBar2, PrevBar2;
    double VOLAT1, CurrentSD1, PrevSD1;
    double VOLAT2, CurrentSD2, PrevSD2;
    
//---- ROC calculation
    CurrentBar1 = iMA(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
    PrevBar1 = iMA(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0+RPeriod);
    CurrentBar2 = iMA(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
    PrevBar2 = iMA(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0+RPeriod);

    CurrentSD1 = iStdDev(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
    PrevSD1 = iStdDev(Pair_Name[k],TimeFrame,ShortMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0+RPeriod);
    CurrentSD2 = iStdDev(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0);
    PrevSD2 = iStdDev(Pair_Name[k],TimeFrame,LongMAPeriod,0,MODE_SMA,PRICE_TYPICAL,0+RPeriod);
    
    ROC1=CurrentBar1-PrevBar1;
    ROC2=CurrentBar2-PrevBar2;
    VOLAT1=CurrentSD1-PrevSD1;
    VOLAT2=CurrentSD2-PrevSD2;
    
    if(PrevBar1!= EMPTY_VALUE && PrevBar1>0) RateOfChange1[k] = 1000*100 * ROC1 / PrevBar1;
    if(PrevSD1!= EMPTY_VALUE && PrevSD1>0) Volatility1[k] = 10*100 * VOLAT1 / PrevSD1;
    if(PrevBar2!= EMPTY_VALUE && PrevBar2>0) RateOfChange2[k] = 1000*100 * ROC2 / PrevBar2;
    if(PrevSD2!= EMPTY_VALUE && PrevSD2>0) Volatility2[k] = 10*100 * VOLAT2 / PrevSD2;
     
   double dStoch =  iStochastic(Pair_Name[k],TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,MODE_MAIN,0);
     
    sLog_Export = sLog_Export + sNL + "   Start FileWrite. Iter=" + k ;
    
    sResultString = Pair_Name[k] + sSep + TimeToStr(TimeLocal(),TIME_DATE|TIME_MINUTES) + sSep;
    sResultString = sResultString + DoubleToStr(dStoch,DisplayDecimals) + sSep + DoubleToStr(StrengthST[k],DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr(StrengthLT[k],DisplayDecimals) + sSep;
    
    sResultString = sResultString + DoubleToStr(AccountBalance(),DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr(AccountEquity(),DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr(AccountMargin(),DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr(AccountProfit(),DisplayDecimals) + sSep;
    sResultString = sResultString + AccountCurrency() + sSep;
    sResultString = sResultString + DoubleToStr(0.5*AccountMargin()/AccountEquity(),DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr(RateOfChange1[k],DisplayDecimals) + sSep + DoubleToStr(Volatility1[k],DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr(RateOfChange2[k],DisplayDecimals) + sSep + DoubleToStr(Volatility2[k],DisplayDecimals) + sSep;
    sResultString = sResultString + DoubleToStr((dAsk + dBid)/2,Digits);
    
    sLog_Export = sLog_Export + sNL + "   sResultString["+ k + "]=" + sResultString;
    
    /*
    FileWrite(handle, 
      Pair_Name[k],
      TimeToStr(TimeLocal(),TIME_DATE|TIME_MINUTES), 
      iStochastic(Pair_Name[k],TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,MODE_MAIN,0), 
      StrengthST[k], StrengthLT[k],
      AccountBalance(), AccountEquity(), AccountMargin(), AccountProfit(), AccountCurrency(), 0.5*AccountMargin()/AccountEquity(),
      RateOfChange1[k], Volatility1[k], RateOfChange2[k], Volatility2[k],
      (MarketInfo(Pair_Name[k],MODE_ASK) + MarketInfo(Pair_Name[k],MODE_BID)) / 2);
      */
      FileWrite(handle2, sResultString);
      
      
      sLog_Export = sLog_Export + sNL + "   End FileWrite. Iter=" + k ;
      
  }  
  
   sLog_Export = sLog_Export + sNL + "   Loop finished. Close file";
   
  FileClose(handle2);
  
  sLog_Export = sLog_Export + sNL + "  File closed.";
  
  if (Comments)
    Comment("Export complete to FXDataExport.csv at C:\Program Files\OANDA - MetaTrader\experts\files at "+TimeToStr(TimeLocal(),TIME_MINUTES));  
    
    sLog_Export = sLog_Export + sNL + "END - Export()-------------------------------------";
    
  return(0);
}

//+------------------------------------------------------------------+
// Glossary
//+------------------------------------------------------------------+
/*
//+------------------------------------------------------------------+
// MAMethod
//+------------------------------------------------------------------+

      case MODE_SMA:  answer = "SMA"  ; break;//0
      case MODE_EMA:  answer = "EMA"  ; break;//1
      case MODE_SMMA: answer = "SMMA" ; break;//2 - default: smoothed moving average
      case MODE_LWMA: answer = "LWMA" ; break;//3
      
//+------------------------------------------------------------------+
// PriceField
//+------------------------------------------------------------------+  
  
      case 0:  answer = "Low/High"    ; break; - default
      case 1:  answer = "Close/Close" ; break;
*/
//+------------------------------------------------------------------+
void CreateFile(string sFullFilePath)
{
//creates the file sFullFilePath   
   
   sLog_CreateFile = "START - CreateFile--------------------------";
   
   int handle = FileOpen(sFullFilePath,FILE_READ|FILE_WRITE);
   
    sLog_CreateFile = sLog_CreateFile + sNL + "    handle=" + handle;
    
    if (handle>0)
   {
    sLog_CreateFile = sLog_CreateFile + sNL + "   File " + sFullFilePath + " successfully opened";
     // FileSeek(handle, 0, SEEK_END); // go to end of file
     // FileWrite(handle, input);
     
      FileClose(handle);
      
      sLog_CreateFile = sLog_CreateFile + sNL + "   File " + sFullFilePath + " closed";
      
   }
   
   sLog_CreateFile = sLog_CreateFile + sNL + "END - CreateFile--------------------------";
   
}//end void CreateFile(string sFullFilePath)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Replacement for the built-in Print(), output to the debug monitor.
* Send information to OutputDebugString() to be viewed and logged
* by SysInternals DebugView (free download from microsoft)
* This is ideal for debugging as an alternative to Print().
* The function will take up to 8 string (or numeric) arguments
* to be concatenated into one debug message.
*/
//All credit to 7bit @ ForexFactory.com forum.

void log(
   string s1,
   string s2 = "",
   string s3 = "",
   string s4 = "",
   string s5 = "",
   string s6 = "",
   string s7 = "",
   string s8 = ""
) {
   string out = StringTrimRight(StringConcatenate(
                                   WindowExpertName(), ".mq4 ", Symbol(),
                                   " ", s1,
                                   " ", s2,
                                   " ", s3,
                                   " ", s4,
                                   " ", s5,
                                   " ", s6,
                                   " ", s7,
                                   " ", s8
                                ));
   OutputDebugStringA(out);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

