Percentage_Crossover_Channel_EA

Author: Copyright 2018, MetaQuotes Software Corp.
6 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