#property copyright "PiKG, master_255, Rever27, Trade Like A Pro"
#define   EAName    "Piranha"
#define   VER       "1.7"
#property version   VER 
#property link      "http://forum.tradelikeapro.ru/index.php?topic=16042.0"
#property strict
#include <stderror.mqh>
#include <stdlib.mqh>

//#define FOR_OPTIMIZATION //comment this line in release

#ifndef FOR_OPTIMIZATION
#include <Canvas\Canvas.mqh>
CCanvas canvas_PANEL;
#endif 

enum  _TurnFilter  {
                  TurnFilterATR     = 0,             //TurnFilter ATR
                  TurnFilterPZ_ATR  = 1,             //TurnFilter PZ & ATR
                  None              = 2              //None
      };
      
      
extern   string S_0     = "<==== OPTIMIZATION SETTINGS ====>";   // =  =  =  =  =  =  =  =  =  =  =
sinput   int               VarOptimTest         = 0;
extern   int               VarOptimCounter      = 1;

sinput   string     _0_ = "<================== GENERAL SETTINGS ==================>"; // =  =  =  =  =  =  =  =  =  =  =
extern   ENUM_TIMEFRAMES   timeframe            = PERIOD_CURRENT; //Рабочий таймфрейм
extern   int               MAGIC                = 0;
extern   int               Slippage             = 5;
extern   double            Lots                 = 0.01;
extern   int               DepoPer001Lot        = 0;
extern   string            SetName              = "[Piranha] [H1]";   

sinput   string     _4_ = "<================== GRID SETTINGS ==================>"; // =  =  =  =  =  =  =  =  =  =  =
extern   int               PipStep              = 15;             //MinGridPipStep
extern   int               Profit               = 50;             //Take Profit
extern   double            DinamicTP_Percent    = 0;
extern   int               Lvl1                 = 4;              //Lvl: Profit/2
extern   int               Lvl2                 = 6;              //Lvl2: BE
extern   double            LotExponent1         = 2;
extern   double            LotExponent2         = 1.5;

extern   int               TimeExit_Start       = 4;              //Time Exit Start Order
extern   int               TimeExit_End         = 99;             //Time Exit End Order
extern   int               TimeExit_Minutes     = 240;            //TimeExit_Minutes: Profit/3
extern   int               LastCloseBy          = 3;              //LastCloseBy <= 3 - off

sinput   string     _2_ = "<================= ENTER SETTINGS =================>"; // =  =  =  =  =  =  =  =  =  =  =
sinput   string     _21 = " == > First Order";                    // > > >
sinput   string    _211 = " = > Настройки ATR_Channels";       // > > 
extern   int               a__PeriodATR         = 18;             // PeriodATR
extern   int               a__MaPeriod          = 49;             // MA Period
extern   ENUM_MA_METHOD    a__MaTypr            = MODE_LWMA;      // MA Type
extern   double            a__Mult_Factor1      = 1.6;            // Mult Factor 1
extern   double            a__Mult_Factor2      = 3.2;            // Mult Factor 2
//extern   double            a__Mult_Factor3      = 4.8;            // Mult Factor 3
sinput   string    _212 = " = > Настройки X2 PRICE ZONE 2";       // > > 
extern   int               ma_period = 2;
extern   int               ma_method = MODE_SMMA;
extern   int               applied_price = PRICE_WEIGHTED;
sinput   string _filter = " = > Настройки ADX";                   // > >
extern   int               FilterADX_Period     = 0;
extern   int               FilterADX_Level      = 10;
sinput   string     _22 = " == > All Orders";                     // > > >
sinput   string   _macd = " = > Настройки MACD";                  // > >
extern   int               macd_FastEma         = 24;             // FastEMA
extern   int               macd_SlowEma         = 48;             // SlowEMA
extern   int               macd_SignalEma       = 12;             // SignalSMA
         int               shift                = 1;              // MACD && ATR shift
extern   bool              UseMACDforNextOrders = false;
sinput   string     _PZ = " = > PZ & ATR Cnannel";            // > >
extern   _TurnFilter       TurnMainFilters      = 1;              //Turn Main Filters
extern   int               ExpandChannelLvl     = 0;
sinput   string     _3_ = "<================= EXIT SETTINGS =================>"; // =  =  =  =  =  =  =  =  =  =  =
extern   int               Exit2ChannelLvl      = 0;
sinput   string     _5_ = "<================= TRAILING STOP SETTINGS =================>"; // =  =  =  =  =  =  =  =  =  =  =
extern   int               TrailStartAfter      = 0;              //TrailStartAfter = 0 - off
extern   int               TrailStart           = 30;                      
extern   int               TrailStop            = 10;
sinput   string     _1_ = "<================= TRADE TIME SETTINGS =================>"; // =  =  =  =  =  =  =  =  =  =  =
extern   bool              UseTradeTime_1Order  = true;           //UseTradeTime for First Order
extern   int               StartHour            = 8;
extern   int               EndHour              = 21;
extern   bool              MONDAY_Enabled       = true;           //MONDAY
extern   bool              TUESDAY_Enabled      = true;           //TUESDAY
extern   bool              WEDNESDAY_Enabled    = true;           //WEDNESDAY
extern   bool              THURSDAY_Enabled     = true;           //THURSDAY
extern   bool              FRIDAY_Enabled       = true;           //FRIDAY;
sinput   string     _6_ = "<================= VISUAL SETTINGS =================>"; // =  =  =  =  =  =  =  =  =  =  =
extern   bool              VisualDebug          = true;
extern   bool              showinfopanel        = true;
extern   color             Col_info             = clrDeepSkyBlue; //Panel Color
extern   uchar             Panel_Transparency   = 220;            //Panel Transparency 
sinput   string     _7_ = "<================= CURRENCY FILTER =================>"; // =  =  =  =  =  =  =  =  =  =  =
input    int               StopByMaxOrdersOneSymbol = 5;
input    int               StopByMaxSymbolTrades    = 3;
input    bool              StopEqualCurrencyTrade   = true;
//-------------------------------------------------------------------------
int lottextpoint = 6, globcount = 0; 
string globcountname = EAName+"_count";

int PipsDivided = 1;
struct SetkaEnv{
   int      count;
   int      count_buy;
   int      count_sell;
   double   countlot_buy;
   double   countlot_sell;
   double   lastprice;
   int      lasttype;
   datetime lasttime;
   int      last_distance;
   double   profit;
   int      ppoint;
   double   firstlot;
   double   lastlot;
   double   avg;
};
SetkaEnv env;

struct TradeEnv{
   string   symbol;
   int      count;
};
TradeEnv tradeenv[];
struct CurrencyFilter{
   int maxorders;
   int symbols;
   bool tradethiscurrency;
};
CurrencyFilter globfilter;
string s1str,s2str;

int stoplevel, lotsize;
double minlot, maxlot, lotstep, trailprice;
double ADX_PLUSDI, ADX_MINUSDI;
double upLineATR = 0, dnLineATR = 0, upLineATR2 = 0, dnLineATR2 = 0, upLinePZ = 0, dnLinePZ = 0;
double TP = 0;
datetime _TimeCurrent, _time1, _time2, lastlastcloseby;

struct _orders{
   int ticket;
   int type;
   double lots;
   double profit;
};
_orders orders[];

struct _stats{
   int maxcount;
   int sumcount;
   int count;
};
_stats stat;

double tickvalue;
int freezlevel;
         
string time_trade = "";
bool RealTrade = (!IsTesting() && !IsOptimization() && !IsVisualMode());

//-------------------------------------------------------------------------
int OnInit(){
   #ifndef FOR_OPTIMIZATION
   if (IsOptimization() || (IsTesting() && !IsVisualMode())) { 
      showinfopanel=false; VisualDebug=false; 
   } 
 
   if(showinfopanel && (RealTrade || (IsTesting() && IsVisualMode()))) { //создание заднего фона   
      canvas_PANEL.CreateBitmapLabel("Piranha|info_panel",3,15,400,400,COLOR_FORMAT_ARGB_NORMALIZE);
      int length = 190;
      canvas_PANEL.FillRectangle(0,0,150,length, ColorToARGB(Col_info,Panel_Transparency));  
      canvas_PANEL.Update();
   }
   #endif 
   
   if (IsOptimization()) { 
      if (VarOptimTest == 1 && VarOptimCounter != 0) { //БЛОК ВЫЗОВА ФУНКЦИЙ ОПТИМИЗАЦИИ И ТЕСТИРОВАНИЯ
         _ReadParametrs(); 
      } 
      if (VarOptimTest == 2 && VarOptimCounter != 0) { 
         _ReadParametrs(); _WriteSet();
         ExpertRemove(); //запись сетов в файл для форвард/беквард тестов.
      }
      
   } 
   
   s1str = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_BASE);
   s2str = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT);
   
   stoplevel = (int)MarketInfo(_Symbol, MODE_STOPLEVEL);
   minlot = MarketInfo(_Symbol, MODE_MINLOT);
   maxlot = MarketInfo(_Symbol, MODE_MAXLOT);
   lotsize = (int)MarketInfo(_Symbol, MODE_LOTSIZE);
   lotstep = MarketInfo(_Symbol, MODE_LOTSTEP);
   freezlevel = (int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_FREEZE_LEVEL);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              if(StringFind(EAName, "Piranh", 0)==-1) return(INIT_FAILED);
   _time2 = iTime(NULL, timeframe, 0);
   tickvalue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   if( Digits == 5 || Digits == 3 ){
      PipsDivided *= 10;
      Slippage *= 10;
      PipStep *= 10;
      Profit *= 10;
      lottextpoint *= 10;
      TrailStart *= 10;
      TrailStop *= 10;
   }
   
   HideTestIndicators(true); 
   
   #ifndef FOR_OPTIMIZATION
   if(!UseTradeTime_1Order) time_trade = "\n  Unlimite trade time";
   else time_trade = "\n  Start Trade: " + (StartHour < 10 ? "0" + (string)StartHour : (string)StartHour) + ":00"
      + "\n  End Trade:  " + (EndHour < 10 ? "0" + (string)EndHour : (string)EndHour) + ":00"; 
      
   if(GlobalVariableCheck(globcountname)) globcount=(int)GlobalVariableGet(globcountname);
   #endif 
   
   Comment(EAName + ", ver: " + (string)VER);
   
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason){
   Comment(""); 
   #ifndef FOR_OPTIMIZATION
   canvas_PANEL.Destroy();
   #endif 
}
//+------------------------------------------------------------------+
//
void OnTick(){

   CalcSetkaEnv(); //запись значений текущей сетки
   
   #ifndef FOR_OPTIMIZATION
   if(showinfopanel) InfoPanel(); //отображать инфопанель
   #endif 
  
   if(env.count>0){
   
      if(_time1 != iTime(NULL, timeframe, 0)){ //Выполнять действия раз в свечу
         _time1 = iTime(NULL, timeframe, 0);
         
         upLinePZ = UpLineIndicator(timeframe, 1);
         dnLinePZ = DnLineIndicator(timeframe, 1);
         upLineATR2 = ATR_OrangeUp(1); 
         dnLineATR2 = ATR_OrangeDn(1);
         upLineATR = ATR_GoldUp(1); 
         dnLineATR = ATR_GoldDn(1);
         
         TP = (DinamicTP_Percent > 0 ? (upLineATR-dnLineATR)*DinamicTP_Percent/100/Point : Profit);
         
      }
      
      if(TrailStartAfter>0 && env.count>=TrailStartAfter){
         if(trailprice>0){
            bool close=false;
            if(env.lasttype==OP_BUY && Bid<trailprice && env.ppoint>0) close=true;
            if(env.lasttype==OP_SELL && Ask>trailprice && env.ppoint>0) close=true;
            if(close){
               #ifndef FOR_OPTIMIZATION
               DrawWarn("Exit: ","By trail",clrOrange);
               Print("Close all by trail: ",DS(env.profit)," $, ",DS(env.ppoint)," pips, ",env.count," orders");
               #endif 
               CloseAll();
               return;
            }
         }
      
         if(env.ppoint>TrailStart){
            double newsl=0;
            if(env.lasttype==OP_BUY){
              newsl=Bid-TrailStop*_Point;
              if(newsl>trailprice) trailprice=newsl;
            }else
            if(env.lasttype==OP_SELL){
              newsl=Ask+TrailStop*_Point;
              if(newsl<trailprice || trailprice==0) trailprice=newsl;
            }
            if(trailprice>0) draw_level("trailstop", trailprice, clrRed);
         }
      }
   
      _TimeCurrent = TimeCurrent();

      if(DayOfWeek()==1 && (_TimeCurrent - env.lasttime)>86400) env.lasttime += 172800;
      
      if(env.count >= Lvl2 && env.ppoint >= 0){
         #ifndef FOR_OPTIMIZATION
         DrawWarn("Exit: ","By profit(lvl2)",clrOrange);
         Print("Close all by profit(lvl2): ",DS(env.profit)," $, ",DS(env.ppoint)," pips, ",env.count," orders");
         #endif 
         CloseAll();
      }else
      if(env.count >= Lvl1 && env.count < Lvl2 && Lvl1 != 0 && env.ppoint >= TP/2){
         #ifndef FOR_OPTIMIZATION
         DrawWarn("Exit: ","By profit(lvl1)",clrOrange);
         Print("Close all by profit(lvl1): ",DS(env.profit)," $, ",DS(env.ppoint)," pips, ",env.count," orders");
         #endif 
         CloseAll();
      }else
      if(env.count < Lvl1 && env.ppoint >= TP){
         #ifndef FOR_OPTIMIZATION
         DrawWarn("Exit: ","By profit",clrOrange);
         Print("Close all by profit: ",DS(env.profit)," $, ",DS(env.ppoint)," pips, ",env.count," orders");
         #endif 
         CloseAll();
      }else
      if(env.count >= Exit2ChannelLvl && Exit2ChannelLvl != 0 && env.ppoint >= 1 && ((env.lasttype==OP_BUY && Bid > upLineATR2) || (env.lasttype==OP_SELL && Ask < dnLineATR2))) {
         #ifndef FOR_OPTIMIZATION
         DrawWarn("Exit: ","Orange Channel",clrOrange);
         Print("Close all by cross channel: ",DS(env.profit)," $, ",DS(env.ppoint)," pips, ",env.count," orders");
         #endif 
         CloseAll();
      }else
      if(env.count >= TimeExit_Start && env.count <= TimeExit_End && env.ppoint >= TP/3 && _TimeCurrent - env.lasttime > 60 * TimeExit_Minutes){
         #ifndef FOR_OPTIMIZATION
         DrawWarn("Exit: ","Time Filter",clrOrange);
         Print("Close all by time: ",IntegerToString((_TimeCurrent-env.lasttime)/60)," min, profit: ",DS(env.profit)," $, ",DS(env.ppoint)," pips, ",env.count," orders");
         #endif 
         CloseAll();
      }else{   
         if(env.last_distance>=PipStep && env.lasttime<_TimeCurrent-900){
         
            if(env.count>LastCloseBy && LastCloseBy>3 && lastlastcloseby<_TimeCurrent-1800){
               fLastCloseBy();
            }
               
            bool OpenOrder = false;
            
            if(!UseMACDforNextOrders || (env.lasttype==OP_SELL && MACD(shift) > 0 && MACD(shift+1) < MACD(shift)) ||
               (env.lasttype==OP_BUY && MACD(shift) < 0 && MACD(shift+1) > MACD(shift))) {
               
               double up=0, down=0;
               if(TurnMainFilters == 0){
                  if(ExpandChannelLvl > 0 && env.count >= ExpandChannelLvl) {
                     up = upLineATR2;
                     down = dnLineATR2;
                  }
                  else {
                     up = upLineATR;
                     down = dnLineATR;
                  }
                  #ifndef FOR_OPTIMIZATION
                  DrawChannel("up",up,clrRoyalBlue);
                  DrawChannel("down",down,clrRoyalBlue); 
                  #endif 
                  if((env.lasttype==OP_BUY && Bid<=down) || (env.lasttype==OP_SELL && Ask>=up)) { DrawWarn("Enter: ","ATR",clrLimeGreen); OpenOrder = true; }
                  
               }else         
               if(TurnMainFilters == 1){
                  up = (upLineATR+upLinePZ)/2;
                  down = (dnLinePZ+dnLineATR)/2;
                  #ifndef FOR_OPTIMIZATION
                  DrawChannel("up",up,clrRoyalBlue);
                  DrawChannel("down",down,clrRoyalBlue); 
                  #endif 
                  if((env.lasttype==OP_BUY && Bid<=down) || (env.lasttype==OP_SELL && Ask>=up)) { DrawWarn("Enter: ","PZ & ATR",clrLimeGreen); OpenOrder = true; }
               }
            }
            
            if(OpenOrder == true) { //если есть сигнал на вход
               if(env.lasttype==OP_BUY){
                  OrderSendX(OP_SELL, CalcLot(env.count), 0, 0, EAName+(string)VER+"-"+IntegerToString(env.count+1), MAGIC, clrRed);
               }else{
                  OrderSendX(OP_BUY, CalcLot(env.count), 0, 0, EAName+(string)VER+"-"+IntegerToString(env.count+1), MAGIC, clrBlue);
               }
            } 
         }      
      }
   }else{
     if(_time2 != iTime(NULL, timeframe, 0)){
         _time2 = iTime(NULL, timeframe, 0);
         //Open first order
         if( HourOk() == false ) return;  
         
         #ifndef FOR_OPTIMIZATION
         //Currency filter
         if(StopByMaxOrdersOneSymbol > 0 && globfilter.symbols >= StopByMaxSymbolTrades) return;
         if(StopByMaxSymbolTrades > 0 && globfilter.maxorders >= StopByMaxSymbolTrades) return;
         if(StopEqualCurrencyTrade && globfilter.tradethiscurrency) return;
         
         if(iBars(_Symbol, timeframe) < a__PeriodATR+1){
            //Print("Error: Недостаточно загруженной истории для ATR");
            return;
         }  
         #endif 
         
         //if(FilterADX_Period > 0 && FilterADX_Level > 0){
         //   if(iADX(NULL, timeframe, FilterADX_Period, PRICE_CLOSE, 0, 1) < FilterADX_Level) return; 
         //}
         
         if(FilterADX_Period > 0) { 
            ADX_PLUSDI = iADX(NULL, timeframe, FilterADX_Period, PRICE_CLOSE, MODE_PLUSDI, 1);
            ADX_MINUSDI = iADX(NULL, timeframe, FilterADX_Period, PRICE_CLOSE, MODE_MINUSDI, 1);
         }  
         
         upLinePZ = UpLineIndicator(timeframe, shift);
         dnLinePZ = DnLineIndicator(timeframe, shift);
         double main_signal = SigLineIndicator(timeframe, shift);
         double second_signal = Sig2LineIndicator(timeframe, shift);
         
         //
         if(upLinePZ == 0.0 || dnLinePZ == 0.0){
            if(GetLastError()==ERR_INDICATOR_CANNOT_LOAD){
               Print("Error: indicator ""X2 PRICE ZONE 2"" not exist");
               ExpertRemove();
            }
         }
         
         double ATR_GoldUp = ATR_GoldUp(shift);
         double ATR_GoldDn = ATR_GoldDn(shift);
         if(ATR_GoldUp == 0.0 || ATR_GoldDn == 0.0) return;
         
         #ifndef FOR_OPTIMIZATION
         DrawChannel("upLinePZ", upLinePZ, clrCadetBlue);
         DrawChannel("dnLinePZ", dnLinePZ, clrCadetBlue);
         DrawChannel("ATR_GoldUp", ATR_GoldUp, clrGold);
         DrawChannel("ATR_GoldDn", ATR_GoldDn, clrGold);
         #endif 
         
         if( second_signal < main_signal)
         if( FilterADX_Period == 0 || FilterADX_Level == 0 || (ADX_MINUSDI < ADX_PLUSDI && ADX_PLUSDI > FilterADX_Level))
         if( iOpen(NULL, timeframe, 0) > upLinePZ )
         if( iOpen(NULL, timeframe, 0) <= ATR_GoldUp )
         if( MACD(shift) > 0.0005 && MACD(shift+1) < MACD(shift) )
         if( MACD_Signal(shift) < MACD(shift)){
            OrderSendX(OP_BUY, DinamicLot(), 0, 0, EAName+(string)VER+"-"+IntegerToString(env.count+1), MAGIC, clrBlue);
            return;
         }
         
         if( second_signal > main_signal)
         if( FilterADX_Period == 0 || FilterADX_Level == 0 || (ADX_MINUSDI > ADX_PLUSDI && ADX_MINUSDI > FilterADX_Level))
         if( iOpen(NULL, timeframe, 0) < dnLinePZ )
         if( iOpen(NULL, timeframe, 0) >= ATR_GoldDn(shift) )
         if( MACD(shift) < -0.0005 && MACD(shift+1) > MACD(shift) )
         if( MACD_Signal(shift) > MACD(shift) ){
            OrderSendX(OP_SELL, DinamicLot(), 0, 0, EAName+(string)VER+"-"+IntegerToString(env.count+1), MAGIC, clrRed);
         }
      }
   }  
   
   #ifndef FOR_OPTIMIZATION
   int Error = GetLastError(); //поиск ошибок в завершение
   if(Error != 0) Print("OnTick() Error ",Error,": ",ErrorDescription(Error));
   #endif 

}

//+------------------------------------------------------------------+

bool HourOk(){
   
   if(!UseTradeTime_1Order) return(true);

   bool work=true;
   
   switch(DayOfWeek()){
      case 1: if(!MONDAY_Enabled) work=false; break;
      case 2: if(!TUESDAY_Enabled)   work=false; break;
      case 3: if(!WEDNESDAY_Enabled) work=false; break;
      case 4: if(!THURSDAY_Enabled)  work=false; break;
      case 5: if(!FRIDAY_Enabled) work=false; break;
      default: work=false;                                              
   }
   if(work){
      if( StartHour == EndHour && Hour() == StartHour) return(true);
      
      if( StartHour < EndHour ){
         if( Hour() == StartHour && Hour() < EndHour ) return(true);
         if( Hour() >  StartHour && Hour() < EndHour ) return(true);
         if( Hour() >  StartHour && Hour() == EndHour ) return(true);
      }
      
      if( StartHour > EndHour ){
         if( Hour() == StartHour ) return(true);
         if( Hour() > StartHour ) return(true);
         if( Hour() < EndHour ) return(true);  
         if( Hour() == EndHour ) return(true);  
      }  
   }
   return(false);
}

//+------------------------------------------------------------------+
double UpLineIndicator(datetime tf, int bar){ return(iCustom(NULL, (int)tf, "X2 PRICE ZONE 2", ma_period, ma_method, applied_price, 3, bar)); }
double DnLineIndicator(datetime tf, int bar){ return(iCustom(NULL, (int)tf, "X2 PRICE ZONE 2", ma_period, ma_method, applied_price, 4, bar)); }
double SigLineIndicator(datetime tf, int bar){ return(iCustom(NULL, (int)tf, "X2 PRICE ZONE 2", ma_period, ma_method, applied_price, 0, bar)); }  
double Sig2LineIndicator(datetime tf, int bar){ return(iCustom(NULL, (int)tf, "X2 PRICE ZONE 2", ma_period, ma_method, applied_price, 6, bar)); }  

double ATR_Channels(int buffer, int bar){
   double atr = iATR(NULL, 0, a__PeriodATR, bar);
   double ma = iMA(NULL, 0, a__MaPeriod, 0, a__MaTypr, PRICE_TYPICAL, bar);
   switch(buffer){
      case 1: return ma + atr*a__Mult_Factor1;
      case 2: return ma - atr*a__Mult_Factor1;
      case 3: return ma + atr*a__Mult_Factor2;
      case 4: return ma - atr*a__Mult_Factor2;
      //case 5: return ma + atr*a__Mult_Factor3;
      //case 6: return ma - atr*a__Mult_Factor3;
   }
   return 0;
}

double ATR_GoldUp(int bar){ return(ATR_Channels(1, bar)); }
double ATR_GoldDn(int bar){ return(ATR_Channels(2, bar)); }
double ATR_OrangeUp(int bar){ return(ATR_Channels(3, bar)); }
double ATR_OrangeDn(int bar){ return(ATR_Channels(4, bar)); }
double ATR_AquaUp(int bar){ return(ATR_Channels(5, bar)); }
double ATR_AquaDn(int bar){ return(ATR_Channels(6, bar)); }

double MACD(int bar){ return iMACD(NULL,timeframe,macd_FastEma, macd_SlowEma, macd_SignalEma,PRICE_CLOSE,0,bar); }
double MACD_Signal(int bar){ return iMACD(NULL,timeframe,macd_FastEma, macd_SlowEma, macd_SignalEma,PRICE_CLOSE,1,bar); }

//+------------------------------------------------------------------+

void CalcSetkaEnv(){
   ZeroMemory(env);
   
   #ifndef FOR_OPTIMIZATION
   if(RealTrade){ ArrayResize(tradeenv,0); ZeroMemory(globfilter);}
   #endif
   
   double lotdiff=0;
   for(int order=OrdersTotal()-1; order>=0; order--){
      if(!OrderSelect(order, SELECT_BY_POS, MODE_TRADES)) continue;
      #ifndef FOR_OPTIMIZATION
      if(RealTrade) CalcTradeEnv(OrderSymbol());
      if(OrderSymbol() != _Symbol) continue;
      if(MAGIC>0 && OrderMagicNumber() != MAGIC) continue;
      #endif 
      
      env.count++;
      env.profit+=OrderProfit()+OrderCommission()+OrderSwap();
      if(OrderLots()<env.firstlot || env.firstlot==0) env.firstlot=OrderLots();
      
      if(OrderType()==OP_BUY)  {
         env.count_buy++;
         env.countlot_buy+=OrderLots();
         lotdiff+=OrderLots();
      }   
      
      if(OrderType()==OP_SELL) {
         env.count_sell++;
         env.countlot_sell+=OrderLots();
         lotdiff-=OrderLots();
      }

      if(OrderLots() > env.lastlot){
         env.lasttime = OrderOpenTime();
         env.lastprice = OrderOpenPrice();
         env.lasttype = OrderType();
         env.lastlot = OrderLots();
      }
   }
   
   #ifndef FOR_OPTIMIZATION
   if(env.count<2) { 
      draw_level("be_level", 0, clrNONE);
      draw_level("profit_level", 0, clrNONE);
   }  
   
   if(RealTrade){
      for(int i=ArraySize(tradeenv)-1; i>=0; i--){
         if(tradeenv[i].count > globfilter.maxorders) globfilter.maxorders = tradeenv[i].count;
         if(StringFind(tradeenv[i].symbol, s1str, 0) >= 0 || StringFind(tradeenv[i].symbol, s2str, 0) >= 0) globfilter.tradethiscurrency = true;
      }
      globfilter.symbols=ArraySize(tradeenv);
   }
   #endif 
   
   if(env.count>0){
      if(env.count>1){
         double newtickvalue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
         if(newtickvalue>0) tickvalue=newtickvalue;
         if(tickvalue==0) tickvalue=1;
         if(lotdiff>0) env.avg = ND(Bid-(env.profit/lotdiff/tickvalue*_Point));
         else
         if(lotdiff<0) env.avg = ND(Ask-(env.profit/lotdiff/tickvalue*_Point));

         draw_level("be_level", env.avg, clrDarkGoldenrod);
      }else
         env.avg = env.lastprice;
      
      double ProfitLine = (env.count >= Lvl2 ? env.avg : (env.count >= Lvl1 && Lvl1 != 0 ? TP/2 : TP))*Point;
      if(env.lasttype==OP_BUY){  
         env.last_distance = (int)NormalizeDouble((env.lastprice - Ask) / _Point,0);
         if(env.avg>0) {
            env.ppoint = (int)NormalizeDouble((Bid - env.avg) / _Point,0);
            draw_level("profit_level", env.avg+ProfitLine, clrLime);
         }
      }else 
      if(env.lasttype==OP_SELL){
         env.last_distance = (int)NormalizeDouble((Bid - env.lastprice) / _Point,0);
         if(env.avg>0) {
            env.ppoint = (int)NormalizeDouble((env.avg - Ask) / _Point,0);
            draw_level("profit_level", env.avg-ProfitLine, clrLime);
         }   
      }
      
      
      if(LastCloseBy>3 && globcount>env.count) env.count=globcount;
   }
   
 
}

void CalcTradeEnv(string symb){
   bool found=false;
   for(int i=ArraySize(tradeenv)-1; i>=0; i--){
      if(tradeenv[i].symbol==symb){
         found=true;
         tradeenv[i].count++;
      }
   }
   if(!found){
      int asize=ArraySize(tradeenv);
      ArrayResize(tradeenv,asize+1);
      tradeenv[asize].symbol=symb;
      tradeenv[asize].count=1;
   }
}

double ND(double val, int dig = EMPTY ){ if(dig == EMPTY) dig = Digits; return( NormalizeDouble(val, dig) ); }
string DS(double d){return DoubleToString(d,2);}

//----------
double DinamicLot(){
   double iLots=Lots;
   if(DepoPer001Lot>0){
      iLots = NormalizeDouble((AccountInfoDouble(ACCOUNT_MARGIN_FREE)/DepoPer001Lot)/100,2);
   }
   CheckVolumeValue(iLots);
   return iLots;
}

//----------
double CalcLot(int Trades){
   double iLots=Lots;
   if(Trades>=Lvl2-1) iLots=NormalizeDouble(env.lastlot * LotExponent2, 2);
   else iLots=NormalizeDouble(env.firstlot * MathPow(LotExponent1, Trades), 2); 
   
   CheckVolumeValue(iLots);
   return iLots;
}

//----------
void CloseAll() {
   _time2 = iTime(NULL, timeframe, 0);
   ArrayResize(orders,0);
   
   //Get orders by lot
   int tickets[], nTickets = GetOrderByLots(tickets)-1;
   for(int iTicket = 0; iTicket <= nTickets; iTicket++) if (OrderSelect(tickets[iTicket], SELECT_BY_TICKET)){
      int asize=ArraySize(orders);
      ArrayResize(orders, asize+1);
      orders[asize].lots=OrderLots();
      orders[asize].type=OrderType();
      orders[asize].ticket=OrderTicket();
   }
   
   //Calc lots after close by
   int size=ArraySize(orders)-1;
   for(int i=size; i>=0; i--){
      if(orders[i].lots==0) continue;
      for(int j=size; j>=0; j--){
         if(orders[j].lots==0) continue;
         if(orders[i].lots <= orders[j].lots && orders[i].type!=orders[j].type){
            orders[j].lots-=orders[i].lots;
            orders[i].lots=0;
            break;
         }
      }
   }
   
   //Close biggest lots
   for(int i=0; i<size; i++){
      if(orders[i].lots==0) continue;
      OrderCloseX(orders[i].ticket, orders[i].lots, orders[i].type, Slippage, orders[i].type==OP_BUY ? clrBlue : clrRed);
   }
   
   //CloseBy
   int retry = 10;
   int cnt1   = 0;
   while(cnt1<retry){
      if(CloseByAll()<1) break;
      cnt1++;
   }
   
   //Close All not closed
   ArrayResize(tickets,0); nTickets = GetOrderByLots(tickets)-1;
   for(int iTicket = 0; iTicket <= nTickets; iTicket++) if (OrderSelect(tickets[iTicket], SELECT_BY_TICKET)){
      OrderCloseX(OrderTicket(), OrderLots(), OrderType(), Slippage, OrderType()==OP_BUY ? clrBlue : clrRed);     
   }
   
   //Stat
   stat.count++;
   stat.sumcount+=env.count;
   if(env.count>stat.maxcount) stat.maxcount=env.count;
   
   //Reset glob
   trailprice=0;
   draw_level("trailstop", trailprice, clrNONE);
   if(LastCloseBy>3){
      globcount=0;
      if(RealTrade) GlobalVariableSet(globcountname, globcount);
   }
}
//----------
int CloseByAll(){
   ArrayResize(orders,0);
   
   int tickets[], nTickets = GetOrderByLots(tickets)-1;
   for(int iTicket = 0; iTicket <= nTickets; iTicket++) if (OrderSelect(tickets[iTicket], SELECT_BY_TICKET)){
      int asize=ArraySize(orders);
      ArrayResize(orders, asize+1);
      orders[asize].lots=OrderLots();
      orders[asize].type=OrderType();
      orders[asize].ticket=OrderTicket();
   }
   
   int size=ArraySize(orders);
   for(int i=0; i<size; i++){
      if(orders[i].lots==0) continue;
      for(int j=0; j<size; j++){
         if(orders[j].lots==0) continue;
         if(orders[i].lots >= orders[j].lots && orders[i].type!=orders[j].type){
            if(OrderCloseBy(orders[i].ticket, orders[j].ticket, clrGray)){
               orders[i].lots=0;
               orders[j].lots=0;
               nTickets-=1;
               break;
            }else{
               int err=GetLastError();
               if(err==3) return 0; else Print("Error: ",ErrorDescription(err)); 
            }
         }
      }
   }
   
   return nTickets;
}

//----------
int GetOrderByLots(int& tickets[]){  
   int nOrders = 0, iOrders=0; double OPs[];
   for(int iPos=OrdersTotal()-1; iPos >= 0; iPos--) 
   if (OrderSelect(iPos, SELECT_BY_POS, MODE_TRADES) && OrderSymbol()==_Symbol && OrderType()<=OP_SELL && (MAGIC==0 || OrderMagicNumber() == MAGIC)){
      int nextTkt = OrderTicket(); double nextOP = OrderLots();
      nOrders++; ArrayResize(tickets,nOrders); ArrayResize(OPs,nOrders);
      for (iOrders=nOrders - 1; iOrders > 0; iOrders--){  // Insertn sort.
         double prevOP = OPs[iOrders-1];
         if ((prevOP - nextOP) >= 0) break;
         int prevTkt = tickets[iOrders-1];
         tickets[iOrders] = prevTkt; OPs[iOrders] = prevOP;
      }
      tickets[iOrders] = nextTkt; OPs[iOrders] = nextOP; // Insert.
   }
   return(nOrders);
}

//----------
void fLastCloseBy(){
   ArrayResize(orders,0);
   
   int tickets[], nTickets = GetOrderByLots(tickets)-1;
   for(int iTicket = 0; iTicket <= nTickets; iTicket++) if (OrderSelect(tickets[iTicket], SELECT_BY_TICKET)){
      int asize=ArraySize(orders);
      ArrayResize(orders, asize+1);
      orders[asize].lots=OrderLots();
      orders[asize].type=OrderType();
      orders[asize].ticket=OrderTicket();
      orders[asize].profit=(OrderProfit()+OrderCommission()+OrderSwap())/orders[asize].lots;
   }
   
   int size=ArraySize(orders)-1;
   for(int i=size; i>=2; i--){
      if(orders[i].lots==0) continue;
      for(int j=size-1; j>=1; j--){
         if(orders[j].lots==0) continue;
         if(orders[i].type!=orders[j].type){
            if((orders[i].profit+orders[j].profit)>=0){
               if(OrderCloseBy(orders[i].ticket,orders[j].ticket)){
                  //ExpertRemove();
                  return;
               }else{
                  int err=GetLastError();
                  if(err==3){
                     if(orders[i].lots>orders[j].lots){
                        OrderCloseX(orders[i].ticket, orders[i].lots-orders[j].lots, orders[i].type, Slippage, clrGray);
                        OrderCloseX(orders[j].ticket, orders[j].lots, orders[j].type, Slippage, clrGray);
                     }else{
                        OrderCloseX(orders[j].ticket, orders[j].lots-orders[i].lots, orders[j].type, Slippage, clrGray);
                        OrderCloseX(orders[i].ticket, orders[i].lots, orders[i].type, Slippage, clrGray);
                     }
                     //return;
                  }else
                     Print("Error: ",ErrorDescription(err));
               }
               #ifndef FOR_OPTIMIZATION
               Print("LastCloseBy: #",orders[i].ticket," (",DoubleToString(orders[i].lots,2)," lot) and #",orders[j].ticket," (",DoubleToString(orders[j].lots,2)," lot)");
               #endif 
               orders[j].lots=0;
               orders[i].lots=0;
               lastlastcloseby=_TimeCurrent;
               break;
            }
         }
      }
   }
}

//----------
void DrawWarn(string condition, string text, color col){ //писать текст с уведомлениями на графике
   #ifndef FOR_OPTIMIZATION
   if(!VisualDebug) return;
   if(RealTrade || (IsTesting() && IsVisualMode())){
   
      string obid="Piranha|"+condition+TimeToStr(Time[0]);
      if(ObjectFind(obid) < 0) {
         ENUM_ANCHOR_POINT anc;
         double price;
      
         if((WindowPriceMax()+WindowPriceMin())/2 < Bid) {
            price=MathMin(Low[0],Low[1])-lottextpoint*2*_Point;
            anc=ANCHOR_RIGHT;
         }
         else {
            price=MathMax(High[0],High[1])+lottextpoint*2*_Point;
            anc=ANCHOR_LEFT;
         }
         
         ObjectCreate(obid, OBJ_TEXT, 0, Time[0], price);
         ObjectSet(obid, OBJPROP_ANGLE, 90);
         ObjectSet(obid,OBJPROP_ANCHOR,anc);
         ObjectSet(obid,OBJPROP_BACK,true);
      }
      ObjectSetText(obid,condition+text,7,"Arial",col);
   }
   #endif 
}

//----------
void DrawChannel(string dir, double pr1, color clr=clrYellow){
   #ifndef FOR_OPTIMIZATION
   if(!VisualDebug) return;
   string name=_Symbol+dir+TimeToString(Time[0]);
   string name_prev=_Symbol+dir+TimeToString(Time[1]);

   double pr2=pr1;
   if(ObjectFind(0,name) < 0){
      if(ObjectFind(0,name_prev) == 0) pr2=ObjectGetDouble(0,name_prev,OBJPROP_PRICE,1);
   
      ObjectCreate(0,name,OBJ_TREND,0,Time[1],pr2,Time[0],pr1);
      ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false); 
      ObjectSetInteger(0,name, OBJPROP_COLOR, clr);
   }
   #endif 
}

//----------
void draw_level(string n, double price, color clr){
   #ifndef FOR_OPTIMIZATION
   if(!VisualDebug) return;
   if(price<=0){
      if(ObjectFind(0,n) != -1) ObjectDelete(0,n);
   }else{
      if(ObjectFind(0,n) < 0) ObjectCreate(0,n, OBJ_HLINE, 0, 0, price); else ObjectSetDouble(0,n, OBJPROP_PRICE, price);
      ObjectSetInteger(0,n, OBJPROP_STYLE, STYLE_DOT);
      ObjectSetInteger(0,n, OBJPROP_COLOR, clr);
   }
   #endif 
}

//----------
bool OrderSendX(ENUM_ORDER_TYPE pType, double pLots, double sl, double tp, string pComment, int pMagic, color pColor=CLR_NONE){
   int  err = ERR_NO_ERROR;
   bool exit_loop = false;
   double pLevel=0;
   uint start=GetTickCount();
   
   int retry = 10;
   int cnt1   = 0;
   int ticket = -1;

   #ifndef FOR_OPTIMIZATION
   double free_margin=AccountFreeMarginCheck(_Symbol,pType,pLots);
   if(free_margin<0){
      err = GetLastError();
      Print(Hour(),":",Minute()," | ",EnumToString(pType)," | ",pLots, " | ",ErrorDescription(err));
      return false;
   }
   #endif 

   while(!exit_loop && cnt1<retry){
     if(pType==OP_BUY)  pLevel=Ask; else if(pType==OP_SELL) pLevel=Bid; else return false;
     start=GetTickCount();
     ticket = OrderSend(_Symbol, pType, pLots, pLevel, Slippage, sl, tp, pComment, pMagic, 0, pColor);
     if(ticket<0){
        err = GetLastError();
        switch(err){
          case ERR_INVALID_PRICE:
               RefreshRates();
               break;
          case ERR_INVALID_TRADE_VOLUME:
               if(pLots>maxlot) pLots = maxlot;
               break;
          case ERR_REQUOTE:
               RefreshRates();
               break;
          case ERR_OFF_QUOTES:
               RefreshRates();
               break;
          case ERR_BROKER_BUSY:
               break;
          case ERR_NOT_ENOUGH_MONEY:
               ExpertRemove();
               break;
          default:
               exit_loop = true;
               break;
        }
        Sleep(1000);
        
        cnt1++;
     }else{
         err = 0;
         exit_loop = true;
     }
   }
   
   #ifndef FOR_OPTIMIZATION
   if(ticket>=0){
      uint time1=GetTickCount()-start;
      exit_loop = false;
      retry = 100;
      cnt1 = 0;
      
      while(!exit_loop && cnt1<retry){
         exit_loop = OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES);
         if(exit_loop){
            double Slp = NormalizeDouble((OrderType()==OP_BUY ? pLevel - OrderClosePrice() : OrderClosePrice() - pLevel)/_Point,1); 
            Print(Hour(),":",Minute()," | ",__FUNCTION__,": ",(OrderType()==OP_BUY ? "BUY" : "SELL")," price / cmd / slp / delay = ",OrderClosePrice()," / ",NormalizeDouble(pLevel,Digits)," / ",DoubleToString(Slp,1)+" point / ",time1," ms");
            //BrokerStatWrite(ticket,"open","ea",Slp,time1,"0");
         }else
            Sleep(200);
         cnt1++; 
      }
      if(!exit_loop) Print(Hour(),":",Minute()," | ",__FUNCTION__," Error: ",ErrorDescription(err));
      
      if(LastCloseBy>3){
         globcount++;
         if(RealTrade) GlobalVariableSet(globcountname, globcount);
      }
      
      return true;
   }
   #endif 
   
   if(err != ERR_NO_ERROR && err != ERR_NO_RESULT) Print("Error open order: " + ErrorDescription(err));
   return false;
}

//----------
bool CheckVolumeValue(double &volume){
   double volume_step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001){
      Print("Message: Lot step correction ",volume," to ",ratio*volume_step); 
      volume = ratio*volume_step;
   }
   
   if(volume < minlot){ 
      Print("Message: Lot = ",volume," < min = ",minlot,", lot correction to min lot"); 
      volume = minlot;
   }
   if(volume > maxlot){ 
      Print("Message: Lot = ",volume," > max = ",maxlot,", lot correction to max lot"); 
      volume = maxlot;
   }
     
   return true;
}

//----------
void OrderCloseX(int ticket1, double lot, int otype, int slp, color clr=CLR_NONE){
    int err = 0; double price = 0; uint start=GetTickCount();
    bool exit_loop = false;

    int retry = 5; 
    int cnt1   = 0;
    
    while(!exit_loop && cnt1<retry){
        if(otype == OP_BUY)  price=Bid;
        if(otype == OP_SELL) price=Ask;

        start=GetTickCount();
        if(!OrderClose(ticket1, lot, price, slp, clr)){
           err = GetLastError();
           switch(err){
             case ERR_INVALID_PRICE:
                  RefreshRates();
                  break;
             case ERR_REQUOTE:
                  RefreshRates();
                  break;
             case ERR_OFF_QUOTES:
                  RefreshRates();
                  break;
             case ERR_BROKER_BUSY:
                  break;
             default:
                  exit_loop = true;
                  break;
           }
           Sleep(1000);
           cnt1++;
        }else{
           err = 0;
           exit_loop = true;
        }
   }
   
   #ifndef FOR_OPTIMIZATION
   if(exit_loop && err == 0){
      uint time=GetTickCount()-start;
      retry = 99;     
      cnt1=0;
      exit_loop = false;

      while(!exit_loop && cnt1<retry){
         exit_loop = OrderSelect(ticket1, SELECT_BY_TICKET, MODE_HISTORY);
         if(exit_loop){
            double Slp = NormalizeDouble((OrderType()==OP_BUY ? price - OrderClosePrice() : OrderClosePrice() - price)/_Point,1); 
            Print(Hour(),":",Minute()," | ",__FUNCTION__,": ",(OrderType()==OP_BUY ? "BUY" : "SELL")," price / cmd / slp / delay = ",OrderClosePrice()," / ",price," / ",DoubleToString(Slp,1)+" point / ",time," ms");
            //BrokerStatWrite(ticket1,"close","ea",Slp,time);
         }else
            Sleep(100);
         cnt1++;
      }
      if(!exit_loop) Print(Hour(),":",Minute()," | ",__FUNCTION__," ",ErrorDescription(GetLastError()));
   }else      
      if(err != ERR_NO_ERROR && err != ERR_NO_RESULT) Print("Error ",__FUNCTION__," #",ticket1,": ",ErrorDescription(err));
   #endif 
}

//----------
void OrderModifyX(int ticket1, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE){
    int err = 0;
    bool exit_loop = false;

    int retry = 10;
    int cnt1   = 0;

   #ifndef FOR_OPTIMIZATION
   if(freezlevel>0){
      if((int)(takeprofit-Bid/_Point) <= freezlevel) return; 
      if((int)(Bid-stoploss/_Point) <= freezlevel) return;
   
      if((int)(Ask-takeprofit/_Point) <= freezlevel) return; 
      if((int)(stoploss-Ask/_Point) <= freezlevel) return;
   }
   #endif 
    
    while(!exit_loop && cnt1<retry){
        if(!OrderModify(ticket1, price, stoploss, takeprofit, expiration, arrow_color)){
           err = GetLastError();
           switch(err){
             case ERR_INVALID_STOPS:
                  if(OrderSelect(ticket1, SELECT_BY_TICKET)){
                     RefreshRates();
                     stoplevel=(int)MarketInfo(_Symbol,MODE_STOPLEVEL);
                     if(takeprofit>0 && !CompareDoubles(takeprofit,OrderTakeProfit())) { 
                        if(OrderType()==OP_BUY)  takeprofit=ND(Ask+stoplevel*_Point);
                        if(OrderType()==OP_SELL) takeprofit=ND(Bid-stoplevel*_Point);
                     }
                  }
                  break;
             case ERR_REQUOTE:
                  RefreshRates();
                  break;
             case ERR_OFF_QUOTES:
                  RefreshRates();
                  break;
             case ERR_BROKER_BUSY:
                  break;
             default:
                  exit_loop = true;
                  break;
           }
           Sleep(1000);
           cnt1++;
        }else{
           err = 0;
           exit_loop = true;
        }
   }
      
   if(err != ERR_NO_ERROR && err != ERR_NO_RESULT) Print ("Error modify #" + IntegerToString(ticket1) + ": " + ErrorDescription(err));
}

//----------
double OnTester(){
  Print("Stat series: max: ",stat.maxcount,", avg: ",(stat.count > 0 ? (string)(stat.sumcount/stat.count) : "0"));
   
  double Res = 0;
  double MaxDD = TesterStatistics(STAT_EQUITY_DD);
  if (MaxDD != 0)
      Res = TesterStatistics(STAT_PROFIT) / MaxDD;
  return Res;
}

//----------
void InfoPanel() {

   string info_panel =
     "\n             " + EAName + ", ver: " + (string)VER
   + "\n           for TRADELikeAPro" 
   + "\n  ----------------------------------------------" 
   + "\n  Set: " + SetName       
   + "\n  ----------------------------------------------" 
   + "\n  Current Spread: " + DoubleToStr((Ask - Bid)/_Point/PipsDivided,1)
   + "\n  ----------------------------------------------"  
   + time_trade
   + "\n  ----------------------------------------------"
   + "\n  Orders Buy: " + IntegerToString(env.count_buy) + ". Sum Lot: " + DoubleToStr(env.countlot_buy,2)
   + "\n  Orders Sell: " + IntegerToString(env.count_sell)+ ". Sum Lot: " + DoubleToStr(env.countlot_sell,2)
   + "\n  Distance to BE: " + (env.count > 0 ? DoubleToStr(MathAbs(Bid-env.avg)/_Point/PipsDivided,1) : "0") + " pips"
   + "\n  Total profit: " + DoubleToStr(env.profit,2) + " "+ AccountCurrency()
   + "\n  ----------------------------------------------";
         
   Comment(info_panel);

}



//+------------------------------------------------------------------+
void _ReadParametrs() {
   string FileName = "test.csv";
   int handle = FileOpen(FileName,FILE_READ||FILE_CSV);//,''); 
   if (handle < 1) return;
   FileSeek(handle,0,SEEK_SET);
   int str = StrToInteger(FileReadString(handle)); 
   int data = StrToInteger(FileReadString(handle)); 
   if (data < VarOptimCounter) { Alert("Wrong number of test result in test.csv file"); return; } //Введено некорректное количество тестовых проходов

   for(int y=1;y<=VarOptimCounter;y++) {
      for(int x=1;x<=str;x++) {
         string s = FileReadString(handle); 
         string ds = FileReadString(handle); 
         if (y != VarOptimCounter) continue;
         s = StringTrimLeft(s);s = StringTrimRight(s);
         ds = StringTrimLeft(ds);ds = StringTrimRight(ds);
         int i = StrToInteger(ds);
         double d = StrToDouble(ds);

         if (s == "MAGIC") { MAGIC = i;  continue; }
         else if (s == "Slippage") { Slippage = i;  continue; }
         else if (s == "Lots") { Lots = d;  continue; }
         else if (s == "DepoPer001Lot") { DepoPer001Lot = i;  continue; }
         
         
         
         else if (s == "PipStep") { PipStep = i;  continue; }
         else if (s == "Profit") { Profit = i;  continue; }
         else if (s == "DinamicTP_Percent") { DinamicTP_Percent = d;  continue; }
         else if (s == "Lvl1") { Lvl1 = i;  continue; }
         else if (s == "Lvl2") { Lvl2 = i;  continue; }
         else if (s == "LotExponent1") { LotExponent1 = d;  continue; }
         else if (s == "LotExponent2") { LotExponent2 = d;  continue; }
         
         else if (s == "TimeExit_Start") { TimeExit_Start = i;  continue; }
         else if (s == "TimeExit_End") { TimeExit_End = i;  continue; }
         else if (s == "TimeExit_Minutes") { TimeExit_Minutes = i;  continue; }
         else if (s == "LastCloseBy") { LastCloseBy = i;  continue; }

         else if (s == "a__PeriodATR") { a__PeriodATR = i;  continue; }
         else if (s == "a__MaPeriod") { a__MaPeriod = i;  continue; }
         else if (s == "a__Mult_Factor1") { a__Mult_Factor1 = d;  continue; }
         else if (s == "a__Mult_Factor2") { a__Mult_Factor2 = d;  continue; }
         
         else if (s == "ma_period") { ma_period = i;  continue; }
         else if (s == "ma_method") { ma_method = i;  continue; }
         else if (s == "applied_price") { applied_price = i;  continue; }
         
         else if (s == "FilterADX_Period") { FilterADX_Period = i;  continue; }
         else if (s == "FilterADX_Level") { FilterADX_Level = i;  continue; }
         
         
         else if (s == "macd_FastEma") { macd_FastEma = i;  continue; }
         else if (s == "macd_SlowEma") { macd_SlowEma = i;  continue; }
         else if (s == "macd_SignalEma") { macd_SignalEma = i;  continue; }
         else if (s == "shift") { shift = i;  continue; }
         else if (s == "UseMACDforNextOrders") { UseMACDforNextOrders = i;  continue; }
         
         else if (s == "TurnMainFilters") { TurnMainFilters = _ReadParametrs(i);  continue; }
         else if (s == "ExpandChannelLvl") { ExpandChannelLvl = i;  continue; }
         
         else if (s == "Exit2ChannelLvl") { Exit2ChannelLvl = i;  continue; }
         
         else if (s == "TrailStartAfter") { TrailStartAfter = i;  continue; }
         else if (s == "TrailStart") { TrailStart = i;  continue; }
         else if (s == "TrailStop") { TrailStop = i;  continue; }
         
         else if (s == "UseTradeTime_1Order") { UseTradeTime_1Order = i;  continue; }
         else if (s == "StartHour") { StartHour = i;  continue; }
         else if (s == "EndHour") { EndHour = i;  continue; }
         else if (s == "MONDAY_Enabled") { MONDAY_Enabled = i;  continue; }
         else if (s == "TUESDAY_Enabled") { TUESDAY_Enabled = i;  continue; }
         else if (s == "WEDNESDAY_Enabled") { WEDNESDAY_Enabled = i;  continue; }
         else if (s == "THURSDAY_Enabled") { THURSDAY_Enabled = i;  continue; }
         else if (s == "FRIDAY_Enabled") { FRIDAY_Enabled = i;  continue; }


      }
   }
   FileClose(handle);
  return;
}

//+------------------------------------------------------------------+
_TurnFilter _ReadParametrs(int variableToEnum) {
   switch (variableToEnum) 
   { 
      case 0: return (TurnFilterATR); 
      case 1: return (TurnFilterPZ_ATR); 
      case 2: return (None);
      default: return (TurnFilterATR); 
   }     
}

//+------------------------------------------------------------------+
void _WriteSet() {

   string TFPeriod = "";
   switch(Period()) { //определение текущего периода для записи имени файла
      case 1:     TFPeriod = "M1"; break;
      case 5:     TFPeriod = "M5"; break;
      case 15:    TFPeriod = "M15"; break;
      case 30:    TFPeriod = "M30"; break;
      case 60:    TFPeriod = "H1"; break;
      case 240:   TFPeriod = "H4"; break; 
      case 1440:  TFPeriod = "D1"; break; 
      case 10080: TFPeriod = "W1"; break;
      case 43200: TFPeriod = "MN"; break;
      default: TFPeriod = "Unknown TF";
   }
   
   string FileName = IntegerToString(VarOptimCounter) + " " + WindowExpertName() + " " + Symbol() + " " + TFPeriod  + ".set";
   string _SetName = WindowExpertName() + " " + Symbol() + " " + TFPeriod;
   int handle = FileOpen((FileName),FILE_WRITE|FILE_CSV);
   if (handle < 1) return;
   
   FileWrite(handle,"timeframe="+ (string)timeframe);
   FileWrite(handle,"MAGIC="+ (string)MAGIC);
   FileWrite(handle,"Slippage="+ (string)Slippage);
   FileWrite(handle,"Lots="+ (string)Lots);
   FileWrite(handle,"DepoPer001Lot="+ (string)DepoPer001Lot);
   
   
   
   FileWrite(handle,"PipStep="+ (string)PipStep);
   FileWrite(handle,"Profit="+ (string)Profit);
   FileWrite(handle,"DinamicTP_Percent="+ (string)DinamicTP_Percent);
   FileWrite(handle,"Lvl1="+ (string)Lvl1);
   FileWrite(handle,"Lvl2="+ (string)Lvl2);
   FileWrite(handle,"LotExponent1="+ (string)LotExponent1);
   FileWrite(handle,"LotExponent2="+ (string)LotExponent2);
   
   FileWrite(handle,"TimeExit_Start="+ (string)TimeExit_Start);
   FileWrite(handle,"TimeExit_End="+ (string)TimeExit_End);
   FileWrite(handle,"TimeExit_Minutes="+ (string)TimeExit_Minutes);
   FileWrite(handle,"LastCloseBy="+ (string)LastCloseBy);
   
   
   
   
   FileWrite(handle,"a__PeriodATR="+ (string)a__PeriodATR);
   FileWrite(handle,"a__MaPeriod="+ (string)a__MaPeriod);
   FileWrite(handle,"a__MaTypr="+ (string)a__MaTypr);
   FileWrite(handle,"a__Mult_Factor1="+ (string)a__Mult_Factor1);
   FileWrite(handle,"a__Mult_Factor2="+ (string)a__Mult_Factor2);
   
   FileWrite(handle,"ma_period="+ (string)ma_period);
   FileWrite(handle,"ma_method="+ (string)ma_method);
   FileWrite(handle,"applied_price="+ (string)applied_price);
   
   FileWrite(handle,"FilterADX_Period="+ (string)FilterADX_Period);
   FileWrite(handle,"FilterADX_Level="+ (string)FilterADX_Level);
   
   
   FileWrite(handle,"macd_FastEma="+ (string)macd_FastEma);
   FileWrite(handle,"macd_SlowEma="+ (string)macd_SlowEma);
   FileWrite(handle,"macd_SignalEma="+ (string)macd_SignalEma);
   FileWrite(handle,"shift="+ (string)shift);
   FileWrite(handle,"UseMACDforNextOrders="+ (string)UseMACDforNextOrders);
   
   FileWrite(handle,"TurnMainFilters="+ (string)TurnMainFilters);
   FileWrite(handle,"ExpandChannelLvl="+ (string)ExpandChannelLvl);
   
   FileWrite(handle,"Exit2ChannelLvl="+ (string)Exit2ChannelLvl);
   
   FileWrite(handle,"TrailStartAfter="+ (string)TrailStartAfter);
   FileWrite(handle,"TrailStart="+ (string)TrailStart);
   FileWrite(handle,"TrailStop="+ (string)TrailStop);
   
   FileWrite(handle,"UseTradeTime_1Order="+ (string)UseTradeTime_1Order);
   FileWrite(handle,"StartHour="+ (string)StartHour);
   FileWrite(handle,"EndHour="+ (string)EndHour);
   FileWrite(handle,"MONDAY_Enabled="+ (string)MONDAY_Enabled);
   FileWrite(handle,"TUESDAY_Enabled="+ (string)TUESDAY_Enabled);
   FileWrite(handle,"WEDNESDAY_Enabled="+ (string)WEDNESDAY_Enabled);
   FileWrite(handle,"THURSDAY_Enabled="+ (string)THURSDAY_Enabled);
   FileWrite(handle,"FRIDAY_Enabled="+ (string)FRIDAY_Enabled);


   FileClose(handle);
   return;
}
