//+------------------------------------------------------------------+
//|                                        bouncingPipEA_BigBear.mq4 |
//|                       Copyright © 2007, BigBear abd Robert Hill. |
//|                                                                  |
//| Based on original rules by BigBear                               |
//|                                                                  |
//| Added MM, test of different stoplos ideas and trailing stop      |
//} Added MFI (14) filter with levels at 20 and 80                   |
//| Above 80 for sell and below 20 for buy                           |
//| Added Stoch with levels at 20 and 80 same criteria as MFI        |
//| Added RSI as additional filter                                   |
//| 9/17/2010                                                        |
//|  Added code to handle 5 digit brokers and ECN open of trades     |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, BigBear and Robert Hill"
#property link      "http://www.forex-tsd.com"
#include <stdlib.mqh>
#include <stderror.mqh> 

// Trend
#define LONG 1
#define SHORT -1
#define FLAT 0

// MoneyManagement method
#define NONE 1
#define NIX 2
#define BURNS 3
#define NIX2 4

extern int     MagicID = 12345;
extern string  UserComment = "bouncingPipBigBear24";
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
extern string  MoneyManagement = "-------------------------------------";
extern double  Lots = 0.1;
extern string  mm0 = "MM Method";
extern string  mm1 = " 1. Use Lots";
extern string  mm2 = " 2. NIX version";
extern string  mm3 = " 3. Burn0050 version";
extern string  mm4 = " 4. NIX new version w/stoploss";
extern int     MM_Method = 2;
extern bool    AccountIsMini = true;
extern double  Risk = 10; // percent
extern double  MIN_lots = 0.1;
extern double  MAX_lots = 5;

extern string  s0 = "---StopLoss Method---";
extern string  s1 = " 1. User Input";
extern string  s2 = " 2. Candle High/Low + UserInput";
extern string  s3 = " 3. Candle High/Low + Spread";
extern int     StopLossMethod = 2;
extern int     StopLoss = 30;

extern int     TakeProfit=0;

extern string  z0 = "---ZigZag settings---";
extern string  z1 = "---ZigZag Pointer---";
extern int     ExtDepth = 100;
extern int      ExtDeviation = 75;
extern int     ExtBackstep = 15;
extern string  z2 = "NonLagZigZag_v2";
extern int     Price = 0;  //Apply to Price(0-Close;1-Open;2-High;3-Low;4-Median price;5-Typical price;6-Weighted Close) 
extern int     Length = 100;  //Period of NonLagMA
extern double  PctFilter = 2;  //Dynamic filter in decimals

extern string  f0 = "---Filter settings---";
extern int     useMFI = 0;
extern int     useStoch = 0;
extern int     useRSI = 0;
extern int     FilterSignalCandle = 0;

extern string  f1 = "---Money Flow Index---";
extern int     MFI_Period = 14;
extern int     MFI_BuyBelowLevel = 20;
extern int     MFI_SellAboveLevel = 80;
extern string  sto0 = "Stochastic Inputs";
extern int     K_Period = 14;
extern int     D_Period = 3;
extern int     Slowing = 3;
extern string  sto1 = "Price Mode";
extern string  sto2 = " 0 - Low/High";
extern string  sto3 = " 1 - Close/Close"; 
extern int     StochPrice = 0;
extern int     Stoch_BuyBelowLevel = 20;
extern int     Stoch_SellAboveLevel = 80;
extern string  r1 = "---RSI---";
extern int     RSI_Period = 14;
extern int     RSI_BuyBelowLevel = 20;
extern int     RSI_SellAboveLevel = 80;


extern string  ts0 = "---TrailingStop Method---";
extern string  ts1 = " 1. None";
extern string  ts2 = " 2. PriceChannelStop";
extern string  ts3 = " 3. Breakeven + Lock";
extern string  ts4 = " 4. Delayed at input";
extern string  ts5 = " 5. Trail immediately";
extern int     TrailingStopMethod = 1;
extern string  ts6 = "2. PriceChannelStop";
extern int     Trigger = 10;
extern string  ts7 = "3. Breakeven at input settings";
extern double  BreakEvenLevel = 30;
extern int     LockInPips = 5;        // Profit Lock in pips
extern string  ts8 = "4. Delayed at input setting";
extern double  BeginTrailingStop = 35;      // Change to whatever number of pips you wish to trail your position with.

bool okBuy,okSell;
int OpenOrderType = 0;
double myStop, myTake;

double   myPoint;
int Slippage = 3;
double TPprice, STprice;

string   gTPpriceName;
string   gSTpriceName;

int init(){

     okBuy=true;
     okSell=true;   
    myPoint = SetPoint();
    GetGlobalVars();

   return(0);
}
int deinit(){

   return(0);
}

double SetPoint()
{
   double mPoint;
   
   if (Digits < 4)
      mPoint = 0.01;
   else
      mPoint = 0.0001;
   
   return(mPoint);
}


int getMFI()
{
   double MFIMain;
   
   MFIMain = iMFI(NULL, 0, MFI_Period, FilterSignalCandle);
   
   if (MFIMain < MFI_BuyBelowLevel) return (LONG);
   
   if (MFIMain > MFI_SellAboveLevel) return (SHORT);
   
   return(FLAT);
   
}

int getStoch()
{
   double StochMain, StochSignal;
   
   StochMain = iStochastic(NULL, 0, K_Period, D_Period, Slowing, MODE_SMA, StochPrice, MODE_MAIN, FilterSignalCandle);
   StochSignal = iStochastic(NULL, 0, K_Period, D_Period, Slowing, MODE_SMA, StochPrice, MODE_SIGNAL, FilterSignalCandle);
   
   if (StochMain < Stoch_BuyBelowLevel)
   {
      if (StochSignal > StochMain) return (LONG);
   }
   
   if (StochMain > Stoch_SellAboveLevel)
   {
      if (StochSignal < StochMain) return (SHORT);
   }
   
   return(FLAT);
   
}

int getRSI()
{
   double RSIMain;
   
   RSIMain = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, FilterSignalCandle);
   
   if (RSIMain < RSI_BuyBelowLevel) return (LONG);
   
   if (RSIMain > RSI_SellAboveLevel) return (SHORT);
   
   return(FLAT);
   
}

bool checkMFI(int cmd)
{
   int MFI;
  
   MFI = getMFI();
   switch (cmd)
   {
   case OP_BUY : if (MFI == LONG) return(true);
                 break;
   case OP_SELL : if (MFI == SHORT) return (true);
   }
   return (false);
}

bool checkStoch(int cmd)
{
   int Stoch;
  
   Stoch = getStoch();
   switch (cmd)
   {
   case OP_BUY : if (Stoch == LONG) return(true);
                 break;
   case OP_SELL : if (Stoch == SHORT) return (true);
   }
   return (false);
}

bool checkRSI(int cmd)
{
   int RSI;
  
   RSI = getRSI();
   switch (cmd)
   {
   case OP_BUY : if (RSI == LONG) return(true);
                 break;
   case OP_SELL : if (RSI == SHORT) return (true);
   }
   return (false);
}

// Modified to allow more than one filter to be used
// All filters must be true to allow trades
bool CheckFilter(int cmd)
{

   bool rule1, rule2, rule3, rule4, rule5, rule6, rule7, rule8;
   
// Assume all rules are met
// That way if a rule is not used it is automaticaly true
   rule1 = true;
   rule2 = true;
   rule3 = true;
   rule4 = true;
   rule5 = true;
   rule6 = true;
   rule7 = true;
   rule8 = true;
   
   
   if (useMFI == 1) rule1 = checkMFI (cmd);
   if (rule1 == true)
   {
       if (useStoch == 1) rule2 = checkStoch(cmd);
       if (rule2 == true)
       {
          if (useRSI == 1) rule3 = checkRSI(cmd);
                
// Done this way to make it easier to add new rules
                
          if (rule3 == true) return(true);
      }
   }
   
   return (false);
   
}

void CloseOrder(int ticket)
{
   int myTicket;

   datetime ctm;
   
   myTicket = ticket;
   
// Do this in case disconnect or power loss cause ticket to reset to 0
   if (ticket == 0)
   {
         myTicket = GetOpenTicket();
   }
   if (OrderSelect(myTicket,SELECT_BY_TICKET) == true){
     ctm = OrderCloseTime();
     if (ctm == 0)  // Order has not closed
     {
        if (OrderType() == OP_BUY){
           OrderClose(myTicket,OrderLots(),Bid,3,Green);
        }
        if (OrderType() == OP_SELL){
           OrderClose(myTicket,OrderLots(),Ask,3,Red);
        //Alert("zzzz: ticket", myTicket);
        }
     }
   }
   
   return(0);
}

 int start(){
   
   static int ticket;
   int myTicket;
   double myLots, mStop;
   double ZigZagUp,ZigZagDown;
   double NonLagZigZag;
   
   
   NonLagZigZag=iCustom(NULL,0,"NonLagZigZag_v2",Price,Length,PctFilter,0,0);   
   
   ZigZagUp=iCustom(NULL,0,"ZigZag Pointer", ExtDepth,ExtDeviation,ExtBackstep,0,0);
   ZigZagDown=iCustom(NULL,0,"ZigZag Pointer", ExtDepth,ExtDeviation,ExtBackstep,1,0);
   
//   alertDisplay(ZigZagUp,ZigZagDown,NonLagZigZag);

// Check for open orders to prevent double trades

   myTicket = GetOpenTicket();
   if (myTicket > 0)
   {
   okBuy = false;   
   okSell = false;   
   }
   else
   {
   okBuy = true;
   okSell = true;   
   }
   
   if ((ZigZagUp != 0) && (ZigZagUp == NonLagZigZag) && (okBuy == true))
   { //up arrow & nonlag
   
       CloseOrder(ticket);
       if (CheckFilter (OP_BUY))
       {
         myStop = GetStopLoss(OP_BUY);
         myLots = GetLots(OP_BUY, myStop, Risk);
         OpenTrade (OP_BUY, myStop, myLots);
      
         okBuy=false;
       }
   }
   
   if ((ZigZagDown != 0) && (ZigZagDown == NonLagZigZag) && (okSell == true))
   { //down arrow & nonlag
   
        CloseOrder(ticket);
        if (CheckFilter (OP_SELL))
        {   
          myStop = GetStopLoss(OP_SELL);
          myLots = GetLots(OP_SELL, myStop, Risk);
          OpenTrade(OP_SELL, myStop, myLots);
      
         okSell=false;
       }
   }
   
   myTicket = GetOpenTicket();
   if (myTicket > 0)
   {
// Check if Sell trade
      if (OpenOrderType == OP_SELL){
      //check up arrow & nonlag
         if ((ZigZagUp != 0) && (ZigZagUp == NonLagZigZag))
         {
            CloseOrder(myTicket);
            okSell = true;
 //           Alert("Down");
            return(0);
         }
         else
            CheckForTrail(myTicket);
      }
   
// Check if Buy trade
      if (OpenOrderType == OP_BUY){
//check down arrow & nonlag
         if ((ZigZagDown != 0) && (ZigZagDown == NonLagZigZag))
         {
            CloseOrder(myTicket);
            okBuy=true; 
 //           Alert("Up"); 
            return(0);
         }
         else
            CheckForTrail(myTicket);
      }
   }
   else
   {
// No open ticket so allow nerw trades
      okBuy = true;
      okSell = true;
   }
   

   return(0);
}
//+------------------------------------------------------------------+

int OpenTrade(int signal, int mStop, double mLots)
{  
  int err, ticket;
  
   RefreshRates();
   
   if (signal==OP_BUY) 
   {
      ticket=OrderSend(Symbol(),OP_BUY,mLots,Ask,Slippage,0,0,UserComment,MagicID,0,Green);
      if (ticket > 0)
      {
         OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES);
         if (mStop != 0 || TakeProfit != 0)
	      {
            TPprice = 0;
            if (TakeProfit > 0)
            {
              TPprice=TakeLong(OrderOpenPrice(), TakeProfit);
		        TPprice = ValidTakeProfit(OP_BUY,Ask, TPprice);
		      }
            STprice = 0;
            if (mStop > 0)
            {
              STprice = StopLong(OrderOpenPrice(), mStop);
		        STprice = ValidStopLoss(OP_BUY,Bid, STprice);
		      }   
            
 // Normalize stoploss / takeprofit to the proper # of digits.
            if (Digits > 0) 
            {
              STprice = NormalizeDouble( STprice, Digits);
              TPprice = NormalizeDouble( TPprice, Digits); 
            }
            SaveTPprice(TPprice);
            SaveSTprice(STprice);
		      OrderModify(ticket, OrderOpenPrice(), STprice, TPprice, 0, LightGreen);
		   }
         
      }
   } 
   else if (signal==OP_SELL) 
   {
      ticket=OrderSend(Symbol(),OP_SELL,mLots,Bid,Slippage,0,0,UserComment,MagicID,0,Red);
      if (ticket > 0)
      {
         OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES);
         if (mStop != 0 || TakeProfit != 0)
	      {
            TPprice = 0;
            if (TakeProfit > 0)
            {
              TPprice=TakeShort(OrderOpenPrice(),TakeProfit);
		        TPprice = ValidTakeProfit(OP_SELL,Bid, TPprice);
		      }
            STprice = 0;
            if (mStop > 0)
            {
              STprice=StopShort(OrderOpenPrice() ,mStop);
		        STprice = ValidStopLoss(OP_SELL,Ask, STprice); 
		      }  
 // Normalize stoploss / takeprofit to the proper # of digits.
            if (Digits > 0) 
            {
              STprice = NormalizeDouble( STprice, Digits);
              TPprice = NormalizeDouble( TPprice, Digits); 
            }
            SaveTPprice(TPprice);
            SaveSTprice(STprice);
		      OrderModify(ticket, OrderOpenPrice(), STprice, TPprice, 0, LightGreen);
		   }
       }
   }
      
   if(ticket<0)
   {
     err = GetLastError();
     Print("OrderSend failed with error(" + err + ") " + ErrorDescription(err) );
   }
   return(ticket);
}

int GetOpenTicket()
{
   int mTicket = 0;
   
   for (int i = OrdersTotal() - 1; i >= 0;i--)
   {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderSymbol() != Symbol()) continue;
      if (OrderMagicNumber() != MagicID) continue;
         
// We have an open trade
         mTicket = OrderTicket();
         OpenOrderType = OrderType();
   }
   
   return (mTicket);
}


// Modified to return stoploss in pips
double GetStopLoss(int cmd)
{
   double myStopLoss;
   
   if (cmd == OP_BUY)
   {
      switch (StopLossMethod)
      {
      case 1 : myStopLoss = StopLoss;
               break;
      case 2 : myStopLoss = (Bid - iLow(Symbol(),Period(),0)) / myPoint + StopLoss;
               break;
      case 3 : myStopLoss = (Bid - iLow(Symbol(),Period(),0)) / myPoint + (MarketInfo(Symbol(),MODE_SPREAD)+1);
      }
   }
   if (cmd == OP_SELL)
   {
      switch (StopLossMethod)
      {
      case 1 : myStopLoss = StopLoss;
               break;
      case 2 : myStopLoss = (iHigh(Symbol(),Period(),0) - Ask) / myPoint + StopLoss;
               break;
      case 3 : myStopLoss = (iHigh(Symbol(),Period(),0) - Ask) / myPoint +(MarketInfo(Symbol(),MODE_SPREAD)+1);
      }
   }
   
   return (myStopLoss);
   
}

double StopLong(double price,int stop)
{
 if(stop==0)
  return(0);
 else
  return(price-(stop*myPoint));
}

double StopShort(double price,int stop)
{
 if(stop==0)
  return(0);
 else
  return(price+(stop*myPoint));
}

double TakeLong(double price,int take)
{
 if(take==0)
  return(0);
 else
  return(price+(take*myPoint));
}

double TakeShort(double price,int take)
{
 if(take==0)
  return(0);
 else
  return(price-(take*myPoint));
}

double GetLots(int cmd, double myStop, double myRisk)
{
  int mStop;
  double mLots;
  
  switch (MM_Method )
  {
     case NONE  : mLots = Lots;
                  break;
     case NIX   : mLots = AutoLots();
                  break;
     case BURNS : if (cmd == OP_BUY) mStop = MathFloor((Bid - myStop) / myPoint); 
                  if (cmd == OP_SELL) mStop = MathFloor((myStop - Ask) / myPoint);
                  mLots = LotSize (mStop, myRisk);
//                  Print("StopInPips : ", mStop, "StopLoss : ", myStop, "Lots : ", mLots);
     case NIX2  : if (cmd == OP_BUY) mStop = MathFloor((Bid - myStop) / myPoint); 
                  if (cmd == OP_SELL) mStop = MathFloor((myStop - Ask) / myPoint);
                  mLots = AutoLots2(myRisk, mStop);
  }
  
  return (mLots);
  
}

// version from burn0050
double LotSize(int stopInPips, double accountRisk){

 
   double lotMM = ( AccountFreeMargin() * (accountRisk/100) )/( MarketInfo(Symbol(),MODE_TICKVALUE) * stopInPips );
       //This can be used with discretion
   if (AccountIsMini) {
       //Round to the nearest 10th - AccountIsMini needs to be a bool set at the top level
      lotMM = MathFloor(lotMM*10)/10;
   } else {
       //Round to the nearest lot
 
      lotMM = MathRound(lotMM);
 
         //To be aggressive, use this one
         //lotMM = MathCeil(lotMM);
 
   }
   if (lotMM < 0.1) lotMM = .1;
   if (lotMM > 100) lotMM = 100;
 
   return (lotMM);
}

// Version from nix
double AutoLots()
{
   int Decimals = 0;
   double mLots;
   double MaxLotPurchase = 0;
  

   //
   // don't overleverage!
   // 
   
   //int AccLeverage = AccountLeverage();
   int AccLeverage = 100;

   //
   // Step for changing lots
   //
   
   double ModeLotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   double ModeLotSize = MarketInfo(Symbol(), MODE_LOTSIZE);
   
   if(ModeLotStep == 0.01)
      Decimals = 2;
   if(ModeLotStep == 0.1)
      Decimals = 1;
   
   //
   // Calculate auto lots
   //
   
   if(ModeLotSize != 0)
      MaxLotPurchase=((AccountEquity()*AccLeverage)/ModeLotSize)*(Risk*0.01);
   else
      MaxLotPurchase=MIN_lots;
      
   mLots = StrToDouble(DoubleToStr(MaxLotPurchase,Decimals));
   
   if (mLots < MIN_lots) mLots = MIN_lots;
   if (mLots > MAX_lots) mLots = MAX_lots;

   return(mLots);    
}

// Version 2 from Nix
//double AutoLots2(int Risk, int StopLossInPips, double MIN_lots = 0.1, double MAX_lots = 5)
// MIN_Lots and MAX_Lots are inputs to the EA
double AutoLots2(int accountRisk, int StopLossInPips)
{
   int    Decimals = 0;
 
   double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   double LotSize = MarketInfo(Symbol(), MODE_LOTSIZE);
   double LotTickValue = MarketInfo(Symbol(), MODE_TICKVALUE);

   if(LotStep == 0.01)
      Decimals = 2;
   if(LotStep == 0.1)
      Decimals = 1;

   double LotsToRisk = ((AccountFreeMargin()*accountRisk)/100)/StopLossInPips;
   double Lots = StrToDouble(DoubleToStr(LotsToRisk/LotTickValue,Decimals));
  
   if (Lots < MIN_lots)
      Lots = MIN_lots;
   if (Lots > MAX_lots)
      Lots = MAX_lots;

   return(Lots);    
}

void CheckForTrail(int ticket)
{
   int myTicket;
   datetime ctm;
   double OrderLTS, OrderOP;
   double OrderTP, OrderSL; 
   
   myTicket = ticket;
   
// Do this in case disconnect or power loss cause ticket to reset to 0
   if (ticket == 0)
   {
         myTicket = GetOpenTicket();
   }
   if (OrderSelect(myTicket,SELECT_BY_TICKET) == true)
   {
      ctm = OrderCloseTime();
      if (ctm == 0)  // Order has not closed
      {
         OrderOP = OrderOpenPrice();
         OrderTP = OrderTakeProfit();
         OrderSL = OrderStopLoss();
      
         if(OrderType()==OP_BUY)
         {
                  HandleTrailingStop(OP_BUY, myTicket, OrderOP, OrderSL, OrderTP);
         }
         if(OrderType()==OP_SELL)
         {
                HandleTrailingStop(OP_SELL, myTicket, OrderOP, OrderSL, OrderTP);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| HandleTrailingStop                                               |
//| Type 1 is do not trail                                           |
//| Type 2 Moves to breakeven + lock when internal TP is hit         |
//| Type 3 is like Type 5 but waits until internal TP is hit         |
//| Type 4 Move stop to breakeven + Lockin, no trail                 |
//| Type 5 waits for price to move the amount of the trailStop       |
//|        before moving stop loss then moves like type 4            |
//| Type 6 moves the stoploss without delay.                         |
//+------------------------------------------------------------------+
void HandleTrailingStop(int cmd, int ticket, double op, double os, double tp)
{
   switch (TrailingStopMethod)
   {
     case 1 : //MoveTP(cmd, ticket, op, os, tp);
              break;
     case 2 : Trail_PriceChannel(cmd, ticket, op, os, tp);
              break;
     case 3 : BreakEven_TrailingStop (cmd, ticket, op, os, tp);
              break;
     case 4 : Delayed_TrailingStop (cmd, ticket, op, os, tp);
              break;
     case 5 : Immediate_TrailingStop (cmd, ticket, op, os, tp);
              break;
    default : //MoveTP(cmd, ticket, op, os, tp);
              break;
	}
}

void Trail_PriceChannel(int cmd, int ticket, double oOP, double oSL, double oTP )
{
   double PriceChannelStopUp,PriceChannelStopDown;
        
    if (OrderType() == OP_BUY)
    {               
            
       if ((Ask-oOP) > Trigger*myPoint)
       {
          PriceChannelStopUp=iCustom(NULL,0,"PriceChannel_Stop_v1",0,0);
          if (PriceChannelStopUp < 1000)
          {
          //Alert("Victor buy: ",Ask-OrderOpenPrice());
          OrderModify(ticket,oOP,PriceChannelStopUp,oTP,0,Red);
          }                 
       }
    }
    if (OrderType() == OP_SELL){
       if ((oOP - Bid)> Trigger*myPoint)
       {
          PriceChannelStopDown=iCustom(NULL,0,"PriceChannel_Stop_v1",1,0);
          if (PriceChannelStopDown < 1000)
          {
          //Alert(" Victor sell: ",OrderOpenPrice() - Bid);
          OrderModify(ticket,oOP,PriceChannelStopDown,oTP,0,Red);
          }
       }
    }
        
}

//+------------------------------------------------------------------+
//|                                           BreakEven_TrailingStop |
//|                                  Copyright © 2006, Forex-TSD.com |
//|                         Written by MrPip,robydoby314@yahoo.com   |
//+------------------------------------------------------------------+
void BreakEven_TrailingStop(int cmd, int ticket, double oOP, double oSL, double oTP )
{
   double myStopLoss;
   
   if (cmd == OP_BUY)
   {
       if(Bid >= oOP + BreakEvenLevel * myPoint)
       {
// Check move stop loss

         if (oSL < oOP)
         {
// Move Stop to Breakeven + BreakEvenLock

            myStopLoss = oOP + LockInPips * myPoint;
            myStopLoss = ValidStopLoss(OP_BUY,Bid, myStopLoss);   
            myStopLoss = NormalizeDouble( myStopLoss, Digits);
            
            ModifyOrder(ticket,oOP, myStopLoss, oTP,LightGreen);

         }
       }
   }
     
   if (cmd == OP_SELL)
   {
       if(Ask <= oOP - BreakEvenLevel * myPoint)
       {
// Check move stop loss

          if((oSL > oOP) || (oSL < 0.1))
          {
// Move Stop to Breakeven + BreakEvenLock
          
             myStopLoss = oOP - LockInPips * myPoint;
             myStopLoss = ValidStopLoss(OP_SELL,Ask, myStopLoss);   
             myStopLoss = NormalizeDouble( myStopLoss, Digits);
             
             ModifyOrder(ticket,oOP, myStopLoss, oTP,DarkOrange);
            
          }
        }

   }
}

//+------------------------------------------------------------------+
//|                                         Delayed_TrailingStop.mq4 |
//|                                  Copyright © 2006, Forex-TSD.com |
//|                         Written by MrPip,robydoby314@yahoo.com   |
//|                                                                  |   
//| Waits for price to move the amount of the BeginTrailingStop      |
//| Moves the stoploss pip for pip after delay.                      |
//+------------------------------------------------------------------+
void Delayed_TrailingStop(int cmd, int ticket, double oOP, double oSL, double oTP )
{
   double myStopLoss;
           
   if(cmd == OP_BUY)
   {
         if(Bid >= oOP + BeginTrailingStop * myPoint)
         {
            myStopLoss = Bid - BeginTrailingStop * myPoint;
            myStopLoss = ValidStopLoss(OP_BUY,Bid, myStopLoss);
            myStopLoss = NormalizeDouble( myStopLoss, Digits);
            if (oSL < myStopLoss)
            {
               ModifyOrder(ticket,oOP, myStopLoss, oTP,LightGreen);
            }
         }
     }
     
     if (cmd == OP_SELL)
     {
         if(Ask <= oOP - BeginTrailingStop * myPoint)
         {
            myStopLoss = Ask + BeginTrailingStop * myPoint;
            myStopLoss = ValidStopLoss(OP_SELL,Ask, myStopLoss);   
            myStopLoss = NormalizeDouble( myStopLoss, Digits);
            if ((oSL > myStopLoss) || (oSL < 0.1))
            {
               ModifyOrder(ticket,oOP, myStopLoss, oTP,DarkOrange);
            }
         }
     }
}

//+------------------------------------------------------------------+
//|                                       Immediate_TrailingStop.mq4 |
//|                                  Copyright © 2006, Forex-TSD.com |
//|                         Written by MrPip,robydoby314@yahoo.com   |
//|                                                                  |   
//| Moves the stoploss without delay.                                |
//+------------------------------------------------------------------+
void Immediate_TrailingStop(int cmd, int ticket, double oOP, double oSL, double oTP)
{
   double  myStopLoss;
   
   if (cmd==OP_BUY)
   {
     myStopLoss = Bid - myStop * myPoint;
     if (Digits > 0) myStopLoss = NormalizeDouble( myStopLoss, Digits);
	  myStopLoss = ValidStopLoss(OP_BUY,Bid, myStopLoss);   
     myStopLoss = NormalizeDouble( myStopLoss, Digits);
     if (oSL < myStopLoss)
     {
	     ModifyOrder(ticket,oOP, myStopLoss, oTP,LightGreen);
     }


   }
   if (cmd==OP_SELL)
   {
     myStopLoss = Ask + myStop * myPoint;
     if (Digits > 0) myStopLoss = NormalizeDouble( myStopLoss, Digits);
     myStopLoss = ValidStopLoss(OP_SELL, Ask, myStopLoss);  
     myStopLoss = NormalizeDouble( myStopLoss, Digits);
     if (oSL > myStopLoss)
     {
       ModifyOrder(ticket,oOP, myStopLoss, oTP,DarkOrange);
     }
     

   }   
}

int ModifyOrder(int ord_ticket,double op, double oSL, double oTP, color mColor)
{
    int CloseCnt, err;
    CloseCnt=0;
    while (CloseCnt < 3)
    {
       if (OrderModify(ord_ticket,op,oSL,oTP,0,mColor))
       {
         CloseCnt = 3;
       }
       else
       {
          err=GetLastError();
          if (err == 1)
             CloseCnt = 3;
          else
          {
            Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err));
            if (err>0) CloseCnt++;
          }
       }
    }
}

double ValidStopLoss(int type, double price, double SL)
{

   double minstop;
   double newSL;
   
   if (SL < 0.1) return(SL);
   minstop = MarketInfo(Symbol(),MODE_STOPLEVEL);
   if (Digits == 3 || Digits == 5) minstop = minstop / 10;
   newSL = SL;
   if (type == OP_BUY)
   {
		 if((price - SL) < minstop*myPoint) newSL = price - minstop*myPoint;
   }
   if (type == OP_SELL)
   {
       if((SL-price) < minstop*myPoint)  newSL = price + minstop*myPoint;  
   }
   newSL = NormalizeDouble(newSL,Digits);   

   return(newSL);   
}

double ValidTakeProfit(int type, double price, double TP)
{

   double newTP, temp;
   
   temp = MarketInfo(Symbol(), MODE_STOPLEVEL) * myPoint;
   newTP = TP;
   if (type == OP_BUY)
   {
		 if((TP - price) < temp) newTP = price + temp;
   }
   if (type == OP_SELL)
   {
       if((price - TP) < temp)  newTP = price - temp;  
   }
   newTP = NormalizeDouble(newTP,Digits);   

   return(newTP);   
}

string tf2txt(int tf)
{
   switch(tf)
   {
      case PERIOD_M1: return("M1");
      case PERIOD_M5: return("M5");
      case PERIOD_M15: return("M15");
      case PERIOD_M30: return("M30");
      case PERIOD_H1: return("H1");
      case PERIOD_H4: return("H4");
      case PERIOD_D1: return("D1");
      case PERIOD_W1: return("W1");
      case PERIOD_MN1: return("MN");
   
   }
   return("??");
}

void GetGlobalVars()
{
   NameGlobalVars();
   InitGlobalVars();
   GetGlobalVarValues();
}
  
void GetGlobalVarValues()
{
   double temp;

// Booleans stored as double so convert to boolean
// > 0 true, < 0 false

//    temp = GlobalVariableGet(gFirst_TP_LevelName);
//    if (temp > 0) First_TP_Level = true; else First_TP_Level = false;
    


    TPprice = GlobalVariableGet (gTPpriceName);
    STprice = GlobalVariableGet (gSTpriceName);
    
}

void InitGlobalVars()
{

// check variable before use

  if(!GlobalVariableCheck(gTPpriceName))
    GlobalVariableSet(gTPpriceName,0);
    
    
  if(!GlobalVariableCheck(gSTpriceName))
    GlobalVariableSet(gSTpriceName,0);



}

void NameGlobalVars()
{
   string  prefix;

   prefix = "VCS_" + Symbol() +  tf2txt(Period());
   gTPpriceName = prefix + "_TPprice";
   gSTpriceName = prefix + "_STprice";
}


void SaveSTprice (double myVal)
{
    GlobalVariableSet(gSTpriceName,myVal);
}


void SaveTPprice (double myVal)
{
    GlobalVariableSet(gTPpriceName,myVal);
}
//+------------------------------------------------------------------+


