#property copyright "Scriptong"
#property link      "http://advancetools.net"
#property description "Ñîçäàíèå ôàéëà äëÿ òåñòåðà ñòðàòåãèé ÌÒ4 èç ôàéëà äàííûõ î ðåàëüíîì òèêîâîì ïîòîêå.\nÎïèñàíèå äîñòóïíî íà ñàéòå AdvanceTools.net â ñòàòüå \"Òåñòèðîâàíèå íà ðåàëüíîé èñòîðèè.\""
#property version   "1.00"
#property strict
#property show_inputs
input datetime          i_startDate       = D'2014.07.28 00:00:00';                                // Íà÷àëüíàÿ äàòà/âðåìÿ ïåðèîäà òåñòèðîâàíèÿ
input datetime          i_endDate         = D'2014.07.29 00:00:00';                                // Êîíå÷íàÿ äàòà/âðåìÿ ïåðèîäà òåñòèðîâàíèÿ
input uint              i_minPreviousBars = 1000;                                                  // Êîëè÷åñòâî áàðîâ äî íà÷àëà òåñòèðîâàíèÿ
input uint              i_spread          = 0;                                                     // Ñïðåä â ïóíêòàõ
string                  g_ticksFileName;                                                           // Èìÿ òèêîâîãî ôàéëà
ENUM_TIMEFRAMES         g_tf;                                                                      // Òàéìôðåéì ãðàôèêà â ìèíóòàõ
int                     g_periodSeconds,                                                           // Êîëè÷åñòâî ñåêóíä â îäíîé ñâå÷å òåêóùåãî òàéìôðåéìà
                        g_startPrevBar,                                                            // Èíäåêñ áàðà, ñ êîòîðîãî íà÷èíàåòñÿ çàïèñü èñòîðèè, ïðåäøåñòâóþùåé äàòå íà÷àëà òåñòèðîâàíèÿ
                        g_endPrevBar;                                                              // Èíäåêñ áàðà, íåïîñðåäñòâåííî ïðåäøåñòâóþùèé äàòå íà÷àëó òåñòèðîâàíèÿ
                        
#import "kernel32.dll"
   bool CopyFileW(string sourceFileName, string destinationFileName, bool bFailIfExists);
   uint GetFileAttributesW(string fileName);
   bool SetFileAttributesW(string fileName, int newAttributes);
#import                        
#define  INVALID_FILE_ATTRIBUTES                   UINT_MAX                                        // Îøèáêà ïðè ïîëó÷åíèè àòðèáóòîâ ôàéëà
#define  FILE_ATTRIBUTE_READONLY                       0x01                                        // Àòðèáóò "Read Only"
struct TestHistoryHeader
{
   int               version;            // 405
   char              copyright[64];      // copyright
   char              description[128];   // server name
// 196
   char              symbol[12];         
   int               period;
   int               model;              // for what modeling type was the ticks sequence generated
   int               bars;               // amount of bars in history
   int               fromdate;
   int               todate;
   int               totalTicks;
   double            modelquality;       // modeling quality
// 240
   //---- general parameters
   char              currency[12];       // currency base
   int               spread;
   int               digits;
   int               unknown1;
   double            point;
   int               lot_min;            // minimum lot size
   int               lot_max;            // maximum lot size
   int               lot_step;
   int               stops_level;        // stops level value
   int               gtc_pendings;       // instruction to close pending orders at the end of day
// 292
   //---- profit calculation parameters
   int               unknown2;
   double            contract_size;      // contract size
   double            tick_value;         // value of one tick
   double            tick_size;          // size of one tick
   int               profit_mode;        // profit calculation mode        { PROFIT_CALC_FOREX, PROFIT_CALC_CFD, PROFIT_CALC_FUTURES }
// 324 
   //---- swap calculation
   int               swap_enable;        // enable swap
   int               swap_type;          // type of swap                   { SWAP_BY_POINTS, SWAP_BY_DOLLARS, SWAP_BY_INTEREST }
   int               unknown3;
   double            swap_long;
   double            swap_short;         // swap overnight value
   int               swap_rollover3days; // three-days swap rollover
// 356   
   //---- margin calculation
   int               leverage;           // leverage
   int               free_margin_mode;   // free margin calculation mode   { MARGIN_DONT_USE, MARGIN_USE_ALL, MARGIN_USE_PROFIT, MARGIN_USE_LOSS }
   int               margin_mode;        // margin calculation mode        { MARGIN_CALC_FOREX,MARGIN_CALC_CFD,MARGIN_CALC_FUTURES,MARGIN_CALC_CFDINDEX };
   int               margin_stopout;     // margin stopout level
   int               margin_stopout_mode;// stop out check mode            { MARGIN_TYPE_PERCENT, MARGIN_TYPE_CURRENCY }
   double            margin_initial;     // margin requirements
   double            margin_maintenance; // margin maintenance requirements
   double            margin_hedged;      // margin requirements for hedged positions
   double            margin_divider;     // margin divider
   char              margin_currency[12];// margin currency
// 420   
   //---- commission calculation
   double            comm_base;          // basic commission
   int               comm_type;          // basic commission type          { COMM_TYPE_MONEY, COMM_TYPE_PIPS, COMM_TYPE_PERCENT }
   int               comm_lots;          // commission per lot or per deal { COMMISSION_PER_LOT, COMMISSION_PER_DEAL }
// 436   
   //---- for internal use
   int               from_bar;           // fromdate bar number
   int               to_bar;             // todate bar number
   int               start_period[6];    // number of bar at which the smaller period modeling started
   int               set_from;           // begin date from tester settings
   int               set_to;             // end date from tester settings
// 476
   //----
   int               end_of_test;
   int               freeze_level;       // order's freeze level in points
   int               generating_errors;  
// 488   
   //----
   int               reserved[60];
};
 
struct TestHistory
{
   datetime          otm;                // âðåìÿ áàðà
   double            open;               // çíà÷åíèÿ OHLCV
   double            high;
   double            low;
   double            close;
   long              volume;
   int               ctm;                // òåêóùåå ðàáî÷åå âðåìÿ âíóòðè áàðà
   int               flag;               // ôëàã çàïóñêà ýêñïåðòà (0-áàð ìîäèôèöèðóåì, à ýêñïåðòà íå çàïóñêàåì)
};
struct TickStruct
{
   datetime time;
   double   bid;
   double   ask;   
};
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Script program start function                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnStart()
{
   g_tf = (ENUM_TIMEFRAMES)Period();
      
   if (!IsParametersCorrect())
      return;  
      
   if (!CreateFXTFile())
      return;
      
   if (!CopyFXTFileToTesterFolder())
      return;
      
   Alert("Ñêðèïò çàêîí÷èë ñâîå âûïîëíåíèå. Ôàéë FXT íàõîäèòñÿ â ïàïêå òåñòåðà ñòðàòåãèé.");
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ïðîâåðêà çíà÷åíèé íàñòðîå÷íûõ ïàðàìåòðîâ                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsParametersCorrect()
{
   string name = WindowExpertName();
   
   g_periodSeconds = PeriodSeconds();
   if (g_periodSeconds <= 0)
   {
      Alert(name, ": ôàòàëüíàÿ îøèáêà òåðìèíàëà - ïåðèîä ãðàôèêà ðàâåí 0 ñåêóíä. Ñêðèïò îòêëþ÷åí.");
      return false;
   }
   if (i_startDate >= i_endDate)
   {
      Alert(name, ": äàòà/âðåìÿ íà÷àëà òåñòèðîâàíèÿ äîëæíà áûòü ìåíüøå äàòû/âðåìåíè îêîí÷àíèÿ òåñòèðîâàíèÿ. Ñêðèïò îòêëþ÷åí.");
      return false;
   }
   
   if (i_minPreviousBars < 1)
   {
      Alert(name, ": êîëè÷åñòâî áàðîâ äî íà÷àëà òåñòèðîâàíèÿ äîëæíî áûòü áîëüøå íóëÿ. Ñêðèïò îòêëþ÷åí.");
      return false;
   }
   if (!IsPreviousHistoryEnough())
   {
      Alert(name, ": êîëè÷åñòâî áàðîâ â èñòîðèè, ïðåäøåñòâóþùåå íà÷àëó òåñòà, íåäîñòàòî÷íî. Ñêðèïò îòêëþ÷åí.");
      return false;
   }
   
   if (!IsTicksDataEnough())
      return false;
      
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Äîñòàòî÷íî ëè èñòîðèè, èìåþùåéñÿ äî äàòû äàòîé íà÷àëà òåñòà?                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsPreviousHistoryEnough()
{
   g_endPrevBar = iBarShift(_Symbol, g_tf, i_startDate);
   int total = iBars(_Symbol, g_tf);
   while (iTime(_Symbol, g_tf, g_endPrevBar) >= i_startDate && g_endPrevBar < total)
      g_endPrevBar++;
      
   g_startPrevBar = g_endPrevBar + (int)i_minPreviousBars - 1;
   return g_startPrevBar < total;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Èìååòñÿ ëè òèêîâàÿ èñòîðèÿ, ñîîòâåòñòâóþùàÿ çàäàííîìó èíòåðâàëó òåñòèðîâàíèÿ?                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsTicksDataEnough()
{
   int handle;
   g_ticksFileName = _Symbol + ".tks";
   if (!IsFileOpen(g_ticksFileName, handle))
      return false;
      
   TickStruct tickStart, tickEnd;
   if (!IsFileRead(handle, tickStart))
      return false;
   
   if (!FileSeek(handle, -sizeof(TickStruct), SEEK_END))
   {
      Alert(WindowExpertName(), " îøèáêà ïåðåìåùåíèÿ ôàéëîâîãî óêàçàòåëÿ â ôàéëå òèêîâ. Ñêðèïò îòêëþ÷åí.");
      FileClose(handle);
      return false;
   }
   
   if (!IsFileRead(handle, tickEnd))
      return false;
   
   FileClose(handle);
   if (tickStart.time <= i_startDate && tickEnd.time >= i_endDate)
      return true;
   Alert("÷òî íå ñîîòâåòñòâóåò çàäàííîìó èíòåðâàëó òåñòèðîâàíèÿ. Ñêðèïò îòêëþ÷åí.");
   Alert(WindowExpertName(), ": òèêîâûé ôàéë ", g_ticksFileName, " ðàñïîëàãàåò äàííûìè ñ ", tickStart.time, " ïî ", tickEnd.time, ",");
   return false;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Îòêðûòèå ôàéëà ñ óêàçàííûì èìåíåì è âîçâðàò äåñêðèïòîðà ôàéëà                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsFileOpen(string fileName, int &fileHandle)
{
   fileHandle = FileOpen(fileName, FILE_READ | FILE_SHARE_READ | FILE_BIN);
   if (fileHandle <= 0)
   {
      Alert(WindowExpertName(), ": îøèáêà (N", GetLastError(),") îòêðûòèÿ ôàéëà ", fileName, ". Ñêðèïò îòêëþ÷åí.");
      return false;
   }
   
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| ×òåíèå òèêîâîãî ôàéëà ñ îáðàáîòêîé îøèáîê                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsFileRead(int handle, TickStruct &tick)
{
   if (FileReadStruct(handle, tick) == 0)
   {
      Alert(WindowExpertName(), ": îøèáêà ÷òåíèÿ ôàéëà òèêîâ. Ñêðèïò îòêëþ÷åí.");
      FileClose(handle);
      return false;
   }
   
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ñîçäàíèå FXT-ôàéëà                                                                                                                                                                                |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool CreateFXTFile()
{
   int fxtFileHandle;
   if (!IsEmptyHeaderWrite(fxtFileHandle))
      return false;
      
   if (!IsPreviousHistoryWrite(fxtFileHandle))
      return false;
   int savedBarsCnt = g_startPrevBar - g_endPrevBar + 1; 
   int savedTicksCnt = savedBarsCnt;  
   datetime startTickDateTime = 0, lastTickDateTime= 0;
   if (!IsHistoryDataWrite(fxtFileHandle, savedBarsCnt, savedTicksCnt, startTickDateTime, lastTickDateTime))
      return false;
   if (!FileSeek(fxtFileHandle, 0, SEEK_SET))
   {
      Alert(WindowExpertName(), ": íå óäàëîñü âåðíóòüñÿ ê íà÷àëó ôàéëà FXT. Ñêðèïò îòêëþ÷åí.");
      FileClose(fxtFileHandle);
      return false;
   }
   
   bool result = IsHeaderWrite(fxtFileHandle, savedBarsCnt, savedTicksCnt, startTickDateTime, lastTickDateTime);
   FileClose(fxtFileHandle);
   
   return result;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ôîðìèðîâàíèå ïóñòîãî çàãîëîâêà FXT-ôàéëà                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsEmptyHeaderWrite(int &fxtFileHandle)
{
   if (!IsFileCreate(GetFXTFileName(), fxtFileHandle))
      return false;
      
   TestHistoryHeader testerHeader;
   return IsReadyHeaderWrite(fxtFileHandle, testerHeader);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ãåíåðàöèÿ èìåíè FXT-ôàéëà                                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetFXTFileName()
{
   return _Symbol + IntegerToString((int)g_tf) + "_0.fxt";
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Çàïèñü çàãîëîâêà FXT-ôàéëà                                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsReadyHeaderWrite(int fxtFileHandle, TestHistoryHeader &testerHeader)
{
   if (FileWriteStruct(fxtFileHandle, testerHeader) == sizeof(TestHistoryHeader))
      return true;
   Alert(WindowExpertName(), ": íå óäàëîñü çàïèñàòü çàãîëîâîê FXT-ôàéëà. Ñêðèïò îòêëþ÷åí.");
   FileClose(fxtFileHandle);
   return false;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ôîðìèðîâàíèå è çàïèñü èñòîðèè, ïðåäøåñòâóþùåé óêàçàííîé äàòå íà÷àëà òåñòèðîâàíèÿ                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsPreviousHistoryWrite(int fxtFileHandle)
{
   TestHistory testHistory = {0, 0, 0, 0, 0, 0, 0};
   int size = sizeof(testHistory);
   for (int i = g_startPrevBar; i >= g_endPrevBar; i--)
   {
      testHistory.otm = iTime(_Symbol, g_tf, i);
      testHistory.open = iOpen(_Symbol, g_tf, i);
      testHistory.high = iHigh(_Symbol, g_tf, i);
      testHistory.low = iLow(_Symbol, g_tf, i);
      testHistory.close = iClose(_Symbol, g_tf, i);
      testHistory.volume = iVolume(_Symbol, g_tf, i);
      testHistory.ctm = (int)testHistory.otm;
      if (FileWriteStruct(fxtFileHandle, testHistory) != size)
      {
         Alert(WindowExpertName(), ": íå óäàëîñü çàïèñàòü äàííûå ïðåäøåñòâóþùåé èñòîðèè. Ñêðèïò îòêëþ÷åí.");
         FileClose(fxtFileHandle);
         return false;
      }
   }
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ñîçäàíèå ôàéëà ñ óêàçàííûì èìåíåì è âîçâðàò äåñêðèïòîðà ôàéëà                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsFileCreate(string fileName, int &fileHandle)
{
   fileHandle = FileOpen(fileName, FILE_WRITE | FILE_SHARE_WRITE | FILE_BIN | FILE_ANSI);
   if (fileHandle <= 0)
   {
      Alert(WindowExpertName(), ": îøèáêà (N", GetLastError(),") ñîçäàíèÿ ôàéëà. Ñêðèïò îòêëþ÷åí.");
      return false;
   }
   
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Çàïèñü äàííûõ â FXT-ôàéë îò íà÷àëüíîé äî êîíå÷íîé äàòû èíòåðâàëà òåñòèðîâàíèÿ                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsHistoryDataWrite(int fxtFileHandle, int &savedBarsCnt, int &savedTicksCnt, datetime &startTickDateTime, datetime &lastTickDateTime)
{
   int handle;
   if (!IsFileOpen(g_ticksFileName, handle))
   {
      FileClose(fxtFileHandle);   
      return false;
   }
   // Ïîèñê ïåðâîãî òèêà, êîòîðûé áûäåò çàïèñàí â FXT-ôàéë
   TickStruct tick = {0, 0, 0};
   while (tick.time < i_startDate && !FileIsEnding(handle))
   {
      if (!IsFileRead(handle, tick))
      {
         FileClose(fxtFileHandle);
         return false;
      }
   }
   startTickDateTime = tick.time;
   
   // Çàïèñü òèêîâ â FXT-ôàéë
   TestHistory testerHistory = {0, 0, 0, 0, 0, 0, 0, 0};
   while(tick.time <= i_endDate && !FileIsEnding(handle))
   {
      if (!IsSaveTickToFXT(fxtFileHandle, tick, testerHistory, savedBarsCnt, savedTicksCnt))
      {
         FileClose(handle);
         return false;
      }
      lastTickDateTime = tick.time;
      
      if (!IsFileRead(handle, tick))
      {
         FileClose(fxtFileHandle);
         return false;
      }
   }
   
   FileClose(handle);
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Çàïèñü óêàçàííîãî òèêà â ôàéë FXT                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsSaveTickToFXT(int fxtFileHandle, TickStruct &tick, TestHistory &testerHistory, int &savedBarsCnt, int &savedTicksCnt)
{
   testerHistory.close = tick.bid;
   testerHistory.ctm = (int)tick.time;
   // Ôîðìèðîâàíèå íîâîãî áàðà
   if (tick.time >= testerHistory.otm + g_periodSeconds)
   {
      testerHistory.otm = (tick.time / g_periodSeconds) * g_periodSeconds;
      testerHistory.open = tick.bid;
      testerHistory.high = tick.bid;
      testerHistory.low = tick.bid;
      testerHistory.volume = 1;
      testerHistory.flag = 1;
      savedBarsCnt++;
   }
   else
   // Ïðîäîëæåíèå ôîðìèðîâàíèÿ ïðåäûäóùåãî áàðà
   {
      testerHistory.high = MathMax(testerHistory.high, tick.bid);
      testerHistory.low = MathMin(testerHistory.low, tick.bid);
      testerHistory.volume++;
   }
   
   // Çàïèñü äàííûõ
   if (FileWriteStruct(fxtFileHandle, testerHistory) == 0)
   {
      Alert(WindowExpertName(), ": íå óäàëîñü çàïèñàòü äàííûå èñòîðèè èíòåðâàëà òåñòèðîâàíèÿ. Ñêðèïò îòêëþ÷åí.");
      FileClose(fxtFileHandle);
      return false;
   }
   
   savedTicksCnt++;
   
   return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ôîðìèðîâàíèå çàãîëîâêà FXT-ôàéëà                                                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsHeaderWrite(int fxtFileHandle, int savedBarsCnt, int savedTicksCnt, datetime startTickDateTime, datetime lastTickDateTime)
{
   TestHistoryHeader testerHeader;
   CreateHeader(testerHeader, savedBarsCnt, savedTicksCnt, startTickDateTime, lastTickDateTime);
   
   return IsReadyHeaderWrite(fxtFileHandle, testerHeader);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Çàïîëíåíèå ñòðóêòóðû çàãîëîâêà ôàéëà                                                                                                                                                              |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void CreateHeader(TestHistoryHeader &testerHeader, int savedBarsCnt, int savedTicksCnt, datetime startTickDateTime, datetime lastTickDateTime)
{
   testerHeader.version = 405;
   string copyright = "Copyright 2001-2014, MetaQuotes Software Corp.";
   ArrayInitialize(testerHeader.copyright, 0);
   StringToCharArray(copyright, testerHeader.copyright);
   string description = AccountInfoString(ACCOUNT_SERVER);
   ArrayInitialize(testerHeader.description, 0);
   StringToCharArray(description, testerHeader.description);
   
   ArrayInitialize(testerHeader.symbol, 0);
   StringToCharArray(_Symbol, testerHeader.symbol);
   testerHeader.period = g_tf;
   testerHeader.model = 0;
   testerHeader.bars = savedBarsCnt;
   testerHeader.fromdate = (int)startTickDateTime; 
   testerHeader.todate = (int)lastTickDateTime;
   testerHeader.modelquality = 100.0;
   testerHeader.totalTicks = 0;
   
   ArrayInitialize(testerHeader.currency, 0);
   StringToCharArray(SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT), testerHeader.currency);
   testerHeader.spread = (int)i_spread;
   testerHeader.digits = _Digits;
   testerHeader.unknown1 = 0;
   testerHeader.point = _Point;
   testerHeader.lot_min = (int)(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN) * 100);
   testerHeader.lot_max = (int)(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX) * 100);
   testerHeader.lot_step = (int)(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP) * 100);
   testerHeader.stops_level = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
   testerHeader.gtc_pendings = 1;                                                                  // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî.  îáðàçöîâûõ FXT-ôàéëàõ óñòàíàâëèâàåòñÿ çíà÷åíèå 1
   
   testerHeader.unknown2 = 0;
   testerHeader.contract_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   testerHeader.tick_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   testerHeader.tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   testerHeader.profit_mode = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_CALC_MODE);
   
   testerHeader.swap_enable = 1;                                                                   // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî.  îáðàçöîâûõ FXT-ôàéëàõ óñòàíàâëèâàåòñÿ çíà÷åíèå 1
   testerHeader.swap_type = (int)SymbolInfoInteger(_Symbol, SYMBOL_SWAP_MODE);
   testerHeader.unknown3 = 0;
   testerHeader.swap_long = SymbolInfoDouble(_Symbol, SYMBOL_SWAP_LONG);
   testerHeader.swap_short = SymbolInfoDouble(_Symbol, SYMBOL_SWAP_SHORT);
   testerHeader.swap_rollover3days = (int)SymbolInfoInteger(_Symbol, SYMBOL_SWAP_ROLLOVER3DAYS);
   
   testerHeader.leverage = (int)AccountInfoInteger(ACCOUNT_LEVERAGE);
   testerHeader.free_margin_mode = 1;                                                              // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî.  îáðàçöîâûõ FXT-ôàéëàõ óñòàíàâëèâàåòñÿ çíà÷åíèå 1
   testerHeader.margin_mode = 0;                                                                   // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî.  îáðàçöîâûõ FXT-ôàéëàõ óñòàíàâëèâàåòñÿ çíà÷åíèå 0
   testerHeader.margin_stopout = (int)AccountInfoDouble(ACCOUNT_MARGIN_SO_SO);
   testerHeader.margin_stopout_mode = (int)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
   testerHeader.margin_initial = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL);
   testerHeader.margin_maintenance = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_MAINTENANCE);
   testerHeader.margin_hedged = MarketInfo(_Symbol, MODE_MARGINHEDGED);
   testerHeader.margin_divider = 1.0;                                                              // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî.  îáðàçöîâûõ FXT-ôàéëàõ óñòàíàâëèâàåòñÿ çíà÷åíèå 1.0 èëè 100.0
   ArrayInitialize(testerHeader.margin_currency, 0);
   StringToCharArray(SymbolInfoString(_Symbol, SYMBOL_CURRENCY_MARGIN), testerHeader.margin_currency);
   
   testerHeader.comm_base = 0.0;                                                                   // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî. 
   testerHeader.comm_type = 0;                                                                     // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî. 
   testerHeader.comm_lots = 1;                                                                     // Çàïðàøèâàåìîå ñâîéñòâî íå íàéäåíî. 
   
   testerHeader.from_bar = 0;
   testerHeader.to_bar = (int)i_minPreviousBars + 1;
   for (int i = 0; i < 6; i++)
      testerHeader.start_period[i] = 0;
   testerHeader.set_from = 0;
   testerHeader.set_to = (int)i_startDate;
   
   testerHeader.end_of_test = (int)i_endDate;
   testerHeader.freeze_level = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL);
   testerHeader.generating_errors = 0;
   
   for (int i = 0; i < 60; i++)
      testerHeader.reserved[i] = 0;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Êîïèðîâàíèå FXT-ôàéëà â ïàïêó òåñòåðà è óñòàíîâêà àòðèáóòà "Read Only"                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool CopyFXTFileToTesterFolder()
{
   string dataFolder = TerminalInfoString(TERMINAL_DATA_PATH);
   string fxtFileName = GetFXTFileName();
   string sourceFullFileName = dataFolder + "\\MQL4\\Files\\" + fxtFileName;
   string destinationFullFileName = dataFolder + "\\tester\\history\\" + fxtFileName;
   
   if (!IsWriteNewFileAllowed(destinationFullFileName))
      return false;
   
   if (CopyFileW(sourceFullFileName, destinationFullFileName, false))
      return IsSetReadOnly(destinationFullFileName);
   Alert(WindowExpertName(), ": îøèáêà êîïèðîâàíèÿ ôàéëà â ïàïêó òåñòåðà ñòðàòåãèé. Ñêðèïò îòêëþ÷åí.");
   return false;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Ïðîâåðêà ñóùåñòâîâàíèÿ ôàéëà ñ òàêèì æå èìåíåì â ïàïêå òåñòåðà è ñíÿòèå åìó àòðèáóòà "Read Only" â ñëó÷àå îáíàðóæåíèÿ                                                                             |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsWriteNewFileAllowed(string fileName)
{
   uint attributes = GetFileAttributesW(fileName);
   if (attributes == INVALID_FILE_ATTRIBUTES)                                                      // Îøèáêà ïîëó÷åíèÿ àòðèáóòîâ ñâèäåòåëüñòâóåò î òîì, ÷òî ôàéë îòñóòñòâóåò. Çíà÷èò, ïóòü îòêðûò.
      return true;
      
   attributes &= 0xFFFE;                                                                           // Óáèðàåì àòðèáóò "Read Only" â àòðèáóòàõ
   if (SetFileAttributesW(fileName, attributes))                                                   // Óñòàíîâêà íîâûõ àòðèáóòîâ
      return true;
      
   Alert(WindowExpertName(), ": íå óäàëîñü óáðàòü àòðèáóò \"òîëüêî äëÿ ÷òåíèÿ\" ñòàðîìó FXT-ôàéëó, íàõîäÿùåìóñÿ â ïàïêå òåñòåðà ñòðàòåãèé. Ñêðèïò îòêëþ÷åí.");
   return false;   
   
   
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Óñòàíîâêà àòðèáóòà "Read Only" FXT-ôàéëó                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsSetReadOnly(string fileName)
{
   uint attributes = GetFileAttributesW(fileName);
   if (attributes == INVALID_FILE_ATTRIBUTES)
   {
      Alert(WindowExpertName(), ": íå óäàëîñü ïîëó÷èòü àòðèáóò ôàéëà. Ñêðèïò îòêëþ÷åí.");
      return false;
   }   
   
   if (SetFileAttributesW(fileName, attributes | FILE_ATTRIBUTE_READONLY))
      return true;
      
   Alert(WindowExpertName(), ": íå óäàëîñü óñòàíîâèòü àòðèáóò \"òîëüêî äëÿ ÷òåíèÿ\" FXT-ôàéëó. Ñêðèïò îòêëþ÷åí.");
   return false;   
}
             
            
            
            
            
Comments