//+------------------------------------------------------------------+
//|                                Jim Sloman's natural market combo |
//|                                                     ocn nmc2.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1  DimGray
#property indicator_color2  DeepSkyBlue
#property indicator_color3  PaleVioletRed
#property indicator_style1  STYLE_DOT
#property indicator_width2  2
#property indicator_width3  2

//
//
//
//
//

extern int   NMCPeriod1  = 40;
extern int   NMCPrice1   = PRICE_CLOSE;
extern int   TEMAPeriod1 =  1;
extern bool  UseRiver1   = true;
extern int   NMCPeriod2  = 80;
extern int   NMCPrice2   = PRICE_CLOSE;
extern int   TEMAPeriod2 =  1;
extern bool  UseRiver2   = true;

//
//
//
//
//

double nmc1[];
double nmc2[];
double zeroLine[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,zeroLine); SetIndexLabel(0,NULL);
   SetIndexBuffer(1,nmc1);     SetIndexLabel(1,"NMC 1"); SetIndexDrawBegin(1,NMCPeriod1);
   SetIndexBuffer(2,nmc2);     SetIndexLabel(2,"NMC 2"); SetIndexDrawBegin(2,NMCPeriod2);
   
   //
   //
   //
   //
   //
  
      string using1 = "";           
         if (UseRiver1)
               using1 = "river ";
         else  using1 = "mirror ";
      string using2 = "";           
         if (UseRiver2)
               using2 = "river ";
         else  using2 = "mirror ";
 
      TEMAPeriod1 = MathMax(TEMAPeriod1,1);
      NMCPeriod1  = MathMax(NMCPeriod1 ,1);
      TEMAPeriod2 = MathMax(TEMAPeriod2,1);
      NMCPeriod2  = MathMax(NMCPeriod2 ,1);

   IndicatorShortName ("nmc2 ("+NMCPeriod1+","+TEMAPeriod1+" "+using1+NMCPeriod2+","+TEMAPeriod2+" "+using2+")");
   return(0);
}
int deinit()
{
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = Bars-counted_bars;

   //
   //
   //
   //
   //

   for(int i=limit; i >= 0; i--)
   {
      if (NMCPeriod1>1) nmc1[i] = iNmc(iMA(NULL,0,1,0,MODE_SMA,NMCPrice1,i),NMCPeriod1,TEMAPeriod1,UseRiver1,i,0);
      if (NMCPeriod2>1) nmc2[i] = iNmc(iMA(NULL,0,1,0,MODE_SMA,NMCPrice2,i),NMCPeriod2,TEMAPeriod2,UseRiver2,i,1);
      zeroLine[i] = 0;
   }
   
   //
   //
   //
   //
   //
   
   return(0);
}


//------------------------------------------------------------------
//
//------------------------------------------------------------------+
//
//
//
//
//

double workNmc[][2];
#define iPrc 0

double iNmc(double price, int period,int temaPeriod, bool tRiver, int i, int instanceNo)
{
   if (ArrayRange(workNmc,0) != Bars) ArrayResize(workNmc,Bars); int r = Bars-i-1; int tBuff = instanceNo;
   
      //
      //
      //
      //
      //
      
      double currPrice = iTema(price,temaPeriod,i,instanceNo);
      if (currPrice > 0)
            workNmc[r][tBuff+iPrc] = MathLog(currPrice);
      else  workNmc[r][tBuff+iPrc] = 0.00;
      
      //
      //
      //
      //
      //

      double nmc = 0;
            double nms = iNmsFunction(period,i,tBuff);
            double tmp;
            if (tRiver)
                  tmp = iNmrFunction(period,1,i,tBuff);
            else  tmp = iNmmFunction(period,1,i,tBuff);
                  tmp = (MathAbs(nms)*tmp+MathAbs(tmp)*nms)/2.00;
              if (tmp > 0) nmc =  MathSqrt( tmp);
              if (tmp < 0) nmc = -MathSqrt(-tmp);
      return(nmc);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------+
//
//
//
//
//

double iNmsFunction(int tPeriod,int tPos,int tBuff)
{
   int    pos    = Bars-tPos-1;
   double sumxy  = 0.00;
   double sumy   = 0.00;
   double sum    = 0.00;

   //
   //
   //
   //
   //
   
   for (int period=1; period<=tPeriod; period++)
   {
      double sumx  = period*(period+1.0)/2.0;
      double sumx2 = period*(period+1.0)*(2*period+1.0)/6.0;
      double price = workNmc[pos-(period-1)][tBuff+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 tPeriod, int startPeriod, int tPos, int tBuff)
{
   int    endPeriod = startPeriod*tPeriod;
   int    pos       = Bars-tPos-1;
   double sum       = 0.00;
   double currPrice = workNmc[pos][tBuff+iPrc];
      
   for (int i= startPeriod; i <= endPeriod; i += startPeriod)
           sum += (currPrice-workNmc[pos-i][tBuff+iPrc])/MathSqrt(i);
   return((sum/tPeriod)*1000.00);
}

//
//
//
//    natural market river
//
//
//

double iNmrFunction(int tPeriod, int startPeriod, int tPos, int tBuff)
{
   int    endPeriod = startPeriod*tPeriod;
   int    pos       = Bars-tPos-1;
   double sum       = 0.00;
      
   for (int i=startPeriod; i <= endPeriod; i+=startPeriod)
          sum += (workNmc[pos-i+startPeriod][tBuff+iPrc]-workNmc[pos-i][tBuff+iPrc])*(MathSqrt(i)-MathSqrt(i-startPeriod));
   return(sum*1000.00);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------+
//
//
//
//
//

double workTema[][6];
#define _ema1 0
#define _ema2 1
#define _ema3 2

double iTema(double price, double period, int i, int instanceNo=0)
{
   if (ArrayRange(workTema,0)!= Bars) ArrayResize(workTema,Bars); instanceNo*=3; int r = Bars-i-1;

   //
   //
   //
   //
   //
      
   double alpha = 2.0 / (1.0+period);
          workTema[r][_ema1+instanceNo] = workTema[r-1][_ema1+instanceNo]+alpha*(price                        -workTema[r-1][_ema1+instanceNo]);
          workTema[r][_ema2+instanceNo] = workTema[r-1][_ema2+instanceNo]+alpha*(workTema[r][_ema1+instanceNo]-workTema[r-1][_ema2+instanceNo]);
          workTema[r][_ema3+instanceNo] = workTema[r-1][_ema3+instanceNo]+alpha*(workTema[r][_ema2+instanceNo]-workTema[r-1][_ema3+instanceNo]);
   return(workTema[r][_ema3+instanceNo]+3.0*(workTema[r][_ema1+instanceNo]-workTema[r][_ema2+instanceNo]));
}