//+------------------------------------------------------------------+
//|                                                                  |
//|       Ñîâåòíèê íà ðàçâîðîò ïî                                    |
//|       êîìáèíàöèè ñâå÷åé                                          |
//|                             http://www.mql4.com/ru/users/ikatsko |
//+------------------------------------------------------------------+
#property copyright "Ivan Katsko"
#property link      "ICQ:372739628"
#include <stdlib.mqh>
//----
extern double Lots         = 0.1;       // Æåñòêî çàäàííîå êîëè÷. ëîòîâ ("0" - ñîâåòíèê âûáèðàåò ñàì)
extern double MaxRisk      = 3;         // Ìàêñèìàëüíûé Loss â ðàçàõ  ê ñâîáîäíûì ñðåäñòâàì
extern int History         = 125;       // Êîëè÷.áàðîâ â ðàñ÷¸òíîé èñòîðèè
extern int MaPerBegin      = 4;
extern int MaPerEnd        = 22;
extern int StDvErr         = 5;
//extern int AveragingPeriod = 3;
extern int Variant         = 1;         // 1 ðàáîåì â òðåíäå, 2 ðàáîòàåì âî ôëåòå, 0 ðàáîòàåì â îáåèõ ñëó÷àÿõ
extern int Wait            = 1;         // Çàäåðæêà (â ïåðèîäàõ) ïðè èçìåíåíèè íàïðàâëåíèÿ
extern double MarginCutoff = 300;       // Expert will stop trading if equity level decreases to that level.
extern int    Slippage     = 4;         // Possible fix for not getting closed Could be higher with some brokers    
//----
int    MagicNumber;                     // Magic EA identifier. Allows for several co-existing EA with different input values
int    attempt             = 5;         //Ïîïûòîê íà îòêðûòèå/çàêðûòèå îðäåðîâ
string ExpertName;                      // To "easy read" which EA place an specific order and remember me forever :)
string news_wav            = "news.wav";
double lotMM, balans, old_balans, loss,price_buy, price_sell, time_buy, time_sell;
double direction           = 0,         // Íàïðàâëåíèå òåêóùåå : ">0" - êóïèòü; "<0" - ïðîäàòü
       old_direction       = 0;         // Íàïðàâëåíèå ïðåäûäóùåå: ">0" - êóïèòü; "<0" - ïðîäàòü
double stimul;
double spread;
bool Trand, Flat;
bool   MoneyManagement;                 // Change to false to shutdown money management controls.
bool   sound_yes           = TRUE;      //Ðàçðåøèòü çâóêè
bool   is_loss             = false;
static int prevtime        = 0;
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start() {
 
   if (Time[0] == prevtime) {
      return(0);
   }
   prevtime = Time[0];
   if(IsTradeAllowed()) {
      RefreshRates();
      spread = (Ask - Bid) / Point;
   } else {
      again();
      return(0);
   }
   int OpPzBUY = openPositionsBUY(false);        // Îòêðûòûõ îðäåðîâ áåç îòëîæåííûõ
   int OpPzSELL = openPositionsSELL(false);
   int period    = GetPeriod(History,MaPerBegin,MaPerEnd);
   old_direction = direction;                    //îïðåäåëÿåì íàñòîÿùåå íàïðàâëåíèå
   direction     = GetDirection(period);         //îïðåäåëÿåì òåêóùåå íàïðàâëåíèå
   
   if (old_direction != direction) {
      if (OpPzBUY > 0) 
         if (price_buy+spread*Point < Open[0] || (Time[0]-time_buy)/60 >= Wait*Period())
            CloseAllPos(OP_BUY);
      if (OpPzSELL > 0) 
         if (price_sell-spread*Point > Open[0] || (Time[0]-time_sell)/60 >= Wait*Period())
            CloseAllPos(OP_SELL);
   } else {
      if (direction > 0 && OpPzSELL > 0)  
         if ((Time[0]-time_sell)/60 >= Wait*Period())
            CloseAllPos(OP_SELL);
      if (direction < 0 && OpPzBUY > 0)  
         if ((Time[0]-time_buy)/60 >= Wait*Period())
            CloseAllPos(OP_BUY);
      return(0);
   }
   if (direction > 0 && OpPzBUY == 0) {
      if(AccountFreeMargin() < MarginCutoff) {
         Print("Not enough money for buy to trade Strategy:", ExpertName);
         return(0);
      }
      lotMM=GetLots();
      OpenBuy();
   }
   if (direction < 0 && OpPzSELL == 0) {
      if(AccountFreeMargin() < MarginCutoff) {
         Print("Not enough money for sell to trade Strategy:", ExpertName);
         return(0);
      }
      lotMM=GetLots();
      OpenSell();
   }
   return(0);
}
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init() {
   if (Variant < 0) Variant = 0;
   if (Variant > 2) Variant = 2;
   switch (Variant) {
      case 0: Trand = true;  Flat = true;  break;
      case 1: Trand = true;  Flat = false; break;
      case 2: Trand = false; Flat = true;  break;
   }
   prevtime = Time[0];
   old_balans = AccountBalance();
   MagicNumber=3000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period());
   ExpertName="iK_StDv: " + MagicNumber + " : " + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period()));
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit() {
   return(0);
}
//+------------------------------------------------------------------+
//| OpenBuy                                                          |
//+------------------------------------------------------------------+
int OpenBuy() {
   int err, ticket;
   double myPrice = NormalizeDouble(Ask,Digits);
   if (Close[1] > Open[1]) 
      double myStopLoss = NormalizeDouble(myPrice - ((Open[1]-Low[1])+0.23*(High[1]-Low[1])),Digits);
   else myStopLoss = NormalizeDouble(myPrice - ((Close[1]-Low[1])+0.23*(High[1]-Low[1])),Digits);
   
   ticket=OrderSend(Symbol(),OP_BUY,lotMM,myPrice,Slippage,0,0,ExpertName, MagicNumber);
   if(ticket<=0) {
      err=GetLastError();
      return(0);
   }
   return(1);
}
//+------------------------------------------------------------------+
//| OpenSell                                                         |
//+------------------------------------------------------------------+
int OpenSell() {
   int err, ticket;
   
   double myPrice = NormalizeDouble(Bid,Digits);         
   if (Close[1] > Open[1]) 
      double myStopLoss = NormalizeDouble(myPrice + ((High[1]-Close[1])+0.23*(High[1]-Low[1])),Digits);
   else myStopLoss = NormalizeDouble(myPrice + ((High[1]-Open[1])+0.23*(High[1]-Low[1])),Digits);
   
   ticket=OrderSend(Symbol(),OP_SELL,lotMM,myPrice,Slippage,0,0,ExpertName, MagicNumber);
   if(ticket<=0) {
      err=GetLastError();
      return(0);
   }
   return(1);
}
//+------------------------------------------------------------------------+
//| counts the number of open positions BUY                                    |
//+------------------------------------------------------------------------+
int openPositionsBUY(bool limit = true) {  
   int op =0;
   for(int i=OrdersTotal()-1;i>=0;i--) {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderSymbol()==Symbol()) {
         if(OrderType()==OP_BUY) {
            op++;
            price_buy = OrderOpenPrice();
            time_buy = OrderOpenTime();
         }
         if(limit && OrderType()==OP_BUYLIMIT)op++;
      }
   }
   return(op);
}
//+------------------------------------------------------------------------+
//| counts the number of open positions SELL                                   |
//+------------------------------------------------------------------------+
int openPositionsSELL(bool limit = true) {  
   int op =0;
   for(int i=OrdersTotal()-1;i>=0;i--) {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderSymbol()==Symbol())  {
         if(OrderType()==OP_SELL) {
            op++;
            price_sell = OrderOpenPrice();
            time_sell = OrderOpenTime();
         }
         if(limit && OrderType()==OP_SELLLIMIT)op++;
      }
   }
   return(op);
}
//+------------------------------------------------------------------+
//| Get number of lots for this trade                                |
//+------------------------------------------------------------------+
double GetLots() {
   double lot,
      Min_Lot=MarketInfo(Symbol(),MODE_MINLOT),        // Ìèíèì. êîëè÷. ëîòîâ 
      Max_Lot=MarketInfo(Symbol(),MODE_MAXLOT),        // Ìèíèì. êîëè÷. ëîòîâ 
      Free   =AccountFreeMargin(),                     // Ñâîáîäí ñðåäñòâà
      One_Lot=MarketInfo(Symbol(),MODE_MARGINREQUIRED),// Ñòîèìîñòü 1 ëîòà
      Step   =MarketInfo(Symbol(),MODE_LOTSTEP);       // Øàã èçìåíåí ðàçìåðà
      lot = Lots;
      loss = GetProfitLastClosePos();
      if (loss < 0) lot=MaxRisk*lot;
      if (lot > Max_Lot) {
         lot = Max_Lot;
         Comment("ËÎÒ îãðàíè÷åí ìàêñèìóìîì è ðàâåí ",MathCeil(lot/Step)*Step);
      }
      if (lot*One_Lot > Free) {
         lot = Free/One_Lot;
         Comment("ËÎÒ îãðàíè÷åí ñâîáîäíûìè ñðåäñòâàìè è ðàâåí ",MathCeil(lot/Step)*Step);
      }
      if (lot < Min_Lot) {
         lot=Min_Lot;               // Íå ìåíüøå ìèíèìàëüí
         Comment("ËÎÒ îãðàíè÷åí ìèíèìóìîì è ðàâåí ",MathCeil(lot/Step)*Step);
      }
   RefreshRates();                                 // Îáíîâëåíèå äàííûõ
   Step = MarketInfo(Symbol(),MODE_LOTSTEP);       // Øàã èçìåíåí ðàçìåðà
   lot = MathCeil(lot/Step)*Step;
   return(lot);
}
//+------------------------------------------------------------------+
int GetProfitLastClosePos(string sy="", int mn=-1) {
  datetime t;
  int      i, k=OrdersHistoryTotal(), r=0;
  
  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) {
      if ((OrderSymbol()==sy || sy=="") && (mn<0 || OrderMagicNumber()==mn)) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (t<OrderCloseTime()) {
            t=OrderCloseTime();
            r=OrderProfit();
          }
        }
      }
    }
  }
  return(r);
}
//+------------------------------------------------------------------+
//| Time frame interval appropriation  function                      |
//+------------------------------------------------------------------+
int func_TimeFrame_Const2Val(int Constant) {
     switch(Constant) {
         case     1: return(1);
         case     5: return(2);
         case    15: return(3);
         case    30: return(4);
         case    60: return(5);
         case   240: return(6);
         case  1440: return(7);
         case 10080: return(8);
         case 43200: return(9);
     }
}
//+------------------------------------------------------------------+
//| Time frame string appropriation  function                        |
//+------------------------------------------------------------------+
string func_TimeFrame_Val2String(int Value) {
    switch(Value) {
        case 1: return("PERIOD_M1");
        case 2: return("PERIOD_M5");
        case 3: return("PERIOD_M15");
        case 4: return("PERIOD_M30");
        case 5: return("PERIOD_H1");
        case 6: return("PERIOD_H4");
        case 7: return("PERIOD_D1");
        case 8: return("PERIOD_W1");
        case 9: return("PERIOD_MN1");
        default: return("undefined " + Value);
    }
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int func_Symbol2Val(string symbol)  {
     if(symbol=="AUDCAD")  {
        return(1);
     } else if(symbol=="AUDJPY") {
        return(2);
     } else if(symbol=="AUDNZD") {
        return(3);
     } else if(symbol=="AUDUSD") {
        return(4);
     } else if(symbol=="CHFJPY") {
        return(5);
     } else if(symbol=="EURAUD") {
        return(6);
     } else if(symbol=="EURCAD") {
        return(7);
     } else if(symbol=="EURCHF") {
        return(8);
     } else if(symbol=="EURGBP") {
        return(9);
     } else if(symbol=="EURJPY") {
        return(10);
     } else if(symbol=="EURUSD") {
        return(11);
     } else if(symbol=="GBPCHF") {
        return(12);
     } else if(symbol=="GBPJPY") {
        return(13);
     } else if(symbol=="GBPUSD") {
        return(14);
     } else if(symbol=="NZDUSD") {
        return(15);
     } else if(symbol=="USDCAD") {
        return(16);
     } else if(symbol=="USDCHF") {
        return(17);
     } else if(symbol=="USDJPY") {
        return(18);
     } else {
        Comment("unexpected Symbol");
        return(0);
     }
}
void CloseAllPos(int typ=2) {
   int l_ord_total_22 = OrdersTotal();
   int l_ord_total_24 = l_ord_total_22;
   for (int l_pos_18 = l_ord_total_22 - 1; l_pos_18 >= 0; l_pos_18--) {
      if (OrderSelect(l_pos_18, SELECT_BY_POS, MODE_TRADES)) {
         ClosePosBySelect(typ);
         l_ord_total_24--;
      }
   }
   if (l_ord_total_24 == 0) return;
} 
void ClosePosBySelect(int typ) {
   bool l_ord_close_0;
   //color l_color_4;
   double l_ord_lots_8;
   double ld_16;
   double ld_24;
   double l_price_32;
   int l_error_40;
   if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
      for (int li_44 = 1; li_44 <= attempt; li_44++) {
         if (!IsTesting() && !IsExpertEnabled() || IsStopped()) break;
         while (!IsTradeAllowed()) Sleep(5000);
         RefreshRates();
         ld_16 = NormalizeDouble(MarketInfo(OrderSymbol(), MODE_ASK), Digits);
         ld_24 = NormalizeDouble(MarketInfo(OrderSymbol(), MODE_BID), Digits);
         if (OrderType() == OP_BUY) {
            l_price_32 = ld_24;
         } else {
            l_price_32 = ld_16;
         }
         l_ord_lots_8 = OrderLots();
         
         if (typ == 2) l_ord_close_0 = OrderClose(OrderTicket(), l_ord_lots_8, l_price_32, Slippage);
         else if (typ == OrderType()) l_ord_close_0 = OrderClose(OrderTicket(), l_ord_lots_8, l_price_32, Slippage);
         
         if (l_ord_close_0) {
            if (!(sound_yes)) break;
            PlaySound(news_wav);
            return;
         }
         l_error_40 = GetLastError();
         if (l_error_40 == 146/* TRADE_CONTEXT_BUSY */) while (IsTradeContextBusy()) Sleep(11000);
         Print("Error(", l_error_40, ") Close ", OrderType(), " ", ErrorDescription(l_error_40), ", try ", li_44);
         Sleep(5000);
      }
   } else Print("Íåêîððåêòíàÿ òîðãîâàÿ îïåðàöèÿ. Close ", OrderType());
}
//+------------------------------------------------------------------+
void again() {
   prevtime = Time[1];
   Sleep(30000);
}
//-------------------------------------------------------------------+
int GetPeriod(int History=140, int MaPerBegin=4, int MaPerEnd=24) {
   double max = 0.0;
   for (int period = MaPerBegin; period <= MaPerEnd; period++) {
      double ok_p = 0.01;
      double ok_m = 0.02;
      for (int i=History; i>=0; i--) {
         bool white_0 = false;
         bool black_0 = false;
         bool white_1 = false;
         bool black_1 = false;
         if (Close[i]  >Open[i])   white_0 = true;
         if (Close[i]  <Open[i])   black_0 = true;
         if (Close[i+1]>Open[i+1]) white_1 = true;
         if (Close[i+1]<Open[i+1]) black_1 = true;
         bool flat = true;
//         if (AveragingPeriod == 0) {
            if (iStdDev(NULL,0,period,0,0,1,i) > iStdDev(NULL,0,period,0,0,1,i+1)) flat = false;
//         } else {
//            if (iCustom(NULL,0,"_StdDev",period,AveragingPeriod,0,i) > iCustom(NULL,0,"_StdDev",period,AveragingPeriod,0,i+1)) flat = false;
//         }
         switch (Variant) {
            case 1:
               if (!flat) {
                  if ((white_0 && white_1) || (black_0 && black_1)) {
                       ok_p = ok_p + 1;
                  } else {
                       ok_m = ok_m + 1;
                  }
               }
               break;
            case 2:
               if (flat) {
                  if ((white_0 && black_1) || (black_0 && white_1)) {
                       ok_p = ok_p + 1;
                  } else {
                       ok_m = ok_m + 1; 
                  }
               }
               break;
            default:
               if (((flat  && ((white_0 && black_1) || (black_0 && white_1)))) ||
                   ((!flat && ((white_0 && white_1) || (black_0 && black_1))))) {
                    ok_p = ok_p + 1;
               } else ok_m = ok_m + 1;
               break;
         }
      }
      if (ok_p/ok_m > max) {
         max = ok_p/ok_m;
         if (max > 1) int per = period;
         else per = 0;
      }
   }
   Comment("History=",History," period=",per," max=",max);
   return(per);
}
//------------------------------------------------------------------+
double GetDirection(int prd) {
   if (prd == 0) return(0);
//   if (AveragingPeriod == 0) {
      double sd0 = iStdDev(NULL,0,prd,0,0,1,0);
      double sd1 = iStdDev(NULL,0,prd,0,0,1,1);
      double stdv = sd0 - sd1;
      if (MathAbs(stdv) <= 0.01*StDvErr*sd0)
         stdv = 0;
//   } else
//      stdv = iCustom(NULL,0,"_StdDev",prd,AveragingPeriod,0,0) - iCustom(NULL,0,"_StdDev",prd,AveragingPeriod,0,1);
   switch (Variant) {
      case  1:
         if (stdv > 0) {
            if (iClose(0,0,1) > iOpen(0,0,1))
               return(1);
            if (iClose(0,0,1) < iOpen(0,0,1))
               return(-1);
         } else return(0);
      case  2:
         if (stdv < 0) {
            if (iClose(0,0,1) > iOpen(0,0,1))
               return(-1);
            if (iClose(0,0,1) < iOpen(0,0,1))
               return(1);
         } else return(0);
      default:
         if (stdv > 0) {
            if (iClose(0,0,1) > iOpen(0,0,1))
               return(1);
            if (iClose(0,0,1) < iOpen(0,0,1))
               return(-1);
         }
         if (stdv < 0) {
            if (iClose(0,0,1) > iOpen(0,0,1))
               return(-1);
            if (iClose(0,0,1) < iOpen(0,0,1))
               return(1);
         }
         if (stdv == 0) {
            return(0);
         }
   }
}
             
            
            
            
Comments