mql5语言的特点、微妙之处以及技巧 - 页 32

 

我检查指标是否准备好了(在OnCalculate 的开头)。

   int calculated=BarsCalculated(IND_handle);
   if(calculated<=0 || !SymbolIsSynchronized(_Symbol) || rates_total<=0 || rates_total-prev_calculated<0) 
      { 
      Comment("Calculate...");
      return(0);
      }

你也可以添加一个周期检查

SeriesInfoInteger(_Symbol,ind_period,SERIES_SYNCHRONIZED)
 
阿列克谢-维克多罗夫

1.只是澄清一下。现在很清楚,我们说的是同一件事。

2) 我理解,但我不同意你必须翻转数组来做这件事。是否有必要为两个终端配备一个指标?这几乎是把镰刀和斧头合二为一。

3.据我所知,Buffer[]在函数CopyBuffer() 中被接收器使用,只获得一个指标值。

4.你没有注意到最重要的事情。拷贝指标值的开始不应该由条形指数决定,而是由第i个条形的时间决定。

1.好的。

2.我颠倒了数组,因为我从四个方面重写了指标--在其中一切工作正常,所有数据都是正确的。其中的一切都与按照循环中读取数据的确切顺序获取数据有关。如果我们不翻转缓冲区,我们将不得不从头开始写指标--为了什么?这是很复杂的。我引用这个指标只是作为一个例子,说明从一个非本地人那里获得数据是多么的错误。

不,在Buffer[]中,数据是一个一个地插入到循环中的--在循环的每个迭代中,从AO()中取出的一个值被插入。

4.你说的 "开始复制 "是什么意思?

 
阿尔乔姆-特里什金

1.良好。

2.我之所以翻转数组,是因为我正在从四个方面重写指标--在其中一切工作正常,所有数据都是正确的。一切都与按照循环中读取数据的确切顺序获取数据联系在一起。如果我们不翻转缓冲区,我们将不得不从头开始写指标--为了什么?这是很复杂的。我引用这个指标只是作为一个例子,说明从一个非本地人那里获得数据是多么的错误。

不,在Buffer[]中,数据被逐一插入循环中--在循环的每个迭代中,从AO()中获取的一个值被插入。

4.你说的 "开始复制 "是什么意思?

2.没有什么能阻止你建立一个从0到rate_total-1的循环。

3.是的,我在什么地方搞错了。

4.

double AO(int shift){
   double array[];
   ArrayResize(array,1);
   ArrayInitialize(array,EMPTY_VALUE);
   error=ERR_SUCCESS;
   ResetLastError();
   if(CopyBuffer(handle,0,shift,1,array)==1) {
      ArraySetAsSeries(array,false);
      return(array[0]);
      }
   else error=GetLastError();
   return(EMPTY_VALUE);
}


int  CopyBuffer(
   int       indicator_handle,     // handle индикатора
   int       buffer_num,           // номер буфера индикатора
   int       start_pos,            // откуда начнем 
   int       count,                // сколько копируем
   double    buffer[]              // массив, куда будут скопированы данные
   );

应改成

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );

"从哪里开始 "或 "从什么日期开始",这是开始将指标值复制到接收器阵列中。


 
阿列克谢-维克多罗夫

3.是的,我在某个地方搞乱了一些东西。

4.在你的代码中。


应改成

"我们从哪里开始 "或 "从什么日期开始",这是开始将指标值复制到接收器阵列中。


如果我从循环索引中读取数值,为什么要传递日期?你有没有运行这个测试指标?它总是只从一个--设置中指定的电流因子--中提取AO。无论你如何切换当前的时间框架,AO图总是与你在设置中设置的时间框架相对应。

在这种情况下,所有的数据都被返回,但在我正在修改的指标中,数据没有从非本地价格返回。

你不需要这个测试指标--来自非本地电流的数据已经被返回。但在我的数据没有返回,但我以同样的方式得到它们。


 
阿尔乔姆-特里什金

如果我从循环索引中读取数值,为什么要传递日期?你有没有运行这个测试指标?它总是只从一个--设置中的setff来绘制AO。无论你如何切换当前的时间框架,AO图总是与你在设置中设置的时间框架相对应。

在这种情况下,所有的数据都被返回,但在我正在修改的指标中,数据没有从非本地价格返回。

你不需要这个测试指标--来自非本地电流的数据已经被返回。但我的没有,但我以完全相同的方式获得数据。


因为零条H4包含四个H1条。如果你要求H1期的指数2,你会得到H4期第2条的指标值。

我几乎不明白我能够写什么。

目前是13:35。当前H1条的开放时间=13:00。你试图通过bar=1的索引复制指标值,即当前H1期的12:00条。但在H4时段,你得到的不是12:00,而是8:00。

对于H1来说,第一条是12:00

对于H4,第一个小节是8:00

那里和那里的酒吧指数都是第一...

 
内置的ArrayCopy绕过了同样的运算符。
 

关于交易、自动交易系统和测试交易策略的论坛

我无法从高时间框架中获得指标数据

Artyom Trishkin, 2017.04.14 01:23

四天来,我一直试图从指标中的高级时间框架中获取标准AO指标的数据,但仍然没有办法...

我在循环中读取AO数据,但正是在循环中没有历史数据。当前栏上有数据。问题是什么?我做错了什么?

//+------------------------------------------------------------------+
//|                                                       MTF AO.mq5 |
//|              Copyright 2017, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot AO
#property  indicator_label1  "AO MTF"
#property  indicator_type1   DRAW_SECTION
#property  indicator_color1  clrRed
#property  indicator_style1  STYLE_SOLID
#property  indicator_width1  1

//--- indicator buffers
double         BufferAO[];
//+------------------------------------------------------------------+
//|  Enums                                                           |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|  Input Variables                                                 |
//+------------------------------------------------------------------+
sinput   ENUM_TIMEFRAMES   PeriodForWork  =  PERIOD_M5;  // Таймфрейм, на котором искать дивергенции
//+------------------------------------------------------------------+
//|  Global Variables                                                |
//+------------------------------------------------------------------+
string            Prefix, symbol;
int               handle_ao;                 // Хэндл AO
int               size_ao=0;                 // Количество скопированных данных AO
double            array_ao[];                // Массив данных АО
ENUM_TIMEFRAMES   periodForWork;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferAO);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   ArrayInitialize(BufferAO,0);
   
   //--- проверка рабочего периода и его смена, если выбран рабочий период меньше текущего
   periodForWork=PeriodForWork;
   if(Period()>periodForWork && PeriodForWork!=PERIOD_CURRENT) {
      Alert("Выбран не корректный период: ",GetNameTF(PeriodForWork),"\nМеняю рабочий период на ",GetNameTF(Period()));
      periodForWork=PERIOD_CURRENT;//GetTFasEnum(Period());
      }

   //--- имена
   symbol=Symbol();                                                        // Symbol()
   Prefix="MTFdiv";                                                        // Префикс имён объектов
   IndicatorSetString(INDICATOR_SHORTNAME,Prefix);                         // Короткое имя индикатора
   
   //--- хэндл AO
   handle_ao=iAO(symbol,periodForWork);
   if(handle_ao==INVALID_HANDLE) {
      Print("Не удалось создать хэндл AO");
      return(INIT_FAILED);
      }
   int count=(int)SeriesInfoInteger(symbol,periodForWork,SERIES_BARS_COUNT);
   size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- delete graphics
   ObjectsDeleteAll(0,Prefix);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   ArraySetAsSeries(BufferAO,true);
   ArraySetAsSeries(array_ao,true);
   //---
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
   
   int count=(int)SeriesInfoInteger(symbol,periodForWork,SERIES_BARS_COUNT);
   //---
   if(rates_total<1) return(0);
   //---
   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-1;
      ArrayInitialize(BufferAO,0);
      }
   
   int periodSeconds=PeriodSeconds(periodForWork); // Количество секунд в рабочем периоде
   static datetime lastTime=0;
   int bar_first=TerminalInfoInteger(TERMINAL_MAXBARS);
   //--- основной цикл индикатора
   for(int i=limit; i>=0; i--) {
      //--- Пропускаем отсутствующие бары
      if(i>bar_first) continue;
      
      //--- Получаем данные АО
      ResetLastError();
      size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);
      if(size_ao<0) Print("Ошибка копирования данных AO ",GetLastError());
      
      //--- время открытия бара на рабочем периоде, соответствующее времени бара i на текущем периоде
      datetime timePeriod=GetTimeOpen(symbol,periodForWork,i);
      //--- если нашли открытие нового бара на рабочем таймфрейме (текущее время больше прошлого)
      if(timePeriod>0 && timePeriod>lastTime) { 
         //---
         datetime time_work=GetTimeOpen(symbol,periodForWork,i);                 // время открытия i на рабочем таймфрейме
         int bar_work_to_current=GetBarShift(symbol,PERIOD_CURRENT,time_work);   // бар открытия времени time_work на текущем периоде графика
         double ao_work=GetDataAO(time_work);                                    // значение АО на баре i
         //---
         if(i<5) {
            Print("Work period: ",GetNameTF(periodForWork),
                  ",i=",i,", bar_work_to_current=",bar_work_to_current,
                  ", time_work=",TimeToString(time_work,TIME_MINUTES),
                  ", ao_work=",DoubleToString(ao_work,Digits())
                 );
            }
         BufferAO[bar_work_to_current]=ao_work;
         //--- конец обработки текущего бара
         lastTime=timePeriod; // запомним прошлое время для дальнейшего сравнения с временем следующего бара
         }
      //--- конец цикла индикатора
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Functions                                                        |
//+------------------------------------------------------------------+
double GetDataAO(int shift) {
   double array[1];
   if(CopyBuffer(handle_ao,0,shift,1,array)==1) return(array[0]);
   return(0);
}
//+------------------------------------------------------------------+
double GetDataAO(datetime shift) {
   double array[1];
   if(CopyBuffer(handle_ao,0,shift,1,array)==1) return(array[0]);
   return(0);
}
//+------------------------------------------------------------------+
datetime GetTimeOpen(string symbol_name, ENUM_TIMEFRAMES timeframe, int index) {
   datetime array[1]={-1};
   ResetLastError();
   if(CopyTime(symbol_name,timeframe,index,1,array)==1) return(array[0]);
   Print(__FUNCTION__," > Ошибка получения времени бара ",index,"(",GetNameTF(timeframe),"): ",GetLastError());
   return(-1);
}
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   datetime last_bar;
   if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
      if(time>last_bar) res=0;
      else {
         const int shift=Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
}
//+------------------------------------------------------------------+
string GetNameTF(int timeframe=PERIOD_CURRENT) {
   if(timeframe==PERIOD_CURRENT) timeframe=Period();
   switch(timeframe) {
      //--- MQL4
      case 1: return("M1");
      case 5: return("M5");
      case 15: return("M15");
      case 30: return("M30");
      case 60: return("H1");
      case 240: return("H4");
      case 1440: return("D1");
      case 10080: return("W1");
      case 43200: return("MN");
      //--- MQL5
      case 2: return("M2");
      case 3: return("M3");
      case 4: return("M4");      
      case 6: return("M6");
      case 10: return("M10");
      case 12: return("M12");
      case 16385: return("H1");
      case 16386: return("H2");
      case 16387: return("H3");
      case 16388: return("H4");
      case 16390: return("H6");
      case 16392: return("H8");
      case 16396: return("H12");
      case 16408: return("D1");
      case 32769: return("W1");
      case 49153: return("MN");      
      default: return("UnknownPeriod");
   }
}
//+------------------------------------------------------------------+


 
阿尔乔姆-特里什金

在我看来,你做了很多 "错误 "的事情。请描述需要做的事情:按顺序,逐点说明。
 

关于交易、自动交易系统和交易策略测试的论坛

mql5语言的特点、技巧和窍门

fxsaber, 2017.02.27 18:40

谢谢你的提示!在野外,它是SymbolInfoMarginRate。所以现在是这样的
// Размер свободных средств, необходимых для открытия 1 лота на покупку
double GetMarginRequired( const string Symb )
{
  MqlTick Tick;
  double MarginInit, MarginMain;

  return((SymbolInfoTick(Symb, Tick) && SymbolInfoMarginRate(Symb, ORDER_TYPE_BUY, MarginInit, MarginMain)) ? MarginInit * Tick.ask *
          SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE) / (SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0);
}

我们需要明确的是,在MT5中,不同方向的保证金要求可能有很大不同。也就是说,单一的MT4变体可能无法工作。当然,在外汇市场上,情况不会是这样的。但你必须记住。因此,一般来说,你应该这样写
// Альтернатива OrderCalcMargin
bool MyOrderCalcMargin( const ENUM_ORDER_TYPE action, const string symbol, const double volume, const double price, double &margin )
{
  double MarginInit, MarginMain;

  const bool Res = SymbolInfoMarginRate(symbol, action, MarginInit, MarginMain);
  
  margin = Res ? MarginInit * price * volume * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE) /
                 (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0;
  
  return(Res);  
}

高亮显示的 可以返回0。BKS遇到了这个问题。

像这样做了。

//+------------------------------------------------------------------+
//| Альтернатива стандартному OrderCalcMargin()                      |
//+------------------------------------------------------------------+
//--- 
bool CGetClass::OrderCalcMargin(const ENUM_ORDER_TYPE action,const string symbol_name,const double volume,const double price,double &margin){
   double margin_init=0,margin_main=0;
   const bool res=SymbolInfoMarginRate(symbol_name,action,margin_init,margin_main);
   int liverage=int(AccountInfoInteger(ACCOUNT_LEVERAGE)==0?1:AccountInfoInteger(ACCOUNT_LEVERAGE));
   margin=res?margin_init*price*volume*SymbolInfoDouble(symbol_name,SYMBOL_TRADE_TICK_VALUE)/
                 (SymbolInfoDouble(symbol_name,SYMBOL_TRADE_TICK_SIZE)*liverage):0;
   
   return(res);  
}
//+------------------------------------------------------------------+


 
阿列克谢-科齐岑
我认为你做的很多事情都是 "错误的"。请描述你需要做什么:一步一步,一点一点。

究竟哪里出了问题?这就是问题所在--我做错了什么,才会从一个非本地的时间框架中获得指标数据?

例如:指标在М1上运行,而AO的数据应该从М5上获得。因此,当我们有极限>1(历史需要重新计算)时,来自M5的AO返回零,没有数据错误。一旦所有的历史被计算出来(limit==0),那么带有M5的AO的数据就会开始到达。