#4X 2010 Sigma Bands

#4X 2010 Sigma Bands

Overview of Logic and Functionality

This script is a sophisticated technical analysis tool designed to identify market trends and generate potential trade signals. It operates by combining several advanced mathematical filters, price action patterns, and volatility measurements to "clean" the market noise and highlight significant movements. Instead of relying on a single indicator, it uses a multi-layered approach to confirm whether a trend is actually shifting or if the price is simply experiencing temporary fluctuations.

Core Analytical Components

To reach its conclusions, the script processes data through three primary engines:

1. Trend Identification (The Foundation) The tool uses two different methods to determine the "true" underlying direction of the market:

  • Hodrick-Prescott Filter: A sophisticated mathematical method used to separate a time series into a trend component and a cyclical component. It is excellent for smoothing out short-term noise while preserving long-term movements.
  • Extratrend Dynamics: An alternative method that calculates harmonic curves based on historical price data, helping to visualize the momentum of the market.

2. Volatility and Boundaries (Sigma Bands) The script calculates "Sigma Bands" (Standard Deviation levels). These act as dynamic boundaries around the trend lines. By identifying when prices deviate significantly from the mean (the 1st and 2nd standard deviations), the tool can help determine if a move is becoming overextended or if it is staying within a normal range of volatility.

3. Signal Confirmation (The Decision Makers) Before displaying a "Buy" or "Sell" arrow on the chart, the script cross-references three different types of market behavior:

  • Heiken Ashi Reversals: It looks at modified candlestick patterns to detect changes in momentum. A signal is only considered if the current candle type contradicts the previous one.
  • Demark Pivots: This identifies "pivot points"—local highs and lows where the price has stabilized relative to the surrounding bars.
  • Tom Strignano Catapult: Based on specific trading techniques, this looks for "catapult" entries where price action breaks out of a defined historical level.

Signal Logic and Execution

The script follows a rigorous "voting" system to ensure high-quality signals:

  • Conflict Resolution: If different methods provide conflicting information (e.g., one suggests a Buy while another suggests a Sell), the script applies a hierarchy of importance. For instance, certain technical patterns are given priority over others to decide which signal takes precedence.
  • Majority Voting: In complex scenarios where multiple signals occur simultaneously, the tool calculates a "majority vote" to determine the final output.
  • Trend Confirmation: Even if a primary signal is generated, the script performs a final check against the underlying trend curve (calculated by the HPF or Extratrend). A "Buy" signal is only displayed if it aligns with an upward trend, and a "Sell" signal is only shown during a downward trend.

User Experience Features

  • Power Management: The script includes a "PowerSaver" mode that limits how often the complex calculations are run, ensuring it doesn't slow down your computer during high-activity periods.
  • Alert System: It can be configured to trigger audio and visual alerts the moment a confirmed signal is detected, allowing for real-time monitoring without constantly staring at the charts.
  • Visual Customization: Users can toggle the visibility of various bands, trend lines, and historical data points to tailor the visual display to their specific trading style.
Price Data Components
Series array that contains open prices of each barSeries array that contains close prices for each barSeries array that contains the lowest prices of each barSeries array that contains the highest prices of each bar
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
7 Views
0 Downloads
0 Favorites
#4X 2010 Sigma Bands
 
// #4X 2010 Sigma Bands       \¦/
// Knowledge of the ancients (ò ó)
//______________________o0o___(_)___o0o_____
//___¦Xard777¦_____¦_____¦_____¦_____¦_2010_¦

#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	= false; // 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 = true; // show 1st deviation
extern bool 	Show2ndBand = true; // show 2nd deviation
extern double 	kstd = 1.83924;//1.63108;//1.5; 	// 1st deviation
extern double 	kstd2 = 2.45323;//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	Blue
#property indicator_color4	Gold

#property indicator_width1  1
#property indicator_width2  1
#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 Yellow//Orange
#property indicator_color6 Yellow//Orange
#property indicator_color7 Yellow//Orange
#property indicator_color8 Yellow//Orange

#property  indicator_style5  1
#property  indicator_style6  1
#property  indicator_style7  1
#property  indicator_style8  1

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_NONE);//change to DRAW_LINE for middle line
	SetIndexStyle(3,DRAW_NONE);//change to DRAW_LINE for middle 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);
}

Comments