//+------------------------------------------------------------------+
//|                                    Damon smTradeSignals_v1.4.mq4 |
//|                                                         SwingMan |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "© 2008, SwingMan"
#property link      ""
//+------------------------------------------------------------------+
// v1.3 2008.03.26  show Alerts Reversal Signals
// v1.4 2008.03.26  Damon smNonLagMA is integrated in the code / more speeder
//+------------------------------------------------------------------+

#property indicator_chart_window

//---- constants
string windowsName = "smTradeSignals_v1.4";

//---- extern inputs -------------------------------------------------
extern bool Show_ReverseSignals = true;
//extern bool Show_Signals_2 = true;
//extern bool Show_Signals_3 = true;
extern bool SendAlert_ReverseSignals = true;
//extern bool SendAlert_Signals_2 = false;
//extern bool SendAlert_Signals_3 = false;
//extern bool Show_Values = false;
//-- indicators
extern string SymbolSuffix = "";
extern int Period_SilverTrend = 9;
extern int Period_NonLagMA = 9;
extern int Period_avg = 5;
extern int Period_ATR = 21;
//--------------------------------------------------------------------

#property indicator_buffers 2
#property indicator_color1 DeepSkyBlue  // EntryLong 1
#property indicator_color2 Magenta   // EntryShort 1
//#property indicator_color3 Blue  // EntryLong 2
//#property indicator_color4 Red   // EntryShort 2
//#property indicator_color5 Blue  // EntryLong 3
//#property indicator_color6 Red   // EntryShort 3

//---- buffers
double EntryLong1[], EntryShort1[];
double EntryLong2[], EntryShort2[];
double EntryLong3[], EntryShort3[];
double BufferNonLagMA[];
int BufferST[], BufferNL[];

//---- constants
string sNonLagMA_Name = "Damon smNonLagMA_v1";

//---- variables
double old_STSignal;
string symbol;
int timeframe, Otstup; 
double Spread;
datetime oldTimeAlert;

//---- variables for NonLag MA ---------------------------------------
int     Price          = 0;  //Apply to Price(0-Close;) 
int     Length         = 9;  //Period of NonLagMA
int     Displace       = 0;  //DispLace or Shift 
double  PctFilter      = 0;  //Dynamic filter in decimal
double  Deviation      = 0;  //Up/down deviation    
//---- indicator buffers
double MABuffer[];
double Del[];
double AvgDel[];
//---- variables NL
double alfa[];
int i, Phase, Len,Cycle=4;
double Coeff, beta, t, Sum, Weight, g;
double pi = 3.1415926535;    

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   symbol = Symbol();
   timeframe = Period();
   Otstup = Get_DefaultOtstup(symbol);
   Spread = MarketInfo(Symbol(), MODE_SPREAD) * Point;
   //-- Arrays
   ArraySetAsSeries(BufferST, true);
   ArraySetAsSeries(BufferNL, true);
   ArraySetAsSeries(BufferNonLagMA, true);
   //-- NL buffers
   ArraySetAsSeries(MABuffer, true);
   ArraySetAsSeries(Del, true);
   ArraySetAsSeries(AvgDel, true);
   ArraySetAsSeries(alfa, true);   
   
   //-- Reverse Signals
   if (Show_ReverseSignals) {
      SetIndexBuffer(0, EntryLong1);   SetIndexStyle(0,DRAW_ARROW,EMPTY,2);       
      SetIndexBuffer(1, EntryShort1);  SetIndexStyle(1,DRAW_ARROW,EMPTY,2); 
      SetIndexLabel(0, "ReverseToLong"); SetIndexLabel(1, "ReverseToShort");
   } else
   {
      SetIndexBuffer(0, EntryLong1);   SetIndexStyle(0,DRAW_ARROW,EMPTY,2); 
      SetIndexBuffer(1, EntryShort1);  SetIndexStyle(1,DRAW_ARROW,EMPTY,2); 
      SetIndexLabel(0, NULL); SetIndexLabel(1, NULL);
   }
   SetIndexArrow(0, 233); // Entry1
   SetIndexArrow(1, 234);
   /*
   SetIndexBuffer(2, EntryLong2);   SetIndexStyle(2,DRAW_ARROW,EMPTY,2); 
   SetIndexBuffer(3, EntryShort2);  SetIndexStyle(3,DRAW_ARROW,EMPTY,2); 
   SetIndexBuffer(4, EntryLong3);   SetIndexStyle(4,DRAW_ARROW,EMPTY,2); 
   SetIndexBuffer(5, EntryShort3);  SetIndexStyle(5,DRAW_ARROW,EMPTY,2);     

   SetIndexArrow(2, 241); // Entry2
   SetIndexArrow(3, 242);
   SetIndexArrow(4, 217); // Entry3
   SetIndexArrow(5, 218);
   
   SetIndexLabel(2, "EntryLong 2"); SetIndexLabel(3, "EntryShort 2");
   SetIndexLabel(4, "EntryLong 3"); SetIndexLabel(5, "EntryShort 3");
   */
   old_STSignal = 0; 
   
//---- NonLag MA initialisations
   Length = Period_NonLagMA;
   Coeff =  3*pi;
   Phase = Length-1;
   Len = Length*4 + Phase;  
   ArrayResize(alfa,Len);
   Weight=0;    
      
   for (i=0;i<Len-1;i++)
   {
      if (i<=Phase-1) t = 1.0*i/(Phase-1);
      else t = 1.0 + (i-Phase+1)*(2.0*Cycle-1.0)/(Cycle*Length-1.0); 
      beta = MathCos(pi*t);
      g = 1.0/(Coeff*t+1);   
      if (t <= 0.5 ) g = 1;
      alfa[i] = g * beta;
      Weight += alfa[i];
   }     
//----
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   Comment("");
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int i,shift,limit;
   
   ArrayResize(BufferST, Bars);
   ArrayResize(BufferNL, Bars);
   ArrayResize(BufferNonLagMA, Bars);
   //-- NL buffers
   ArrayResize(MABuffer, Bars);
   ArrayResize(Del, Bars);
   ArrayResize(AvgDel, Bars);
   ArrayResize(alfa, Bars);
   
   int counted_bars=IndicatorCounted();
   /*if(counted_bars < 0) return(-1); 
   if(counted_bars > 0) counted_bars--; 
   int limit=Bars-counted_bars;*/
   
   if ( counted_bars > 0 )  limit=Bars-counted_bars;
   if ( counted_bars < 0 )  return(0);
   if ( counted_bars ==0 )  limit=Bars-Len-1; 
   if ( counted_bars < 1 )  for(i=1;i<Length*Cycle+Length;i++) MABuffer[Bars-i]=0;
   
   
   //---- 1. signals SilverTrend -------------------------------------
   for (int SH=1; SH<=limit; SH++) {
      int iSilverTrend = 0;
      int shiftHighest = iHighest(symbol,timeframe,MODE_HIGH,Period_SilverTrend,SH);
      double SHMax = iHigh(symbol, timeframe, shiftHighest);
      
      int shiftLowest = iLowest(symbol,timeframe,MODE_LOW,Period_SilverTrend,SH);
      double SHMin = iLow(symbol, timeframe, shiftLowest);
      
      //-- Long signal
      if (iClose(symbol, timeframe,SH)<=SHMin+(SHMax-SHMin)*Otstup/100.0)
         iSilverTrend = 1;
      
      //-- short signal
      if (iClose(symbol, timeframe,SH)>=SHMax-(SHMax-SHMin)*Otstup/100.0)
         iSilverTrend = -1;
      
      BufferST[SH] = iSilverTrend;
   }  
   
   
   //---- 2. signals NonLag MA ---------------------------------------
   for(i=1;i<Length*Cycle+Length;i++)    
      MABuffer[Bars-i]=0;    
   
   for(shift=limit;shift>=0;shift--) {	
      Sum = 0;
      for (i=0;i<=Len-1;i++) { 
         double price = iMA(Symbol(),0,1,0,3,Price,i+shift);      
         Sum+= alfa[i]*price;      
      }
   
	   if (Weight > 0) MABuffer[shift] = (1.0+Deviation/100)*Sum/Weight;   
      
      if (PctFilter>0) {
         Del[shift] = MathAbs(MABuffer[shift] - MABuffer[shift+1]);
   
         double sumdel=0;
         for (i=0;i<=Length-1;i++) sumdel = sumdel+Del[shift+i];
         AvgDel[shift] = sumdel/Length;
    
         double sumpow = 0;
         for (i=0;i<=Length-1;i++) sumpow+=MathPow(Del[shift+i]-AvgDel[shift+i],2);
         double StdDev = MathSqrt(sumpow/Length); 
     
        double Filter = PctFilter * StdDev;
     
        if( MathAbs(MABuffer[shift]-MABuffer[shift+1]) < Filter ) MABuffer[shift]=MABuffer[shift+1];
      }
      else
        Filter=0;
   }
   
   //#################################################################
   for (SH=1; SH<=limit; SH++) {
      int iNLMA_Trend = 0;
      double dMABuffer0 = MABuffer[SH];
      double dMABuffer1 = MABuffer[SH+1];
      double dMABuffer2 = MABuffer[SH+2];
  
      //-- last MA trend change
      if (dMABuffer0 >= dMABuffer1 && dMABuffer1 <= dMABuffer2) iNLMA_Trend = 1;
      if (dMABuffer0 < dMABuffer1 && dMABuffer1 > dMABuffer2)   iNLMA_Trend = -1;
      
      BufferNL[SH] = iNLMA_Trend;
   }
   
   //---- draw REVERSE signals ---------------------------------------  
   for (SH=1; SH<=limit; SH++) {
      double dOffset = iATR(symbol,timeframe,Period_ATR,SH+1) * 0.40;
      //-- entry long
      if (BufferNL[SH] == 1) {
         for (i=0; i<=limit; i++) {
            if (BufferST[SH+i] == 1) {
               EntryLong1[SH]  = Low[SH] - dOffset;
               if (SendAlert_ReverseSignals && SH==1 && Time[0] != oldTimeAlert) function_SendAlert(OP_BUY);
               break;
            }
            if (BufferST[SH+i] == -1) break;
         }
      }
      else
      //-- entry short
      if (BufferNL[SH] == -1) {
         for (i=0; i<=limit; i++) {
            if (BufferST[SH+i] == -1) {
               EntryShort1[SH] = High[SH] + dOffset;
               if (SendAlert_ReverseSignals && SH==1 && Time[0] != oldTimeAlert) function_SendAlert(OP_SELL);
               break;
            }
            if (BufferST[SH+i] == 1) break;
         }
      }
   }   
//----
   return(0);
}
//+------------------------------------------------------------------+

//####################################################################
//+------------------------------------------------------------------+
//    function SendAlert
//+------------------------------------------------------------------+
void function_SendAlert(int iOrderType)
{   
   string st, sPrice, sTime, sOrder;
   string sPeriod = Get_sPeriod();
   switch (iOrderType)
   {
      case OP_BUY:
         double dValue = iHigh(Symbol(), Period(), 1) + 1.0*Point + Spread;
         sPrice = DoubleToStr(dValue, Digits);
         sTime  = TimeToStr(TimeCurrent(),TIME_MINUTES);  
         st = "Buy "+Symbol() + "  " + sPrice +  "  (Damon ATPchart ReverseSignal_" + sPeriod + "  " + sTime +")";
         sOrder = "BUY  " + sPrice + "  (ReverseSignal " + sTime +")";
         Show_Comment(sOrder);
         break;
      case OP_SELL:
         dValue = iLow(Symbol(), Period(), 1) - 1.0*Point;
         sPrice = DoubleToStr(dValue, Digits);
         sTime  = TimeToStr(TimeCurrent(),TIME_MINUTES);  
         st = "Sell "+Symbol() + "  " + sPrice +  "  (Damon ATPchart ReverseSignal_" + sPeriod + "  " + sTime +")";
         sOrder = "SELL  " + sPrice + "  (ReverseSignal " + sTime +")";
         Show_Comment(sOrder);
         break;   
   }
   Alert(st);
   if (Time[0] != oldTimeAlert) oldTimeAlert = Time[0];
}

void Show_Comment(string sOrder)
{
   string s0 = "======================\n";
   string st = s0;
   st = st + windowsName + "  [Otstup="  + Otstup + "]\n";
   st = st + sOrder + "\n";
//----
   st = st + s0;
   Comment(st);
}



//####################################################################
//+------------------------------------------------------------------+
//    Get Default Otstup
//+------------------------------------------------------------------+
int Get_DefaultOtstup(string sSymbol)
{
   if (sSymbol == "AUDUSD"+SymbolSuffix) return(15);
   if (sSymbol == "EURUSD"+SymbolSuffix) return(15);
   if (sSymbol == "GBPUSD"+SymbolSuffix) return(20);
   if (sSymbol == "USDCAD"+SymbolSuffix) return(10);
   if (sSymbol == "USDCHF"+SymbolSuffix) return(15);
   if (sSymbol == "USDJPY"+SymbolSuffix) return(15);
   if (sSymbol == "GBPJPY"+SymbolSuffix) return(15);
   if (sSymbol == "GBPCHF"+SymbolSuffix) return(20);
   if (sSymbol == "EURGBP"+SymbolSuffix) return(15);
   if (sSymbol == "NZDUSD"+SymbolSuffix) return(10);
   if (sSymbol == "EURJPY"+SymbolSuffix) return(15);
   if (sSymbol == "EURCHF"+SymbolSuffix) return(20);
   if (sSymbol == "EURAUD"+SymbolSuffix) return(30);
   if (sSymbol == "EURCAD"+SymbolSuffix) return(20);
   return(-1);
}

string Get_sPeriod()
{
   if (Period() == PERIOD_M1) return("M1");
   if (Period() == PERIOD_M5) return("M5");
   if (Period() == PERIOD_M15) return("M15");
   if (Period() == PERIOD_H1) return("H1");
   if (Period() == PERIOD_H4) return("H4");
   if (Period() == PERIOD_D1) return("D1");
   if (Period() == PERIOD_W1) return("W1");
   if (Period() == PERIOD_MN1) return("MN1");
}