//------------------------------------------------------------------
//
//
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers  12
//#property indicator_minimum 0
//#property indicator_maximum 1
#property strict
//
//
//
//
//
enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_tbiased2,   // Trend biased (extreme) price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased,  // Heiken ashi trend biased price
   pr_hatbiased2  // Heiken ashi trend biased (extreme) price
};
enum enColorOn
{
   chg_onZero,   // Change color on zero cross
   chg_onOuter,  // Change color on levels cross
   chg_onOuter2, // Change color on opposite levels cross
   chg_onSlope   // Change color on slope change
};



extern ENUM_TIMEFRAMES TimeFrameCur        = PERIOD_CURRENT; //Time frame for current
extern ENUM_TIMEFRAMES TimeFrameHtf        = PERIOD_H1;      //Time frame for higher

input  int             DspPeriod    = 14;              // DSP period
input  enPrices        Price        = pr_hatbiased2;   // DSP price
extern int             SignalPeriod = 9;               // Signal period
input  enColorOn       ColorOn      = chg_onSlope;     // Change color on :

extern color           colorUp             = clrLime;
extern color           colorDown           = clrRed;
extern color           colorNeutral        = clrDarkSlateGray;
extern int             linesWidth          = 2;
extern string          IndicatorName       = "Detrended Synthetic Price (oscillator) mtf"; // Indicator name to use

extern bool            histoVisible        = true;           // Show histogram?
extern bool            arrowsVisible       = false;          // Arrows visible?
extern color           arrowsUpColor       = clrLime;        // Up arrow color
extern color           arrowsDnColor       = clrRed;         // Down arrow color
extern int             arrowsUpCode        = 241;            // Up arrow code
extern int             arrowsDnCode        = 242;            // Down arrow code
extern int             arrowsSize          = 0;              // Arrows size

extern int      YDistance        = 74;
extern int      XDistance        = 134;
extern int      corner           = 1;
extern string   ButtonID         = "DSP CHART";

bool returnBars;
bool Interpolate = true;
string indicatorFileName;
string lastArrow = CharToStr(104);
double Value[],LineVa[],ValueUa[],ValueUb[],ValueDa[],ValueDb[],LineVaUa[],LineVaUb[],LineVaDa[],LineVaDb[],upa[],dna[],slope[],slopeHtf[],count[];

#define _bufferDefaultCall(_timeFrame,_buff,_ind) iCustom(NULL,0,IndicatorName,_timeFrame,DspPeriod,Price,SignalPeriod,ColorOn,_buff,_ind)
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrameCur,indicatorFileName,PERIOD_CURRENT,TimeFrameHtf,DspPeriod,Price,SignalPeriod,ColorOn,_buff,_ind)

color arrowsUpColor_1 = arrowsUpColor;
color arrowsDnColor_1 = arrowsDnColor;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
int OnInit() 
{
   int arst = (!arrowsVisible) ? DRAW_LINE : DRAW_ARROW;
   int hist = (histoVisible)   ? DRAW_HISTOGRAM : DRAW_NONE;
   IndicatorBuffers(15);

   SetIndexBuffer( 0, Value);   SetIndexStyle(0,hist,EMPTY,linesWidth,colorNeutral);
   SetIndexBuffer( 1, ValueUa); SetIndexStyle(1,hist,EMPTY,linesWidth,colorUp);
   SetIndexBuffer( 2, ValueUb); SetIndexStyle(2,hist,EMPTY,linesWidth,colorUp);
   SetIndexBuffer( 3, ValueDa); SetIndexStyle(3,hist,EMPTY,linesWidth,colorDown);
   SetIndexBuffer( 4, ValueDb); SetIndexStyle(4,hist,EMPTY,linesWidth,colorDown);
   
   SetIndexBuffer( 5, LineVa);   SetIndexStyle(5,DRAW_LINE,EMPTY,2,colorNeutral);   
   SetIndexBuffer( 6, LineVaUa); SetIndexStyle(6,DRAW_LINE,EMPTY,2,colorUp);
   SetIndexBuffer( 7, LineVaUb); SetIndexStyle(7,DRAW_LINE,EMPTY,2,colorUp);
   SetIndexBuffer( 8, LineVaDa); SetIndexStyle(8,DRAW_LINE,EMPTY,2,colorDown);
   SetIndexBuffer( 9, LineVaDb); SetIndexStyle(9,DRAW_LINE,EMPTY,2,colorDown);    
   
   SetIndexBuffer(10, upa);     SetIndexStyle(10,arst,EMPTY,arrowsSize,arrowsUpColor); SetIndexArrow(10,arrowsUpCode);
   SetIndexBuffer(11, dna);     SetIndexStyle(11,arst,EMPTY,arrowsSize,arrowsDnColor); SetIndexArrow(11,arrowsDnCode); 
   SetIndexBuffer(12, slope);
   SetIndexBuffer(13, slopeHtf);
   SetIndexBuffer(14, count);
   indicatorFileName = WindowExpertName();
   TimeFrameCur = MathMax(TimeFrameCur,_Period);
   TimeFrameHtf = MathMax(TimeFrameHtf,_Period); 
   IndicatorShortName(timeFrameToString(TimeFrameCur)+"/"+timeFrameToString(TimeFrameHtf)+" Detrended Synthetic Price Multi mtf");
   if (ObjectFind(ButtonID)!=0)   
   {
       ObjectCreate(ChartID(),ButtonID,OBJ_BUTTON,WindowOnDropped(),0,0);
         ObjectSetString(ChartID(),ButtonID,OBJPROP_TEXT,timeFrameToString(TimeFrameCur)+"/"+timeFrameToString(TimeFrameHtf)+" "+ButtonID+" is on");
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_FONTSIZE,7);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_CORNER,corner);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_COLOR,clrWhite);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrDimGray);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_YDISTANCE,YDistance);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_XDISTANCE,XDistance);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_XSIZE,120);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_YSIZE,16);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_SELECTABLE,false);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_HIDDEN,true);
         ObjectSetInteger(ChartID(),ButtonID,OBJPROP_STATE,true);
         
       ObjectCreate(ChartID(),ButtonID+"symbol",OBJ_BUTTON,WindowOnDropped(),0,0);
         ObjectSetString(ChartID(),ButtonID+"symbol",OBJPROP_FONT,"Wingdings");
         ObjectSetString(ChartID(),ButtonID+"symbol",OBJPROP_TEXT,lastArrow);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_FONTSIZE,9);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_CORNER,corner);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_COLOR,clrWhite);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrDimGray);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_YDISTANCE,YDistance);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_XDISTANCE,XDistance+119);
            if (corner == 1 || corner == 3)
            {
               ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_XDISTANCE,XDistance-119);
            }         
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_XSIZE,13);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_YSIZE,16);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_SELECTABLE,false);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_HIDDEN,true);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_STATE,true);
         ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BACK,false);       
   }
   return(INIT_SUCCEEDED);
}
//---+
void OnDeinit(const int reason)
{ 
   if (!returnBars)
      switch(reason)
      {
         case REASON_PARAMETERS  : 
         case REASON_CHARTCHANGE : 
         case REASON_RECOMPILE   : 
         case REASON_CLOSE       : break;
         default                 : ObjectsDeleteAll(0,ButtonID);
      }
}

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
   static string prevState ="";
   if (id==CHARTEVENT_OBJECT_CLICK && sparam==ButtonID)
   {
   string newState = GetButtonState(ButtonID);
         if (newState!=prevState)
         if (newState=="off")
         { 
             arrowsDnColor = clrNONE;
             arrowsUpColor = clrNONE;
            for (int i=0; i<12; i++) SetIndexStyle(i,DRAW_NONE);                       
            prevState=newState;
         }
         else  
         { 
             arrowsDnColor = arrowsDnColor_1;
             arrowsUpColor = arrowsUpColor_1;
            if(histoVisible)
            { 
            for (int i=0; i<5; i++) SetIndexStyle(i,DRAW_HISTOGRAM);
            };
            for (int i=5; i<10; i++) SetIndexStyle(i,DRAW_LINE);
            if(arrowsVisible)
            {
               SetIndexStyle(10,DRAW_ARROW);
               SetIndexStyle(11,DRAW_ARROW);
            }
            prevState=newState;
         }
         
           ObjectSetString(ChartID(),ButtonID,OBJPROP_TEXT,timeFrameToString(TimeFrameCur)+"/"+timeFrameToString(TimeFrameHtf)+" "+ButtonID+" is "+newState);
           ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_STATE,ObjectGetInteger(ChartID(),ButtonID,OBJPROP_STATE));

   }
   if (id==CHARTEVENT_OBJECT_CLICK && sparam==ButtonID+"symbol")
      ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_STATE,ObjectGetInteger(ChartID(),ButtonID,OBJPROP_STATE));
}
//---+
//
//
//
//
//


int OnCalculate (const int       rates_total,
                 const int       prev_calculated,
                 const datetime& time[],
                 const double&   open[],
                 const double&   high[],
                 const double&   low[],
                 const double&   close[],
                 const long&     tick_volume[],
                 const long&     volume[],
                 const int&      spread[])
{
   int counted_bars = prev_calculated;
      if(counted_bars < 0) return(-1);
      if(counted_bars > 0) counted_bars--;
      int limit=MathMax(MathMin(rates_total-counted_bars,rates_total-1),0); count[0] = limit;
         if (TimeFrameCur!=_Period)
         {
            limit = (int)MathMax(limit,MathMin(rates_total-1,_mtfCall(14,0)*TimeFrameCur/_Period));
            if (slope[limit]== 1) {CleanPoint(limit,ValueUa,ValueUb); CleanPoint(limit,LineVaUa,LineVaUb);}
            if (slope[limit]==-1) {CleanPoint(limit,ValueDa,ValueDb); CleanPoint(limit,LineVaDa,LineVaDb);}
            for (int i=limit;i>=0 && !_StopFlag; i--)
            {
               int y = iBarShift(NULL,TimeFrameCur,time[i]);
                  Value[i]    = _mtfCall(0,y);
                  LineVa[i]   = _mtfCall(5,y);
                  slope[i]    = _mtfCall(12,y);
                  slopeHtf[i] = _bufferDefaultCall(TimeFrameHtf,7,i);
                  if (i<Bars-1)
                  {
                     if((slope[i] != slope[i+1])||(slopeHtf[i] != slopeHtf[i+1]))
                     {
                        upa[i] = (slope[i] == 1 && slopeHtf[i] == 1) ? (Value[i]-0.1*MathAbs(Value[i])) : EMPTY_VALUE;
                        dna[i] = (slope[i] ==-1 && slopeHtf[i] ==-1) ? (Value[i]+0.1*MathAbs(Value[i])) : EMPTY_VALUE;
                     }
                  }                  
                  ValueDa[i] = EMPTY_VALUE;
                  ValueDb[i] = EMPTY_VALUE;
                  ValueUa[i] = EMPTY_VALUE;
                  ValueUb[i] = EMPTY_VALUE;
                  
                  LineVaDa[i] = EMPTY_VALUE;
                  LineVaDb[i] = EMPTY_VALUE;
                  LineVaUa[i] = EMPTY_VALUE;
                  LineVaUb[i] = EMPTY_VALUE;
                  
                  if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrameCur,time[i-1]))) continue;
                  
                  //
                  //
                  //
                  //
                  //
                  
                  #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                  int n,k; datetime itime = iTime(NULL,TimeFrameCur,y);
                     for(n = 1; (i+n)<rates_total && time[i+n] >= itime; n++) continue;	
                     for(k = 1; k<n && (i+n)<rates_total && (i+k)<rates_total; k++) 
                     {                        
                        _interpolate(Value);
                        _interpolate(LineVa);
                     }                  
            }
            for (int i=limit;i>=0 && !_StopFlag; i--)
            {
            if (slope[i]== 1&&slopeHtf[i] == 1) {PlotPoint(i,ValueUa,ValueUb,Value); PlotPoint(i,LineVaUa,LineVaUb,LineVa); lastArrow = CharToStr(char(arrowsUpCode));}
            if (slope[i]==-1&&slopeHtf[i] ==-1) {PlotPoint(i,ValueDa,ValueDb,Value); PlotPoint(i,LineVaDa,LineVaDb,LineVa); lastArrow = CharToStr(char(arrowsDnCode));}

            ObjectSetString(ChartID(),ButtonID+"symbol",OBJPROP_TEXT,lastArrow); 
            }
            {ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrDimGray); ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrDimGray);}                    
            if(slope[0]==  1&&slopeHtf[0] == 1) {ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrGreen); ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrGreen);}
            if(slope[0]== -1&&slopeHtf[0] ==-1) {ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrFireBrick); ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrFireBrick);}
                     
            return(rates_total);
         }        
                  
      if (slope[limit]== 1) {CleanPoint(limit,ValueUa,ValueUb); CleanPoint(limit,LineVaUa,LineVaUb);}
      if (slope[limit]==-1) {CleanPoint(limit,ValueDa,ValueDb); CleanPoint(limit,LineVaDa,LineVaDb);}
      int i=limit; for(; i>=0 && !_StopFlag; i--)         
      {

            Value[i]    = _bufferDefaultCall(TimeFrameCur,2,i);
            LineVa[i]   = _bufferDefaultCall(TimeFrameCur,2,i);            
            slope[i]    = _bufferDefaultCall(TimeFrameCur,7,i);
            slopeHtf[i] = _bufferDefaultCall(TimeFrameHtf,7,i);
            
            if (i<Bars-1)
            {                      
               if((slope[i] != slope[i+1])||(slopeHtf[i] != slopeHtf[i+1]))
               {
                  upa[i] = (slope[i] == 1 && slopeHtf[i] == 1) ? (Value[i]-0.1*MathAbs(Value[i])) : EMPTY_VALUE;
                  dna[i] = (slope[i] ==-1 && slopeHtf[i] ==-1) ? (Value[i]+0.1*MathAbs(Value[i])) : EMPTY_VALUE;
               }
            }  
            ValueDa[i] = EMPTY_VALUE;
            ValueDb[i] = EMPTY_VALUE;
            ValueUa[i] = EMPTY_VALUE;
            ValueUb[i] = EMPTY_VALUE;
            
            LineVaDa[i] = EMPTY_VALUE;
            LineVaDb[i] = EMPTY_VALUE;
            LineVaUa[i] = EMPTY_VALUE;
            LineVaUb[i] = EMPTY_VALUE;         
     
            if (slope[i]== 1&&slopeHtf[i] == 1) {PlotPoint(i,ValueUa,ValueUb,Value); PlotPoint(i,LineVaUa,LineVaUb,LineVa); lastArrow = CharToStr(char(arrowsUpCode));}
            if (slope[i]==-1&&slopeHtf[i] ==-1) {PlotPoint(i,ValueDa,ValueDb,Value); PlotPoint(i,LineVaDa,LineVaDb,LineVa); lastArrow = CharToStr(char(arrowsDnCode));}
            ObjectSetString(ChartID(),ButtonID+"symbol",OBJPROP_TEXT,lastArrow);          


            
//            if (slope[i]== 1&&slopeHtf[i] == 1) PlotPoint(i,LineVaUa,LineVaUb,LineVa); 
//            if (slope[i]==-1&&slopeHtf[i] ==-1) PlotPoint(i,LineVaDa,LineVaDb,LineVa);
                     


      } 
   {ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrDimGray); ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrDimGray);}                    
   if(slope[0]==  1&&slopeHtf[0] == 1) {ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrGreen); ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrGreen);}
   if(slope[0]== -1&&slopeHtf[0] ==-1) {ObjectSetInteger(ChartID(),ButtonID,OBJPROP_BGCOLOR,clrFireBrick); ObjectSetInteger(ChartID(),ButtonID+"symbol",OBJPROP_BGCOLOR,clrFireBrick);}
   
   return(rates_total-i-1); 
}
//
//
//
//
//
//
//---+
void CleanPoint(int i,double& first[],double& second[])
{
   if (i>=Bars-3) return;
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}
//---+
void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (i>=Bars-2) return;
   if (first[i+1] == EMPTY_VALUE)
      if (first[i+2] == EMPTY_VALUE) 
            { first[i]  = from[i];  first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }
      else  { second[i] =  from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }
   else     { first[i]  = from[i];                           second[i] = EMPTY_VALUE; }
}
//---+
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("");
}

string GetButtonState(string whichbutton)
{
    bool selected=ObjectGetInteger(ChartID(),whichbutton,OBJPROP_STATE);
    if (selected)
        {return ("on");} 
    else
        {return ("off");}
}
//---+
