//+------------------------------------------------------------------+
//|                                        smMilliped Signals_v1.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010.08.10 SwingMan"
#property link      ""

/*--------------------------------------------------------------------
2010.08.10 v1 - combination of Kinetic(Ema 6,8&ZeroLagMACD) + AOAC
--------------------------------------------------------------------*/
#property indicator_chart_window

#property indicator_buffers 2
#property indicator_color1 DodgerBlue
#property indicator_color2 DeepPink

#property indicator_width1 1
#property indicator_width2 1

string sIndicatorName = "SwingMan Milliped-Signals (Kinetic,AO,AC)";

//---- input parameters 
//+------------------------------------------------------------------+
extern bool Draw_EntryLabels = true;
extern string ____MovingAverages="";
extern int periodCloses = 6; 
extern int periodOpens = 8; 
extern string ____ZeroLag_MACD="";
extern int FastEMA = 12; 
extern int SlowEMA = 24;
extern int SignalEMA = 9;
extern int ma_method  = MODE_EMA;
extern int MaxBars = 2000;//1025;
extern double factorWindow=0.03;
//+------------------------------------------------------------------+

//---- buffers 
double signalUP[],signalDN[];
double tempSignals[];
//---- buffers temp
double UpTrend[], DnTrend[];
double UpTrend1[], DnTrend1[];
double UpTrend2[], DnTrend2[];
double UpTrend3[], DnTrend3[];

//---- buffers Kinetic
double MACDBuffer[];
double MACDBufferUp[];
double MACDBufferDn[];
double SignalBuffer[];
double FastEMABuffer[];
double SlowEMABuffer[];
double SignalEMABuffer[];

//---- variables
double histValue=1;
datetime thisTime,oldTime;
bool newBar;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   ArraySetAsSeries(MACDBuffer,true);
   ArraySetAsSeries(MACDBufferUp,true);
   ArraySetAsSeries(MACDBufferDn,true);
   ArraySetAsSeries(SignalBuffer,true);
   ArraySetAsSeries(FastEMABuffer,true);
   ArraySetAsSeries(SlowEMABuffer,true);
   ArraySetAsSeries(SignalEMABuffer,true);
   
   ArraySetAsSeries(UpTrend,true); ArraySetAsSeries(DnTrend,true);
   ArraySetAsSeries(UpTrend1,true); ArraySetAsSeries(DnTrend1,true);
   ArraySetAsSeries(UpTrend2,true); ArraySetAsSeries(DnTrend2,true);
   ArraySetAsSeries(UpTrend3,true); ArraySetAsSeries(DnTrend3,true);
   //ArraySetAsSeries(tempSignals,true);
   
   IndicatorShortName(sIndicatorName);
   Comment(sIndicatorName);
   
   IndicatorBuffers(3);
   // signals .......................................................
   int arrowUP=233;
   int arrowDN=234;
   SetIndexBuffer(0, signalUP); SetIndexStyle(0,DRAW_ARROW); SetIndexArrow(0,arrowUP);
   SetIndexBuffer(1, signalDN); SetIndexStyle(1,DRAW_ARROW); SetIndexArrow(1,arrowDN);
   
   SetIndexBuffer(2, tempSignals);
   
   SetIndexLabel(0,"Milliped UP");     
   SetIndexLabel(1,"Milliped DOWN");   
   
   IndicatorDigits(Digits);
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   Comment("");
   Delete_Objects("eaEntry_");
   return(0);
}

//####################################################################
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   ArrayResize(MACDBuffer,Bars);
   ArrayResize(MACDBufferUp,Bars);
   ArrayResize(MACDBufferDn,Bars);
   ArrayResize(SignalBuffer,Bars);
   ArrayResize(FastEMABuffer,Bars);
   ArrayResize(SlowEMABuffer,Bars);
   ArrayResize(SignalEMABuffer,Bars);
   
   ArrayResize(UpTrend,Bars); ArrayResize(DnTrend,Bars);
   ArrayResize(UpTrend1,Bars); ArrayResize(DnTrend1,Bars);
   ArrayResize(UpTrend2,Bars); ArrayResize(DnTrend2,Bars);
   ArrayResize(UpTrend3,Bars); ArrayResize(DnTrend3,Bars);
   //ArrayResize(tempSignals,Bars);
   
   int i,limit;
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
   
   if (limit>MaxBars) limit=MaxBars;
   else
   if (Bars-2<MaxBars) 
   {
      MaxBars=Bars-2; 
      limit=MaxBars;
   }

   
               //*********************************      
               //    1. MOVING AVERAGES          *
               //*********************************
   for(i=0; i<limit; i++)
   {
      UpTrend1[i] = EMPTY_VALUE;
      DnTrend1[i] = EMPTY_VALUE;

      double closeLine = iMA(Symbol(),Period(), periodCloses,0,ma_method,PRICE_CLOSE,i);
      double openLine  = iMA(Symbol(),Period(), periodOpens, 0,ma_method,PRICE_OPEN,i);
      
      bool Cond_Long1  = (closeLine>openLine);                        
      bool Cond_Short1 = (closeLine<openLine);
                            
      if (Cond_Long1)
         UpTrend1[i] = histValue;
      else         
      if (Cond_Short1)
         DnTrend1[i] = histValue;
   }
   
               //*********************************      
               //    2. ZeroLag MACD             *
               //*********************************
   //==========================
   Get_ZeroLagMACDValues(limit);
   //==========================
   
   for(i=0; i<limit; i++)
   {      
      UpTrend2[i] = EMPTY_VALUE;
      DnTrend2[i] = EMPTY_VALUE;
      
      if (MACDBufferUp[i]!=EMPTY_VALUE) 
         UpTrend2[i]=histValue;
      if (MACDBufferDn[i]!=EMPTY_VALUE) 
         DnTrend2[i]=histValue;   
   } 
   
               //*********************************      
               //    3. AO & AC                  *
               //*********************************   
   for(i=0; i<limit; i++)
   {
      UpTrend3[i] = EMPTY_VALUE;
      DnTrend3[i] = EMPTY_VALUE;
      
      double AO_Line0  =  iAO(Symbol(),Period(),i);
      double AO_Line1  =  iAO(Symbol(),Period(),i+1);
      double AC_Line0  =  iAC(Symbol(),Period(),i);
      double AC_Line1  =  iAC(Symbol(),Period(),i+1);
      
      int idxAO = 0;
      if (AO_Line0 > AO_Line1) idxAO = 1; else
      if (AO_Line0 < AO_Line1) idxAO = -1;
      
      int idxAC = 0;
      if (AC_Line0 > AC_Line1) idxAC = 1; else
      if (AC_Line0 < AC_Line1) idxAC = -1;
      
      bool Cond_Long3  = (idxAO==1 && idxAC==1);
      bool Cond_Short3 = (idxAO==-1 && idxAC==-1);
                            
      if (Cond_Long3)
         UpTrend3[i] = histValue;
      else         
      if (Cond_Short3)
         DnTrend3[i] = histValue;
   }  

               //*********************************      
               //    UP/DN TREND                 *
               //*********************************      
   for(i=limit; i>=0; i--)
   {
      UpTrend[i] = EMPTY_VALUE;
      DnTrend[i] = EMPTY_VALUE;

      if (UpTrend1[i]!=EMPTY_VALUE && 
          UpTrend2[i]!=EMPTY_VALUE &&
          UpTrend3[i]!=EMPTY_VALUE)
      {
         UpTrend[i] = histValue;      
      }
      else
      if (DnTrend1[i]!=EMPTY_VALUE && 
          DnTrend2[i]!=EMPTY_VALUE &&
          DnTrend3[i]!=EMPTY_VALUE)
      {
         DnTrend[i] = histValue;      
      }
   }               
   
               //*********************************      
               //    SIGNALS                     *
               //*********************************
   int prevSignal;
   double windHeight = WindowPriceMax() - WindowPriceMin();
   double offset = windHeight*factorWindow;               
   
   tempSignals[MaxBars+1] = EMPTY_VALUE;

   for(i=limit; i>=0; i--)
   {        
      prevSignal = tempSignals[i+1];
            
      if (UpTrend[i]!=EMPTY_VALUE && (prevSignal==-1 || prevSignal==EMPTY_VALUE))
      {
         signalUP[i]    = Low[i]-offset;      
         tempSignals[i] = 1;
      }
      else
      if (DnTrend[i]!=EMPTY_VALUE && (prevSignal==1 || prevSignal==EMPTY_VALUE))
      {
         signalDN[i]    = High[i]+offset;
         tempSignals[i] = -1;
      }
      else
      {
         signalUP[i] = EMPTY_VALUE;
         signalDN[i] = EMPTY_VALUE;
         tempSignals[i]=tempSignals[i+1];
         Delete_SingleObject(i);
      }   
      
      //-- Draw Entry Labels ----------------------------------------
      thisTime=Time[i];
      if (thisTime!=oldTime)
      {
         oldTime=thisTime; newBar=true;
      }
      else newBar=false;
      
      if (newBar && Draw_EntryLabels)
      {
         if (signalUP[i+1]!=EMPTY_VALUE)
            DrawArrow_Entry(i, Open[i], Blue);
         else   
         if (signalDN[i+1]!=EMPTY_VALUE)
            DrawArrow_Entry(i, Open[i], DeepPink);
      }
   }
   
/*Comment(
"Time=",TimeToStr(TimeCurrent(),TIME_MINUTES|TIME_SECONDS),"\n",
"limit=",limit,"\n",
"sig0=",tempSignals[0],"\n",
"sig1=",tempSignals[1],"\n",
"sig2=",tempSignals[2],"\n",
"sig3=",tempSignals[3],"\n",
"sig4=",tempSignals[4]
);*/

//----
   return(0);
}
//+------------------------------------------------------------------+

//___________________________________________________________________
void Get_ZeroLagMACDValues(int limit)
{
double EMA, ZeroLagEMAp, ZeroLagEMAq;

   for(int i = 0; i < limit; i++)
     {
       FastEMABuffer[i] = iMA(NULL, 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE, i);
       SlowEMABuffer[i] = iMA(NULL, 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, i);
     }
   for(i = 0; i < limit; i++)
     {
        EMA = iMAOnArray(FastEMABuffer, Bars, FastEMA, 0, MODE_EMA, i);
        ZeroLagEMAp = FastEMABuffer[i] + FastEMABuffer[i] - EMA;
        EMA = iMAOnArray(SlowEMABuffer, Bars, SlowEMA, 0, MODE_EMA, i);
        ZeroLagEMAq = SlowEMABuffer[i] + SlowEMABuffer[i] - EMA;
        MACDBuffer[i] = ZeroLagEMAp - ZeroLagEMAq;
     }
   for(i = 0; i < limit; i++)
       SignalEMABuffer[i] = iMAOnArray(MACDBuffer, Bars, SignalEMA, 0, MODE_EMA, i);
   for(i = 0; i < limit; i++)
     {
       EMA = iMAOnArray(SignalEMABuffer, Bars, SignalEMA, 0, MODE_EMA, i);
       SignalBuffer[i] = SignalEMABuffer[i] + SignalEMABuffer[i] - EMA;
   }
   for (i=limit-1; i>=0; i--) {
      if (MACDBufferUp[i+1] != EMPTY_VALUE && MACDBufferUp[i+1] == MACDBuffer[i+1]) {
         MACDBufferUp[i] = MACDBuffer[i];
      } else if (MACDBufferDn[i+1] != EMPTY_VALUE && MACDBufferDn[i+1] == MACDBuffer[i+1]) {
         MACDBufferDn[i] = MACDBuffer[i];
      }

      if (MACDBuffer[i+1] < MACDBuffer[i]) {
         MACDBufferUp[i] = MACDBuffer[i];
         MACDBufferDn[i] = EMPTY_VALUE;
      } else if (MACDBuffer[i+1] > MACDBuffer[i]) {
         MACDBufferDn[i] = MACDBuffer[i];
         MACDBufferUp[i] = EMPTY_VALUE;
      }
     }
}//Get_ZeroLagMACDValues

int arrowWidth = 2;
//____________________________________________________________________
void DrawArrow_Entry(int iBar, double dValue, color dColor)
{
   string sObjName = "eaEntry_" + TimeToStr(Time[iBar])+"_";
   Delete_Objects(sObjName);
   sObjName = sObjName + DoubleToStr(dValue,Digits);
   ObjectCreate(sObjName,OBJ_ARROW,0,Time[iBar],dValue);
   ObjectSet(sObjName,OBJPROP_COLOR,dColor);
   ObjectSet(sObjName,OBJPROP_WIDTH,arrowWidth);
   ObjectSet(sObjName,OBJPROP_ARROWCODE,SYMBOL_LEFTPRICE);
   ObjectSet(sObjName,OBJPROP_BACK,false);
   //objEntryArrow=sObjName;
   return;
}//DrawArrow_Entry

//___________________________________________________________________
void Delete_Objects(string sText)
{
   int total = ObjectsTotal();
   for (int i = total; i>= 0; i--)
   {
      string sObjectName = ObjectName(i);
      if (StringFind(sObjectName, sText, 0) != -1) {
         ObjectDelete(sObjectName);
      }
   }   
   return;
}//Delete_Objects

//___________________________________________________________________
void Delete_SingleObject(int iBar)
{
   string sObjName = "eaEntry_" + TimeToStr(Time[iBar])+"_";
   Delete_Objects(sObjName);   
   return;
}//Delete_SingleObject