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);
      }

また、Periodチェックを追加することができます。

SeriesInfoInteger(_Symbol,ind_period,SERIES_SYNCHRONIZED)
 
アレクセイ・ヴィクトロフ

1.ただ、明確にしておくことがあります。これで、私たちが同じことを話しているのは明らかです。

2.それはわかるが、配列を反転させないとできないのは納得がいかない。2つの端子に対して1つのインジケーターが必要なのでしょうか?2in1を鎌と斧にしたようなものですね。

3.私の理解では、Buffer[]は、関数CopyBuffer() で受信者が1つの指標値だけを取得するために使用します。

4.一番大事なことに目を向けていない。指標値のコピー開始は、バーインデックスではなく、i番目のバーの時刻で判断する必要があります。

1.OKです。

2.私は4からインジケータを書き換えるので、配列を逆にしました - その中ですべてが正常に動作し、すべてのデータが正しいです。その中のすべてが、ループの中で読み込まれる正確な順序でデータを取得することに結び付いている。バッファを反転させないと、インジケータを一から書き直さなければなりませんが、何のために?かなり複雑なんです。この指標を挙げたのは、あくまでネイティブではないCFからデータを取得することがいかに誤りであるかを示す例としてです。

Buffer[]では、ループの繰り返しごとに、AO()から取得した値を1つずつ挿入していきます。

4.コピー開始とはどういう意味ですか?

 
アルチョム・トリシキン

1.良い

2.配列を反転させているのは、4からインジケータを書き換えて いるためで、その中ではすべてが正しく動作し、すべてのデータが正しい。すべては、ループの中で読み込まれる正確な順序でデータを取得することに結び付いている。バッファを反転させないと、インジケータを一から書き直さなければなりませんが、何のために?かなり複雑なんです。この指標を挙げたのは、あくまでも、非ネイティブのGFからデータを取ることがいかに誤りであるかの例としてです。

Buffer[]には、ループ内に1つずつデータが挿入されます。ループの繰り返しごとに、AO()から取得した値が1つずつ挿入されます。

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.あなたのコードで


に変更する必要があります。

"Where do we start from" または "from what date" インジケータ値を受信側配列にコピーする作業を開始します。


ループのインデックスから値を読み取るのに、なぜ日付を渡すのですか?このテストインジケータを実行しましたか?AOは常に、設定で指定されたcurrentfactorの1つだけから引き出されます。現在のタイムフレームをどのように切り替えても、AOチャートは常に設定で設定されたものに対応します。

この場合、すべてのデータが返されますが、私が改造しているインジケータでは、非ネイティブの価格からデータが返されないのです。

このテストインジケータは必要ありません - 非ネイティブの電流からのデータはすでに返されています。しかし、私のところではデータは返ってきませんが、同じように取得できています。


 
アルチョム・トリシキン

ループのインデックスから値を読み取るのに、なぜ日付を渡すのですか?このテストインジケータを実行しましたか?AOは常に1つだけ、つまり設定のsetffからプロットされます。現在のタイムフレームをどのように切り替えても、AOチャートは常に設定で設定されたものに対応します。

この場合、すべてのデータが返されますが、私が改造しているインジケータでは、非ネイティブの価格からデータが返されないのです。

このテストインジケータは必要ありません - 非ネイティブの電流からのデータはすでに返されています。でも、私のはそうじゃなくて、同じようにデータを取得するんです。


なぜなら、ゼロバーのH4には4本のH1バーが含まれているからです。また、期間H1のインデックス2をリクエストすると、期間H4のバー2のインジケータの値が取得されます。

自分が何を書けたのか、ほとんど理解できていない。

現在、13時35分です。現在のH1バーのオープン時間=13:00。バー=1のインデックス、つまり現在のH1期間のバー12:00でインジケータの値をコピーしようとします。しかし、12:00ではなく、8:00の時間帯のH4が表示されます。

H1の場合、最初のバーが12:00

H4の場合、最初のバーは8:00です。

あそこもここも、バーインデックスが先に...。

 
組み込みのArrayCopyは、同じ演算子をバイパスします。
 

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

ハイタイムフレームからインジケーターデータを取得することができない

アルチョム・トリシキン さん 2017.04.14 01:23

4日前から、標準の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言語の特徴、TipsとTricks

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バリアントが機能しない場合があります。もちろん、FXの場合はそうではないでしょう。でも、忘れてはいけないことがあります。したがって、一般的には次のように書けばよいでしょう。
// Альтернатива 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);  
}
//+------------------------------------------------------------------+


 
アレクセイ・コジツィン
いろいろなことを "勘違い "しているのではないでしょうか。ステップバイステップ、ポイントバイポイントで、必要なことを記述してください。

具体的に何が問題なのでしょうか?ネイティブではないタイムフレームからインジケータデータを取得するために、私は何を間違えているのだろうか?という疑問でした。

例:AOのデータはМ5から取得する必要があるのに、インジケーターはМ1で動作している。そのため、limit>1(履歴の再計算が必要)でありながら、M5からのAOはデータエラーがなく0を返します。すべての履歴が計算された(limit=0)時点で、M5を持つAOからのデータが届き始める。

理由: