convertticksfile

Author: Scriptong
Miscellaneous
It issuies visual alerts to the screenUses files from the file systemIt opens Message Boxes to the userIt writes information to file
0 Views
0 Downloads
0 Favorites
convertticksfile
//+------------------------------------------------------------------+
//|                                             convertticksfile.mq4 |
//|                                        Copyright 2012, Scriptong |
//|                                          http://advancetools.net |
//+------------------------------------------------------------------+
#property copyright "Scriptong"
#property link      "http://advancetools.net"
#property description "English: Converting file ticks to the CSV-format specified period of chart.\nRussian: Êîíâåðòèðîâàíèå ôàéëà òèêîâ â CSV-ôîðìàò çàäàííîãî ïåðèîäà ãðàôèêà."
#property strict
#property show_inputs
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_CONVERT_WAY
  {
   CONVERT_WAY_CSV_TICKS,                                                                          // To CSV - file of ticks / Â CSV - ôàéë òèêîâ
   CONVERT_WAY_CSV_CANDLES,                                                                        // To CSV - file of candles /  CSV - ôàéë ñâå÷åé
   CONVERT_WAY_HST_CANDLES                                                                         // To history file / Â ôàéë èñòîðèè
  };
//---
input ENUM_CONVERT_WAY  i_convertWay      = CONVERT_WAY_CSV_CANDLES;                               // Way to convert / Ñïîñîá ïðåîáðàçîâàíèÿ
input uint              i_tfMinutes       = 5;                                                     // Minutes in candle / Ìèíóò â ñâå÷å
input string            i_sourceFile      = "EURUSD.tks";                                          // Source file name / Èìÿ èñõîäíîãî ôàéëà
input string            i_destinationFile = "EURUSD.csv";                                          // Destination file name / Èìÿ ôîðìèðóåìîãî ôàéëà
input int               i_digits          = 5;                                                     // Amount of significant digits / Êîëè÷åñòâî çíà÷àùèõ öèôð
//---
uint g_tfSeconds;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct TickStruct
  {
   datetime          time;
   double            bid;
   double            ask;
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct HistoryHeader
  {
   int               version;
   uchar             copyright[64];
   uchar             symbol[12];
   int               timeFrame;
   int               digits;
   int               reserved1;
   int               reserved2;
   int               unused[13];
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_MESSAGE_CODE
  {
   MESSAGE_CODE_SAME_FILES,
   MESSAGE_CODE_WRONG_TF,
   MESSAGE_CODE_FILE_OPEN_ERROR,
   MESSAGE_CODE_FATAL_ERROR,
   MESSAGE_CODE_READ_ERROR,
   MESSAGE_CODE_WRITE_ERROR,
   MESSAGE_CODE_HISTORY_IS_ABSENT,
   MESSAGE_CODE_ENOUGHT_MEMORY,
   MESSAGE_CODE_HISTORY_READ_ERROR,
   MESSAGE_CODE_CONFIRM_REWRITE_HISTORY,
   MESSAGE_CODE_TITLE_REWRITE_HISTORY,
   MESSAGE_CODE_HISTORY_WRITE_ERROR,
   MESSAGE_CODE_COMPLETED,
   MESSAGE_CODE_SUCCESS_COMPLETE
  };
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Script program start function                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnStart()
  {
   if(!TuningParameters())
      return;

// Preparing the buffers for copying history data   
   MqlRates rates[];
   ulong ratesCnt=0;

// Opening the files
   int sourceHandle,destHandle;
   if(!IsFilesOpen(sourceHandle,destHandle,rates,ratesCnt))
      return;

// Converting the data    
   bool isDone=ConvertData(sourceHandle,destHandle,rates,ratesCnt);
   FileClose(sourceHandle);
   FileClose(destHandle);

// End of work
   if(isDone)
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_SUCCESS_COMPLETE));
   Comment("");
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Checking the correctness of values of tuning parameters                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool TuningParameters()
  {
   if(i_sourceFile==i_destinationFile)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_SAME_FILES));
      return false;
     }

   if(i_tfMinutes==0 && i_convertWay!=CONVERT_WAY_CSV_TICKS)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_WRONG_TF));
      return false;
     }

   g_tfSeconds=i_tfMinutes*60;
   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Opening the files for read and write of data                                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsFilesOpen(int &sourceHandle,int &destHandle,MqlRates &rates[],ulong &ratesCnt)
  {
// Open the source file
   sourceHandle=FileOpen(i_sourceFile,FILE_BIN|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE,',');
   if(sourceHandle<1)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_FILE_OPEN_ERROR),i_sourceFile,".");
      return false;
     }

// Open the destination file
   if(i_convertWay!=CONVERT_WAY_HST_CANDLES) // Open the CSV-file
     {
      destHandle=FileOpen(i_destinationFile,FILE_CSV|FILE_WRITE|FILE_SHARE_WRITE,',');
      if(destHandle<1)
        {
         Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_FILE_OPEN_ERROR),i_destinationFile,".");
         return false;
        }
     }
   else                                                                                            // Open or create the HST-file
     {
      HistoryHeader historyHeader={401,
           {
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
           }
            ,
           {0,0,0,0,0,0,0,0,0,0,0,0},0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0}
        };
      StringToCharArray("(C)opyright 2003, MetaQuotes Software Corp.",historyHeader.copyright);
      StringToCharArray(Symbol(),historyHeader.symbol);
      historyHeader.timeFrame=(int)i_tfMinutes;
      historyHeader.digits=i_digits;

      if(!CopyExistsHistoryFile(historyHeader,rates,ratesCnt))
         return false;

      if(ratesCnt>0)
         if(MessageBox(GetStringByMessageCode(MESSAGE_CODE_CONFIRM_REWRITE_HISTORY),GetStringByMessageCode(MESSAGE_CODE_TITLE_REWRITE_HISTORY),MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)==IDNO)
            return false;

      destHandle=FileOpenHistory(Symbol()+IntegerToString(i_tfMinutes)+".hst",FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_BIN);
      if(destHandle<1)
        {
         Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_FILE_OPEN_ERROR),Symbol()+IntegerToString(i_tfMinutes)+".hsts.");
         return false;
        }

      if(FileWriteStruct(destHandle,historyHeader)==0)
        {
         Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_HISTORY_WRITE_ERROR),GetLastError());
         FileClose(destHandle);
         return false;
        }
     }

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Copy data from existing history file                                                                                                                                                              |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool CopyExistsHistoryFile(HistoryHeader &historyHeader,MqlRates &rates[],ulong &ratesCnt)
  {
// Try to open history file
   ratesCnt=0;
   int handle=FileOpenHistory(Symbol()+IntegerToString(i_tfMinutes)+".hst",FILE_READ|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI|FILE_BIN);
   if(handle<0)
     {
      Print(GetStringByMessageCode(MESSAGE_CODE_HISTORY_IS_ABSENT));
      return true;
     }

// Allocating the memory for history data
   ulong barsCnt=(FileSize(handle)-sizeof(historyHeader))/sizeof(MqlRates);
   if(ArrayResize(rates,(int)barsCnt)<0)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_ENOUGHT_MEMORY));
      return false;
     }

// Reading the header of history file
   if(FileReadStruct(handle,historyHeader)==0)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_HISTORY_READ_ERROR),GetLastError());
      FileClose(handle);
      return false;
     }

// Reading the history file
   while(ratesCnt<barsCnt)
     {
      if(FileReadStruct(handle,rates[(int)ratesCnt])==0)
        {
         Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_HISTORY_READ_ERROR),GetLastError());
         FileClose(handle);
         return false;
        }

      ratesCnt++;
     }

   FileClose(handle);
   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Converting the data                                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool ConvertData(int &sourceHandle,int &destHandle,MqlRates &rates[],ulong &ratesCnt)
  {
// Determination of the amount of ticks written in the file
   ulong sizeInRec=GetFileTicksCount(sourceHandle);
   if(sizeInRec==0)
      return false;
   sizeInRec--;

   TickStruct oneTick;
   ulong recCnt=0;

// Reading ticks and their transformation into a candle
   string completed=GetStringByMessageCode(MESSAGE_CODE_COMPLETED);
   while(recCnt<=sizeInRec)
     {
      uint bytesCnt=FileReadStruct(sourceHandle,oneTick);
      if(bytesCnt==0)
        {
         Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_READ_ERROR),recCnt,".");
         return false;
        }

      if(!ChoiceConvertionWay(destHandle,oneTick,rates,ratesCnt,recCnt==sizeInRec))
         return false;

      recCnt++;
      Comment(completed,DoubleToString(recCnt/1.0/sizeInRec*100,2),"%...");
     }

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determination of the amount of ticks written in the file                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
ulong GetFileTicksCount(int sourceHandle)
  {
// Define the size of ticks structure
   uint recSize=sizeof(TickStruct);
   if(recSize==0)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_FATAL_ERROR));
      return 0;
     }

   return FileSize(sourceHandle) / recSize;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| The choice of conversion method                                                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool ChoiceConvertionWay(int destHandle,TickStruct &tick,MqlRates &rates[],ulong &ratesCnt,bool isLastTick)
  {
// Saving ticks to a CSV-file
   if(i_convertWay==CONVERT_WAY_CSV_TICKS)
     {
      if(FileWrite(destHandle,TimeToStr(tick.time,TIME_DATE|TIME_SECONDS),DoubleToStr(tick.bid,i_digits),DoubleToStr(tick.ask,i_digits))==0)
        {
         Alert(WindowExpertName(),MESSAGE_CODE_WRITE_ERROR);
         return false;
        }
      return true;
     }

// Saving candles to CSV- or HST-file
   return ConvertTicksToTF(destHandle, tick, rates, ratesCnt, isLastTick);
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Convert ticks to the candles of specified period                                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool ConvertTicksToTF(int destHandle,TickStruct &tick,MqlRates &rates[],ulong &ratesCnt,bool isLastTick)
  {
   static MqlRates candle={0,0,0,0,0,0,0,0};
   datetime tickCandleTime=(tick.time/g_tfSeconds)*g_tfSeconds;

// Continued formation of candle
   if(tickCandleTime==candle.time)
     {
      candle.tick_volume++;
      candle.high= MathMax(tick.bid,candle.high);
      candle.low = MathMin(tick.bid,candle.low);
      candle.close=tick.bid;
      if(!isLastTick)
         return true;
     }

// The candle is formed. We writing it to a file
   if(candle.time>0)
      if(i_convertWay==CONVERT_WAY_CSV_CANDLES)
        {
         if(!IsCandleWritingToCSV(destHandle,candle))
            return false;
        }
   else
   if(!IsCandleWritingToHST(destHandle,candle,rates,ratesCnt,isLastTick))
      return false;

// Opening the new candle
   candle.time=tickCandleTime;
   candle.tick_volume=1;
   candle.open = tick.bid;
   candle.high = tick.bid;
   candle.low=tick.bid;
   candle.close=tick.bid;

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Saving data of candle to CSV-file                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsCandleWritingToCSV(int destHandle,MqlRates &candle)
  {
   if(FileWrite(destHandle,TimeToStr(candle.time,TIME_DATE),
      TimeToStr(candle.time,TIME_MINUTES),
      DoubleToStr(candle.open, i_digits),
      DoubleToStr(candle.high, i_digits),
      DoubleToStr(candle.low, i_digits),
      DoubleToStr(candle.close, i_digits),
      IntegerToString(candle.tick_volume))==0)
     {
      Alert(WindowExpertName(),MESSAGE_CODE_WRITE_ERROR);
      return false;
     }

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Saving data of candle to HST-file                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsCandleWritingToHST(int destHandle,MqlRates &candle,MqlRates &rates[],ulong ratesCnt,bool isLastTick)
  {
   static ulong curRatesIndex=0;

// Writing to a file "old" candles
   if(!IsWritingOldCandles(destHandle,curRatesIndex,candle.time,rates,ratesCnt))
      return false;

// Inserting a new candle or rewriting the "old" candle
   if(curRatesIndex<ratesCnt && candle.time==rates[(int)curRatesIndex].time)
      curRatesIndex++;

   if(FileWriteStruct(destHandle,candle)==0)
     {
      Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_HISTORY_WRITE_ERROR),GetLastError());
      FileClose(destHandle);
      return false;
     }

// Writing the remaining candles
   if(isLastTick)
      return IsWritingOldCandles(destHandle, curRatesIndex, StringToTime("3000.12.30 00:00"), rates, ratesCnt);

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Writing "old" candles to a fila                                                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsWritingOldCandles(int destHandle,ulong &curRatesIndex,datetime candleTime,MqlRates &rates[],ulong ratesCnt)
  {
   while(curRatesIndex<ratesCnt && candleTime>rates[(int)curRatesIndex].time)
     {
      if(FileWriteStruct(destHandle,rates[(int)curRatesIndex])==0)
        {
         Alert(WindowExpertName(),GetStringByMessageCode(MESSAGE_CODE_HISTORY_WRITE_ERROR),GetLastError());
         FileClose(destHandle);
         return false;
        }
      curRatesIndex++;
     }

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Getting string by code of message and terminal language                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetStringByMessageCode(ENUM_MESSAGE_CODE messageCode)
  {
   string language=TerminalInfoString(TERMINAL_LANGUAGE);
   if(language=="Russian")
      return GetRussianMessage(messageCode);

   return GetEnglishMessage(messageCode);
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Getting string by code of message for Russian language                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetRussianMessage(ENUM_MESSAGE_CODE messageCode)
  {
   switch(messageCode)
     {
      case MESSAGE_CODE_SAME_FILES:                   return ": èìåíà ôàéëîâ íå äîëæíû ñîâïàäàòü!";
      case MESSAGE_CODE_WRONG_TF:                     return ": êîëè÷åñòâî ìèíóò â ñâå÷å äîëæíî áûòü áîëüøå íóëÿ!";
      case MESSAGE_CODE_FILE_OPEN_ERROR:              return ": íå óäàëîñü îòêðûòü ôàéë ";
      case MESSAGE_CODE_FATAL_ERROR:                  return ": ôàòàëüíàÿ îøèáêà ñêðèïòà - ñòðóêòóðà TickStruct èìååò íóëåâîé ðàçìåð.";
      case MESSAGE_CODE_READ_ERROR:                   return ": îøèáêà ÷òåíèÿ èç èñõîäíîãî ôàéëà. Íîìåð çàïèñè ";
      case MESSAGE_CODE_WRITE_ERROR:                  return ": îøèáêà çàïèñè â ôàéë íàçíà÷åíèÿ. Íîìåð çàïèñè ";
      case MESSAGE_CODE_HISTORY_IS_ABSENT:            return "Óêàçàííûé ôàéë èñòîðèè íå íàéäåí. Áóäåò ñîçäàí íîâûé ôàéë.";
      case MESSAGE_CODE_ENOUGHT_MEMORY:               return ": íå õâàòàåò ïàìÿòè äëÿ êîïèðîâàíèÿ äàííûõ.";
      case MESSAGE_CODE_HISTORY_READ_ERROR:           return ": îøèáêà ÷òåíèÿ ôàéëà èñòîðèè. Îøèáêà N";
      case MESSAGE_CODE_CONFIRM_REWRITE_HISTORY:      return " òåðìèíàëå ñóùåñòâóåò ïîäîáíàÿ èñòîðèÿ êîòèðîâîê.\n ìåñòàõ ñîâïàäåíèÿ ñâå÷åé èñòîðèÿ áóäåò ïåðåçàïèñàíà. Ïðîäîëæàòü?";
      case MESSAGE_CODE_TITLE_REWRITE_HISTORY:        return "ÂÍÈÌÀÍÈÅ! Ïåðåçàïèñü èñòîðèè.";
      case MESSAGE_CODE_HISTORY_WRITE_ERROR:          return ": îøèáêà çàïèñè â ôàéë èñòîðèè.";
      case MESSAGE_CODE_COMPLETED:                    return "Îáðàáîòàíî ";
      case MESSAGE_CODE_SUCCESS_COMPLETE:             return ": ïðåîáðàçîâàíèå óñïåøíî çàâåðøåíî.";
     }

   return "";
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Getting string by code of message for English language                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetEnglishMessage(ENUM_MESSAGE_CODE messageCode)
  {
   switch(messageCode)
     {
      case MESSAGE_CODE_SAME_FILES:                   return ": file names do not have to match!";
      case MESSAGE_CODE_WRONG_TF:                     return ": the number of minutes in the candle should be greater than zero!";
      case MESSAGE_CODE_FILE_OPEN_ERROR:              return ": could not open the file ";
      case MESSAGE_CODE_FATAL_ERROR:                  return ": fatal error the script - TickStruct structure has zero size.";
      case MESSAGE_CODE_READ_ERROR:                   return ": the source file reading error. Record number ";
      case MESSAGE_CODE_WRITE_ERROR:                  return ": the destination file writing error. Record number ";
      case MESSAGE_CODE_HISTORY_IS_ABSENT:            return "The specified history file is not found. The new file will be created.";
      case MESSAGE_CODE_ENOUGHT_MEMORY:               return ": not enough memory to copy data.";
      case MESSAGE_CODE_HISTORY_READ_ERROR:           return ": reading error of the history file. Error N";
      case MESSAGE_CODE_CONFIRM_REWRITE_HISTORY:      return "MetaTrader contains the similar history of quotes.\nMatching candles of history will be overwritten. Continue?";
      case MESSAGE_CODE_TITLE_REWRITE_HISTORY:        return "ATTENTION! Rewriting history.";
      case MESSAGE_CODE_HISTORY_WRITE_ERROR:          return ": writing error of the history file. Error N";
      case MESSAGE_CODE_COMPLETED:                    return "Completed ";
      case MESSAGE_CODE_SUCCESS_COMPLETE:             return ": conversion was successful complete.";
     }

   return "";
  }
//+------------------------------------------------------------------+

Comments