CustomTicksReplace

MqlTick类型数组数据完全替换指定时间间隔内自定义交易品种的价格历史。

int  CustomTicksReplace(
   const string     symbol,            // 交易品种名称
   long             from_msc,          // 开始日期
   long             to_msc,            // 结束日期
   const MqlTick&   ticks[],           // 即将用于自定义交易品种的数据数组
   uint             count=WHOLE_ARRAY  // 即将使用的ticks[]数组元素的数量
   );

参数

交易品种

[in]  自定义交易品种名称。

from_msc

[in]  即将移除的指定范围内价格历史的第一个报价时间。时间以毫秒为单位从01.01.1970开始计算。

to_msc

[in]  即将移除的指定范围内价格历史的最后报价时间。时间以毫秒为单位从01.01.1970开始计算。

ticks[]

[in]   以升序时间顺序排列的MqlTick类型报价数据数组。

count=WHOLE_ARRAY

[in]  即将用于在指定时间间隔内进行替换的ticks[]数组元素的数量。WHOLE_ARRAY意味着所有ticks[]数组元素都应被使用。

返回值

已更新报价的数量,错误情况下为-1。

注意

由于多个报价常常在报价流中有最多1毫秒的相同时间(正确报价时间保存在MqlTick结构的time_msc文件里),CustomTicksReplace函数不会根据时间自动排序ticks[]数组元素。因此,报价数组一定要及时以升序提前排列。

报价会日复一日的持续被替换,直至到达to_msc指定的时间或出现错误为止。从指定范围的第一天开始处理,然后是第二天。当检测到报价时间和升序(非降序)不匹配时,那么当日的报价替换停止。如果之前全部报价被成功替换,那么当日(错误报价时间)和指定间隔内全部剩余日保持不变。

如果ticks[] 数组包含任何时间的非报价数据(通常是任何时间间隔),那么使用ticks[]报价数据后,丢失数据对应的“hole”显示在自定义交易品种的历史中。换句话说,调用丢失报价的CustomTicksReplace函数等同于删除部分报价历史,就好比调用“hole”间隔的CustomTicksDelete函数。

如果报价数据库在指定时间间隔内没有数据,那么CustomTicksReplace将添加到数据库报价构成的ticks[]数组。

CustomTicksReplace函数通过报价数据库直接工作。

 

示例:

//+------------------------------------------------------------------+
//|                                           CustomTicksReplace.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#define   CUSTOM_SYMBOL_NAME     Symbol()+".C"     // 自定义交易品种名称
#define   CUSTOM_SYMBOL_PATH     "Forex"           // 创建的交易品种所在组的名称
#define   CUSTOM_SYMBOL_ORIGIN   Symbol()          // 自定义交易品种的基础交易品种名称
 
#define   DATATICKS_TO_COPY      UINT_MAX          // 复制的报价数量
#define   DATATICKS_TO_PRINT     20                // 发送到日志中的报价数量
 
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 取得创建自定义交易品种时的错误代码
   int create=CreateCustomSymbol(CUSTOM_SYMBOL_NAMECUSTOM_SYMBOL_PATHCUSTOM_SYMBOL_ORIGIN);
   
//--- 如果错误代码不为0 (创建交易品种成功) 也不为 5304 (交易品种已经被创建) - 退出
   if(create!=0 && create!=5304)
      return;
 
//--- 把标准交易品种的报价数据读取至 MqlTick 数组中
   MqlTick array[]={};
   if(!GetTicksToArray(CUSTOM_SYMBOL_ORIGINDATATICKS_TO_COPYarray))
      return;
   
//--- 打印接收到的标准交易品种的第一个和最后一个报价的时间
   int total=(int)array.Size();
   PrintFormat("First tick time: %s.%03u, Last tick time: %s.%03u",
               TimeToString(array[0].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
               TimeToString(array[total-1].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
               
//--- 把标准交易品种最后一个报价的 DATATICKS_TO_PRINT 数据打印至日志中
   PrintFormat("\nThe last %d ticks for the standard symbol '%s':"DATATICKS_TO_PRINTCUSTOM_SYMBOL_ORIGIN);
   for(int i=total-DATATICKS_TO_PRINTi<totali++)
     {
      if(i<0)
         continue;
      PrintFormat("  %dth Tick: %s"iGetTickDescription(array[i]));
     }
   
//--- 在市场报价窗口中添加一个自定义交易品种
   ResetLastError();
   if(!SymbolSelect(CUSTOM_SYMBOL_NAMEtrue))
     {
      Print("SymbolSelect() failed. Error "GetLastError());
      return;
     }
     
//--- 把报价数组数据添加到自定义交易品种的价格历史中
   Print("...");
   uint start=GetTickCount();
   PrintFormat("Start of adding %u ticks to the history of the custom symbol '%s'"array.Size(), CUSTOM_SYMBOL_NAME);
   int added=CustomTicksAdd(CUSTOM_SYMBOL_NAMEarray);
   PrintFormat("Added %u ticks to the history of the custom symbol '%s' in %u ms"addedCUSTOM_SYMBOL_NAMEGetTickCount()-start);
   
//--- 把新增的自定义交易品种报价数据读取至 MqlTick 数组中
   Print("...");
   if(!GetTicksToArray(CUSTOM_SYMBOL_NAMEarray.Size(), array))
      return;
   
//--- 打印收到的自定义交易品种第一个和最后一个报价的时间
   total=(int)array.Size();
   PrintFormat("First tick time: %s.%03u, Last tick time: %s.%03u",
               TimeToString(array[0].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
               TimeToString(array[total-1].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
               
//--- 把自定义交易品种最后报价的 DATATICKS_TO_PRINT 数据打印到日志中
   PrintFormat("\nThe last %d ticks for the custom symbol '%s':"DATATICKS_TO_PRINTCUSTOM_SYMBOL_NAME);
   for(int i=total-DATATICKS_TO_PRINTi<totali++)
     {
      if(i<0)
         continue;
      PrintFormat("  %dth Tick: %s"iGetTickDescription(array[i]));
     }
 
//--- 现在使用公式 Ask(Symbol) = 1.0 / Ask(Symbol), Bid(Symbol) = 1.0 / Bid(Symbol) 来在数组中修改 Ask 和 Bid 报价数值
   for(int i=0i<totali++)
     {
      array[i].ask = (array[i].ask !=0 ? 1.0 / array[i].ask : array[i].ask);
      array[i].bid = (array[i].bid !=0 ? 1.0 / array[i].bid : array[i].bid);
     }
   Print("\nNow the ticks are changed");
 
//--- 使用修改过的报价数组数据替换自定义交易品种的报价历史
   Print("...");
   start=GetTickCount();
   PrintFormat("Start replacing %u changed ticks in the history of the custom symbol '%s'"array.Size(), CUSTOM_SYMBOL_NAME);
   int replaced=CustomTicksReplace(CUSTOM_SYMBOL_NAMEarray[0].time_mscarray[total-1].time_mscarray);
   PrintFormat("Replaced %u ticks in the history of the custom symbol '%s' in %u ms"replacedCUSTOM_SYMBOL_NAMEGetTickCount()-start);
   
//--- 把替换过的自定义交易品种报价数据读取至 MqlTick 数组中
   Print("...");
   if(!GetTicksToArray(CUSTOM_SYMBOL_NAMEarray.Size(), array))
      return;
   
//--- 打印修改过的自定义交易品种报价的第一个和最后一个报价的时间
   total=(int)array.Size();
   PrintFormat("First changed tick time: %s.%03u, Last changed tick time: %s.%03u",
               TimeToString(array[0].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
               TimeToString(array[total-1].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
               
//--- 在日志中打印自定义交易品种最近 DATATICKS_TO_PRINT 个修改过的报价
   PrintFormat("\nThe last %d changed ticks for the custom symbol '%s':"DATATICKS_TO_PRINTCUSTOM_SYMBOL_NAME);
   for(int i=total-DATATICKS_TO_PRINTi<totali++)
     {
      if(i<0)
         continue;
      PrintFormat("  %dth Changed tick: %s"iGetTickDescription(array[i]));
     }
 
//--- 在图表注释区显示脚本终止键的提示
   Comment(StringFormat("Press 'Esc' to exit or 'Del' to delete the '%s' symbol and exit"CUSTOM_SYMBOL_NAME));
//--- 在无尽循环中等待按下 Esc 或 Del 键
   while(!IsStopped() && TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)==0)
     {
      Sleep(16);
      //--- 当按下 Del 时, 删除所创建的自定义交易品种和它的数据
      if(TerminalInfoInteger(TERMINAL_KEYSTATE_DELETE)<0)
        {
         //--- 删除柱形数据
         int deleted=CustomRatesDelete(CUSTOM_SYMBOL_NAME0LONG_MAX);
         if(deleted>0)
            PrintFormat("%d history bars of the custom symbol '%s' were successfully deleted"deletedCUSTOM_SYMBOL_NAME);
         
         //--- 删除报价数据
         deleted=CustomTicksDelete(CUSTOM_SYMBOL_NAME0LONG_MAX);
         if(deleted>0)
 
         
         //--- 删除交易品种
         if(DeleteCustomSymbol(CUSTOM_SYMBOL_NAME))
            PrintFormat("Custom symbol '%s' deleted successfully"CUSTOM_SYMBOL_NAME);
         break;
        }
     }
//--- 退出前清空图表
   Comment("");
   /*
   结果:
   Requested 4294967295 ticks to get tick history for the symbol 'EURUSD'
   The tick history for the 'EURUSDsymbol is received in the amount of 351195822 ticks in 55735 ms
   First tick time2011.12.19 00:00:08.000Last tick time2024.06.21 08:39:03.113
   
   The last 20 ticks for the standard symbol 'EURUSD':
     351195802th Tick2024.06.21 08:38:10.076 Ask=1.07194 (Info tick)
     351195803th Tick2024.06.21 08:38:13.162 Ask=1.07195 (Info tick)
     351195804th Tick2024.06.21 08:38:13.872 Bid=1.07195 (Info tick)
     351195805th Tick2024.06.21 08:38:14.866 Ask=1.07194 Bid=1.07194 (Info tick)
     351195806th Tick2024.06.21 08:38:17.374 Bid=1.07194 (Info tick)
     351195807th Tick2024.06.21 08:38:18.883 Bid=1.07194 (Info tick)
     351195808th Tick2024.06.21 08:38:19.771 Bid=1.07194 (Info tick)
     351195809th Tick2024.06.21 08:38:20.873 Ask=1.07195 Bid=1.07195 (Info tick)
     351195810th Tick2024.06.21 08:38:22.278 Ask=1.07196 Bid=1.07196 (Info tick)
     351195811th Tick2024.06.21 08:38:22.775 Bid=1.07196 (Info tick)
     351195812th Tick2024.06.21 08:38:23.477 Bid=1.07196 (Info tick)
     351195813th Tick2024.06.21 08:38:38.194 Ask=1.07197 (Info tick)
     351195814th Tick2024.06.21 08:38:38.789 Ask=1.07196 (Info tick)
     351195815th Tick2024.06.21 08:38:39.290 Ask=1.07197 (Info tick)
     351195816th Tick2024.06.21 08:38:43.695 Ask=1.07196 (Info tick)
     351195817th Tick2024.06.21 08:38:52.203 Ask=1.07195 Bid=1.07195 (Info tick)
     351195818th Tick2024.06.21 08:38:55.105 Ask=1.07196 Bid=1.07196 (Info tick)
     351195819th Tick2024.06.21 08:38:57.607 Ask=1.07195 Bid=1.07195 (Info tick)
     351195820th Tick2024.06.21 08:39:00.512 Ask=1.07196 Bid=1.07196 (Info tick)
     351195821th Tick2024.06.21 08:39:03.113 Ask=1.07195 Bid=1.07195 (Info tick)
   ...
   Start of adding 351195822 ticks to the history of the custom symbol 'EURUSD.C'
   Added 351195822 ticks to the history of the custom symbol 'EURUSD.Cin 349407 ms
   ...
   Requested 351195822 ticks to get tick history for the symbol 'EURUSD.C'
   The tick history for the 'EURUSD.Csymbol is received in the amount of 351195822 ticks in 190203 ms
   First tick time2011.12.19 00:00:08.000Last tick time2024.06.21 08:39:03.113
   
   The last 20 ticks for the custom symbol 'EURUSD.C':
     351195802th Tick2024.06.21 08:38:10.076 Ask=1.07194 Bid=1.07194 (Info tick)
     351195803th Tick2024.06.21 08:38:13.162 Ask=1.07195 Bid=1.07195 (Info tick)
     351195804th Tick2024.06.21 08:38:13.872 Ask=1.07195 Bid=1.07195 (Info tick)
     351195805th Tick2024.06.21 08:38:14.866 Ask=1.07194 Bid=1.07194 (Info tick)
     351195806th Tick2024.06.21 08:38:17.374 Ask=1.07194 Bid=1.07194 (Info tick)
     351195807th Tick2024.06.21 08:38:18.883 Ask=1.07194 Bid=1.07194 (Info tick)
     351195808th Tick2024.06.21 08:38:19.771 Ask=1.07194 Bid=1.07194 (Info tick)
     351195809th Tick2024.06.21 08:38:20.873 Ask=1.07195 Bid=1.07195 (Info tick)
     351195810th Tick2024.06.21 08:38:22.278 Ask=1.07196 Bid=1.07196 (Info tick)
     351195811th Tick2024.06.21 08:38:22.775 Ask=1.07196 Bid=1.07196 (Info tick)
     351195812th Tick2024.06.21 08:38:23.477 Ask=1.07196 Bid=1.07196 (Info tick)
     351195813th Tick2024.06.21 08:38:38.194 Ask=1.07197 Bid=1.07197 (Info tick)
     351195814th Tick2024.06.21 08:38:38.789 Ask=1.07196 Bid=1.07196 (Info tick)
     351195815th Tick2024.06.21 08:38:39.290 Ask=1.07197 Bid=1.07197 (Info tick)
     351195816th Tick2024.06.21 08:38:43.695 Ask=1.07196 Bid=1.07196 (Info tick)
     351195817th Tick2024.06.21 08:38:52.203 Ask=1.07195 Bid=1.07195 (Info tick)
     351195818th Tick2024.06.21 08:38:55.105 Ask=1.07196 Bid=1.07196 (Info tick)
     351195819th Tick2024.06.21 08:38:57.607 Ask=1.07195 Bid=1.07195 (Info tick)
     351195820th Tick2024.06.21 08:39:00.512 Ask=1.07196 Bid=1.07196 (Info tick)
     351195821th Tick2024.06.21 08:39:03.113 Ask=1.07195 Bid=1.07195 (Info tick)
   
   Now the ticks are changed
   ...
   Start replacing 351195822 changed ticks in the history of the custom symbol 'EURUSD.C'
   Replaced 351195822 ticks in the history of the custom symbol 'EURUSD.Cin 452266 ms
   ...
   Requested 351195822 ticks to get tick history for the symbol 'EURUSD.C'
   The tick history for the 'EURUSD.Csymbol is received in the amount of 351195822 ticks in 199812 ms
   First changed tick time2011.12.19 00:00:08.000Last changed tick time2024.06.21 08:39:03.113
   
   The last 20 changed ticks for the custom symbol 'EURUSD.C':
     351195802th Changed tick2024.06.21 08:38:10.076 Ask=0.93289 Bid=0.93289 (Info tick)
     351195803th Changed tick2024.06.21 08:38:13.162 Ask=0.93288 Bid=0.93288 (Info tick)
     351195804th Changed tick2024.06.21 08:38:13.872 Ask=0.93288 Bid=0.93288 (Info tick)
     351195805th Changed tick2024.06.21 08:38:14.866 Ask=0.93289 Bid=0.93289 (Info tick)
     351195806th Changed tick2024.06.21 08:38:17.374 Ask=0.93289 Bid=0.93289 (Info tick)
     351195807th Changed tick2024.06.21 08:38:18.883 Ask=0.93289 Bid=0.93289 (Info tick)
     351195808th Changed tick2024.06.21 08:38:19.771 Ask=0.93289 Bid=0.93289 (Info tick)
     351195809th Changed tick2024.06.21 08:38:20.873 Ask=0.93288 Bid=0.93288 (Info tick)
     351195810th Changed tick2024.06.21 08:38:22.278 Ask=0.93287 Bid=0.93287 (Info tick)
     351195811th Changed tick2024.06.21 08:38:22.775 Ask=0.93287 Bid=0.93287 (Info tick)
     351195812th Changed tick2024.06.21 08:38:23.477 Ask=0.93287 Bid=0.93287 (Info tick)
     351195813th Changed tick2024.06.21 08:38:38.194 Ask=0.93286 Bid=0.93286 (Info tick)
     351195814th Changed tick2024.06.21 08:38:38.789 Ask=0.93287 Bid=0.93287 (Info tick)
     351195815th Changed tick2024.06.21 08:38:39.290 Ask=0.93286 Bid=0.93286 (Info tick)
     351195816th Changed tick2024.06.21 08:38:43.695 Ask=0.93287 Bid=0.93287 (Info tick)
     351195817th Changed tick2024.06.21 08:38:52.203 Ask=0.93288 Bid=0.93288 (Info tick)
     351195818th Changed tick2024.06.21 08:38:55.105 Ask=0.93287 Bid=0.93287 (Info tick)
     351195819th Changed tick2024.06.21 08:38:57.607 Ask=0.93288 Bid=0.93288 (Info tick)
     351195820th Changed tick2024.06.21 08:39:00.512 Ask=0.93287 Bid=0.93287 (Info tick)
     351195821th Changed tick2024.06.21 08:39:03.113 Ask=0.93288 Bid=0.93288 (Info tick)
   */
  }
//+------------------------------------------------------------------+
//| 创建一个自定义交易品种, 返回错误代码                                  |
//+------------------------------------------------------------------+
int CreateCustomSymbol(const string symbol_nameconst string symbol_pathconst string symbol_origin=NULL)
  {
//--- 定义自定义交易品种所基于的交易品种名称
   string origin=(symbol_origin==NULL ? Symbol() : symbol_origin);
   
//--- 如果创建自定义交易品种失败并且错误代码不是 5304, 在日志中报告
   ResetLastError();
   int error=0;
   if(!CustomSymbolCreate(symbol_namesymbol_pathorigin))
     {
      error=GetLastError();
      if(error!=5304)
         PrintFormat("CustomSymbolCreate(%s, %s, %s) failed. Error %d"symbol_namesymbol_pathoriginerror);
     }
//--- 成功
   return(error);
  }
//+------------------------------------------------------------------+
//| 删除一个自定义交易品种                                              |
//+------------------------------------------------------------------+
bool DeleteCustomSymbol(const string symbol_name)
  {
//--- 从市场报价窗口中隐藏交易品种
   ResetLastError();
   if(!SymbolSelect(symbol_namefalse))
     {
      PrintFormat("SymbolSelect(%s, false) failed. Error %d"GetLastError());
      return(false);
     }
      
//--- 如果删除自定义交易品种失败,在日志中报告并返回 'false'
   ResetLastError();
   if(!CustomSymbolDelete(symbol_name))
     {
      PrintFormat("CustomSymbolDelete(%s) failed. Error %d"symbol_nameGetLastError());
      return(false);
     }
//--- 成功
   return(true);
  }
//+------------------------------------------------------------------+
//| 把指定数量的报价读取到数组中                                         |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbolconst uint countMqlTick &array[])
  {
//--- 通知开始载入历史数据
   PrintFormat("Requested %u ticks to get tick history for the symbol '%s'"countsymbol);
   
//--- 为接收报价做3次尝试
   int attempts=0;
   while(attempts<3)
     {
      //--- 测量接收报价的开始时间
      uint start=GetTickCount();
      
      //--- 从 1970.01.01 00:00.001 (参数 from=1 ms) 开始请求报价历史
      int received=CopyTicks(symbolarrayCOPY_TICKS_ALL1count);
      if(received!=-1)
        {
         //--- 显示报价数量和花费的时间 
         PrintFormat("The tick history for the '%s' symbol is received in the amount of %u ticks in %d ms"symbolreceivedGetTickCount()-start);
         
         //--- 如果报价历史已同步, 错误代码等于0 - 返回 'true'
         if(GetLastError()==0)
            return(true);
 
         PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d"
                     symbolreceivedGetTickCount()-startGetLastError());
        }
      //--- 计数尝试次数 
      attempts++; 
      //--- 暂停一秒以等待报价数据库同步结束 
      Sleep(1000);
     }
//--- 3次尝试复制报价失败
   return(false);
  }
//+------------------------------------------------------------------+ 
//| 返回报价的字符串类型描述                                             |
//+------------------------------------------------------------------+ 
string GetTickDescription(MqlTick &tick
  { 
   string desc=StringFormat("%s.%03u "TimeToString(tick.timeTIME_DATE|TIME_MINUTES|TIME_SECONDS),tick.time_msc%1000);
   
//--- 检查报价标志
   bool buy_tick   = ((tick.flags &TICK_FLAG_BUY)   == TICK_FLAG_BUY); 
   bool sell_tick  = ((tick.flags &TICK_FLAG_SELL)  == TICK_FLAG_SELL); 
   bool ask_tick   = ((tick.flags &TICK_FLAG_ASK)   == TICK_FLAG_ASK); 
   bool bid_tick   = ((tick.flags &TICK_FLAG_BID)   == TICK_FLAG_BID); 
   bool last_tick  = ((tick.flags &TICK_FLAG_LAST)  == TICK_FLAG_LAST); 
   bool volume_tick= ((tick.flags &TICK_FLAG_VOLUME)== TICK_FLAG_VOLUME); 
   
//--- 首先检查用于交易的报价标志 (没有 CustomTicksAdd())
   if(buy_tick || sell_tick
     { 
      //--- 构建交易报价的输出内容 
      desc += (buy_tick ? StringFormat("Buy Tick: Last=%G Volume=%d "tick.lasttick.volume)  : ""); 
      desc += (sell_tickStringFormat("Sell Tick: Last=%G Volume=%d ",tick.lasttick.volume) : ""); 
      desc += (ask_tick ? StringFormat("Ask=%G "tick.ask) : ""); 
      desc += (bid_tick ? StringFormat("Bid=%G "tick.ask) : ""); 
      desc += "(Trade tick)"
     } 
   else 
     { 
      //--- 构建信息报价的输出稍有不同 
      desc += (ask_tick   ? StringFormat("Ask=%G ",  tick.ask)    : ""); 
      desc += (bid_tick   ? StringFormat("Bid=%G ",  tick.ask)    : ""); 
      desc += (last_tick  ? StringFormat("Last=%G "tick.last)   : ""); 
      desc += (volume_tickStringFormat("Volume=%d ",tick.volume): ""); 
      desc += "(Info tick)"
     } 
//--- 返回报价描述
   return(desc); 
  } 

 

另见

CustomRatesDeleteCustomRatesUpdateCustomTicksDeleteCopyTicksCopyTicksRange