history_data_analysis_v3

Author: Copyright � 2007, Kiriyenko Dmitriy
history_data_analysis_v3

This script is designed for MetaTrader 4 (MT4) to perform a comprehensive audit of historical trading data. Its primary purpose is to identify and quantify "gaps" in market history—periods where price data is missing due to server outages, connectivity issues, or low liquidity—and categorize them based on their severity.

Here is a breakdown of how the logic functions:

Data Input Methods

The script offers two ways to source information for analysis:

  1. Direct Chart Analysis: It can scan the history currently visible on your active trading chart (e.g., an H1 or M15 chart).
  2. External File Analysis: You can point the script toward a specific historical data file (.hst). The script is capable of opening these files, reading the specific symbol names, timeframes, and date ranges contained within them to perform the audit.

The Core Filtering Logic

The script does not just report every tiny flicker in price; it uses user-defined filters to focus on meaningful data inconsistencies:

  • Hole Detection: It looks for missing bars (time gaps). You can set a minimum threshold so that only significant gaps are recorded.
  • Breakup Identification: It distinguishes between minor "holes" and major "breakups" based on a specific bar count.
  • Gap Analysis: It calculates the price difference (in pips) between two consecutive data points. If the price "jumps" significantly without continuous data, it records this as a gap.

How the Analysis Works

The script moves through the history chronologically and performs the following steps:

  1. Time Gap Calculation: It compares the timestamp of one bar to the next. If the difference exceeds the expected duration of that timeframe (e.g., more than 60 minutes for an H1 chart), it identifies a gap.
  2. Holiday/Weekend Adjustment: The logic is smart enough to account for weekends and holidays. It attempts to subtract standard non-trading periods so that it doesn't falsely report a "gap" simply because the market was closed.
  3. Classification:
    • If a gap exceeds your minimum threshold, it is logged as a Hole.
    • If a gap is exceptionally large (exceeding your "Breakup" threshold), it is categorized as a Breakup.
  4. Statistics Gathering: As it scans, it keeps a running tally of the total number of holes, the average size of those holes, and the maximum price jump (pips) recorded.

Output and Reporting

Once the analysis is complete, the script generates a professional report in two ways:

  • CSV Report: It creates a detailed .csv file (which can be opened in Excel). This table lists every single gap found, including the start time, end time, duration in minutes, number of bars missing, and the price jump in pips.
  • Summary Report: If enabled, the script adds a summary at the beginning or end of the file. This provides "at-a-glance" statistics, such as the total count of gaps, average sizes, maximum jumps, and a clear distinction between minor holes and major breakups.

Essentially, this tool acts as a data quality inspector, helping traders identify unreliable periods in their historical charts to ensure they aren't making decisions based on "broken" or incomplete price history.

Miscellaneous
It opens Message Boxes to the userUses files from the file systemIt reads information from a fileIt reads information from a fileIt reads information from a fileIt writes information to file
12 Views
0 Downloads
0 Favorites
history_data_analysis_v3
//+------------------------------------------------------------------+
//|                                     history_data_analysis_v3.mq4 |
//|                              Copyright © 2007, Kiriyenko Dmitriy |
//|                                      http://kiriyenko.moikrug.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Kiriyenko Dmitriy"
#property link      "http://kiriyenko.moikrug.ru"
//----
#property show_inputs
#define FILE_NAME "history_data_analysis_v3.ex4"
#define WRONG_TF "Òàéìôðåéì äîëæåí íàõîäèòüñÿ â ïðåäåëàõ M1-H4.\n\nÂûáåðèòå äðóãîé òàéìôðåéì."
#define WRONG_TF_HDR "Íåâåðíî âûáðàí òàéìôðåéì âõîäíûõ äàííûõ!"
#define WRONG_BREAKUP "Çíà÷åíèå break_up äîëæíî áûòü íå ìåíüøå êðèòåðèÿ ôèëüòðà äëÿ äûðû.\n"
#define BREAKUP_CHANGE "Çíà÷åíèå breakup_min áóäåò èçìåíåíî íà "
#define WRONG_BREAKUP_HDR "Íåâåðíî çàäàí êðèòåðèé ðàçðûâà!"
#define WRONG_FILE_EXT "Íåâåðíûé òèï ôàéëà: ìîæíî çàäàâàòü òîëüêî *.hst ôàéëû"
#define WRONG_FILE_EXT_HDR "Îøèáêà âõîäíûõ äàííûõ"
//----
extern string header0 = "<---------- Âõîäíûå äàííûå ---------->";
extern bool   input_from_file = false;
extern string input_file_name = ".hst";
extern bool   input_file_in_history = true;
//----
extern string header1 = "<---------- Ïàðàìåòðû ôèëüòðàöèè ---------->";
extern bool   bars_ignore = true; // àêòèâàòîð 
extern int    hole_min    = 3; // êîëè÷åñòâî îòñóòñòâóþùèõ áàðîâ, êîòîðûå êîä ñ÷èòàåò äûðîé
//----
extern int breakup_min    = 20; // êîë-âî îòñóòñòâóþùèõ áàðîâ, êîòîðûå êîä ñ÷èòàåò ðàçðûâîì

extern bool gap_ignore    = true; // àêòèâàòîð
extern int  gap_min       = 5; // êîë-âî îòñóòñòâóþùèõ ïèïñîâ, êîòîðûå êîä áóäåò èãíîðèðîâàòü
//----
extern string header2 = "<---------- Ïàðàìåòðû îò÷¸òà ---------->";
extern bool report_summary = false; // âûâîäèòü ñâîäêó
extern bool report_table = true; // âûâîäèòü òàáëèöó
//----
string begin_week_sessions = "00:00"; // âðåìÿ íà÷àëà íåäåëüíîé ñåññèè (÷÷:ìì)
string end_week_sessions = "21:59";   // âðåìÿ îêîí÷àíèÿ íåäåëüíîé ñåññèè (÷÷:ìì)
bool   new_file = true;               // ôëàã, ÷òîáû øàïêó òàáëèöû çàïèñàòü îäèí ðàç
int    in_handle, out_handle;         // ôàéëîâûå îáðàáîò÷èêè îòêðûòûõ ôàéëîâ
int    err;                           // ïåðåìåííàÿ äëÿ õðàíåíèÿ êîäà îøèáêè
//----
#include <WinUser32.mqh>
#include <stdlib.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   int      period;               // òàéìôðåéì â ìèíóòàõ
   string   symbol;               // îáðàáàòûâàåìûé ñèìâîë
   int      bars;                 // ÷èñëî áàðîâ íà ãðàôèêå
   double   point;                // ðàçìåð ïóíêòà â âàëþòå êîòèðîâêè
   datetime time_start, time_end; // íà÷àëüíûé è êîíå÷íûé áàð
// íà÷àëüíàÿ îáðàáîòêà âõîäíîãî ôàéëà è óñòàíîâêà ãëîáàëüíûõ äàííûõ
   if(input_from_file)
     {
       // îïðåäåëåíèå òèïà
       if(file_ext(input_file_name) != "hst")
         {
           MessageBox(WRONG_FILE_EXT, WRONG_FILE_EXT_HDR, MB_OK | MB_ICONSTOP);
           return(-3);
         }
       // îòêðûòèå ôàéëà
       if(input_file_in_history)
           in_handle = FileOpenHistory(input_file_name, FILE_BIN | FILE_READ);
       else
           in_handle = FileOpen(input_file_name, FILE_BIN | FILE_READ);
       err = GetLastError();
       if(in_handle < 0 || err > 0) 
           return(error_out(err, "Îòêðûòèå âõîäíîãî ôàéëà"));
       // îïðåäåëåíèå ÷èñëà áàðîâ
       bars = (FileSize(in_handle) - 148) / 44;
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "Îïðåäåëåíèå ðàçìåðà âõîäíîãî ôàéëà"));
       // ÷òåíèå çàãîëîâêà âõîäíîãî ôàéëà
       FileSeek(in_handle, 68, SEEK_SET);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "Ñìåùåíèå âî âõîäíîì ôàéëå ê ñèìâîëó"));
       // ÷òåíèå ñèìâîëà/ïåðèîäà
       symbol = FileReadString(in_handle, 12);
       period = FileReadInteger(in_handle, LONG_VALUE);
       int digits = FileReadInteger(in_handle, LONG_VALUE);
       point = MathPow(10, -digits);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "×òåíèå ñèìâîëà è ïåðèîäà èç âõîäíîãî ôàéëà"));
       // îïðåäåëåíèå âðåìåííûõ ãðàíèö èñòîðè÷åñêèõ äàíûõ
       FileSeek(in_handle, 60, SEEK_CUR);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "Ñìåùåíèå âî âõîäíîì ôàéëå ê ïåðâîé äàòå"));
       time_start = FileReadInteger(in_handle, LONG_VALUE);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "×òåíèå ïåðâîé äàòû èç âõîäíîãî ôàéëà"));
       FileSeek(in_handle, -44, SEEK_END);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "Ñìåùåíèå âî âõîäíîì ôàéëå ê ïîñëåäíåé äàòå"));
       time_end = FileReadInteger(in_handle, LONG_VALUE);
       err = GetLastError();
       if(err > 0) 
           return (error_out(err, "×òåíèå ïîñëåäíåé äàòû èç âõîäíîãî ôàéëà"));
       // ïåðåâîä êóðñîðà â íà÷àëî êîòèðîâîê â *.hst ôàéëå
       FileSeek(in_handle, 148, SEEK_SET);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "Ñìåùåíèå âî âõîäíîì ôàéëå ê íà÷àëó êîòèðîâîê"));
     }
   else // èëè ïîäñòàíîâêà ãëîáàëüíûõ äàííûõ ñ ãðàôèêà
     {
       bars = Bars;
       symbol = Symbol();
       period = Period();
       point = Point;
       time_start = Time[Bars-1];
       time_end = Time[0];
     }
// âûáîð ïàðàìåòðîâ ïîä òàéìôðåéì
   string time_frame;    // òàéìôðåéì
   int duration_bar = period*60;  // äëèòåëüíîñòü áàðà â ñåê.
   switch(period)
     {
       case 1:   time_frame = "M1";  break;
       case 5:   time_frame = "M5";  break;
       case 15:  time_frame = "M15"; break;
       case 30:  time_frame = "M30"; break;
       case 60:  time_frame = "H1";  break;
       case 240: time_frame = "H4";  break;
       default: 
           MessageBox(WRONG_TF, WRONG_TF_HDR, MB_OK | MB_ICONWARNING | MB_DEFBUTTON1); 
           return(-2);
     }
// ïðîâåðêà êîððåêòíîñòè çàäàíèÿ ôèëüòðà ïî áàðàì
   if(hole_min < 1) 
       hole_min = 1; 
   if(bars_ignore == false) 
       hole_min = 1;
// ïðîâåðêà êîððåêòíîñòè çàäàíèÿ ôèëüòðà ïî ãýïàì
   if(gap_min < 0) 
       gap_min = 0;
   if(gap_ignore == false) 
       gap_min = 0;
   if(breakup_min < hole_min)
     { 
       string message = StringConcatenate(WRONG_BREAKUP, BREAKUP_CHANGE, hole_min);
       int warning_1 = MessageBox(message, WRONG_BREAKUP_HDR,
                                  MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON1); 
       if(warning_1 == 1) 
           breakup_min = hole_min;  
       else 
           return(-1);
       err = GetLastError();
       if(err > 0) 
           return(error_out(err, "Âûâîä ñîîáùåíèÿ î êîððåêöèè êðèòåðèÿ ðàçðûâà"));
     }
// ñîçäàíèå èìåíè ôàéëà
   string date_start = TimeToStr(time_start, TIME_DATE);
   string date_end   = TimeToStr(time_end, TIME_DATE);
   string file_name = StringConcatenate(symbol, "_", time_frame, "_holes_",
                                        date_start, "-", date_end, ".csv");
// îòêðûòèå âûõîäíîãî ôàéëà
   out_handle = FileOpen(file_name, FILE_CSV |FILE_WRITE, ";");
   err = GetLastError();
   if(out_handle < 0 || err > 0) 
       return(error_out(err, "Îòêðûòèå âûõîäíîãî ôàéëà"));
// àíàëèç äàííûõ èñòîðèè 
   int    week_seconds = 604800; // êîëè÷åñòâî ñåêóíä â íåäåëå
   double weeks;                 // îòíîøåíèå äèàïàçîíà äûðû ê êîëè÷åñòâó ñåêóíä â íåäåëå
// âûõîäíûå äíè â ñåê.
   datetime holiday = StrToTime(begin_week_sessions) - StrToTime(end_week_sessions)
                        + (24*3600*3) - duration_bar;
   int hole_range; // äèàïàçîí äûðû
   int bars_hole;  // áàðîâ â äûðå
   int holes_total_amount;   // îáùåå êîëè÷åñòâî äûð
   int breakup_total_amount; // îáùåå êîëè÷åñòâî ðàçðûâîâ
   int bars_hole_amount;     // îáùåå êîëè÷åñòâî áàðîâ â äûðàõ
   int bars_breakup_amount;  // îáùåå êîëè÷åñòâî áàðîâ â ðàçðûâàõ
   int gap_total_amount;     // îáùåå êîëè÷åñòâî ãýïîâ
   int gap_holes;            // îáùèé ãýï â äûðàõ
   int gap_breakups;         // îáùèé ãýï â ðàçðûâàõ
   int hole_max;             // çíà÷åíèå ìàêñèìàëüíîé äûðû
   int breakup_max;          // çíà÷åíèå ìàêñèìàëüíîãî ðàçðûâà
   int gap_max;              // çíà÷åíèå ìàêñèìàëüíîãî ãýïà
   bool note_ = false;
   double months, days, hours, minutes, seconds;
   int n = 1;
   for(int h = 0; h < bars; h++)
     {
       // âðåìÿ òåêóùåãî è ïðåäûäóùåãî áàðîâ â èñòîðèè
       datetime bar_time_current, bar_time_previous;
       // öåíà îòêðûòèÿ òåêóùåãî è öåíà çàêðûòèÿ ïðåäûäóùåãî áàðîâ â èñòîðèè
       double open_price_current, close_price_previous;
       if(!input_from_file)
         {
           bar_time_current  = iTime(NULL, 0, Bars - h - 2);
           bar_time_previous = iTime(NULL, 0, Bars - h - 1);
           open_price_current   = NormalizeDouble(Open[Bars - h - 2],4);
           close_price_previous = NormalizeDouble(Close[Bars - h - 1],4);
         }
       else
         {
           bar_time_previous = FileReadInteger(in_handle, LONG_VALUE);
           err = GetLastError();
           // åñëè ôàéë çàêîí÷èëñÿ, çàâåðøàåì öèêë
           if(err == 4099) 
               break; 
           if(err > 0) 
               return(error_out(err, "×òåíèå èç âõîäíîãî ôàéëà âðåìåíè ïðåä.áàðà"));
           FileSeek(in_handle, 24, SEEK_CUR);
           err = GetLastError();
           if(err > 0) 
               return(error_out(err, "Ñìåùåíèå âî âõ. ôàéëå ê ö.çàêð. ïðåä. áàðà"));
           close_price_previous = FileReadDouble(in_handle, DOUBLE_VALUE);
           if(err == 4099) 
               break; // åñëè ôàéë çàêîí÷èëñÿ, çàâåðøàåì öèêë
           err = GetLastError();
           if(err > 0) 
               return(error_out(err, "×òåíèå èç âõîäíîãî ôàéëà öåíû çàêðûòèÿ"));
           FileSeek(in_handle, 8, SEEK_CUR);
           err = GetLastError();
           if(err > 0) 
               return(error_out(err, "Ñìåùåíèå âî âõîäíîì ôàéëå ê ñëåä.áàðó"));
           bar_time_current = FileReadInteger(in_handle, LONG_VALUE);
           open_price_current = FileReadDouble(in_handle, DOUBLE_VALUE);
           err = GetLastError();
           if(err == 4099) 
               break; // åñëè ôàéë çàêîí÷èëñÿ, çàâåðøàåì öèêë
           if(err > 0) 
               return(error_out(err, "×òåíèå èç âõ. ôàéëà ñëåä.áàðà"));
           FileSeek(in_handle, -12, SEEK_CUR);
           err = GetLastError();
           if(err > 0) 
               return(error_out(err, "Ñìåùåíèå âî âõîäíîì ôàéëå ê íà÷àëó áàðà"));
         }
       // ãýï â ïóíêòàõ
       double abs_gap  = MathAbs(open_price_current - close_price_previous);
       double pips_gap = NormalizeDouble(abs_gap/point, 0);  
       // ôàêòè÷åñêèé äèàïàçîí òàéìôðåéìà ñ ó÷åòîì íåòî÷íîñòè
       int time_frame_range = bar_time_current - bar_time_previous; 
       if(time_frame_range > duration_bar) // êîë-âî ñåêóíä â áàðå ïðåâûøàåò òàéìôðåéì
         {
           // êîë-âî ñåêóíä â áàðå ïðåâûøàåò êîëè÷åñòâî ñåêóíä â íåäåëå
           if(time_frame_range > week_seconds) 
             {
               // çíà÷åíèå äûðû â íåäåëüíîì âûðàæåíèè
               weeks = MathFloor(time_frame_range / week_seconds); 
                  
               if(TimeDayOfWeek(bar_time_previous) > TimeDayOfWeek(bar_time_current))
                   hole_range = time_frame_range - holiday * (1 + weeks) - duration_bar;
               else 
                   hole_range = time_frame_range - (holiday * weeks) - duration_bar;
             } 
           else
             {
               weeks = 0;
               if(TimeDayOfWeek(bar_time_previous) > TimeDayOfWeek(bar_time_current))
                   hole_range = time_frame_range - holiday - duration_bar;
               else 
                   hole_range = time_frame_range - duration_bar;
             }
           bars_hole = hole_range / duration_bar;
           if(bars_hole >= hole_min && pips_gap >= gap_min)
             { 
               holes_total_amount++;          // îáùåå êîëè÷åñòâî äûð (óâåëè÷èâàåì)
               // îáùåå êîëè÷åñòâî áàðîâ â äûðàõ (óâåëè÷èâàåì)
               bars_hole_amount += bars_hole;
               int gap;
               if(pips_gap >= gap_min) 
                 {
                   gap_holes += pips_gap; // îáùèé ãýï â äûðàõ 
                   gap = pips_gap;
                   if(pips_gap == 0) 
                       n = 0; 
                 }
               else 
                   gap = 0;
               seconds = bars_hole * duration_bar;
               string duration_hole = interval_to_str(seconds);
               if(bars_hole >= breakup_min)
                 {
                   // îáùåå êîëè÷åñòâî ðàçðûâîâ
                   breakup_total_amount++;
                   // îáùåå êîëè÷åñòâî áàðîâ â ðàçðûâàõ
                   bars_breakup_amount += bars_hole; 
                   // îáùèé ãýï â ðàçðûâàõ
                   gap_breakups += pips_gap; 
                 }
               if(hole_max < bars_hole && bars_hole < breakup_min)
                 {
                   // ìàêñèìàëüíàÿ äûðà
                   hole_max = bars_hole;
                   // ï/ï íîìåð
                   int number_hole = holes_total_amount;
                 } 
               if(breakup_max <= bars_hole && bars_hole >= breakup_min)
                 {
                   // ìàêñèìàëüíûé ðàçðûâ
                   breakup_max = bars_hole;
                   // ï/ï íîìåð
                   int number_breakup = holes_total_amount;
                 }     
               if(gap_max <= pips_gap)
                 {
                   // ìàêñèìàëüíûé ãýï
                   gap_max = pips_gap;
                   // ï/ï íîìåð
                   int number_gap = holes_total_amount; 
                 }     
               // ñîçäàíèå òàáëèöû *.csv ôàéëà
               if(new_file && report_table)
                 {
                   if(report_summary)
                     {
                       FileSeek (out_handle, 2400, SEEK_END);
                       err = GetLastError();
                       if(err > 0) 
                           return(error_out(err, "Ñìåùåíèå â ôàéëå äëÿ ñâîäêè"));
                     }
                   FileWrite(out_handle, "¹ ï/ï","Âðåìÿ íà÷àëà", "Âðåìÿ îêîí÷àíèÿ",
                                         "Ðàçìåð (áàðîâ)", "Äëèòåëüíîñòü (ìèí)",
                                         "Äëèòåëüíîñòü", "Ãýï (ïò)");
                   err = GetLastError();
                   if(err > 0) 
                       return(error_out(err, "Çàïèñü øàïêè òàáëèöû"));
                   new_file = false;
                 }
               FileWrite(out_handle, holes_total_amount,
                         TimeToStr(bar_time_previous + duration_bar),
                         TimeToStr(bar_time_current),
                         bars_hole, bars_hole*Period(),
                         duration_hole, gap);
               err = GetLastError();
               if(err > 0) 
                   return(error_out(err, "Çàïèñü ñòðîêè òàáëèöû"));
               // ìàêñèìàëüíàÿ äûðà è ðàçðûâ
               int hole_range_max = number_hole;
               int breakup_range_max = number_breakup;
               int gap_range_max = number_gap;
             }
         }
     }
   // ëîâëÿ îøèáêè "èíäåêñ çà ïðåäåëàìè ìàññèâà"
   err = GetLastError();
   if(err > 0 && err != 4002) 
       return(error_out(err, "Ïîñëå îêîí÷àíèÿ ïåðåáîðà áàðîâ"));
   // ñîçäàíèå îò÷åòà *.csv ôàéëà 
   double bars_hole_amount_     = bars_hole_amount;     
   double bars_breakup_amount_  = bars_breakup_amount;  
   double holes_total_amount_   = holes_total_amount;   
   double breakup_total_amount_ = breakup_total_amount; 
   double gap_holes_            = gap_holes;
   double gap_total_amount_     = gap_total_amount;
   double bars_                 = bars;
   double hole_average_size_; 
   if(holes_total_amount != breakup_total_amount)
     {
       seconds = (bars_hole_amount - bars_breakup_amount) * duration_bar;
       string duration_holes = interval_to_str(seconds);
       hole_average_size_ = NormalizeDouble((bars_hole_amount_ - 
                                            bars_breakup_amount_) /
                                            (holes_total_amount_ - 
                                            breakup_total_amount_), 2);
       int only_holes_total_amount_ = (holes_total_amount - breakup_total_amount);
       int bars_only_hole_amount_ = (bars_hole_amount - bars_breakup_amount);
     }
   seconds = time_end - time_start;
   string duration_period = interval_to_str(seconds);
   if (holes_total_amount > 0)
     {
       seconds = bars_hole_amount * duration_bar;
       string duration_holes_ = interval_to_str(seconds);        
       double hole_average_size = NormalizeDouble(bars_hole_amount_/holes_total_amount_,2);
       string gap_average_size  = NormalizeDouble(gap_holes_/holes_total_amount_, 2);

       FileSeek(out_handle, 0, SEEK_SET);
       err = GetLastError();
       if (err > 0) return (error_out(err,"Ñìåùåíèå â íà÷àëî ôàéëà äëÿ çàïèñè îò÷¸òà"));
       
       string hole_comment;
       if (hole_min == breakup_min) hole_comment = "ñìîòðåòü <Ðàçðûâû>, ñîãëàñíî çàäàííûì"+
                                                   " ïîëüçîâàòåëåì óñëîâèÿì)";
       else hole_comment = StringConcatenate(hole_min," - ",breakup_min," áàðîâ )"); 
       hole_comment = StringConcatenate("ÄÛÐÛ  ( ",hole_comment);

       string breakup_comment = StringConcatenate("ÐÀÇÐÛÂÛ ( ",breakup_min," áàðîâ è âûøå)");
       
       if (breakup_total_amount != 0)          
       {
           seconds = bars_breakup_amount * duration_bar;
           string duration_breakups = interval_to_str(seconds);
           double breakup_average_size = NormalizeDouble(bars_breakup_amount_
                                                           /breakup_total_amount_, 2);
       }

       if (report_summary)
       {
           FileWrite(out_handle, "\nÎò÷åò ïî îòñóòñòâóþùèì áàðàì â äàííûõ èñòîðèè");
           FileWrite(out_handle, "Èíñòðóìåíò - ",Symbol(),"Òàéìôðåéì",time_frame);
           FileWrite(out_handle, "Ïåðèîä",date_start,date_end);
           FileWrite(out_handle, "Áàðîâ â èñòîðèè",bars,"áàðîâ");
           FileWrite(out_handle, "Äëèòåëüíîñòü (ìèí)",(time_end-time_start)/60,
                                 duration_period);
           FileWrite(out_handle, "\nÎÁÙÈÉ ÀÍÀËÈÇ äûð è ðàçðûâîâ");
           FileWrite(out_handle, "Êîëè÷åñòâî",holes_total_amount);
           FileWrite(out_handle, "Îáùèé ðàçìåð",bars_hole_amount,"áàðîâ");
           FileWrite(out_handle, "Äëèòåëüíîñòü (ìèí)",
                                 (bars_hole_amount*duration_bar)/60,duration_holes_);
           FileWrite(out_handle, "Ñðåäíèé ðàçìåð",hole_average_size,"áàðîâ");
           FileWrite(out_handle, "Îáùèé ãýï",gap_holes,"ïò");
           FileWrite(out_handle,"Ìàêñèìàëüíûé ãýï",gap_max,"ïò","¹",gap_range_max);
           FileWrite(out_handle, "Ñðåäíèé ãýï",gap_average_size,"ïò");
           FileWrite(out_handle, "\n" + hole_comment);
           FileWrite(out_handle,  "Êîëè÷åñòâî",only_holes_total_amount_);
           FileWrite(out_handle, "Ðàçìåð",bars_only_hole_amount_,"áàðîâ");
           FileWrite(out_handle, "Äëèòåëüíîñòü (ìèí)",
                                 (bars_hole_amount-bars_breakup_amount)*duration_bar/60,
                                 duration_holes);
           FileWrite(out_handle, "Ìàêñèìàëüíûé ðàçìåð",hole_max,"¹",hole_range_max);
           FileWrite(out_handle, "Ñðåäíèé ðàçìåð",hole_average_size_);
           FileWrite(out_handle, "\n" + breakup_comment);
           FileWrite(out_handle, "Êîëè÷åñòâî",breakup_total_amount);
           FileWrite(out_handle, "Ðàçìåð",bars_breakup_amount,"áàðîâ");
           FileWrite(out_handle, "Äëèòåëüíîñòü (ìèí)",bars_breakup_amount*duration_bar/60,
                                 duration_breakups);
           FileWrite(out_handle, "Ìàêñèìàëüíûé ðàçìåð",breakup_max,"áàðîâ","¹",
                                 breakup_range_max);
           FileWrite(out_handle, "Ñðåäíèé ðàçìåð",breakup_average_size,"áàðîâ\n");
           err = GetLastError();
           if (err > 0) return (error_out(err,"Çàïèñü îò÷¸òà"));
       }
     }
   else
     {
       FileWrite(out_handle, "Íà äàííîì ãðàôèêå äûð è ðàçðûâîâ ÍÅ ÎÁÍÀÐÓÆÅÍÎ");
       err = GetLastError();
       if (err > 0) return (error_out(err,"Çàïèñü \"Äûð íå îáíàðóæåíî\""));
     }
   FileClose(out_handle);
   err = GetLastError();
   if(err > 0) 
       return(error_out(err, "Çàêðûòèå ôàéëà"));
   MessageBox(" ïàïêå òåðìèíàëà MT4: \Experts\files\ ñîçäàí ôàéë îò÷åòà:\n\n" + file_name, 
              "Àíàëèç äàííûõ èñòîðèè óñïåøíî çàâåðøåí", MB_OK | MB_DEFBUTTON1);
   err = GetLastError();
   if(err > 0) 
       return(error_out(err, "Âûâîä ñîîáùåíèÿ î çàâåðøåíèè ðàáîòû"));
   return(0);
 }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string interval_to_str(int seconds)
  {
   int hours = seconds / 3600;
   int minutes = seconds % 3600 / 60;
   string str_interval;
   string zero_h = "", zero_m = ""; 
   if(hours < 10) 
       zero_h = "0"; 
   if(minutes < 10) 
       zero_m = "0"; 
   str_interval = StringConcatenate(zero_h, DoubleToStr(hours, 0), ":",
                                    zero_m, DoubleToStr(minutes, 0));            
   if(hours > 24)  
     {
       int days = hours / 24; hours = hours % 24;
       if(hours < 10) 
           zero_h = "0";
       str_interval = StringConcatenate(DoubleToStr(days, 0), " äí. ",
                                        zero_h, DoubleToStr(hours, 0), ":",
                                        zero_m, DoubleToStr(minutes, 0));  
       if(days > 30)   
         {
           int months = days/30; days = days%30;
           str_interval = StringConcatenate(DoubleToStr(months,0)," ìåñ. ",
                                            DoubleToStr(days,0)," äí. ",
                                            zero_h,DoubleToStr(hours,0),":",
                                            zero_m,DoubleToStr(minutes,0));  
           
           if(months > 12) 
             {
               int years  = months / 2; months = months % 12;
               str_interval = StringConcatenate(DoubleToStr(years, 0), " ëåò ",
                                                   DoubleToStr(months, 0), " ìåñ. ",
                                                   DoubleToStr(days, 0), " äíåé  ",
                                                   zero_h, DoubleToStr(hours, 0),":",
                                                   zero_m, DoubleToStr(minutes, 0));
             }
         }
     }   
   return (str_interval);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int error_out(int err, string where)
  {
   if (err == 0) return;
   string message = StringConcatenate("Îøèáêà ¹", err, ":\"", ErrorDescription(err), "\"\n",
                                      "âîçíèêëà ïðè âûïîëíåíèè îïåðàöèè \"", where, "\"");
   string caption = StringConcatenate("Âîçíèêëà îøèáêà â ìîäóëå: \"", FILE_NAME, "\"!");
   MessageBox(message, caption, MB_OK | MB_ICONSTOP);
   return (err);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string file_ext(string file_name)
  {
   string result = StringSubstr(file_name, StringLen(file_name) - 3, 3);
   int err = GetLastError();
   if(err > 0) 
       return(error_out(err, "Îáðàáîòêà çàäàííîé ñòðîêè-èìåíè ôàéëà"));
   return (result);
  }
//+------------------------------------------------------------------+

Comments