//+------------------------------------------------------------------+
//| TWIS_V0.1.2 EA
//|
//|    Generated by StrategyQuant EA Wizard version 1.6
//|    Generated at Mon May 20 19:37:00 CEST 2013
//+------------------------------------------------------------------+
#property copyright "StrategyQuant.com"
#property link      "http://www.StrategyQuant.com"
#include <stdlib.mqh>
#define PATTERN_DOJI 1
#define PATTERN_HAMMER 2
#define PATTERN_SHOOTING_STAR 3
#define PATTERN_DARK_CLOUD 4
#define PATTERN_PIERCING_LINE 5
#define PATTERN_BEARISH_ENGULFING 6
#define PATTERN_BULLISH_ENGULFING 7
#define PATTERN_BEARISH_HARAMI 8
#define PATTERN_BULLISH_HARAMI 9
#define PATTERN_BEARISH_HARAMI_CROSS 10
#define PATTERN_BULLISH_HARAMI_CROSS 11



//+------------------------------------------------------------------+
// -- Variables
//+------------------------------------------------------------------+
extern string s0 = "SL, TP & BE settings";
extern int StopLossInPips = 20;
extern int ProfitTargetInPips = 100;
extern int BreakEvenAfter = 15;
extern string s1 = "Money Management Options";
extern double LotsIfNoMM = 0.01;
extern double RiskInPercent = 2;
extern double LotsDecimals = 2;
extern double MaximumLots = 10;
extern string FirstTakeProfit = "Takes away x% after x pips";
extern string DeactivateTP1 = "To turn off TP1, just put 0 in TP1InPips";
extern double TP1InPips = 30;
double TP1SHORT = 30;
extern int TP1Percentage = 50;
int MaxSlippage = 3;
double TP1L = 0;
double TP1S = 0;
extern string TradingHours = "Start/End Trading";
extern int TradingStart = 7;
extern int NoMoreNewTradesAfter = 14;
extern int TradingEnd = 16;
extern string AdvancedSettings = "Advanced Settings";
extern int PipsAboveCloud = 5;
extern int PipsBelowCloud = 5;
extern int MaxDistanceToSMA = 15;
extern string TenkanExit = "0 = No, 1 = After TP1";
extern int TenkanExitMethod = 1;

extern bool DisplayInfoPanel = true;


//+------------------------------------------------------------------+
// -- Other Hidden Parameters
//+------------------------------------------------------------------+
bool writeInfoMessagesToLog = false;
double gPointPow = 0;
double gPointCoef = 0;
int lastHistoryPosChecked = 0;
int lastHistoryPosCheckedNT = 0;
string currentTime = "";
string lastTime = "";
double brokerStopDifference = 0;
string sqLastPeriod;
bool sqIsBarOpen;
int signalShift = 0;

int LabelCorner = 1;
int OffsetHorizontal = 5;
int OffsetVertical = 20;
color LabelColor = White;

//+------------------------------------------------------------------+
// -- Functions
//+------------------------------------------------------------------+

int init() {
   Log("--------------------------------------------------------");
   Log("Starting the EA");

   double realDigits;
   if(Digits < 4) { realDigits = 2; } else { realDigits = 4; }

   gPointPow = MathPow(10, realDigits);
   gPointCoef = 1/gPointPow;

   Log("Broker Stop Difference: ",DoubleToStr(brokerStopDifference*gPointPow, 2));

   Log("--------------------------------------------------------");

   if(DisplayInfoPanel) {
      ObjectCreate("line1", OBJ_LABEL, 0, 0, 0);
      ObjectSet("line1", OBJPROP_CORNER, LabelCorner);
      ObjectSet("line1", OBJPROP_YDISTANCE, OffsetVertical + 0 );
      ObjectSet("line1", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("line1", "TWIS_V0.1.2 EA", 9, "Tahoma", LabelColor);

      ObjectCreate("linec", OBJ_LABEL, 0, 0, 0);
      ObjectSet("linec", OBJPROP_CORNER, LabelCorner);
      ObjectSet("linec", OBJPROP_YDISTANCE, OffsetVertical + 16 );
      ObjectSet("linec", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("linec", "Generated by StrategyQuant EA Wizard", 8, "Tahoma", LabelColor);

      ObjectCreate("line2", OBJ_LABEL, 0, 0, 0);
      ObjectSet("line2", OBJPROP_CORNER, LabelCorner);
      ObjectSet("line2", OBJPROP_YDISTANCE, OffsetVertical + 28);
      ObjectSet("line2", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("line2", "------------------------------------------", 8, "Tahoma", LabelColor);

      ObjectCreate("lines", OBJ_LABEL, 0, 0, 0);
      ObjectSet("lines", OBJPROP_CORNER, LabelCorner);
      ObjectSet("lines", OBJPROP_YDISTANCE, OffsetVertical + 44);
      ObjectSet("lines", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("lines", "Last Signal:  -", 9, "Tahoma", LabelColor);

      ObjectCreate("lineopl", OBJ_LABEL, 0, 0, 0);
      ObjectSet("lineopl", OBJPROP_CORNER, LabelCorner);
      ObjectSet("lineopl", OBJPROP_YDISTANCE, OffsetVertical + 60);
      ObjectSet("lineopl", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("lineopl", "Open P/L: -", 8, "Tahoma", LabelColor);

      ObjectCreate("linea", OBJ_LABEL, 0, 0, 0);
      ObjectSet("linea", OBJPROP_CORNER, LabelCorner);
      ObjectSet("linea", OBJPROP_YDISTANCE, OffsetVertical + 76);
      ObjectSet("linea", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("linea", "Account Balance: -", 8, "Tahoma", LabelColor);

      ObjectCreate("lineto", OBJ_LABEL, 0, 0, 0);
      ObjectSet("lineto", OBJPROP_CORNER, LabelCorner);
      ObjectSet("lineto", OBJPROP_YDISTANCE, OffsetVertical + 92);
      ObjectSet("lineto", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("lineto", "Total profits/losses so far: -/-", 8, "Tahoma", LabelColor);

      ObjectCreate("linetp", OBJ_LABEL, 0, 0, 0);
      ObjectSet("linetp", OBJPROP_CORNER, LabelCorner);
      ObjectSet("linetp", OBJPROP_YDISTANCE, OffsetVertical + 108);
      ObjectSet("linetp", OBJPROP_XDISTANCE, OffsetHorizontal);
      ObjectSetText("linetp", "Total P/L so far: -", 8, "Tahoma", LabelColor);
   }

   return(0);
}

//+------------------------------------------------------------------+

int deinit() {
   ObjectDelete("line1");
   ObjectDelete("linec");
   ObjectDelete("line2");
   ObjectDelete("lines");
   ObjectDelete("lineopl");
   ObjectDelete("linea");
   ObjectDelete("lineto");
   ObjectDelete("linetp");
   return(0);
}

//+------------------------------------------------------------------+

int start() {
   if(Bars<30) {
      if(writeInfoMessagesToLog) Print("NOT ENOUGH DATA: Less Bars than 30");
      return(0);
   }

   string currentPeriod = sqGetPeriodAsStr();
   if(currentPeriod == sqLastPeriod) {
      sqIsBarOpen = false;
   } else {
      sqLastPeriod = currentPeriod;
      sqIsBarOpen = true;
   }

   sqTextFillOpens();
   if(sqIsBarOpen) {
      sqTextFillTotals();
   }

   manageOrders();

   //--------------------------------------
   // GoLong 
   if (((sqIsBarOpen == true) 
      && ((TimeCurrent() > sqGetTime(TradingStart, 0 , 0)) 
      && ((TimeCurrent() < sqGetTime(NoMoreNewTradesAfter, 0 , 0)) 
      && ((Ask > (iIchimoku(NULL, 0 , 12 , 29 , 52 , 3 , 0) + sqConvertToRealPips(PipsAboveCloud))) 
      && ((Ask > (iIchimoku(NULL, 0 , 12 , 29 , 52 , 4 , 0) + sqConvertToRealPips(PipsAboveCloud))) 
      && ((sqHeikenAshi("NULL", 0,"Low", 0) == sqHeikenAshi("NULL", 0,"Open", 0)) 
      && ((sqHeikenAshi("NULL", 0,"Close", 0) > sqHeikenAshi("NULL", 0,"Open", 0)) 
      && ((Ask < (iMA(NULL, 0 , 50, 0, MODE_SMA, 0, 0) + sqConvertToRealPips(MaxDistanceToSMA))) 
      && ((iStochastic(NULL, 0 , 25 , 3 , 3 , 0 , 0 , 0 , 0) > 20) 
      && (sqGetOrderPosition(1000) != 1)))))))))))
   {
      // Action #1
       sqCloseOrder(1001);

      // Action #2
      sqOpenOrder("NULL", OP_BUY, getOrderSize(1000, OP_BUY ), getOrderPrice(1000), "", 1000, "GoLong");

      // Action #3
       TP1L = 1;
   }
   //--------------------------------------
   // GoShort 
   if (((sqIsBarOpen == true) 
      && ((TimeCurrent() > sqGetTime(TradingStart, 0 , 0)) 
      && ((TimeCurrent() < sqGetTime(NoMoreNewTradesAfter, 0 , 0)) 
      && ((Bid < (iIchimoku(NULL, 0 , 12 , 29 , 52 , 3 , 0) - sqConvertToRealPips(PipsBelowCloud))) 
      && ((Bid < (iIchimoku(NULL, 0 , 12 , 29 , 52 , 4 , 0) - sqConvertToRealPips(PipsBelowCloud))) 
      && ((sqHeikenAshi("NULL", 0,"High", 0) == sqHeikenAshi("NULL", 0,"Open", 0)) 
      && ((sqHeikenAshi("NULL", 0,"Close", 0) < sqHeikenAshi("NULL", 0,"Open", 0)) 
      && ((Bid > (iMA(NULL, 0 , 50, 0, MODE_SMA, 0, 0) - sqConvertToRealPips(MaxDistanceToSMA))) 
      && ((iStochastic(NULL, 0 , 25 , 3 , 3 , 0 , 0 , 0 , 0) < 80) 
      && (sqGetOrderPosition(1001) != -1)))))))))))
   {
      // Action #1
       sqCloseOrder(1000);

      // Action #2
      sqOpenOrder("NULL", OP_SELL, getOrderSize(1001, OP_SELL ), getOrderPrice(1001), "", 1001, "GoShort");

      // Action #3
       TP1S = 1;
   }
   //--------------------------------------
   // TP1Long 
   if (((sqGetOpenPLInPips(1000) >= TP1InPips) 
      && ((TP1L == 1) 
      && (TP1InPips > 0))))
   {
      // Action #1
       sqCloseOrderPartialPct(1000, TP1Percentage);

      // Action #2
       TP1L = 2;
   }
   //--------------------------------------
   // TP1Short 
   if (((sqGetOpenPLInPips(1001) >= TP1InPips) 
      && ((TP1S == 1) 
      && (TP1InPips > 0))))
   {
      // Action #1
       sqCloseOrderPartialPct(1001, TP1Percentage);

      // Action #2
       TP1S = 2;
   }
   //--------------------------------------
   // ExitLong 
   if (((sqIsBarOpen == true) 
      && ((TenkanExitMethod == 1) 
      && ((TP1L == 2) 
      && (sqHeikenAshi("NULL", 0,"Close", 0) < iIchimoku(NULL, 0 , 12 , 29 , 52 , 1 , 0))))))
   {
       sqCloseOrder(1000);
   }
   //--------------------------------------
   // ExitShort 
   if (((sqIsBarOpen == true) 
      && ((TenkanExitMethod == 1) 
      && ((TP1S == 2) 
      && (sqHeikenAshi("NULL", 0,"Close", 0) > iIchimoku(NULL, 0 , 12 , 29 , 52 , 1 , 0))))))
   {
       sqCloseOrder(1001);
   }
   //--------------------------------------
   // ExitTime 
   if ((TimeCurrent() >= sqGetTime(TradingEnd, 0 , 0)))
   {
       sqCloseAllOrders();
   }

   return(0);
}

//+------------------------------------------------------------------+

void manageOrders() {
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if (OrderSelect(i,SELECT_BY_POS)==true) {
         manageOrder(OrderMagicNumber());

         if(sqIsBarOpen) {
            manageOrderExpiration(OrderMagicNumber());
         }
      }

      if(OrdersTotal() <= 0) return;
   }
}

//----------------------------------------------------------------------------

void manageOrder(int orderMagicNumber) {
   double tempValue = 0;
   double tempValue2 = 0;
   double newSL = 0;
   double plValue = 0;

   if(orderMagicNumber == 1000) {
      if(OrderType() == OP_BUY || OrderType() == OP_SELL) {
         // handle only active orders

         // Trailing Stop
         tempValue = getOrderTrailingStop(1000, OrderType(), OrderOpenPrice());
         if(tempValue > 0) {
            tempValue2 = getOrderTrailingStopActivation(1000);

            if(OrderType() == OP_BUY) {
               plValue = Bid - OrderOpenPrice();
               newSL = tempValue;

               if (plValue >= tempValue2 && (OrderStopLoss() == 0 || OrderStopLoss() < newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            } else { // OrderType() == OP_SELL
               plValue = OrderOpenPrice() - Ask;
               newSL = tempValue;

               if (plValue >= tempValue2 && (OrderStopLoss() == 0 || OrderStopLoss() > newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            }
         }

         // Move Stop Loss to Break Even
         tempValue = getOrderBreakEven(1000, OrderType(), OrderOpenPrice());
         tempValue2 = getOrderBreakEvenAddPips(1000);
         if(tempValue > 0) {
            if(OrderType() == OP_BUY) {
               newSL = OrderOpenPrice() + tempValue2;
               if (OrderOpenPrice() <= tempValue && (OrderStopLoss() == 0 || OrderStopLoss() < newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            } else { // OrderType() == OP_SELL
               newSL = OrderOpenPrice() - tempValue2;
               if (OrderOpenPrice() >= tempValue && (OrderStopLoss() == 0 || OrderStopLoss() > newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            }
         }

         // Exit After X Bars
         tempValue = getOrderExitAfterXBars(1000);
         if(tempValue > 0) {
            if (sqGetOpenBarsForOrder(tempValue+10) >= tempValue) {
               sqClosePositionAtMarket(-1);
            }
         }
      }
   }

   if(orderMagicNumber == 1001) {
      if(OrderType() == OP_BUY || OrderType() == OP_SELL) {
         // handle only active orders

         // Trailing Stop
         tempValue = getOrderTrailingStop(1001, OrderType(), OrderOpenPrice());
         if(tempValue > 0) {
            tempValue2 = getOrderTrailingStopActivation(1001);

            if(OrderType() == OP_BUY) {
               plValue = Bid - OrderOpenPrice();
               newSL = tempValue;

               if (plValue >= tempValue2 && (OrderStopLoss() == 0 || OrderStopLoss() < newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            } else { // OrderType() == OP_SELL
               plValue = OrderOpenPrice() - Ask;
               newSL = tempValue;

               if (plValue >= tempValue2 && (OrderStopLoss() == 0 || OrderStopLoss() > newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            }
         }

         // Move Stop Loss to Break Even
         tempValue = getOrderBreakEven(1001, OrderType(), OrderOpenPrice());
         tempValue2 = getOrderBreakEvenAddPips(1001);
         if(tempValue > 0) {
            if(OrderType() == OP_BUY) {
               newSL = OrderOpenPrice() + tempValue2;
               if (OrderOpenPrice() <= tempValue && (OrderStopLoss() == 0 || OrderStopLoss() < newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            } else { // OrderType() == OP_SELL
               newSL = OrderOpenPrice() - tempValue2;
               if (OrderOpenPrice() >= tempValue && (OrderStopLoss() == 0 || OrderStopLoss() > newSL) && !sqDoublesAreEqual(OrderStopLoss(), newSL)) {
                  OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
               }
            }
         }

         // Exit After X Bars
         tempValue = getOrderExitAfterXBars(1001);
         if(tempValue > 0) {
            if (sqGetOpenBarsForOrder(tempValue+10) >= tempValue) {
               sqClosePositionAtMarket(-1);
            }
         }
      }
   }

}


//----------------------------------------------------------------------------

void manageOrderExpiration(int orderMagicNumber) {
   int tempValue = 0;
   int barsOpen = 0;

   if(orderMagicNumber == 1000) {
      if(OrderType() != OP_BUY && OrderType() != OP_SELL) {
         // handle only pending orders

         // Stop/Limit Order Expiration
         tempValue = getOrderExpiration(1000);
         if(tempValue > 0) {
            barsOpen = sqGetOpenBarsForOrder(tempValue+10);
            if(barsOpen >= tempValue) {
               OrderDelete(OrderTicket());
            }
         }
      }
   }

   if(orderMagicNumber == 1001) {
      if(OrderType() != OP_BUY && OrderType() != OP_SELL) {
         // handle only pending orders

         // Stop/Limit Order Expiration
         tempValue = getOrderExpiration(1001);
         if(tempValue > 0) {
            barsOpen = sqGetOpenBarsForOrder(tempValue+10);
            if(barsOpen >= tempValue) {
               OrderDelete(OrderTicket());
            }
         }
      }
   }

}

//----------------------------------------------------------------------------


double getOrderSize(int orderMagicNumber, int orderType) {
   double size = 0;
   if(orderMagicNumber == 1000) {
      size = sqMMFixedRisk(orderMagicNumber, orderType);
   }

   if(orderMagicNumber == 1001) {
      size = sqMMFixedRisk(orderMagicNumber, orderType);
   }


   return(size);
}

//----------------------------------------------------------------------------

double sqGetAverage(int avgIndiNumber, int period, int maMethod, int signalShift) {

   double indicatorValue[1000];

   for(int i=0; i<period; i++) {
   }

   double maValue = iMAOnArray(indicatorValue, period, period, 0, maMethod, 0);

   return(maValue);
}


//----------------------------------------------------------------------------

double getOrderPrice(int orderMagicNumber) {
   double price = 0;

   if(orderMagicNumber == 1000) {

      price = Ask;
   }
   if(orderMagicNumber == 1001) {

      price = Bid;
   }

   return(NormalizeDouble(price, Digits));
}

//----------------------------------------------------------------------------

double getOrderStopLoss(int orderMagicNumber, int orderType, double price) {
   double value = 0;

   if(orderMagicNumber == 1000) {
      value = ((StopLossInPips * gPointCoef));
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = price - value;
         } else {
            value = price + value;
         }
      }

   }

   if(orderMagicNumber == 1001) {
      value = ((StopLossInPips * gPointCoef));
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = price - value;
         } else {
            value = price + value;
         }
      }

   }


   return(NormalizeDouble(value, Digits));
}

//----------------------------------------------------------------------------

double getOrderProfitTarget(int orderMagicNumber, int orderType, double price) {
   double value = 0;

   if(orderMagicNumber == 1000) {
      value = ((ProfitTargetInPips * gPointCoef));
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = price + value;
         } else {
            value = price - value;
         }
      }

   }

   if(orderMagicNumber == 1001) {
      value = ((ProfitTargetInPips * gPointCoef));
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = price + value;
         } else {
            value = price - value;
         }
      }

   }


   return(NormalizeDouble(value, Digits));
}

//----------------------------------------------------------------------------

double getOrderExitAfterXBars(int orderMagicNumber) {
   double price = 0;

   if(orderMagicNumber == 1000) {
      price = 0;
   }

   if(orderMagicNumber == 1001) {
      price = 0;
   }


   return(NormalizeDouble(price, Digits));
}

//----------------------------------------------------------------------------

double getStopDifferencePrice(int orderMagicNumber) {
   double price = 0;

   if(orderMagicNumber == 1000) {
      price = 0;
   }

   if(orderMagicNumber == 1001) {
      price = 0;
   }


   return(NormalizeDouble(price, Digits));
}

//----------------------------------------------------------------------------

double getOrderTrailingStop(int orderMagicNumber, int orderType, double price) {
   double value = 0;

   if(orderMagicNumber == 1000) {
      value = ( 0 * gPointCoef);
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = Bid - value;
         } else {
            value = Ask + value;
         }
      }

   }

   if(orderMagicNumber == 1001) {
      value = ( 0 * gPointCoef);
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = Bid - value;
         } else {
            value = Ask + value;
         }
      }

   }


   return(NormalizeDouble(value, Digits));
}

//----------------------------------------------------------------------------

double getOrderTrailingStopActivation(int orderMagicNumber) {
   double value = 0;

   if(orderMagicNumber == 1000) {
      value = ( 0 * gPointCoef);
   }

   if(orderMagicNumber == 1001) {
      value = ( 0 * gPointCoef);
   }


   return(NormalizeDouble(value, Digits));
}

//----------------------------------------------------------------------------

double getOrderBreakEven(int orderMagicNumber, int orderType, double price) {
   double value = 0;

   if(orderMagicNumber == 1000) {
      value = (BreakEvenAfter * gPointCoef);
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = Bid - value;
         } else {
            value = Ask + value;
         }
      }

   }

   if(orderMagicNumber == 1001) {
      value = (BreakEvenAfter * gPointCoef);
      if(value > 0) {
         if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
            value = Bid - value;
         } else {
            value = Ask + value;
         }
      }

   }


   return(NormalizeDouble(value, Digits));
}

//----------------------------------------------------------------------------

double getOrderBreakEvenAddPips(int orderMagicNumber) {
   double value = 0;

   if(orderMagicNumber == 1000) {
      value = ( 0 * gPointCoef);
   }

   if(orderMagicNumber == 1001) {
      value = ( 0 * gPointCoef);
   }


   return(NormalizeDouble(value, Digits));
}

//----------------------------------------------------------------------------

double getOrderExpiration(int orderMagicNumber) {
   double price = 0;

   if(orderMagicNumber == 1000) {
      price = 0;
   }

   if(orderMagicNumber == 1001) {
      price = 0;
   }


   return(NormalizeDouble(price, Digits));
}

//----------------------------------------------------------------------------

bool getReplaceStopLimitOrder(int orderMagicNumber) {
   bool value = false;

   if(orderMagicNumber == 1000) {
      value = 0;
   }

   if(orderMagicNumber == 1001) {
      value = 0;
   }


   return(value);
}


//+------------------------------------------------------------------+
//+ Global functions
//+------------------------------------------------------------------+

double sqConvertToRealPips(int value) {
   return(gPointCoef * value);
}

//----------------------------------------------------------------------------

double sqConvertToPips(double value) {
   return(gPointPow * value);
}

//----------------------------------------------------------------------------

datetime sqGetTime(int hour, int minute, int second) {
   // StrToTime works only on a current date, for previous dates it should be used like this:
   // return(StrToTime(StringConcatenate(TimeToStr(Time[i], TIME_DATE), " 12:00"))));

   return(StrToTime(hour+ ":" + minute)+second);
}

//----------------------------------------------------------------------------

double sqHeikenAshi(string symbol, int timeframe, string mode, int shift) {
   if(symbol == "NULL") {
      if(mode == "Open") {
         return(iCustom(NULL, 0, "Heiken Ashi", 0,0,0,0, 2, shift));
      }
      if(mode == "Close") {
         return(iCustom(NULL, 0, "Heiken Ashi", 0,0,0,0, 3, shift));
      }
      if(mode == "High") {
         return(MathMax(iCustom( NULL, 0, "Heiken Ashi", 0,0,0,0, 0, shift), iCustom( NULL, 0, "Heiken Ashi", 0,0,0,0, 1, shift)));
      }
      if(mode == "Low") {
         return(MathMin(iCustom( NULL, 0, "Heiken Ashi", 0,0,0,0, 0, shift), iCustom( NULL, 0, "Heiken Ashi", 0,0,0,0, 1, shift)));
      }

   } else {
      if(mode == "Open") {
         return(iCustom( symbol, timeframe, "Heiken Ashi", 0,0,0,0, 2, shift));
      }
      if(mode == "Close") {
         return(iCustom( symbol, timeframe, "Heiken Ashi", 0,0,0,0, 3, shift));
      }
      if(mode == "High") {
         return(MathMax(iCustom( symbol, timeframe, "Heiken Ashi", 0,0,0,0, 0, shift), iCustom( symbol, timeframe, "Heiken Ashi", 0,0,0,0, 1, shift)));
      }
      if(mode == "Low") {
         return(MathMin(iCustom( symbol, timeframe, "Heiken Ashi", 0,0,0,0, 0, shift), iCustom( symbol, timeframe, "Heiken Ashi", 0,0,0,0, 1, shift)));
      }
   }

   return(-1);
}


//+------------------------------------------------------------------+

double sqHighest(string symbol, int timeframe, int period, int shift) {
   double maxnum = -1000;
   double val;

   for(int i=shift; i<shift+period; i++) {
      if(symbol == "NULL") {
         val = iHigh(NULL, timeframe, i);
      } else {
         val = iHigh(symbol, timeframe, i);
      }

      if(val > maxnum) {
         maxnum = val;
      }
   }

   return(maxnum);
}

//+------------------------------------------------------------------+

double sqLowest(string symbol, int timeframe, int period, int shift) {
   double minnum = 1000;
   double val;

   for(int i=shift; i<shift+period; i++) {
      if(symbol == "NULL") {
         val = iLow(NULL, timeframe, i);
      } else {
         val = iLow(symbol, timeframe, i);
      }

      if(val < minnum) {
         minnum = val;
      }
   }

   return(minnum);
}

//+------------------------------------------------------------------+

double sqBiggestRange(string symbol, int timeframe, int period, int shift) {
   double maxnum = -1000;
   double range;

   for(int i=shift; i<shift+period; i++) {
      if(symbol == "NULL") {
         range = iHigh(NULL, timeframe, i) - iLow(NULL, timeframe, i);
      } else {
         range = iHigh(symbol, timeframe, i) - iLow(symbol, timeframe, i);
      }

      if(range > maxnum) {
         maxnum = range;
      }
   }

   return(maxnum);
}


//+------------------------------------------------------------------+

double sqSmallestRange(string symbol, int timeframe, int period, int shift) {
   double minnum = 1000;
   double range;

   for(int i=shift; i<shift+period; i++) {
      if(symbol == "NULL") {
         range = iHigh(NULL, timeframe, i) - iLow(NULL, timeframe, i);
      } else {
         range = iHigh(symbol, timeframe, i) - iLow(symbol, timeframe, i);
      }

      if(range < minnum) {
         minnum = range;
      }
   }

   return(minnum);
}

//+------------------------------------------------------------------+

double sqBarRange(string symbol, int timeframe, int shift) {
   if(symbol == "NULL") {
      return(iHigh(NULL, timeframe, shift) - iLow(NULL, timeframe, shift));
   } else {
      return(iHigh(symbol, timeframe, shift) - iLow(symbol, timeframe, shift));
   }
}

//+------------------------------------------------------------------+

double sqMinimum(double value1, double value2) {
   return(MathMin(value1, value2));
}

//+------------------------------------------------------------------+

double sqMaximum(double value1, double value2) {
   return(MathMax(value1, value2));
}

//+------------------------------------------------------------------+

void Log(string s1, string s2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="" ) {
   Print(TimeToStr(TimeCurrent()), " ", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
}


//+------------------------------------------------------------------+

void LogToFile(string fileName, string s1, string s2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="" ) {
   int handle = FileOpen(fileName, FILE_READ | FILE_WRITE, ";");
   if(handle>0) {
      FileSeek(handle,0,SEEK_END);
      FileWrite(handle, TimeToStr(TimeCurrent()), " ", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
      FileClose(handle);
   }
}

//+------------------------------------------------------------------+

string sqGetPeriodAsStr() {
   string str = TimeToStr(Time[0], TIME_DATE);
   int period = Period();

   if(period == PERIOD_H4 || period == PERIOD_H1) {
      str = str + TimeHour(Time[0]);
   }
   if(period == PERIOD_M30 || period == PERIOD_M15 || period == PERIOD_M5 || period == PERIOD_M1) {
      str = str + " " + TimeToStr(Time[0], TIME_MINUTES);
   }

   return(str);
}

//+------------------------------------------------------------------+

bool sqDoublesAreEqual(double n1, double n2) {
   string s1 = DoubleToStr(n1, Digits);
   string s2 = DoubleToStr(n2, Digits);

   return (s1 == s2);
}

//+------------------------------------------------------------------+

int sqGetBarsFromOrderOpen(int expBarsPeriod) {
   datetime opTime = OrderOpenTime();
   datetime currentTime = TimeCurrent();

   int numberOfBars = 0;
   for(int i=i; i<expBarsPeriod+10; i++) {
      if(opTime < Time[i]) {
         numberOfBars++;
      }
   }

   return(numberOfBars);
}

//+------------------------------------------------------------------+

int sqGetBarsFromOrderClose(int expBarsPeriod) {
   datetime clTime = OrderCloseTime();
   datetime currentTime = TimeCurrent();

   int numberOfBars = 0;
   for(int i=i; i<expBarsPeriod+10; i++) {
      if(clTime < Time[i]) {
         numberOfBars++;
      }
   }

   return(numberOfBars);
}

//----------------------------------------------------------------------------

void sqCloseOrder(int orderMagicNumber) {
   for(int i=0; i<OrdersTotal(); i++) {
      if (OrderSelect(i,SELECT_BY_POS)==true && OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {

         if(OrderType() == OP_BUY || OrderType() == OP_SELL) {
            sqClosePositionAtMarket(-1);
         } else {
            OrderDelete(OrderTicket());
         }
      }
   }
}

//----------------------------------------------------------------------------

void sqCloseAllOrders() {
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if (OrderSelect(i,SELECT_BY_POS)==true && OrderSymbol() == Symbol()) {
         if(OrderType() == OP_BUY || OrderType() == OP_SELL) {
            sqClosePositionAtMarket(-1);
         } else {
            OrderDelete(OrderTicket());
         }
      }
   }
}

//----------------------------------------------------------------------------

void sqCloseOrderPartialPct(int orderMagicNumber, double percentage) {
   double lotMM = sqGetCurrentPositionSize(orderMagicNumber) * (percentage / 100.0);

   lotMM = NormalizeDouble( lotMM, 2);

   if(MarketInfo(Symbol(), MODE_LOTSIZE)==10000.0) lotMM=lotMM*10.0 ;
   lotMM=NormalizeDouble(lotMM, 2);

   double Smallest_Lot = MarketInfo(Symbol(), MODE_MINLOT);
   double Largest_Lot = MarketInfo(Symbol(), MODE_MAXLOT);

   if (lotMM < Smallest_Lot) lotMM = Smallest_Lot;
   if (lotMM > Largest_Lot) lotMM = Largest_Lot;

   sqCloseOrderPartial(orderMagicNumber, lotMM);
}

//----------------------------------------------------------------------------

void sqCloseOrderPartial(int orderMagicNumber, double size) {
   for(int i=0; i<OrdersTotal(); i++) {
      if (OrderSelect(i,SELECT_BY_POS)==true && OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {

         if(OrderType() == OP_BUY || OrderType() == OP_SELL) {
            sqClosePositionAtMarket(size);
         } else {
            OrderDelete(OrderTicket());
         }
      }
   }
}

//+------------------------------------------------------------------+

void sqClosePositionAtMarket(double size) {
   int retries = 3;
   while(true) {
      retries--;
      if(retries < 0) return(0);

      if(sqIsTradeAllowed() == 1) {
      Log("CLOSE RETRY: ", 3-retries);
         if(sqClosePositionWithHandling(size)) {
            // trade successfuly closed
            return(true);
         }
      }

      Sleep(500);
   }
}

//+------------------------------------------------------------------+

bool sqClosePositionWithHandling(double size) {
   RefreshRates();
   double priceCP;

   if(OrderType() != OP_BUY && OrderType() != OP_SELL) {
     return(true);
   }

   if(OrderType() == OP_BUY) {
      priceCP = Bid;
   } else {
      priceCP = Ask;
   }

   if(size <= 0) {
      return(OrderClose(OrderTicket(), OrderLots(), priceCP, MaxSlippage));
   } else {
      return(OrderClose(OrderTicket(), size, priceCP, MaxSlippage));
   }
}

//+------------------------------------------------------------------+

bool sqOpenOrder(string symbol, int orderType, double orderLots, double price, string comment, int orderMagicNumber, string ruleName) {
   int error, ticket;

   if(sqLiveOrderExists(orderMagicNumber)) {
      if(writeInfoMessagesToLog) Log("Order with magic number: ", orderMagicNumber, " already exists, cannot open another one!");
      return(false);
   }

   if(sqPendingOrderExists(orderMagicNumber)) {
      if(!getReplaceStopLimitOrder(orderMagicNumber)) {
         if(writeInfoMessagesToLog) Log("Pending Order with magic number: ", orderMagicNumber, " already exists, and replace is not allowed!");
         return(false);
      }

      // close pending order
      sqDeletePendingOrder(orderMagicNumber);
   }

   RefreshRates();
   if(orderType == OP_BUYSTOP || orderType == OP_SELLSTOP) {
      double AskOrBid;
      if(orderType == OP_BUYSTOP) { AskOrBid = Ask; } else { AskOrBid = Bid; }

      // check if stop/limit price isn't too close
      if(NormalizeDouble(MathAbs(price - AskOrBid), Digits) <= NormalizeDouble(getStopDifferencePrice(orderMagicNumber)/gPointPow, Digits)) {
         //Log("stop/limit order is too close to actual price");
         return(false);
      }
   }

   double realSL = getOrderStopLoss(orderMagicNumber, orderType, price);
   double realPT = getOrderProfitTarget(orderMagicNumber, orderType, price);

   int retries = 3;
   while(true) {
      retries--;
      if(retries < 0) return(0);
      if(sqGetOrderPosition(orderMagicNumber) != 0) return(0);

      if(sqIsTradeAllowed() == 1) {
         ticket = sqOpenOrderWithErrorHandling(symbol, orderType, orderLots, price, realSL, realPT, comment, orderMagicNumber);
         if(ticket > 0) {
            // trade successfuly opened
            ObjectSetText("lines", "Last Signal: "+ruleName, 8, "Tahoma", LabelColor);

            return(true);
         }
      }

      if(ticket == -130 || ticket == -131) {
         // invalid stops or volume, we cannot open the trade
         return(false);
      }

      Sleep(1000);
   }

   return(false);
}

//+------------------------------------------------------------------+

int sqIsTradeAllowed(int MaxWaiting_sec = 30) {
    // check whether the trade context is free
    if(!IsTradeAllowed()) {
        int StartWaitingTime = GetTickCount();
        Print("Trade context is busy! Wait until it is free...");
        // infinite loop
        while(true) {
            // if the expert was terminated by the user, stop operation
            if(IsStopped()) {
                Print("The expert was terminated by the user!");
                return(-1);
            }
            // if the waiting time exceeds the time specified in the
            // MaxWaiting_sec variable, stop operation, as well
            if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000) {
                Print("The waiting limit exceeded (" + MaxWaiting_sec + " ???.)!");
                return(-2);
            }
            // if the trade context has become free,
            if(IsTradeAllowed()) {
                Print("Trade context has become free!");
                RefreshRates();
                return(1);
            }
            // if no loop breaking condition has been met, "wait" for 0.1
            // second and then restart checking
            Sleep(100);
          }
    } else {
        //Print("Trade context is free!");
        return(1);
    }
}

//+------------------------------------------------------------------+

int sqOpenOrderWithErrorHandling(string symbol, int orderType, double orderLots, double price, double realSL, double realPT, string comment, int orderMagicNumber) {
   int ticket, error;

   if(symbol == "NULL") {
      ticket = OrderSend(Symbol(), orderType, orderLots, price, MaxSlippage, 0, 0, comment, orderMagicNumber);
   } else {
      ticket = OrderSend(symbol, orderType, orderLots, price, MaxSlippage, 0, 0, comment, orderMagicNumber);
   }
   if(ticket < 0) {
      // order failed, write error to log
      return(-1*GetLastError());
   }

   OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES);
   Log("Order opened: ", OrderTicket(), " at price:", OrderOpenPrice());

   // set up stop loss and profit target
   // it has to be done separately to support ECN brokers
   if((realSL > 0 || realPT > 0) && (OrderStopLoss() != realSL || OrderTakeProfit() != realPT)) {
      if(OrderModify(ticket, OrderOpenPrice(), realSL, realPT, 0, 0)) {
         Log("Order modified, StopLoss: ", realSL,", Profit Target: ", realPT);
      } else {
         error = GetLastError();
         Log("Error modifying order: ",error, " : ", ErrorDescription(error));

         RefreshRates();
         if(orderType == OP_BUY) price = Ask;
         if(orderType == OP_SELL) price = Bid;
         if(OrderClose(ticket, orderLots, price, 6) != true) {
            error = GetLastError();
            Log("CANNOT CLOSE ORDER: ", OrderTicket(), ", Error opening order : ",error, " : ", ErrorDescription(error));
            return(-1*error);
         }
      }
   }

   return(ticket);
}

//+------------------------------------------------------------------+

int sqGetMarketPosition() {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (OrderSelect(cc, SELECT_BY_POS) && OrderSymbol() == Symbol()) {

         if(OrderType() == OP_BUY) {
            return(1);
         }
         if(OrderType() == OP_SELL) {
            return(-1);
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

double sqGetOrderPosition(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         if(OrderType() == OP_BUY) {
            return(1);
         }
         if(OrderType() == OP_SELL) {
            return(-1);
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

double sqGetOpenPrice(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         return(OrderOpenPrice());
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

double sqGetOrderStopLoss(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         return(OrderStopLoss());
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

double sqGetOrderProfitTarget(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         return(OrderTakeProfit());
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

void sqDeletePendingOrder(int orderMagicNumber) {
   for(int i=0; i<OrdersTotal(); i++) {
      if (OrderSelect(i,SELECT_BY_POS)==true) {
         if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
            OrderDelete(OrderTicket());
            return;
         }
      }
   }
}

//+------------------------------------------------------------------+

bool sqLiveOrderExists(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() != orderMagicNumber || OrderSymbol() != Symbol()) continue;
      if(OrderType() != OP_BUY && OrderType() != OP_SELL) continue;

      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqPendingOrderExists(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() != orderMagicNumber || OrderSymbol() != Symbol()) continue;
      if(OrderType() == OP_BUY || OrderType() == OP_SELL) continue;

      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqIsCandlePattern(int shift, int pattern) {
   if(pattern == PATTERN_DOJI) return(sqCandlePatternDoji(shift));
   if(pattern == PATTERN_HAMMER) return(sqCandlePatternHammer(shift));
   if(pattern == PATTERN_SHOOTING_STAR) return(sqCandlePatternShootingStar(shift));
   if(pattern == PATTERN_DARK_CLOUD) return(sqCandlePatternDarkCloudCover(shift));
   if(pattern == PATTERN_PIERCING_LINE) return(sqCandlePatternPiercingLine(shift));
   if(pattern == PATTERN_BEARISH_ENGULFING) return(sqCandlePatternBearishEngulfing(shift));
   if(pattern == PATTERN_BULLISH_ENGULFING) return(sqCandlePatternBullishEngulfing(shift));

   if(pattern == PATTERN_BEARISH_HARAMI) return(sqCandlePatternBearishHarami(shift));
   if(pattern == PATTERN_BULLISH_HARAMI) return(sqCandlePatternBullishHarami(shift));
   if(pattern == PATTERN_BEARISH_HARAMI_CROSS) return(sqCandlePatternBearishHC(shift));
   if(pattern == PATTERN_BULLISH_HARAMI_CROSS) return(sqCandlePatternBullishHC(shift));

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternDoji(int shift) {
   if(MathAbs(Open[shift] - Close[shift])*gPointPow < 0.6) {
      return(true);
   }
   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternHammer(int shift) {
   double H = High[shift];
   double L = Low[shift];
   double L1 = Low[shift+1];
   double L2 = Low[shift+2];
   double L3 = Low[shift+3];

   double O = Open[shift];
   double C = Close[shift];
   double CL = H-L;

   double BodyLow, BodyHigh;
   double Candle_WickBody_Percent = 0.9;
   double CandleLength = 12;

   if (O > C) {
      BodyHigh = O;
      BodyLow = C;
   } else {
      BodyHigh = C;
      BodyLow = O;
   }

   double LW = BodyLow-L;
   double UW = H-BodyHigh;
   double BLa = MathAbs(O-C);
   double BL90 = BLa*Candle_WickBody_Percent;

   double pipValue = gPointCoef;

   if ((L<=L1)&&(L<L2)&&(L<L3))  {
      if (((LW/2)>UW)&&(LW>BL90)&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((LW/3)<=UW)&&((LW/4)<=UW)/*&&(H<H1)&&(H<H2)*/)  {
         return(true);
      }
      if (((LW/3)>UW)&&(LW>BL90)&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((LW/4)<=UW)/*&&(H<H1)&&(H<H2)*/)  {
         return(true);
      }
      if (((LW/4)>UW)&&(LW>BL90)&&(CL>=(CandleLength*pipValue))&&(O!=C)/*&&(H<H1)&&(H<H2)*/)  {
         return(true);
      }
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternPiercingLine(int shift) {
   double L = Low[shift];
   double H = High[shift];

   double O = Open[shift];
   double O1 = Open[shift+1];
   double C = Close[shift];
   double C1 = Close[shift+1];
   double CL = H-L;

   double CO_HL;
   if((H - L) != 0) {
      CO_HL = (C-O)/(H-L);
   } else {
      CO_HL = 0;
   }

   double Piercing_Line_Ratio = 0.5;
   double Piercing_Candle_Length = 10;

   if ((C1<O1)&&(((O1+C1)/2)<C)&&(O<C) && (CO_HL>Piercing_Line_Ratio)&&(CL>=(Piercing_Candle_Length*gPointCoef))) {
      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternShootingStar(int shift) {
   double L = Low[shift];
   double H = High[shift];
   double H1 = High[shift+1];
   double H2 = High[shift+2];
   double H3 = High[shift+3];

   double O = Open[shift];
   double C = Close[shift];
   double CL = H-L;

   double BodyLow, BodyHigh;
   double Candle_WickBody_Percent = 0.9;
   double CandleLength = 12;

   if (O > C) {
      BodyHigh = O;
      BodyLow = C;
   } else {
      BodyHigh = C;
      BodyLow = O;
   }

   double LW = BodyLow-L;
   double UW = H-BodyHigh;
   double BLa = MathAbs(O-C);
   double BL90 = BLa*Candle_WickBody_Percent;

   double pipValue = gPointCoef;

   if ((H>=H1)&&(H>H2)&&(H>H3))  {
      if (((UW/2)>LW)&&(UW>(2*BL90))&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((UW/3)<=LW)&&((UW/4)<=LW)/*&&(L>L1)&&(L>L2)*/)  {
         return(true);
      }
      if (((UW/3)>LW)&&(UW>(2*BL90))&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((UW/4)<=LW)/*&&(L>L1)&&(L>L2)*/)  {
         return(true);
      }
      if (((UW/4)>LW)&&(UW>(2*BL90))&&(CL>=(CandleLength*pipValue))&&(O!=C)/*&&(L>L1)&&(L>L2)*/)  {
         return(true);
      }
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternBearishEngulfing(int shift) {
   double O = Open[shift];
   double O1 = Open[shift+1];
   double C = Close[shift];
   double C1 = Close[shift+1];

   if ((C1>O1)&&(O>C)&&(O>=C1)&&(O1>=C)&&((O-C)>(C1-O1))) {

      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternBullishEngulfing(int shift) {
   double O = Open[shift];
   double O1 = Open[shift+1];
   double C = Close[shift];
   double C1 = Close[shift+1];

   if ((O1>C1)&&(C>O)&&(C>=O1)&&(C1>=O)&&((C-O)>(O1-C1))) {
      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternDarkCloudCover(int shift) {
   double L = Low[shift];
   double H = High[shift];

   double O = Open[shift];
   double O1 = Open[shift+1];
   double C = Close[shift];
   double C1 = Close[shift+1];
   double CL = H-L;

   double OC_HL;
   if((H - L) != 0) {
      OC_HL = (O-C)/(H-L);
   } else {
      OC_HL = 0;
   }

   double Piercing_Line_Ratio = 0.5;
   double Piercing_Candle_Length = 10;

   if ((C1>O1)&&(((C1+O1)/2)>C)&&(O>C)&&(C>O1)&&(OC_HL>Piercing_Line_Ratio)&&((CL>=Piercing_Candle_Length*gPointCoef))) {
      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternBearishHarami(int shift) {
   double O = Open[shift];
   double O1 = Open[shift+1];
   double C = Close[shift];
   double C1 = Close[shift+1];

   if ((C1>O1)&&(O>C)&&(O<=C1)&&(O1<=C)&&((O-C)<(C1-O1))) {
      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternBullishHarami(int shift) {
   double O = Open[shift];
   double O1 = Open[shift+1];
   double C = Close[shift];
   double C1 = Close[shift+1];

   if ((O1>C1)&&(C>O)&&(C<=O1)&&(C1<=O)&&((C-O)<(O1-C1))) {
      return(true);
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqCandlePatternBearishHC(int shift) {
   return (sqCandlePatternBearishHarami(shift) && sqCandlePatternDoji(shift));
}

//+------------------------------------------------------------------+

bool sqCandlePatternBullishHC(int shift) {
   return (sqCandlePatternBullishHarami(shift) && sqCandlePatternDoji(shift));
}

//+------------------------------------------------------------------+

double sqGetOpenPLInPips(int orderMagicNumber) {
   double pl = 0;

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderType() != OP_BUY && OrderType() != OP_SELL) continue;
      if(OrderSymbol() != Symbol() || orderMagicNumber != 0 && OrderMagicNumber() != orderMagicNumber) continue;

      if(OrderType() == OP_BUY) {
         pl += Bid - OrderOpenPrice();
      } else {
         pl += OrderOpenPrice() - Ask;
      }
   }

   return(pl*gPointPow);
}

//+------------------------------------------------------------------+

int sqGetClosedPLInPips(int orderMagicNumber, int shift) {
   double pl = 0;
   int index = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {

         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(index != shift) {
               index++;
               continue;
            }

            // return the P/L of last order
            // or return the P/L of last order with given Magic Number
            if(OrderType() == OP_BUY) {
               pl = OrderClosePrice() - OrderOpenPrice();
            } else {
               pl = OrderOpenPrice() - OrderClosePrice();
            }
            return(pl*gPointPow);
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

int sqGetTotalClosedPLInPips(int orderMagicNumber, int numberOfLastOrders) {
   double pl = 0;
   int count = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {

         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            // return the P/L of last order
            // or return the P/L of last order with given Magic Number
            count++;
            if(OrderType() == OP_BUY) {
               pl = pl + (OrderClosePrice() - OrderOpenPrice());
            } else {
               pl = pl + (OrderOpenPrice() - OrderClosePrice());
            }

            if(count >= numberOfLastOrders) break;
         }
      }
   }

   return(pl*gPointPow);
}

//+------------------------------------------------------------------+

int sqGetTotalProfits(int orderMagicNumber, int numberOfLastOrders) {
   double pl = 0;
   int count = 0;
   int profits = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {

         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            // return the P/L of last order
            // or return the P/L of last order with given Magic Number
            count++;

            if(OrderType() == OP_BUY) {
               pl = (OrderClosePrice() - OrderOpenPrice());
            } else {
               pl = (OrderOpenPrice() - OrderClosePrice());
            }

            if(pl > 0) {
               profits++;
            }

            if(count >= numberOfLastOrders) break;
         }
      }
   }

   return(profits);
}

//+------------------------------------------------------------------+

int sqGetTotalLosses(int orderMagicNumber, int numberOfLastOrders) {
   double pl = 0;
   int count = 0;
   int losses = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {

         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            // return the P/L of last order
            // or return the P/L of last order with given Magic Number
            count++;

            if(OrderType() == OP_BUY) {
               pl = (OrderClosePrice() - OrderOpenPrice());
            } else {
               pl = (OrderOpenPrice() - OrderClosePrice());
            }

            if(pl < 0) {
               losses++;
            }

            if(count >= numberOfLastOrders) break;
         }
      }
   }

   return(losses);
}

//+------------------------------------------------------------------+

double sqGetOpenPLInMoney(int orderMagicNumber) {
   double pl = 0;

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderType() != OP_BUY && OrderType() != OP_SELL) continue;
      if(OrderSymbol() != Symbol()) continue;
      if(orderMagicNumber != 0 && OrderMagicNumber() != orderMagicNumber) continue;

      pl += OrderProfit();
   }

   return(pl);
}

//+------------------------------------------------------------------+

double sqGetClosedPLInMoney(int orderMagicNumber, int shift) {
   double pl = 0;
   int index = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(index != shift) {
            index++;
            continue;
         }

         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            // return the P/L of last order or the P/L of last order with given Magic Number
            return(OrderProfit());
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

double sqGetTotalClosedPLInMoney(int orderMagicNumber, int numberOfLastOrders) {
   double pl = 0;
   int count = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            // return the P/L of last order or the P/L of last order with given Magic Number

            count++;
            pl = pl + OrderProfit();

            if(count >= numberOfLastOrders) break;
         }
      }
   }

   return(pl);
}

//+------------------------------------------------------------------+

double sqGetCurrentPositionSize(int orderMagicNumber) {
   double lots = 0;

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderType() != OP_BUY && OrderType() != OP_SELL) continue;
      if(OrderSymbol() != Symbol()) continue;
      if(orderMagicNumber != 0 && OrderMagicNumber() != orderMagicNumber) continue;

      lots += OrderLots();
   }

   return(lots);
}

//+------------------------------------------------------------------+

void sqMoveSLTo(int orderMagicNumber, double newSL) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;

      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0);
      }
   }
}

//+------------------------------------------------------------------+

void sqMovePTTo(int orderMagicNumber, double newPT) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;

      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), newPT, 0);
      }
   }
}

//+------------------------------------------------------------------+


int sqGetBarsSinceEntry(int orderMagicNumber) {
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (OrderSelect(cc, SELECT_BY_POS) ) {

         if((orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) && OrderSymbol() == Symbol()) {
            return (sqGetBarsFromOrderOpen(1000));
         }
      }
   }

   return(-1);
}

//+------------------------------------------------------------------+

int sqGetBarsSinceExit(int orderMagicNumber) {

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true) {

         if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
            return (sqGetBarsFromOrderClose(1000));
         }
      }
   }

   return(-1);
}

//+------------------------------------------------------------------+

int sqGetOpenBarsForOrder(int expBarsPeriod) {
   datetime opTime = OrderOpenTime();
   datetime currentTime = TimeCurrent();

   int numberOfBars = 0;
   for(int i=i; i<expBarsPeriod+10; i++) {
      if(opTime < Time[i]) {
         numberOfBars++;
      }
   }

   return(numberOfBars);
}

//+------------------------------------------------------------------+

int sqGetOrdersOpenedToday(int direction, string includePending) {
   string todayTime = TimeToStr( TimeCurrent(), TIME_DATE);
   int tradesOpenedToday = 0;

   for(int i=0;i<OrdersHistoryTotal();i++) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {

         if(direction == 1) {
            if(OrderType() == OP_SELL || OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP) {
               // skip short orders
               continue;
            }
         } else if(direction == -1) {
            if(OrderType() == OP_BUY || OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP) {
               // skip long orders
               continue;
            }
         }

         if(includePending == "false") {
            if(OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP || OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP) {
               // skip pending orders
               continue;
            }
         }

         if(TimeToStr( OrderOpenTime(), TIME_DATE) == todayTime) {
            tradesOpenedToday++;
         }
      }
   }

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) && OrderSymbol() == Symbol()) {

         if(direction == 1) {
            if(OrderType() == OP_SELL || OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP) {
               // skip short orders
               continue;
            }
         } else if(direction == -1) {
            if(OrderType() == OP_BUY || OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP) {
               // skip long orders
               continue;
            }
         }

         if(includePending == "false") {
            if(OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP || OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP) {
               // skip pending orders
               continue;
            }
         }

         if(TimeToStr( OrderOpenTime(), TIME_DATE) == todayTime) {
            tradesOpenedToday++;
         }
      }
   }

   return(tradesOpenedToday);
}

//+------------------------------------------------------------------+

int sqGetLastOrderType() {
   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(OrderType() == OP_BUY) {
            return(1);
         }
         if(OrderType() == OP_SELL) {
            return(-1);
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

int sqGetLastOrderTodayType() {
   string todayTime = TimeToStr( TimeCurrent(), TIME_DATE);

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(TimeToStr( OrderOpenTime(), TIME_DATE) != todayTime) {
            continue;
         }

         if(OrderType() == OP_BUY) {
            return(1);
         }
         if(OrderType() == OP_SELL) {
            return(-1);
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+

bool sqOrderOpenedThisBar(int orderMagicNumber) {
   double pl = 0;

   for(int i=0; i<OrdersTotal(); i++) {
      if (OrderSelect(i,SELECT_BY_POS)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderOpenTime() > Time[1]) {
               return(true);
            }
         }
      }
   }

   for(i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderOpenTime() > Time[1]) {
               return(true);
            }
         }
      }
   }


   return(false);
}

//+------------------------------------------------------------------+

bool sqOrderClosedThisBar(int orderMagicNumber) {
   double pl = 0;

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderCloseTime() > Time[1]) {
               return(true);
            }
         }
      }
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqOrderOpenedThisMinute(int orderMagicNumber) {
   datetime timeCandle = TimeCurrent() - 60; //iTime(NULL, PERIOD_M1, 1);

   for(int i=0; i<OrdersTotal(); i++) {
      if (OrderSelect(i,SELECT_BY_POS)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderOpenTime() >= timeCandle) {
               return(true);
            }
         }
      }
   }

   for(i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderOpenTime() >= timeCandle) {
               return(true);
            }
         }
      }
   }

   return(false);
}

//+------------------------------------------------------------------+

bool sqOrderClosedThisMinute(int orderMagicNumber) {
   datetime timeCandle = TimeCurrent() - 60; //iTime(NULL, PERIOD_M1, 1);

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderCloseTime() >= timeCandle) {
               return(true);
            }
         }
      }
   }

   return(false);
}

//+------------------------------------------------------------------+

double sqGetAngle(double value1, double value2, int period, double coef) {
   double diff = value1 - value2;

   double fAngleRad = MathArctan(diff / (coef*period));
   double PI =  3.141592654;

   double fAngleDegrees = (fAngleRad * 180) / PI;

   return((fAngleDegrees));
}

//+------------------------------------------------------------------+

string sqGetOrderSymbol(int orderMagicNumber) {
   datetime timeCandle = TimeCurrent() - 60; //iTime(NULL, PERIOD_M1, 1);

   for(int i=OrdersHistoryTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol() == Symbol()) {
         if(orderMagicNumber == 0 || OrderMagicNumber() == orderMagicNumber) {
            if(OrderCloseTime() >= timeCandle) {
               return(OrderSymbol());
            }
         }
      }
   }

   return("");
}

//+------------------------------------------------------------------+

void sqTextFillOpens() {
   ObjectSetText("lineopl", "Open P/L: "+DoubleToStr(sqGetOpenPLInMoney(0), 2), 8, "Tahoma", LabelColor);
   ObjectSetText("linea", "Account Balance: "+DoubleToStr(AccountBalance(), 2) , 8, "Tahoma", LabelColor);
}

//+------------------------------------------------------------------+

void sqTextFillTotals() {
   ObjectSetText("lineto", "Total profits/losses so far: "+sqGetTotalProfits(0, 100)+"/"+sqGetTotalLosses(0, 100), 8, "Tahoma", LabelColor);
   ObjectSetText("linetp", "Total P/L so far: "+DoubleToStr(sqGetTotalClosedPLInMoney(0, 1000), 2), 8, "Tahoma", LabelColor);
}

//+------------------------------------------------------------------+

double sqHighestInRange(string symbol, int timeframe, string timeFrom, string timeTo) {
   int indexTo = -1;
   int indexFrom = -1;

   // find index of bar for timeTo
   for(int i=0; i<=100; i++) {
      if(TimeToStr(Time[i], TIME_MINUTES) >= timeTo && TimeToStr(Time[i+1], TIME_MINUTES) < timeTo) {
         //Log("Found timeTo: ", TimeToStr(Time[i]));
         indexTo = i;
         break;
      }
   }

   if(indexTo == -1) {
      Log("Not found timeTo");
      return(-1);
   }

   // find index of bar for timeFrom
   for(i=0; i<=100; i++) {
      if(TimeToStr(Time[i], TIME_MINUTES) >= timeFrom && TimeToStr(Time[i+1], TIME_MINUTES) < timeFrom && i > indexTo) {
         //Log("Found timeFrom: ", TimeToStr(Time[i]));
         indexFrom = i;
         break;
      }
   }

   if(indexFrom == -1) {
      Log("Not found time From");
      return(-1);
   }

   double value = -10000.0;

   for(i=indexTo; i<=indexFrom; i++) {
      if(symbol == "NULL") {
         value = MathMax(value, iHigh(NULL, timeframe, i));
      } else {
         value = MathMax(value, iHigh(symbol, timeframe, i));
      }
   }

   return(value);
}

//+------------------------------------------------------------------+

double sqLowestInRange(string symbol, int timeframe, string timeFrom, string timeTo) {
   int indexTo = -1;
   int indexFrom = -1;

   // find index of bar for timeTo
   for(int i=0; i<=100; i++) {
      if(TimeToStr(Time[i], TIME_MINUTES) >= timeTo && TimeToStr(Time[i+1], TIME_MINUTES) < timeTo) {
         //Log("Found timeTo: ", TimeToStr(Time[i]));
         indexTo = i;
         break;
      }
   }

   if(indexTo == -1) {
      Log("Not found timeTo");
      return(-1);
   }

   // find index of bar for timeFrom
   for(i=0; i<=100; i++) {
      if(TimeToStr(Time[i], TIME_MINUTES) >= timeFrom && TimeToStr(Time[i+1], TIME_MINUTES) < timeFrom && i > indexTo) {
         //Log("Found timeFrom: ", TimeToStr(Time[i]));
         indexFrom = i;
         break;
      }
   }

   if(indexFrom == -1) {
      Log("Not found time From");
      return(-1);
   }

   double value = 100000.0;

   for(i=indexTo; i<=indexFrom; i++) {
      if(symbol == "NULL") {
         value = MathMin(value, iLow(NULL, timeframe, i));
      } else {
         value = MathMin(value, iLow(symbol, timeframe, i));
      }
   }

   return(value);
}

//+------------------------------------------------------------------+

double sqGetOrdersAveragePrice(int orderMagicNumber) {
   double sum = 0.0;
   double cnt = 0.0;
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if(OrderMagicNumber() == orderMagicNumber && OrderSymbol() == Symbol()) {
         if(OrderType() == OP_BUY && OrderCloseTime() == 0) {
            sum += OrderLots() * OrderOpenPrice ();
            cnt += OrderLots();
         }
         if(OrderType() == OP_SELL && OrderCloseTime() == 0) {
            sum += OrderLots() * OrderOpenPrice ();
			   cnt += OrderLots();
         }
      }
   }

   if (NormalizeDouble (cnt, Digits) == 0) return (0);

   return(sum / cnt);
}

//+------------------------------------------------------------------+

double sqGetIf (double condition, double val1, double val2) {
	if (NormalizeDouble(condition, Digits) > 0) return (val1);
	return (val2);
}

//+------------------------------------------------------------------+

double sqRound(double value, int digits) {
   double pow = MathPow(10, digits);
   return(MathRound(value * pow) / pow);
}


//+------------------------------------------------------------------+
//+ Money Management functions
//+------------------------------------------------------------------+

double sqMMGetOrderStopLossDistance(int orderMagicNumber, int orderType) {
   double openPrice = getOrderPrice(orderMagicNumber);
   double slSize = getOrderStopLoss(orderMagicNumber, orderType, openPrice);

   if(orderType == OP_BUY || orderType == OP_BUYSTOP || orderType == OP_BUYLIMIT) {
      return(openPrice - slSize);
   } else {
      return(slSize - openPrice);
   }
}


double sqMMFixedRisk(int orderMagicNumber, int orderType) {
   double slSize = sqMMGetOrderStopLossDistance(orderMagicNumber, orderType) * gPointPow;
   if(slSize <= 0) {
      return(LotsIfNoMM);
   }

   double _riskInPercent = RiskInPercent;
   double _lotsDecimals = LotsDecimals;
   double _maximumLots = MaximumLots;
   double _exchRate = 1.0;

   if(_riskInPercent < 0 ) {
      Log("Incorrect RiskInPercent size, it must be above 0");
      return(0);
   }
   double riskPerTrade = (_exchRate * AccountBalance() *  (_riskInPercent / 100.0));
   if(slSize <= 0) {
      Log("Incorrect StopLossPips size, it must be above 0");
      return(0);
   }

   Log("SL: ", slSize, ", AccBal: ", AccountBalance(),", Tickval: ", MarketInfo(Symbol(), MODE_TICKVALUE),", Point: ", MarketInfo(Symbol(), MODE_POINT));

   // adjust money management for non-US currencies
   double CurrencyAdjuster=1;
   if (MarketInfo(Symbol(),MODE_TICKSIZE)!=0) CurrencyAdjuster=MarketInfo(Symbol(),MODE_TICKVALUE) * (MarketInfo(Symbol(),MODE_POINT) / MarketInfo(Symbol(),MODE_TICKSIZE));

   double lotMM1 = NormalizeDouble(riskPerTrade / CurrencyAdjuster / (slSize * 10.0), _lotsDecimals);
   double lotMM;
   double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(MathMod(lotMM*100, lotStep*100) > 0) {
      lotMM = lotMM1 - MathMod(lotMM1, lotStep);
   } else {
      lotMM = lotMM1;
   }

   lotMM = NormalizeDouble( lotMM, _lotsDecimals);

   if(MarketInfo(Symbol(), MODE_LOTSIZE)==10000.0) lotMM=lotMM*10.0 ;
   lotMM=NormalizeDouble(lotMM,_lotsDecimals);

   double Smallest_Lot = MarketInfo(Symbol(), MODE_MINLOT);
   double Largest_Lot = MarketInfo(Symbol(), MODE_MAXLOT);

   if (lotMM < Smallest_Lot) lotMM = Smallest_Lot;
   if (lotMM > Largest_Lot) lotMM = Largest_Lot;

   if(lotMM > _maximumLots) {
      lotMM = _maximumLots;
   }

   return (lotMM);
}

//+------------------------------------------------------------------+
//+ Custom functions
//+
//+ Here you can define your own custom functions that can be used
//+ in EA Wizard.
//+ The functions can perform some action (for example draw on chart
//+ or manipulate with orders) or they can return value that
//+ can be used in comparison.
//+
//+ Note! All the functions below must be in valid MQL code!
//+ Contents of this file will be appended to your EA code.
//+
//+------------------------------------------------------------------+

double exampleFunction(double value) {
   return(2 * value);
}