Crossing bar number 1

Author: Copyright © 2022, Vladimir Karputov
Price Data Components
Series array that contains tick volumes of each bar
Indicators Used
Moving average indicator
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Crossing bar number 1
ÿþ//+------------------------------------------------------------------+

//|                                        Crossing bar number 1.mq5 |

//|                              Copyright © 2022, Vladimir Karputov |

//|                      https://www.mql5.com/en/users/barabashkakvn |

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

#property copyright "Copyright © 2022, Vladimir Karputov"

#property link      "https://www.mql5.com/en/users/barabashkakvn"

#property version   "1.003"

#property description "No Take Profit, No Stop Loss and No Trailing"

/*

   barabashkakvn Trading engine 4.015

*/

/*

   !B@0B538O ?> ?5@5A5G5=8N 8=48:0B>@0 iMA (Moving Average') 10@><: ?5@5A5G5=85 (F5=0 10@0 'Close') ?@>25@O5BAO =0 :064>< B8:5,

   0 2>B 7=0G5=85 8=48:0B>@0 15@QBAO A 10@0 #1. !>25B=8: B>@3C5B (=018@05B ?>78F88) 2 >4=C AB>@>=C - 5A;8 ?>O28;AO

   ?@>B82>?>;>6=K9 A83=0;, B> 70:@KB85 1C45B 2 A;CG05 >1I59 ?>;>68B5;L=>9 ?@81K;8.



   "0: :0: =5B =8 "59: @>D8B, =8 !B>? ;>AA, =8 "@59;8=30, B> 70:@KB85 <>65B 1KBL ?@8 4>AB865=88 C1KB:>2 7=0G5=8O 'Max Loss'

   8;8 ?@8 4>AB865=88 <8=8<0;L=>9 ?@81K;8 'Min Profit'.



   Strategy for crossing the iMA (Moving Average') indicator by a bar: the crossing (price of the 'Close' bar) is checked on each tick,

   but the indicator value is taken from bar #1. The EA trades (gains positions) in one direction - if an

   opposite signal appears, then the closure will be in case of a total positive profit.



   Since there is no Take Profit, no Stop Loss, no Trailing, the closing can be when the loss reaches the 'Max Loss'

   value or when the minimum profit 'Min Profit' is reached.

*/

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>

#include <Trade\AccountInfo.mqh>

#include <Trade\DealInfo.mqh>

#include <Expert\Money\MoneyFixedMargin.mqh>

//---

CPositionInfo  m_position;                   // object of CPositionInfo class

CTrade         m_trade;                      // object of CTrade class

CSymbolInfo    m_symbol;                     // object of CSymbolInfo class

CAccountInfo   m_account;                    // object of CAccountInfo class

CDealInfo      m_deal;                       // object of CDealInfo class

CMoneyFixedMargin *m_money;                  // object 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 (range: from 1.00 to 100.00)

  };

//--- input parameters

input group             "Trading settings"

input ENUM_TIMEFRAMES      InpWorkingPeriod        = PERIOD_CURRENT; // Working timeframe

input double               InpMaxLoss              = 20;             // Max Loss (in deposit money)

input double               InpMinProfit            = 20;             // Min Profit (in deposit money)

input group             "Position size management (lot calculation)"

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

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

input group             "MA"

input int                  Inp_MA_ma_period        = 12;             // MA: averaging period

input int                  Inp_MA_ma_shift         = 0;              // MA: horizontal shift

input ENUM_MA_METHOD       Inp_MA_ma_method        = MODE_SMA;       // MA: smoothing type

input ENUM_APPLIED_PRICE   Inp_MA_applied_price    = PRICE_CLOSE;    // MA: type of price

input group             "Additional features"

input bool                 InpPrintLog             = true;           // Print log

input ulong                InpDeviation            = 10;             // Deviation, in Points (1.00045-1.00055=10 points)

input ulong                InpMagic                = 478965410;      // Magic number

//---

int      handle_iMA;                            // variable for storing the handle of the iMA indicator



bool     m_need_close_all           = false;    // close all positions

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

bool     m_init_error               = false;    // error on InInit

//--- the tactic is this: for positions we strictly monitor the result, ***

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

//| Structure Positions                                              |

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

struct STRUCT_POSITION

  {

   ENUM_POSITION_TYPE pos_type;              // position type

   bool              waiting_transaction;    // waiting transaction, "true" -> it's forbidden to trade, we expect a transaction

   ulong             waiting_order_ticket;   // waiting order ticket, ticket of the expected order

   bool              transaction_confirmed;  // transaction confirmed, "true" -> transaction confirmed

   //--- Constructor

                     STRUCT_POSITION()

     {

      pos_type                   = WRONG_VALUE;

      waiting_transaction        = false;

      waiting_order_ticket       = 0;

      transaction_confirmed      = false;

     }

  };

STRUCT_POSITION SPosition[];

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

//| Expert initialization function                                   |

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

int OnInit()

  {

//--- forced initialization of variables

   m_need_close_all           = false;    // close all positions

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

   m_init_error               = false;    // error on InInit

//---

   ResetLastError();

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

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");

      return(INIT_FAILED);

     }

   RefreshRates();

//---

   m_trade.SetExpertMagicNumber(InpMagic);

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(m_symbol.Name());

   m_trade.SetDeviationInPoints(InpDeviation);

//--- tuning for 3 or 5 digits

   int digits_adjust=1;

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

      digits_adjust=10;

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

   string err_text="";

   if(InpLotOrRisk==lot)

     {

      if(!CheckVolumeValue(InpVolumeLotOrRisk,err_text))

        {

         if(MQLInfoInteger(MQL_TESTER)) // when testing, we will only output to the log about incorrect input parameters

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

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

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

         //---

         m_init_error=true;

         return(INIT_SUCCEEDED);

        }

     }

   else

      if(InpLotOrRisk==risk)

        {

         if(m_money!=NULL)

            delete m_money;

         m_money=new CMoneyFixedMargin;

         if(m_money!=NULL)

           {

            if(InpVolumeLotOrRisk<1 || InpVolumeLotOrRisk>100)

              {

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

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

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

               //---

               m_init_error=true;

               return(INIT_SUCCEEDED);

              }

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

              {

               Print(__FILE__," ",__FUNCTION__,", ERROR: CMoneyFixedMargin.Init");

               //---

               m_init_error=true;

               return(INIT_SUCCEEDED);

              }

            m_money.Percent(InpVolumeLotOrRisk);

           }

         else

           {

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

            return(INIT_FAILED);

           }

        }

//--- create handle of the indicator iMA

   handle_iMA=iMA(m_symbol.Name(),InpWorkingPeriod,Inp_MA_ma_period,Inp_MA_ma_shift,

                  Inp_MA_ma_method,Inp_MA_applied_price);

//--- if the handle is not created

   if(handle_iMA==INVALID_HANDLE)

     {

      //--- tell about the failure and output the error code

      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",

                  m_symbol.Name(),

                  EnumToString(InpWorkingPeriod),

                  GetLastError());

      //--- the indicator is stopped early

      m_init_error=true;

      return(INIT_SUCCEEDED);

     }

//---

   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_init_error)

      return;

//---

   if(m_need_close_all)

     {

      if(IsPositionExists())

        {

         CloseAllPositions();

         return;

        }

      else

        {

         m_need_close_all=false;

         ArrayFree(SPosition);

        }

     }

//---

   int size_need_position=ArraySize(SPosition);

   if(size_need_position>0)

     {

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

        {

         if(SPosition[i].waiting_transaction)

           {

            if(!SPosition[i].transaction_confirmed)

              {

               if(InpPrintLog)

                  Print(__FILE__," ",__FUNCTION__,", OK: ","transaction_confirmed: ",SPosition[i].transaction_confirmed);

               return;

              }

            else

               if(SPosition[i].transaction_confirmed)

                 {

                  ArrayRemove(SPosition,i,1);

                  return;

                 }

           }

         //---

         SPosition[i].waiting_transaction=true;

         OpenPosition(i);

         return;

        }

     }

//--- search for trading signals

   SearchTradingSignals();

//---

  }

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

//| TradeTransaction function                                        |

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

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {

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

     {

      ResetLastError();

      if(HistoryDealSelect(trans.deal))

         m_deal.Ticket(trans.deal);

      else

        {

         Print(__FILE__," ",__FUNCTION__,", ERROR: ","HistoryDealSelect(",trans.deal,") error: ",GetLastError());

         return;

        }

      if(m_deal.Symbol()==m_symbol.Name() && m_deal.Magic()==InpMagic)

        {

         ENUM_DEAL_TYPE deal_type   = m_deal.DealType();

         ENUM_DEAL_ENTRY deal_entry = m_deal.Entry();

         if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)

           {

            if(deal_entry==DEAL_ENTRY_IN || deal_entry==DEAL_ENTRY_INOUT)

               m_last_deal_in=iTime(m_symbol.Name(),InpWorkingPeriod,0);

            int size_need_position=ArraySize(SPosition);

            if(size_need_position>0)

              {

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

                 {

                  if(SPosition[i].waiting_transaction)

                     if(SPosition[i].waiting_order_ticket==m_deal.Order())

                       {

                        Print(__FUNCTION__," Transaction confirmed");

                        SPosition[i].transaction_confirmed=true;

                        break;

                       }

                 }

              }

           }

        }

     }

  }

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

//| Refreshes the symbol quotes data                                 |

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

bool RefreshRates()

  {

//--- refresh rates

   if(!m_symbol.RefreshRates())

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: ","RefreshRates error");

      return(false);

     }

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

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

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: ","Ask == 0.0 OR Bid == 0.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);

  }

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

//| Open position                                                    |

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

void OpenPosition(const int index)

  {

   if(!RefreshRates())

      return;

   /*

   SYMBOL_TRADE_STOPS_LEVEL determines the number of points for minimum indentation of the

      StopLoss and TakeProfit levels from the current closing price of the open position

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

   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

   if(SPosition[index].pos_type==POSITION_TYPE_BUY)

     {

      OpenBuy(index);

      return;

     }

//--- sell

   if(SPosition[index].pos_type==POSITION_TYPE_SELL)

     {

      OpenSell(index);

      return;

     }

  }

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

//| Open Buy position                                                |

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

void OpenBuy(const int index)

  {

   double sl=0.0;

   double tp=0.0;

   double long_lot=0.0;

   if(InpLotOrRisk==risk)

     {

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

      if(InpPrintLog)

         Print(__FILE__," ",__FUNCTION__,", OK: ",

               "CheckOpenLong (price(",DoubleToString(m_symbol.Ask(),m_symbol.Digits()),"),sl(",DoubleToString(sl,m_symbol.Digits()),"))",

               " -> Lot: ",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)

        {

         ArrayRemove(SPosition,index,1);

         if(InpPrintLog)

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

         return;

        }

     }

   else

     {

      if(InpLotOrRisk==lot)

        {

         long_lot=InpVolumeLotOrRisk;

        }

      else

        {

         if(InpLotOrRisk==lots_min)

           {

            long_lot=m_symbol.LotsMin();

           }

         else

           {

            ArrayRemove(SPosition,index,1);

            return;

           }

        }

     }

//---

   if(m_symbol.LotsLimit()>0.0)

     {

      int      count_buys           = 0;

      double   volume_buys          = 0.0;

      double   volume_biggest_buys  = 0.0;

      int      count_sells          = 0;

      double   volume_sells         = 0.0;

      double   volume_biggest_sells = 0.0;

      CalculateAllPositions(count_buys,volume_buys,volume_biggest_buys,

                            count_sells,volume_sells,volume_biggest_sells,

                            true);

      if(volume_buys+volume_sells+long_lot>m_symbol.LotsLimit())

        {

         ArrayRemove(SPosition,index,1);

         if(InpPrintLog)

            Print(__FILE__," ",__FUNCTION__,", ERROR: ","#0 Buy, Volume Buy (",DoubleToString(volume_buys,2),

                  ") + Volume Sell (",DoubleToString(volume_sells,2),

                  ") + Volume long (",DoubleToString(long_lot,2),

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

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

                       long_lot,

                       m_symbol.Ask());

   if(free_margin_check>margin_check)

     {

      if(m_trade.Buy(long_lot,m_symbol.Name(),m_symbol.Ask(),sl,tp)) // CTrade::Buy -> "true"

        {

         if(m_trade.ResultDeal()==0)

           {

            if(m_trade.ResultRetcode()==10009) // trade order went to the exchange

              {

               SPosition[index].waiting_transaction=true;

               SPosition[index].waiting_order_ticket=m_trade.ResultOrder();

              }

            else

              {

               SPosition[index].waiting_transaction=false;

               if(InpPrintLog)

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

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

              }

            if(InpPrintLog)

               PrintResultTrade(m_trade,m_symbol);

           }

         else

           {

            if(m_trade.ResultRetcode()==10009)

              {

               SPosition[index].waiting_transaction=true;

               SPosition[index].waiting_order_ticket=m_trade.ResultOrder();

              }

            else

              {

               SPosition[index].waiting_transaction=false;

               if(InpPrintLog)

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

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

              }

            if(InpPrintLog)

               PrintResultTrade(m_trade,m_symbol);

           }

        }

      else

        {

         /*

         10018 TRADE_RETCODE_MARKET_CLOSED   Market is closed

         10043 TRADE_RETCODE_SHORT_ONLY   The request is rejected, because the "Only short positions are allowed" rule is set for the symbol (POSITION_TYPE_SELL)

         10044 TRADE_RETCODE_CLOSE_ONLY   The request is rejected, because the "Only position closing is allowed" rule is set for the symbol

         */

         SPosition[index].waiting_transaction=false;

         if(InpPrintLog)

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

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

         if(InpPrintLog)

            PrintResultTrade(m_trade,m_symbol);

         if(m_trade.ResultRetcode()==10018 || m_trade.ResultRetcode()==10043 || m_trade.ResultRetcode()==10044)

            ArrayRemove(SPosition,index,1);

        }

     }

   else

     {

      ArrayRemove(SPosition,index,1);

      if(InpPrintLog)

         Print(__FILE__," ",__FUNCTION__,", ERROR: ","Free Margin Check (",DoubleToString(free_margin_check,2),") <= Margin Check (",DoubleToString(margin_check,2),")");

      return;

     }

//---

  }

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

//| Open Sell position                                               |

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

void OpenSell(const int index)

  {

   double sl=0.0;

   double tp=0.0;

   double short_lot=0.0;

   if(InpLotOrRisk==risk)

     {

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

      if(InpPrintLog)

         Print(__FILE__," ",__FUNCTION__,", OK: ",

               "CheckOpenShort (price(",DoubleToString(m_symbol.Bid(),m_symbol.Digits()),"),sl(",DoubleToString(sl,m_symbol.Digits()),"))",

               " -> Lot: ",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)

        {

         ArrayRemove(SPosition,index,1);

         if(InpPrintLog)

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

         return;

        }

     }

   else

     {

      if(InpLotOrRisk==lot)

        {

         short_lot=InpVolumeLotOrRisk;

        }

      else

        {

         if(InpLotOrRisk==lots_min)

           {

            short_lot=m_symbol.LotsMin();

           }

         else

           {

            ArrayRemove(SPosition,index,1);

            return;

           }

        }

     }

//---

   if(m_symbol.LotsLimit()>0.0)

     {

      int      count_buys           = 0;

      double   volume_buys          = 0.0;

      double   volume_biggest_buys  = 0.0;

      int      count_sells          = 0;

      double   volume_sells         = 0.0;

      double   volume_biggest_sells = 0.0;

      CalculateAllPositions(count_buys,volume_buys,volume_biggest_buys,

                            count_sells,volume_sells,volume_biggest_sells,

                            true);

      if(volume_buys+volume_sells+short_lot>m_symbol.LotsLimit())

        {

         ArrayRemove(SPosition,index,1);

         if(InpPrintLog)

            Print(__FILE__," ",__FUNCTION__,", ERROR: ","#0 Buy, Volume Buy (",DoubleToString(volume_buys,2),

                  ") + Volume Sell (",DoubleToString(volume_sells,2),

                  ") + Volume short (",DoubleToString(short_lot,2),

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

         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)) // CTrade::Sell -> "true"

        {

         if(m_trade.ResultDeal()==0)

           {

            if(m_trade.ResultRetcode()==10009) // trade order went to the exchange

              {

               SPosition[index].waiting_transaction=true;

               SPosition[index].waiting_order_ticket=m_trade.ResultOrder();

              }

            else

              {

               SPosition[index].waiting_transaction=false;

               if(InpPrintLog)

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

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

              }

            if(InpPrintLog)

               PrintResultTrade(m_trade,m_symbol);

           }

         else

           {

            if(m_trade.ResultRetcode()==10009)

              {

               SPosition[index].waiting_transaction=true;

               SPosition[index].waiting_order_ticket=m_trade.ResultOrder();

              }

            else

              {

               SPosition[index].waiting_transaction=false;

               if(InpPrintLog)

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

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

              }

            if(InpPrintLog)

               PrintResultTrade(m_trade,m_symbol);

           }

        }

      else

        {

         /*

          10018 TRADE_RETCODE_MARKET_CLOSED   Market is closed

          10043 TRADE_RETCODE_SHORT_ONLY   The request is rejected, because the "Only short positions are allowed" rule is set for the symbol (POSITION_TYPE_SELL)

          10044 TRADE_RETCODE_CLOSE_ONLY   The request is rejected, because the "Only position closing is allowed" rule is set for the symbol

          */

         SPosition[index].waiting_transaction=false;

         if(InpPrintLog)

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

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

         if(InpPrintLog)

            PrintResultTrade(m_trade,m_symbol);

         if(m_trade.ResultRetcode()==10018 || m_trade.ResultRetcode()==10043 || m_trade.ResultRetcode()==10044)

            ArrayRemove(SPosition,index,1);

        }

     }

   else

     {

      ArrayRemove(SPosition,index,1);

      if(InpPrintLog)

         Print(__FILE__," ",__FUNCTION__,", ERROR: ","Free Margin Check (",DoubleToString(free_margin_check,2),") <= Margin Check (",DoubleToString(margin_check,2),")");

      return;

     }

//---

  }

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

//| Print CTrade result                                              |

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

void PrintResultTrade(CTrade &trade,CSymbolInfo &symbol)

  {

   Print(__FILE__," ",__FUNCTION__,", Symbol: ",symbol.Name()+", "+

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

         "Code of request result as a string: "+trade.ResultRetcodeDescription(),

         "Trade execution mode: "+symbol.TradeExecutionDescription());

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

         "Order ticket: "+IntegerToString(trade.ResultOrder())+", "+

         "Order retcode external: "+IntegerToString(trade.ResultRetcodeExternal())+", "+

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

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

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

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

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

  }

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

//| Get value of buffers                                             |

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

bool iGetArray(const int handle,const int buffer,const int start_pos,

               const int count,double &arr_buffer[])

  {

   bool result=true;

   if(!ArrayIsDynamic(arr_buffer))

     {

      if(InpPrintLog)

         PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);

      return(false);

     }

   ArrayFree(arr_buffer);

//--- reset error code

   ResetLastError();

//--- fill a part of the iBands array with values from the indicator buffer

   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);

   if(copied!=count)

     {

      //--- if the copying fails, tell the error code

      if(InpPrintLog)

         PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",

                     __FILE__,__FUNCTION__,count,copied,GetLastError());

      //--- quit with zero result - it means that the indicator is considered as not calculated

      return(false);

     }

   return(result);

  }

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

//| Calculate all positions                                          |

//|  'lots_limit=true' - only for 'if(m_symbol.LotsLimit()>0.0)'     |

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

void CalculateAllPositions(int &count_buys,double &volume_buys,double &volume_biggest_buys,

                           int &count_sells,double &volume_sells,double &volume_biggest_sells,

                           bool lots_limit=false)

  {

   count_buys           = 0;

   volume_buys          = 0.0;

   volume_biggest_buys  = 0.0;

   count_sells          = 0;

   volume_sells         = 0.0;

   volume_biggest_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() && (lots_limit || (!lots_limit && m_position.Magic()==InpMagic)))

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               count_buys++;

               volume_buys+=m_position.Volume();

               if(m_position.Volume()>volume_biggest_buys)

                  volume_biggest_buys=m_position.Volume();

               continue;

              }

            else

               if(m_position.PositionType()==POSITION_TYPE_SELL)

                 {

                  count_sells++;

                  volume_sells+=m_position.Volume();

                  if(m_position.Volume()>volume_biggest_sells)

                     volume_biggest_sells=m_position.Volume();

                 }

           }

  }

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

//| Profit all positions                                             |

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

void ProfitAllPositions(int &count_buys,double &profit_buys,int &count_sells,double &profit_sells)

  {

   count_buys           = 0;

   profit_buys          = 0.0;

   count_sells          = 0;

   profit_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()==InpMagic)

           {

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

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               count_buys++;

               profit_buys+=profit;

              }

            else

              {

               count_sells++;

               profit_sells+=profit;

              }

           }

  }

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

//| Search trading signals                                           |

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

bool SearchTradingSignals(void)

  {

   if(m_last_deal_in==iTime(m_symbol.Name(),InpWorkingPeriod,0)) // on one bar - only one deal

      return(true);

   MqlRates rates[];

   double ma[];

   ArraySetAsSeries(ma,true);

   ArraySetAsSeries(rates,true);

   int start_pos=0,count=3;

   if(!iGetArray(handle_iMA,0,start_pos,count,ma) || CopyRates(m_symbol.Name(),InpWorkingPeriod,start_pos,count,rates)!=count)

      return(false);

   int size_need_position=ArraySize(SPosition);

   if(size_need_position>0)

      return(true);

//---

   int count_buys       = 0;

   double profit_buys   = 0.0;

   int count_sells      = 0;

   double profit_sells  = 0.0;

   ProfitAllPositions(count_buys,profit_buys,count_sells,profit_sells);

//--- check 'Max Loss' and 'Min Profit'

   double profit_all=profit_buys+profit_sells;

   if(profit_all!=0.0)

     {

      if(InpMaxLoss!=0.0 && profit_all<MathAbs(InpMaxLoss) || InpMinProfit!=0.0 && profit_all>MathAbs(InpMinProfit))

        {

         m_need_close_all=true;

         return(true);

        }

     }

//--- BUY Signal

   if(rates[0].open<ma[1] && rates[0].close>ma[1])

     {

      //---

      ENUM_SYMBOL_TRADE_MODE trade_mode=m_symbol.TradeMode();

      if(trade_mode==SYMBOL_TRADE_MODE_DISABLED)

         return(true);

      //---

      if(trade_mode!=SYMBOL_TRADE_MODE_FULL)

         if(trade_mode==SYMBOL_TRADE_MODE_SHORTONLY || trade_mode==SYMBOL_TRADE_MODE_CLOSEONLY)

            return(true);

      //---

      if(count_sells>0 && profit_sells>0.0)

         m_need_close_all=true;

      if(count_sells==0)

        {

         ArrayResize(SPosition,size_need_position+1);

         SPosition[size_need_position].pos_type=POSITION_TYPE_BUY;

         if(InpPrintLog)

            Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY");

         return(true);

        }

     }

//--- SELL Signal

   if(rates[0].open>ma[1] && rates[0].close<ma[1])

     {

      //---

      ENUM_SYMBOL_TRADE_MODE trade_mode=m_symbol.TradeMode();

      if(trade_mode==SYMBOL_TRADE_MODE_DISABLED)

         return(true);

      //---

      if(trade_mode!=SYMBOL_TRADE_MODE_FULL)

         if(trade_mode==SYMBOL_TRADE_MODE_LONGONLY || trade_mode==SYMBOL_TRADE_MODE_CLOSEONLY)

            return(true);

      //---

      if(count_buys>0 && profit_buys>0.0)

         m_need_close_all=true;

      if(count_buys==0)

        {

         ArrayResize(SPosition,size_need_position+1);

         SPosition[size_need_position].pos_type=POSITION_TYPE_SELL;

         if(InpPrintLog)

            Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL");

         return(true);

        }

     }

//---

   return(true);

  }

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

//| Is position exists                                               |

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

bool 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()==InpMagic)

            return(true);

//---

   return(false);

  }

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

//| Close all positions                                              |

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

void CloseAllPositions(void)

  {

   if(!RefreshRates())

      return;

   /*

   SYMBOL_TRADE_FREEZE_LEVEL shows the distance of freezing the trade operations

      for pending orders and open positions in points

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

   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

   ------------------------------------------------------------------------------------------

   */

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

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               if(!m_trade.PositionClose(m_position.Ticket())) // close a position by the specified m_symbol

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","BUY PositionClose ",m_position.Ticket(),", ",m_trade.ResultRetcodeDescription());

              }

            if(m_position.PositionType()==POSITION_TYPE_SELL)

              {

               if(!m_trade.PositionClose(m_position.Ticket())) // close a position by the specified m_symbol

                  if(InpPrintLog)

                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","SELL PositionClose ",m_position.Ticket(),", ",m_trade.ResultRetcodeDescription());

              }

           }

  }

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

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