论坛全局菜单下方 - TICKMILL 285X70论坛全局菜单下方 - ThinkMarkets285X70论坛全局菜单下方 - 荔枝返现285X70论坛全局菜单下方 -  icmarkets285X70
  • 1
  • 2
  • 3
  • 4
前往
共 73 条
帖子
作者
回复/查看
最后发表
2005-11-29 04:35
156
62973
2015-09-04 09:58
增加TimeShift参数,可以用来设置转化时候的时间移动偏差, 比如在 H1图标上用24作为倍数,并且将TimeShift设置为6, 则可以获得以服务器 时间每天06:00作为起始时间, 第二天05:59作为结束时间的天图, 比如生成的1月18日天图K线是以1.18 06:00 - 1.19 05:00的小时图数据 综合得到的. 其他的依次类推. 如果想用前一天时间的作为日线起始点则可以相应的把TimeShift设置为负数. 注意的是这里的所有时间都是服务器时间,如果想用本地时间还需计算 服务器与本地时间的时差后获得对应的TimeShift. 另外因为生成的D1为MT4内置时间周期,直接生成D1的历史数据的会将会产生冲突, 生成的数据会被MT4从服务器获取的未进行时间偏移的数据覆盖,所以生成的 时候将自动监测当目标周期为D1的时候,离线图表里面显示的名称为M1441(实际内容 就是生成后偏移过的D1数据, CSV文件名因无冲突问题则不会变化) 当TimeShift为0(默认数)时,工作方式同以前的老版本. //+------------------------------------------------------------------+ //| Period_Converter_Opt.mq4| //| Copyright ?2005, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //| Modified by wfy05@talkforex based on Period_Converter| //| http://www.talkfx.com | //+------------------------------------------------------------------+ #property copyright "[email protected]" #property link "http://www.mql4.com/codebase/indicators/277/" #property indicator_chart_window #property show_inputs #include /* Readme: I. Features: This is an improved version of period converter for MT4 based on the MT4's default period converter by metaquotes. The default period converter script do not support real-time refreshing, and consume lots of CPU (50%-9x%) making the whole system slow. Also, the default one is a script which do not save when you exit MT4, so you have to apply every converter script again after restarting, quite annoying. This one fixed all above problems: 1. Real-time updating or custom interval millisecond level updating. 2. Low CPU cost, average 5%-10% or less. 3. Works as an indicator, so can be saved and reloaded during restart. 4. There is no one converter per chart limitation as it is not script any more, you can only use one window as source to generate as many new timeframe chart as possible. 5. Auto updating if there is new history block loaded. II. How to use: Copy the mq4 file to your MT4 indicators folder (experts\indicators) to install it as an indicator, NOT script. then in the custom indicator list, attach period_converter_opt to the chart you want. It support 4 parameters: PeriodMultiplier: new period multiplier factor, default is 2 UpdateInterval: update interval in milliseconds, zero means update real-time. default is zero. Enabled: You can disable it without remove it with this option. Other parameters are comments or for debugging, it is safe to ignore them. Also Make sure you have Allow Dll imports option checked in common tab or it won't work After that, File->Open Offline to open the generated offline data. then the offline data will be updated automatically. As long as you keep the source chart open and the converter indicator running, the generated chart including indicators inside will always be updated. also you can close the generated chart and open again later from File->Open Offline without problem. If you want to quit MT4, you can leave those offline chart as other normal online charts. when you start MT4 next time, those charts will also be loaded and updated. III. Notes: 1. Do NOT uncheck the "offline chart" option in offline chart common properties. or after MT4 restart, it will treat that chart as online chart and request the data from server, resulting empty chart window. 2. You can attach more than one converter to same window with different PeriodMultiplier, e.g: you can attach 3 converter with PeriodMultiplier = 2, 4, 10 to M1 to generate M2, M4, M10 at the same time. It is even ok to use the M1 chart to generate Hourly chart like H2, which only cost a few more CPU resource during initial conversion. but usually most server don't have much data for those short period. resulting the generated data isn't long enough for long period. so it is suggested to use Hourly/Daily charts as source when needed. 3. The real-time updating mode updates quotes as fast as possible, but as this is done via script, and MT will skip calling start() function when your PC is busy and lots of quotes income. anyway, this seldom happen, and you can at least get 10 updates each seconds which is much more than enough. 4. The offline chart don't have a bid line showing in chart, but all data in the chart including the indicators is still being updated, so don't worry. you can show the bid line by unclick the "offline chart" option in chart properties. but which don't helps much and if you forget to check "offline chart" option before exit. it will cause errors and become empty on next startup. you have to close the window and open again from File->Open offline, which don't worth the trouble. IV. History: 2006.02.16 1.5 Added TimeShift option, can be used to shift hour timeframe to generate daily timeframe when your timezone is different from the server, default is zero. 2005.12.24 1.4 faster to detect if data changed by removing float point operations, added support to output CSV file in real time. OutputCSVFile = 0 means no CSV. OutputCSVFile = 1 means CSV + HST OutputCSVFile = 2 CSV only, no HST . (useful if you want to generate CSV for builtin periods) CSV Filename will be the same as HST file except the extension. added safe checking for PeriodMultiplier. 2005.12.04 1.3 Fixed missing data when there is large amount of data loaded in several blocks, and support auto updating when new history is loaded. 2005.11.29 1.2 Additional fix for missing data and server changing. 2005.11.29 1.1 Fixed missing partial data after restart. Reinitialize after changing server or data corrupted. 2005.11.28 1.0 Initial release */ extern double Version = 1.5; // code version extern string BuildInfo = "2006.02.16 by [email protected]"; extern int PeriodMultiplier = 2; // new period multiplier factor extern int OutputCSVFile = 0; // also output CSV file? extern int TimeShift = 0; // time shift value extern int UpdateInterval = 0; // update interval in milliseconds, zero means update real-time. extern bool Enabled = true; extern bool Debug = false; int FileHandle = -1; int CSVHandle = -1; int NewPeriod = 0; int NewPeriodOutput = 0; #define OUTPUT_HST_ONLY 0 #define OUTPUT_CSV_HST 1 #define OUTPUT_CSV_ONLY 2 #define CHART_CMD_UPDATE_DATA 33324 void DebugMsg(string msg) { if (Debug) Alert(msg); } int init() { //safe checking for PeriodMultiplier. if (PeriodMultiplier <= 1) { //only output CSV file PeriodMultiplier = 1; OutputCSVFile = 2; } NewPeriod = Period() * PeriodMultiplier; if (OpenHistoryFile() < 0) return (-1); WriteHistoryHeader(); UpdateHistoryFile(Bars-1, true); 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 = Symbol() + NewPeriod; NewPeriodOutput = NewPeriod; if (OutputCSVFile != OUTPUT_CSV_ONLY) { if (NewPeriod == 1440) { NewPeriodOutput = NewPeriod+1; name = Symbol() + NewPeriodOutput; } 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, Symbol(), 12); FileWriteInteger(FileHandle, NewPeriodOutput, 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; int shift; // if (FileHandle < 0) return (-1); // normalize open time ps = NewPeriod * 60; shift = Period() * 60 * TimeShift; i_time = (Time[start_pos]-shift)/ps; i_time *= ps; if (init) { //first time, init data d_open = Open[start_pos]; d_low = Low[start_pos]; d_high = High[start_pos]; d_close = Close[start_pos]; d_volume = Volume[start_pos]; 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 = Time-shift; //a new bar if (LastBarTime >= i_time+ps) { //write the bar data WriteHistoryData(); cnt++; i_time = LastBarTime/ps; i_time *= ps; d_open = Open; d_low = Low; d_high = High; d_close = Close; d_volume = Volume; } else { //no new bar d_volume += Volume; if (Lowd_high) d_high = High; d_close = Close; } 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 -= Volume[0]; //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(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 = Time[Bars-1]; LastEndTime = Time[0]; LastBarCount = 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 != Volume[0]) { LastVolume = Volume[0]; ret = true; } if (LastTime != Time[0]) { LastTime = Time[0]; ret = true; } if (LastBars != Bars) { LastBars = Bars; ret = true; } return (ret); } int CheckNewData() { static string LastServer = ""; if (Bars < 2) { //the data is not loaded yet. DebugMsg("Data not loaded, only " + 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 (Time[Bars-1] != 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 < Bars; i++) { if (Time <= LastEndTime) { break; } } if (i >= Bars || Time != LastEndTime) { DebugMsg("End time " + TimeToStr(LastEndTime) + " not found"); reinit(); return (-1); } cnt = 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 = Bars; LastEndTime = Time[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(); //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); }
2006-02-16 08:06
原帖由 hardwood 于 2005-12-24 21:11 发表 实时输出数据,涉及频繁写硬盘,所以想将CSV文件保存的目录设置在一个RAMDISK中(B盘), 将 name = Symbol() + NewPeriod;  改为 name = "b:\" + Symbol() + NewPeriod; 编译时出错;若改为 name ...
首先如果写驱动器名字符串中带"\"必须用"\\"来表示. 其次MT为了保证安全性, 脚本中用标准函数FileOpen打开的文件都必须在experts\files目录下, 如果想建到其他目录下就只能Windows API配合外部dll来实现了. 你看看是否可以将ram虚拟盘虚拟到某个目录的形式来实现, 或者将MT的目录每次启动更新到虚拟盘上 之类的方式来实现. 另外这个脚本就算是实时更新都只有很少的磁盘操作(这也就是为什么资源占用很少的原因), 具体说 就是每次有新数据来的时候都只更新文件尾最末一个柱状条不到50字节信息, 就算一秒钟刷新10次 20次也不到1k的数据,而且系统还有磁盘缓冲实际磁盘的写次数就更少. 此外还可以设更新周期, 30秒刷新的话一分钟也就2次共100字节的写操作. 主要消耗资源的肯定还是 读数据的部分 -- 那些excel之类的程序都没有设计成为只读尾部更新的模式,每次都是重新读入并且 分析整个文件这个数据量自然就很大了. 如果真想做实时性和效率要求比较高的最好用其他更优化 的方法. [ 本帖最后由 wfy05 于 2005-12-24 22:23 编辑 ]
2005-12-24 14:22
更新到1.4, 加快了数据变化的检测, 增加了对输入参数的安全检测. 增加了输出到excel csv文件的支持, 具体用OutputCSVFile参数设置. OutputCSVFile = 0 表示不输出CSV (和以前版本一样,默认参数) OutputCSVFile = 1 表示同时输出HST和CSV. OutputCSVFile = 2 表示只输出CSV不输出HST, 这个对你内置 时间周期转出CSV有用,比如把H1的实时输出到CSV的话就设置 转化倍数PeriodMultiplier 为1, OutputCSVFile = 2 即可. 生成的CSV文件在experts\files目录下, 文件名同HST文件, 比如EURUSD H1的转化就是EURUSD60.csv 不过一般如果只是要生成csv的话更新频率不用太高, 1分钟一次的话 可以将刷新周期也定为1分钟(60000)或者30秒(30000)来节省资源. //+------------------------------------------------------------------+ //| Period_Converter_Opt.mq4| //| Copyright ?2005, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //| Modified by wfy05@talkforex based on Period_Converter| //| http://www.talkfx.com | //+------------------------------------------------------------------+ #property copyright "[email protected]" #property link "http://www.talkfx.com" #property indicator_chart_window #property show_inputs #include /* Readme: I. Features: This is an improved version of period converter for MT4 based on the MT4's default period converter by metaquotes. The default period converter script do not support real-time refreshing, and consume lots of CPU (50%-9x%) making the whole system slow. Also, the default one is a script which do not save when you exit MT4, so you have to apply every converter script again after restarting, quite annoying. This one fixed all above problems: 1. Real-time updating or custom interval millisecond level updating. 2. Low CPU cost, average 5%-10% or less. 3. Works as an indicator, so can be saved and reloaded during restart. 4. There is no one converter per chart limitation as it is not script any more, you can only use one window as source to generate as many new timeframe chart as possible. 5. Auto updating if there is new history block loaded. II. How to use: Copy the mq4 file to your MT4 indicators folder (experts\indicators) to install it as an indicator, NOT script. then in the custom indicator list, attach period_converter_opt to the chart you want. It support 4 parameters: PeriodMultiplier: new period multiplier factor, default is 2 UpdateInterval: update interval in milliseconds, zero means update real-time. default is zero. Enabled: You can disable it without remove it with this option. Other parameters are comments or for debugging, it is safe to ignore them. Also Make sure you have Allow Dll imports option checked in common tab or it won't work After that, File->Open Offline to open the generated offline data. then the offline data will be updated automatically. As long as you keep the source chart open and the converter indicator running, the generated chart including indicators inside will always be updated. also you can close the generated chart and open again later from File->Open Offline without problem. If you want to quit MT4, you can leave those offline chart as other normal online charts. when you start MT4 next time, those charts will also be loaded and updated. III. Notes: 1. Do NOT uncheck the "offline chart" option in offline chart common properties. or after MT4 restart, it will treat that chart as online chart and request the data from server, resulting empty chart window. 2. You can attach more than one converter to same window with different PeriodMultiplier, e.g: you can attach 3 converter with PeriodMultiplier = 2, 4, 10 to M1 to generate M2, M4, M10 at the same time. It is even ok to use the M1 chart to generate Hourly chart like H2, which only cost a few more CPU resource during initial conversion. but usually most server don't have much data for those short period. resulting the generated data isn't long enough for long period. so it is suggested to use Hourly/Daily charts as source when needed. 3. The real-time updating mode updates quotes as fast as possible, but as this is done via script, and MT will skip calling start() function when your PC is busy and lots of quotes income. anyway, this seldom happen, and you can at least get 10 updates each seconds which is much more than enough. 4. The offline chart don't have a bid line showing in chart, but all data in the chart including the indicators is still being updated, so don't worry. you can show the bid line by unclick the "offline chart" option in chart properties. but which don't helps much and if you forget to check "offline chart" option before exit. it will cause errors and become empty on next startup. you have to close the window and open again from File->Open offline, which don't worth the trouble. IV. History: 2005.12.24 1.4 faster to detect if data changed by removing float point operations, added support to output CSV file. OutputCSVFile = 0 means no CSV. OutputCSVFile = 1 means CSV + HST OutputCSVFile = 2 CSV only, no HST . (useful if you want to generate CSV for builtin periods) CSV Filename will be the same as HST file except the extension. added safe checking for PeriodMultiplier. 2005.12.04 1.3 Fixed missing data when there is large amount of data loaded in several blocks, and support auto updating when new history is loaded. 2005.11.29 1.2 Additional fix for missing data and server changing. 2005.11.29 1.1 Fixed missing partial data after restart. Reinitialize after changing server or data corrupted. 2005.11.28 1.0 Initial release */ extern double Version = 1.4; // code version extern string BuildInfo = "2005.12.24 by [email protected]"; extern int PeriodMultiplier = 2; // new period multiplier factor extern int OutputCSVFile = 0; // also output CSV file? extern int UpdateInterval = 0; // update interval in milliseconds, zero means update real-time. extern bool Enabled = true; extern bool Debug = false; int FileHandle = -1; int CSVHandle = -1; int NewPeriod = 0; #define OUTPUT_HST_ONLY 0 #define OUTPUT_CSV_HST 1 #define OUTPUT_CSV_ONLY 2 #define CHART_CMD_UPDATE_DATA 33324 void DebugMsg(string msg) { if (Debug) Alert(msg); } int init() { //safe checking for PeriodMultiplier. if (PeriodMultiplier <= 1) { //only output CSV file PeriodMultiplier = 1; OutputCSVFile = 2; } NewPeriod = Period() * PeriodMultiplier; if (OpenHistoryFile() < 0) return (-1); WriteHistoryHeader(); UpdateHistoryFile(Bars-1, true); 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 = 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, 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 = Time[start_pos]/ps; i_time *= ps; if (init) { //first time, init data d_open = Open[start_pos]; d_low = Low[start_pos]; d_high = High[start_pos]; d_close = Close[start_pos]; d_volume = Volume[start_pos]; 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 = Time; //a new bar if (LastBarTime >= i_time+ps) { //write the bar data WriteHistoryData(); cnt++; i_time = LastBarTime/ps; i_time *= ps; d_open = Open; d_low = Low; d_high = High; d_close = Close; d_volume = Volume; } else { //no new bar d_volume += Volume; if (Lowd_high) d_high = High; d_close = Close; } 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 -= Volume[0]; //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(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 = Time[Bars-1]; LastEndTime = Time[0]; LastBarCount = 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 != Volume[0]) { LastVolume = Volume[0]; ret = true; } if (LastTime != Time[0]) { LastTime = Time[0]; ret = true; } if (LastBars != Bars) { LastBars = Bars; ret = true; } return (ret); } int CheckNewData() { static string LastServer = ""; if (Bars < 2) { //the data is not loaded yet. DebugMsg("Data not loaded, only " + 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 (Time[Bars-1] != 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 < Bars; i++) { if (Time <= LastEndTime) { break; } } if (i >= Bars || Time != LastEndTime) { DebugMsg("End time " + TimeToStr(LastEndTime) + " not found"); reinit(); return (-1); } cnt = 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 = Bars; LastEndTime = Time[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(); //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); }
2005-12-24 01:47
2005-11-10 12:47
199
42931
2016-03-19 13:16
MT 4.0 Build 187以后的版本把SpeechText函数去掉了以前的朗读相关功能都无法再继续使用. 现在必须用自己的DLL来实现了语音功能了, 简单写了一个dll版本的如下: 第一部分代码为更新后的MQ4代码,第二部分代码为dll源代码, 大家可自行编译成dll 或者用附件中编译好的. 将附件改名为SpeechText.dll后放到MT4的experts\libraries\目录下 //+------------------------------------------------------------------+ //| 语音报价.mq4 | //| | //| | //+------------------------------------------------------------------+ #property copyright "[email protected]" #property link "www.talkfx.com" #import "SpeechText.dll" int MT_SpeechText(string text, int async); #import //---- input parameters extern string Version="1.4"; extern string BuildInfo = "2006.01.18 by [email protected]"; extern string Format = "%SELL_CURR% 兑 %BUY_CURR% %ACTION% 价为 %PRICE% %ADD_DIR% %ADD%"; extern bool UseBid=true; extern int SpeakInterval=10; extern int SpeakDelta=0; extern double Range1Min=0.0; extern double Range1Max=99999.9; extern double Range2Min=0.0; extern double Range2Max=0.0; extern bool Enabled=true; extern bool InitSpeak=false; extern bool LogMessage=false; double LastPrice = 0; int LastSpeakTime = 0; string StrListGetVar(string & array, string name) { int i, n; n = ArraySize(array)/2; for (i=0; i n1+1) { out = StringConcatenate(out, StringVarGetValue(StringSubstr(str, n1+1, n2-n1-1))); } else if (n2 == n1 + 1) { out = StringConcatenate(out, "%"); } start = n2+1; } return (out); } string StrList = { "SELL_CURR",, "BUY_CURR",, "PRICE",, "ACTION",, "ADD_DIR",, "ADD",, "BID_PRICE",, "ASK_PRICE",, }; string StringVarGetValue(string name) { return (StrListGetVar(StrList, name)); } bool StringVarSetValue(string name, string value) { return (StrListSetVar(StrList, name, value)); } void DoSpeech() { string str; UpdateVars(); str = StringReplaceVar(Format); MT_SpeechText(str, 1); LastSpeakTime = GetTickCount(); if (LogMessage) Print (str); return; } double GetPriceChanged() { double diff; double p = GetCurrPrice(); int n = MathPow(10, Digits); diff = p * n -LastPrice *n; return (diff); } double GetCurrPrice() { double p; if (UseBid) { p = Bid; } else { p = Ask; } return (p); } void UpdateVars() { StringVarSetValue("BID_PRICE", DoubleToStr(Bid, Digits)); StringVarSetValue("ASK_PRICE", DoubleToStr(Ask, Digits)); StringVarSetValue("PRICE", DoubleToStr(GetCurrPrice(), Digits)); string add, adddir; double diff = GetPriceChanged(); double abs_diff = MathAbs(diff); double p = GetCurrPrice(); if (abs_diff != 0) { if (diff > 0) { adddir = "上涨"; } else if (diff < 0) { adddir = "下跌"; } add = DoubleToStr(abs_diff, 0) + "点"; } else { adddir = ""; add = ""; } LastPrice = p; StringVarSetValue("ADD_DIR", adddir); StringVarSetValue("ADD", add); return; } void InitVars() { StringVarSetValue("SELL_CURR", GetSymbolCurrency(true)); StringVarSetValue("BUY_CURR", GetSymbolCurrency(false)); if (UseBid) { StringVarSetValue("ACTION", "买入"); } else { StringVarSetValue("ACTION", "卖出"); } return; } //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- LastPrice = GetCurrPrice(); LastSpeakTime = 0; if (InitSpeak) { string str; str = "开始进行" + GetSymbolName(Symbol()) + "的自动报价"; str = str + "当前价格为" + DoubleToStr(LastPrice, Digits); MT_SpeechText(str, 1); } InitVars(); if (Enabled) DoSpeech(); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- if (InitSpeak) { string str; str = "停止" + GetSymbolName(Symbol()) + "的自动报价"; MT_SpeechText(str, 1); } //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- if (!Enabled) return (0); if (MathAbs(GetTickCount() - LastSpeakTime) < SpeakInterval * 1000) { return (0); } double p = GetCurrPrice(); if (!(p >= Range1Min && p <= Range1Max) && !(p >= Range2Min && p <= Range2Max)) { return (0); } double abs_diff = MathAbs(GetPriceChanged()); if (abs_diff < SpeakDelta) { return (0); } DoSpeech(); //---- return(0); } //+------------------------------------------------------------------+ #include #include #pragma comment(lib, "ole32.lib") #pragma comment(lib, "sapi.lib") ISpVoice * gpVoice = NULL; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: if (FAILED(CoInitialize(NULL))) { return FALSE; } if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&gpVoice))) { return FALSE; } if (!gpVoice) return FALSE; break; case DLL_PROCESS_DETACH: /* if (gpVoice) gpVoice->Release(); */ gpVoice = NULL; CoUninitialize(); break; default: break; } return TRUE; } BOOL WINAPI MT_SpeechText(char const * text, BOOL async) { WCHAR * msg; BOOL ret; int len; DWORD dwFlags; len = strlen(text) + 1; msg = new WCHAR[len]; MultiByteToWideChar(CP_ACP, 0, text, len, msg, len); if (async) { dwFlags = SPF_ASYNC; } else { dwFlags = SPF_DEFAULT; } if (FAILED(gpVoice->Speak(msg, dwFlags, NULL))) { ret = FALSE; } else { ret = TRUE; } delete msg; return ret; } [ 本帖最后由 wfy05 于 2006-1-18 14:18 编辑 ]SpeechText.jpegSpeechText.jpeg
2006-01-18 06:16
2005-11-25 02:06
61
25019
2016-01-09 09:56
再次更新加入4个服务器, 大家如果有数据比较好(特别是有美指)的MT3服务器不妨也推荐一下,可能会有其对应mt4的服务器了. IP,名称,时区,币种,其它,速度,公司,位置,主页,邮件 217.74.32.222:443,Alpari-Demo ,GMT+1,黄金,美指(延迟),,刷新慢,Alpari Ltd.,俄国,http://www.alpari-idc.ru,[email protected] 209.61.208.17:443,DirectForex,GMT-6,仅直盘及少量叉盘,,刷新频率高,"Direct Forex, LLC",美国,,[email protected] mt.forexua.com:443,Forex-Server,GMT+2,"直盘, 美指,少量叉盘","股指,股票",有滑点,Forex Ltd.,,http://www.forexua.com,[email protected] mt1.fxprofit.ru:443,FxProfit-Demo,GMT+1,黄金,"股指,股票,期货",,Integra Capital Ltd.,,http://www.fxprofit.ru,[email protected] 66.114.105.89:443,InterbankFX-Demo,GMT+0,仅货币直盘及很少叉盘,,刷新频率高,"Interbank FX, LLC",美国,,[email protected] demo.metaquotes.net:443,MetaQuotes-Demo,GMT+1,黄金,"股票,股指,期货",,MetaQuotes Software Corp.,,http://www.metaquotes.net,[email protected] 66.235.184.206:443,MIG-Demo,GMT+1,"黄金白银,货币",,,MIG Investments SA.,瑞士,http://www.migfx.ch,[email protected] demo.fxteam.ru:443,North Finance-Demo,GMT+2,"货币,黄金,白银","股票,股指",,North Finance Company Ltd,,http://www.northfinance.com,[email protected] 66.148.84.147:443,Ntwo-Main,GMT+0,"黄金,白银",少量叉盘,,Ntwo Capital Market LLC.,,http://www.n2cm.com,[email protected] 66.36.230.215:443,PTMillennium-Server,GMT+2,"货币全(HKD,CNY),金银",期货,,PT Millennium Penata Futures,,http://www.mdicorps.com,[email protected] 217.8.185.218:443,XTrade-Demo,GMT+1,货币直盘,,,X-Trade Brokers DM S.A.,,http://www.xtb.pl,[email protected] 66.235.184.157:443,Money-Tec Demo,GMT+1,"直盘,黄金,少量叉盘","股票,股指",刷新慢,MoneyTec LLC,,http://www.strategybuilderfx.com,[email protected] 212.12.60.156:443,Gimex-NEXTT,GMT+1,"直盘,黄金,少量叉盘","股票,股指,期货",刷新快,Gimex Group,,http://www.gimex.ch,[email protected] 217.27.32.243:443,Windsor Brokers-Demo,GMT+2,"货币,金银","股票,股指,期货",,Windsor Brokers Ltd,塞浦路斯,http://www.windsorbrokers.biz,[email protected] 212.100.249.39:443,ForexService-Server,GMT+1,"货币,黄金","股票,期货",,Financial Network Worldwide Ltd.,俄国,http://www.forexservice.net/,[email protected] 217.16.27.150:443,FIBO-Demo,GMT+1,"货币(NZD,NOK,SGD,SEK)",,,"Fibo Group, Ltd",英国伦敦,http://fibogroup.com/,[email protected] 66.36.231.125:443,TeleTrade-Server,GMT+2,仅直盘及少量叉盘,,,Teletrade D.J. International Consulting Ltd,俄国,http://www.teletrade-dj.com,[email protected] 83.142.230.30:443,Admiral-Demo,GMT+0,"直盘及少量叉盘,黄金",股指,,Admiral Investments and Securities Ltd.,英国伦敦,http://www.fxservice.com/,[email protected] 66.36.242.238:443,FxPro-Server,GMT+0,"货币,金银",期货,,Fx-Pro Ltd,英国,http://www.fx-pro.com,[email protected] 66.36.240.247,Orion-Demo,GMT+4,"货币,金银","股票,股指,期货",,Orion Global Financial Services,美国,http://www.orionbrokers.com/,[email protected] 212.109.44.23:443,Ukrsotsbank-MT4,GMT+2,"货币,金银",,,Ukrsotsbank,俄国,http://forex.ukrsotsbank.com/,[email protected] 66.235.180.133:443,SNC-Server,GMT+2,仅货币直盘及很少叉盘,,,"SNC Investments, Inc.",加拿大,http://www.sncfx.com/,[email protected] mt4demo.sts.bg:443,STS-Demo,GMT+2,"货币,金银","股票,股指,期货",,STS Finance SC,保加利亚,http://www.finance.sts.bg,[email protected] ,,,,,,,,, 2005-12-27,,,wfy05@talkforex 测试整理,,,,,,mt4-servers.gifmt4-servers.gif
2005-12-27 13:02
  • 1
  • 2
  • 3
  • 4
前往
共 73 条

本站免责声明:

1、本站所有广告及宣传信息均与韬客无关,如需投资请依法自行决定是否投资、斟酌资金安全及交易亏损风险;

2、韬客是独立的、仅为投资者提供交流的平台,网友发布信息不代表韬客的观点与意思表示,所有因网友发布的信息而造成的任何法律后果、风险与责任,均与韬客无关;

3、金融交易存在极高法律风险,未必适合所有投资者,请不要轻信任何高额投资收益的诱导而贸然投资;投资保证金交易导致的损失可能超过您投入的资金和预期。请您考虑自身的投资经验及风险承担能力,进行合法、理性投资;

4、所有投资者的交易帐户应仅限本人使用,不应交由第三方操作,对于任何接受第三方喊单、操盘、理财等操作的投资和交易,由此导致的任何风险、亏损及责任由投资者个人自行承担;

5、韬客不隶属于任何券商平台,亦不受任何第三方控制,韬客不邀约客户投资任何保证金交易,不接触亦不涉及投资者的任何资金及账户信息,不代理任何交易操盘行为,不向客户推荐任何券商平台,亦不存在其他任何推荐行为。投资者应自行选择券商平台,券商平台的任何行为均与韬客无关。投资者注册及使用韬客即表示其接受和认可上述声明,并自行承担法律风险。

版权所有:韬客外汇论坛 www.talkfx.com 联络我们:[email protected]