测试 "CopyTicks"。 - 页 41

 
遇到一个bug,CopyTicksRange正确地返回所有请求的ticks,但LastError == ERR_HISTORY_TIMEOUT(4403)。


 
fxsaber:

tkc文件是按月划分的。因为这个问题而产生的问题

  1. 如果终端还没有上传tick数据,当你调用CopyTicks时,终端如何知道要提取哪些kc文件?
每月提取,从当前月份开始。
  1. CopyTicksRange是基于CopyTicks还是独立实现的?
基于CopyTicks,即根本没有优化。
  1. 我是否可以这样理解,例如,通过CopyTicksRange获取9月份的ticks,总是比通过CopyTicks要快,因为CopyTicks不知道通过输入参数,应该提取哪个月份的数据?

不,CopyTicksRange也会一样慢,因为上面的观点。这里有一个脚本,显示了目前CopyTicksRange实现的一些荒谬之处

#define  TOSTRING(A) #A + " = " + (string)(A)

void OnStart()
{  
  
  MqlTick Ticks[];
  
  ResetLastError();
  
  Print(__FUNCTION__);
  Print(TOSTRING(CopyTicksRange(_Symbol, Ticks, COPY_TICKS_ALL, 1, 2)));
  Print(TOSTRING(_LastError));
}

它似乎清楚地给出了必须拉出哪些tkc文件的信息。但是没有,它将以与CopyTicks相同的方式拉动--所有的Tkc-文件。而且它将因超时而停止工作。但实际上,它应该几乎立刻就能发挥作用。

  1. 你需要尽快将历史数据纳入指标。可以通过CopyTicksRange请求,得到一个-1,直到所有的东西都下载完毕。而如果你按月申请:本月,然后是上月,等等。它不会更慢,但指标将准备好工作,至少有一些历史。对吗?

事实证明,没有区别(见上文各点)。

 

如果UninitializeReason !=REASON_CHARTCHANGE,CopyTicks在OnDeinit中不起作用。

#define  TOSTRING(A) (#A + " = " + (string)(A))

void TickTest()
{
  MqlTick Ticks[];

  ResetLastError();
  Print(TOSTRING(CopyTicks(_Symbol, Ticks)));
  Print(TOSTRING(_LastError));
}

void OnInit()
{
  Print("\n" + __FUNCTION__);
  
  TickTest();
}

void OnDeinit( const int )
{
  Print("\n" + __FUNCTION__);
  Print(TOSTRING(UninitializeReason()));
  
  TickTest();
}


结果(删除专家顾问后)。

OnInit
CopyTicks(_Symbol,Ticks) = 2000
_LastError = 0

OnDeinit
UninitializeReason() = 1
CopyTicks(_Symbol,Ticks) = -1
_LastError = 4401


这发生在专家顾问系统中。在指标中,CopyTicks在OnDeinit中正常工作。

 
当你改变账户(到另一个交易服务器)时,我们需要将旧账户的最后2000点写入文件中。如何做到这一点?


这是不可能的。

void OnDeinit( const int )
{
  MqlTick Ticks[];

  CopyTicks(_Symbol, Ticks); // Если была смена торгового сервера, то БД-тиков поменялась

  FileSave(__FILE__, Ticks);
}


请在账户变更前生成CHARTEVENT_ACCOUNTCLOSING事件,当处理它时(在OnChartEvent中),所有的交易环境还没有切换到新的环境。

 
fxsaber:
当改变账户(另一个交易服务器)时,有必要将旧账户的最后2000点写入文件中。我如何做到这一点?


这是不可能的。


在改变账户之前,请生成CHARTEVENT_ACCOUNTCLOSING事件,当处理它时(在OnChartEvent),整个交易环境还没有切换到新的环境。

聪明的是,我们应该添加一个反馈,就像在Windows中那样。

以图表(或非图表)事件中的标志的形式,当设置它时,事件本身(在这种情况下,账户切换)被取消了。

 

让它突然,但令人讨厌的是,几十个bug报告,他们得到了修复,而新的bug却不断出现在这个CopyTicks上。

这样的小把戏让我很累。

#define  TOSTRING(A) (#A + " = " + (string)(A))

void OnStart()
{
  MqlTick Ticks[];

  if (CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, 0, 131072 + 1) > 0) // Если прибавлять не единицу, а ноль, то все будет работать
  {
    const ulong BeginTime = Ticks[0].time_msc;
    
    Print(TOSTRING(CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, BeginTime, LONG_MAX)));
    Print(TOSTRING(CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, BeginTime, (TimeCurrent() + 1) * 1000)));
  }
}


结果

CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,LONG_MAX) = 0
CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,(TimeCurrent()+1)*1000) = 131073


从源代码中删除一个

CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,LONG_MAX) = 131072
CopyTicksRange(_Symbol,Ticks,COPY_TICKS_INFO,BeginTime,(TimeCurrent()+1)*1000) = 131072


在不同的角色和贸易服务器上重现。在休息日检查了一下--报价者是站着的。


这条线上的虫子什么时候能被打败?

 

的确,这种语言中的有趣功能,而且开箱即用......。

这里有一个问题。我通过符号菜单手动下载了刻度线(685,007刻度线)。我需要EURUSD从2016.11.01 00:00到2016.11.08 00:00。下面是一个截图。



我是以编程方式提出请求的,像这样。

void OnStart()
  {
   string symbol="EURUSD";
   MqlTick ticks_array[];
   uint flags=COPY_TICKS_INFO;
   ulong from_msc,to_msc;
   from_msc=(ulong)D'01.11.2016 00:00';
   to_msc=(ulong)D'08.11.2016 00:00';
//--- получить тики - 20 попыток
   for(int att=0;att<20;att++)
     {
      int copied=CopyTicksRange(symbol,ticks_array,flags,from_msc,to_msc);
      if(copied>0)
         break;
      Sleep(100);
     }
//--- остановка
   DebugBreak();
  }


输出是0。什么是错的?

 
Dennis Kirichenko:

输出是0,怎么了?

乘以1000从和到。

 
fxsaber:

乘以1,000从和到。


惭愧,我弄错了。谢谢你,伙计。

 
损失了大量的时间来本地化这个错误 CopyTicksRange


template <typename T>
T MyPrint( const T Value, const string Str )
{
  static const bool IsDebug = MQLInfoInteger(MQL_DEBUG);

//  if (IsDebug)
  {
//    DebugBreak(); // если хочется посмотреть средствами дебага

    Print(Str + " = " + (string)Value);
  }
  
  return(Value);
}

#define _P(A) MyPrint(A, __FUNCSIG__ ", Line = " + (string)__LINE__ + ": " + #A)

int GetSymbolTicks( const string Symb, MqlTick &Ticks[] )
{
  const bool Selected = SymbolInfoInteger(Symb, SYMBOL_SELECT);

  const int Amount = SymbolInfoInteger(Symb, SYMBOL_CUSTOM) && (Selected || SymbolSelect(Symb, true)) ? _P(CopyTicksRange(Symb, Ticks, COPY_TICKS_INFO)) : -1; // здесь баг!
  
  if (!Selected)
    SymbolSelect(Symb, false);

  return(Amount);
}

bool TicksToSymbol( const string Symb, const MqlTick &Ticks[] )
{
  const int Size = ArraySize(Ticks);
  
  CustomTicksDelete(Symb, Ticks[0].time_msc, Ticks[Size - 1].time_msc);
  
  return(Size ? (_P(CustomTicksReplace(Symb, Ticks[0].time_msc, Ticks[Size - 1].time_msc, Ticks)) > 0) : false);
}

void OnStart()
{
  MqlTick Ticks[];
    
  if (CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, D'2017.12.01' * 1000, (TimeCurrent() + 1) * 1000) > 100) // Если поставить сегодня - D'2017.12.05', то баг не проявится
  {
    ArrayResize(Ticks, 100);
    
    static const string Name = _Symbol + "_Custom";
    
    CustomSymbolDelete(Name);
    
    if (CustomSymbolCreate(Name) && CustomSymbolSetInteger(Name, SYMBOL_DIGITS, _Digits))
    {    
      TicksToSymbol(Name, Ticks);
    
      MqlTick Ticks2[];
      
      GetSymbolTicks(Name, Ticks2);
    }

    CustomSymbolDelete(Name);
  }
}

EURUSD M1 MetaQuotes-Demo上第一次运行后,我们得到了一个正确的结果

bool TicksToSymbol(const string,const MqlTick&[]), Line = 36: CustomTicksReplace(Symb,Ticks[0].time_msc,Ticks[Size-1].time_msc,Ticks) = 100
int GetSymbolTicks(const string,MqlTick&[]), Line = 22: CopyTicksRange(Symb,Ticks,COPY_TICKS_INFO) = 100


接下来的所有运行将显示一个错误

bool TicksToSymbol(const string,const MqlTick&[]), Line = 36: CustomTicksReplace(Symb,Ticks[0].time_msc,Ticks[Size-1].time_msc,Ticks) = 100
int GetSymbolTicks(const string,MqlTick&[]), Line = 22: CopyTicksRange(Symb,Ticks,COPY_TICKS_INFO) = 0


重新加载终端后,情况会重复出现:第一次运行--良好,接下来的运行--错误。


SZY 注意来源中的突出评论!