Author: runik
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
11 Views
0 Downloads
0 Favorites
Fluctuate
ÿþ//+------------------------------------------------------------------+

//|                           Fluctuate(barabashkakvn's edition).mq5 |

//|                                                Copyright © runik |

//|                                                  ngb2008@mail.ru |

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

#property copyright "runik"

#property link      "ngb2008@mail.ru"

#property version   "1.000"

//---

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>  

#include <Trade\AccountInfo.mqh>

#include <Trade\OrderInfo.mqh>

#include <Expert\Money\MoneyFixedMargin.mqh>

CPositionInfo  m_position;                   // trade position object

CTrade         m_trade;                      // trading object

CSymbolInfo    m_symbol;                     // symbol info object

CAccountInfo   m_account;                    // account info wrapper

COrderInfo     m_order;                      // pending orders object

CMoneyFixedMargin *m_money;

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

//| Enum Lor or Risk                                                 |

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

enum ENUM_LOT_OR_RISK

  {

   lot=0,   // Constant lot

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

  };

//--- input parameters

input ushort   InpStopLoss       = 50;       // Stop Loss, in pips (1.00045-1.00055=1 pips)

input ushort   InpTakeProfit     = 50;       // Take Profit, in pips (1.00045-1.00055=1 pips)

input ushort   InpTrailingStop   = 5;        // Trailing Stop (min distance from price to Stop Loss, in pips

input ushort   InpTrailingStep   = 5;        // Trailing Step, in pips (1.00045-1.00055=1 pips)

input ENUM_LOT_OR_RISK IntLotOrRisk=lot;     // Money management: Lot OR Risk (only for first positions)

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

//--- trading logic

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

input double   InpLotCoef        = 2.0;      // Lot coefficient (for a series of deals)

input bool     InpMultiplyLotCoef= false;    // Multiply the volume of all positions

input uchar    InpMaxPositions   = 9;        // Maximum number of positions

input double   InpMaxTotalVolume = 50.0;     // Maximum volume of all positions

input double   InpProfitTarget   = 50.0;     // Profit target in money ("0.0" -> OFF)

input double   InpMinEquity      = 30.0;     // Minimum Equity (in percent of balance) -> pause in trade

input bool     InpCloseAll       = false;    // Close all positions at startup

//---

input ulong    m_magic           = 35814657; // magic number

input uchar    InpStartHour      = 10;       // Start hour

input uchar    InpEndHour        = 20;       // End hour

//---

ulong  m_slippage=10;                // slippage

double ExtStopLoss=0.0;

double ExtTakeProfit=0.0;

double ExtTrailingStop=0.0;

double ExtTrailingStep=0.0;

double ExtStep=0.0;

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

bool   m_delete_all_pending   = false;

bool   m_need_open_sell_stop  = false;

bool   m_need_open_buy_stop   = false;

double m_last_position_price  = -1;

double m_last_position_volume = -1;

datetime PrevBars=0;

bool   m_close_all;

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

//| Expert initialization function                                   |

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

int OnInit()

  {

   m_last_position_price   = -1;

   m_last_position_volume  = -1;

   m_close_all             = InpCloseAll;

//---

   if(InpTrailingStop!=0 && InpTrailingStep==0)

     {

      string err_text=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")?

                      ""@59;8=3 =52>7<>65=: ?0@0<5B@ \"Trailing Step\" @025= =C;N!":

                      "Trailing is not possible: parameter \"Trailing Step\" is zero!";

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

        }

     }

//---

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

      return(INIT_FAILED);

   RefreshRates();

//---

   m_trade.SetExpertMagicNumber(m_magic);

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(m_symbol.Name());

   m_trade.SetDeviationInPoints(m_slippage);

//--- tuning for 3 or 5 digits

   int digits_adjust=1;

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

      digits_adjust=10;

   m_adjusted_point=m_symbol.Point()*digits_adjust;



   ExtStopLoss       = InpStopLoss        * m_adjusted_point;

   ExtTakeProfit     = InpTakeProfit      * m_adjusted_point;

   ExtTrailingStop   = InpTrailingStop    * m_adjusted_point;

   ExtTrailingStep   = InpTrailingStep    * m_adjusted_point;

   ExtStep           = InpStep            * m_adjusted_point;

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

   string err_text="";

   if(IntLotOrRisk==lot)

     {

      if(!CheckVolumeValue(InpVolumeLorOrRisk,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(InpVolumeLorOrRisk);

        }

      else

        {

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

         return(INIT_FAILED);

        }

     }

//---

   return(INIT_SUCCEEDED);

  }

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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason)

  {

//---

   if(m_money!=NULL)

      delete m_money;

  }

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

//| Expert tick function                                             |

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

void OnTick()

  {

   if(m_close_all)

     {

      CloseAllPositions();

      DeleteAllPendingOrders();

      m_close_all=false;

     }

//---

   Trailing();

//---

   if(InpProfitTarget>0.0)

      if(ProfitAllPositions()>=InpProfitTarget)

        {

         CloseAllPositions();

         DeleteAllPendingOrders();

        }

//---

   if(m_need_open_buy_stop)

     {

      if(RefreshRates())

         if(PendingOrderCheck(ORDER_TYPE_BUY_STOP))

            m_need_open_buy_stop=false;

     }

   if(m_need_open_sell_stop)

     {

      if(RefreshRates())

         if(PendingOrderCheck(ORDER_TYPE_SELL_STOP))

            m_need_open_sell_stop=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;

     }

//---

   MqlDateTime STime0;

   TimeToStruct(time_0,STime0);

   if(STime0.hour<InpStartHour || STime0.hour>=InpEndHour)

     {

      DeleteAllPendingOrders();

      return;

     }

//---

   int      count_buys        = 0;

   double   volumne_buys      = 0.0;

   int      count_sells       = 0;

   double   volumne_sells     = 0.0;

   CalculateAllPositions(count_buys,volumne_buys,count_sells,volumne_sells);



   int count_buy_stops        = 0;

   double volumne_buy_stops   = 0.0;

   int count_sell_stops       = 0;

   double volumne_sell_stops  = 0.0;

   CalculateAllPendingOrders(count_buy_stops,volumne_buy_stops,count_sell_stops,volumne_sell_stops);

//--- beginning of the trading cycle

   if(count_buys+count_sells==0)

     {

      DeleteAllPendingOrders();

      m_last_position_price=-1;

      m_last_position_volume=-1;

      //---

      double close_array[];

      ArraySetAsSeries(close_array,true);

      if(CopyClose(m_symbol.Name(),Period(),0,3,close_array)!=3)

         return;

      //---

      if(!RefreshRates())

        {

         PrevBars=0;

         return;

        }

      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;



      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)

        {

         PrevBars=0;

         return;

        }

      //---

      if(close_array[0]>close_array[1])

        {

         //--- open buy

         double price=m_symbol.Ask();

         double sl=(InpStopLoss==0)?0.0:price-ExtStopLoss;

         double tp=(InpTakeProfit==0)?0.0:price+ExtTakeProfit;

         if(((sl!=0 && ExtStopLoss>=stop_level) || sl==0.0) && ((tp!=0 && ExtTakeProfit>=stop_level) || tp==0.0))

           {

            OpenBuy(sl,tp);

            return;

           }

        }

      else

        {

         //--- open sell

         double price=m_symbol.Bid();

         double sl=(InpStopLoss==0)?0.0:price+ExtStopLoss;

         double tp=(InpTakeProfit==0)?0.0:price-ExtTakeProfit;

         if(((sl!=0 && ExtStopLoss>=stop_level) || sl==0.0) && ((tp!=0 && ExtTakeProfit>=stop_level) || tp==0.0))

           {

            OpenSell(sl,tp);

            return;

           }

        }

     }

  }

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

//| TradeTransaction function                                        |

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

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {

   double res=0.0;

   int losses=0.0;

//--- get transaction type as enumeration value 

   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;

//--- if transaction is result of addition of the transaction in history

   if(type==TRADE_TRANSACTION_DEAL_ADD)

     {

      long     deal_ticket       =0;

      long     deal_order        =0;

      long     deal_time         =0;

      long     deal_time_msc     =0;

      long     deal_type         =-1;

      long     deal_entry        =-1;

      long     deal_magic        =0;

      long     deal_reason       =-1;

      long     deal_position_id  =0;

      double   deal_volume       =0.0;

      double   deal_price        =0.0;

      double   deal_commission   =0.0;

      double   deal_swap         =0.0;

      double   deal_profit       =0.0;

      string   deal_symbol       ="";

      string   deal_comment      ="";

      string   deal_external_id  ="";

      if(HistoryDealSelect(trans.deal))

        {

         deal_ticket       =HistoryDealGetInteger(trans.deal,DEAL_TICKET);

         deal_order        =HistoryDealGetInteger(trans.deal,DEAL_ORDER);

         deal_time         =HistoryDealGetInteger(trans.deal,DEAL_TIME);

         deal_time_msc     =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);

         deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);

         deal_entry        =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);

         deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);

         deal_reason       =HistoryDealGetInteger(trans.deal,DEAL_REASON);

         deal_position_id  =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);



         deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);

         deal_price        =HistoryDealGetDouble(trans.deal,DEAL_PRICE);

         deal_commission   =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);

         deal_swap         =HistoryDealGetDouble(trans.deal,DEAL_SWAP);

         deal_profit       =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);



         deal_symbol       =HistoryDealGetString(trans.deal,DEAL_SYMBOL);

         deal_comment      =HistoryDealGetString(trans.deal,DEAL_COMMENT);

         deal_external_id  =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);

        }

      else

         return;

      if(deal_symbol==m_symbol.Name() && deal_magic==m_magic)

         if(deal_entry==DEAL_ENTRY_IN && (deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL))

           {

            m_last_position_price=deal_price;

            m_last_position_volume=deal_volume;

            DeleteAllPendingOrders();

            if(deal_type==DEAL_TYPE_BUY)

               m_need_open_sell_stop=true;

            else if(deal_type==DEAL_TYPE_SELL)

               m_need_open_buy_stop=true;

           }

     }

  }

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

//| Refreshes the symbol quotes data                                 |

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

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

  }

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

//| Calculate all positions                                          |

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

void CalculateAllPositions(int &count_buys,double &volumne_buys,

                           int &count_sells,double &volumne_sells)

  {

   count_buys  =0;   volumne_buys   = 0.0;

   count_sells =0;   volumne_sells  = 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() && m_position.Magic()==m_magic)

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               count_buys++;

               volumne_buys+=m_position.Volume();

               continue;

              }

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

              {

               count_sells++;

               volumne_sells+=m_position.Volume();

              }

           }

  }

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

//| Calculate all pending orders                                     |

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

void CalculateAllPendingOrders(int &count_buy_stops,double &volumne_buy_stops,

                               int &count_sell_stops,double &volumne_sell_stops)

  {

   count_buy_stops   = 0;

   volumne_buy_stops = 0.0;

   count_sell_stops  = 0;

   volumne_sell_stops= 0.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()==m_magic)

           {

            if(m_order.OrderType()==ORDER_TYPE_BUY_STOP)

               count_buy_stops++;

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

               count_sell_stops++;

           }

  }

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

//| Open Buy position                                                |

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

void OpenBuy(double sl,double tp)

  {

   sl=m_symbol.NormalizePrice(sl);

   tp=m_symbol.NormalizePrice(tp);



   double long_lot=0.0;

   if(IntLotOrRisk==risk)

     {

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

      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)

        {

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

         return;

        }

     }

   else if(IntLotOrRisk==lot)

      long_lot=InpVolumeLorOrRisk;

   else

      return;

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

   double free_margin_check= m_account.FreeMarginCheck(m_symbol.Name(),ORDER_TYPE_BUY,long_lot,m_symbol.Ask());

   double margin_check     = m_account.MarginCheck(m_symbol.Name(),ORDER_TYPE_SELL,long_lot,m_symbol.Bid());

   if(free_margin_check>margin_check)

     {

      if(m_trade.Buy(long_lot,m_symbol.Name(),m_symbol.Ask(),sl,tp))

        {

         if(m_trade.ResultDeal()==0)

           {

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

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

            PrintResultTrade(m_trade,m_symbol);

           }

         else

           {

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

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

            PrintResultTrade(m_trade,m_symbol);

           }

        }

      else

        {

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

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

         PrintResultTrade(m_trade,m_symbol);

        }

     }

   else

     {

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

      return;

     }

//---

  }

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

//| Open Sell position                                               |

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

void OpenSell(double sl,double tp)

  {

   sl=m_symbol.NormalizePrice(sl);

   tp=m_symbol.NormalizePrice(tp);



   double short_lot=0.0;

   if(IntLotOrRisk==risk)

     {

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

      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)

        {

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

         return;

        }

     }

   else if(IntLotOrRisk==lot)

      short_lot=InpVolumeLorOrRisk;

   else

      return;

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

   double free_margin_check= m_account.FreeMarginCheck(m_symbol.Name(),ORDER_TYPE_SELL,short_lot,m_symbol.Bid());

   double margin_check     = m_account.MarginCheck(m_symbol.Name(),ORDER_TYPE_SELL,short_lot,m_symbol.Bid());

   if(free_margin_check>margin_check)

     {

      if(m_trade.Sell(short_lot,m_symbol.Name(),m_symbol.Bid(),sl,tp))

        {

         if(m_trade.ResultDeal()==0)

           {

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

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

            PrintResultTrade(m_trade,m_symbol);

           }

         else

           {

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

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

            PrintResultTrade(m_trade,m_symbol);

           }

        }

      else

        {

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

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

         PrintResultTrade(m_trade,m_symbol);

        }

     }

   else

     {

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

      return;

     }

//---

  }

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

//| Delete all pending orders                                        |

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

void DeleteAllPendingOrders(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()==m_magic)

            m_trade.OrderDelete(m_order.Ticket());

  }

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

//| Pending order                                                    |

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

bool PendingOrderCheck(ENUM_ORDER_TYPE order_type)

  {

   if(!RefreshRates())

     {

      PrevBars=0;

      return(false);

     }

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

   if(freeze_level==0.0)

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

   freeze_level*=1.1;



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

   if(stop_level==0.0)

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

   stop_level*=1.1;



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

     {

      PrevBars=0;

      return(false);

     }

//--- check number of positions and volume of all positions

   int      count_buys        = 0;

   double   volumne_buys      = 0.0;

   int      count_sells       = 0;

   double   volumne_sells     = 0.0;

   CalculateAllPositions(count_buys,volumne_buys,count_sells,volumne_sells);



   int count_buy_stops        = 0;

   double volumne_buy_stops   = 0.0;

   int count_sell_stops       = 0;

   double volumne_sell_stops  = 0.0;

   CalculateAllPendingOrders(count_buy_stops,volumne_buy_stops,count_sell_stops,volumne_sell_stops);



   if(count_buys+count_sells+count_buy_stops+count_sell_stops>=InpMaxPositions || 

      volumne_buys+volumne_sells+volumne_buy_stops+volumne_sell_stops>=InpMaxTotalVolume)

      return(false);

//--- calculate and check lot

   double lot=0.0;

   if(!InpMultiplyLotCoef)

     {

      lot=(m_last_position_volume!=-1)?m_last_position_volume*InpLotCoef:m_symbol.LotsMin();

     }

   else

     {

      lot=(volumne_buys+volumne_sells)*InpLotCoef;

     }

   lot=LotCheck(lot);

   if(lot==0.0 || volumne_buys+volumne_sells+volumne_buy_stops+volumne_sell_stops+lot>=InpMaxTotalVolume)

      return(false);

//---

   if(order_type==ORDER_TYPE_BUY_STOP)

     {

      double price=(m_last_position_price!=-1)?m_last_position_price:m_symbol.Ask();

      price=price+ExtStep+(m_symbol.Ask()-m_symbol.Bid());

      if(price-m_symbol.Ask()>freeze_level)

        {

         double sl=(InpStopLoss==0)?0.0:price-ExtStopLoss;

         double tp=(InpTakeProfit==0)?0.0:price+ExtTakeProfit;

         if(((sl!=0 && ExtStopLoss>=stop_level) || sl==0.0) && ((tp!=0 && ExtTakeProfit>=stop_level) || tp==0.0))

           {

            return(PendingOrder(order_type,lot,price,sl,tp));

           }

        }

     }

   else if(order_type==ORDER_TYPE_SELL_STOP)

     {

      double price=(m_last_position_price!=-1)?m_last_position_price:m_symbol.Bid();

      price=price-ExtStep-(m_symbol.Ask()-m_symbol.Bid());

      if(m_symbol.Bid()-price>freeze_level)

        {

         double sl=(InpStopLoss==0)?0.0:price+ExtStopLoss;

         double tp=(InpTakeProfit==0)?0.0:price-ExtTakeProfit;

         if(((sl!=0 && ExtStopLoss>=stop_level) || sl==0.0) && ((tp!=0 && ExtTakeProfit>=stop_level) || tp==0.0))

           {

            return(PendingOrder(order_type,lot,price,sl,tp));

           }

        }

      int d=0;

     }

//---

   return(false);

  }

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

//| Pending order                                                    |

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

bool PendingOrder(ENUM_ORDER_TYPE order_type,double lot,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_STOP:

         check_order_type=ORDER_TYPE_BUY;

         break;

      case ORDER_TYPE_SELL_STOP:

         check_order_type=ORDER_TYPE_SELL;

         break;

      default:

         return(false);

         break;

     }

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

   double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(),check_order_type,lot,price);

   if(free_margin_check>0.0)

     {

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

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

        {

         if(m_trade.ResultOrder()==0)

           {

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

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

            PrintResultTrade(m_trade,m_symbol);

            return(false);

           }

         else

           {

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

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

            PrintResultTrade(m_trade,m_symbol);

            return(true);

           }

        }

      else

        {

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

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

         PrintResultTrade(m_trade,m_symbol);

         return(false);

        }

     }

   else

     {

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

      return(false);

     }

//---

   return(false);

  }

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

//| Trailing                                                         |

//|   InpTrailingStop: min distance from price to Stop Loss          |

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

void Trailing()

  {

   if(InpTrailingStop==0)

      return;

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

      if(m_position.SelectByIndex(i))

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

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               if(m_position.PriceCurrent()-m_position.PriceOpen()>ExtTrailingStop+ExtTrailingStep)

                  if(m_position.StopLoss()<m_position.PriceCurrent()-(ExtTrailingStop+ExtTrailingStep))

                    {

                     if(!m_trade.PositionModify(m_position.Ticket(),

                        m_symbol.NormalizePrice(m_position.PriceCurrent()-ExtTrailingStop),

                        m_position.TakeProfit()))

                        Print("Modify ",m_position.Ticket(),

                              " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

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

                     RefreshRates();

                     m_position.SelectByIndex(i);

                     PrintResultModify(m_trade,m_symbol,m_position);

                     continue;

                    }

              }

            else

              {

               if(m_position.PriceOpen()-m_position.PriceCurrent()>ExtTrailingStop+ExtTrailingStep)

                  if((m_position.StopLoss()>(m_position.PriceCurrent()+(ExtTrailingStop+ExtTrailingStep))) || 

                     (m_position.StopLoss()==0))

                    {

                     if(!m_trade.PositionModify(m_position.Ticket(),

                        m_symbol.NormalizePrice(m_position.PriceCurrent()+ExtTrailingStop),

                        m_position.TakeProfit()))

                        Print("Modify ",m_position.Ticket(),

                              " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

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

                     RefreshRates();

                     m_position.SelectByIndex(i);

                     PrintResultModify(m_trade,m_symbol,m_position);

                    }

              }



           }

  }

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

//| Lot Check                                                        |

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

double LotCheck(double lots)

  {

//--- calculate maximum volume

   double volume=NormalizeDouble(lots,2);

   double stepvol=m_symbol.LotsStep();

   if(stepvol>0.0)

      volume=stepvol*MathFloor(volume/stepvol);

//---

   double minvol=m_symbol.LotsMin();

   if(volume<minvol)

      volume=0.0;

//---

   double maxvol=m_symbol.LotsMax();

   if(volume>maxvol)

      volume=maxvol;

   return(volume);

  }

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

//| Print CTrade result                                              |

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

void PrintResultTrade(CTrade &trade,CSymbolInfo &symbol)

  {

   Print("File: ",__FILE__,", symbol: ",m_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());

  }

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

//| Print CTrade result                                              |

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

void PrintResultModify(CTrade &trade,CSymbolInfo &symbol,CPositionInfo &position)

  {

   Print("File: ",__FILE__,", symbol: ",m_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());

   Print("Price of position opening: "+DoubleToString(position.PriceOpen(),symbol.Digits()));

   Print("Price of position's Stop Loss: "+DoubleToString(position.StopLoss(),symbol.Digits()));

   Print("Price of position's Take Profit: "+DoubleToString(position.TakeProfit(),symbol.Digits()));

   Print("Current price by position: "+DoubleToString(position.PriceCurrent(),symbol.Digits()));

  }

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

//| Profit all positions                                             |

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

double ProfitAllPositions()

  {

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

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

//---

   return(profit);

  }

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

//| Close all positions                                              |

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

void 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()==m_magic)

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

  }

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

Comments