Percentage_Crossover_Channel_EA

Author: Copyright 2018, MetaQuotes Software Corp.
Price Data Components
Series array that contains open time of each barSeries array that contains close prices for each barSeries array that contains the lowest prices of each barSeries array that contains the highest prices of each bar
0 Views
0 Downloads
0 Favorites
Percentage_Crossover_Channel_EA
ÿþ//+------------------------------------------------------------------+

//|                              Percentage_Crossover_Channel_EA.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

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

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#property version   "1.00"

//--- enums

enum ENUM_INPUT_YES_NO

  {

   INPUT_YES   =  1, // Yes

   INPUT_NO    =  0  // No

  };

//--- input parameters

sinput   long                 InpMagic       =  1234567;       // Experts magic number

input double                  InpPercent     =  50.0;          // Percent

input    ENUM_APPLIED_PRICE   InpAppliedPrice=  PRICE_CLOSE;   // Applied price

sinput   ENUM_INPUT_YES_NO    InpCrossMiddle =  INPUT_NO;      // Trade at the intersection of the middle line

sinput   ENUM_INPUT_YES_NO    InpReverce     =  INPUT_NO;      // Reverse trade

input    double               InpVolume      =  0.1;           // Lots

input    uint                 InpStopLoss    =  0;             // Stop loss in points

input    uint                 InpTakeProfit  =  0;             // Take profit in points

sinput   ulong                InpDeviation   =  10;            // Slippage of price

sinput   uint                 InpSizeSpread  =  2;             // Multiplier spread for stops

//--- includes

#include <Arrays\ArrayLong.mqh>

#include <Trade\TerminalInfo.mqh>

#include <Trade\AccountInfo.mqh>

#include <Trade\Trade.mqh>

//--- global variables

struct SIndicator

  {

   double      m_buffer_up[];       // CD5@ 0 - 25@E=OO ;8=8O 8=48:0B>@0

   double      m_buffer_md[];       // CD5@ 1 - A@54=OO ;8=8O 8=48:0B>@0

   double      m_buffer_dn[];       // CD5@ 2 - =86=OO ;8=8O 8=48:0B>@0

  }

SDataInd;

//---

CSymbolInfo    symbol_info;         // 1J5:B-CSymbolInfo

CAccountInfo   account_info;        // 1J5:B-CAccountInfo

CTerminalInfo  terminal_info;       // 1J5:B-CTerminalInfo

CTrade         trade;               // 1J5:B-CTrade

CArrayLong     list_tickets_buy;    // !?8A>: B8:5B>2 4;8==KE ?>78F89

CArrayLong     list_tickets_sell;   // !?8A>: B8:5B>2 :>@>B:8E ?>78F89

double         total_volume_buy;    // 1I89 >1JQ< 4;8==KE ?>78F89

double         total_volume_sell;   // 1I89 >1JQ< :>@>B:8E ?>78F89

double         lot;                 // 1JQ< ?>78F88

string         symb;                // !8<2>;

datetime       last_time;           // @5<O ?>A;54=53> 10@0

int            prev_total;          // >;8G5AB2> ?>78F89 =0 ?@>H;>9 ?@>25@:5

int            size_spread;         // =>68B5;L A?@540

int            handle_ind;          // %M=4; 8=48:0B>@0 Percentage_Crossover_Channel

double         percent_ind;         // 0@0<5B@ "Percent" 8=48:0B>@0

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

//| Expert initialization function                                   |

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

int OnInit()

  {

//--- #AB0=>2:0 B>@3>2KE ?0@0<5B@>2

   if(!SetTradeParameters())

      return INIT_FAILED;

//--- #AB0=>2:0 7=0G5=89 ?5@5<5==KE

   percent_ind=(InpPercent<=0 ? 0.1 : InpPercent);

   size_spread=int(InpSizeSpread<1 ? 1 : InpSizeSpread);

   symb=symbol_info.Name();

   last_time=0;

   prev_total=0;

//--- =8F80;870F8O <0AA82>2 1CD5@>2 8=48:0B>@0

   ArraySetAsSeries(SDataInd.m_buffer_up,true);

   ArraySetAsSeries(SDataInd.m_buffer_md,true);

   ArraySetAsSeries(SDataInd.m_buffer_dn,true);

   ArrayResize(SDataInd.m_buffer_up,2);

   ArrayResize(SDataInd.m_buffer_md,2);

   ArrayResize(SDataInd.m_buffer_dn,2);

   ArrayInitialize(SDataInd.m_buffer_up,0);

   ArrayInitialize(SDataInd.m_buffer_md,0);

   ArrayInitialize(SDataInd.m_buffer_dn,0);

//--- !>740=85 8 ?@>25@:0 EM=4;0 8=48:0B>@0 Percentage_Crossover_Channel

   handle_ind=iCustom(symb,PERIOD_CURRENT,"Percentage_Crossover_Channel",percent_ind,InpAppliedPrice);

   if(handle_ind==INVALID_HANDLE)

     {

      Print("The Percentage_Crossover_Channel(",DoubleToString(percent_ind,2),") object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

//--- #A?5H=0O 8=8F80;870F8O

   return(INIT_SUCCEEDED);

  }

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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason)

  {

//---



  }

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

//| Expert tick function                                             |

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

void OnTick()

  {

//--- @>25@:0 =C;52KE F5=

   if(!RefreshRates()) return;

//--- 0?>;=5=85 A?8A:>2 B8:5B>2 ?>78F89

   int positions_total=PositionsTotal();

   if(prev_total!=positions_total)

     {

      FillingListTickets();

      prev_total=positions_total;

     }

   int num_b=NumberBuy();

   int num_s=NumberSell();

//--- ">@3>2;O =0 =>2>< 10@5

   if(last_time!=Time(0))

     {

      //--- 0?>;=5=85 <0AA82>2 1CD5@>2 8=48:0B>@0

      if(!FillingBuffersArrays())

         return;

   //--- >;CG5=85 40==KE >B 8=48:0B>@0

      double line_up1=LineUP(1);

      double line_up2=LineUP(2);

      double line_md1=LineMD(1);

      double line_md2=LineMD(2);

      double line_dn1=LineDN(1);

      double line_dn2=LineDN(2);

   //--- @>25@:0 A83=0;>2 >B 8=48:0B>@0

      bool open_long=false;

      bool open_short=false;

   //--- A;8 A83=0;K ?> ?5@5A5G5=8N A@54=59 ;8=88

      if(InpCrossMiddle)

        {

         if(Close(2)>line_md2 && Close(1)<line_md1)

           {

            if(!InpReverce)

               open_long=true;

            else

               open_short=true;

           }

         if(Close(2)<line_md2 && Close(1)>line_md1)

           {

            if(!InpReverce)

               open_short=true;

            else

               open_long=true;

           }

        }

   //--- A;8 A83=0;K ?> ?5@5A5G5=8N 3@0=8F :0=0;0

      else

        {

         if(Low(2)>line_dn2 && Low(1)<=line_dn1)

           {

            if(!InpReverce)

               open_long=true;

            else

               open_short=true;

           }

         if(High(2)<line_up2 && High(1)>=line_up1)

           {

            if(!InpReverce)

               open_short=true;

            else

               open_long=true;

           }

        }

   //--- B:@KB85 ?>78F89 ?> A83=0;0<

      if(open_long)

        {

         if(num_s>0) CloseSell();

         if(num_b==0)

           {

            double sl=(InpStopLoss==0   ? 0 : CorrectStopLoss(ORDER_TYPE_BUY,InpStopLoss));

            double tp=(InpTakeProfit==0 ? 0 : CorrectTakeProfit(ORDER_TYPE_BUY,InpTakeProfit));

            double ll=trade.CheckVolume(symb,lot,symbol_info.Ask(),ORDER_TYPE_BUY);

            if(ll>0 && CheckLotForLimitAccount(POSITION_TYPE_BUY,ll))

              {

               if(trade.Buy(ll,symb,0,sl,tp))

                  FillingListTickets();

              }

           }

        }

      if(open_short)

        {

         if(num_b>0) CloseBuy();

         if(num_s==0)

           {

            double sl=(InpStopLoss==0   ? 0 : CorrectStopLoss(ORDER_TYPE_SELL,InpStopLoss));

            double tp=(InpTakeProfit==0 ? 0 : CorrectTakeProfit(ORDER_TYPE_SELL,InpTakeProfit));

            double ll=trade.CheckVolume(symb,lot,symbol_info.Ask(),ORDER_TYPE_SELL);

            if(ll>0 && CheckLotForLimitAccount(POSITION_TYPE_SELL,ll))

              {

               if(trade.Sell(ll,symb,0,sl,tp))

                  FillingListTickets();

              }

           }

        }

   //--- A>E@0=5=85 2@5<5=8 =0 A;54CNICN ?@>25@:C

      last_time=Time(0);

     }

  }

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

//| Trade function                                                   |

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

void OnTrade()

  {

//---



  }

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

//| TradeTransaction function                                        |

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

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {

//---



  }

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

//| >72@0I05B 40==K5 1CD5@0 8=48:0B>@0 87 <0AA820                   |

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

double GetBuffer(const int buffer,const int shift)

  {

   return(buffer==0 ? SDataInd.m_buffer_up[shift-1] : buffer==1 ? SDataInd.m_buffer_md[shift-1] : SDataInd.m_buffer_dn[shift-1]);

  }

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

//| >72@0I05B 40==K5 25@E=53> 1CD5@0 ?> 8=45:AC 7=0G5=8O            |

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

double LineUP(const int shift)

  {

   return GetBuffer(0,shift);

  }

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

//| >72@0I05B 40==K5 A@54=53> 1CD5@0 ?> 8=45:AC 7=0G5=8O            |

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

double LineMD(const int shift)

  {

   return GetBuffer(1,shift);

  }

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

//| >72@0I05B 40==K5 =86=53> 1CD5@0 ?> 8=45:AC 7=0G5=8O             |

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

double LineDN(const int shift)

  {

   return GetBuffer(2,shift);

  }

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

//| 0?>;=O5B <0AA82K 40==KE 1CD5@>2 8=48:0B>@0                      |

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

bool FillingBuffersArrays(void)

  {

   int copied=0,count=2;

   copied=CopyBuffer(handle_ind,0,1,count,SDataInd.m_buffer_up);

   if(copied!=count) return false;

   copied=CopyBuffer(handle_ind,1,1,count,SDataInd.m_buffer_md);

   if(copied!=count) return false;

   copied=CopyBuffer(handle_ind,2,1,count,SDataInd.m_buffer_dn);

   if(copied!=count) return false;

   return true;

  }

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

//| #AB0=>2:0 B>@3>2KE ?0@0<5B@>2                                    |

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

bool SetTradeParameters()

  {

//--- #AB0=>2:0 A8<2>;0

   ResetLastError();

   if(!symbol_info.Name(Symbol()))

     {

      Print("Error setting ",Symbol()," symbol: ",GetLastError());

      return false;

     }

//--- >;CG5=85 F5=

   ResetLastError();

   if(!symbol_info.RefreshRates())

     {

      Print("Error obtaining ",symbol_info.Name()," data: ",GetLastError());

      return false;

     }

   if(account_info.MarginMode()==ACCOUNT_MARGIN_MODE_RETAIL_NETTING)

     {

      Print(account_info.MarginModeDescription(),"-account. EA should work on a hedge account.");

      return false;

     }

//--- 2B><0B8G5A:0O CAB0=>2:0 B8?0 70?>;=5=8O

   trade.SetTypeFilling(GetTypeFilling());

//--- #AB0=>2:0 <038:0

   trade.SetExpertMagicNumber(InpMagic);

//--- #AB0=>2:0 ?@>A:0;L7K20=8O

   trade.SetDeviationInPoints(InpDeviation);

//--- #AB0=>2:0 ;>B0 A :>@@5:B8@>2:>9 2254Q==>3> 7=0G5=8O

   lot=CorrectLots(InpVolume);

//--- 

   return true;

  }

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

//| 1=>2;5=85 F5=                                                   |

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

bool RefreshRates(void)

  {

   if(!symbol_info.RefreshRates()) return false;

   if(symbol_info.Ask()==0 || symbol_info.Bid()==0) return false;

   return true;

  }

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

//| >72@0I05B 2@5<O >B:@KB8O 7040==>3> 10@0                         |

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

datetime Time(int shift)

  {

   datetime array[];

   if(CopyTime(symb,PERIOD_CURRENT,shift,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B F5=C 70:@KB8O 7040==>3> 10@0                          |

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

double Close(int shift)

  {

   double array[];

   if(CopyClose(symb,PERIOD_CURRENT,shift,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B F5=C High 7040==>3> 10@0                              |

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

double High(int shift)

  {

   double array[];

   if(CopyHigh(symb,PERIOD_CURRENT,shift,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B F5=C Low 7040==>3> 10@0                               |

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

double Low(int shift)

  {

   double array[];

   if(CopyLow(symb,PERIOD_CURRENT,shift,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B :>@@5:B=K9 ;>B                                        |

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

double CorrectLots(const double lots,const bool to_min_correct=true)

  {

   double min=symbol_info.LotsMin();

   double max=symbol_info.LotsMax();

   double step=symbol_info.LotsStep();

   return(to_min_correct ? VolumeRoundToSmaller(lots,min,max,step) : VolumeRoundToCorrect(lots,min,max,step));

  }

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

//| >72@0I05B 1;8609H89 :>@@5:B=K9 ;>B                              |

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

double VolumeRoundToCorrect(const double volume,const double min,const double max,const double step)

  {

   return(step==0 ? min : fmin(fmax(round(volume/step)*step,min),max));

  }

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

//| >72@0I05B 1;8609H89 2 <5=LHCN AB>@>=C :>@@5:B=K9 ;>B            |

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

double VolumeRoundToSmaller(const double volume,const double min,const double max,const double step)

  {

   return(step==0 ? min : fmin(fmax(floor(volume/step)*step,min),max));

  }

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

//| >72@0I05B D;03 =5 ?@52KH5=8O >1I53> >1JQ<0 =0 AGQB5             |

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

bool CheckLotForLimitAccount(const ENUM_POSITION_TYPE position_type,const double volume)

  {

   if(symbol_info.LotsLimit()==0) return true;

   double total_volume=(position_type==POSITION_TYPE_BUY ? total_volume_buy : total_volume_sell);

   return(total_volume+volume<=symbol_info.LotsLimit());

  }

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

//| >72@0I05B :>@@5:B=K9 StopLoss >B=>A8B5;L=> StopLevel            |

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

double CorrectStopLoss(const ENUM_ORDER_TYPE order_type,const int stop_loss)

  {

   if(stop_loss==0) return 0;

   double pt=symbol_info.Point();

   double price=(order_type==ORDER_TYPE_BUY ? SymbolInfoDouble(symbol_info.Name(),SYMBOL_ASK) : SymbolInfoDouble(symbol_info.Name(),SYMBOL_BID));

   int lv=StopLevel(),dg=symbol_info.Digits();

   return

   (order_type==ORDER_TYPE_BUY ?

    NormalizeDouble(fmin(price-lv*pt,price-stop_loss*pt),dg) :

    NormalizeDouble(fmax(price+lv*pt,price+stop_loss*pt),dg)

    );

  }

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

//| >72@0I05B :>@@5:B=K9 TakeProfit >B=>A8B5;L=> StopLevel          |

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

double CorrectTakeProfit(const ENUM_ORDER_TYPE order_type,const int take_profit)

  {

   if(take_profit==0) return 0;

   double pt=symbol_info.Point();

   double price=(order_type==ORDER_TYPE_BUY ? SymbolInfoDouble(symbol_info.Name(),SYMBOL_ASK) : SymbolInfoDouble(symbol_info.Name(),SYMBOL_BID));

   int lv=StopLevel(),dg=symbol_info.Digits();

   return

   (order_type==ORDER_TYPE_BUY ?

    NormalizeDouble(fmax(price+lv*pt,price+take_profit*pt),dg) :

    NormalizeDouble(fmin(price-lv*pt,price-take_profit*pt),dg)

    );

  }

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

//| >72@0I05B @0AAG8B0==K9 StopLevel                                |

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

int StopLevel(void)

  {

   int sp=symbol_info.Spread();

   int lv=symbol_info.StopsLevel();

   return(lv==0 ? sp*size_spread : lv);

  }

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

//| 0:@K205B ?>78F88 Buy                                            |

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

void CloseBuy(void)

  {

   int total=list_tickets_buy.Total();

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

     {

      ulong ticket=list_tickets_buy.At(i);

      if(ticket==NULL) continue;

      trade.PositionClose(ticket,InpDeviation);

     }

   FillingListTickets();

  }

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

//| 0:@K205B ?>78F88 Sell                                           |

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

void CloseSell(void)

  {

   int total=list_tickets_sell.Total();

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

     {

      ulong ticket=list_tickets_sell.At(i);

      if(ticket==NULL) continue;

      trade.PositionClose(ticket,InpDeviation);

     }

   FillingListTickets();

  }

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

//| 0?>;=O5B <0AA82K B8:5B>2 ?>78F89                                |

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

void FillingListTickets(void)

  {

   list_tickets_buy.Clear();

   list_tickets_sell.Clear();

   total_volume_buy=0;

   total_volume_sell=0;

//---

   int total=PositionsTotal();

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

     {

      ulong ticket=PositionGetTicket(i);

      if(ticket==0) continue;

      if(PositionGetInteger(POSITION_MAGIC)!=InpMagic)   continue;

      if(PositionGetString(POSITION_SYMBOL)!=symb)       continue;

      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

      double volume=PositionGetDouble(POSITION_VOLUME);

      if(type==POSITION_TYPE_BUY)

        {

         list_tickets_buy.Add(ticket);

         total_volume_buy+=volume;

        }

      else if(type==POSITION_TYPE_SELL)

        {

         list_tickets_sell.Add(ticket);

         total_volume_sell+=volume;

        }

     }

  }

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

//| >72@0I05B :>;8G5AB2> ?>78F89 Buy                                |

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

int NumberBuy(void)

  {

   return list_tickets_buy.Total();

  }

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

//| >72@0I05B :>;8G5AB2> ?>78F89 Sell                               |

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

int NumberSell(void)

  {

   return list_tickets_sell.Total();

  }

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

//| >72@0I05B B8? 8A?>;=5=8O >@45@0, @02=K9 type,                   |

//| 5A;8 >= 4>ABC?5= =0 A8<2>;5, 8=0G5 - :>@@5:B=K9 20@80=B          |

//| https://www.mql5.com/ru/forum/170952/page4#comment_4128864       |

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

ENUM_ORDER_TYPE_FILLING GetTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_RETURN)

  {

   const ENUM_SYMBOL_TRADE_EXECUTION exe_mode=symbol_info.TradeExecution();

   const int filling_mode=symbol_info.TradeFillFlags();



   return(

          (filling_mode==0 || (type>=ORDER_FILLING_RETURN) || ((filling_mode &(type+1))!=type+1)) ?

          (((exe_mode==SYMBOL_TRADE_EXECUTION_EXCHANGE) || (exe_mode==SYMBOL_TRADE_EXECUTION_INSTANT)) ?

          ORDER_FILLING_RETURN :((filling_mode==SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) : type

          );

  }

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

Comments