//+------------------------------------------------------------------+
//|                                                         SWAP.mq4 |
//|                      Copyright © 2009, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
#include <stdlib.mqh>
#include <WinUser32.mqh>


extern string PARAMETERS_FILTER = "PARAMETERS FILTER";
extern bool UseHourTrade = false;
extern int FromHourTrade = 8;
extern int ToHourTrade = 18;

extern double ProfitExit = 10; //% profit exit
extern bool   bUseStopLevelForTS = True;
extern bool   bUseTPLevelFor = True;
extern double    ATRStopPeriod= 14;
extern double    ATRStopRatio = 0.5;
extern double Lots          = 0.01;
extern int    MagicNumber    = 777;
extern bool   PolLots        = true;
extern int    MaxOrders      =  1152;

extern bool RiskManagement = True;
extern double RiskPercent = 3;
extern int Slippage = 9;
extern double PercentProfit   = 20.00;   
extern double PercentLoss     = 50.00;         
extern bool   CloseTerminal   = False;      
extern bool   ShowComment     = True;           
extern bool   UseSound        = False;         
extern string NameFileSound   = "expert.wav";    
extern int    NumberOfTry     = 5;              
extern int    PauseAfterError = 75; 


int TrailingStop,TakeProfit,prevtime,InitialSL;
double curprof;
bool exit,tickvalue,atrstop;
bool  gbDisabled  = False;      
color clCloseBuy  = Blue;       
color clCloseSell = Red; 
double dXPoint = 1;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()  {

  if(Digits==3||Digits==5){
dXPoint=10;
Slippage = Slippage*dXPoint;
}
//----
      //----------------------- GENERATE MAGIC NUMBER AND TICKET COMMENT
//----------------------- SOURCE : PENGIE
   MagicNumber    = subGenerateMagicNumber(MagicNumber, Symbol(), Period());
   tickvalue = MarketInfo(Symbol(),MODE_TICKVALUE);
   
     gbDisabled=False;
  if (!IsTradeAllowed()) {
    Message("Trade context is busy! The expert cannot open position!\n"+
            "Trade context is busy! Wait until it is free...");
    gbDisabled=True; return;
  }

  if (!IsTesting()) {
    if (IsExpertEnabled()) Message("Trade context is free!");
    else Message("Trade context is free! Trying to open a position...");
  }
}
//----
   return(0);
  
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit() { if (!IsTesting()) Comment(""); }
   return(0);
//----
//----

  
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
  
   if (UseHourTrade){
   if((Hour()>=FromHourTrade)&&(Hour()<=ToHourTrade))
      Comment("Trading Hours");
   else
     {
      Comment("Non-trading Hours");
      return(0);
     }
   }
//----
   bool MM=RiskManagement;
   if(MM){if(RiskPercent<0.1||RiskPercent>100){Comment("Invalid Risk Value.");return(0);}
   else{Lots=MathFloor((AccountFreeMargin()*AccountLeverage()*(RiskPercent*dXPoint)*Point*100)/(Ask*MarketInfo(Symbol(),MODE_LOTSIZE)*
   MarketInfo(Symbol(),MODE_MINLOT)))*MarketInfo(Symbol(),MODE_MINLOT);}}
   if(MM==false){Lots=Lots;}

  int Open_Trades = OrdersTotal();
  
  int Pos=0;
  
  int Buy_Total=0;
  int Sell_Total=0;
  
  while (Open_Trades > Pos)
   {
    if (OrderSelect(Pos,SELECT_BY_POS,MODE_TRADES))
     {
      int Order_Type = OrderType();
      if (Order_Type == OP_BUY)
       {
        Buy_Total++;
       }
      if (Order_Type == OP_SELL)
       {
        Sell_Total++;
       }
     }
    Pos++;
   }

  if (gbDisabled) {
    Message("Trade context is busy! The expert cannot open position!"); return;
  }
  if (!IsTesting()) {
    if (ShowComment) {
RefreshRates();
double Eq.CM = AccountEquity();
double Bal.CM = AccountBalance();
double Mar.CM = AccountMargin();
double Prof.CM = AccountProfit();
double Lev.CM = AccountLeverage();
double TV.CM = MarketInfo(Symbol(), MODE_TICKVALUE);
double Sprd.CM = MarketInfo(Symbol(), MODE_SPREAD);
double SWL.CM = MarketInfo(Symbol(), MODE_SWAPLONG);
double SWS.CM = MarketInfo(Symbol(), MODE_SWAPSHORT);
double STP.CM = MarketInfo(Symbol(),MODE_STOPLEVEL);
double Odr.CM = OrderOpenPrice();
double BUY.CM =  Buy_Total;
double SELL.CM = Sell_Total;
double ODR.CM =  OrdersTotal();






      string st="PercentProfit="+DoubleToStr(PercentProfit, 2)
               +"PercentLoss="+DoubleToStr(PercentLoss, 2)+"\n"
               +"AccountBalance="+DoubleToStr(AccountBalance(), 2)+"\n"
               +"AccountEquity="+DoubleToStr(AccountEquity(), 2)+"\n"
               +"Percentage="+DoubleToStr((AccountEquity()/AccountBalance()-1)*100, 2)+" %"+"\n"
               +"Account profit is "+DoubleToStr(Prof.CM,2)+"\n"
               +"Account margin is "+DoubleToStr(Mar.CM,2)+"\n"
               +"Account Leverage is "+DoubleToStr(Lev.CM,2) +"\n"       
               +"Tick Value is "+DoubleToStr(TV.CM,4)+"\n"
               +"Spread is "+DoubleToStr(Sprd.CM,0)+"\n"
               +"Swap Long is "+DoubleToStr(SWL.CM,4)+"\n"
               +"Swap Short is "+DoubleToStr(SWS.CM,4)+"\n"
               +"Minimum StopLevel is "+DoubleToStr(STP.CM,4)+"\n"
               +"Order Open Price is "+DoubleToStr(Odr.CM,4)+"\n"
               +"Buy Orders Total "+DoubleToStr(BUY.CM,4)+"\n"
               +"Sell Orders Total "+DoubleToStr(SELL.CM,4)+"\n"                                         
               +"Current time is "+TimeToStr(TimeCurrent())+"\n";
      Comment(st);
    } else Comment("");
  }



  if (AccountEquity()>=AccountBalance()*(1+PercentProfit/100)) ClosePosFirstProfit();
  if (AccountEquity()<=AccountBalance()*(1-PercentLoss  /100)) ClosePosFirstProfit();


//--------------------------------------------------------------------------------------------------------------  
   
   if(bUseStopLevelForTS)TrailingStop = MarketInfo(Symbol(),MODE_STOPLEVEL);
   if(bUseTPLevelFor)TakeProfit = MarketInfo(Symbol(),MODE_STOPLEVEL);
   exit = (AccountEquity()>=AccountBalance()*(1+ProfitExit/100));
   
    atrstop=iATR(NULL,0,ATRStopPeriod,1);
    InitialSL = atrstop*ATRStopRatio*(dXPoint)*Point;



   int i=0;
   int total = OrdersTotal();   
   for(i = 0; i <= total; i++) 
     {
      if(TrailingStop>0)  
       {                 
       OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
       if(OrderMagicNumber() == MagicNumber) 
         {
         TrailingStairs(OrderTicket(),TrailingStop);
         }
       }
      }

bool BuyOp=false;
bool SellOp=false;


if (MarketInfo(Symbol(), MODE_SWAPLONG) > 0) BuyOp=true;
if (MarketInfo(Symbol(), MODE_SWAPSHORT) > 0) SellOp=true;

{

}
   if(Time[0] == prevtime) 
       return(0);
   prevtime = Time[0];
   if(!IsTradeAllowed()) 
     {
       prevtime = Time[1];
       return(0);
     }
      if(Volume[0]>1) return;


   if (total < MaxOrders || MaxOrders == 0)
     {   
       if(BuyOp)
        { 
                 if (InitialSL!=0)
          {

           OrderSend(Symbol(),OP_BUY,Lots,Ask,3,Bid-(InitialSL*dXPoint)*Point,Bid+(exit),"SWAP_Buy",MagicNumber,0,Green);
          }
         else
          {

           OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,exit,"SWAP_Buy",MagicNumber,0,Green);
          }
        }
       if(SellOp)
        { 
         if (InitialSL!=0)
          {

           OrderSend(Symbol(),OP_SELL,Lots,Bid,3,Ask+(InitialSL*dXPoint)*Point,Ask-(exit),"SWAP_Sell",MagicNumber,0,Red);
          } 
         else 
          {

           OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,exit,"SWAP_Sell",MagicNumber,0,Red);
          }
        }
      }
   
//----
   return(0);
 
}
//+----------------------------------------------------------------------------+
void ClosePosBySelect() {
  bool   fc;
  color  clClose;
  double ll, pAsk, pBid, pp;
  int    err, it;

  if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
    for (it=1; it<=NumberOfTry; it++) {
      if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
      while (!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      pAsk=MarketInfo(OrderSymbol(), MODE_ASK);
      pBid=MarketInfo(OrderSymbol(), MODE_BID);
      if (OrderType()==OP_BUY) {
        pp=pBid; clClose=clCloseBuy;
      } else {
        pp=pAsk; clClose=clCloseSell;
      }
      ll=OrderLots();
      fc=OrderClose(OrderTicket(), ll, pp, Slippage, clClose);
      if (fc) {
        if (UseSound) PlaySound(NameFileSound); break;
      } else {
        err=GetLastError();
        if (err==146) while (IsTradeContextBusy()) Sleep(1000*PauseAfterError);
        Print("Error(",err,") Close ",GetNameOP(OrderType())," ",
              ErrorDescription(err),", try ",it);
        Print(OrderTicket(),"  Ask=",pAsk,"  Bid=",pBid,"  pp=",pp);
        Print("sy=",OrderSymbol(),"  ll=",ll,"  sl=",OrderStopLoss(),
              "  tp=",OrderTakeProfit(),"  mn=",OrderMagicNumber());
        Sleep(1000*PauseAfterError);
      }
    }
  } else Print("Percentage Target Hit. Close ",GetNameOP(OrderType()));
}


//+----------------------------------------------------------------------------+
void ClosePosFirstProfit() {
  int i, k=OrdersTotal();


  for (i=k-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
        if (OrderProfit()+OrderSwap()>0) ClosePosBySelect();
      }
    }
  }

  k=OrdersTotal();
  for (i=k-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderType()==OP_BUY || OrderType()==OP_SELL) ClosePosBySelect();
    }
  }
  if (CloseTerminal && !ExistPositions()) CloseTerminal();
}


//+----------------------------------------------------------------------------+
void CloseTerminal() {
Print("Percentage Target Hit CloseTerminal()");
  int hwnd=WindowHandle(Symbol(), Period());
  int hwnd_parent=0;

  while(!IsStopped()) {
    hwnd=GetParent(hwnd);
    if (hwnd==0) break;
    hwnd_parent=hwnd;
  }
  if (hwnd_parent!=0) PostMessageA(hwnd_parent, WM_CLOSE, 0, 0);
}


//+----------------------------------------------------------------------------+
bool ExistPositions(string sy="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal();

  if (StringLen(sy)==1 && StringGetChar(sy, 0)==48) sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sy || sy=="") {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (op<0 || OrderType()==op) {
            if (mn<0 || OrderMagicNumber()==mn) return(True);
          }
        }
      }
    }
  }
  return(False);
}


//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
	switch (op) {
		case OP_BUY      : return("Buy");
		case OP_SELL     : return("Sell");
		case OP_BUYLIMIT : return("Buy Limit");
		case OP_SELLLIMIT: return("Sell Limit");
		case OP_BUYSTOP  : return("Buy Stop");
		case OP_SELLSTOP : return("Sell Stop");
		default          : return("Unknown Operation");
	}
}


//+----------------------------------------------------------------------------+
void Message(string m) {
  Comment(m);
  if (StringLen(m)>0) Print(m);
}


//+------------------------------------------------------------------+
void TrailingStairs(int ticket,int trldistance)
   {
    int Spred=Ask - Bid;
    if (OrderType()==OP_BUY)
      {
       if((Bid-OrderOpenPrice())>(trldistance*dXPoint)*Point)
         {
          if(OrderStopLoss()<Bid-(trldistance*dXPoint)*Point || (OrderStopLoss()==0))
            {
             OrderModify(ticket,OrderOpenPrice(),Bid-(trldistance*dXPoint)*Point,OrderTakeProfit(),0,Blue);
             if (PolLots)
             if (NormalizeDouble(OrderLots()/2,2)>MarketInfo(Symbol(), MODE_MINLOT))
               {
               OrderClose(ticket,NormalizeDouble(OrderLots()/2,2),Ask,3,Green);
               }
             else
               {
               OrderClose(ticket,OrderLots(),Ask,3,Green);
               }
            }
         }
       }
     else
       {
        if((OrderOpenPrice()-Ask)>((trldistance*dXPoint)*Point))
          {
           if((OrderStopLoss()>(Ask+(trldistance*dXPoint)*Point)) || (OrderStopLoss()==0))
             {
              OrderModify(OrderTicket(),OrderOpenPrice(),Ask+(trldistance*dXPoint)*Point,OrderTakeProfit(),0,Red);
             if (PolLots)
             if (NormalizeDouble(OrderLots()/2,2)>MarketInfo(Symbol(), MODE_MINLOT))
               {
               OrderClose(ticket,NormalizeDouble(OrderLots()/2,2),Bid,3,Green);
               }
             else
               {
               OrderClose(ticket,OrderLots(),Bid,3,Green);
               }
             }
          }
        }
    }
  
//----------------------- GENERATE MAGIC NUMBER BASE ON SYMBOL AND TIME FRAME FUNCTION
//----------------------- SOURCE   : PENGIE

int subGenerateMagicNumber(int Magic_Number, string symbol, int timeFrame)
{
   int isymbol = 0;
   if (symbol == "AUDCAD")       isymbol = 1;
   else if (symbol == "AUDCHF")  isymbol = 2;
   else if (symbol == "AUDJPY")  isymbol = 3;
   else if (symbol == "AUDDKK")  isymbol = 4;
   else if (symbol == "AUDNZD")  isymbol = 5;
   else if (symbol == "AUDPLN")  isymbol = 6;
   else if (symbol == "AUDSGD")  isymbol = 7;
   else if (symbol == "AUDUSD")  isymbol = 8;
   else if (symbol == "CADCHF")  isymbol = 9;
   else if (symbol == "CADJPY")  isymbol = 10;
   else if (symbol == "CHFCAD")  isymbol = 11;
   else if (symbol == "CHFJPY")  isymbol = 12;
   else if (symbol == "CHFSGD")  isymbol = 13;
   else if (symbol == "EURAUD")  isymbol = 14;
   else if (symbol == "EURCAD")  isymbol = 15;
   else if (symbol == "EURCHF")  isymbol = 16;
   else if (symbol == "EURDKK")  isymbol = 17;
   else if (symbol == "EURGBP")  isymbol = 18;
   else if (symbol == "EURHKD")  isymbol = 19;
   else if (symbol == "EURHUF")  isymbol = 20;
   else if (symbol == "EURJPY")  isymbol = 21;
   else if (symbol == "EURLVL")  isymbol = 22;
   else if (symbol == "EURNOK")  isymbol = 23;
   else if (symbol == "EURNZD")  isymbol = 24;
   else if (symbol == "EURPLN")  isymbol = 25;
   else if (symbol == "EURSEK")  isymbol = 26;
   else if (symbol == "EURSGD")  isymbol = 27;
   else if (symbol == "EURSKK")  isymbol = 28;
   else if (symbol == "EURUSD")  isymbol = 29;
   else if (symbol == "EURZAR")  isymbol = 30;
   else if (symbol == "GBPAUD")  isymbol = 31;
   else if (symbol == "GBPCAD")  isymbol = 32;
   else if (symbol == "GBPCHF")  isymbol = 33;
   else if (symbol == "GBPDKK")  isymbol = 34;
   else if (symbol == "GBPJPY")  isymbol = 35;
   else if (symbol == "GBPNOK")  isymbol = 36;
   else if (symbol == "GBPNZD")  isymbol = 37;
   else if (symbol == "GBPSEK")  isymbol = 38;
   else if (symbol == "GBPSGD")  isymbol = 39;
   else if (symbol == "GBPUSD")  isymbol = 40;
   else if (symbol == "GBPZAR")  isymbol = 41;
   else if (symbol == "NZDCAD")  isymbol = 42;
   else if (symbol == "NZDCHF")  isymbol = 43;
   else if (symbol == "NZDJPY")  isymbol = 44;
   else if (symbol == "NZDSGD")  isymbol = 45;
   else if (symbol == "NZDUSD")  isymbol = 46;
   else if (symbol == "SGDJPY")  isymbol = 47;
   else if (symbol == "USDCAD")  isymbol = 48;
   else if (symbol == "USDCHF")  isymbol = 49;
   else if (symbol == "USDCCK")  isymbol = 50;
   else if (symbol == "USDDKK")  isymbol = 51;
   else if (symbol == "USDHKD")  isymbol = 52;
   else if (symbol == "USDHRK")  isymbol = 53;
   else if (symbol == "USDHUF")  isymbol = 54;
   else if (symbol == "USDJPY")  isymbol = 55;
   else if (symbol == "USDLVL")  isymbol = 56;
   else if (symbol == "USDLTL")  isymbol = 57;
   else if (symbol == "USDMXN")  isymbol = 58;
   else if (symbol == "USDNOK")  isymbol = 59;
   else if (symbol == "USDPLN")  isymbol = 60;
   else if (symbol == "USDSEK")  isymbol = 61;
   else if (symbol == "USDSGD")  isymbol = 62;
   else if (symbol == "USDSKK")  isymbol = 63;
   else if (symbol == "USDZAR")  isymbol = 64;
   else if (symbol == "#AA")  isymbol = 65;
   else if (symbol == "#AXP")  isymbol = 66;
   else if (symbol == "#BA")  isymbol = 67;
   else if (symbol == "#C")  isymbol = 68;
   else if (symbol == "#DD")  isymbol = 69;
   else if (symbol == "#DIS")  isymbol = 70;
   else if (symbol == "#AIG")  isymbol = 71;
   else if (symbol == "#GE")  isymbol = 72;
   else if (symbol == "#GM")  isymbol = 73;
   else if (symbol == "#HD")  isymbol = 74;
   else if (symbol == "#HON")  isymbol = 75;
   else if (symbol == "#HPQ")  isymbol = 76;
   else if (symbol == "#IBM")  isymbol = 77;
   else if (symbol == "#VZ")  isymbol = 78;
   else if (symbol == "#INTC")  isymbol = 79;
   else if (symbol == "#JNJ")  isymbol = 80;
   else if (symbol == "#JPM")  isymbol = 81;
   else if (symbol == "#KO")  isymbol = 82;
   else if (symbol == "#MCD")  isymbol = 83;
   else if (symbol == "#MMM")  isymbol = 84;
   else if (symbol == "#MO")  isymbol = 85;
   else if (symbol == "#MRK")  isymbol = 86;
   else if (symbol == "#MSFT")  isymbol = 87;
   else if (symbol == "#PG")  isymbol = 88;
   else if (symbol == "#T")  isymbol = 89;
   else if (symbol == "#PFE")  isymbol = 90;
   else if (symbol == "#UTX")  isymbol = 91;
   else if (symbol == "#WMT")  isymbol = 92;
   else if (symbol == "#XOM")  isymbol = 93;
   else if (symbol == "Gold")  isymbol = 94;
   else if (symbol == "Silver")  isymbol = 95;
   else if (symbol == "#EP")  isymbol = 96;
   else if (symbol == "#ENQ")  isymbol = 97;
   else if (symbol == "#YM")  isymbol = 98;
   else if (symbol == "#CL")  isymbol = 99;
   else if (symbol == "#NG")  isymbol = 100;
   else if (symbol == "#W")  isymbol = 101;
   else if (symbol == "#C")  isymbol = 102;
   else if (symbol == "#S")  isymbol = 103;
   else                          isymbol = 104;
   if(isymbol<10) Magic_Number = MagicNumber * 10;
   return (StrToInteger(StringConcatenate(MagicNumber, isymbol, timeFrame)));
   
}
//+------------------------------------------------------------------+    