Multicurrency Grid

Author: Copyright © 2019, Vladimir Karputov
Price Data Components
Series array that contains tick volumes of each bar
Orders Execution
Checks for the total of open orders
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Multicurrency Grid
ÿþ//+------------------------------------------------------------------+

//|                                           Multicurrency Grid.mq5 |

//|                              Copyright © 2019, Vladimir Karputov |

//|                                           http://wmua.ru/slesar/ |

//+------------------------------------------------------------------+

#property copyright "Copyright © 2019, Vladimir Karputov"

#property link      "http://wmua.ru/slesar/"

#property version   "1.002"

//---

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>  

CPositionInfo  ClassPosition;                   // trade position object

CTrade         ClassTrade;                      // trading object

CSymbolInfo    ClassSymbol;                     // symbol info object



#include <Arrays\ArrayObj.mqh>

CArrayObj      m_array_obj;                  // CArrayObj object

//+------------------------------------------------------------------+

//| Enum Lor or Risk                                                 |

//+------------------------------------------------------------------+

enum ENUM_LOT_OR_RISK

  {

   lot=0,   // Constant lot

   risk=1,  // Risk in percent for a deal

  };

//--- input parameters

input string   InpSymbols="EURUSD,USDJPY";            // Symbols

input ushort   InpStep                 = 15;          // Step, in pips (1.00045-1.00055=1 pips)

input uchar    InpNumberSteps          = 3;           // Number of steps

input uchar    InpAllowablSpread       = 15;          // Allowable spread, in points (1.00045-1.00055=10 points)

input double   InpMinimumProfit        = 15;          // Minimum Profit

input ENUM_LOT_OR_RISK IntLotOrRisk    = risk;        // Money management: Lot OR Risk

input double   InpVolumeLotOrRisk      = 1.0;         // The value for "Money management"

input bool     InpPrintLog             = false;       // Print log

input ulong    InpMagic                = 35966754;    // Magic number

//---

bool  ExtNeedCloseAll;

//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

   ExtNeedCloseAll=false;

//---

   string to_split=InpSymbols;   // a string to split into substrings 

   StringTrimLeft(to_split);

   StringTrimRight(to_split);



   string sep=",";               // a separator as a character 

   ushort u_sep;                 // the code of the separator character 

   string result[];              // an array to get strings 

//--- get the separator code 

   u_sep=StringGetCharacter(sep,0);

//--- split the string to substrings 

   int k=StringSplit(to_split,u_sep,result);



   for(int i=0;i<k;i++)

     {

      if(!ClassSymbol.Name(result[i])) // sets symbol name

         return(INIT_FAILED);



      CMultiGrid *multi=new CMultiGrid;

      if(multi==NULL)

        {

         Print("Object CMultiGrid create error");

         return(INIT_FAILED);

        }

      m_array_obj.Add(multi);

      int init=multi.OnInit(result[i],

                            InpStep,                  // Step, in pips (1.00045-1.00055=1 pips)

                            InpNumberSteps,           // Number of steps

                            InpAllowablSpread,        // Allowable spread, in points (1.00045-1.00055=10 points)

                            IntLotOrRisk,             // Money management: Lot OR Risk

                            InpVolumeLotOrRisk,       // The value for "Money management"

                            InpPrintLog,              // Print log

                            InpMagic,                 // Magic number

                            10                        // Slippage

                            );

      if(init!=INIT_SUCCEEDED)

         return(init);

     }

//---

   ClassTrade.SetExpertMagicNumber(0);

   ClassTrade.SetMarginMode();

   ClassTrade.SetTypeFillingBySymbol(Symbol());

   ClassTrade.SetDeviationInPoints(10);

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//---

   for(int i=0;i<m_array_obj.Total();i++)

     {

      CMultiGrid *multi=m_array_obj.At(i);

      if(multi==NULL)

        {

         //--- Error reading from array 

         Print("Object CMultiGrid create error");

         return;

        }

      multi.OnDeinit(reason);

     }

  }

//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

  {

   if(ExtNeedCloseAll)

     {

      int total=0;

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

         if(ClassPosition.SelectByIndex(i)) // selects the position by index for further access to its properties

            if(ClassPosition.Magic()==InpMagic)

               total++;

      if(total==0)

         ExtNeedCloseAll=false;



      for(int i=0;i<m_array_obj.Total();i++)

        {

         CMultiGrid *multi=m_array_obj.At(i);

         if(multi==NULL)

           {

            //--- Error reading from array 

            Print("Object CMultiGrid create error");

            return;

           }

         multi.Pause(false);

        }

     }



   double profit=0.0;

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

      if(ClassPosition.SelectByIndex(i)) // selects the position by index for further access to its properties

         if(ClassPosition.Magic()==InpMagic)

            profit+=ClassPosition.Commission()+ClassPosition.Swap()+ClassPosition.Profit();



   if(profit>=InpMinimumProfit)

     {

      ExtNeedCloseAll=true;

      for(int i=0;i<m_array_obj.Total();i++)

        {

         CMultiGrid *multi=m_array_obj.At(i);

         if(multi==NULL)

           {

            //--- Error reading from array 

            Print("Object CMultiGrid create error");

            return;

           }

         multi.Pause(true);

        }

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

         if(ClassPosition.SelectByIndex(i)) // selects the position by index for further access to its properties

            if(ClassPosition.Magic()==InpMagic)

               ClassTrade.PositionClose(ClassPosition.Ticket());

      return;

     }



   for(int i=0;i<m_array_obj.Total();i++)

     {

      CMultiGrid *multi=m_array_obj.At(i);

      if(multi==NULL)

        {

         //--- Error reading from array 

         Print("Object CMultiGrid create error");

         return;

        }

      multi.OnTick();

     }

//---

  }

//+------------------------------------------------------------------+

//| TradeTransaction function                                        |

//+------------------------------------------------------------------+

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {

//--- 



  }

//+------------------------------------------------------------------+

//|                                                    MultiGrid.mqh |

//|                              Copyright © 2019, Vladimir Karputov |

//|                                           http://wmua.ru/slesar/ |

//+------------------------------------------------------------------+

#property copyright "Copyright © 2019, Vladimir Karputov"

#property link      "http://wmua.ru/slesar/"

#property version   "1.000"

//---

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>  

#include <Trade\AccountInfo.mqh>

#include <Trade\DealInfo.mqh>

#include <Trade\OrderInfo.mqh>

#include <Expert\Money\MoneyFixedMargin.mqh>

//+------------------------------------------------------------------+

//| Class CMultiGrid.                                                |

//| Appointment: Class Expert Advisor.                               |

//|              Derives from class CObject.                         |

//+------------------------------------------------------------------+

class CMultiGrid : public CObject

  {

protected:

   CPositionInfo     m_position;                   // trade position object

   CTrade            m_trade;                      // trading object

   CSymbolInfo       m_symbol;                     // symbol info object

   CAccountInfo      m_account;                    // account info wrapper

   CDealInfo         m_deal;                       // deals object

   COrderInfo        m_order;                      // pending orders object

   CMoneyFixedMargin *m_money;

   //---

   double            ExtStep;                      // Step, in pips (1.00045-1.00055=1 pips)

   uchar             ExtNumberSteps;               // Number of steps

   uchar             ExtAllowablSpread;            // Allowable spread, in points (1.00045-1.00055=10 points)

   ENUM_LOT_OR_RISK  ExtLotOrRisk;                 // Money management: Lot OR Risk

   double            ExtVolumeLotOrRisk;           // The value for "Money management"

   bool              ExtPrintLog;                  // Print log

   ulong             ExtMagic;                     // Magic number

   ulong             ExtSlippage;                  // Slippage

   double            ExtAdjustedPoint;             // point value adjusted for 3 or 5 points

   bool              ExtNeedOpenBuyStop;

   bool              ExtNeedOpenSellStop;

   bool              ExtPause;

   datetime          PrevBars;

   //--- Refreshes the symbol quotes data

   bool              RefreshRates(void);

   //--- Check the correctness of the position volume

   bool              CheckVolumeValue(double volume,string &error_description);

   //--- Check Freeze and Stops levels 

   bool              FreezeStopsLevels(double &level);

   //--- Place Orders     

   void              PlaceOrders(const ENUM_ORDER_TYPE order_type,const double level);

   //--- Pending order   

   bool              PendingOrder(ENUM_ORDER_TYPE order_type,double price,double sl,double tp);

   //--- Print CTrade result     

   void              PrintResultTrade(CTrade &trade,CSymbolInfo &symbol);

   //--- Close all positions  

   void              CloseAllPositions();

   //--- Calculate all pending orders      

   void              CalculateAllPendingOrders(int &count_buy_stops,int &count_sell_stops);

   //--- Is pendinf orders exists    

   bool              IsPendingOrdersExists(void);

   //--- Delete all pending orders    

   void              DeleteAllPendingOrders(const double level);

   //--- Is position exists  

   bool              IsPositionExists(void);

   //--- Calculate all volumes

   void              CalculateAllVolumes(double &volumne_buys,double &volumne_sells,

                                         double &volumne_buy_limits,double &volumne_sell_limits,

                                         double &volumne_buy_stops,double &volumne_sell_stops);



private:



public:

                     CMultiGrid();

                    ~CMultiGrid();

   //--- expert initialization function

   int               OnInit(string           EASymbolName,     // Symbol name

                            ushort           Step,             // Step, in pips (1.00045-1.00055=1 pips)

                            uchar            NumberSteps,      // Number of steps

                            uchar            AllowablSpread,   // Allowable spread, in points (1.00045-1.00055=10 points)

                            ENUM_LOT_OR_RISK LotOrRisk,        // Money management: Lot OR Risk

                            double           VolumeLotOrRisk,  // The value for "Money management"

                            bool             PrintLog,         // Print log

                            ulong            Magic,            // Magic number

                            ulong            Slippage          // Slippage

                            );

   //--- expert deinitialization function

   void              OnDeinit(const int reason);

   //--- expert tick function

   void              OnTick();

   //--- pause

   void              Pause(const bool volume)      { ExtPause=volume;         }

   bool              Pause(void)                   { return(ExtPause);        }



  };

//+------------------------------------------------------------------+

//| Constructor                                                      |

//+------------------------------------------------------------------+

CMultiGrid::CMultiGrid(void) : ExtStep(15),

                               ExtNumberSteps(3),

                               ExtAllowablSpread(15),

                               ExtLotOrRisk(risk),

                               ExtVolumeLotOrRisk(1.0),

                               ExtPrintLog(false),

                               ExtMagic(0),

                               ExtSlippage(10),

                               ExtAdjustedPoint(0.0001),

                               ExtNeedOpenBuyStop(false),

                               ExtNeedOpenSellStop(false),

                               ExtPause(false),

                               PrevBars(0)

  {

  }

//+------------------------------------------------------------------+

//| Destructor                                                       |

//+------------------------------------------------------------------+

CMultiGrid::~CMultiGrid()

  {

  }

//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int CMultiGrid::OnInit(string             EASymbolName,     // Symbol name

                       ushort             Step,             // Step, in pips (1.00045-1.00055=1 pips)

                       uchar              NumberSteps,      // Number of steps

                       uchar              AllowablSpread,   // Allowable spread, in points (1.00045-1.00055=10 points)

                       ENUM_LOT_OR_RISK   LotOrRisk,        // Money management: Lot OR Risk

                       double             VolumeLotOrRisk,  // The value for "Money management"

                       bool               PrintLog,         // Print log

                       ulong              Magic,            // Magic number

                       ulong              Slippage          // Slippage

                       )

  {

//---

   if(!m_symbol.Name(EASymbolName)) // sets symbol name

      return(INIT_FAILED);

   RefreshRates();

//---

   m_trade.SetExpertMagicNumber(Magic);

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(m_symbol.Name());

   m_trade.SetDeviationInPoints(Slippage);

//--- tuning for 3 or 5 digits

   int digits_adjust=1;

   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)

      digits_adjust=10;

   ExtAdjustedPoint=m_symbol.Point()*digits_adjust;



   ExtStep           = Step  *ExtAdjustedPoint;

   ExtNumberSteps    = NumberSteps;

   ExtAllowablSpread = AllowablSpread;

   ExtLotOrRisk      = LotOrRisk;

   ExtVolumeLotOrRisk= VolumeLotOrRisk;

   ExtPrintLog       = PrintLog;

   ExtMagic          = Magic;

   ExtSlippage       = Slippage;

//--- check the input parameter "Lots"

   string err_text="";

   if(LotOrRisk==lot)

     {

      if(!CheckVolumeValue(ExtVolumeLotOrRisk,err_text))

        {

         //--- when testing, we will only output to the log about incorrect input parameters

         if(MQLInfoInteger(MQL_TESTER))

           {

            Print(__FUNCTION__,", ERROR: ",err_text);

            return(INIT_FAILED);

           }

         else // if the Expert Advisor is run on the chart, tell the user about the error

           {

            Alert(__FUNCTION__,", ERROR: ",err_text);

            return(INIT_PARAMETERS_INCORRECT);

           }

        }

     }

   else

     {

      if(m_money!=NULL)

         delete m_money;

      m_money=new CMoneyFixedMargin;

      if(m_money!=NULL)

        {

         if(!m_money.Init(GetPointer(m_symbol),Period(),m_symbol.Point()*digits_adjust))

            return(INIT_FAILED);

         m_money.Percent(ExtVolumeLotOrRisk);

        }

      else

        {

         Print(__FUNCTION__,", ERROR: Object CMoneyFixedMargin is NULL");

         return(INIT_FAILED);

        }

     }

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void CMultiGrid::OnDeinit(const int reason)

  {

//---

   if(m_money!=NULL)

      delete m_money;

  }

//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void CMultiGrid::OnTick()

  {

   if(Pause())

      return;

//--- need open Buy stop

   if(ExtNeedOpenBuyStop)

     {

      int count_buy_stops=0,count_sell_stops=0;

      CalculateAllPendingOrders(count_buy_stops,count_sell_stops);

      if(count_buy_stops==0)

        {

         double level;

         if(FreezeStopsLevels(level))

            PlaceOrders(ORDER_TYPE_BUY_STOP,level);

         return;

        }

      else

         ExtNeedOpenBuyStop=false;

     }

//--- ned open Sell stop

   if(ExtNeedOpenSellStop)

     {

      int count_buy_stops=0,count_sell_stops=0;

      CalculateAllPendingOrders(count_buy_stops,count_sell_stops);

      if(count_sell_stops==0)

        {

         double level;

         if(FreezeStopsLevels(level))

            PlaceOrders(ORDER_TYPE_SELL_STOP,level);

         return;

        }

      else

         ExtNeedOpenSellStop=false;

     }

//--- we work only at the time of the birth of new bar

   datetime time_0=iTime(m_symbol.Name(),Period(),0);

   if(time_0==PrevBars)

      return;

   PrevBars=time_0;

   if(!RefreshRates())

     {

      PrevBars=0;

      return;

     }

//---

   int count_buy_stops=0,count_sell_stops=0;

   CalculateAllPendingOrders(count_buy_stops,count_sell_stops);



   if(count_buy_stops==0)

      ExtNeedOpenBuyStop=true;

   if(count_sell_stops==0)

      ExtNeedOpenSellStop=true;



//---

  }

//+------------------------------------------------------------------+

//| Refreshes the symbol quotes data                                 |

//+------------------------------------------------------------------+

bool CMultiGrid::RefreshRates(void)

  {

//--- refresh rates

   if(!m_symbol.RefreshRates())

     {

      Print("RefreshRates error");

      return(false);

     }

//--- protection against the return value of "zero"

   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)

      return(false);

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Check the correctness of the position volume                     |

//+------------------------------------------------------------------+

bool CMultiGrid::CheckVolumeValue(double volume,string &error_description)

  {

//--- minimal allowed volume for trade operations

   double min_volume=m_symbol.LotsMin();

   if(volume<min_volume)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< <5=LH5 <8=8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MIN=%.2f",min_volume);

      else

         error_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=m_symbol.LotsMax();

   if(volume>max_volume)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< 1>;LH5 <0:A8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MAX=%.2f",max_volume);

      else

         error_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=m_symbol.LotsStep();

   int ratio=(int)MathRound(volume/volume_step);

   if(MathAbs(ratio*volume_step-volume)>0.0000001)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< =5 :@0B5= <8=8<0;L=><C H03C SYMBOL_VOLUME_STEP=%.2f, 1;8609H89 ?@028;L=K9 >1J5< %.2f",

                                        volume_step,ratio*volume_step);

      else

         error_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);

     }

   error_description="Correct volume value";

   return(true);

  }

//+------------------------------------------------------------------+

//| Check Freeze and Stops levels                                    |

//+------------------------------------------------------------------+

bool CMultiGrid::FreezeStopsLevels(double &level)

  {

//--- check Freeze and Stops levels

/*

   Type of order/position  |  Activation price  |  Check

   ------------------------|--------------------|--------------------------------------------

   Buy Limit order         |  Ask               |  Ask-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy Stop order          |  Ask	            |  OpenPrice-Ask  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Limit order        |  Bid	            |  OpenPrice-Bid  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Stop order	      |  Bid	            |  Bid-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy position            |  Bid	            |  TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL 

                           |                    |  Bid-StopLoss   >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell position           |  Ask	            |  Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL

                           |                    |  StopLoss-Ask   >= SYMBOL_TRADE_FREEZE_LEVEL

                           

   Buying is done at the Ask price                 |  Selling is done at the Bid price

   ------------------------------------------------|----------------------------------

   TakeProfit        >= Bid                        |  TakeProfit        <= Ask

   StopLoss          <= Bid	                     |  StopLoss          >= Ask

   TakeProfit - Bid  >= SYMBOL_TRADE_STOPS_LEVEL   |  Ask - TakeProfit  >= SYMBOL_TRADE_STOPS_LEVEL

   Bid - StopLoss    >= SYMBOL_TRADE_STOPS_LEVEL   |  StopLoss - Ask    >= SYMBOL_TRADE_STOPS_LEVEL

*/

   if(!RefreshRates() || !m_symbol.Refresh())

      return(false);

//--- FreezeLevel -> for pending order and modification

   double freeze_level=m_symbol.FreezeLevel()*m_symbol.Point();

   if(freeze_level==0.0)

      freeze_level=(m_symbol.Ask()-m_symbol.Bid())*3.0;

   freeze_level*=1.1;

//--- StopsLevel -> for TakeProfit and StopLoss

   double stop_level=m_symbol.StopsLevel()*m_symbol.Point();

   if(stop_level==0.0)

      stop_level=(m_symbol.Ask()-m_symbol.Bid())*3.0;

   stop_level*=1.1;



   if(freeze_level<=0.0 || stop_level<=0.0)

      return(false);



   level=(freeze_level>stop_level)?freeze_level:stop_level;

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Place Orders                                                     |

//+------------------------------------------------------------------+

void CMultiGrid::PlaceOrders(const ENUM_ORDER_TYPE order_type,const double level)

  {

   if(m_symbol.Ask()-m_symbol.Bid()>ExtAllowablSpread*m_symbol.Point())

      return;

//--- check Freeze and Stops levels

/*

   Type of order/position  |  Activation price  |  Check

   ------------------------|--------------------|--------------------------------------------

   Buy Limit order         |  Ask               |  Ask-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy Stop order          |  Ask	            |  OpenPrice-Ask  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Limit order        |  Bid	            |  OpenPrice-Bid  >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell Stop order	      |  Bid	            |  Bid-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL

   Buy position            |  Bid	            |  TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL 

                           |                    |  Bid-StopLoss   >= SYMBOL_TRADE_FREEZE_LEVEL

   Sell position           |  Ask	            |  Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL

                           |                    |  StopLoss-Ask   >= SYMBOL_TRADE_FREEZE_LEVEL

                           

   Buying is done at the Ask price                 |  Selling is done at the Bid price

   ------------------------------------------------|----------------------------------

   TakeProfit        >= Bid                        |  TakeProfit        <= Ask

   StopLoss          <= Bid	                     |  StopLoss          >= Ask

   TakeProfit - Bid  >= SYMBOL_TRADE_STOPS_LEVEL   |  Ask - TakeProfit  >= SYMBOL_TRADE_STOPS_LEVEL

   Bid - StopLoss    >= SYMBOL_TRADE_STOPS_LEVEL   |  StopLoss - Ask    >= SYMBOL_TRADE_STOPS_LEVEL

*/

   for(int i=0;i<ExtNumberSteps;i++)

     {

      //--- buy stop

      if(order_type==ORDER_TYPE_BUY_STOP)

        {

         double price=m_symbol.Ask()+(i+1)*ExtStep;

         if(price-m_symbol.Ask()<level) // check price

            price=m_symbol.Ask()+level;



         PendingOrder(ORDER_TYPE_BUY_STOP,price,0.0,0.0);

        }

      //--- sell stop

      if(order_type==ORDER_TYPE_SELL_STOP)

        {

         double price=m_symbol.Bid()-(i+1)*ExtStep;

         if(m_symbol.Bid()-price<level) // check price

            price=m_symbol.Bid()-level;



         PendingOrder(ORDER_TYPE_SELL_STOP,price,0.0,0.0);

        }

     }

//---

  }

//+------------------------------------------------------------------+

//| Pending order                                                    |

//+------------------------------------------------------------------+

bool CMultiGrid::PendingOrder(ENUM_ORDER_TYPE order_type,double price,double sl,double tp)

  {

   sl=m_symbol.NormalizePrice(sl);

   tp=m_symbol.NormalizePrice(tp);

//--- check volume before OrderSend to avoid "not enough money" error (CTrade)

   ENUM_ORDER_TYPE check_order_type=-1;

   switch(order_type)

     {

      case  ORDER_TYPE_BUY:

         check_order_type=ORDER_TYPE_BUY;

         break;

      case ORDER_TYPE_SELL:

         check_order_type=ORDER_TYPE_SELL;

         break;

      case ORDER_TYPE_BUY_LIMIT:

         check_order_type=ORDER_TYPE_BUY;

         break;

      case ORDER_TYPE_SELL_LIMIT:

         check_order_type=ORDER_TYPE_SELL;

         break;

      case ORDER_TYPE_BUY_STOP:

         check_order_type=ORDER_TYPE_BUY;

         break;

      case ORDER_TYPE_SELL_STOP:

         check_order_type=ORDER_TYPE_SELL;

         break;

      default:

         return(false);

         break;

     }

//---

   double long_lot=0.0;

   double short_lot=0.0;

   if(ExtLotOrRisk==risk)

     {

      bool error=false;

      long_lot=m_money.CheckOpenLong(m_symbol.Ask(),sl);

      if(ExtPrintLog)

         Print("sl=",DoubleToString(sl,m_symbol.Digits()),

               ", CheckOpenLong: ",DoubleToString(long_lot,2),

               ", Balance: ",    DoubleToString(m_account.Balance(),2),

               ", Equity: ",     DoubleToString(m_account.Equity(),2),

               ", FreeMargin: ", DoubleToString(m_account.FreeMargin(),2));

      if(long_lot==0.0)

        {

         if(ExtPrintLog)

            Print(__FUNCTION__,", ERROR: method CheckOpenLong returned the value of \"0.0\"");

         error=true;

        }

      //---

      short_lot=m_money.CheckOpenShort(m_symbol.Bid(),sl);

      if(ExtPrintLog)

         Print("sl=",DoubleToString(sl,m_symbol.Digits()),

               ", CheckOpenLong: ",DoubleToString(short_lot,2),

               ", Balance: ",    DoubleToString(m_account.Balance(),2),

               ", Equity: ",     DoubleToString(m_account.Equity(),2),

               ", FreeMargin: ", DoubleToString(m_account.FreeMargin(),2));

      if(short_lot==0.0)

        {

         if(ExtPrintLog)

            Print(__FUNCTION__,", ERROR: method CheckOpenShort returned the value of \"0.0\"");

         error=true;

        }

      //---

      if(error)

         return(false);

     }

   else if(ExtLotOrRisk==lot)

     {

      long_lot=ExtVolumeLotOrRisk;

      short_lot=ExtVolumeLotOrRisk;

     }

   else

      return(false);

//--- check volume before OrderSend to avoid "not enough money" error (CTrade)

   double check_price=0;

   double check_lot=0;

   if(check_order_type==ORDER_TYPE_BUY)

     {

      check_price=m_symbol.Ask();

      check_lot=long_lot;

     }

   else

     {

      check_price=m_symbol.Bid();

      check_lot=short_lot;

     }

//---

   if(m_symbol.LotsLimit()>0.0)

     {

      double volume_buys        = 0.0;   double volume_sells       = 0.0;

      double volume_buy_limits  = 0.0;   double volume_sell_limits = 0.0;

      double volume_buy_stops   = 0.0;   double volume_sell_stops  = 0.0;

      CalculateAllVolumes(volume_buys,volume_sells,

                          volume_buy_limits,volume_sell_limits,

                          volume_buy_stops,volume_sell_stops);

      if(volume_buys+volume_sells+

         volume_buy_limits+volume_sell_limits+

         volume_buy_stops+volume_sell_stops+check_lot>m_symbol.LotsLimit())

        {

         if(ExtPrintLog)

            Print("#0 ,",EnumToString(order_type),", ",

                  "Volume Buy's (",DoubleToString(volume_buys,2),")",

                  "Volume Sell's (",DoubleToString(volume_sells,2),")",

                  "Volume Buy limit's (",DoubleToString(volume_buy_limits,2),")",

                  "Volume Sell limit's (",DoubleToString(volume_sell_limits,2),")",

                  "Volume Buy stops's (",DoubleToString(volume_buy_stops,2),")",

                  "Volume Sell stops's (",DoubleToString(volume_sell_stops,2),")",

                  "Check lot (",DoubleToString(check_lot,2),")",

                  " > Lots Limit (",DoubleToString(m_symbol.LotsLimit(),2),")");

         return(false);

        }

     }

//---

   double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(),check_order_type,check_lot,check_price);

   if(free_margin_check>0.0)

     {

      if(m_trade.OrderOpen(m_symbol.Name(),order_type,check_lot,0.0,

         m_symbol.NormalizePrice(price),m_symbol.NormalizePrice(sl),m_symbol.NormalizePrice(tp),ORDER_TIME_DAY))

        {

         if(m_trade.ResultOrder()==0)

           {

            if(ExtPrintLog)

               Print("#1 ",EnumToString(order_type)," -> false. Result Retcode: ",m_trade.ResultRetcode(),

                     ", description of result: ",m_trade.ResultRetcodeDescription());

            if(ExtPrintLog)

               PrintResultTrade(m_trade,m_symbol);

            return(false);

           }

         else

           {

            if(ExtPrintLog)

               Print("#2 ",EnumToString(order_type)," -> true. Result Retcode: ",m_trade.ResultRetcode(),

                     ", description of result: ",m_trade.ResultRetcodeDescription());

            if(ExtPrintLog)

               PrintResultTrade(m_trade,m_symbol);

            return(true);

           }

        }

      else

        {

         if(ExtPrintLog)

            Print("#3 ",EnumToString(order_type)," -> false. Result Retcode: ",m_trade.ResultRetcode(),

                  ", description of result: ",m_trade.ResultRetcodeDescription());

         if(ExtPrintLog)

            PrintResultTrade(m_trade,m_symbol);

         return(false);

        }

     }

   else

     {

      if(ExtPrintLog)

         Print(__FUNCTION__,", ERROR: method CAccountInfo::FreeMarginCheck returned the value ",DoubleToString(free_margin_check,2));

      return(false);

     }

//---

   return(false);

  }

//+------------------------------------------------------------------+

//| Print CTrade result                                              |

//+------------------------------------------------------------------+

void CMultiGrid::PrintResultTrade(CTrade &trade,CSymbolInfo &symbol)

  {

   Print("File: ",__FILE__,", symbol: ",symbol.Name());

   Print("Code of request result: "+IntegerToString(trade.ResultRetcode()));

   Print("code of request result as a string: "+trade.ResultRetcodeDescription());

   Print("Deal ticket: "+IntegerToString(trade.ResultDeal()));

   Print("Order ticket: "+IntegerToString(trade.ResultOrder()));

   Print("Volume of deal or order: "+DoubleToString(trade.ResultVolume(),2));

   Print("Price, confirmed by broker: "+DoubleToString(trade.ResultPrice(),symbol.Digits()));

   Print("Current bid price: "+DoubleToString(symbol.Bid(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultBid(),symbol.Digits()));

   Print("Current ask price: "+DoubleToString(symbol.Ask(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultAsk(),symbol.Digits()));

   Print("Broker comment: "+trade.ResultComment());

   int d=0;

  }

//+------------------------------------------------------------------+

//| Close all positions                                              |

//+------------------------------------------------------------------+

void CMultiGrid::CloseAllPositions()

  {

   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions

      if(m_position.SelectByIndex(i))     // selects the position by index for further access to its properties

         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==ExtMagic)

            m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol

  }

//+------------------------------------------------------------------+

//| Calculate all pending orders                                     |

//+------------------------------------------------------------------+

void CMultiGrid::CalculateAllPendingOrders(int &count_buy_stops,int &count_sell_stops)

  {

   count_buy_stops   = 0;

   count_sell_stops  = 0;



   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders

      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties

         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==ExtMagic)

           {

            if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)

               count_buy_stops++;

            else if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)

               count_sell_stops++;

           }

  }

//+------------------------------------------------------------------+

//| Is pendinf orders exists                                         |

//+------------------------------------------------------------------+

bool CMultiGrid::IsPendingOrdersExists(void)

  {

   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders

      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties

         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==ExtMagic)

            return(true);

//---

   return(false);

  }

//+------------------------------------------------------------------+

//| Delete all pending orders                                        |

//+------------------------------------------------------------------+

void CMultiGrid::DeleteAllPendingOrders(const double level)

  {

   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders

      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties

         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==ExtMagic)

           {

            if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT)

              {

               if(m_symbol.Ask()-m_order.PriceOpen()>=level)

                  m_trade.OrderDelete(m_order.Ticket());

               continue;

              }

            if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)

              {

               if(m_order.PriceOpen()-m_symbol.Ask()>=level)

                  m_trade.OrderDelete(m_order.Ticket());

               continue;

              }

            if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT)

              {

               if(m_order.PriceOpen()-m_symbol.Bid()>=level)

                  m_trade.OrderDelete(m_order.Ticket());

               continue;

              }

            if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)

              {

               if(m_symbol.Bid()-m_order.PriceOpen()>=level)

                  m_trade.OrderDelete(m_order.Ticket());

               continue;

              }

           }

  }

//+------------------------------------------------------------------+

//| Is position exists                                               |

//+------------------------------------------------------------------+

bool CMultiGrid::IsPositionExists(void)

  {

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

      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties

         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==ExtMagic)

            return(true);

//---

   return(false);

  }

//+------------------------------------------------------------------+

//| Calculate all volumes                                            |

//+------------------------------------------------------------------+

void CMultiGrid::CalculateAllVolumes(double &volumne_buys,double &volumne_sells,

                                     double &volumne_buy_limits,double &volumne_sell_limits,

                                     double &volumne_buy_stops,double &volumne_sell_stops)

  {

   volumne_buys         = 0.0;   volumne_sells        = 0.0;

   volumne_buy_limits   = 0.0;   volumne_sell_limits  = 0.0;

   volumne_buy_stops    = 0.0;   volumne_sell_stops   = 0.0;



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

      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties

         if(m_position.Symbol()==m_symbol.Name())

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

               volumne_buys+=m_position.Volume();

            else if(m_position.PositionType()==POSITION_TYPE_SELL)

               volumne_sells+=m_position.Volume();

           }



   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders

      if(m_order.SelectByIndex(i)) // selects the pending order by index for further access to its properties

         if(m_order.Symbol()==m_symbol.Name())

           {

            if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT)

               volumne_buy_limits+=m_order.VolumeInitial();

            else if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT)

               volumne_sell_limits+=m_order.VolumeInitial();

            else if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)

               volumne_buy_stops+=m_order.VolumeInitial();

            else if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)

               volumne_sell_stops+=m_order.VolumeInitial();

           }

  }

//+------------------------------------------------------------------+

Comments