← К каталогу
Исходный код · ID 3528

unlockernew.mq4

Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Данный продукт представляет собой торговый советник для MetaTrader 4, реализующий механизм локирования и разблокирования торговых позиций. Советник использует индикатор SAR (Stop and Reverse) и EMA с периодом 200 для формирования торговых сигналов и управления ордерами.

Класс CLock обеспечивает работу с частичными локами, накопление прибыли в «копилку» и закрытие позиций при достижении заданного процента профита. Класс CUnlocker управляет основной логикой разблокирования: стабилизацией позиций, выставлением отложек, сопровождением ордеров поддержки, трейлингом и разрезанием убыточных лотов за счёт накопленной прибыли.

Советник работает с торговыми событиями MetaTrader 4, использует торговые операции через OrderSend, OrderClose и OrderModify. Параметры сохраняются глобально через pglobal.LoadParam и pglobal.SaveParam, что позволяет сохранять состояние между перезапусками советника.

Получить полный код

Поиск по коду файла

#ifndef __SOVETNIKOV_UNLOCKER_2sdfhgsd
#define __SOVETNIKOV_UNLOCKER_2sdfhgsd

#include <sovetnikovNET\Orders.mqh>

class CLock: public COrders
  {
public:
   datetime          tmKopilka;
   ENUM_TIMEFRAMES   eSupportTF;
   bool              bSupport;
   double            dLockMultiplicator; //Lock lot multiplicator / Множитель лота для лок
   double            dKopilkaProcent; //Profit % for moneybox / Процент профита в копилку
   double            dTPinProcent; //All profit % at balance / Закрытие в профит всех ордеров
   long              iLockMagic; //Lock magic and rezerved: Magic+1 / Идентификатор ордеров лок

   CNewBar           m_barSupport;

   int               hsar;

   virtual bool      OnInitIndicators()
     {
      m_barSupport.OnInit(m_name,eSupportTF);

#ifdef __MQL5__
      hsar=iSAR(m_name,eSupportTF,0.002,0.2);
#endif

      return true;
     }

   virtual bool      OnDeinitIndicators()
     {
#ifdef __MQL5__     
      IndicatorRelease(hsar);
#endif    
      return true;
     }

   bool              CloseByProfitInProcent()
     {
      double dprofit=ND2(AccountBalance()*dTPinProcent/100);
      datetime tmLock=(datetime)pglobal.LoadParam("Kopilka_Time",0);
      double dSummProfit=getProfit(ALL);

      if(tmLock>0)
         dSummProfit+=getProfit(ALL,MODE_HISTORY,tmLock);

      if(dSummProfit>0 && dSummProfit>=dprofit)
        {

         OrderCloseAll(ALL);
         return true;
        }

      return false;

     }

   void              Run()
     {
      string _sExpertName=WindowExpertName();

      double dprofit=ND2(AccountBalance()*dTPinProcent/100);

      double dsar[2];

#ifdef __MQL5__
      dsar[0]=iCustom(hsar,0,0);
      dsar[1]=iCustom(hsar,0,1);

#else
      dsar[0]=iSAR(m_name,eSupportTF,0.002,0.2,0);
      dsar[1]=iSAR(m_name,eSupportTF,0.002,0.2,1);

#endif
      m_barSupport.Refresh();
      double dLots[2];

      if(CloseByProfitInProcent())
         return;

      this.OnTick();

      int idirect=0;
      double dAvg=get_Average(ALL,idirect);

      ENUM_ORDER_TYPE iTradeMode=-1;

      if(idirect<0)
         iTradeMode=OP_SELL;
      if(idirect>0)
         iTradeMode=OP_BUY;

      if(dAvg>0) m_drawvirtual.DrawHLine(0,"bu",0,iTime(m_name,PERIOD_CURRENT,1),dAvg,1,STYLE_SOLID,clrGreen,false,false,"BU");
      else m_drawvirtual.Delete(0,"bu");

      string sType=TypeToString(iTradeMode);

      if(Kopilka(iTradeMode))
         return;

      double ddeltaLot=Abs(get_lots(dLots));   

      double dSummLot=0;
      double dLastPrice=0,dPrice=0; //цена от которой идет рассчет для установки следующего лока
      datetime tmFirst=0,tmLast=0;

      if(iTradeMode==OP_BUY)
        {

         if(dsar[0]>iHigh(m_name,eSupportTF,0) && m_barSupport.isNewBar())
           {

            ulong t=OrderSend(OP_SELL,NLot(ddeltaLot+dLots[0]*dLockMultiplicator),-1,0,0,NULL);
            DEBUG_OrderSend3(t);

            if(t>0)
               SetAll(OP_SELL,0,0,true);

           }
           /*else if(dsar[0]<iLow(m_name,eSupportTF,0) && m_barSupport.isNewBar())
           {

            ulong t=OrderSend(OP_SELL,NLot(ddeltaLot),-1,0,dLockTP,NULL);
            DEBUG_OrderSend3(t);

            if(t>0)
               SetAll(OP_SELL,0,0,true);

           }*/

        }

      if(iTradeMode==OP_SELL)
        {

         if(dsar[0]<iLow(m_name,eSupportTF,0) && m_barSupport.isNewBar())
           {
            ulong t=OrderSend(OP_BUY,NLot(ddeltaLot+dLots[1]*dLockMultiplicator),-1,0,0,NULL);
            DEBUG_OrderSend3(t);

            if(t>0)
               SetAll(OP_BUY,0,0,true);
           }

           /*else
           if(dsar[0]>iHigh(m_name,eSupportTF,0) && m_barSupport.isNewBar())
           {

            ulong t=OrderSend(OP_BUY,NLot(ddeltaLot),-1,0,dLockTP,NULL);
            DEBUG_OrderSend3(t);

            if(t>0)
               SetAll(OP_BUY,0,0,true);

           }*/
        }

     }

   virtual bool      Check(string symbol,long imagic)
     {

      if(m_name==NULL || symbol==m_name)
         return true;

      return false;
     }

   void              Reset(datetime tmNew)
     {
      if(tmNew==0.0)
        {
         tmKopilka=0;
         pglobal.DeleteParam("Kopilka_Profit"); //сбросим копилку
         pglobal.DeleteParam("Kopilka_Time"); //сбросим копилку
         m_drawvirtual.Delete(0,"bu");
        }

      tmKopilka=(datetime)pglobal.LoadParam("Kopilka_Time",0);

      if(tmNew>tmKopilka)
        {
         tmKopilka=tmNew;
         pglobal.SaveParam("Kopilka_Time",tmKopilka); //сохраним новое время для копилки
        }

     }

   virtual ulong      getLastOrderTicket(double &dSummLot,int itype,_ORDER_MODE imode=ORDER_UP,datetime dtmOpen=0)
     {
      double array_order_open[][2]; //0- price,1-ticket
      ArrayResize(array_order_open,0);

      dSummLot=0;

      int c=0;

      for(int i=PositionsTotal()-1; i>=0; i--)
        {

         if(!SelectByIndex(i,true))
            continue;

         ulong uOrderTicket=m_position.Ticket();
         int lOrderType=m_position.PositionType();
         double dOrderOpenPrice=m_position.PriceOpen();
         double dOrderLots=m_position.Volume();

         if(m_position.Time()>=dtmOpen)
           {

            if(lOrderType==POSITION_TYPE_BUY && itype==OP_BUY)
              {

               ArrayResize(array_order_open,c+1);
               array_order_open[c][0]=dOrderOpenPrice;
               array_order_open[c][1]=(double)uOrderTicket;
               dSummLot+=dOrderLots;
               c++;
              }

            if(lOrderType==POSITION_TYPE_SELL && itype==OP_SELL)
              {

               ArrayResize(array_order_open,c+1);
               array_order_open[c][0]=dOrderOpenPrice;
               array_order_open[c][1]=(double)uOrderTicket;
               dSummLot+=dOrderLots;
               c++;
              }
           }

        }

      if(itype==OP_BUY && c>0)
        {
         ArraySort(array_order_open); //сортируем в сторону увеличения, тогда 0й ордер будет самый нижний, последний сверху (первый).
         if(imode==ORDER_DN)
            return ((ulong)array_order_open[0][1]);
         if(imode==ORDER_UP)
            return ((ulong)array_order_open[c-1][1]);
        }

      if(itype==OP_SELL && c>0)
        {
         ArraySort(array_order_open); //сортируем в сторону уменьшения, тогда 0й ордер будет самый нижний, последний сверху (первый).
         if(imode==ORDER_UP)
            return ((ulong)array_order_open[c-1][1]);
         if(imode==ORDER_DN)
            return ((ulong)array_order_open[0][1]);
        }

      return 0;
     }

   bool              Kopilka(int _itype)
     {
      if(_itype==-1)
         return false;

      datetime tmTime=(datetime)pglobal.LoadParam("Kopilka_Time",0);
      /*
      нужно загрузить все данные по закрытым ордерам и обновить переменную времени, чтобы их повторо не грузить
      */

      if(tmTime==0)
        {
         ulong tfirst=getFirstOrderTicket(ALL,0);
         if(OrderSelect(tfirst,true))
            tmTime=OrderOpenTime(true);

         pglobal.SaveParam("Kopilka_Time",tmTime);
        }

      datetime tmp_tmFirst=tmTime;
      datetime _tmFirst=tmTime;

      datetime tmCurrent=TimeCurrent();
      HistorySelect(tmTime,tmCurrent); //загрузем историю закрытых ордеров

      double dProfit=0;

      for(int i=HistoryDealsTotal()-1; i>=0; i--)
        {
         if(!m_deal.SelectByIndex(i))
            continue;

         if(m_deal.Symbol()==m_name && (m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL))
           {
            double dlock_profit=m_deal.Profit()+m_deal.Swap()+m_deal.Commission();

            if(dlock_profit>0)
              {
               dlock_profit=ND2(dlock_profit*dKopilkaProcent/100);
              }

            dProfit+=dlock_profit;

            if(m_deal.Time()>tmp_tmFirst)
               tmp_tmFirst=m_deal.Time();

           }
        }

      if(dProfit>0)
        {

         double dKopilkaAdd=dProfit;

         string sType=TypeToString(_itype);

         double dKopilka=pglobal.LoadParam("Kopilka_Profit",0);
         dKopilka+=dKopilkaAdd;

         _tmFirst=tmp_tmFirst+1;

         PrintFormat("Kopilka %s add profit: %.2f Kopilka: %.2f Time: %s",sType,dKopilkaAdd,dKopilka,TimeToString(_tmFirst+1,TIME_DATE|TIME_SECONDS));

         pglobal.SaveParam("Kopilka_Profit",dKopilka);

        }

      string sType=TypeToString(_itype);
      double dKopilka=pglobal.LoadParam("Kopilka_Profit",0); //текущее значение в копилке

      if(dKopilka>0)
        {
         int iforClose=0,ifor=0;
         double dMinusForClose=0;
         double dminuslot=0;
         double dminlot=0;
         ulong itickets=0;
         double dpartlot=0;

         double dlotstep=SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP);//шаг лота
         double dMinLot=MinLot(m_name);

         double dMaxLoss=0;

         for(int i=PositionsTotal()-1; i>=0; i--)
           {

            if(!SelectByIndex(i,true))
               continue;

            ulong uOrderTicket=m_position.Ticket();
            int etype=m_position.PositionType();

            double dPositionProfit=m_position.Profit()+2*m_position.Commission()+m_position.Swap();
            double dPositionLot=m_position.Volume();

            double dminuslotUp=NormalizeDouble(dPositionProfit*dlotstep/dPositionLot,2); //рассчитаем профит на минимальный шаг лота 0.01

            if(dPositionProfit<0 && dPositionProfit<dMaxLoss)
              {

               dMaxLoss=dPositionProfit;

               dminuslot=dminuslotUp; //минус на 1 лот
               dminlot=dPositionLot;//лот ордера
               dpartlot=0;
               itickets=uOrderTicket;
               iforClose++;

              }

           }

         if(iforClose>0)
           {

            for(int j=1; !IsStopped(); j++)
              {
               double dMinus=NormalizeDouble(dminuslot*j,2);

               if(dMinus+dKopilka>=0 && dMinus<0)
                 {
                  dMinusForClose=dMinus;
                  dpartlot=NLot(j*dlotstep);
                 }
               else
                 {
                  break;
                 }
              }
           }

         if(dMinusForClose+dKopilka>=0 && dMinusForClose<0 &&  iforClose>0)
           {

            PrintFormat("Minis for close: %.2f Kopilka: %.2f count: %d",dMinusForClose,dKopilka,iforClose);

            int iOrderClose=0;

            if(dpartlot>0)
              {
               ulong iticket=itickets;
               double dlot=NLot(dpartlot);
               OrderClose(iticket,dlot);
               iOrderClose++;
              }

            if(iOrderClose>0)
              {
               dKopilka+=dMinusForClose; //вычтем из копилки
               tmCurrent=TimeCurrent();

               if(tmCurrent+1>_tmFirst)
                  _tmFirst=tmCurrent+1;

               PrintFormat("Kopilka close orders %s Kopilka: %.2f Time: %s",sType,dKopilka,TimeToString(_tmFirst,TIME_DATE|TIME_SECONDS));

               pglobal.SaveParam("Kopilka_Profit",dKopilka);

               return true;
              }

           }
        }

      return false;
     }

  };

class CUnlocker: public COrders
  {
public:
   int               iop;

#ifdef __MQL5__
   int               hma,hsar;

   void              InitIndicators(ENUM_TIMEFRAMES etf)
     {
      hma=iMA(m_name,etf,200,0,MODE_EMA,PRICE_OPEN);
      hsar=iSAR(m_name,etf,0.002,0.02);
     }

#endif
   virtual bool      Check(string symbol,long imagic)
     {

      if((m_name==NULL || symbol==m_name) && (m_imagic==-1 || m_imagic==imagic || imagic==-1))
         return true;

      return false;
     }

   virtual bool      CheckLocksMagic(string symbol,long iMagic)
     {

      if((m_name==NULL || symbol==m_name) && (iMagic==m_imagic || iMagic==m_imagic+1))
         return true;

      return false;
     }

   virtual int               CountLocks()
     {
      __COPYRIGHT__
      int ic=0;

      for(int i=0; i<PositionsTotal(); i++)
        {

         if(!SelectByIndex(i,true))
            continue; //если не выбирает, пропускаем

         if(CheckLocksMagic(m_position.Symbol(),m_position.Magic()) && m_position.PositionType()<2)
           {
            ic++;
           }
        }

      return ic;
     }

   virtual double    getMaxLotForUnlocker(long iSupportMagic)
     {

      double dreturn_lot=0;

      double dbuy=0,dsell=0;

      int icount=PositionsTotal();

      for(int i=icount-1; i>=0; i--)
        {
         if(!SelectByIndex(i,true))
            continue;

         if(!Check(m_position.Symbol(),m_position.Magic()))
            continue;

         if(m_position.PositionType()>=2 || m_position.Magic()==iSupportMagic)
            continue;

         if(m_position.PositionType()==POSITION_TYPE_BUY)
            dbuy+=m_position.Volume();
         if(m_position.PositionType()==POSITION_TYPE_SELL)
            dsell+=m_position.Volume();

        }

      dreturn_lot=MathMax(dbuy,dsell);

      return dreturn_lot;
     }

   virtual void              GetAllHistory(datetime tmLock,datetime &tmEnd,double &dSummProfit,double &dSummMinus)
     {

      datetime tmStart=tmEnd;
      double dSumm=0;
      dSummProfit=0;
      dSummMinus=0;

      HistorySelect(tmLock,TimeCurrent());

      for(int i=HistoryDealsTotal()-1; i>=0; i--)
        {
         if(!m_deal.SelectByIndex(i))
            continue;

         if(Check(m_deal.Symbol(),m_deal.Magic()) && tmLock>0 && m_deal.Entry()==DEAL_ENTRY_OUT)
           {

            if(m_deal.Time()<tmLock && tmLock>0)
               break;

            if(m_deal.Time()>tmStart && m_deal.Time()>=tmLock)
              {
               dSumm=m_deal.Profit()+m_deal.Commission()+m_deal.Swap(); //посчитаем суммарный профит\убыток закрытых ордеров

               if(dSumm>=0)
                  dSummProfit+=dSumm;
               else
                  dSummMinus+=dSumm;

               if(m_deal.Time()>tmEnd)
                  tmEnd=m_deal.Time();//обновим время обновления для следующего учета

              }

           }
        }
     }

   virtual bool              getMaximumMinus(ulong &tMin,double &dPositionLot,double &dPositionProfit)
     {

      tMin=0;

      dPositionLot=0;

      dPositionProfit=0;

      double dmin=0;

      double dprice=(_Ask+_Bid)/2;

      for(int i=0; i<PositionsTotal(); i++)
        {

         if(!SelectByIndex(i,true))
            continue;

         if(Check(m_position.Symbol(),m_position.Magic()) && m_position.PositionType()<2)
           {
            double ddelta=Abs(dprice-m_position.PriceOpen());
            double dMacroProfit=m_deal.Profit()+m_deal.Commission()+m_deal.Swap();

            if(dMacroProfit<0 && (ddelta>dmin || dmin==0))
              {
               dmin=ddelta;
               tMin=m_position.Ticket();
               dPositionLot=m_position.Volume();
               dPositionProfit=dMacroProfit;
              }
           }

        }

      if(tMin>0)
         return true;

      return false;
     }

   virtual void              MovePending(int iLockMagic,ENUM_TIMEFRAMES etf,double dMinOffset)
     {

      double dsarprice=0;
#ifdef __MQL5__
      double dma=iCustom(hma,0,0);
#else
      double dma=iMA(m_name,etf,200,0,MODE_EMA,PRICE_OPEN,0);
#endif

      for(int i=0; i<iBars(m_name,etf); i++)
        {
#ifdef __MQL5__
         double dsar=iCustom(hsar,0,i);
         double dsar1=iCustom(hsar,0,i+1);;
#else
         double dsar=iSAR(m_name,etf,0.002,0.02,i);
         double dsar1=iSAR(m_name,etf,0.002,0.02,i+1);
#endif

         if(dsar>iHigh(m_name,etf,i) && dsar1<iLow(m_name,etf,i+1) && _Ask<dsar+dMinOffset*p)
           {
            dsarprice=dsar;
            break;
           }
        }

      double dOpen=0,dNewOpen=0;

      if(dsarprice>0)
        {
         ulong tbuy=getOrderTicket(OP_BUYSTOP,0,iLockMagic);

         if(OrderSelect(tbuy,false))
           {
            dOpen=OrderOpenPrice();

            dNewOpen=dsarprice+dMinOffset*p;

            if(dOpen>dNewOpen && _Ask<dNewOpen)
              {

               OrderModify(tbuy,dNewOpen,0,0);
              }
           }
        }

      dsarprice=0;

      for(int i=0; i<iBars(m_name,etf); i++)
        {

#ifdef __MQL5__
         double dsar=iCustom(hsar,0,i);
         double dsar1=iCustom(hsar,0,i+1);;
#else
         double dsar=iSAR(m_name,etf,0.002,0.02,i);
         double dsar1=iSAR(m_name,etf,0.002,0.02,i+1);
#endif

         if(dsar<iLow(m_name,etf,i) && dsar1>iHigh(m_name,etf,i+1) && _Bid>dsar-dMinOffset*p)
           {
            dsarprice=dsar;
            break;
           }
        }

      if(dsarprice>0)
        {
         ulong tsell=getOrderTicket(OP_SELLSTOP,0,iLockMagic);

         if(OrderSelect(tsell))
           {

            dOpen=OrderOpenPrice();

            dNewOpen=dsarprice-dMinOffset*p;

            if(dOpen<dNewOpen && _Bid>dNewOpen)
              {

               OrderModify(tsell,dNewOpen,0,0);
              }
           }
        }

     }

   virtual bool              Stabilization(int iLockMagic,
                                           ENUM_TIMEFRAMES etf,
                                           double dPending_MinOffset,
                                           double dMinProfit,
                                           double dSupportMn,
                                           bool   bRecountLot,
                                           double dSupportTral,
                                           double dSupportStep)
     {

      int iSupportMagic=iLockMagic+1; //поддерка будет с меджиком +1 от лока

      double array_order_buy[][4];
      double array_order_sell[][4];

      ArrayResize(array_order_buy,0);
      ArrayResize(array_order_sell,0);

      int cb=0,cs=0;
      double dbuyprofit=0,dsellprofit=0;

      for(int i=PositionsTotal()-1; i>=0; i--)
        {
         if(!SelectByIndex(i,true))
            continue;

         if(OrderType()==OP_BUY)
           {
            if(ArrayResize(array_order_buy,cb+1)!=-1

Показано первые 50% кода (символов: 23459)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
2 345,90₽ ≈ $28.67