//+------------------------------------------------------------------+
//|                                Jim Sloman's natural market combo |
//|                                                     ocn nmc2.mq4 |
//|                                                           mladen |
//|                                                   mtf by mrtools |    
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers     1
#property indicator_color1      DeepSkyBlue
#property indicator_levelstyle  STYLE_DOT
#property indicator_levelcolor  DimGray

//
//
//
//
//

extern string TimeFrame   = "Current time frame";
extern int    NMCPeriod   = 40;
extern int    NMCPrice    = PRICE_CLOSE;
extern int    TEMAPeriod  = 1;
extern bool   UseRiver    = true;
extern bool   Interpolate = false;

//
//
//
//
//

double nmc[];
double tBuffer[][4];
double alpha;

//
//
//
//
//

string indicatorFileName;
bool   calculateValue;
bool   returnBars;
int    timeFrame;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,nmc);  SetIndexLabel(0,"NMC") ; SetIndexDrawBegin(0,NMCPeriod);
   SetLevelValue(0,0);
   
   //
   //
   //
   //
   //
  
   string PriceType;
      switch(NMCPrice)
      {
         case PRICE_CLOSE:    PriceType = "Close";    break;  // 0
         case PRICE_OPEN:     PriceType = "Open";     break;  // 1
         case PRICE_HIGH:     PriceType = "High";     break;  // 2
         case PRICE_LOW:      PriceType = "Low";      break;  // 3
         case PRICE_MEDIAN:   PriceType = "Median";   break;  // 4
         case PRICE_TYPICAL:  PriceType = "Typical";  break;  // 5
         case PRICE_WEIGHTED: PriceType = "Weighted"; break;  // 6
      }      
   string using = "";           
      if (UseRiver)
            using = "river ";
      else  using = "mirror ";
 
   //
   //
   //
   //
   //
   
         TEMAPeriod        = MathMax(TEMAPeriod,1);
         NMCPeriod         = MathMax(NMCPeriod ,1);
         alpha             = 2.0 /(1.0 + TEMAPeriod);
         indicatorFileName = WindowExpertName();
         calculateValue    = (TimeFrame=="CalculateValue"); if (calculateValue) return(0);
         returnBars        = (TimeFrame=="returnBars");     if (returnBars)     return(0);
         timeFrame         = stringToTimeFrame(TimeFrame);
         
         //
         //
         //
         //
         //
         

   IndicatorShortName (timeFrameToString(timeFrame)+"  nmc2 "+using+" ("+NMCPeriod+","+PriceType+","+TEMAPeriod+")");
   return(0);
}

int deinit() {   return(0); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define iPrc 3

//
//
//
//
//

int start()
{
   int    counted_bars=IndicatorCounted();
   int    i,k,r,limit;

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = Bars-counted_bars;
         if (ArrayRange(tBuffer,0) != Bars) ArrayResize(tBuffer,Bars);
         if (returnBars) { nmc[0] = limit+1; return(0); }

   //
   //
   //
   //
   //
   
   if (calculateValue || timeFrame==Period())
   {    
     for(i=limit, r=Bars-i-1; i >= 0; i--,r++)
     {

       double rawPrice  = iMA(NULL,0,1,0,MODE_SMA,NMCPrice,i);
       double currPrice = iTema(rawPrice,r);
          if (currPrice > 0)
                tBuffer[r][iPrc] = MathLog(currPrice);
          else  tBuffer[r][iPrc] = 0.00;
      
         //
         //
         //
         //
         //

         nmc[i]      = 0;

            double nms = iNmsFunction(i);            
            double tmp;
            if (UseRiver)
                  tmp = iNmrFunction(1,i);
            else  tmp = iNmmFunction(1,i);
                  tmp = (MathAbs(nms)*tmp+MathAbs(tmp)*nms)/2.00;
              if (tmp > 0) nmc[i] =  MathSqrt( tmp);
              if (tmp < 0) nmc[i] = -MathSqrt(-tmp);
   }
   
   return(0);
   }
   
   //
   //
   //
   //
   //

   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
   for (i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
         nmc[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",NMCPeriod,NMCPrice,TEMAPeriod,UseRiver,0,y);
         
         //
         //
         //
         //
         //
        
         if (!Interpolate || y==iBarShift(NULL,timeFrame,Time[i-1])) continue;

         //
         //
         //
         //
         //

         datetime time = iTime(NULL,timeFrame,y);
            for(int n = 1; i+n < Bars && Time[i+n] >= time; n++) continue;
            for(int x = 1; x < n; x++) 
            {
              
               nmc[i+x] = nmc[i] + (nmc[i+n] - nmc[i])* x/n;
            }
     
     
   }
   
return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//    natural market slope
//
//
//

double iNmsFunction(int tPos)
{
   int    pos    = Bars-tPos-1;
   double sumxy  = 0.00;
   double sumy   = 0.00;
   double sum    = 0.00;

   //
   //
   //
   //
   //
   
   for (int period=1; period<=NMCPeriod; period++)
   {
      double sumx  = period*(period+1.0)/2.0;
      double sumx2 = period*(period+1.0)*(2*period+1.0)/6.0;
      double price = tBuffer[pos-(period-1)][iPrc];
      
             sumxy += sumy+price;
             sumy  +=      price;
             
      double bot   = period*sumx2 - sumx*sumx;
      double slope = 0.00;
      if (bot != 0) slope = (period*sumxy - sumx*sumy)/bot;
             sum += slope*MathSqrt(period);
   }           
   return(sum*100.00);
}

//
//
//
//    natural market mirror
//
//
//

double iNmmFunction(int startPeriod, int tPos)
{
   int    endPeriod = startPeriod*NMCPeriod;
   int    pos       = Bars-tPos-1;
   double sum       = 0.00;
   double currPrice = tBuffer[pos][iPrc];
      
   for (int i= startPeriod; i <= endPeriod; i += startPeriod)
           sum += (currPrice-tBuffer[pos-i][iPrc])/MathSqrt(i);
   return((sum/NMCPeriod)*1000.00);
}

//
//
//
//    natural market river
//
//
//

double iNmrFunction(int startPeriod, int tPos)
{
   int    endPeriod = startPeriod*NMCPeriod;
   int    pos       = Bars-tPos-1;
   double sum       = 0.00;
      
   for (int i=startPeriod; i <= endPeriod; i+=startPeriod)
          sum += (tBuffer[pos-i+startPeriod][iPrc]-tBuffer[pos-i][iPrc])*(MathSqrt(i)-MathSqrt(i-startPeriod));
   return(sum*1000.00);
}

//
//
//
//
//

double iTema(double price,int i)
{
   if (i < 1)
      {
         tBuffer[i][0] = price;
         tBuffer[i][1] = price;
         tBuffer[i][2] = price;
      }
   else
      {
         tBuffer[i][0] = tBuffer[i-1][0]+alpha*(price        -tBuffer[i-1][0]);
         tBuffer[i][1] = tBuffer[i-1][1]+alpha*(tBuffer[i][0]-tBuffer[i-1][1]);
         tBuffer[i][2] = tBuffer[i-1][2]+alpha*(tBuffer[i][1]-tBuffer[i-1][2]);
      }
   return(3*tBuffer[i][0] - 3*tBuffer[i][1] + tBuffer[i][2]);
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}


