//+------------------------------------------------------------------+
//|                                                Scalpel 3.7.1.mq4 |
//|                                            Copyright  2009, alx |
//|                  with important pieces of code from other authors|
//+------------------------------------------------------------------+
#property copyright "Copyright  2009, alx@novusorsa.pl"
#property link      "www.novusorsa.pl/lmt/"

#define Sell -1
#define Buy 1
#define Any 10
#define Nothing 0

#define Down -1
#define Up 1

extern bool	showTrueHistory		= false;
extern int 	smooth 				= 0;
extern int	BarShift			= 0; // for visual back testing purposes. Automatic self-backtesting is completly different story...

// Extratrend settings
extern int		ExtratrendBars	= 240;
extern int		HarmDivider		= 20; // ExtratrendBars/HarmDivider = extratrendHarmonics. I found it easier to adjust the Extratrend

// Hodrick-Prescott Filter settings
extern bool useHPF				= false; // if not, Extratrend will be used.
extern int switchToHPFon 		= 0; // time frame value to switch HPF on automatically. 0 = no switch.
extern int PastBars    			= 1000; //Number of PastBars to smooth  10 000 is much too much I guess..
extern int FiltPer 				= 20;   //Equivalent to SMA period. It was 12 in the original code, I find 16 more accurate for my purposes. Or even 20...
extern bool	EnableTradeSignals	= true; // when enabled, arrows will be plot and alarm trigered if enabled
extern bool	UseFractalTriggers	= false; // this enables trade triger when fractal level is surpassed
extern bool	UseHaReversals		= true;
bool	UseInternalHA		= true; // it looks it works just right but let's leave it for some time to observe...
extern bool	UseDemarkPivots 	= true;
extern bool	UseTomCatapult		= true;
extern bool	UseTomTimeFrame		= true; // Tom Strignano works on H1
extern bool	ShowAllEntryPoints 	= false; // this is for testing purposes. If ShowAllEntryPoints = true, it will show all entry points unfiltered.
extern bool	maskWithSigmaOnHPF	= false;
extern bool EnableAlarm 		= false;
extern bool	UseClosedCandle		= false; // triggers alarm on current or closed bar.
// Demark pivots settings
extern int LevDP				= 2; //  Demar Pint Levels; 2 = central bar will be higher (lower) then 2 PastBars on the left side and 2 PastBars on the right one.
// standart deviation
extern bool 	Show1stBand = false; // show 1st deviation
extern bool 	Show2ndBand = true; // show 2nd deviation
extern double 	kstd = 1.5; 	// 1st deviation
extern double 	kstd2 = 2.2;	// or 2.5... 2nd deviation
// PowerSaver
extern int	PowerSaver			= 15; // in seconds - to reduce CPU usage it will calculate every n seconds instead of every tick. 0 = realtime.

int	UpArrowSymbol  		= 221;
int	DownArrowSymbol  	= 222;
int result, prevResult;
int timeFrame, targetTimeFrame;
string timeFrameName;
string symbol;
datetime previousBarTime = 0;

// indicator stuff
#property indicator_chart_window
#property indicator_buffers 8 //10 - I can't have any more...

#property indicator_color1	Gold
#property indicator_color2	Blue
#property indicator_color3	SpringGreen
#property indicator_color4	Tomato

#property indicator_width1  3
#property indicator_width2  3
#property indicator_width3  2
#property indicator_width4  2

// internal Heiken Ashi stuff
int currentBarCount, previousBarCount;
double HaLow[], HaHigh[],HaOpen[],HaClose[];

// so called Fractals stuff 
double FractalUpArrow[];
double FractalDownArrow[];
double FractalUpLevel[];
double FractalDownLevel[];

//---- base indicator buffers
double BuySignalBuffer[];
double SellSignalBuffer[];
double TrendUp[];
double TrendDown[];

// Hodrick-Prescott Filter stuff
double priceData[];
double LambdaBuf[7];

// Extratrend stuff
int		extratrendHarmonics; // used to be external, now calculated internally
double  FreqTOL  =0.0002;//Tolerance of frequency calculation FreqTOL > 0.001 may not converge

#import "Extratrend.dll"
void calculateExtratrendDll(int bars, int harmonics, double freqTOL, double priceArray[], double& curve[]);
void prepareHPFDLL(int filtPer, double& lambdaBuf[]);
void HPFDLLnoLambda(int filtPer, int bars, int startIndex, double& lambdaBuf[], double prices[], double& curve[]);
void sigmaBands(int bars, double kstd1, double kstd2, double priceArray[], double& curveArray[], double& firstHigh[], double& firstLow[], double& secondHigh[], double& secondLow[]);
#import

// HPF and Extratrend common buffer and variables
double extrapolatedCurve[];
int barsRequired, nobs;

// standart deviation stuff
double sqh[],sql[],sqh2[],sql2[]; // main indicator bufers
double fh[], fl[], sh[], sl[]; // temp buffers
double firstBand, secondBand;
	
#property indicator_color5 Gold
#property indicator_color6 Gold
#property indicator_color7 Orange
#property indicator_color8 Orange

#property  indicator_width5  1
#property  indicator_width6  1
#property  indicator_width7  2
#property  indicator_width8  2

double nonRepaintingCurve[];

int currentCPUtime = 0, previousCPUtime = 0, powerSaverInterval;
//----------------------------------------------------------
int init()
{
	// some input settings check up
	if (PastBars < 20) PastBars = 20; // doesn't make sense to calculate it on shorter period. However, it works even on that short period!
	if (FiltPer < 6) FiltPer = 6; // bellow 6 it's just a noise...
	if (!EnableTradeSignals) EnableAlarm = false; // otherwise doesn't make any sense
	result 		= Nothing; // signal trigger result. I don't remember why I made it global variable, but let's leave it if it works...
	prevResult 	= Nothing;
	
	
	if (kstd < 0.5) kstd = 0.5; // just to ensure no 0 or negative value passed
	if (kstd2 <= kstd) kstd2 = 2*kstd; // as above
	
	IndicatorBuffers(8);
	//---- drawing settings
	SetIndexStyle(0,DRAW_ARROW);
	SetIndexStyle(1,DRAW_ARROW);

	//SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,2);
	//SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,2);
	
	SetIndexStyle(2,DRAW_LINE);
	SetIndexStyle(3,DRAW_LINE);
	
	SetIndexArrow(0, UpArrowSymbol);
	SetIndexArrow(1, DownArrowSymbol);
	
	SetIndexBuffer(0,BuySignalBuffer);
	SetIndexBuffer(1,SellSignalBuffer);
	
	SetIndexBuffer(2,TrendUp);
	SetIndexBuffer(3,TrendDown);	
	
	SetIndexShift(2,-BarShift); // I manipulate price array for the Hodrick-Prescott Filter. Base array gets shifted data so I have to shift the rest accordingly
	SetIndexShift(3,-BarShift);
	
	//---- name for DataWindow and indicator subwindow label
	IndicatorShortName("Scalpel 3.5.5");
	SetIndexLabel(0,"Scalpel 3.5.5 Bull Reversal");
	SetIndexLabel(1,"Scalpel 3.5.5 Bear Reversal");
	SetIndexLabel(2,"Scalpel 3.5.5 Uptrend");
	SetIndexLabel(3,"Scalpel 3.5.5 Downtrend");

	symbol = Symbol();
	timeFrame = Period();
	switch (timeFrame)
	{
		case(PERIOD_M1): timeFrameName = "M1"; break;
		case(PERIOD_M5): timeFrameName = "M5"; break;
		case(PERIOD_M15): timeFrameName = "M15"; break;
		case(PERIOD_M30): timeFrameName = "M30"; break;
		case(PERIOD_H1): timeFrameName = "H1"; break;
		case(PERIOD_H4): timeFrameName = "H4"; break;
		case(PERIOD_D1): timeFrameName = "D1"; break;
		case(PERIOD_W1): timeFrameName = "W1"; break;
		case(PERIOD_MN1): timeFrameName = "MN1"; break;
	}
	
	if (UseTomTimeFrame) targetTimeFrame = PERIOD_H1; else targetTimeFrame = timeFrame;
	
	prepareHPFDLL(FiltPer, LambdaBuf); // ok. use or not, it's just several microseconds...
	
	// this is just makeshift - I only check if no negative values or 0 meaning current timeframe...
	// but I don;t check for the timeframe value validity. Anything greater than 0 will pass...
	if (switchToHPFon <= 0) switchToHPFon = 0; // this way I don'ty have to check for the time frame value validity :-)
	else {if (timeFrame <= switchToHPFon) useHPF = true;}
	
	if (useHPF)
		{
			// Hodrick-Prescott Filter stuff
			if (FiltPer <1) FiltPer = 1;
			if(PastBars < 100) PastBars = 100;
			//ArrayResize(priceData,PastBars);
			//ArrayResize(extrapolatedCurve,PastBars);
			barsRequired = PastBars;
			nobs = PastBars;
		}
	else
		{
			// Extratrend stuff
			if (ExtratrendBars < 20)
				{
					ExtratrendBars = 241; // tak na wszelki wypadek.
					Print("Invalid ExtratrendBars settings. Reverting to default.");
				}
				
			if (HarmDivider < 1)
				{
					HarmDivider = 15; // tak na wszelki wypadek.
					Print("Invalid HarmDivider settings. Reverting to default.");
				}
			extratrendHarmonics=ExtratrendBars/HarmDivider;		
			//ArrayResize(priceData,ExtratrendBars);		
			//ArrayResize(extrapolatedCurve,ExtratrendBars);
			barsRequired = ExtratrendBars;
			nobs = ExtratrendBars;	
		}
		
	// array initializations
	ArrayResize(priceData,nobs);	
	ArrayInitialize(priceData,NULL);
	
	ArrayResize(extrapolatedCurve,nobs);
	ArrayInitialize(extrapolatedCurve,EMPTY_VALUE);
	
	ArrayResize(nonRepaintingCurve, nobs);
	ArrayInitialize(nonRepaintingCurve,EMPTY_VALUE);
	
	// no need to resize and initialize sigma bands buffers. They are not of that importance. BTW: they get initialized by default.
	
	if (showTrueHistory)
		{
			// I need more bars to make real walkthrough
			if (useHPF) barsRequired = PastBars*2;
			else
				{
					barsRequired = ExtratrendBars*2;
				}
		}
	
		barsRequired += BarShift;
		
// standard deviation

	if(Show1stBand)
		{
			ArrayResize(fh,nobs);
			ArrayResize(fl,nobs);
			firstBand = kstd;
		}
	else firstBand = 0;
	
	if(Show2ndBand)
		{
			ArrayResize(sh,nobs);
			ArrayResize(sl,nobs);
			secondBand = kstd2;
		}
	else secondBand = 0;
	
	SetIndexBuffer(4, sqh);
	SetIndexBuffer(5, sql);
	SetIndexBuffer(6, sqh2);
	SetIndexBuffer(7, sql2);

	SetIndexShift(4,-BarShift); // I manipulate price array for the Hodrick-Prescott Filter. Base buffer gets shifted data so I have to shift the rest accordingly
	SetIndexShift(5,-BarShift);
	SetIndexShift(6,-BarShift);
	SetIndexShift(7,-BarShift);
	
	SetIndexLabel(4,"1st High");
	SetIndexLabel(5,"1st Low");	
	SetIndexLabel(6,"2nd High");
	SetIndexLabel(7,"2nd Low");
	
	SetIndexStyle(4, DRAW_LINE);
	SetIndexStyle(5, DRAW_LINE);
	SetIndexStyle(6, DRAW_LINE);
	SetIndexStyle(7, DRAW_LINE);
  
	SetIndexEmptyValue(4, 0.0); // EMPTY_VALUE?
	SetIndexEmptyValue(5, 0.0);
	SetIndexEmptyValue(6, 0.0);
	SetIndexEmptyValue(7, 0.0);


	// Internal Heiken Ashi
	previousBarCount = 0;
	if (UseHaReversals)
		{
			ArrayResize(HaLow,Bars);
			ArrayResize(HaHigh,Bars);
			ArrayResize(HaOpen,Bars);
			ArrayResize(HaClose,Bars);
			
			ArrayInitialize(HaLow, EMPTY_VALUE);
			ArrayInitialize(HaHigh, EMPTY_VALUE);
			ArrayInitialize(HaOpen, EMPTY_VALUE);
			ArrayInitialize(HaClose, EMPTY_VALUE);
			
			ArraySetAsSeries(HaLow, true);
			ArraySetAsSeries(HaHigh, true);
			ArraySetAsSeries(HaOpen, true);
			ArraySetAsSeries(HaClose, true);
		}
		
	// so called Fractal stuff
	if (UseFractalTriggers)
		{
			ArrayResize(FractalUpArrow,Bars);
			ArrayResize(FractalDownArrow,Bars);
			ArrayResize(FractalUpLevel,Bars);
			ArrayResize(FractalDownLevel,Bars);
			
			ArrayInitialize(FractalUpArrow, EMPTY_VALUE);
			ArrayInitialize(FractalDownArrow, EMPTY_VALUE);
			ArrayInitialize(FractalUpLevel, EMPTY_VALUE);
			ArrayInitialize(FractalDownLevel, EMPTY_VALUE);
			
			ArraySetAsSeries(FractalUpArrow, true);
			ArraySetAsSeries(FractalDownArrow, true);
			ArraySetAsSeries(FractalUpLevel, true);
			ArraySetAsSeries(FractalDownLevel, true);
		}

	// PowerSaver
	if (PowerSaver <=0) PowerSaver = 0;
	int timeFrameSeconds = timeFrame*60;
	if (PowerSaver >timeFrameSeconds) PowerSaver = timeFrameSeconds; // it doesn't make sense to calcucate less frequently.
	powerSaverInterval = PowerSaver*1000; // I need miliseconds
	//Print("PowerSaver ", PowerSaver, " powerSaverInterval ", powerSaverInterval);
	
	return(0);
}
//----------------------------------------------------------
int deinit()
{
	return(Nothing);
}
//----------------------------------------------------------
// Tom Strignano Catapult entry
double TomCatapultHigh(int bar)
{
	int targetBar;	
	if (UseTomTimeFrame) // check only round hour bars for signal conditions while current bar for passing threshold
		{
			datetime barTime = Time[bar];
			// let's strip it from minutes and seconds easy way
			barTime -= (TimeMinute(barTime)*60+TimeSeconds(barTime));
			targetBar = iBarShift(symbol,targetTimeFrame,barTime, true);
		}
	else targetBar = bar;
	
	if (iOpen(symbol,targetTimeFrame,targetBar+1)	< iClose(symbol,targetTimeFrame,targetBar+1)&& 
		iOpen(symbol,targetTimeFrame,targetBar+2)	> iClose(symbol,targetTimeFrame,targetBar+2)&& 
		iLow(symbol,targetTimeFrame,targetBar+1) 	> iLow(symbol,targetTimeFrame,targetBar+2)	&& 
		//iClose(symbol,targetTimeFrame,bar) 	< iLow(symbol,targetTimeFrame,targetBar+2))
		Close[bar] 	< iLow(symbol,targetTimeFrame,targetBar+2))
			{
				return (iHigh(symbol,targetTimeFrame,targetBar));
			}
	else return(Nothing);
}
//----------------------------------------------------------
double TomCatapultLow(int bar) // Long entry
{
	int targetBar;
	if (UseTomTimeFrame) // check only round hour bars for signal conditions while current bar for passing threshold
		{
			datetime barTime = Time[bar];
			// let's strip it from minutes and seconds easy way
			barTime -= (TimeMinute(barTime)*60+TimeSeconds(barTime));
			targetBar = iBarShift(symbol,targetTimeFrame,barTime, true);
		}
	else targetBar = bar;
	
	if (iOpen(symbol,targetTimeFrame,targetBar+1)	> iClose(symbol,targetTimeFrame,targetBar+1)&& 
		iOpen(symbol,targetTimeFrame,targetBar+2)	< iClose(symbol,targetTimeFrame,targetBar+2)&& 
		iHigh(symbol,targetTimeFrame,targetBar+1)	< iHigh(symbol,targetTimeFrame,targetBar+2)	&& 
		//iClose(symbol,targetTimeFrame,targetBar) 	> iHigh(symbol,targetTimeFrame,targetBar+2))
		Close[bar] 	> iHigh(symbol,targetTimeFrame,targetBar+2))
			{
				return (iLow(symbol,targetTimeFrame,targetBar));
			}
	else return(Nothing);
}
//----------------------------------------------------------
// Demark Pivots calculation - I don't even know the original author. Kara Software Corp, GreenDog, whoever he/she is - contact me regarding your code usage
double DemHigh(int cnt, int sh)
{
	if (High[cnt]>=High[cnt+sh] && High[cnt]>High[cnt-sh])
		{
			if (sh>1) return(DemHigh(cnt,sh-1));
			else return(High[cnt]);
		}
	else return(Nothing);
}
//----------------------------------------------------------
double DemLow(int cnt, int sh)
{
	if (Low[cnt]<=Low[cnt+sh] && Low[cnt]<Low[cnt-sh])
		{
			if (sh>1) return(DemLow(cnt,sh-1));
			else return(Low[cnt]);
		}
	else return(Nothing);
}
//----------------------------------------------------------
int checkConfirmation(int bar) // check the trend direction. Very simple yet very accurate :-)
{
	if (showTrueHistory) 
		{
			if (bar == 0) bar = UseClosedCandle; // bar 0 is always open. If I check only closed candles, I should omit it;
			else bar = 0; // the curve is already shifted. I need only the first value
		}
	if (useHPF) bar -= BarShift; // workaround...
	
	if 		(extrapolatedCurve[bar] > extrapolatedCurve[bar+1]) return(Up);
	else if (extrapolatedCurve[bar] < extrapolatedCurve[bar+1]) return(Down);
	
	return (Nothing);
 }
//----------------------------------------------------------
int checkConditions(int bar) // this will require some cleanup. Basically I check Heiken Ashi candles for reversal and Demark for pivots.
{
	if (!EnableTradeSignals) return (Nothing); // not signal if no any needed

	double Value3,Value4;
	int HaCandle, prevHaCandle;
	
	int confirmation;
	int HaSignal = Nothing, DemSignal = Nothing, TomSignal = Nothing;

	if (UseHaReversals)
		{
			if (UseInternalHA)
				{
					// check if the candle is up or down bar
					Value3	= HaOpen[bar];
					Value4	= HaClose[bar];
					
					if (Value3 > Value4) // down bar
						HaCandle = Sell;
					else				// up bar
						HaCandle = Buy;
						
					// now check the previous one
					Value3	= HaOpen[bar+1];
					Value4	= HaClose[bar+1];
				
					if (Value3 > Value4)
						prevHaCandle = Sell;
					else				
						prevHaCandle = Buy;	
				}			
			else
				{
					// check if the candle is up or down bar
					Value3	= iCustom(symbol, timeFrame, "Heiken Ashi", Red, White, Red, White, 2, bar);
					Value4	= iCustom(symbol, timeFrame, "Heiken Ashi", Red, White, Red, White, 3, bar);
					
					if (Value3 > Value4) // down bar
						HaCandle = Sell;
					else				// up bar
						HaCandle = Buy;
						
					// now check the previous one
					Value3	= iCustom(symbol, timeFrame, "Heiken Ashi", Red, White, Red, White, 2, bar+1);
					Value4	= iCustom(symbol, timeFrame, "Heiken Ashi", Red, White, Red, White, 3, bar+1);
				
					if (Value3 > Value4)
						prevHaCandle = Sell;
					else				
						prevHaCandle = Buy;	
				}
				
			// if the two candles are opposite, we have a possible reversal
			HaSignal = Nothing;
			if (HaCandle == Buy && prevHaCandle == Sell) HaSignal = Buy;
			if (HaCandle == Sell && prevHaCandle == Buy) HaSignal = Sell;
		}
		
	// Demark pivots
	if (UseDemarkPivots)
		{
			if (DemHigh(bar,LevDP) > 0) DemSignal=Sell;
			if (DemLow(bar,LevDP) > 0) DemSignal=Buy;
		}

	// Tom Strignano
	if(UseTomCatapult)
		{
			if (TomCatapultHigh(bar) > 0) TomSignal=Sell;
			if (TomCatapultLow(bar) > 0) TomSignal=Buy;
		}

	// Now I have to mix the signals
	
	int finalSignal = Nothing;
	
	// let's make it classic bit parade, I'll optimize it later on;
	if (HaSignal == Nothing && DemSignal == Nothing && TomSignal == Nothing) return (Nothing); 			//000
	if (HaSignal == Nothing && DemSignal == Nothing && TomSignal != Nothing) finalSignal = TomSignal; 	//001
	if (HaSignal == Nothing && DemSignal != Nothing && TomSignal == Nothing) finalSignal = DemSignal;	//010
	if (HaSignal == Nothing && DemSignal != Nothing && TomSignal != Nothing) 							//011
		{
			// in case of conflict, Tom wins
			 finalSignal = TomSignal;
		}
	if (HaSignal != Nothing && DemSignal == Nothing && TomSignal == Nothing) finalSignal = HaSignal; 	//100
	if (HaSignal != Nothing && DemSignal == Nothing && TomSignal != Nothing)							//101
		{
			// in case of conflict, Tom wins
			 finalSignal = TomSignal;
		}
	if (HaSignal != Nothing && DemSignal != Nothing && TomSignal == Nothing)							//110
		{
			// in case of conflict, Demark wins
			 finalSignal = DemSignal;
		}
	if (HaSignal != Nothing && DemSignal != Nothing && TomSignal != Nothing)							//111
		{
			// now I check for majority vote
			double sum = HaSignal + DemSignal + TomSignal;
			sum /=3;
			if (sum > 0) finalSignal = Buy;
			if (sum < 0) finalSignal = Sell;
			
			// alternate Tom wins
			// finalSignal = TomSignal;					
		}

	if (finalSignal !=Nothing)
		{
			if (!ShowAllEntryPoints) confirmation = checkConfirmation(bar); else confirmation = Any; // this is for testing purposes. If ShowAllEntryPoints = true, it will show all entry points unfiltered.
			
			if ((finalSignal == Buy && (confirmation == Buy || confirmation == Any)) || (finalSignal == Sell && (confirmation == Sell || confirmation == Any))) return (finalSignal);
			else return (Nothing);
		}
   	return (Nothing);
}
//----------------------------------------------------------
int start()
{
	currentCPUtime = GetTickCount();
	if (PowerSaver <=0 || currentCPUtime >= previousCPUtime+powerSaverInterval)
		{
			//Print("previousCPUtime ", previousCPUtime, " currentCPUtime ", currentCPUtime);
			if (Bars < barsRequired) return(Nothing);
			int counted_bars=IndicatorCounted();
			//---- check for possible errors
			if(counted_bars<0) return(-1);
			if(counted_bars>0) counted_bars--;
			
			int i, currentBarResult = Nothing;
			double currentBar, previousBar;
			bool up = false;
		
			// ....................................
			// Heiken Ashi and Fractal level stuff
			// at the moment it is calculated across all bars available. But It can be shortened to match the Extratrend/HPF.
			if (UseHaReversals || UseFractalTriggers)
				{
					currentBarCount = Bars;
					if (currentBarCount > previousBarCount)
						{	
							if (ArraySize(HaLow) < currentBarCount)
								{
									if (UseHaReversals)
										{
											increaseArray(HaLow,currentBarCount,EMPTY_VALUE);
											increaseArray(HaHigh,currentBarCount,EMPTY_VALUE);
											increaseArray(HaOpen,currentBarCount,EMPTY_VALUE);
											increaseArray(HaClose,currentBarCount,EMPTY_VALUE);
										}
										
									if (UseFractalTriggers)
										{
											increaseArray(FractalUpArrow,currentBarCount,EMPTY_VALUE);
											increaseArray(FractalDownArrow,currentBarCount,EMPTY_VALUE);
											increaseArray(FractalUpLevel,currentBarCount,EMPTY_VALUE);
											increaseArray(FractalDownLevel,currentBarCount,EMPTY_VALUE);
										}
								}
							previousBarCount = currentBarCount;
						}
					
					double haOpen, haHigh, haLow, haClose;
					int pos;
					int ExtCountedBars=IndicatorCounted();
					
					// I need some more bars to recalculate if Fractals used
					if (UseFractalTriggers)
						{
							if(ExtCountedBars<=2) pos=Bars-ExtCountedBars-3;
							else
								{
									ExtCountedBars--;
									pos=Bars-ExtCountedBars-1;
								}
						}
					else
						{
							if (ExtCountedBars>0) ExtCountedBars--;
							pos=Bars-ExtCountedBars-1;		
						}
						
					if (pos > barsRequired) pos = barsRequired+1; // I don't need full history.
				
					bool   bFound;
					double dCurrent;
					while(pos>=0)
						{
							// Heiken Ashi
							haOpen=(HaOpen[pos+1]+HaClose[pos+1])/2;
							haClose=(Open[pos]+High[pos]+Low[pos]+Close[pos])/4;
							haHigh=MathMax(High[pos], MathMax(haOpen, haClose));
							haLow=MathMin(Low[pos], MathMin(haOpen, haClose));
							if (haOpen<haClose) 
								{
									HaLow[pos]=haLow;
									HaHigh[pos]=haHigh;
								} 
							else
								{
									HaLow[pos]=haHigh;
									HaHigh[pos]=haLow;
								} 
							HaOpen[pos]=haOpen;
							HaClose[pos]=haClose;
							
							// Fractals	- again, I don't need full history - about 200 bars should be OK.
							if (pos>=2 && pos < 200)
								{
									//----Fractals up
									bFound=false;
									dCurrent=High[pos];
									if(dCurrent>High[pos+1] && dCurrent>High[pos+2] && dCurrent>High[pos-1] && dCurrent>High[pos-2])
										{
											bFound=true;
											FractalUpArrow[pos]=dCurrent;
										}
									//----6 bars Fractal
									if(!bFound && (Bars-pos-1)>=3)
										{
											if(dCurrent==High[pos+1] && dCurrent>High[pos+2] && dCurrent>High[pos+3] &&
											dCurrent>High[pos-1] && dCurrent>High[pos-2])
												{
													bFound=true;
													FractalUpArrow[pos]=dCurrent;
												}
										}         
									//----7 bars Fractal
									if(!bFound && (Bars-pos-1)>=4)
										{   
											if(dCurrent>=High[pos+1] && dCurrent==High[pos+2] && dCurrent>High[pos+3] && dCurrent>High[pos+4] &&
											dCurrent>High[pos-1] && dCurrent>High[pos-2])
												{
													bFound=true;
													FractalUpArrow[pos]=dCurrent;
												}
										}  
									//----8 bars Fractal                          
									if(!bFound && (Bars-pos-1)>=5)
										{   
											if(dCurrent>=High[pos+1] && dCurrent==High[pos+2] && dCurrent==High[pos+3] && dCurrent>High[pos+4] && dCurrent>High[pos+5] && 
											dCurrent>High[pos-1] && dCurrent>High[pos-2])
												{
													bFound=true;
													FractalUpArrow[pos]=dCurrent;
												}
										} 
									//----9 bars Fractal                                        
									if(!bFound && (Bars-pos-1)>=6)
										{   
										if(dCurrent>=High[pos+1] && dCurrent==High[pos+2] && dCurrent>=High[pos+3] && dCurrent==High[pos+4] && dCurrent>High[pos+5] && 
										dCurrent>High[pos+6] && dCurrent>High[pos-1] && dCurrent>High[pos-2])
											{
												bFound=true;
												FractalUpArrow[pos]=dCurrent;
											}
										}                                    
									//----Fractals down
									bFound=false;
									dCurrent=Low[pos];
									if(dCurrent<Low[pos+1] && dCurrent<Low[pos+2] && dCurrent<Low[pos-1] && dCurrent<Low[pos-2])
										{
											bFound=true;
											FractalDownArrow[pos]=dCurrent;
										}
									//----6 bars Fractal
									if(!bFound && (Bars-pos-1)>=3)
										{
											if(dCurrent==Low[pos+1] && dCurrent<Low[pos+2] && dCurrent<Low[pos+3] &&
											dCurrent<Low[pos-1] && dCurrent<Low[pos-2])
												{
													bFound=true;
													FractalDownArrow[pos]=dCurrent;
												}                      
										}         
									//----7 bars Fractal
									if(!bFound && (Bars-pos-1)>=4)
										{   
											if(dCurrent<=Low[pos+1] && dCurrent==Low[pos+2] && dCurrent<Low[pos+3] && dCurrent<Low[pos+4] &&
											dCurrent<Low[pos-1] && dCurrent<Low[pos-2])
												{
													bFound=true;
													FractalDownArrow[pos]=dCurrent;
												}                      
										}  
									//----8 bars Fractal                          
									if(!bFound && (Bars-pos-1)>=5)
										{   
											if(dCurrent<=Low[pos+1] && dCurrent==Low[pos+2] && dCurrent==Low[pos+3] && dCurrent<Low[pos+4] && dCurrent<Low[pos+5] && 
											dCurrent<Low[pos-1] && dCurrent<Low[pos-2])
												{
													bFound=true;
													FractalDownArrow[pos]=dCurrent;
												}                      
										} 
									//----9 bars Fractal                                        
									if(!bFound && (Bars-pos-1)>=6)
										{   
											if(dCurrent<=Low[pos+1] && dCurrent==Low[pos+2] && dCurrent<=Low[pos+3] && dCurrent==Low[pos+4] && dCurrent<Low[pos+5] && 
											dCurrent<Low[pos+6] && dCurrent<Low[pos-1] && dCurrent<Low[pos-2])
												{
													bFound=true;
													FractalDownArrow[pos]=dCurrent;
												}                      
										}  
									
									// Levels
									FractalUpLevel[pos] = FractalUpArrow[pos];
									if(FractalUpLevel[pos] == EMPTY_VALUE) FractalUpLevel[pos] = FractalUpLevel[pos+1];
									
									FractalDownLevel[pos] = FractalDownArrow[pos];
									if(FractalDownLevel[pos] == EMPTY_VALUE) FractalDownLevel[pos] = FractalDownLevel[pos+1];				
								}
							else
								{
									FractalUpLevel[pos] = FractalUpLevel[pos+1];
									FractalDownLevel[pos] = FractalDownLevel[pos+1];				
								}
							pos--;
						}
				}
			// ....................................
		
			if (showTrueHistory)
				{
					// now how many bars to process in the current loop
					int barsToProcess = Bars-counted_bars;
					if (barsToProcess > nobs) barsToProcess = nobs;
					//for (i=BarShift;i<barsToProcess+BarShift;i++)
					//Print ("barsToProcess ", barsToProcess-1);
					//for (i=0;i<barsToProcess;i++)
					//int loopcount = 0;
					for (i=barsToProcess-1;i>=0;i--) // I need to go with the time, not backward...
						{
							//loopcount ++;
							ArrayCopy(priceData, Close, 0, i+BarShift, nobs);
							if (useHPF) HPFDLLnoLambda(FiltPer, nobs, 0, LambdaBuf, priceData, extrapolatedCurve);
							else  calculateExtratrendDll(ExtratrendBars, extratrendHarmonics, FreqTOL, priceData, extrapolatedCurve);
							nonRepaintingCurve[i] = extrapolatedCurve[0]; // na razie tak... potem trzeba bedzie dorobic obejscie 0...
							
							if (Show1stBand || Show2ndBand)
								{							
									sigmaBands(nobs, firstBand, secondBand, priceData, extrapolatedCurve, fh, fl, sh, sl);
									
									if(Show1stBand)
										{
											ArrayCopy(sqh, fh, i, 0, 1); // jeden, czy dwa?
											ArrayCopy(sql, fl, i, 0, 1);
										}
									
									if(Show2ndBand)
										{
											ArrayCopy(sqh2, sh, i, 0, 1);
											ArrayCopy(sql2, sl, i, 0, 1);
										}			
								}
								// end of standart deviation
		
							
							// this is only for visual control
							int currentBarIndex = 0; 
							if (i == 0) currentBarIndex = UseClosedCandle; // bar 0 is always open. If I check only closed candles, I should omit it;
							
							currentBar = extrapolatedCurve[currentBarIndex];
							previousBar = extrapolatedCurve[currentBarIndex+1];
		
							if(currentBar >= previousBar) up = true; else up = false;
							
							if (up)
								{
									TrendUp[i] = currentBar; 
									if(i > 0 && TrendUp[i+1] == EMPTY_VALUE) TrendDown[i] = currentBar; else TrendDown[i] = EMPTY_VALUE;
								}
							else
								{
									TrendDown[i] = currentBar;
									if(i > 0 && TrendDown[i+1] == EMPTY_VALUE) TrendUp[i] = currentBar; else TrendUp[i] = EMPTY_VALUE;
								}
							
							if (i>= BarShift) // this gives me some pain... two methods of indexing...
								{
									result = checkConditions(i);
									if (i==UseClosedCandle) currentBarResult = result; // I save it here for alarm usage...
									if (result == Buy) BuySignalBuffer[i] = Low[i];	else BuySignalBuffer[i] = EMPTY_VALUE;
									if (result == Sell) SellSignalBuffer[i] = High[i];else SellSignalBuffer[i] = EMPTY_VALUE;
								}
						}
					//Print ("bars caulculated ",loopcount);
				}
			else
				{
					ArrayCopy(priceData, Close, 0, BarShift, nobs);
					if (useHPF) HPFDLLnoLambda(FiltPer, nobs, 0, LambdaBuf, priceData, extrapolatedCurve);
					else  calculateExtratrendDll(ExtratrendBars, extratrendHarmonics, FreqTOL, priceData, extrapolatedCurve);
		
					// standart deviation
				
					if (Show1stBand || Show2ndBand)
						{
							sigmaBands(nobs, firstBand, secondBand, priceData, extrapolatedCurve, fh, fl, sh, sl);
							
							if(Show1stBand)
								{
									ArrayCopy(sqh, fh, 0, 0, nobs);
									ArrayCopy(sql, fl, 0, 0, nobs);
								}
							
							if(Show2ndBand)
								{
									ArrayCopy(sqh2, sh, 0, 0, nobs);
									ArrayCopy(sql2, sl, 0, 0, nobs);
								}			
						}
						// end of standart deviation
		
					for(i=0; i<nobs; i++) // frankly, it should be walked other way, with time, not against...
						 {
							// this is only for visual control only
							currentBar = extrapolatedCurve[i];
							previousBar = extrapolatedCurve[i+1];
							
							if(currentBar >= previousBar) up = true; else up = false;
							
							if (up)
								{
									TrendUp[i] = currentBar; 
									if(i > 0 && TrendUp[i-1] == EMPTY_VALUE) TrendDown[i] = currentBar; else TrendDown[i] = EMPTY_VALUE;
								}
							else
								{
									TrendDown[i] = currentBar;
									if(i > 0 && TrendDown[i-1] == EMPTY_VALUE) TrendUp[i] = currentBar; else TrendUp[i] = EMPTY_VALUE;
								}
								
							result = checkConditions(i+BarShift);
							if (i==UseClosedCandle) currentBarResult = result; // I save it here for alarm usage...
				
							if (result == Buy) BuySignalBuffer[i+BarShift] = Low[i+BarShift];	else BuySignalBuffer[i+BarShift] = EMPTY_VALUE;
							if (result == Sell) SellSignalBuffer[i+BarShift] = High[i+BarShift];else SellSignalBuffer[i+BarShift] = EMPTY_VALUE;
						 }		
				}
		
			//result = currentBarResult; // recalling saved value
			
		// alarm
			if (currentBarResult != Nothing && currentBarResult != prevResult)
				{
					if (EnableAlarm)
						{
							string altertText;
							if (currentBarResult == Buy) altertText = "Buy ";
							if (currentBarResult == Sell) altertText = "Sell ";
							altertText = StringConcatenate("Scalpel: ", altertText, Symbol (), " ",timeFrameName);
							Alert(altertText);		
							Print("-----------------------------------");
							altertText = ">>>>>>>  " + altertText;
							Print(altertText);
							Print("-----------------------------------");
						}
				}
			prevResult = currentBarResult;
			
			previousCPUtime = GetTickCount();
 		}
//---- end of main loop

   return(0);
}
//----------------------------------------------------------
bool increaseArray(double& array[], int targetSize, double blankValue)
{	
	int currentSize = ArraySize(array);
	if (targetSize <= currentSize) return (false);
	if (blankValue != NULL || blankValue != EMPTY_VALUE) blankValue = EMPTY_VALUE;
	double tempArray[];
	ArrayResize(tempArray, currentSize);
	bool reversedOrder = ArrayGetAsSeries(array);
	if (reversedOrder) ArraySetAsSeries(array, false);
	ArrayCopy(tempArray, array, 0, 0, WHOLE_ARRAY);
	ArrayResize(array, targetSize);
	ArrayInitialize(array, blankValue);
	ArrayCopy(array, tempArray, 0, 0, WHOLE_ARRAY);
	if (reversedOrder) ArraySetAsSeries(array, true);
	return(true);
}