stevehopwoodforex.com
https://www.stevehopwoodforex.com/phpBB3/
Print view

Zigzag Bollinger Band
https://www.stevehopwoodforex.com/phpBB3/viewtopic.php?t=3237
Page 4 of 28
Author:  snailbeard [ Mon Dec 16, 2013 6:07 pm ]
Post subject:  Re: Zigzag Bollinger Band

And here is the code in case someone else has the same issue:

Code: Select all

/* ----------------------------------------------------------------------------------------------------------------------
	bwaGetHighLow.mq4

	Copyright Brian Abram 2013
	www.pipad.co.uk
	Licence: GPL (The GNU General Public License (GPL-2.0) Version 2, June 1991; http://opensource.org/licenses/gpl-2.0.php )
	
	Empty4 CrappyTester does not provide proper Bar High/Low behaviour which is why a module like this is required!
	This module keeps track of the highest and lowest price for each bar type.
	Also some minutes are 'lost' by CrappyTester here and there so the retart of a new bar can also be 'lost'
	It is mainly due to 'zero' bars in the data but my new bar detection code could be improved to better manage missing minutes
	
	Note:MQL is MetaQuotes MetatTrader 4 programming language based on 'C'.
	It is an anachronism, a dinosaur, and requires old style programming methods such as global variables.
	It is ideal for small simple programs and positivily inappropriate for anything sophisticated.
	Unfortunately I am stuck here due to a large body of code already created out of earlier development in mql.
	However, if you are reading this and thinking of starting a non-trivial project 
	then it is worth considering developing code in say C#/dotNet or Java.
	
	I hope nobody needs this module but if you do I hope you find it useful. Let me know if you spot any problems with it.
	This first version is only tested with AUDUSD and Sunday candles
------------------------------------------------------------------------------------------------------------------------ */

//#include "bwaGetHighLow.mqh"

/// Empty4 CrappyTester does not provide proper Bar High/Low behaviour which is why this is required!
double GHL_dMN1BarHighest = -1.0;
double GHL_dW1BarHighest = -1.0;
double GHL_dD1BarHighest = -1.0;
double GHL_dH4BarHighest = -1.0;
double GHL_dH1BarHighest = -1.0;
double GHL_dM30BarHighest = -1.0;
double GHL_dM15BarHighest = -1.0;
double GHL_dM5BarHighest = -1.0;
double GHL_dM1BarHighest = -1.0;

double GHL_dMN1BarLowest = -1.0;
double GHL_dW1BarLowest = -1.0;
double GHL_dD1BarLowest = -1.0;
double GHL_dH4BarLowest = -1.0;
double GHL_dH1BarLowest = -1.0;
double GHL_dM30BarLowest = -1.0;
double GHL_dM15BarLowest = -1.0;
double GHL_dM5BarLowest = -1.0;
double GHL_dM1BarLowest = -1.0;

int GHL_CountTotalLostMinutes = 0;
int GHL_CountInstancesLostMinutes = 0;
int GHL_CountEachLostSingleMins = 0;
datetime GHL_TimeOfLostMinute[1000] = {0};
int GHL_LostMinutePrevMin[1000] = {0};
int GHL_LostMinuteCurrMin[1000] = {0};
int GHL_ElapsedSeconds[1000] = {0};

//bool   GHL_addSundayToMonday     = true;
bool   GHL_sundayCandlesDetected = false;

#define GHL_MaxTradingDays 7
int GHL_HoursPerDay[GHL_MaxTradingDays];

#define GHL_M5BarIdx  0
#define GHL_M15BarIdx  1
#define GHL_M30BarIdx  2
#define GHL_H1BarIdx  3
#define GHL_H4BarIdx  4

#define GHL_MaxBarTypes 5
int GHL_BarsPerDay[GHL_MaxBarTypes];

int GHL_TotalExpectedMins = 0;
int GHL_TotalReceivedMins = 0;
#define MAXDAYSPERMONTH 32  // start on 1 not 0
int GHL_CountedDays;
int GHL_CalculatedD1Mins[MAXDAYSPERMONTH];
int GHL_ReceivedD1Mins[MAXDAYSPERMONTH];
int GHL_MissingD1Mins[MAXDAYSPERMONTH];

int GHL_CalculatedH4Bars[MAXDAYSPERMONTH];
int GHL_ReceivedH4Bars[MAXDAYSPERMONTH];
int GHL_MissingH4Bars[MAXDAYSPERMONTH];

int GHL_CalculatedH1Bars[MAXDAYSPERMONTH];
int GHL_ReceivedH1Bars[MAXDAYSPERMONTH];
int GHL_MissingH1Bars[MAXDAYSPERMONTH];
	
int GHL_CalculatedM30Bars[MAXDAYSPERMONTH];
int GHL_ReceivedM30Bars[MAXDAYSPERMONTH];
int GHL_MissingM30Bars[MAXDAYSPERMONTH];

int GHL_CalculatedM15Bars[MAXDAYSPERMONTH];
int GHL_ReceivedM15Bars[MAXDAYSPERMONTH];
int GHL_MissingM15Bars[MAXDAYSPERMONTH];

int GHL_CalculatedM5Bars[MAXDAYSPERMONTH];
int GHL_ReceivedM5Bars[MAXDAYSPERMONTH];
int GHL_MissingM5Bars[MAXDAYSPERMONTH];

int GHL_CountLostM5BarRestarts = 0;
int GHL_CountLostM15BarRestarts = 0;
int GHL_CountLostM30BarRestarts = 0;
int GHL_CountLostH1BarRestarts = 0;
int GHL_CountLostH4BarRestarts = 0;

int GHL_CountM5BarRestarts = 0;
int GHL_CountM15BarRestarts = 0;
int GHL_CountM30BarRestarts = 0;
int GHL_CountH1BarRestarts = 0;
int GHL_CountH4BarRestarts = 0;

bool GHL_TestBarHighLow = true;

	// Check progress of almost complete bars
int GHL_TestMonth = 4; // April
int GHL_Test3DayOfMonth = 28; // Wednesday
static int GHL_Test3Hour = 20; // 8 pm 
static int GHL_Test3Minute = 59; // almost 9pm final trading minute of Friday

static string GHL_StrDOW[] ={ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };

/* -----------------------------------------------------------
	forceHighLowExit()
---------------------------------------------------------- */
void forceHighLowExit(string strReason)
{
	int a = 0, b = 1, c;
	Print("bwaGetHighLow() serious fault: "+ strReason );
	c = b / a;
}

/* -----------------------------------------------------------
	init_GHL_DetectSundayCandle()
---------------------------------------------------------- */
void GHL_init_DetectSundayCandle() {
	GHL_sundayCandlesDetected = false;
	for ( int i = 0; i < 8; i++ ) {
		if ( TimeDayOfWeek( iTime( NULL, PERIOD_D1, i ) ) == 0 ) {
			GHL_sundayCandlesDetected = true;
			break;
		}
	}
}


/* -----------------------------------------------------------
	PrintBarsPerDay()
---------------------------------------------------------- */
void	PrintBarsPerDay()
{
	Print("---------------------------");
	Print("Count of bars today: " + GHL_StrDOW[ DayOfWeek() ] );
	Print("....M5 Bars : "+ GHL_BarsPerDay[GHL_M5BarIdx] );
	Print("...M15 Bars : "+ GHL_BarsPerDay[GHL_M15BarIdx] );	
	Print("...M30 Bars : "+ GHL_BarsPerDay[GHL_M30BarIdx] );
	Print("....H1 Bars : "+ GHL_BarsPerDay[GHL_H1BarIdx] );
	Print("....H4 Bars : "+ GHL_BarsPerDay[GHL_H4BarIdx] );
	Print("---------------------------\n");
}

/* -----------------------------------------------------------
	calcBarsPerDay()
---------------------------------------------------------- */
void calcBarsPerDay()
{
	static int iMaxReports = 3;
	static int iLastDay = -1;
	static bool bReportedSunday = false;
	static bool bReportedMonday = false;
	static bool bReportedFriday = false;
	static int iReportedSunday = 0;
	static int iReportedMonday = 0;
	static int iReportedFriday = 0;
	
	
	int iDayOfyear = DayOfYear();
	int iDayOfWeek = DayOfWeek() ;
	int iDayOfMonth = Day() ;
	bool bNewDay = false;
	
	if( iDayOfyear != iLastDay )
	{
		bNewDay = true;
		iLastDay = iDayOfyear;
	} else
		return;
	
	
	int iNumOfHoursToday = GHL_HoursPerDay[iDayOfWeek];
	int iNumOfMinsToday = iNumOfHoursToday * 60;
	
	GHL_BarsPerDay[GHL_M5BarIdx] = iNumOfMinsToday / 5;
	GHL_BarsPerDay[GHL_M15BarIdx] = iNumOfMinsToday / 15;
	GHL_BarsPerDay[GHL_M30BarIdx] = iNumOfMinsToday / 30;
	GHL_BarsPerDay[GHL_H1BarIdx] = iNumOfHoursToday;
	GHL_BarsPerDay[GHL_H4BarIdx] = iNumOfHoursToday / 4;
	
	GHL_CalculatedD1Mins[iDayOfMonth] = iNumOfMinsToday;
	GHL_TotalExpectedMins = GHL_TotalExpectedMins + iNumOfMinsToday;
	GHL_ReceivedD1Mins[iDayOfMonth] = 0;
	GHL_MissingD1Mins[iDayOfMonth] = 0;
	//------------------------------------------------------
	GHL_CalculatedH4Bars[iDayOfMonth] = GHL_BarsPerDay[GHL_H4BarIdx];
	GHL_ReceivedH4Bars[iDayOfMonth] = 0;

	GHL_CalculatedH1Bars[iDayOfMonth] = GHL_BarsPerDay[GHL_H1BarIdx];
	GHL_ReceivedH1Bars[iDayOfMonth] = 0;
		
	GHL_CalculatedM30Bars[iDayOfMonth] = GHL_BarsPerDay[GHL_M30BarIdx];
	GHL_ReceivedM30Bars[iDayOfMonth] = 0;

	GHL_CalculatedM15Bars[iDayOfMonth] = GHL_BarsPerDay[GHL_M15BarIdx];
	GHL_ReceivedM15Bars[iDayOfMonth] = 0;

	GHL_CalculatedM5Bars[iDayOfMonth] = GHL_BarsPerDay[GHL_M5BarIdx];
	GHL_ReceivedM5Bars[iDayOfMonth] = 0;
	//------------------------------------------------------
	bool bReportBarsPerDay = false;
	if( bReportBarsPerDay )
	{
		if( (iDayOfWeek == 0) && (iReportedSunday == 0) ) 
		{
			if( bReportedSunday == false )
			{
				PrintBarsPerDay();
				bReportedSunday = true;
				iReportedSunday++;
			}
		}
		else if( (iDayOfWeek == 1) && (iReportedMonday == 0) ) 
		{
			if( bReportedMonday == false)
			{
				PrintBarsPerDay();
				bReportedMonday = true;
				iReportedMonday++;
			}
		}
		else if( (iDayOfWeek == 5) && (iReportedFriday == 0) ) 
		{
			if( bReportedFriday == false )
			{
				PrintBarsPerDay();
				bReportedFriday = true;
				iReportedFriday++;
			}
		}
	}
}

/* -----------------------------------------------------------
	init_HoursPerDay()
---------------------------------------------------------- */
void GHL_init_HoursPerDay()
{
	GHL_HoursPerDay[1] = 24;
	GHL_HoursPerDay[2] = 24;
	GHL_HoursPerDay[3] = 24;
	GHL_HoursPerDay[4] = 24;

	if( GHL_sundayCandlesDetected )
	{
			GHL_HoursPerDay[0] = 3;
			GHL_HoursPerDay[5] = 21;
	}
	else
	{
			GHL_HoursPerDay[0] = 0;
			GHL_HoursPerDay[5] = 24;
	}
}

/* -----------------------------------------------------------
	init_BarHighLow()
---------------------------------------------------------- */
void GHL_init_BarHighLow()
{
	if( IsTesting() == false )
		return;
		
	ArrayInitialize(GHL_CalculatedD1Mins, 0);
	ArrayInitialize(GHL_ReceivedD1Mins, 0);
	ArrayInitialize(GHL_MissingD1Mins, 0);
		
	GHL_init_DetectSundayCandle();
		
	GHL_init_HoursPerDay();
}

/* -----------------------------------------------------------
	missedBarRestart()
---------------------------------------------------------- */
bool GHL_missedBarRestart( int timeframe, int iHour, int iMinute, int countedRestarts)
{


}


/* -----------------------------------------------------------
	ReportTimesOfLostMinutes()
---------------------------------------------------------- */
void ReportTimesOfLostMinutes()
{
	if( GHL_CountInstancesLostMinutes > 0 )
	{
		Print("Date stamp of lost minutes: ");
		for( int iLostMin = 1; iLostMin < GHL_CountInstancesLostMinutes; iLostMin++ )
		{
				Print( 
					"\n"
					+"\nGHL_TimeOfLostMinute[ "+ iLostMin + " ]: "  + TimeToStr( GHL_TimeOfLostMinute[iLostMin],  TIME_DATE | TIME_MINUTES | TIME_SECONDS) 
					+ "\nGHL_LostMinutePrevMin[ ]: "  + GHL_LostMinutePrevMin[iLostMin] 
					+ ", GHL_LostMinuteCurrMin[ ]: "  + GHL_LostMinuteCurrMin[iLostMin] 
					+ ", GHL_ElapsedSeconds[ ]: "  + GHL_ElapsedSeconds[iLostMin] 
				);
		}
	}
}

/* -----------------------------------------------------------
	updateBarHighLow()
---------------------------------------------------------- */
void GHL_updateBarHighLow()
{
	static bool bFirstRun = true;
	
	if( IsTesting() == false )
		return;
		
	if( bFirstRun ) {
		bFirstRun = false;
		
		GHL_init_BarHighLow();
	}
	
	static int iCountAllMins = 0;
	static int iCountMins = 0;
	static int iPrevPrevMin = 0;
	static datetime dtPreviousTime = 0;
	//static bool bRestartSunday = false;
	//static bool bDoneSundayCandle = false;
	//static bool bRestartMN1 = false;
	static bool bRestartMN1Bar = true;
	static bool bRestartW1Bar = true;
	static bool bRestartD1Bar = true;
	static bool bRestartH4Bar = true;
	static bool bRestartH1Bar = true;
	static bool bRestartM30Bar = true;
	static bool bRestartM15Bar = true;
	static bool bRestartM5Bar = true;
	
	static int iCountedH4Restarts = 0;
	static int iCountedM30Restarts = 0;	
	static int iCountedM15Restarts = 0;	
	static int iCountedM5Restarts = 0;	
	
	static int iPreviousMinute = -1;
	static int iPreviPrevMin = -1;
	static int iPreviousHour = 0;
	static int iPreviousDay = -1;
	static int iPrevDayOfWeek = -1;
	static int iPreviousMonth = -1;
	//----------------------------
	static double st_dMN1BarHighest = -1;
	static double st_dMN1BarLowest = -1;	
	
	static int iPrevM30Bar = -1;
	static int iPrevM15Bar = -1;
	static int iPrevM5Bar = -1;
	
	static int iM5Remainder = -1;
	static int iM15Remainder = -1;
	static int iM30Remainder = -1;
	static int iH4Remainder = -1;
	//----------------------------
	static int iM5AllRemainder = -1;
	static int iM5CyclicRemainder = -1;
	
	int iM5Parts = 0;
	int iM15Parts = 0;
	int iM30Parts = 0;
	int iH4Parts = 0;
	
	int iCurrM30Bar = -1;
	int iCurrM15Bar = -1;
	int iCurrM5Bar = -1;

	int iCurrMin = Minute();
	int iCurrHour = Hour();
	int iCurrMonth = Month();
	int iDayOfWeek = DayOfWeek();
	int iDayOfMonth = Day();
	int iDayOfyear = DayOfYear();
	//---------------------------
	bool bNewMinute = false;
	int iMinuteDiff = 0;
	int iMinuteErrorDiff = 0;
	datetime dtNow = 0;
	int dtElapsed = 0;

	double dValue = Ask;
	bool bCorrectHourWrap = false;

	if( iCurrMin != iPreviousMinute )
	{
		dtNow = TimeCurrent();
		dtElapsed = dtNow - dtPreviousTime;

		if( iPreviousMinute == 59 && iCurrMin == 0 )
		{
			bCorrectHourWrap = true;
		} else {
		
			iMinuteDiff = iCurrMin - iPreviousMinute;
			if( (iMinuteDiff > 1) || (iMinuteDiff < -1) )
			{
				if( iPreviousDay == iDayOfyear )
				{
					GHL_CountInstancesLostMinutes++;
					
					GHL_TimeOfLostMinute[GHL_CountInstancesLostMinutes] = TimeCurrent();
					GHL_LostMinutePrevMin[GHL_CountInstancesLostMinutes] = iPreviousMinute;
					GHL_LostMinuteCurrMin[GHL_CountInstancesLostMinutes] = iCurrMin;
					GHL_ElapsedSeconds[GHL_CountInstancesLostMinutes] = dtElapsed;				
				}
			}
		
		}
		
		dtPreviousTime = dtNow;
	}
	//----------------------------
	if( iCurrMin != iPreviousMinute )
	{
		bNewMinute = true;
		// start M1 again...
		GHL_dM1BarHighest = dValue;
		GHL_dM1BarLowest = dValue;

		iCountMins++;
		GHL_TotalReceivedMins++;
		GHL_ReceivedD1Mins[iDayOfMonth]++;
		
		iM5Remainder =  iCurrMin % 5;
		iM15Remainder = iCurrMin % 15;
		iM30Remainder = iCurrMin % 30;
		iH4Remainder = iCurrHour % 4;
		
		iM5AllRemainder =  iCountAllMins % 5;
		iM5CyclicRemainder =  iCountMins % 5;
		
		//iM5Parts = iCurrMin / 5;
		//iM15Parts = iCurrMin / 15;
		//iM30Parts = iCurrMin / 30 ;
		//iH4Parts = iCurrHour / 4;

		iCurrM30Bar = iCurrMin / 30;
		iCurrM15Bar = iCurrMin / 15;
		iCurrM5Bar = iCurrMin / 5;
		//----------------------------------------
		datetime dtTestDate = D'2010.04.01 00:01';
		bool bTestTime = false;
		if( TimeCurrent() == dtTestDate )
		{
			bTestTime = true;
			Print("GHL_updateBarHighLow() :- test time :- ");
			
		}
		//----------------------------------------

		if( iPreviousDay != iDayOfyear )
		{
			bRestartD1Bar = true;
			calcBarsPerDay();
			
			GHL_CountedDays++;
			
			if( iPreviousDay > 0 ) {
				int iGoBack = 1;
				if(  iDayOfWeek == 0 ) 
					iGoBack = 2;
				GHL_MissingD1Mins[iDayOfMonth - iGoBack] = GHL_CalculatedD1Mins[iDayOfMonth - iGoBack] - GHL_ReceivedD1Mins[iDayOfMonth - iGoBack];
				GHL_MissingH4Bars[iDayOfMonth - iGoBack] = GHL_CalculatedH4Bars[iDayOfMonth - iGoBack] - GHL_ReceivedH4Bars[iDayOfMonth - iGoBack];
				GHL_MissingH1Bars[iDayOfMonth - iGoBack] = GHL_CalculatedH1Bars[iDayOfMonth - iGoBack] - GHL_ReceivedH1Bars[iDayOfMonth - iGoBack];
				GHL_MissingM30Bars[iDayOfMonth - iGoBack] = GHL_CalculatedM30Bars[iDayOfMonth - iGoBack] - GHL_ReceivedM30Bars[iDayOfMonth - iGoBack];
				GHL_MissingM15Bars[iDayOfMonth - iGoBack] = GHL_CalculatedM15Bars[iDayOfMonth - iGoBack] - GHL_ReceivedM15Bars[iDayOfMonth - iGoBack];
				GHL_MissingM5Bars[iDayOfMonth - iGoBack] = GHL_CalculatedM5Bars[iDayOfMonth - iGoBack] - GHL_ReceivedM5Bars[iDayOfMonth - iGoBack];
			}
		}
		if(	bTestTime ) {
			Print("bRestartD1Bar: ", bRestartD1Bar );
		}
		
		if( iPreviousHour != iCurrHour )
		{
			bRestartH1Bar = true;
			GHL_ReceivedH1Bars[iDayOfMonth]++;
			
			 iPreviousHour = iCurrHour;
		}
		
		if(	bTestTime ) {
			Print("bRestartH1Bar: ", bRestartH1Bar );
		}
		
		if( (iH4Remainder == 0) && bRestartH1Bar )
		{
			bRestartH4Bar = true;
			GHL_ReceivedH4Bars[iDayOfMonth]++;
			
		}
		if( iCurrM30Bar != iPrevM30Bar )
		{
			bRestartM30Bar = true;
			GHL_ReceivedM30Bars[iDayOfMonth]++;
			
			iPrevM30Bar = iCurrM30Bar;
		}
		if( iCurrM15Bar != iPrevM15Bar )
		{
			bRestartM15Bar = true;
			GHL_ReceivedM15Bars[iDayOfMonth]++;			
			
			iPrevM15Bar = iCurrM15Bar;
		}
		if(  iCurrM5Bar != iPrevM5Bar  ) {
			bRestartM5Bar = true;
			GHL_ReceivedM5Bars[iDayOfMonth]++;			
			
			iPrevM5Bar  = iCurrM5Bar;
			iCountMins = 0;
		}
		//-----------------------------------
		
	} else {
		GHL_dM1BarHighest = MathMax( dValue, GHL_dM1BarHighest );
		GHL_dM1BarLowest = MathMin( dValue, GHL_dM1BarLowest );
		return;
	}
	///================================

	if(bNewMinute)
	{
		 if( iCurrMin >0 && iCurrMin < 5 ) 
		 {
			//Check for missing M5 Bar 
			
		}
		 if( iCurrMin >= 6 && iCurrMin <= 9 ) 
		 {
			//Check for missing M15 Bar 
			
		}

	}
	//--------------------	
	if( GHL_TestBarHighLow) 
	{
		bool bReportMissingBars = false;
		if( bReportMissingBars )
		{
		}

		if( bNewMinute ) {
			if( (Month() == GHL_TestMonth)  &&  (Day() == GHL_Test3DayOfMonth) ) 
			{
				if( (Hour() == GHL_Test3Hour) &&  (Minute() == GHL_Test3Minute) )
				{
					Print("----------------------------------------");
					Print("StrategyTester 30 day backtest missing minutes:-");
					Print( "Separate occurances: " + GHL_CountInstancesLostMinutes );

					Print("----------------------------------------");
				}
			}
		}
	}
	
	//-----------------------------
	if( bRestartD1Bar && (iPreviousMonth != iCurrMonth) )
	{
		// A new month begins...
		bRestartMN1Bar =  true;
		
		GHL_dMN1BarHighest = dValue;
		GHL_dMN1BarLowest = dValue;
		iPreviousMonth = iCurrMonth;
		Print(" bRestartD1Bar && (iPreviousMonth != iCurrMonth): "+ TimeToStr(TimeCurrent()) );
		
	} else {
			GHL_dMN1BarHighest = MathMax( dValue, GHL_dMN1BarHighest);
			GHL_dMN1BarLowest = MathMin( dValue, GHL_dMN1BarLowest ); 
	}


	if( bRestartD1Bar && bRestartW1Bar )
	{
		// A new week begins...
		bRestartW1Bar =  false;
		//bRestartWeek = true;
		GHL_dW1BarHighest = dValue;
		GHL_dW1BarLowest = dValue;
		Print("bRestartD1Bar && bRestartW1Bar: "+ TimeToStr(TimeCurrent()) );
	} else {
			GHL_dW1BarHighest = MathMax( dValue, GHL_dW1BarHighest) ;
			GHL_dW1BarLowest = MathMin( dValue, GHL_dW1BarLowest ); 
	}

	if( bRestartD1Bar )
	{
		GHL_dD1BarHighest = dValue;
		GHL_dD1BarLowest = dValue;
		iPreviousDay = iDayOfyear;
		
		if( iDayOfWeek == 5 )
			bRestartW1Bar = true;
		
	} else {
			GHL_dD1BarHighest = MathMax( dValue, GHL_dD1BarHighest) ;
			GHL_dD1BarLowest = MathMin( dValue, GHL_dD1BarLowest ); 
	}
	
	//---------------------------------------------------------
	if( bRestartH4Bar == true) 
	{
			GHL_dH4BarHighest = dValue;
			GHL_dH4BarLowest = dValue;
	}
	else 
	{
			GHL_dH4BarHighest = MathMax( dValue, GHL_dH4BarHighest) ;
			GHL_dH4BarLowest = MathMin( dValue, GHL_dH4BarLowest ); 
	}
	//---------------------------------------------------------
	if( bRestartH1Bar == false ) 
	{
			GHL_dH1BarHighest = dValue;
			GHL_dH1BarLowest = dValue;
	}
	else 
	{
			GHL_dH1BarHighest = MathMax( dValue, GHL_dH1BarHighest) ;
			GHL_dH1BarLowest = MathMin( dValue, GHL_dH1BarLowest ); 
	}
	//---------------------------------------------------------
	if( bRestartM30Bar == true ) 
	{
			GHL_dM30BarHighest = dValue;
			GHL_dM30BarLowest = dValue;
	}
	else 
	{
			GHL_dM30BarHighest = MathMax( dValue, GHL_dM30BarHighest) ;
			GHL_dM30BarLowest = MathMin( dValue, GHL_dM30BarLowest ); 
	}
	//---------------------------------------------------------
	if( bRestartM15Bar == true) 
	{
			GHL_dM15BarHighest = dValue;
			GHL_dM15BarLowest = dValue;
	}
	else 
	{
			GHL_dM15BarHighest = MathMax( dValue, GHL_dM15BarHighest) ;
			GHL_dM15BarLowest = MathMin( dValue, GHL_dM15BarLowest ); 
	}
	//---------------------------------------------------------
	if( bRestartM5Bar == true) 
	{
			GHL_dM5BarHighest = dValue;
			GHL_dM5BarLowest = dValue;
	}
	else 
	{
			GHL_dM5BarHighest = MathMax( dValue, GHL_dM5BarHighest) ;
			GHL_dM5BarLowest = MathMin( dValue, GHL_dM5BarLowest ); 
	}
	
	//---------------------------------------------------------
	bRestartMN1Bar = false;
	bRestartD1Bar = false;
	bRestartH4Bar = false;
	bRestartH1Bar = false;
	bRestartM30Bar = false;
	bRestartM15Bar = false;
	bRestartM5Bar = false;
	//---------------------------------------------------------
	if( iPreviousHour != iCurrHour )
		iPreviousHour = iCurrHour; 

	if( iPrevDayOfWeek != iDayOfWeek )
		iPrevDayOfWeek = iDayOfWeek;

	if( iCurrMin != iPreviousMinute )
	{
		iPreviPrevMin = iPreviousMinute;
		iPreviousMinute = iCurrMin;
		bNewMinute = false;
	}
}

///==============================================

///==============================================
/* -----------------------------------------------------------
	getBarHigh()
---------------------------------------------------------- */
double getBarHigh( string symbol, int timeframe, int shift)
{
	double dResult = -1.0;
	
	if( shift != 0 )
		dResult = iHigh( symbol, timeframe, shift);
	else if( (IsTesting() == false) && (IsVisualMode() == false) )
		 dResult = iHigh( symbol, timeframe, shift);
	else	 
		dResult = locateHigh( timeframe);
	
	if( dResult < 0 ) {
		string strReason = "ERROR: getBarHigh() Failed!";
		forceHighLowExit(strReason);
	}
	
	return( dResult );
}

/* -----------------------------------------------------------
	getBarLow()
---------------------------------------------------------- */
double getBarLow( string symbol, int timeframe, int shift)
{
	double dResult = -1.0;
	
	if( shift != 0 ) 
		dResult = iLow( symbol, timeframe, shift);
	else if( (IsTesting() == false) && (IsVisualMode() == false) )
		dResult = iLow( symbol, timeframe, shift);
	else	 
		dResult = locateLow(timeframe);

	if( dResult < 0 ) {
		string strReason = "ERROR: getBarLow() Failed!";
		string strDetails = "\nsymbol: " + symbol + ",  timeframe: " + timeframe +  " ,  shift: " + shift;
		forceHighLowExit(strReason+strDetails);
	}

	return( dResult );
}

/* -----------------------------------------------------------
	locateHigh()
---------------------------------------------------------- */
double locateHigh(int timeframe)
{
	switch(timeframe) {
	case PERIOD_MN1: return( GHL_dMN1BarHighest );
	case PERIOD_W1: return( GHL_dW1BarHighest );
	case PERIOD_D1: return( GHL_dD1BarHighest );
	case PERIOD_H4: return( GHL_dH4BarHighest );
	case PERIOD_H1: return( GHL_dH1BarHighest );
	case PERIOD_M30: return( GHL_dM30BarHighest );
	case PERIOD_M15: return( GHL_dM15BarHighest );
	case PERIOD_M5: return( GHL_dM5BarHighest );
	case PERIOD_M1: return( GHL_dM1BarHighest );
	default:
		string strReason = "ERROR locateHigh() : invalid timeframe ";
		forceHighLowExit(strReason);
	}
}

/* -----------------------------------------------------------
	locateLow()
---------------------------------------------------------- */
double locateLow(int timeframe)
{
	switch(timeframe) {
	case PERIOD_MN1: return( GHL_dMN1BarLowest );
	case PERIOD_W1: return( GHL_dW1BarLowest );
	case PERIOD_D1: return( GHL_dD1BarLowest );
	case PERIOD_H4: return( GHL_dH4BarLowest );
	case PERIOD_H1: return( GHL_dH1BarLowest );
	case PERIOD_M30: return( GHL_dM30BarLowest );
	case PERIOD_M15: return( GHL_dM15BarLowest );
	case PERIOD_M5: return( GHL_dM5BarLowest );
	case PERIOD_M1: return( GHL_dM1BarLowest );
	default:
		string strReason = "ERROR locateLow() : invalid timeframe ";
		forceHighLowExit(strReason);
	}
}

/* -----------------------------------------------------------
	CollectReferenceLow()
---------------------------------------------------------- */
void CollectReferenceBars()
{
	static string strPair = "AUDUSD";
	static int iYear = 2010;
	static int iMonth = 4; //April because last day of month is also last day of week
	static int iDayOfMonth = 30; // Friday = End of week && End of Month
	static int iHour = 20; // last hour of Friday
	static int iMinute = 59; // Last Minute of last Hour;
	
		if( (Month() == iMonth)  &&  (Day() == iDayOfMonth) ) 
			if( (Hour() == iHour) &&  (Minute() == iMinute) )
			{
				ReportLowValues();
				ReportHighValues();
			}

}

/* -----------------------------------------------------------
	ReportLowValues()
---------------------------------------------------------- */
void ReportLowValues()
{
		string strTitle =  "\n"+"Compare Low values against actual data:-";
		string strTime = "\n"+ TimeToStr( TimeCurrent(), TIME_DATE|TIME_MINUTES|TIME_SECONDS ) + "\n";
		
		string strReport1 = "_M1 " + DoubleToStr( getBarLow( Symbol(), PERIOD_M1, 0),5 )
		+  ", iLow " +  DoubleToStr(  iLow( Symbol(), PERIOD_M1, 0), 5 ) + "\n";
		
		string strReport2 = "_M5 " + DoubleToStr( getBarLow( Symbol(), PERIOD_M5, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_M5, 0), 5 ) + "\n";
		
		string strReport3 = "M15 " + DoubleToStr( getBarLow( Symbol(), PERIOD_M15, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_M15, 0), 5 ) + "\n";
		
		string strReport4 = "M30 " + DoubleToStr( getBarLow( Symbol(), PERIOD_M30, 0),5 ) 
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_M30, 0), 5 ) + "\n";
		
		string strReport5 = "_H1 " + DoubleToStr( getBarLow( Symbol(), PERIOD_H1, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_H1, 0), 5 ) + "\n";
		
		string strReport6 = "_H4 " + DoubleToStr( getBarLow( Symbol(), PERIOD_H4, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_H4, 0), 5 ) + "\n";
		
		string strReport7 = "_D1 " + DoubleToStr( getBarLow( Symbol(), PERIOD_D1, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_D1, 0), 5 ) + "\n";
		
		string strReport8 = "_W1 " + DoubleToStr( getBarLow( Symbol(), PERIOD_W1, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_W1, 0), 5 ) + "\n";
		
		string strReport9 = "MN1 " + DoubleToStr( getBarLow( Symbol(), PERIOD_MN1, 0),5 )
		+  ", iLow " +  DoubleToStr(   iLow( Symbol(), PERIOD_MN1, 0), 5 ) + "\n";
		
		string strReport =  strTitle +  strTime + strReport1 + strReport2  + strReport3  + strReport4  
			+ strReport5  + strReport6  + strReport7  + strReport8  + strReport9;
		Print(strReport);

}

/* -----------------------------------------------------------
	ReportHighValues()
---------------------------------------------------------- */
void ReportHighValues()
{
	string strTitle =  "\n"+"Compare High values against actual data:-";
			
		string strTime = "\n"+TimeToStr( TimeCurrent(), TIME_DATE|TIME_MINUTES|TIME_SECONDS ) + "\n";
		
		string strReport1 = "_M1 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_M1, 0),5 )
		+  ", iHigh " +  DoubleToStr(  iHigh( Symbol(), PERIOD_M1, 0), 5 ) + "\n";
		
		string strReport2 = "_M5 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_M5, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_M5, 0), 5 ) + "\n";
		
		string strReport3 = "M15 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_M15, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_M15, 0), 5 ) + "\n";
		
		string strReport4 = "M30 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_M30, 0),5 ) 
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_M30, 0), 5 ) + "\n";
		
		string strReport5 = "_H1 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_H1, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_H1, 0), 5 ) + "\n";
		
		string strReport6 = "_H4 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_H4, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_H4, 0), 5 ) + "\n";
		
		string strReport7 = "_D1 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_D1, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_D1, 0), 5 ) + "\n";
		
		string strReport8 = "_W1 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_W1, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_W1, 0), 5 ) + "\n";
		
		string strReport9 = "MN1 " + DoubleToStr( getBarHigh( Symbol(), PERIOD_MN1, 0),5 )
		+  ", iHigh " +  DoubleToStr(   iHigh( Symbol(), PERIOD_MN1, 0), 5 ) + "\n";
		
		string strReport = strTitle +  strTime + strReport1 + strReport2  + strReport3  + strReport4  
			+ strReport5  + strReport6  + strReport7  + strReport8  + strReport9;
			
		Print(strReport);
}

/* -----------------------------------------------------------
	ReportHighLowValues()
---------------------------------------------------------- */
void ReportHighLowValues()
{

	ReportLowValues();
	ReportHighValues();
	Print("--------------------------------------------------\n");
}



/* -----------------------------------------------------------
	start()
---------------------------------------------------------- */
int start()
{
	static int iTestMonth = 4; //April
	//-----------------------
	static int iTest1DayOfMonth = 1; // Thursday
	static int iTest1Hour = 0; // 00:01
	static int iTest1Minute = 1; // 00:01
	
	// Check progress of incomplete bars
	static int iTest2DayOfMonth = 14; // Wednesday
	static int iTest2Hour = 14; // 14:00
	static int iTest2Minute = 47; // 00:47 -> 14:47
	static int iLastMinute = -1;
	
	bool bNewM1Bar =  false;
	
	if( iLastMinute != Minute() )
	{
		bNewM1Bar =  true;
		iLastMinute = Minute();
	}
	
	//-----------------------
	GHL_updateBarHighLow();
	//-----------------------
	
	bool bNeedRefBars = true;
	if( bNeedRefBars && bNewM1Bar )
		CollectReferenceBars();
		
	if( bNewM1Bar &&  GHL_TestBarHighLow ) {
		// Check three times during 1 month
		bool bMoreSample =  false;
		
		if( (Month() == iTestMonth)  &&  (Day() == iTest1DayOfMonth) ) 
			if( (Hour() == iTest1Hour) &&  (Minute() == iTest1Minute) )
			{
				ReportHighLowValues();
			}
		if(bMoreSample)
		{
			if( (Month() == iTestMonth)  &&  (Day() == 12) ) 
				if(  (Hour() == 0) &&  (Minute() == 1) )
				{
					ReportHighLowValues();
				}
		}
		if( (Month() == iTestMonth)  &&  (Day() == iTest2DayOfMonth) ) 
			if(  (Hour() == iTest2Hour) &&  (Minute() == iTest2Minute) )
			{
				ReportHighLowValues();
			}
		
		if(bMoreSample)
		{
			if( (Month() == iTestMonth)  &&  (Day() == 15) ) 
				if(  (Hour() == 0) &&  (Minute() == 1) )
				{
					ReportHighLowValues();
				}
		}
		if( (Month() == GHL_TestMonth)  &&  (Day() == GHL_Test3DayOfMonth) ) 
			if( (Hour() == GHL_Test3Hour) &&  (Minute() == GHL_Test3Minute) )
			{
				ReportHighLowValues();
				PrintFinalSummary();
			}
		
	}
}

/* -----------------------------------------------------------
	getDayOfWeek()
---------------------------------------------------------- */
int	getDayOfWeek(int year, int month, int day ) 
{
	bool bDebugTrace = false;
	
  static string weekdayname[] = {"Monday", "Tuesday",
        "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
		
	int FXDow = 0;
		
  int iJndFull =                                                     
          day                                                      
        + ((153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5) 
        + (365 * (year + 4800 - ((14 - month) / 12)))              
        + ((year + 4800 - ((14 - month) / 12)) / 4)                
        - ((year + 4800 - ((14 - month) / 12)) / 100)              
        + ((year + 4800 - ((14 - month) / 12)) / 400)              
        - 32045;
		
	int iJnd = iJndFull % 7;
	FXDow = iJnd + 1;
	
	if( FXDow > 6 ) FXDow = 0;
		
	if( bDebugTrace )
		Print("iJnd: "+ iJnd + ", FXDow: "+ FXDow );
		
	return( FXDow );
}

/* -----------------------------------------------------------
	PrintBarHistory()
---------------------------------------------------------- */
void PrintBarHistory( int& expected[], int& recieved[], int& missing[] ) 
{
	int dow = 0;
	string strDOM, strExpBars, strReceivedBars, strMissingBars;
	strDOM            = "Day:       ";
	strExpBars        = "Expected:  ";
	strReceivedBars = "Received:  ";
	strMissingBars    = "Missing:    ";
	
	for( int dom = 1; dom < MAXDAYSPERMONTH; dom++ )
	{
		if( expected[dom] == 0 ) {
		} else {
			dow = getDayOfWeek(Year(), Month(), dom) ;
			strDOM = strDOM + "  " + dom + "("+dow+")";
			strExpBars = strExpBars + "  "+ expected[dom];
			strReceivedBars = strReceivedBars + "  "+ recieved[dom];
			strMissingBars = strMissingBars + "   "+ missing[dom];
			if( dow == 5 )  {
				Print(strDOM);
				Print(strExpBars);
				Print(strReceivedBars);
				Print(strMissingBars);
				Print("");
				strDOM            = "Day:       ";
				strExpBars        = "Expected:  ";
				strReceivedBars = "Received:  ";
				strMissingBars    = "Missing:    ";
			}
		}
	}

}


/* -----------------------------------------------------------
	PrintFinalSummary()
---------------------------------------------------------- */
void PrintFinalSummary()
{
	string strExpBars = "", strReceivedBars = "", strMissingBars = "";
	int iTotalLostMinutes = GHL_TotalExpectedMins - GHL_TotalReceivedMins;
	int dom = 0;
	int dow = 0;
	
	Print("----------------------------------------------------------------");
	Print("Final Summary");
	Print("GHL_CountedDays:        " + GHL_CountedDays);
	Print("GHL_TotalExpectedMins: " + GHL_TotalExpectedMins );
	Print("GHL_TotalReceivedMins: " + GHL_TotalReceivedMins );
	Print("TotalLostMinutes:          " + iTotalLostMinutes );
	Print("----------------------------------------------------------------");
	
	Print("M1 bars");
	PrintBarHistory( GHL_CalculatedD1Mins, GHL_ReceivedD1Mins, GHL_MissingD1Mins);
	
	Print("----------------------------------------------------------------");
	Print("M5 bars");
	PrintBarHistory( GHL_CalculatedM5Bars, GHL_ReceivedM5Bars, GHL_MissingM5Bars);
	Print("----------------------------------------------------------------");
	Print("M15 bars");
	PrintBarHistory( GHL_CalculatedM15Bars, GHL_ReceivedM15Bars, GHL_MissingM15Bars);
	Print("----------------------------------------------------------------");
	Print("M30 bars");
	PrintBarHistory( GHL_CalculatedM30Bars, GHL_ReceivedM30Bars, GHL_MissingM30Bars);
	Print("----------------------------------------------------------------");
	Print("H1 bars");
	PrintBarHistory( GHL_CalculatedH1Bars, GHL_ReceivedH1Bars, GHL_MissingH1Bars);
	Print("----------------------------------------------------------------");
	Print("H4 bars");
	PrintBarHistory( GHL_CalculatedH4Bars, GHL_ReceivedH4Bars, GHL_MissingH4Bars);
	Print("----------------------------------------------------------------");
	Print("----------------------------------------------------------------");
	
	ReportTimesOfLostMinutes();
}

/* -----------------------------------------------------------
	testDateToDom()
---------------------------------------------------------- */
void testDateToDom()
{
	int year = 2010;
	int month = 4;
	int day = 14; // Wednesday ( 3 )
	int dow = 0;
	
	dow = getDayOfWeek(year, month, day);
	
	Print("Test getDayOfWeek():-");
	Print(" year: " + year + ",  month: " + month + ", day: " + day + ", DOW: " + dow);


}

/* -----------------------------------------------------------
	test_start()
---------------------------------------------------------- */
int test_start()
{
	bool bNewM1Bar =  false;

	// Check progress of incomplete bars
	static int iTestMonth = 4;
	static int iTest2DayOfMonth = 14; // Wednesday
	static int iTest2Hour = 14; // 14:00
	static int iTest2Minute = 47; // 00:47 -> 14:47
	static int iLastMinute = -1;

	if( iLastMinute != Minute() )
	{
		bNewM1Bar =  true;
		iLastMinute = Minute();
	}
	

	if( bNewM1Bar &&  GHL_TestBarHighLow ) 
	{
		if( (Month() == iTestMonth)  &&  (Day() == iTest2DayOfMonth) ) 
		{
			if(  (Hour() == iTest2Hour) &&  (Minute() == iTest2Minute) )
			{
				testDateToDom();
			}
		}
	}

}

Author:  snailbeard [ Tue Dec 17, 2013 9:57 am ]
Post subject:  The last straw

The Last straw...

I just tried to integrate the getHighLow code into the autotrader, but it seems to be the straw that broke the camel's back...

Code: Select all

MetaTrader4\experts\Snailbeard.mq4;3926:41;'arrTicketNum' - too many arrays
The script has grown and grown, inflating like a balloon,
and now it has popped. :uff:
Author:  snailbeard [ Wed Dec 18, 2013 6:52 am ]
Post subject:  Building a DLL

Building a DLL

If you are not a regular programmer then you might have some difficulties doing this.

MQ have provided a sample DLL which reduces the pain somewhat, however if you get it to work first time I would be surprised.

Step1. You need a friendly C++ development environment...

Most people would go for MS Visual Studio C++ express or similar
I use CodeBlocks which I run under WINE ( a Windows emmulator for Linux )

Step2.
Assuming you are using VS: import the example project

Step3.
Build the project

Step4.

Common Empty4 error message: cannot load dll (error 126)

Include the sample include file and put the Dll where your script can find it.
i.e. in the library folder

Now the pitfalls:

cannot call function from dll (error 127) - lots of posts about it in the forums

This is probably a name mangling issue
e.g. __Z11GetIntValuei@4 instead of GetIntValue

.....experts/libraries$

using some Linux utilities to see whats in the the DLL:

nm GetHighLowBar.dll | grep -i GetIntValue

70a01400 T __Z11GetIntValuei@4

Solution:

Add 'extern "C"' { } to the exported functions...

extern "C"
{
Empty4_EXPFUNC int __stdcall GetIntValue(const int ipar)
} ;

Rebuild the DLL:

......../experts/libraries$

nm GetHighLowBar.dll | grep -i GetIntValue

70a01400 T _GetIntValue@4

Pitfall 2:

Empty4 did not automatically reload the DLL after rebuilding

To be absolutely sure that Empty4 picked up the latest version I restarted Empty4
Author:  snailbeard [ Thu Dec 19, 2013 10:21 am ]
Post subject:  Building a DLL

Building a DLL

Finally, if you are still having problems with:

cannot call function from dll (error 127)

then check the compiler settings:

a) 32 bit versus 64 bit
b) CodeBlocks with MingW needs: -Wl,--kill-at
(this setting gets rid of the @ suffix at the end of the function names)
More info here:
http://stackoverflow.com/questions/8063 ... all-suffix

After all this I can finally call my own functions from a custom DLL :yahoo:

If only I had started this way in the first place :cry:

So whats next:- I have been banging away at this EA for some time and perhaps its time to reflect on what has been achieved so far.
Author:  snailbeard [ Thu Dec 19, 2013 11:54 am ]
Post subject:  End of year summary

End of year summary

Firstly, whether the EA is usable or not, investigating results forced me to study hundreds of charts. It is interesting that I thought I had a good grasp of technical analysis before I started, but I reached a new level by carrying out this work.
I discovered that my entry method is reliable but suboptimal. Next year I'll be looking at combination of events based around a break-in to the H1 Bollinger Band because I am fairly confident that this will result in more frequent trades and fewer stop-outs.

Secondly, basket trading is for basket cases, or at least is beyond my capabilities to handle the complexities of it.
It is useful to see if one currency consistently produces better/worse results but otherwise for me it clouds the results.
Since each pair has its own moods and an EA has to adapt to those moods it becomes difficult to handle this in a single EA. It is better either to focus on one pair or have multiple accounts and trade one pair per account.
This will mean the data accumulated from back-testing, forward-testing and live-trades is more useful, in the sense of comparing like-for-like, which cannot be done when multi-pair interdependencies occur.

Thirdly, I would like to thank Jeremy for his hard work helping to set up GlobalPrime and providing confidence that the EA forward-testing has some value! And also for suggesting that back-testing for more than 12 months is important.
And and even bigger thankyou to Steve for providing us with this forum: a place to learn and grow.

After the EA was consistently doing better and better on 2012/2013 data, I had a big shock at the bad results when I tried it on 2010 data. This resulted in more technical analysis, more understanding and a new set of entry filters which I was dreading to apply to more recent data. More filters generally means less trades including good ones.

It was this last phase of work which broke the limits of what can be programmed into an Empty4 script. An approach that I was dying to escape from anyway. So finally Empty4 forced me down a better road. The road to platform independent code!

So here is a summary of the 3 most recent versions with 3 popular pairs:
Author:  snailbeard [ Thu Dec 19, 2013 12:28 pm ]
Post subject:  AUDUSD 2010 Shocker

AUDUSD 2010 Shocking results:
AUDUSD-M1-2010-1Y-backtest-results-run-on-2013-12-02.png
Applying the first set of filters:
AUDUSD-M1-2010-1Y-improved-results-2013-12-07.png
Applying the second set of filters
AUDUSD-M1-2010-1Y-backtest-results-run-on-2013-12-10.png.png
Applying the third set of filters
AUDUSD-M1-2010-1Y-backtest-results-run-on-2013-12-12.png
Experienced traders will say "You're curve fitting to 2010 data :roll: " and I agree that seemed a likely explanation.

So what happens when we go 'back to the future' to the 2012/2013 data:
AUDUSD-M1-1Y-May2012-May2013-backtest-run-on-12Dec13.png
In conclusion

My fears of curve fitting have been allayed and my confidence that this is data modelling restored.
I could fill a book with everything I have learnt in 2013 but I doubt there would be enough time to write it and put it into practice.
Author:  currymonster [ Thu Dec 19, 2013 8:47 pm ]
Post subject:  Re: Zigzag Bollinger Band

Interesting stuff snaily, much appreciated - all your hard work,

Cal
Author:  snailbeard [ Fri Dec 20, 2013 7:38 am ]
Post subject:  visual test mode

Visual Test Mode

I hardly used the visual test mode in the past - relying on the log file instead. However, updating the screen reduces the time spent searching through copious log lines. The latest internal states of the autotrader are represented by a shorthand for geometric relationships between time and price.
Author:  snailbeard [ Mon Jan 06, 2014 2:31 pm ]
Post subject:  Re: Zigzag Bollinger Band

Greetings Traders,
May the Pips be forever in your favour.

First of all, hats off to Mrs Snailbeard who proved me wrong about the latest version of the Auto trader. I kept on insisting the the latest version was the best and she kept insisting I give her back the previous version (02Dec2013).

My end of year summary did not include GBPUSD which proved Mrs Snailbeard correct about the earlier version.
First the latest and greatest version (not):
StrategyTester.gif
and now the earlier version:
StrategyTester.gif
We cannot really say that the earlier version is better. It is more a matter of working out which entry filters should be on or off for a particular pair based on volatility and price stability. There is currently no way to manually control these or run the settings through the optimiser.

I have been too tied up rewriting the DLL for fixing the back-testing weaknesses to cope with the limitations of CrappyTester and I have only just completed rigourous testing of this.
This new DLL nolonger relies on bars from Empty4 instead it synchronises to the time and checks if the starts of new bars are late and compensates for those missing/late bars.
There is a lot of cross checking. There are arrays holding the expected number of bars and other arrays holding a count of each new bar. There is another function to print a report summary at the end of a run.
I also had to write a small test program to stuff the DLL with ticks and prices. Which meant I had to come up with a random price mover (which is not intended to produce real price patterns), FxDice() is called for several timeframes so that the price drifts with bias that creates shorter trends within longer term trends.

Anyway, now that is complete I could move on to creating a DLL which enables user control of pairs and entry filters. The other area I am keen to develop is the sub-trades (counter trades) as there are often daily opportunities missed by AT.
Author:  snailbeard [ Mon Jan 06, 2014 3:14 pm ]
Post subject:  Re: Zigzag Bollinger Band

The random price movement is called from the test program:

Code: Select all

		
        //----------------------------------------------
        GHL_UpdateHighLowValue( dPriceValue, timeInSecs);

        dPriceValue = FxDice(dPriceValue, 0);
        //------------------------------------

After some experimentation, I found that the following code produces a reasonable variation in price:

Code: Select all

/* -----------------------------------------------------------
	FxDice()
---------------------------------------------------------- */
	Empty4_EXPFUNC double __stdcall FxDice(double dOldPrice, const int bStartAgain)
	{
		static int iM1Increment = 1; //0.00001;
		static int iM15Increment = 1; //0.00001;
		static int iH1Increment = 1; //0.00002;
		static int iH4Increment = 1; //0.00004;
		static int iD1Increment = 1; //0.00008;

		static int iM1CurrDir = 0;
		static int iM15CurrDir = 0;
		static int iH1CurrDir = 0;
		static int iH4CurrDir = 0;
		static int iD1CurrDir = 0;

		static int iM1CurrInc = 0;
		static int iM15CurrInc = 0;
		static int iH1CurrInc = 0;
		static int iH4CurrInc = 0;
		static int iD1CurrInc = 0;

		bool bDebugTrace = false;

		if( getM1BarChanged() ) { iM1CurrDir = dice(); iM1CurrInc = iM1CurrDir * iM1Increment; }
		if( getM15BarChanged() ) { iM15CurrDir = dice(); iM15CurrInc = iM15CurrDir * iM15Increment; }
		if( getH1BarChanged() ) { iH1CurrDir = dice(); iH1CurrInc = iH1CurrDir * iH1Increment; }
		if( getH4BarChanged() ) { iH4CurrDir = dice(); iH4CurrInc = iH4CurrDir * iH4Increment; }
		if( getD1BarChanged() ) { iD1CurrDir = dice(); iD1CurrInc = iD1CurrDir * iD1Increment; }

		int 	iNewOffset = 0;
		double dNewOffset = 0;
		double dNewPrice = 0;

		dNewOffset = (1.0*iM1CurrInc) + (1.0*iM15CurrInc) + (1.0*iH1CurrInc) + ((1.0*iH4CurrInc)/10.0) + ((1.0*iD1CurrInc)/10.0);
		dNewOffset = (dNewOffset) / 10000.0;
		dNewPrice = dOldPrice + dNewOffset;

		if( bDebugTrace )
			cout << "FxDice() dNewPrice: " <<  dNewPrice << endl;

		return( dNewPrice );
	}
}
All times are UTC Page 4 of 28