#property copyright "master_255"
//#property strict

extern int    MagicNumber = 9999;
extern double slip = 3.0;
extern double Lots = 0.01;
extern int    DepoPer001Lot = 0;
extern string _2 = "Настройки";
input  int    BodyShadowPercent = 100;
extern int    MaxCandlePips = 1500;
extern int    DistancePoint = 200;
input  bool   BreakEvenNextDay = True;
extern int    TrailStart = 300;
extern int    TrailStop = 200;
extern int    TrailStep = 100;
//---------------------------
double minLot, maxLot, Min_Dist;
string EAName="Test imperia";
datetime timeprev = 0, TimeLastTrail=0;
bool RealTrade=false; 
//+------------------------------------------------------------------+
int OnInit() {
   minLot  = MarketInfo(Symbol(), MODE_MINLOT);
   maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);
   Min_Dist= MarketInfo(Symbol(), MODE_STOPLEVEL);

   if (_Digits == 2 || _Digits == 4){
        DistancePoint /= 10;
        TrailStart /= 10;
        TrailStop /= 10;
        TrailStep /= 10;
        MaxCandlePips /= 10;
        slip /= 10; if(slip<1) slip=1;
        //Print("Correction 4 digits: TakeProfit:"+TakeProfit+" StopLoss:"+StopLoss+" TrailStart:"+TrailStart+" TrailStop:"+TrailStop+" slp:"+slip);
   }

   if(!IsTesting() && !IsOptimization()) RealTrade=true;
   
   return (INIT_SUCCEEDED);
}
//нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
void OnTick(){
   int i;
   //Трейлинг раз в минуту
   if(TrailStop>0){
      if(TimeLastTrail+30 < TimeCurrent()){
         TrailingStandart(MagicNumber, TrailStop);
         TimeLastTrail=TimeCurrent();
      }
   }
   
   //Закрываем сделки в пятницу
   if(TimeDayOfWeek(TimeCurrent())==5 && TimeHour(TimeCurrent())>=22){
      for(i=OrdersTotal()-1;i>=0;i--){
         if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==false) continue;
         if (OrderSymbol() != _Symbol || OrderMagicNumber() != MagicNumber) continue;
         if(OrderType()>1) if(!OrderDelete(OrderTicket())) Print("Ошибка удаления ордера: ", GetLastError());
         if(OrderType()==OP_BUY) OrderCloseX(OrderTicket(), OrderLots(), OP_BUY, slip);
         if(OrderType()==OP_SELL) OrderCloseX(OrderTicket(), OrderLots(), OP_SELL, slip);
      }
   }

   if (timeprev == Time[0]) return;
   timeprev = Time[0];
   
   //Есть сработавшие отложки, переведем в бу
   if(BreakEvenNextDay){
      int Spr=MarketInfo(Symbol(), MODE_SPREAD);
      for(i=OrdersTotal()-1;i>=0;i--){
         if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==false) continue;
         if (OrderSymbol() != _Symbol || OrderMagicNumber() != MagicNumber) continue;
         if(OrderType()==OP_BUY && Bid>=OrderOpenPrice()+(Min_Dist+Spr)*_Point)
            OrderModifyX(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+Spr*_Point,0,0,clrDarkOrange);
         if(OrderType()==OP_SELL && Ask<=OrderOpenPrice()-(Min_Dist+Spr)*_Point)
            OrderModifyX(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-Spr*_Point,0,0,clrDarkOrange);
      }
   }
   //Открытие свечи во вторник
   if(TimeDayOfWeek(TimeCurrent())!=2) return;  

   //динамический лот
   if(DepoPer001Lot>0){
      Lots = NormalizeDouble((AccountFreeMargin()/DepoPer001Lot)/100,2);
      if(Lots<minLot) Lots = minLot; 
   }
   
   //сигнал
   double body,upShadow,downShadow;
   if(Open[1] > Close[1]){ 
      body = Open[1]-Close[1];
      upShadow = High[1]-Open[1];
      downShadow = Close[1]-Low[1];
   }else{
      body = Close[1]-Open[1];
      upShadow = High[1]-Close[1];
      downShadow = Open[1]-Low[1];
   }
   
   //слишком большая свеча
   if((High[1]-Low[1])/_Point > MaxCandlePips){
      DrawWarn("Слишком большая свеча");
      return;
   }
   
   //слишком длинные тени
   if(upShadow>=(body*BodyShadowPercent/100) || downShadow>=(body*BodyShadowPercent/100)){
      DrawWarn("Тень больше "+BodyShadowPercent+"% тела");
      return;
   }

   double boprice = High[1]+DistancePoint*_Point;
   double soprice = Low[1]-DistancePoint*_Point;
   if(!OrderSend(_Symbol, OP_BUYSTOP, Lots, boprice, slip, soprice, 0, EAName, MagicNumber, TimeCurrent()+PERIOD_W1*60, Blue))
      Print("Ошибка открытия ордера: ", GetLastError());
   if(!OrderSend(_Symbol, OP_SELLSTOP, Lots, soprice, slip, boprice, 0, EAName, MagicNumber, TimeCurrent()+PERIOD_W1*60, HotPink))
      Print("Ошибка открытия ордера: ", GetLastError());
}

//нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн

void OrderCloseX(int ticket1, double lots, int otype, int slp, color clr=CLR_NONE){
    int err = 0; double price = 0;
    bool exit_loop = false;

    int retry = 10;
    int cnt1   = 0;
    
    while(!exit_loop && cnt1<retry){
        if(otype == OP_BUY)  price=Bid;
        if(otype == OP_SELL) price=Ask;
        if(!OrderClose(ticket1, lots, 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
           exit_loop = true;
   }
      
   if(err != ERR_NO_ERROR && err != ERR_NO_RESULT) Print ("Ошибка закрытия ордера #" + IntegerToString(ticket1) + " Код ошибки: " + IntegerToString(err));
}
//+------------------------------------------------------------------+
double ND(double ad_0) {
   return (NormalizeDouble(ad_0, _Digits));
}


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;
    
    while(!exit_loop && cnt1<retry){
        if(!OrderModify(ticket1, price, stoploss, takeprofit, expiration, arrow_color)){
           err = GetLastError();
           switch(err){
             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
           exit_loop = true;
   }
      
   if(err != ERR_NO_ERROR && err != ERR_NO_RESULT) Print ("Ошибка модификации ордера #" + IntegerToString(ticket1) + " Код ошибки: " + IntegerToString(err));
}


void TrailingStandart(int CurrentMagic, int trldistance){ 
   double nextsl,sl,tp;
   int trlstart=TrailStart;
  
   Min_Dist=MarketInfo(Symbol(),MODE_STOPLEVEL);
   if(trldistance<Min_Dist){
      //Print("StopLevel: "+Min_Dist+" < stop: "+stop);
      trlstart+=Min_Dist-trldistance;
      trldistance=Min_Dist;
   }
   
   int total=OrdersTotal();
   for(int pos=0;pos<total;pos++) {
      if (OrderSelect(pos, SELECT_BY_POS, MODE_TRADES)==false) continue;
      if (OrderSymbol() != Symbol() || OrderMagicNumber() != CurrentMagic) continue;

      sl=ND(OrderStopLoss());
      if(sl>0) trldistance+=TrailStep;
      if (OrderType()==OP_BUY){
         if(Bid>OrderOpenPrice()+ND(trlstart*_Point)){
            nextsl = ND(Bid - trldistance*_Point);
            tp = ND(OrderTakeProfit());
            if(nextsl>=tp) tp=0;
            if(nextsl>sl || sl==0){
               OrderModifyX(OrderTicket(),OrderOpenPrice(),nextsl,tp,0,clrDarkOrange);
            }
         }
      }
      
      if (OrderType()==OP_SELL){ 
         if(Ask<OrderOpenPrice()-ND(trlstart*_Point)){
            nextsl = ND(Ask + trldistance*_Point);
            tp = ND(OrderTakeProfit());
            if(nextsl<=tp) tp=0;
            if((nextsl<sl || sl==0)){
               OrderModifyX(OrderTicket(),OrderOpenPrice(),nextsl,tp,0,clrDarkOrange);
            }
         }
      }   
   }    
}

//--------
void DrawWarn(string text){
   string obid=_Symbol+TimeToStr(Time[1]);
   if(ObjectFind(obid)!=-1) ObjectDelete(obid);
   
   ENUM_ANCHOR_POINT anc;
   double price;

   if((WindowPriceMax()+WindowPriceMin())/2 < Bid){
      price=Low[1];
      anc=ANCHOR_RIGHT;
   }else{
      price=High[1];
      anc=ANCHOR_LEFT;
   }
   
   ObjectCreate(obid, OBJ_TEXT, 0, Time[1], price);
   ObjectSet(obid, OBJPROP_ANGLE, 90);
   ObjectSet(obid,OBJPROP_ANCHOR,anc);
   ObjectSet(obid,OBJPROP_BACK,false);
   ObjectSetText(obid,text,10,"Arial",clrPlum);
}