//+------------------------------------------------------------------+
//|                                                     BOLINGER.mq4 |
//|                        Copyright 2022, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
input double RiskPercent   = 1;
extern int Kf              = 1;     // Соотнош. приб. к убытку
input double bbotcl        = 2.0;
input int    bbperiod      = 20;
input int    MAPeriod      = 240;
input int    MAGICMA       = 123;
//+------------------------------------------------------------------+
//| Расчет риска в % от величины SL                                  |
//+------------------------------------------------------------------+
   double CalculateLot(double _stop) {
   double loss = _stop / MarketInfo(_Symbol, MODE_TICKSIZE) * MarketInfo(_Symbol, MODE_TICKVALUE);  
   double lots = AccountFreeMargin() * RiskPercent / 100 / loss;
   return (NormalizeDouble(MathMin(MarketInfo(_Symbol, MODE_MAXLOT), MathMax(MarketInfo(_Symbol, MODE_MINLOT), lots)), 2));
}
//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
  {
   int buys=0,sells=0;
//---
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
        {
         if(OrderType()==OP_BUY)  buys++;
         if(OrderType()==OP_SELL) sells++;
        }
     }
//--- return orders volume
   if(buys>0) return(buys);
   else       return(-sells);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void CheckForOpen()
  {
   int    res;
   double bbup=iBands(Symbol(),0,bbperiod,bbotcl,0,PRICE_CLOSE,MODE_UPPER,1);
   double bbMain=iBands(Symbol(),0,bbperiod,bbotcl,0,PRICE_CLOSE,MODE_MAIN,1);
   double bblow=iBands(Symbol(),0,bbperiod,bbotcl,0,PRICE_CLOSE,MODE_LOWER,1); 
   double ma=iMA(NULL,0,MAPeriod,0,MODE_SMMA,PRICE_CLOSE,1);
   double Lo = NormalizeDouble(iLow(_Symbol, _Period, 1), Digits);
   double H = NormalizeDouble(iHigh(_Symbol, _Period, 1), Digits);
   double Lo_2 = NormalizeDouble(iLow(_Symbol, _Period, 2), Digits);
   double H_2 = NormalizeDouble(iHigh(_Symbol, _Period, 2), Digits);
   double Cl = NormalizeDouble(iClose(_Symbol, _Period, 1), Digits);
   double Cl_2 = NormalizeDouble(iClose(_Symbol, _Period, 2), Digits);
   double OP = NormalizeDouble(iOpen(_Symbol, _Period, 1), Digits);
   double max = High[iHighest(_Symbol, _Period,MODE_HIGH, 12,1)];
   double min = Low[iLowest(_Symbol,_Period,MODE_LOW,12,1)];
   double Sl_S = Bid + (Bid - bblow);
   double Sl_B = Ask - (bbup - Ask);
//--- sell conditions
   if(bbMain < OP && bbMain > Bid && bbMain < ma)
     {
      res=OrderSend(Symbol(),OP_SELL,CalculateLot(max - Bid),Bid,30,max,Bid - Kf*(max - Bid),"BOLINGER",MAGICMA,0,Red);
      return;
     }
//--- buy conditions
   if(bbMain > OP  && bbMain < Ask && bbMain > ma)
     {
      res=OrderSend(Symbol(),OP_BUY,CalculateLot(Ask - min),Ask,30,min,Ask + Kf*(Ask - min),"BOLINGER",MAGICMA,0,Blue);
      return;
     }
//---
  }

//+------------------------------------------------------------------+
//| OnTick function                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- check for history and trading
   if(Bars<100 || IsTradeAllowed()==false)
      return;
//--- calculate open orders by current symbol
   if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
//---
  }
//+------------------------------------------------------------------+
