//+------------------------------------------------------------------+
//|                                                          RGC.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#include "lib_cisnewbar.mqh"

#define magic 3904930

extern bool useHMA = true;
extern bool useTraling = true;
extern bool usePartialClose = true;
extern double Lot = 0.1;
extern int tralingInPercent = 100;
extern bool use_per_of_depo = false;
extern double per_of_depo = 2.3;
extern int maxSizeCandle = 200;

double prevPrice = -1;

CisNewBar current_chart; // экземпляр класса CisNewBar: текущий график
  
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   current_chart.SetSymbol(Symbol());
   current_chart.SetPeriod(PERIOD_CURRENT);
//---
   return(INIT_SUCCEEDED);
  }

void GetCandleParams(int candleIndex, double &open, double &close, double &high, double &low)
{
   low = iLow(Symbol(),Period(),candleIndex);
   high = iHigh(Symbol(),Period(),candleIndex);
   open = iOpen(Symbol(),Period(),candleIndex);
   close = iClose(Symbol(),Period(),candleIndex);
}

double PointValuePerLot() {    
    return(  MarketInfo(Symbol(), MODE_TICKVALUE)
           / MarketInfo(Symbol(), MODE_TICKSIZE) ); // Not Point.
}

double calcPositionSize(int type, string sym, double entry, double stop) {
   double StopLoss = (MathAbs( entry - stop ) + (MarketInfo(sym, MODE_SPREAD) * MarketInfo(sym, MODE_POINT))) / Point;
   
   double  lot_min         = MarketInfo( Symbol(), MODE_MINLOT  ); 
   double  lot_max         = MarketInfo( Symbol(), MODE_MAXLOT  ); 
   double  lot_step        = MarketInfo( Symbol(), MODE_LOTSTEP ); 
   double  lotcost         = MarketInfo( Symbol(), MODE_TICKVALUE );       
   
   double  lot             = 0.0;
   double  dollarsPerPip   = 0.0;
        
   lot = AccountBalance()*per_of_depo/100.0;
   dollarsPerPip = lot/StopLoss;
   //   if (lot_min<2) {znakov_lot=0;  if (lot_min<0.2) {znakov_lot=1;  if (lot_min<0.02) {znakov_lot=3;  if (lot_min<0.002) {znakov_lot=4; }}}}      
   lot = NormalizeDouble( dollarsPerPip/lotcost, 2 );      
        
   lot = NormalizeDouble( lot / lot_step, 0 ) * lot_step;
        
   if ( lot < lot_min ) lot = lot_min;
   if ( lot > lot_max ) lot = lot_max;
        
   if ( AccountFreeMarginCheck( Symbol(), type, lot ) < 10 || GetLastError() == 134 ) 
   { 
      Alert ( "Impossible to open position with lot = ", DoubleToStr( lot, 2 ), ". Not enough money." );
      return(-1);
   }

   return lot;   
}

void OnNewBar()
{
   // Смотрим параметры последней и предпоследней свеч. 
   // Отсчет ведется от текущей свечи
   double firstLow, firstHigh, firstOpen, firstClose;
   GetCandleParams(1, firstOpen, firstClose, firstHigh, firstLow);
   bool isFirstGreen = firstOpen < firstClose;
   
   double secondLow, secondHigh, secondOpen, secondClose;
   GetCandleParams(2, secondOpen, secondClose, secondHigh, secondLow);
   bool isSecondGreen = secondOpen < secondClose;
   
   if (isFirstGreen == isSecondGreen)
      return ;                  
   
   MqlDateTime nextDay;
   TimeToStruct(TimeCurrent(), nextDay);
   nextDay.day++;
   
   double distance = MathAbs(firstLow - firstHigh);
   if (distance > maxSizeCandle)
      return ;
   
   double HMAValue112 = iCustom(Symbol(), Period(), "HMA Color", 20, 0, 3, TRUE, 2, 1, 0);
   double HMAValue120 = iCustom(Symbol(), Period(), "HMA Color", 20, 0, 3, TRUE, 2, 3, 0);
   
   // Открываем ордер только в направлении HMA
   bool isGreenHMA = !useHMA || (MathFloor(HMAValue112) != EMPTY_VALUE && MathFloor(HMAValue120) == EMPTY_VALUE);
   bool isRedHMA = !useHMA || (MathFloor(HMAValue112) == EMPTY_VALUE && MathFloor(HMAValue120) != EMPTY_VALUE);   

   int orderNumber = -1;
   int trailingStop = MathFloor(distance / Point)* tralingInPercent / 100;   
   double spred = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) * Point;
   // Первая свеча зеленая, вторая красная - играем на повышение
   if (isFirstGreen && !isSecondGreen)  
   {     
      if (isGreenHMA)
      {
         double Lots = use_per_of_depo ? calcPositionSize(OP_BUY, Symbol(), firstHigh, firstLow) : Lot;
         orderNumber = OrderSend(Symbol(), OP_BUYSTOP, Lots, firstHigh + spred, 3, /*firstHigh - trailingStop * Point*/firstLow - spred, 0, NULL, magic, StructToTime(nextDay));
      }
   }
   // В противном случае играем на понижение
   else
   {
      if (isRedHMA)
      {
         double Lots = use_per_of_depo ? calcPositionSize(OP_SELL, Symbol(), firstHigh, firstLow) : Lot;
         orderNumber = OrderSend(Symbol(), OP_SELLSTOP, Lots, firstLow - spred, 3, /*firstLow + trailingStop * Point*/firstHigh + spred, 0, NULL, magic, StructToTime(nextDay));
      }
   }      
}
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if (prevPrice > 0 && useTraling)
   {      
      for (int i=0;i<OrdersTotal();i++)
      {
         if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) break;
         if (OrderMagicNumber()!=magic || OrderSymbol()!=Symbol()) continue;         
         if ((Bid > prevPrice && OrderType() == OP_BUY) || (Bid < prevPrice && OrderType() == OP_SELL))
            OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() + (Bid - prevPrice), OrderTakeProfit(), OrderExpiration());
      }                          
   }
   
   if (usePartialClose)
   {
      for (int i=0;i<OrdersTotal();i++)
      {
         if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) break;
         if (OrderMagicNumber()!=magic || OrderSymbol()!=Symbol()) continue;
         if ((OrderType()==OP_BUY) || (OrderType()==OP_SELL))
         {                
           /*double x=OrderLots();
            double tp = OrderTakeProfit();
            double openPrice = OrderOpenPrice();
            int orderType = OrderType();
            OrderClose(OrderTicket(),OrderLots(),Ask,3);        
            OrderSend(Symbol(), orderType, NormalizeDouble(x/2.0, 2), Bid, 10, openPrice, tp, NULL, magic);     */  
            double distance = MathAbs(OrderOpenPrice() - OrderStopLoss()) / 2.0;
            if (((OrderType() == OP_BUY  && Bid >= (OrderOpenPrice() + distance)) || 
                (OrderType() == OP_SELL && Bid <= (OrderOpenPrice() - distance))))
            {
               double x=OrderLots();
               double tp = OrderTakeProfit();
               double openPrice = OrderOpenPrice();
               int orderType = OrderType();
               OrderClose(OrderTicket(),OrderLots(),Ask,3);     
               if (MarketInfo(Symbol(), MODE_MINLOT) < x/2.0)   
                  OrderSend(Symbol(), orderType, NormalizeDouble(x/2.0, 2), Bid, 10, openPrice, tp, NULL, magic);
            }
         }
      }
   }   
   
   prevPrice = Bid;   
   
   if (TimeDayOfWeek(TimeCurrent()) == 5)
      return ;
   
//---
   if(current_chart.isNewBar()>0)
   {        
      OnNewBar();
   }
}  