//+---------------------------------------------------------------------+
//|                                             TickLoggerForFXT_V4.mq4 |
//|                                                  Paul Hampton-Smith |
//| Version 2 with seconds recorded, additional comments on the chart   |
//| and recording in GMT														      |
//| Version 3 with header added, and ask recorded as well as bid        |
//| Version 4 with version, username & password added to header         |
//+---------------------------------------------------------------------+
/*


To use this logger
~~~~~~~~~~~~~~~~~~
:: Enable dll calls in MT4 using Tools->Options->Expert Advisers>Allow DLL imports
:: Drop the logger onto the chart of the currency pair that you want to log. Timeframe does not matter
:: Username and password are for identification and verification of loggers when logfiles are uploaded
:: All tick logs will be stored in experts\files\tick_logs\
:: A new file is created every day at 00:00 GMT

File name
~~~~~~~~~
Filename = tick_logs\AAABBB_yyyymmdd_ticks.csv
Subfolder_name is defined by global variable strFolder
AAABBB = Symbol() of the chart on which the logger is running.

Header format
~~~~~~~~~~~~~
Logger version
Username
Password
Company
Server name
STANDARD|DEMO
Currency pair

Data format
~~~~~~~~~~~
yyyy.mm.dd hh:mm:ss,Bid,Ask    (note comma delimited)


*////////////////////////////////////////////////////////


#include <stdlib.mqh>

extern string username = " ";
extern string password = " ";

int LogHandle;
string strFilename;
int nTickCount;
string strEAname = "TickLoggerForFXT_V4";
string strFolder = "tick_logs/"; // subfolder from experts\files

int init()
{
   Comment("\nWaiting for first tick");
}

int deinit()
{
   FileClose(LogHandle);
}

int start()
{
   Comment("\nLogging tick #",nTickCount," to ",strFilename,"\n",TimeToStr(TimeGMT(),TIME_DATE|TIME_MINUTES|TIME_SECONDS),"  GMT");

	WriteTickData();
	
   return(0);
}

bool WriteHeader()
{
/*
	Logger version
	Username
	Password
	Company
	Server name
	STANDARD|DEMO
	Currency pair
*/
	
	int nLastError = 0;

	// Version
	FileWrite(LogHandle,strEAname); nLastError = GetLastError();
	if (nLastError != 0) { Print("WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }

	// username
	FileWrite(LogHandle,username); nLastError = GetLastError();
	if (nLastError != 0) { Print("WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }
	
	// password
	FileWrite(LogHandle,password); nLastError = GetLastError();
	if (nLastError != 0) { Print("WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }

	// Company
	FileWrite(LogHandle,AccountCompany()); nLastError = GetLastError();
	if (nLastError != 0) { Print("WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }

	// Server name
	FileWrite(LogHandle,AccountServer()); nLastError = GetLastError();
	if (nLastError != 0) { Alert(strEAname," WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }

	// STANDARD|DEMO
	if (MarketInfo(Symbol(),MODE_TICKVALUE) > 1.1)
	{
		FileWrite(LogHandle,"STANDARD");
	}
	else
	{	
		FileWrite(LogHandle,"MINI");
	}
	if (nLastError != 0) { Alert("WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }

	// Currency pair
	FileWrite(LogHandle,Symbol()); nLastError = GetLastError();
	if (nLastError != 0) { Alert(strEAname," WriteHeader() encountered error ",ErrorDescription(nLastError)); return(false); }

	// OK
	return(true);	
}

bool WriteTickData()
{
	static int nDaysSince1970 = 0;
	datetime dtGMT = TimeGMT();
	int nLastError = 0;

	// create a new file on startup or new day
	if (TimeGMT()/(60*60*24) > nDaysSince1970 || LogHandle <= 0 )
	{
		if (LogHandle > 0) FileClose(LogHandle);
		strFilename = strFolder+Symbol()+"_"+TimeYear(dtGMT)+LeadingZero(TimeMonth(dtGMT))+LeadingZero(TimeDay(dtGMT))+"_ticks.csv";

		LogHandle = FileOpen(strFilename,FILE_CSV|FILE_READ|FILE_WRITE,',');
 	  	if (LogHandle <= 0) { Alert(strEAname," could not open file ",strFilename); return(false);	}
   
   	if (FileSize(LogHandle) > 0)
   	{
 	  		FileSeek(LogHandle,0,SEEK_END);
   	}
   	else
   	{
   		if (!WriteHeader()) return(false);
   	}
		nDaysSince1970 = dtGMT/(60*60*24);
	}

	// should be ready to write data
	nTickCount++;
	FileWrite(LogHandle,TimeToStr(dtGMT,TIME_DATE|TIME_MINUTES|TIME_SECONDS),Bid,Ask); nLastError = GetLastError();
	if (nLastError != 0) { Alert(strEAname," encountered error ",ErrorDescription(nLastError)); return(false); }

	return(true);
}

string LeadingZero(int n)
{
	if (n <= 9) 
		return("0"+n);
	else
		return(n);
}
	
	
	
//=================================================================
// Copied from TimeGMT.mqh
//=================================================================

#import "kernel32.dll"
int  GetTimeZoneInformation(int& TZInfoArray[]);
#import

#define TIME_ZONE_ID_UNKNOWN   0
#define TIME_ZONE_ID_STANDARD  1
#define TIME_ZONE_ID_DAYLIGHT  2

// Local timezone in hours, adjusting for daylight saving
double TimeZoneLocal()
{
	int TZInfoArray[43];

	switch(GetTimeZoneInformation(TZInfoArray))
	{
	case TIME_ZONE_ID_UNKNOWN: 
		Print("Error obtaining PC timezone from GetTimeZoneInformation in kernel32.dll. Returning 0");
		return(0);

	case TIME_ZONE_ID_STANDARD:
		return(TZInfoArray[0]/(-60.0));
	
	case TIME_ZONE_ID_DAYLIGHT:
		return((TZInfoArray[0]+TZInfoArray[42])/(-60.0));
		
	default:
		Print("Unkown return value from GetTimeZoneInformation in kernel32.dll. Returning 0");
		return(0);
	}
}

// Server timezone in hours
double TimeZoneServer()
{
	int ServerToLocalDiffMinutes = (TimeCurrent()-TimeLocal())/60;
	
	// round to nearest 30 minutes to allow for inaccurate PC clock
	int nHalfHourDiff = MathRound(ServerToLocalDiffMinutes/30.0);
	ServerToLocalDiffMinutes = nHalfHourDiff*30;
	return(TimeZoneLocal() + ServerToLocalDiffMinutes/60.0);
}

// Uses local PC time, local PC timezone, and server time to calculate GMT time at arrival of last tick
datetime TimeGMT()
{
	return(TimeCurrent() - TimeZoneServer()*3600);
}


