148 lines
10 KiB
Plaintext
148 lines
10 KiB
Plaintext
//------------------------------------------------------------------
|
|
#property copyright "© mladen, 2018"
|
|
#property link "mladenfx@gmail.com"
|
|
#property description "Nonlinear regression"
|
|
//+------------------------------------------------------------------
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 4
|
|
#property indicator_plots 1
|
|
#property indicator_label1 "Nonlinear regression"
|
|
#property indicator_type1 DRAW_COLOR_LINE
|
|
#property indicator_color1 clrDarkGray,clrDeepPink,clrLimeGreen
|
|
#property indicator_width1 2
|
|
//--- input parameters
|
|
input int inpPeriod = 50; // Period
|
|
input ENUM_APPLIED_PRICE inpPrice = PRICE_CLOSE; // Price
|
|
//--- indicator buffers
|
|
double val[],valc[];
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//--- indicator buffers mapping
|
|
SetIndexBuffer(0,val,INDICATOR_DATA);
|
|
SetIndexBuffer(1,valc,INDICATOR_COLOR_INDEX);
|
|
//--- indicator short name assignment
|
|
IndicatorSetString(INDICATOR_SHORTNAME,"Nonlinear regression ("+(string)inpPeriod+")");
|
|
//---
|
|
return (INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator de-initialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator iteration function |
|
|
//+------------------------------------------------------------------+
|
|
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[])
|
|
{
|
|
if(Bars(_Symbol,_Period)<rates_total) return(prev_calculated);
|
|
for(int i=(int)MathMax(prev_calculated-1,0); i<rates_total && !IsStopped(); i++)
|
|
{
|
|
val[i]=iNlr(getPrice(inpPrice,open,close,high,low,i,rates_total),inpPeriod,i,0,rates_total);
|
|
valc[i]=(i>0) ?(val[i]>val[i-1]) ? 2 :(val[i]<val[i-1]) ? 1 : valc[i-1]: 0;
|
|
}
|
|
return(rates_total);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom functions |
|
|
//+------------------------------------------------------------------+
|
|
double workNlr[][1];
|
|
double nlrYValue[];
|
|
double nlrXValue[];
|
|
//
|
|
//---
|
|
//
|
|
double iNlr(double price,int Length,int shift,int desiredBar,int bars,int instanceNo=0)
|
|
{
|
|
if(ArrayRange(workNlr,0)!=bars) ArrayResize(workNlr,bars);
|
|
if(ArraySize(nlrYValue)!=Length) ArrayResize(nlrYValue,Length);
|
|
if(ArraySize(nlrXValue)!=Length) ArrayResize(nlrXValue,Length);
|
|
//
|
|
//---
|
|
//
|
|
double AvgX = 0;
|
|
double AvgY = 0;
|
|
int r=shift;
|
|
workNlr[r][instanceNo]=price;
|
|
ArrayInitialize(nlrXValue,0);
|
|
ArrayInitialize(nlrYValue,0);
|
|
for(int i=0;i<Length && (r-i)>=0;i++)
|
|
{
|
|
nlrXValue[i] = i;
|
|
nlrYValue[i] = workNlr[r-i][instanceNo];
|
|
AvgX += nlrXValue[i];
|
|
AvgY += nlrYValue[i];
|
|
}
|
|
AvgX /= Length;
|
|
AvgY /= Length;
|
|
//
|
|
//---
|
|
//
|
|
double SXX = 0;
|
|
double SXY = 0;
|
|
double SYY = 0;
|
|
double SXX2 = 0;
|
|
double SX2X2 = 0;
|
|
double SYX2 = 0;
|
|
|
|
for(int i=0;i<Length;i++)
|
|
{
|
|
double XM = nlrXValue[i] - AvgX;
|
|
double YM = nlrYValue[i] - AvgY;
|
|
double XM2 = nlrXValue[i] * nlrXValue[i] - AvgX*AvgX;
|
|
SXX += XM*XM;
|
|
SXY += XM*YM;
|
|
SYY += YM*YM;
|
|
SXX2 += XM*XM2;
|
|
SX2X2 += XM2*XM2;
|
|
SYX2 += YM*XM2;
|
|
}
|
|
//
|
|
//---
|
|
//
|
|
double tmp;
|
|
double ACoeff=0;
|
|
double BCoeff=0;
|
|
double CCoeff=0;
|
|
|
|
tmp=SXX*SX2X2-SXX2*SXX2;
|
|
if(tmp!=0)
|
|
{
|
|
BCoeff = ( SXY*SX2X2 - SYX2*SXX2 ) / tmp;
|
|
CCoeff = ( SXX*SYX2 - SXX2*SXY ) / tmp;
|
|
}
|
|
ACoeff = AvgY - BCoeff*AvgX - CCoeff*AvgX*AvgX;
|
|
tmp = ACoeff + BCoeff*desiredBar + CCoeff*desiredBar*desiredBar;
|
|
return(tmp);
|
|
}
|
|
//
|
|
//---
|
|
//
|
|
double getPrice(ENUM_APPLIED_PRICE tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars)
|
|
{
|
|
if(i>=0)
|
|
switch(tprice)
|
|
{
|
|
case PRICE_CLOSE: return(close[i]);
|
|
case PRICE_OPEN: return(open[i]);
|
|
case PRICE_HIGH: return(high[i]);
|
|
case PRICE_LOW: return(low[i]);
|
|
case PRICE_MEDIAN: return((high[i]+low[i])/2.0);
|
|
case PRICE_TYPICAL: return((high[i]+low[i]+close[i])/3.0);
|
|
case PRICE_WEIGHTED: return((high[i]+low[i]+close[i]+close[i])/4.0);
|
|
}
|
|
return(0);
|
|
}
|
|
//+------------------------------------------------------------------+
|