//+------------------------------------------------------------------+
//|   ViperGridEa_Version1.mq4
//|   Viper Trading 
//|   Recoded and enhanced by: TradingViper
//|   Base code taken from : FOREXflash (forexfactory)
//|   Original based on: WilliamsA (forexpeacearmy)
//|
//|   Backround: This is a Martingale system which will always win
//|   given unlimited trade capital/margin. This system likes trending 
//|   markets and the system "Death Trade" occurs in sideways markets
//|   where trades are accumulated, never liquidated, until margin is 
//|   exhausted. Therefore, the system should be traded with the largest
//|   capital possible, the maximum leverage available, AND the absolute
//|   smallest position size allowed.
//|
//|   Modifications: I have added few additional entry filters to try to 
//|   enter the market when it is trending or most likely to be trending,
//|   lessening the chance of hitting the death trade.  More importantly,
//|   I have added code that trys to determine if we may be caught in
//|   the "Death Trade Trap" and enters a "liquidation" mode, in which no 
//|   further open orders are placed, pending orders are cancelled, and 
//|   it attempts to liquidate all open positions for a profit. The logic
//|   is that if we are whipsawing back and forth, we should be able to 
//|   close open positions on both sides for a profit, at the right points
//|   of the whip. Most likely this will not actually be possible, but even 
//|   if we can close "most" positions for a profit, we will minimize the 
//|   losses.  Here's to hoping  :-)
//|   
//+------------------------------------------------------------------+
#property copyright "Viper Trading"
#property link      ""

//#include <stderror.mqh>
#include <OrderReliable_v0_2_5.mqh>

#define ACCUMULATE 1
#define LIQUIDATE -1

//---- input parameters ---------------------------------------------+

extern string    Note0="****** Grid Definition Parameters ******";

extern string    Note0a="--Increment=0 means auto computed, else in pips--";
extern int       Increment = 40;
extern int       IncrementAdjustForTpSl = 20;
extern int       Levels = 3;

extern string    Note1="****** Money Management and Risk Control *******";

extern string    Note1a="--PercentToRisk=0.0 means fixed min lot, 1.0=1% equity--";
extern double    PercentToRisk = 0.0;

extern string    Note1b="--Set negative (-300) to use; Immediate exit if trade loss exceeds--";
extern double    OpenLossToCloseTrades = 0.0;  

extern string    Note1c="--Used margin before death trade mitigation--";
extern int       MaxPercentMarginProfitEscape = 35; // low water mark
extern int       MaxPercentMarginLiquidate = 75;    // high water mark

extern string    Note1d="--MaxLots as whole lots; 1 == 1 lot, 10 mini lots, 100 micro lots --";
extern double    MaxLots = 0;  // Another way to reach the high water mark

extern string    Note2="****** Entry Control Filters ******";

extern string    Note2a="--Hour(0-23)==-1 means no time filter, can control independently--";
extern int       MinHourToStart = -1;
extern int       MaxHourToStart = -1;
extern bool      InvertTimeWindow = false; // if true, can't start new trade sequence in time window

extern string    Note2b="--MinStandardDeviation = 0.0 to turns off filter--";
extern double    MinStandardDeviation = 0.000;  // recomend = 0.002
extern int       StandardDevTimeFrame = 15;     // 0=Null=current chart=not recommended 

extern string    Note2c="--UseTrendFilter false to turn off--";
extern bool      UseTrendFilter = false;

extern string    Note2d="--Max spread to open in pips";
extern bool      MaxSpreadToOpen = 10;

extern int       MagicNumber=1234321;


//---- Global Variables ---------------------------------------------+

int      Mode = ACCUMULATE;
double   Lots=0.01; 
double   PointValue;
string   Version = "ver 1.0";
int      MaxExitSlippage = 10;

bool     UseProfitTarget=false;
bool     UsePartialProfitTarget=false;
int      TargetAutoIncrement  = 10;
int      NextTarget = 10;

// Variables to remain fixed throughout set
int      increment;
int      incrementAdjust;
int      levels;
double   percentToRisk;
double   spread;


//+------------------------------------------------------------------+
//| expert initialization function
//+------------------------------------------------------------------+
int init()
{
   // Account for brokers that use 5 digit precision
   PointValue = Point;
   if( Digits == 5 || Digits == 3 ) PointValue *= 10;

   // Always trade with min lots allowed by broker
   // This system will ALWAYS be profitable if you are never forced
   // to overtrade - which can happen, i.e. the DEATH TRADE !!
   Lots = MarketInfo(Symbol(), MODE_MINLOT);

   if( MinHourToStart < 0 || MinHourToStart > 23 ) MinHourToStart = -1;
   if( MaxHourToStart < 0 || MaxHourToStart > 23 ) MaxHourToStart = 25;
   
   if(IncrementAdjustForTpSl < 0 ) IncrementAdjustForTpSl = 0;
   
   return(0);
}


//+------------------------------------------------------------------+
//| expert deinitialization function
//+------------------------------------------------------------------+
int deinit()
{
   return(0);
}


//+------------------------------------------------------------------+
//| expert start function
//+------------------------------------------------------------------+
int start()
{
   int slippage=5;                                 
   int ticket, cpt, openOrderCount=0, buyGoalProfit, sellGoalProfit;
   double profitTarget=0.0, buyGoal=0.0, sellGoal=0.0, initialPrice=0.0;
   int percentMarginUsed=0, tradeProfit=0;
   double totalPositionSize=0.0;

   computeSessionStats( openOrderCount, tradeProfit, totalPositionSize, percentMarginUsed );

   //+------------------------------------------------------------------+
   // Check for partial profits

   for( cpt=0; cpt < OrdersTotal(); cpt++ )
   {
      OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
      if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol())
      {
         if(!initialPrice) initialPrice = StrToDouble(OrderComment());
         if(UsePartialProfitTarget && UseProfitTarget && OrderType() < 2)
         {
            double val=getPipValue(OrderOpenPrice(),OrderType());
            takeProfit(val,OrderTicket()); 
         }
      }
   }

   if( openOrderCount < 1 )
   {
      // If we have no open positions, reset mode to ACCUMULATE
      Mode = ACCUMULATE;

      // Set spread for this set
      spread = Ask - Bid;

      // Check to see if this is a good time to enter a new set - 
      // Run all filters in here (trend, volatility, time of day, etc.) 
      // to try to maxamize chances of avoiding the dreaded death trade

      if( !tradingIsDesirable() ) return (0);

      // Set all variables which should remain fixed for duration of trade sequence
      
      // Compute the best grid increment for this set of trades - 
      // then remains fixed for the entire set
   
      increment = Increment;
      if( increment == 0 ) increment = computeAutoIncrement();

      incrementAdjust = IncrementAdjustForTpSl;
      levels = Levels;
      percentToRisk = PercentToRisk;
      
      Lots = computeLots( percentToRisk );


      Print("** STARTING NEW TRADE SET **");
      
      //+------------------------------------------------------------------+
      // - Open Check - Start Cycle
      initialPrice=Ask;
      sellGoal = initialPrice - ((Levels+1)*increment+incrementAdjust)*PointValue;
      buyGoal  = initialPrice + ((Levels+1)*increment+incrementAdjust)*PointValue;
      
      for(cpt=1; cpt <= Levels; cpt++)
      {
         OrderSendReliable(Symbol(),OP_BUYSTOP,Lots,initialPrice+cpt*increment*PointValue,slippage,
                           sellGoal,buyGoal,DoubleToStr(initialPrice,Digits),MagicNumber,0);
         OrderSendReliable(Symbol(),OP_SELLSTOP,Lots,initialPrice-cpt*increment*PointValue,slippage,
                           buyGoal+spread,sellGoal+spread,DoubleToStr(initialPrice,Digits),MagicNumber,0);
      }
   } // initial entry setup done - all channels are set up

   else if(Mode == ACCUMULATE) // We are in the middle of a trade set
   {
      // If we have closed any orders from the set, close them all
      openOrderCount = OrdersHistoryTotal();
      for(cpt=0; cpt < openOrderCount; cpt++)
      {
         OrderSelect(cpt,SELECT_BY_POS,MODE_HISTORY);
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber && StrToDouble(OrderComment())==initialPrice)
         {
            endSession();
            return(0);
         }
      }

      profitTarget = increment*2;
      if(UseProfitTarget && checkProfits(Lots,OP_SELL,true,initialPrice) > profitTarget) 
      {
         endSession();
         return(0);
      }
      
      buyGoal  = initialPrice + ((Levels+1)*increment+incrementAdjust)*PointValue;
      sellGoal = initialPrice - ((Levels+1)*increment+incrementAdjust)*PointValue;

      buyGoalProfit  = checkProfits(Lots,OP_BUY,false,initialPrice);
      sellGoalProfit = checkProfits(Lots,OP_SELL,false,initialPrice);
      
      if(buyGoalProfit < profitTarget)
      // - Increment Lots Buy
      {
         for(cpt=Levels; cpt >= 1 && buyGoalProfit < profitTarget; cpt--)
         {
            if(Ask <= (initialPrice+(cpt*increment-MarketInfo(Symbol(),MODE_STOPLEVEL))*PointValue))
            {
               ticket =
               OrderSendReliable(Symbol(),OP_BUYSTOP,cpt*Lots,initialPrice+cpt*increment*PointValue,slippage,sellGoal,
                                 buyGoal,DoubleToStr(initialPrice,Digits),MagicNumber,0);
            }
            if(ticket > 0) buyGoalProfit += Lots*(buyGoal-initialPrice-cpt*increment*PointValue)/PointValue;
         }
      }

      if(sellGoalProfit < profitTarget)
      // - increment Lots Sell
      {
         for(cpt=Levels; cpt >= 1 && sellGoalProfit < profitTarget; cpt--)
         {
            if(Bid >= (initialPrice-(cpt*increment-MarketInfo(Symbol(),MODE_STOPLEVEL))*PointValue))
            {
               ticket =
               OrderSendReliable(Symbol(),OP_SELLSTOP,cpt*Lots,initialPrice-cpt*increment*PointValue,slippage,buyGoal+spread,
                                 sellGoal+spread,DoubleToStr(initialPrice,Digits),MagicNumber,0);
            }
            if(ticket > 0) sellGoalProfit += Lots*(initialPrice-cpt*increment*PointValue-sellGoal-spread)/PointValue;
         }
      }
      
      // Check high-water mark
      if( (MaxPercentMarginLiquidate > 0 && percentMarginUsed > MaxPercentMarginLiquidate) ||
          (MaxLots > 0 && totalPositionSize >= MaxLots) ) 
      {
         Mode = LIQUIDATE;
         Print("** EXCEEDED MAX ALLOWED MARGIN - LIQUIDATING!! **");
      }
   }
   else  // Mode = LIQUIDATE
   {
      // If we can exit the entire set for a profit or breakeven, do it
      if( tradeProfit > 0 ) endSession();

      // First delete all pending orders - lets not dig ourselves any deeper
   
      // Next ideally, we want to liquidate every order we can for a profit.
      // Try to get a single Increments worth of profit out to minimize the loss when the TP/SL
      // is finally triggered. 
      // In the best situation, the market will continue sideways long enough and wide enough 
      // to allow us to liquidate everything for a profit - after all, that is what it did to get
      // us into this mess  :-)
   
      openOrderCount = OrdersTotal();
   
      for(cpt=0; cpt < openOrderCount; cpt++)
      {
         OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
         if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber )
         {
            if(OrderType() > 1) OrderDelete(OrderTicket());
            if(OrderType() == OP_BUY && (Bid-OrderOpenPrice())/PointValue > increment) 
               OrderCloseReliable(OrderTicket(),OrderLots(),Bid,MaxExitSlippage);
            if(OrderType() == OP_SELL && (OrderOpenPrice()-Ask)/PointValue > increment) 
               OrderCloseReliable(OrderTicket(),OrderLots(),Ask,MaxExitSlippage);               
            Sleep(3000);
         }
      }
   }
   
   // Check low-water mark 
   if( (MaxPercentMarginProfitEscape > 0 && percentMarginUsed > MaxPercentMarginProfitEscape) && tradeProfit > 0 )
   {
      Print("** EXCEEDED MARGIN WARNING - PROFIT EXIT!! **");
      endSession();
   }
   
   // Cut Losses
   if( OpenLossToCloseTrades < 0.0 && tradeProfit <= OpenLossToCloseTrades )
   {
      Print("** EXCEEDED MAX INTRASET LOSS - EXITING POSITIONS! **");
      endSession();
   }

   //+------------------------------------------------------------------+   
   
   Comment("ViperGrid EXPERT ADVISOR" + Version +"\n",
            "FX Acc Server:",AccountServer(),"\n",
            "Date: ",Month(),"-",Day(),"-",Year()," Server Time: ",Hour(),":",Minute(),":",Seconds(),"\n",
            "Minimum Lot Sizing: ",MarketInfo(Symbol(),MODE_MINLOT),"\n",
            "Account Balance:  $",AccountBalance(),"\n",
            "Symbol: ", Symbol(),"\n",
            "Price:  ",NormalizeDouble(Bid,4),"\n",
            "Pip Spread:  ",MarketInfo(Symbol(),MODE_SPREAD),"\n",
            "Lots:  ",Lots,"\n",
            "Levels: " + levels,"\n",
            "increment: " +  increment,"\n",
            "Free Margin: " + AccountFreeMargin(),"\n",
            "Free Equity: " + AccountEquity(),"\n");
   
   return(0);
}


//+------------------------------------------------------------------+
//| Function:  checkProfits
//+------------------------------------------------------------------+
int 
checkProfits(double lots, int goal, bool current, double initialPrice)
{
   int profit=0, cpt;
   if(current)//return current profit
   {
      for(cpt=0;cpt<OrdersTotal();cpt++)
      {
         OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
         if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==initialPrice)
         {
            if(OrderType()==OP_BUY) profit+=(Bid-OrderOpenPrice())/PointValue*OrderLots()/lots;
            if(OrderType()==OP_SELL) profit+=(OrderOpenPrice()-Ask)/PointValue*OrderLots()/lots;
         }
      }
      return(profit);
   }
   else
   {
      if(goal==OP_BUY)
      {
         for(cpt=0;cpt<OrdersTotal();cpt++)
         {
            OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==initialPrice)
            {
               if(OrderType()==OP_BUY)     profit+=(OrderTakeProfit()-OrderOpenPrice())/PointValue*OrderLots()/lots;
               if(OrderType()==OP_SELL)    profit-=(OrderStopLoss()-OrderOpenPrice())/PointValue*OrderLots()/lots;
               if(OrderType()==OP_BUYSTOP) profit+=(OrderTakeProfit()-OrderOpenPrice())/PointValue*OrderLots()/lots;
            }
         }
         return(profit);
      }
      else
      {
         for(cpt=0;cpt<OrdersTotal();cpt++)
         {
            OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==initialPrice)
            {
               if(OrderType()==OP_BUY)      profit-=(OrderOpenPrice()-OrderStopLoss())/PointValue*OrderLots()/lots;
               if(OrderType()==OP_SELL)     profit+=(OrderOpenPrice()-OrderTakeProfit())/PointValue*OrderLots()/lots;
               if(OrderType()==OP_SELLSTOP) profit+=(OrderOpenPrice()-OrderTakeProfit())/PointValue*OrderLots()/lots;              
            }
         }
         return(profit);
      }
   }
}


//+------------------------------------------------------------------+
//| Function:  endSession
//+------------------------------------------------------------------+
void 
endSession()
{
   int cpt, openOrderCount=OrdersTotal();
   
   for(cpt=0; cpt < openOrderCount; cpt++)
   {
      OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
      {
         if(OrderType()>1) OrderDelete(OrderTicket());
         else if(OrderType()==OP_BUY)  OrderCloseReliable(OrderTicket(),OrderLots(),Bid,MaxExitSlippage);
         else if(OrderType()==OP_SELL) OrderCloseReliable(OrderTicket(),OrderLots(),Ask,MaxExitSlippage);
         Sleep(1000);
      }
   }
}


//+------------------------------------------------------------------+
//| Function:  getPipValue                            
//+------------------------------------------------------------------+
double 
getPipValue(double entryPrice, int dir)
{
   double val;
   RefreshRates();
   if(dir == 1) val = (NormalizeDouble(entryPrice,Digits) - NormalizeDouble(Ask,Digits));
   else         val = (NormalizeDouble(Bid,Digits) - NormalizeDouble(entryPrice,Digits));

   val /= PointValue;

   return(val);   
}


//+------------------------------------------------------------------+
//| Function:  takeProfit
//+------------------------------------------------------------------+
void 
takeProfit(int current_pips, int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET))
   {
      if(current_pips >= NextTarget && current_pips < (NextTarget + TargetAutoIncrement ))
      {
         if(OrderType()==1)
         {
            if(OrderCloseReliable(ticket, OrderLots(), Ask, MaxExitSlippage))
               NextTarget+=TargetAutoIncrement;
            else
               Print("Error closing order : ",GetLastError()); 
         } 
         else
         {
            if(OrderCloseReliable(ticket, OrderLots(), Bid, MaxExitSlippage))
               NextTarget+=TargetAutoIncrement ;
            else
               Print("Error closing order : ",GetLastError());  
         }        
      }
   }
}


//+------------------------------------------------------------------+
//| Function:  computeAutoIncrement
//+------------------------------------------------------------------+
int 
computeAutoIncrement()
{
   //----Collect daily range info
   double  riskToRewardRatio =  3.0;  

   int R1=0, R5=0, R10=0, R20=0, autoIncrement=0;
   int RAvg=0;
   int spreadValue = (Ask - Bid) / PointValue;

   int CURRENT_INDEX = 1;
   
   // Get the average daily range in pips
   R1  = iATR(NULL,PERIOD_D1, 1,CURRENT_INDEX) / PointValue;
   R5  = iATR(NULL,PERIOD_D1, 5,CURRENT_INDEX) / PointValue;
   R10 = iATR(NULL,PERIOD_D1,10,CURRENT_INDEX) / PointValue;
   R20 = iATR(NULL,PERIOD_D1,20,CURRENT_INDEX) / PointValue;
   RAvg  =  (3*R1+2*R5+R10+R20) / 7;

   // AutoIncrement calculation  R1 = Previous Day range, R5 = 5 day,  R10=10 Day
   // AutoIncrement replaces the need to manaully set increment.  PreviousDay R1 is more heavily weighted
   // then the R5 range.  
                                                                        // Equation history for reference
   autoIncrement = (RAvg  / (Levels + 1) ) / 2;                        //  ((((R5*0.4) + (R1*0.6))  / (Levels + 1)) / (2));
                                                                      //   (((R5)/(Levels + 1))/2);

   Print("Setting autoincrement; RAvg="+RAvg+"; autoIncrement="+autoIncrement);

   if(autoIncrement < MarketInfo(Symbol(),MODE_STOPLEVEL)+spreadValue)
   {
      autoIncrement = MarketInfo(Symbol(),MODE_STOPLEVEL)+spreadValue+1;
   }

   return(autoIncrement);
}


//+------------------------------------------------------------------+
//| Function:  computeSessionStats
//+------------------------------------------------------------------+
void
computeSessionStats( int & openOrderCount, int & tradeProfit, 
                     double & totalPositionSize, int & percentMarginUsed ) 
{
   for( int cpt=0; cpt < OrdersTotal(); cpt++ )
   {
      OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
      if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol())
      {
         openOrderCount++;
         tradeProfit += OrderProfit();
         totalPositionSize += OrderLots();
      }
   }
   
   percentMarginUsed = AccountMargin() / (AccountMargin() + AccountFreeMargin()) * 100;
}


//+------------------------------------------------------------------+
//| Function:  computeLots
//+------------------------------------------------------------------+
double
computeLots( double percentEquityToRisk ) 
{
   double MINLOT = MarketInfo(Symbol(),MODE_MINLOT);
   double lots = MINLOT;
   
   if( percentEquityToRisk > 0 )
   {
      lots = NormalizeDouble(AccountBalance()*AccountLeverage()/1000000*percentEquityToRisk,0) * MINLOT;
      if(lots < MINLOT) lots = MINLOT;
   }
   
   return (lots);
}


//+------------------------------------------------------------------+
//| Function:  tradingIsDesirable
//| Entry condition filters
//+------------------------------------------------------------------+
bool
tradingIsDesirable()
{
   bool isDesirable = true;
   string failReason = "ViperGridEA: "+Symbol()+"; No trade allowed; \n";


   //-----------------------------------------------------------------------------
   // Perform time of day test
   int currentHour = Hour();
   bool inDefinedWindow = (currentHour >= MinHourToStart && currentHour <= MaxHourToStart);
   if( (!InvertTimeWindow && !inDefinedWindow) ||
       ( InvertTimeWindow && inDefinedWindow)  )
   {
      isDesirable = false;
      failReason = failReason + "Not within allowed time window; \n";
   }


   //-----------------------------------------------------------------------------
   // Perform StdDev test

   int maPeriod=10;
   int maShift=0;     //MA shift. 
   //  methods="**0-SMA,1-EMA,2-SMMA,3-LWMA**";
   int maMethod=1;    
   //  AppliedPrice="**0-Close,1-Open,2-Hi,3-Low,4-Med,5-Typ,6-Weighted**";
   int appliedPrice=0; 
   int shift=0;         

   if( MinStandardDeviation != 0.0 )
   {
      double sval=iStdDev(NULL,StandardDevTimeFrame,maPeriod,maShift,maMethod,appliedPrice,shift);
    
      if(sval <= MinStandardDeviation)
      {
         isDesirable = false;
         failReason = failReason + "Insufficient volatility according to Standard Deviation; \n";
      }
   }


   //-----------------------------------------------------------------------------
   // Perform trending test
   // Don't care if it is moving up or down just that it is moving
   // Can force to pass multiple timeframes if desired -
   
   if( UseTrendFilter )
   {
      if( trendDirection(PERIOD_D1) == 0 )
      {
         isDesirable = false;
         failReason = failReason + "Insufficient trend strength; \n";
      }
   }


   //-----------------------------------------------------------------------------
   // 
   
   if( MaxSpreadToOpen > 0 && spread > MaxSpreadToOpen )
   {
      {
         isDesirable = false;
         failReason = failReason + "Spread too wide; \n";
      }
   }


   //-----------------------------------------------------------------------------
   // Completed all Entry filters - comment on failed entry

   if( !isDesirable )
   {
      Comment( "                                          ","\n",   
               "**Unable to Enter Market due to the following reason(s)**","\n",
               failReason ,"\n");
   }


   // return result of filter tests
   return (isDesirable);
}


//+------------------------------------------------------------------+
//| Function:  trendDirection
//+------------------------------------------------------------------+
int
trendDirection(int timeframe)
{
   int currentTrend = 0;

   // Check for trend - (non-flat)

   int rsiPeriod = 24, cciPeriod = 50;
   int shortEma = 21, longEma = 55;

   double rsi          = iRSI(NULL,timeframe,rsiPeriod,PRICE_CLOSE,1);
   double cci          = iCCI(NULL,timeframe,cciPeriod,PRICE_TYPICAL,1);
   double ShortMaOpen  = iMA(NULL,timeframe,shortEma,0,MODE_EMA,PRICE_OPEN,1);
   double ShortMaClose = iMA(NULL,timeframe,shortEma,0,MODE_EMA,PRICE_CLOSE,1);
   double LongMaHi     = iMA(NULL,timeframe,longEma,0,MODE_EMA,PRICE_HIGH,1);
   double LongMaLo     = iMA(NULL,timeframe,longEma,0,MODE_EMA,PRICE_LOW,1);

   if(ShortMaClose >= ShortMaOpen && ShortMaClose >= LongMaHi && rsi >= 50 && cci >= 0) currentTrend =  1;
   if(ShortMaClose <= ShortMaOpen && ShortMaClose <= LongMaLo && rsi <= 50 && cci <= 0) currentTrend = -1;

   return( currentTrend );
}


