//+-------------------------------------------------------------------------+
//+-------------------------------------------------------------------------+
#property copyright "www.forex-station.com"
#property link      "www.forex-station.com"

#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1  clrLime
#property indicator_color2  clrCoral
#property indicator_width2  2
#property indicator_color3  clrCoral
#property indicator_width3  2
#property indicator_color4  clrLime
#property indicator_width4  2
#property indicator_color5  clrLime
#property indicator_width5  2
#property indicator_color6  clrDodgerBlue
#property indicator_color7  clrDarkGoldenrod
#property indicator_width7  2


//

//
enum enTimeFrames
{
   tf_cu  = PERIOD_CURRENT, // Current time frame
   tf_m1  = PERIOD_M1,      // 1 minute
   tf_m5  = PERIOD_M5,      // 5 minutes
   tf_m15 = PERIOD_M15,     // 15 minutes
   tf_m30 = PERIOD_M30,     // 30 minutes
   tf_h1  = PERIOD_H1,      // 1 hour
   tf_h4  = PERIOD_H4,      // 4 hours
   tf_d1  = PERIOD_D1,      // Daily
   tf_w1  = PERIOD_W1,      // Weekly
   tf_mn1 = PERIOD_MN1,     // Monthly
   tf_n1  = -1,             // First higher time frame
   tf_n2  = -2,             // Second higher time frame
   tf_n3  = -3              // Third higher time frame
};
//
//

//

 extern enTimeFrames TimeFrame               = tf_cu;      // Time frame
extern string             WPR1           = "*** WPR1 ***";
extern int                t3_period     = 8;
extern double             b              = 0.7;
extern int                per      = 14;
extern int                psel            = 30;
extern int                pbuy            = -30;
extern string             WPR2            = "*** WPR2 ***";
extern int                t3_period_2     = 8;
extern double             b_2              = 0.7;
extern int                per_2      = 96;

extern int                psel_2          = 40;
extern int                pbuy_2          = -40;
input bool               Interpolate = true;            // Interpolate in multi time frame mode on/off?

extern bool               alertsOn        = false;
extern bool               alertsOnCurrent = true;
extern bool               alertsMessage   = true;
extern bool               alertsSound     = false;
extern bool               alertsNotify    = false;
extern bool               alertsEmail     = false;
extern string             soundFile       = "alert2.wav";

//
//
//
//
//

double Buffer1[];
double Buffer2[];
double Dn2[];
double Dn1[];
double Mid[];
double Up1[];
double Up2[],count[];

//
//
//
//
//




string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,"",t3_period,b,per,psel,pbuy,"",t3_period_2,b_2,per_2,psel_2,pbuy_2,Interpolate,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,_buff,_ind)
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,Buffer2); 
   SetIndexBuffer(1,Up1);     
   SetIndexBuffer(2,Dn1);     
   SetIndexBuffer(3,Up2);     
   SetIndexBuffer(4,Dn2);     
   SetIndexBuffer(5,Mid); 
   SetIndexBuffer(6,Buffer1); 
   SetIndexBuffer(7,count); 
   
    SetIndexStyle(1,DRAW_HISTOGRAM);
      SetIndexStyle(2,DRAW_HISTOGRAM);
      SetIndexStyle(3,DRAW_HISTOGRAM);
      SetIndexStyle(4,DRAW_HISTOGRAM);
      SetIndexStyle(5,DRAW_HISTOGRAM);
      SetLevelValue(0,psel_2);
      SetLevelValue(1,psel);
      SetLevelValue(2,0);
      SetLevelValue(3,pbuy);
      SetLevelValue(4,pbuy_2);
      //
      //
      //
      //
        indicatorFileName = WindowExpertName();
         TimeFrame         = (enTimeFrames)timeFrameValue(TimeFrame);      
  
   
   IndicatorShortName(timeFrameToString(TimeFrame)+"  haos  visual ");
   
      
    
    return(0);
}
int deinit()
{
 
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,limit;

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = MathMin(Bars-counted_bars,Bars-1);count[0] = limit;
     
           
           
            if (TimeFrame != _Period)
            {
               limit = (int)MathMax(limit,MathMin(Bars-1,_mtfCall(7,0)*TimeFrame/_Period));
              
               for( i=limit; i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                 
                     Buffer1[i]    = _mtfCall(6,y);
                     Buffer2[i] = _mtfCall(0,y);
                      Up1[i] = _mtfCall(1,y);
                      Dn1[i] = _mtfCall(2,y);
                      Up2[i] = _mtfCall(3,y);
                      Dn2[i] = _mtfCall(4,y);
                      Mid[i] = _mtfCall(5,y);
                                
                     //
                     //
                     //
                     //
                     //
                  
                     if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
                        #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                        int n,k; datetime ctime = iTime(NULL,TimeFrame,y);
                           for(n = 1; (i+n)<Bars && Time[i+n] >= ctime; n++) continue;
                           for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) 
                           {
                              
                              _interpolate(Buffer1);
                              _interpolate(Buffer2);
                             
                              
                              
                           }                              
               }
                       for(i=limit; i>=0; i--) 
            {
            Up2[i]=EMPTY_VALUE; 
   	   Dn1[i]=EMPTY_VALUE; 
	      Up1[i]=EMPTY_VALUE; 
	      Dn2[i]=EMPTY_VALUE; 
         Mid[i]=EMPTY_VALUE; 
   	               if (Buffer1[i]> psel && Buffer2[i]>psel_2) Dn2[i]=Buffer2[i];
      else if (Buffer1[i]<=psel && Buffer2[i]>psel_2) Dn1[i]=Buffer2[i];
	   else if (Buffer1[i]< pbuy && Buffer2[i]<pbuy_2) Up2[i]=Buffer2[i];
	   else if (Buffer1[i]>=pbuy && Buffer2[i]<pbuy_2) Up1[i]=Buffer2[i];
      else                                            Mid[i]=Buffer2[i];
            }  
                            
               return(0);
            }
            
            
   //
   //
   //
   //
   //
   
 
 //  {
      for(i=limit; i>=0; i--)
      { 
          Buffer1[i] = iT3(iWPR(NULL,0,per,i)  ,t3_period  ,b  ,false,i,0)+50;
         Buffer2[i] = iT3(iWPR(NULL,0,per_2,i),t3_period_2,b_2,false,i,1)+50;
         Up2[i]=EMPTY_VALUE; 
   	   Dn1[i]=EMPTY_VALUE; 
	      Up1[i]=EMPTY_VALUE; 
	      Dn2[i]=EMPTY_VALUE; 
         Mid[i]=EMPTY_VALUE; 


           if (Buffer1[i]> psel && Buffer2[i]>psel_2) Dn2[i]=Buffer2[i];
      else if (Buffer1[i]<=psel && Buffer2[i]>psel_2) Dn1[i]=Buffer2[i];
	   else if (Buffer1[i]< pbuy && Buffer2[i]<pbuy_2) Up2[i]=Buffer2[i];
	   else if (Buffer1[i]>=pbuy && Buffer2[i]<pbuy_2) Up1[i]=Buffer2[i];
      else                                            Mid[i]=Buffer2[i];
       }
        
       
 if (alertsOn)
    {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1; whichBar = iBarShift(NULL,0,iTime(NULL,TimeFrame,whichBar)); 
      
      //
      //
      //
      //
      //
      
      if (Dn2[whichBar+1] == EMPTY_VALUE && Dn2[whichBar] != EMPTY_VALUE) doAlert(whichBar,"strong sell");
      if (Dn1[whichBar+1] == EMPTY_VALUE && Dn1[whichBar] != EMPTY_VALUE) doAlert(whichBar,"weak sell");
      if (Up2[whichBar+1] == EMPTY_VALUE && Up2[whichBar] != EMPTY_VALUE) doAlert(whichBar,"strong buy");
      if (Up1[whichBar+1] == EMPTY_VALUE && Up1[whichBar] != EMPTY_VALUE) doAlert(whichBar,"weak buy");        
       }      
            
           
         
     
      return(0);
   }
   
   //
   //
   //
   //
   //

  
//
//
double workT3[][12];
double workT3Coeffs[][6];
#define _period 0
#define _c1     1
#define _c2     2
#define _c3     3
#define _c4     4
#define _alpha  5

//
//
//
//
//

double iT3(double price, double period, double hot, bool original, int i, int instanceNo=0)
{
   if (ArrayRange(workT3,0) !=Bars)                 ArrayResize(workT3,Bars);
   if (ArrayRange(workT3Coeffs,0) < (instanceNo+1)) ArrayResize(workT3Coeffs,instanceNo+1);

   if (workT3Coeffs[instanceNo][_period] != period)
   {
     workT3Coeffs[instanceNo][_period] = period;
        double a = hot;
            workT3Coeffs[instanceNo][_c1] = -a*a*a;
            workT3Coeffs[instanceNo][_c2] = 3*a*a+3*a*a*a;
            workT3Coeffs[instanceNo][_c3] = -6*a*a-3*a-3*a*a*a;
            workT3Coeffs[instanceNo][_c4] = 1+3*a+a*a*a+3*a*a;
            if (original)
                 workT3Coeffs[instanceNo][_alpha] = 2.0/(1.0 + period);
            else workT3Coeffs[instanceNo][_alpha] = 2.0/(2.0 + (period-1.0)/2.0);
   }
   
   //
   //
   //
   //
   //
   
   int buffer = instanceNo*6;
   int r = Bars-i-1;
   if (r == 0)
      {
         workT3[r][0+buffer] = price;
         workT3[r][1+buffer] = price;
         workT3[r][2+buffer] = price;
         workT3[r][3+buffer] = price;
         workT3[r][4+buffer] = price;
         workT3[r][5+buffer] = price;
      }
   else
      {
         workT3[r][0+buffer] = workT3[r-1][0+buffer]+workT3Coeffs[instanceNo][_alpha]*(price              -workT3[r-1][0+buffer]);
         workT3[r][1+buffer] = workT3[r-1][1+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][0+buffer]-workT3[r-1][1+buffer]);
         workT3[r][2+buffer] = workT3[r-1][2+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][1+buffer]-workT3[r-1][2+buffer]);
         workT3[r][3+buffer] = workT3[r-1][3+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][2+buffer]-workT3[r-1][3+buffer]);
         workT3[r][4+buffer] = workT3[r-1][4+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][3+buffer]-workT3[r-1][4+buffer]);
         workT3[r][5+buffer] = workT3[r-1][5+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][4+buffer]-workT3[r-1][5+buffer]);
      }

   //
   //
   //
   //
   //
   
   return(workT3Coeffs[instanceNo][_c1]*workT3[r][5+buffer] + 
          workT3Coeffs[instanceNo][_c2]*workT3[r][4+buffer] + 
          workT3Coeffs[instanceNo][_c3]*workT3[r][3+buffer] + 
          workT3Coeffs[instanceNo][_c4]*workT3[r][2+buffer]);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//
string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}
int timeFrameValue(int _tf)
{
   int add  = (_tf>=0) ? 0 : MathAbs(_tf);
   if (add != 0) _tf = _Period;
   int size = ArraySize(iTfTable); 
      int i =0; for (;i<size; i++) if (iTfTable[i]==_tf) break;
                                   if (i==size) return(_Period);
                                                return(iTfTable[(int)MathMin(i+add,size-1)]);
}

void doAlert(int forBar, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[forBar]) {
          previousAlert  = doWhat;
          previousTime   = Time[forBar];

          //
          //
          //
          //
          //

          message =  StringConcatenate(Symbol()," ",timeFrameToString(TimeFrame)," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," Haos Visual ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol(), Period(), " Haos Visual "),message);
             if (alertsSound)   PlaySound(soundFile);
      }
}
