Pending Orders Grid Three Symbols

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
Pending Orders Grid Three Symbols
ÿþ//+------------------------------------------------------------------+

//|                            Pending Orders Grid Three Symbols.mq5 |

//|                              Copyright © 2019, Vladimir Karputov |

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

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

#property copyright "Copyright © 2019, Vladimir Karputov"

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

#property version   "1.015"

/*

   barabashkakvn Trading engine 3.035

*/

#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>

CPositionInfo  m_position;                   // trade position object

CTrade         m_array_trade[];              // dynamic array of pointers to instances of CTrade class

CSymbolInfo    m_array_symbol[];             // dynamic array of pointers to instances of CSymbolInfo class

CAccountInfo   m_account;                    // account info wrapper

CDealInfo      m_deal;                       // deals object

COrderInfo     m_order;                      // pending orders object

CMoneyFixedMargin m_array_money[];           // dynamic array of pointers to instances of CMoneyFixedMargin class

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

//| Enum Lor or Risk                                                 |

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

enum ENUM_LOT_OR_RISK

  {

   lots_min=0, // Lots Min

   lot=1,      // Constant lot

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

  };

//--- input parameters

input ushort   InpSignalsFrequency  = 9;           // Search signals, in seconds (< "10" -> only on a new bar)

input ENUM_LOT_OR_RISK InpLotOrRisk = lots_min;    // Money management: Lot OR Risk

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

//---

input string   InpSymbol_0_Name     = "USDJPY";    // Symbol #0 Name

input string   InpSymbol_1_Name     = "EURUSD";    // Symbol #1 Name

input string   InpSymbol_2_Name     = "GBPUSD";    // Symbol #2 Name

input ushort   InpSymbol_0_Step     = 35;          // Step Symbol #0, in pips (1.00045-1.00055=1 pips)

input ushort   InpSymbol_1_Step     = 35;          // Step Symbol #1, in pips (1.00045-1.00055=1 pips)

input ushort   InpSymbol_2_Step     = 35;          // Step Symbol #2, in pips (1.00045-1.00055=1 pips)

input double   InpProfitMin         = 15;          // Minimum Profit all positions

//---

input bool     InpPrintLog          = false;       // Print log

input ulong    InpMagic             = 382509036;   // Magic number

//---

ulong  ExtSlippage=10;              // Slippage



double array_ExtStep[];              // Step Symbol #N -> double



double   array_ExtAdjustedPoint[];           // point value adjusted for 3 or 5 points

bool     ExtNeedCloseAll         = false;    //

datetime ExtLastSignals          = 0;        // "0" -> D'1970.01.01 00:00';

datetime ExtPrevBars             = 0;        // "0" -> D'1970.01.01 00:00';

bool     ExtNeedDeleteAll        = false;    // delete all pending orders

bool     ExtWaitingPendingOrder  = false;    // waiting for a pending order

//--- B0:B8:0 B0:0O: ***

//---    0 >B;>65==K5 >@45@0 (5A;8 ?@>H;0 ?@>25@:0 ?> A?@54C) 

//---    ?@>AB> 2KAB@5;8205< 8 >1=C;O5< <0AA82K AB@C:BC@

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

//| Structure Need Pending                                           |

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

struct STRUCT_NEED_PENDING

  {

   ENUM_ORDER_TYPE   pending_type;           // pending order type

   double            volume;                 // pending order volume

   CSymbolInfo      *symbol;                 // symbol

   CMoneyFixedMargin *money;                 // money

   CTrade           *trade;                  // trade

   double            stop_loss;              // pending order stop loss, in pips * ExtAdjustedPoint (if "0.0" -> the ExtStopLoss)

   double            take_profit;            // pending order take profit, in pips * ExtAdjustedPoint (if "0.0" -> the ExtTakeProfit)

   double            price;                  // pending order price

   ulong             magic;                  // magic

   //--- Constructor 

                     STRUCT_NEED_PENDING()

     {

      pending_type               = WRONG_VALUE;

      volume                     = 0.0;

      price                      = 0.0;

      magic                      = 0;

     }

  };

STRUCT_NEED_PENDING SNeedPending[];

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

//| Expert initialization function                                   |

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

int OnInit()

  {

   CSymbolInfo   *symbol_info;

   int size_symbol=ArraySize(m_array_symbol);

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

     {

      symbol_info=GetPointer(m_array_symbol[i]);

      if(CheckPointer(symbol_info)!=POINTER_INVALID)

         delete symbol_info;

     }

   ArrayFree(m_array_symbol);

//---

   CMoneyFixedMargin   *money_fixed_margin;

   int size_money=ArraySize(m_array_money);

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

     {

      money_fixed_margin=GetPointer(m_array_money[i]);

      if(CheckPointer(money_fixed_margin)!=POINTER_INVALID)

         delete money_fixed_margin;

     }

   ArrayFree(m_array_money);

//---

   CTrade   *trade;

   int size_trade=ArraySize(m_array_trade);

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

     {

      trade=GetPointer(m_array_trade[i]);

      if(CheckPointer(trade)!=POINTER_INVALID)

         delete trade;

     }

   ArrayFree(m_array_trade);

//--- init m_array_symbol[]

   string temp_name[3];

   temp_name[0]=InpSymbol_0_Name;

   temp_name[1]=InpSymbol_1_Name;

   temp_name[2]=InpSymbol_2_Name;

   ArrayResize(m_array_symbol,3);

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

     {

      symbol_info=GetPointer(m_array_symbol[i]);

      if(CheckPointer(symbol_info)!=POINTER_INVALID)

        {

         if(!m_array_symbol[i].Name(temp_name[i])) // sets symbol name

            return(INIT_FAILED);

         RefreshRates(m_array_symbol[i]);

        }

      else

        {

         Print(__FUNCTION__,", ERROR: CheckPointer m_array_symbol[",i,"] -> POINTER_INVALID");

         return(INIT_FAILED);

        }

     }

//---

   ArrayResize(m_array_trade,1);

   m_array_trade[0].SetExpertMagicNumber(InpMagic);

   m_array_trade[0].SetMarginMode();

   m_array_trade[0].SetTypeFillingBySymbol(m_array_symbol[0].Name());

   m_array_trade[0].SetDeviationInPoints(ExtSlippage);

//--- tuning for 3 or 5 digits

   ArrayResize(array_ExtAdjustedPoint,3);

   ArrayResize(array_ExtStep,3);

   int digits_adjust[3]={1,1,1};

   ushort temp_step[3];

   temp_step[0]=InpSymbol_0_Step;

   temp_step[1]=InpSymbol_1_Step;

   temp_step[2]=InpSymbol_2_Step;

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

     {

      if(m_array_symbol[i].Digits()==3 || m_array_symbol[i].Digits()==5)

         digits_adjust[i]=10;

      array_ExtAdjustedPoint[i]=m_array_symbol[i].Point()*digits_adjust[i];



      array_ExtStep[i]=temp_step[i]*array_ExtAdjustedPoint[i];

     }

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

   string err_text="";

   if(InpLotOrRisk==lot)

     {

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

         if(!CheckVolumeValue(InpVolumeLotOrRisk,err_text,m_array_symbol[i]))

           {

            //--- 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(InpLotOrRisk==risk)

     {

      if(InpVolumeLotOrRisk<1 || InpVolumeLotOrRisk>100)

        {

         Print("The value for \"Money management\" (",DoubleToString(InpVolumeLotOrRisk,2),") -> invalid parameters");

         Print("   parameter must be in the range: from 1.00 to 100.00");

         return(INIT_FAILED);

        }

      ArrayResize(m_array_money,3);

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

        {

         if(!m_array_money[i].Init(GetPointer(m_array_symbol[i]),Period(),array_ExtAdjustedPoint[i]))

            return(INIT_FAILED);

         m_array_money[i].Percent(InpVolumeLotOrRisk);

        }

     }

//---

   return(INIT_SUCCEEDED);

  }

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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason)

  {

//---



  }

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

//| Expert tick function                                             |

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

void OnTick()

  {

   if(ExtNeedCloseAll)

     {

      int count=0;

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

        {

         if(IsPositionExists(m_array_symbol[i]))

           {

            count++;

            double level;

            if(FreezeStopsLevels(level,m_array_symbol[i],array_ExtAdjustedPoint[i]))

              {

               CloseAllPositions(level,m_array_symbol[i],m_array_trade[0]);  return;

              }

            else

               return;

           }

        }

      if(count==0)

         ExtNeedCloseAll=false;

     }

//---

   if(ExtNeedDeleteAll)

     {

      int count=0;

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

        {

         if(IsPendingOrdersExists(m_array_symbol[i]))

           {

            count++;

            double level;

            if(FreezeStopsLevels(level,m_array_symbol[i],array_ExtAdjustedPoint[i]))

              {

               DeleteAllPendingOrders(level,m_array_symbol[i],m_array_trade[0]);  return;

              }

            else

               return;

           }

        }

      if(count==0)

         ExtNeedDeleteAll=false;

     }

//---

   if(ProfitAllPositions()>=InpProfitMin)

     {

      ExtNeedCloseAll=true;      //

                                 //ExtNeedDeleteAll=true;     // 

      ArrayFree(SNeedPending);

     }

//---

   int size_need_pending=ArraySize(SNeedPending);

   if(size_need_pending>0)

     {

      if(!ExtWaitingPendingOrder)

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

           {

            double level;

            double adjusted_point=0;

            if(SNeedPending[i].symbol.Name()==InpSymbol_0_Name)

               adjusted_point=array_ExtAdjustedPoint[0];

            else if(SNeedPending[i].symbol.Name()==InpSymbol_1_Name)

               adjusted_point=array_ExtAdjustedPoint[1];

            else

               adjusted_point=array_ExtAdjustedPoint[2];

            if(FreezeStopsLevels(level,SNeedPending[i].symbol,adjusted_point))

              {

               ExtWaitingPendingOrder=true;

               PlaceOrders(i,level);

              }

           }

      return;

     }

//---

   if(InpSignalsFrequency>=10) // search for trading signals no more than once every 10 seconds

     {

      datetime time_current=TimeCurrent();

      if(time_current-ExtLastSignals>10)

        {

         //--- search for trading signals

         if(!RefreshRates(m_array_symbol[0]))

           {

            ExtPrevBars=0; return;

           }

         if(!SearchTradingSignals())

           {

            ExtPrevBars=0; return;

           }

         ExtLastSignals=time_current;

        }

     }

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

   datetime time_0=iTime(Symbol(),Period(),0);

   if(time_0==ExtPrevBars)

      return;

   ExtPrevBars=time_0;

   if(InpSignalsFrequency<10) // search for trading signals only at the time of the birth of new bar

     {

      //--- search for trading signals

      if(!SearchTradingSignals())

        {

         ExtPrevBars=0; return;

        }

     }

//---

  }

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

//| TradeTransaction function                                        |

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

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {



//--- 

  }

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

//| Refreshes the symbol quotes data                                 |

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

bool RefreshRates(CSymbolInfo &symbol)

  {

//--- refresh rates

   if(!symbol.RefreshRates())

     {

      Print("RefreshRates error");

      return(false);

     }

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

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

      return(false);

//---

   return(true);

  }

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

//| Check the correctness of the position volume                     |

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

bool CheckVolumeValue(double volume,string &error_description,CSymbolInfo &symbol)

  {

//--- minimal allowed volume for trade operations

   double min_volume=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=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=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);

  }

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

//| Lot Check                                                        |

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

double LotCheck(double lots,CSymbolInfo &symbol)

  {

//--- calculate maximum volume

   double volume=NormalizeDouble(lots,2);

   double stepvol=symbol.LotsStep();

   if(stepvol>0.0)

      volume=stepvol*MathFloor(volume/stepvol);

//---

   double minvol=symbol.LotsMin();

   if(volume<minvol)

      volume=0.0;

//---

   double maxvol=symbol.LotsMax();

   if(volume>maxvol)

      volume=maxvol;

   return(volume);

  }

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

//| Check Freeze and Stops levels                                    |

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

bool FreezeStopsLevels(double &level,CSymbolInfo &symbol,const double ExtAdjustedPoint)

  {

//--- 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(symbol) || !symbol.Refresh())

      return(false);

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

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

   if(freeze_level==0.0)

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

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

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

   if(stop_level==0.0)

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



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

      return(false);



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



   double spread=symbol.Spread()*symbol.Point()*3.0;

   level=(level>spread)?level:spread;

//---

   return(true);

  }

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

//| Print CTrade result                                              |

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

void 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());

  }

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

//| Search trading signals                                           |

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

bool SearchTradingSignals(void)

  {

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

     {

      if(MQLInfoInteger(MQL_TESTER))

         iTime(m_array_symbol[i].Name(),Period(),0);

      if(!IsPendingOrdersExists(m_array_symbol[i]))

         if(RefreshRates(m_array_symbol[i]))

           {

            for(int j=0;j<2;j++)

              {

               int size_need_pending=ArraySize(SNeedPending);

               ArrayResize(SNeedPending,size_need_pending+1);



               SNeedPending[size_need_pending].pending_type    = ORDER_TYPE_BUY_STOP;

               SNeedPending[size_need_pending].symbol          = GetPointer(m_array_symbol[i]);

               if(InpLotOrRisk==risk)

                  SNeedPending[size_need_pending].money        = GetPointer(m_array_money[i]);

               SNeedPending[size_need_pending].trade           = GetPointer(m_array_trade[0]);

               SNeedPending[size_need_pending].stop_loss       = 0.0;

               SNeedPending[size_need_pending].take_profit     = 0.0;

               SNeedPending[size_need_pending].price           = m_array_symbol[i].Ask()+array_ExtStep[i]*(j+1.0);

               SNeedPending[size_need_pending].magic           = InpMagic;



               size_need_pending=ArraySize(SNeedPending);

               ArrayResize(SNeedPending,size_need_pending+1);



               SNeedPending[size_need_pending].pending_type    = ORDER_TYPE_SELL_STOP;

               SNeedPending[size_need_pending].symbol          = GetPointer(m_array_symbol[i]);

               if(InpLotOrRisk==risk)

                  SNeedPending[size_need_pending].money        = GetPointer(m_array_money[i]);

               SNeedPending[size_need_pending].trade           = GetPointer(m_array_trade[0]);

               SNeedPending[size_need_pending].stop_loss       = 0.0;

               SNeedPending[size_need_pending].take_profit     = 0.0;

               SNeedPending[size_need_pending].price           = m_array_symbol[i].Bid()-array_ExtStep[i]*(j+1.0);

               SNeedPending[size_need_pending].magic           = InpMagic;

              }

           }

     }

//---

   return(true);

  }

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

//| Delete all pending orders                                        |

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

void DeleteAllPendingOrders(const double level,CSymbolInfo &symbol,CTrade &trade)

  {

   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()==symbol.Name() && m_order.Magic()==InpMagic)

           {

            if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)

              {

               if(m_order.PriceOpen()-symbol.Ask()>level)

                 {

                  if(!trade.OrderDelete(m_order.Ticket()))

                     int d=0;

                 }

               continue;

              }

            if(m_order.OrderType()==ORDER_TYPE_SELL_STOP)

              {

               if(symbol.Bid()-m_order.PriceOpen()>level)

                 {

                  if(!trade.OrderDelete(m_order.Ticket()))

                     int d=0;

                 }

               continue;

              }

           }

  }

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

//| Is pendinf orders exists                                         |

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

bool IsPendingOrdersExists(CSymbolInfo &symbol)

  {

   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()==symbol.Name() && m_order.Magic()==InpMagic)

            return(true);

//---

   return(false);

  }

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

//| Place Orders                                                     |

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

void PlaceOrders(const int index,const 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

*/

//--- buy stop

   if(SNeedPending[index].pending_type==ORDER_TYPE_BUY_STOP)

     {

      double price=SNeedPending[index].price;

      if(price-SNeedPending[index].symbol.Ask()<level) // check price

         price=SNeedPending[index].symbol.Ask()+level;



      double sl=SNeedPending[index].stop_loss;

      if(sl<=0.0)// check sl

         sl=0.0;

      else if(price-sl<level)

         sl=price-level;



      double tp=SNeedPending[index].take_profit;

      if(tp<=0.0) // check tp

         tp=0.0;

      else if(tp-price<level)

         tp=price+level;



      PendingOrder(index,price,sl,tp);

      ArrayRemove(SNeedPending,index,1);

      ExtWaitingPendingOrder=false;

      return;

     }

//--- sell stop

   if(SNeedPending[index].pending_type==ORDER_TYPE_SELL_STOP)

     {

      double price=SNeedPending[index].price;

      if(SNeedPending[index].symbol.Bid()-price<level) // check price

         price=SNeedPending[index].symbol.Bid()-level;



      double sl=SNeedPending[index].stop_loss;

      if(sl<=0.0) // check sl

         sl=0.0;

      else if(sl-price<level)

         sl=price+level;



      double tp=SNeedPending[index].take_profit;

      if(tp<=0.0) // check tp

         tp=0.0;

      else if(price-tp<level)

         tp=price-level;



      PendingOrder(index,price,sl,tp);

      ArrayRemove(SNeedPending,index,1);

      ExtWaitingPendingOrder=false;

      return;

     }

  }

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

//| Pending order                                                    |

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

bool PendingOrder(const int index,double price,double sl,double tp)

  {

   SNeedPending[index].trade.SetExpertMagicNumber(SNeedPending[index].magic);

   sl=SNeedPending[index].symbol.NormalizePrice(sl);

   tp=SNeedPending[index].symbol.NormalizePrice(tp);

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

   ENUM_ORDER_TYPE check_order_type=-1;

   switch(SNeedPending[index].pending_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(InpLotOrRisk==risk)

     {

      bool error=false;

      long_lot=SNeedPending[index].money.CheckOpenLong(SNeedPending[index].symbol.Ask(),sl);

      if(InpPrintLog)

         Print("sl=",DoubleToString(sl,SNeedPending[index].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(InpPrintLog)

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

         error=true;

        }

      //---

      short_lot=SNeedPending[index].money.CheckOpenShort(SNeedPending[index].symbol.Bid(),sl);

      if(InpPrintLog)

         Print("sl=",DoubleToString(sl,SNeedPending[index].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(InpPrintLog)

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

         error=true;

        }

      //---

      if(error)

         return(false);

     }

   else if(InpLotOrRisk==lot)

     {

      long_lot=InpVolumeLotOrRisk;

      short_lot=InpVolumeLotOrRisk;

     }

   else if(InpLotOrRisk==lots_min)

     {

      long_lot=SNeedPending[index].symbol.LotsMin();

      short_lot=SNeedPending[index].symbol.LotsMin();

     }

   else

      return(false);

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

   double check_price=0;

   double check_lot=0;

   check_price=price;

   if(check_order_type==ORDER_TYPE_BUY)

     {

      //check_price=SNeedPending[index].symbol.Ask();

      check_lot=long_lot;

     }

   else

     {

      //check_price=SNeedPending[index].symbol.Bid();

      check_lot=short_lot;

     }

//---

   if(SNeedPending[index].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,

                          GetPointer(SNeedPending[index].symbol));

      if(volume_buys+volume_sells+

         volume_buy_limits+volume_sell_limits+

         volume_buy_stops+volume_sell_stops+check_lot>SNeedPending[index].symbol.LotsLimit())

        {

         if(InpPrintLog)

            Print("#0 ,",EnumToString(SNeedPending[index].pending_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(SNeedPending[index].symbol.LotsLimit(),2),")");

         return(false);

        }

     }

   int limit_orders=m_account.LimitOrders();

   if(limit_orders>0)

      if(limit_orders<=CalculateAllPendingOrders()+1)

         return(false);

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

   double free_margin_check=m_account.FreeMarginCheck(SNeedPending[index].symbol.Name(),

                                                      check_order_type,check_lot,check_price);

   double margin_check=m_account.MarginCheck(SNeedPending[index].symbol.Name(),

                                             check_order_type,check_lot,price);

   if(free_margin_check*2.0>margin_check)

     {

      datetime expiration=TimeCurrent()+60*60+1;

      if(SNeedPending[index].trade.OrderOpen(SNeedPending[index].symbol.Name(),

         SNeedPending[index].pending_type,check_lot,0.0,

         SNeedPending[index].symbol.NormalizePrice(price),

         SNeedPending[index].symbol.NormalizePrice(sl),

         SNeedPending[index].symbol.NormalizePrice(tp),ORDER_TIME_SPECIFIED,expiration))

        {

         if(SNeedPending[index].trade.ResultOrder()==0)

           {

            if(InpPrintLog)

               Print("#1 ",EnumToString(SNeedPending[index].pending_type)," -> false. Result Retcode: ",SNeedPending[index].trade.ResultRetcode(),

                     ", description of result: ",SNeedPending[index].trade.ResultRetcodeDescription());

            if(InpPrintLog)

               PrintResultTrade(SNeedPending[index].trade,SNeedPending[index].symbol);

            return(false);

           }

         else

           {

            if(InpPrintLog)

               Print("#2 ",EnumToString(SNeedPending[index].pending_type)," -> true. Result Retcode: ",SNeedPending[index].trade.ResultRetcode(),

                     ", description of result: ",SNeedPending[index].trade.ResultRetcodeDescription());

            if(InpPrintLog)

               PrintResultTrade(SNeedPending[index].trade,SNeedPending[index].symbol);

            return(true);

           }

        }

      else

        {

         if(InpPrintLog)

            Print("#3 ",EnumToString(SNeedPending[index].pending_type)," -> false. Result Retcode: ",SNeedPending[index].trade.ResultRetcode(),

                  ", description of result: ",SNeedPending[index].trade.ResultRetcodeDescription());

         if(InpPrintLog)

            PrintResultTrade(SNeedPending[index].trade,SNeedPending[index].symbol);

         return(false);

        }

     }

   else

     {

      if(InpPrintLog)

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

      return(false);

     }

//---

   return(false);

  }

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

//| 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,

                         CSymbolInfo *symbol)

  {

   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()==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()==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();

           }

  }

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

//| Is position exists                                               |

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

bool IsPositionExists(CSymbolInfo &symbol)

  {

   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()==symbol.Name() && m_position.Magic()==InpMagic)

            return(true);

//---

   return(false);

  }

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

//| Close all positions                                              |

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

void CloseAllPositions(const double level,CSymbolInfo &symbol,CTrade &trade)

  {

/*

   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=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()==symbol.Name() && m_position.Magic()==InpMagic)

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               bool take_profit_level=(m_position.TakeProfit()!=0.0 && m_position.TakeProfit()-m_position.PriceCurrent()>=level) || m_position.TakeProfit()==0.0;

               bool stop_loss_level=(m_position.StopLoss()!=0.0 && m_position.PriceCurrent()-m_position.StopLoss()>=level) || m_position.StopLoss()==0.0;

               if(take_profit_level && stop_loss_level)

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

              }

            if(m_position.PositionType()==POSITION_TYPE_SELL)

              {

               bool take_profit_level=(m_position.TakeProfit()!=0.0 && m_position.PriceCurrent()-m_position.TakeProfit()>=level) || m_position.TakeProfit()==0.0;

               bool stop_loss_level=(m_position.StopLoss()!=0.0 && m_position.StopLoss()-m_position.PriceCurrent()>=level) || m_position.StopLoss()==0.0;

               if(take_profit_level && stop_loss_level)

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

              }

           }

  }

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

//| Profit all positions                                             |

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

double ProfitAllPositions(void)

  {

   double profit=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_array_symbol[0].Name() || 

            m_position.Symbol()==m_array_symbol[1].Name()||

            m_position.Symbol()==m_array_symbol[2].Name()) &&m_position.Magic()==InpMagic)

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

//---

   return(profit);

  }

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

//| Calculate all pending orders                                     |

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

int CalculateAllPendingOrders(void)

  {

   int count=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

         count++;

//---

   return(count);

  }

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

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---