CustomTicksAdd

添加MqlTick类型的数组数据到自定义交易品种的价格历史。自定义交易品种一定要在市场报价窗口来选择

int  CustomTicksAdd(
   const string     symbol,             // 交易品种名称
   const MqlTick&   ticks[],            // 应该应用于自定义交易品种的报价数据数组
   uint             count=WHOLE_ARRAY   // 即将使用的ticks[]数组元素的数量
   );

参数

交易品种

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

ticks[]

[in]   MqlTick类型的报价数据数组按照从早期到最近的顺序排列,例如ticks[k].time_msc <= ticks[n].time_msc,if k<n。

count=WHOLE_ARRAY

[in]  即将用于添加的ticks[]数组元素的数量。WHOLE_ARRAY意味着所有ticks[]数组元素都应被使用。

返回值

添加报价的数量,错误情况下为-1。

进一步注释

CustomTicksAdd函数只能用于在市场报价窗口打开的自定义交易品种。如果没有在市场报价窗口选择交易品种,您应该使用CustomTicksReplace添加报价。

CustomTicksAdd函数允许按照在交易商服务器上交付的模式传递报价。数据发送至市场报价来代替直接写入报价数据库。然后程序端将来自市场报价的价格保存到数据库。如果函数调用期间传递的数据量过于庞大,函数处理会发生变化以减少资源使用率。如果传递超过256个报价,数据将被分为两个部分。第一部分,即数据量大的部分直接写入报价数据库(如同CustomTicksReplace函数的操作)。第二部分包含128个报价,被传递到市场报价窗口,程序端在这里将报价保存到数据库。

MqlTick结构有两个时间值字段:time (以秒表示的报价时间)和 time_msc (以毫秒表示的报价时间),从1970年1月1日开始计算。添加报价的这些字段按照以下顺序进行处理:

  1. 如果ticks[k].time_msc!=0,我们用它来填写ticks[k].time字段,例如为报价设置 ticks[k].time=ticks[k].time_msc/1000(整除)
  2. 如果ticks[k].time_msc==0 并且 ticks[k].time!=0,那么将乘以1000来获得毫秒表示的时间,例如ticks[k].time_msc=ticks[k].time*1000
  3. 如果ticks[k].time_msc==0和ticks[k].time==0,那么将调用CustomTicksAdd函数时当前交易服务器的毫秒时间写入这些字段。

如果ticks[k].bid,ticks[k].ask,ticks[k].last或ticks[k].volume的数值大于零,那么将适当的标识组合写入ticks[k].flags 字段:

  • TICK_FLAG_BID – 报价已更改卖价
  • TICK_FLAG_ASK  – 报价已更改买价
  • TICK_FLAG_LAST – 报价已更改最后交易价
  • TICK_FLAG_VOLUME – 报价已更改交易量

如果字段的值小于或等于零,对应的标识将不写入ticks[k].flags字段。

 

自定义交易品种历史记录不添加TICK_FLAG_BUY and TICK_FLAG_SELL标识。

 

示例:

//+------------------------------------------------------------------+
//|                                               CustomTicksAdd.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].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 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]));
     }
 
//--- 在图表注释区显示脚本终止键的提示
   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 download tick history for the symbol 'EURUSD'
   The tick history for the 'EURUSDsymbol is received in the amount of 351183943 ticks in 56454 ms
   First tick time2011.12.19 00:00:08.000Last tick time2024.06.20 21:18:12.010
   
   The last 20 ticks for the standard symbol 'EURUSD':
     351183923th Tick2024.06.20 21:17:46.380 Bid=1.07124 (Info tick)
     351183924th Tick2024.06.20 21:17:47.779 Ask=1.07125 Bid=1.07125 (Info tick)
     351183925th Tick2024.06.20 21:17:48.584 Ask=1.07124 Bid=1.07124 (Info tick)
     351183926th Tick2024.06.20 21:17:49.481 Ask=1.07125 (Info tick)
     351183927th Tick2024.06.20 21:17:49.985 Ask=1.07122 Bid=1.07122 (Info tick)
     351183928th Tick2024.06.20 21:17:50.482 Ask=1.07124 Bid=1.07124 (Info tick)
     351183929th Tick2024.06.20 21:17:51.584 Ask=1.07123 Bid=1.07123 (Info tick)
     351183930th Tick2024.06.20 21:17:52.786 Ask=1.07124 Bid=1.07124 (Info tick)
     351183931th Tick2024.06.20 21:17:53.487 Ask=1.07125 Bid=1.07125 (Info tick)
     351183932th Tick2024.06.20 21:17:53.989 Ask=1.07126 Bid=1.07126 (Info tick)
     351183933th Tick2024.06.20 21:17:55.789 Ask=1.07125 Bid=1.07125 (Info tick)
     351183934th Tick2024.06.20 21:17:58.495 Ask=1.07126 Bid=1.07126 (Info tick)
     351183935th Tick2024.06.20 21:18:00.102 Bid=1.07126 (Info tick)
     351183936th Tick2024.06.20 21:18:00.698 Ask=1.07129 Bid=1.07129 (Info tick)
     351183937th Tick2024.06.20 21:18:03.699 Bid=1.07129 (Info tick)
     351183938th Tick2024.06.20 21:18:04.699 Ask=1.07128 Bid=1.07128 (Info tick)
     351183939th Tick2024.06.20 21:18:05.901 Ask=1.07129 Bid=1.07129 (Info tick)
     351183940th Tick2024.06.20 21:18:07.606 Ask=1.07128 Bid=1.07128 (Info tick)
     351183941th Tick2024.06.20 21:18:11.512 Ask=1.07127 Bid=1.07127 (Info tick)
     351183942th Tick2024.06.20 21:18:12.010 Ask=1.07126 Bid=1.07126 (Info tick)
   ...
   Start of adding 351183943 ticks to the history of the custom symbol 'EURUSD.C'
   Added 351183943 ticks to the history of the custom symbol 'EURUSD.Cin 269890 ms
   ...
   Requested 351183943 ticks to download tick history for the symbol 'EURUSD.C'
   The tick history for the 'EURUSD.Csymbol is received in the amount of 351183943 ticks in 116407 ms
   First tick time2011.12.19 00:00:08.000Last tick time2024.06.20 21:18:12.010
   
   The last 20 ticks for the custom symbol 'EURUSD.C':
     351183923th Tick2024.06.20 21:17:46.380 Ask=1.07124 Bid=1.07124 (Info tick)
     351183924th Tick2024.06.20 21:17:47.779 Ask=1.07125 Bid=1.07125 (Info tick)
     351183925th Tick2024.06.20 21:17:48.584 Ask=1.07124 Bid=1.07124 (Info tick)
     351183926th Tick2024.06.20 21:17:49.481 Ask=1.07125 Bid=1.07125 (Info tick)
     351183927th Tick2024.06.20 21:17:49.985 Ask=1.07122 Bid=1.07122 (Info tick)
     351183928th Tick2024.06.20 21:17:50.482 Ask=1.07124 Bid=1.07124 (Info tick)
     351183929th Tick2024.06.20 21:17:51.584 Ask=1.07123 Bid=1.07123 (Info tick)
     351183930th Tick2024.06.20 21:17:52.786 Ask=1.07124 Bid=1.07124 (Info tick)
     351183931th Tick2024.06.20 21:17:53.487 Ask=1.07125 Bid=1.07125 (Info tick)
     351183932th Tick2024.06.20 21:17:53.989 Ask=1.07126 Bid=1.07126 (Info tick)
     351183933th Tick2024.06.20 21:17:55.789 Ask=1.07125 Bid=1.07125 (Info tick)
     351183934th Tick2024.06.20 21:17:58.495 Ask=1.07126 Bid=1.07126 (Info tick)
     351183935th Tick2024.06.20 21:18:00.102 Ask=1.07126 Bid=1.07126 (Info tick)
     351183936th Tick2024.06.20 21:18:00.698 Ask=1.07129 Bid=1.07129 (Info tick)
     351183937th Tick2024.06.20 21:18:03.699 Ask=1.07129 Bid=1.07129 (Info tick)
     351183938th Tick2024.06.20 21:18:04.699 Ask=1.07128 Bid=1.07128 (Info tick)
     351183939th Tick2024.06.20 21:18:05.901 Ask=1.07129 Bid=1.07129 (Info tick)
     351183940th Tick2024.06.20 21:18:07.606 Ask=1.07128 Bid=1.07128 (Info tick)
     351183941th Tick2024.06.20 21:18:11.512 Ask=1.07127 Bid=1.07127 (Info tick)
     351183942th Tick2024.06.20 21:18:12.010 Ask=1.07126 Bid=1.07126 (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); 
  } 

 

另见

CustomRatesDeleteCustomRatesUpdateCustomTicksReplaceCopyTicksCopyTicksRange