//+------------------------------------------------------------------+ //| Period_Converter_Opt.mq4| //| Copyright ?2005, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //| Modified by wfy05@talkforex based on Period_Converter| //| http://www.talkforex.com | //+------------------------------------------------------------------+ #property copyright "wfy05@talkforex.com" #property link "http://www.mql4.com/codebase/indicators/277/" #property indicator_chart_window #property show_inputs //USDX=50.14348112 x EUR/USD-0.576 x USD/JPY0.136 x GBP/USD-0.119 x USD/ CAD0.091 x USD/SEK0.042 x USD/CHF0.036 #include extern int timeframe=15; extern bool Enabled = true; extern int UpdateInterval = 15000; // update interval in milliseconds, zero means update real-time. double Version = 1.4; // code version string BuildInfo = "2005.12.24 by wfy05@talkforex.com"; int PeriodMultiplier = 1; // new period multiplier factor int OutputCSVFile = 0; // also output CSV file? bool Debug = false; bool My_Alert = false; int digits=4; int FileHandle = -1; int CSVHandle = -1; int NewPeriod = 0; string New_Symbol = "USDx"; #define OUTPUT_HST_ONLY 0 #define OUTPUT_CSV_HST 1 #define OUTPUT_CSV_ONLY 2 #define CHART_CMD_UPDATE_DATA 33324 //+------------------------------------------------------------------+ //| TOLHCV | //+------------------------------------------------------------------+ double TOLHCV(int Shift, int Selection_Item) { double Open_Temp, Low_Temp, High_Temp, Close_Temp, Volume_Temp; Open_Temp = 50.14348112* MathPow(iOpen("EURUSD", timeframe, Shift), -0.576)* MathPow(iOpen("USDJPY", timeframe, Shift), 0.136)* MathPow(iOpen("GBPUSD", timeframe, Shift), -0.119)* MathPow(iOpen("USDCAD", timeframe, Shift), 0.091)* MathPow(iOpen("USDSEK", timeframe, Shift), 0.042)* MathPow(iOpen("USDCHF", timeframe, Shift), 0.036); Low_Temp = 50.14348112* MathPow(iLow("EURUSD", timeframe, Shift), -0.576)* MathPow(iLow("USDJPY", timeframe, Shift), 0.136)* MathPow(iLow("GBPUSD", timeframe, Shift), -0.119)* MathPow(iLow("USDCAD", timeframe, Shift), 0.091)* MathPow(iLow("USDSEK", timeframe, Shift), 0.042)* MathPow(iLow("USDCHF", timeframe, Shift), 0.036); High_Temp = 50.14348112* MathPow(iHigh("EURUSD", timeframe, Shift), -0.576)* MathPow(iHigh("USDJPY", timeframe, Shift), 0.136)* MathPow(iHigh("GBPUSD", timeframe, Shift), -0.119)* MathPow(iHigh("USDCAD", timeframe, Shift), 0.091)* MathPow(iHigh("USDSEK", timeframe, Shift), 0.042)* MathPow(iHigh("USDCHF", timeframe, Shift), 0.036); Close_Temp = 50.14348112* MathPow(iClose("EURUSD", timeframe, Shift), -0.576)* MathPow(iClose("USDJPY", timeframe, Shift), 0.136)* MathPow(iClose("GBPUSD", timeframe, Shift), -0.119)* MathPow(iClose("USDCAD", timeframe, Shift), 0.091)* MathPow(iClose("USDSEK", timeframe, Shift), 0.042)* MathPow(iClose("USDCHF", timeframe, Shift), 0.036); Volume_Temp = 50.14348112* MathPow(iVolume("EURUSD", timeframe, Shift), -0.576)* MathPow(iVolume("USDJPY", timeframe, Shift), 0.136)* MathPow(iVolume("GBPUSD", timeframe, Shift), -0.119)* MathPow(iVolume("USDCAD", timeframe, Shift), 0.091)* MathPow(iVolume("USDSEK", timeframe, Shift), 0.042)* MathPow(iVolume("USDCHF", timeframe, Shift), 0.036); double Max_Open_Close, Min_Open_Close; /* if (Open_Temp >= Close_Temp) {Max_Open_Close = Open_Temp; Min_Open_Close = Close_Temp;} if (Open_Temp < Close_Temp) {Max_Open_Close = Close_Temp; Min_Open_Close = Open_Temp;} if (Low_Temp >= High_Temp) High_Temp = Low_Temp; Low_Temp = High_Temp; if (High_Temp <= Max_Open_Close) High_Temp = Max_Open_Close; if (Low_Temp >= Min_Open_Close) Low_Temp = Min_Open_Close; */ if (Open_Temp >= Close_Temp) {High_Temp = Open_Temp; Low_Temp = Close_Temp;} if (Open_Temp < Close_Temp) {High_Temp = Close_Temp; Low_Temp = Open_Temp;} switch (Selection_Item) { case 0: {return(iTime("EURUSD", timeframe, Shift)); break;} case 1: {return(Open_Temp); break;} case 2: {return(Low_Temp); break;} case 3: {return(High_Temp); break;} case 4: {return(Close_Temp); break;} case 5: {return(Volume_Temp); break;} } } //+------------------------------------------------------------------+ //| Min_Bars | //+------------------------------------------------------------------+ int Min_Bars() { int Mas_Bars[6]; Mas_Bars[0]=iBars("EURUSD", timeframe); Mas_Bars[1]=iBars("USDJPY", timeframe); Mas_Bars[2]=iBars("GBPUSD", timeframe); Mas_Bars[3]=iBars("USDCAD", timeframe); Mas_Bars[4]=iBars("USDSEK", timeframe); Mas_Bars[5]=iBars("USDCHF", timeframe); return(Mas_Bars[ArrayMinimum(Mas_Bars, WHOLE_ARRAY, 0)]); //return(iBars("EURUSD", timeframe)); } void DebugMsg(string msg) { if (Debug) Alert(msg); } void alert(string msg) { if (My_Alert) Alert(msg); } int init() { /* //safe checking for PeriodMultiplier. if (PeriodMultiplier <= 1) { //only output CSV file PeriodMultiplier = 1; OutputCSVFile = 2; } */ NewPeriod = timeframe * PeriodMultiplier; if (OpenHistoryFile() < 0) return (-1); WriteHistoryHeader(); //alert("01 - init - WriteHistoryHeader"); UpdateHistoryFile(Min_Bars()-1, true); //alert("02 - init - UpdateHistoryFile"); UpdateChartWindow(); //alert("03 - init - UpdateChartWindow"); return (0); } void deinit() { //Close file handle if(FileHandle >= 0) { FileClose(FileHandle); FileHandle = -1; } if (CSVHandle >= 0) { FileClose(CSVHandle); CSVHandle = -1; } } int OpenHistoryFile() { string name; name = New_Symbol + NewPeriod; if (OutputCSVFile != OUTPUT_CSV_ONLY) { FileHandle = FileOpenHistory(name + ".hst", FILE_BIN|FILE_WRITE); if (FileHandle < 0) return(-1); } if (OutputCSVFile != OUTPUT_HST_ONLY) { CSVHandle = FileOpen(name + ".csv", FILE_CSV|FILE_WRITE, ','); if (CSVHandle < 0) return(-1); } return (0); } int WriteHistoryHeader() { string c_copyright; int i_digits = digits; int i_unused[13] = {0}; int version = 400; if (FileHandle < 0) return (-1); c_copyright = "(C)opyright 2003, MetaQuotes Software Corp."; FileWriteInteger(FileHandle, version, LONG_VALUE); FileWriteString(FileHandle, c_copyright, 64); FileWriteString(FileHandle, New_Symbol, 12); FileWriteInteger(FileHandle, NewPeriod, LONG_VALUE); FileWriteInteger(FileHandle, i_digits, LONG_VALUE); FileWriteInteger(FileHandle, 0, LONG_VALUE); //timesign FileWriteInteger(FileHandle, 0, LONG_VALUE); //last_sync FileWriteArray(FileHandle, i_unused, 0, ArraySize(i_unused)); return (0); } static double d_open, d_low, d_high, d_close, d_volume; static int i_time; void WriteHistoryData() { if (FileHandle >= 0) { FileWriteInteger(FileHandle, i_time, LONG_VALUE); FileWriteDouble(FileHandle, d_open, DOUBLE_VALUE); FileWriteDouble(FileHandle, d_low, DOUBLE_VALUE); FileWriteDouble(FileHandle, d_high, DOUBLE_VALUE); FileWriteDouble(FileHandle, d_close, DOUBLE_VALUE); FileWriteDouble(FileHandle, d_volume, DOUBLE_VALUE); } if (CSVHandle >= 0) { int i_digits = digits; FileWrite(CSVHandle, TimeToStr(i_time, TIME_DATE), TimeToStr(i_time, TIME_MINUTES), DoubleToStr(d_open, i_digits), DoubleToStr(d_high, i_digits), DoubleToStr(d_low, i_digits), DoubleToStr(d_close, i_digits), d_volume); } } int UpdateHistoryFile(int start_pos, bool init = false) { static int last_fpos, csv_fpos; int i, ps; // if (FileHandle < 0) return (-1); // normalize open time ps = NewPeriod * 60; i_time = TOLHCV(start_pos, 0)/ps; i_time *= ps; if (init) { //first time, init data d_open = TOLHCV(start_pos, 1); d_low = TOLHCV(start_pos, 2); d_high = TOLHCV(start_pos, 3); d_close = TOLHCV(start_pos, 4); d_volume = TOLHCV(start_pos, 5); i = start_pos - 1; if (FileHandle >= 0) last_fpos = FileTell(FileHandle); if (CSVHandle >= 0) csv_fpos = FileTell(CSVHandle); } else { i = start_pos; if (FileHandle >= 0) FileSeek(FileHandle,last_fpos,SEEK_SET); if (CSVHandle >= 0) FileSeek(CSVHandle, csv_fpos, SEEK_SET); } if (i < 0) return (-1); int cnt = 0; int LastBarTime; //processing bars while (i >= 0) { LastBarTime = TOLHCV(i, 0); //a new bar if (LastBarTime >= i_time+ps) { //write the bar data WriteHistoryData(); cnt++; i_time = LastBarTime/ps; i_time *= ps; d_open = TOLHCV(i, 1); d_low = TOLHCV(i, 2); d_high = TOLHCV(i, 3); d_close = TOLHCV(i, 4); d_volume = TOLHCV(i, 5); } else { //no new bar d_volume += TOLHCV(i, 5); if (TOLHCV(i, 2)d_high) d_high = TOLHCV(i, 3); d_close = TOLHCV(i, 4); } i--; } //record last_fpos before writing last bar. if (FileHandle >= 0) last_fpos = FileTell(FileHandle); if (CSVHandle >= 0) csv_fpos = FileTell(CSVHandle); WriteHistoryData(); cnt++; d_volume -= TOLHCV(0, 5); //flush the data writen if (FileHandle >= 0) FileFlush(FileHandle); if (CSVHandle >= 0) FileFlush(CSVHandle); return (cnt); } int UpdateChartWindow() { static int hwnd = 0; if (FileHandle < 0) { //no HST file opened, no need updating. return (-1); } if(hwnd == 0) { //trying to detect the chart window for updating hwnd = WindowHandle(New_Symbol, NewPeriod); } if(hwnd!= 0) { if (IsDllsAllowed() == false) { //DLL calls must be allowed DebugMsg("Dll calls must be allowed"); return (-1); } if (PostMessageA(hwnd,WM_COMMAND,CHART_CMD_UPDATE_DATA,0) == 0) { //PostMessage failed, chart window closed hwnd = 0; } else { //PostMessage succeed return (0); } } //window not found or PostMessage failed return (-1); } /* int PerfCheck(bool Start) { static int StartTime = 0; static int Index = 0; if (Start) { StartTime = GetTickCount(); Index = 0; return (StartTime); } Index++; int diff = GetTickCount() - StartTime; Alert("Time used [" + Index + "]: " + diff); StartTime = GetTickCount(); return (diff); } */ static int LastStartTime = 0; static int LastEndTime = 0; static int LastBarCount = 0; int reinit() { deinit(); init(); LastStartTime = TOLHCV(Min_Bars()-1, 0); LastEndTime = TOLHCV(0, 0); LastBarCount = Min_Bars(); } bool IsDataChanged() { /* static int LastBars = 0, LastTime = 0, LastVolume = 0; static double LastOpen = 0, LastClose = 0, LastHigh = 0, LastLow = 0; if (LastVolume != Volume[0] || LastBars != Bars || LastTime != Time[0]|| LastClose != Close[0] || LastHigh != High[0] || LastLow != Low[0] || LastOpen != Open[0]) { LastBars = Bars; LastVolume = Volume[0]; LastTime = Time[0]; LastClose = Close[0]; LastHigh = High[0]; LastLow = Low[0]; LastOpen = Open[0]; return (true); } return (false); */ /* fast version without float point operation */ static int LastBars = 0, LastTime = 0, LastVolume = 0; bool ret; ret = false; if (LastVolume != TOLHCV(0, 5)) { LastVolume = TOLHCV(0, 5); ret = true; } if (LastTime != TOLHCV(0, 0)) { LastTime = TOLHCV(0, 0); ret = true; } if (LastBars != Min_Bars()) { LastBars = Min_Bars(); ret = true; } return (ret); } int CheckNewData() { static string LastServer = ""; if (Min_Bars() < 2) { //the data is not loaded yet. DebugMsg("Data not loaded, only " + Min_Bars() + " Bars"); return (-1); } string serv = ServerAddress(); if (serv == "") { //no server yet DebugMsg("No server connected"); return (-1); } //server changed? check this and reinit to prevent wrong data while changing server. if (LastServer != serv) { DebugMsg("Server changed from " + LastServer + " to " + serv); LastServer = serv; reinit(); return (-1); } if (!IsDataChanged()) { //return if no data changed to save resource DebugMsg("No data changed"); return (-1); } if (TOLHCV(Min_Bars()-1, 0) != LastStartTime) { DebugMsg("Start time changed, new history loaded or server changed"); reinit(); return (-1); } int i, cnt; //try to find LastEndTime bar, which should be Time[0] or Time[1] usually, //so the operation is fast for (i = 0; i < Min_Bars(); i++) { if (TOLHCV(i, 0) <= LastEndTime) { break; } } if (i >= Min_Bars() || TOLHCV(i, 0) != LastEndTime) { DebugMsg("End time " + TimeToStr(LastEndTime) + " not found"); reinit(); return (-1); } cnt = Min_Bars() - i; if (cnt != LastBarCount) { DebugMsg("Data loaded, cnt is " + cnt + " LastBarCount is " + LastBarCount); reinit(); return (-1); } //no new data loaded, return with LastEndTime position. LastBarCount = Min_Bars(); LastEndTime = TOLHCV(0, 0); return (i); } //+------------------------------------------------------------------+ //| program start function | //+------------------------------------------------------------------+ int start() { static int last_time = 0; if (!Enabled) return (0); //always update or update only after certain interval if (UpdateInterval != 0) { int cur_time; cur_time = GetTickCount(); if (MathAbs(cur_time - last_time) < UpdateInterval) { return (0); } last_time = cur_time; } //if (Debug) PerfCheck(true); int n = CheckNewData(); //Print(n); //if (Debug) PerfCheck(false); if (n < 0) return (0); //update history file with new data UpdateHistoryFile(n); //refresh chart window UpdateChartWindow(); //if (Debug) PerfCheck(false); return(0); }