SampleTrailingstop-MT5

Author: Tungman
Orders Execution
Checks for the total of open orders
0 Views
0 Downloads
0 Favorites
SampleTrailingstop-MT5
//+------------------------------------------------------------------+
//|                                       SampleTrailingstop-MT5.mq5 |
//|                                                          Tungman |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Tungman"
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>

CTrade               eatrade;
CPositionInfo        eaposition;
COrderInfo           eapending;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
input double               PriceTP                 = 900; // Take profit (point) (0 = not use)
input double               PriceSL                 = 300; // Stop loss (point)
input int                  trailingstoppoint       = 200; // Trailing stop point (can view by symbol)
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double   CurrentBid        = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double   CurrentAsk        = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   MqlDateTime eadate;
   datetime curdatetime       = TimeCurrent(eadate);
   datetime expdate           = curdatetime + PeriodSeconds(PERIOD_D1);
   double   BuyPrice, SellPrice, SL, TP;
   bool CheckSellPending      = CheckPendingOrder("S");
   bool CheckBuyPending       = CheckPendingOrder("B");
   string d                   = "";
   double Volume              = 0.01;
   bool IsCheckVolume         = CheckVolumeValue(Volume, d);
   bool IsCheckMoneySell      = CheckMoneyForTrade(_Symbol,Volume,ORDER_TYPE_SELL);
   bool IsCheckMoneyBuy       = CheckMoneyForTrade(_Symbol,Volume,ORDER_TYPE_BUY);

   if(!IsCheckMoneySell)
      return;

   if(!IsCheckMoneyBuy)
      return;

   if(!IsCheckMoneySell)
      return;

   if(!IsCheckMoneyBuy)
      return;

   if(!CheckBuyPending && IsCheckVolume)
     {
      BuyPrice = NormalizeDouble(CurrentAsk, _Digits);
      SL       = NormalizeDouble(BuyPrice - (PriceSL * _Point), _Digits);
      TP       = NormalizeDouble(BuyPrice + (PriceTP * _Point), _Digits);
      eatrade.BuyStop(Volume, BuyPrice, _Symbol, SL, TP, ORDER_TIME_SPECIFIED, expdate, "B" + _Symbol);
     }

   if(!CheckSellPending && IsCheckVolume)
     {
      SellPrice   = NormalizeDouble(CurrentBid, _Digits);
      SL          = NormalizeDouble(SellPrice + (PriceSL * _Point), _Digits);
      TP          = NormalizeDouble(SellPrice - (PriceTP * _Point), _Digits);
      eatrade.SellStop(Volume, SellPrice, _Symbol, SL, TP, ORDER_TIME_SPECIFIED, expdate, "S" + _Symbol);
     }

  }

//+------------------------------------------------------------------+
//|Check lot size before open pending order                          |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume, string &description)
  {
//--- minimal allowed volume for trade operations
   double min_volume=SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f", min_volume);
      return(false);
     }
//--- maximal allowed volume of trade operations
   double max_volume=SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f", max_volume);
      return(false);
     }
//--- get minimal step of volume changing
   double volume_step=SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_STEP);
   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                               volume_step, ratio*volume_step);
      return(false);
     }
   description="Correct volume value";
   return(true);
  }
//+------------------------------------------------------------------+
void TrailingStop()
  {
   for(int i = PositionsTotal(); i >= 0; i --)
     {
      if(eaposition.SelectByIndex(i))
        {
         double Priceopen              = NormalizeDouble(eaposition.PriceOpen(), _Digits);
         double Pricecur               = NormalizeDouble(eaposition.PriceCurrent(), _Digits);
         int freeze_level              = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL);
         int stop_level                = (int)SymbolInfoInteger(eaposition.Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
         int spred                     = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
         double trailpoint             = NormalizeDouble(trailingstoppoint * _Point, _Digits);
         double bid                    = NormalizeDouble(SymbolInfoDouble(eaposition.Symbol(), SYMBOL_BID), _Digits);
         double ask                    = NormalizeDouble(SymbolInfoDouble(eaposition.Symbol(), SYMBOL_ASK), _Digits);
         double sl, tp;
         double CurrentSL              = NormalizeDouble(eaposition.StopLoss(), _Digits);
         double CurrentTP              = NormalizeDouble(eaposition.TakeProfit(), _Digits);
         double MaxSL                  = 0;
         double NewSL                  = NormalizeDouble(((stop_level + spred) * _Point), _Digits);
         double NewTP                  = NormalizeDouble(((stop_level) * _Point), _Digits);
         string PosSymbol              = eaposition.Symbol();
         double Posprofit              = eaposition.Profit();
         double ValidSell              = NormalizeDouble(ask + NewSL, _Digits);
         double ValidBuy               = NormalizeDouble(bid - NewSL, _Digits);
         bool check                    = false;
         if(PosSymbol == _Symbol)
           {
            if(eaposition.PositionType() == POSITION_TYPE_BUY)
              {
               bool checkfreeze  = ((ask - Priceopen) > freeze_level * _Point);
               if(CurrentSL < Priceopen || CurrentSL == 0)
                 {
                  if(Posprofit > 0 &&  bid >= (Priceopen + trailpoint) && checkfreeze)
                    {
                     sl = NormalizeDouble(ValidBuy, _Digits); // sl must less than bid price
                     tp = 0;//NormalizeDouble(bid + (PriceTP * _Point),_Digits);

                     check = eatrade.PositionModify(eaposition.Ticket(), sl, tp);
                    }
                 }
               else
                  if(CurrentSL > Priceopen)
                    {
                     if(Posprofit > 0 && CurrentSL <= ValidBuy  && checkfreeze)
                       {
                        sl = NormalizeDouble(bid - ValidBuy, _Digits); // sl must less than bid price
                        tp = NormalizeDouble(bid + (PriceTP * _Point), _Digits);
                        check =  eatrade.PositionModify(eaposition.Ticket(), sl, tp);
                       }
                    }
              }
            if(eaposition.PositionType() == POSITION_TYPE_SELL)
              {
               bool checkfreeze = ((Priceopen - bid) > freeze_level *_Point);
               if(CurrentSL > Priceopen || CurrentSL == 0)
                 {
                  if(Posprofit > 0 && ask <= (Priceopen - trailpoint) && checkfreeze)
                    {
                     sl = NormalizeDouble(ValidSell, _Digits);
                     tp = 0;//NormalizeDouble(ask - (PriceTP * _Point),_Digits);

                     check =  eatrade.PositionModify(eaposition.Ticket(), sl, tp);
                    }
                 }
               else
                  if(CurrentSL < Priceopen)
                    {
                     if(Posprofit > 0 && CurrentSL >= ValidSell && checkfreeze)
                       {
                        sl = NormalizeDouble(ask + ValidSell, _Digits);
                        tp = NormalizeDouble(ask - (PriceTP * _Point), _Digits);
                        check =  eatrade.PositionModify(eaposition.Ticket(), sl, tp);
                       }
                    }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|Check free margin before open order                               |
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(string symb, double lots, ENUM_ORDER_TYPE type)
  {
//--- Getting the opening price
   MqlTick mqltick;
   SymbolInfoTick(symb, mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- values of the required and free margin
   double margin, free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
   if(!OrderCalcMargin(type, symb, lots, price, margin))
     {
      //--- something went wrong, report and return false
      Print("Error in ", __FUNCTION__, " code=", GetLastError());
      return(false);
     }
//--- if there are insufficient funds to perform the operation
   if(margin>free_margin)
     {
      //--- report the error and return false
      Print("Not enough money for ", EnumToString(type), " ", lots, " ", symb, " Error code=", GetLastError());
      return(false);
     }
//--- checking successful
   return(true);
  }

//+------------------------------------------------------------------+
//|Check exists pending order
// ordertype S = SELL, B = BUY
//+------------------------------------------------------------------+
bool CheckPendingOrder(string ordertype)
  {
   bool res = false;
// Check existiing pending
   for(int i = OrdersTotal(); i >= 0; i --)
     {
      if(eapending.SelectByIndex(i))
        {
         string PenSymbol        = eapending.Symbol();
         string comment          = eapending.Comment();
         if(PenSymbol == _Symbol && comment == ordertype + _Symbol)
           {
            res = true;
            break;
           }
        }
     }
   return res;
  }
//+------------------------------------------------------------------+

Comments