Array fuori portata in Bisogno di aiuto - pagina 9

 
Aleksei Stepanenko:

Per quanto riguarda ArrayCopyRates, Alexey ha detto correttamente. È scritto nell'aiuto:

Quindi devi scriverlo:

Ma non è un codice economico.

Sì, non ha senso trascinare tutte e 6 le metriche delle barre se ne serve solo una. Basso.

E non ha senso andare in profondità su una scala (TF). Dopo un quarto si può passare alle settimane, poi ai mesi, e 132 mesi, cioè 11 anni.

In generale l'idea è che non ha senso contare su tutto il grafico, la quantità di dati storici è essenzialmente casuale, può essere dall'anno 70 o dal 2000, diversi fornitori di dati hanno dati diversi su diversi strumenti, e la logica è sempre meglio quando è la stessa per tutti i casi.

 

Valery, tu dici esattamente questo!

L'idea è che abbiamo bisogno solo di queste barre di storia:


Il resto può essere eliminato dall'array. Questo è il momento in cui sarebbe economico.

 
Aleksei Stepanenko:

Valery, tu dici esattamente questo!

L'idea è che abbiamo bisogno solo di queste barre di storia:


Il resto può essere eliminato dall'array. Questo è il momento in cui sarebbe economico.

Questo è il modo in cui è stato disegnato. L'idea non è stata ancora espressa da TopekStarter)

Dobbiamo trovare gli estremi significativi per TC e confrontarli. Ci sono molti Low identici a distanza. Molto spesso l'Open e il Close su una candela sono uguali, e cosa dire dei prezzi minimi del giorno a una distanza considerevole.

 

Ho notato un errore nei cicli. E ha cambiato il confronto con ieri invece che con il giorno corrente. Prova

#property version   "1.00"
#property strict

//символ и таймфрейм текущего графика
string symbol;
ENUM_TIMEFRAMES frame;
datetime time=0, current;
int digits;

long ChartId;
int Window;
string Name="MiniMax";

struct BarData
   {
   struct Elem
      {
      int      number;     //порядковый номер периода (дня, месяца или года)
      double   high;       //максимум периода
      double   low;        //минимум периода
      datetime time_high;  //время максимума
      datetime time_low;   //время минимума
      } Arr[];             //массив периода
   int index;              //текущий индекс массива
   double   max;           //последнее максимальное значение периода
   double   min;           //последнее минимальное значение периода
   datetime time_max;      //время максимума
   datetime time_min;      //время минимума

   //при создании структуры указываем, что массив пустой
   BarData(){index=-1;}    
   
   //функция записывает текущие экстремумы
   void WriteBar(int eNumber, string eSymbol, ENUM_TIMEFRAMES eFrame, datetime eTime)
      {
      if(eTime==0) return;
      int eShift=iBarShift(eSymbol,eFrame,eTime);
      double eHigh=iHigh(eSymbol,eFrame,eShift);
      double eLow=iLow(eSymbol,eFrame,eShift);
      //если элементов ещё нет или период сменился
      if(index<0 || eNumber!=Arr[index].number)
         {         
         ArrayResize(Arr,++index+1);
         Arr[index].number=eNumber;
         Arr[index].high=eHigh;
         Arr[index].low=eLow;
         Arr[index].time_high=eTime;
         Arr[index].time_low=eTime;
         if(index==0)
            {
            max=eHigh;
            time_max=eTime;
            min=eLow;
            time_min=eTime;
            }
         }
      //если произошло обновление текущего максимума
      if(eHigh-Arr[index].high>0)
         {
         Arr[index].high=eHigh;
         Arr[index].time_high=eTime;
         }
      //если произошло обновление текущего минимума
      if(Arr[index].low-eLow>0)
         {
         Arr[index].low=eLow;
         Arr[index].time_low=eTime;
         }
      //если произошло обновление предыдущего максимума
      if(index>0)
         {
         max=Arr[index-1].high;
         time_max=Arr[index-1].time_high;
         for(int i=index-2; i>=0; i--)
            {
            if(Arr[i].high-Arr[index-1].high>0)
               {
               max=Arr[i].high;
               time_max=Arr[i].time_high;
               break;
               }
            }
         }
      //если произошло обновление предыдущего минимума
      if(index>0)
         {
         min=Arr[index-1].low;
         time_min=Arr[index-1].time_low;
         for(int i=index-2; i>=0; i--)
            {
            if(Arr[index-1].low-Arr[i].low>0)
               {
               min=Arr[i].low;
               time_min=Arr[i].time_low;
               break;
               }
            }
         }
      }
      
   double GetHigh() {return(index>0?Arr[index-1].high:Arr[index].high);}
   double GetLow() {return(index>0?Arr[index-1].low:Arr[index].low);}
   } day, month, year;

int OnInit()
   {
   symbol=Symbol();
   frame=(ENUM_TIMEFRAMES)Period();
   digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
   //идентификатор графика и номер окна индикатора
   ChartId=ChartID();
   Window=0;
   return(INIT_SUCCEEDED);
   }

void OnTick()
   {
   //текущее время закрытого бара
   current=iTime(symbol,frame,1);

   do
      {    
      MqlDateTime date; 
      TimeToStruct(time,date);
      
      //делаем записи каждого периода
      day.WriteBar(date.day,symbol,frame,time);
      month.WriteBar(date.mon,symbol,frame,time);
      year.WriteBar(date.year,symbol,frame,time);
      
      if(time<current) {time=iTime(symbol,frame,(iBarShift(symbol,frame,time)-1));} else break;
      }
   while(time<=current);
   
   RedrawHLine(ChartId,Window,Name+" High",day.GetHigh(),clrBlue,1,DoubleToString(day.GetHigh(),digits),digits);
   RedrawHLine(ChartId,Window,Name+" Low",day.GetLow(),clrBlue,1,DoubleToString(day.GetLow(),digits),digits);
   RedrawText(ChartId,Window,Name+" High_Text",iTime(symbol,frame,30),day.GetHigh(),"Day 1:  "+DoubleToString(day.GetHigh(),digits),ANCHOR_RIGHT_LOWER,"Arial",8,clrBlue,"",digits);
   RedrawText(ChartId,Window,Name+" Low_Text",iTime(symbol,frame,30),day.GetLow(),"Day 1:  "+DoubleToString(day.GetLow(),digits),ANCHOR_RIGHT_UPPER,"Arial",8,clrBlue,"",digits);

   RedrawHLine(ChartId,Window,Name+" Max",day.max,clrRed,1,DoubleToString(day.max,digits),digits);
   RedrawHLine(ChartId,Window,Name+" Min",day.min,clrRed,1,DoubleToString(day.max,digits),digits);
   RedrawText(ChartId,Window,Name+" Max_Text",iTime(symbol,frame,30),day.max,"Day Max:  "+DoubleToString(day.max,digits),ANCHOR_RIGHT_LOWER,"Arial",8,clrRed,"",digits);
   RedrawText(ChartId,Window,Name+" Min_Text",iTime(symbol,frame,30),day.min,"Day Min:  "+DoubleToString(day.min,digits),ANCHOR_RIGHT_UPPER,"Arial",8,clrRed,"",digits);
   }

//перерисовывает линию по новым координатам, если её нет, то создаёт
void RedrawHLine(long eChartId, int eWindow, string eName, double ePrice, color eColor, int eWidth, string eTooltip, int eDigits)
   {
   if(ObjectFind(eChartId,eName)==-1)
      {
      if(!ObjectCreate(eChartId,eName,OBJ_HLINE,eWindow,0,0)) return;
      ObjectSetInteger(eChartId,eName,OBJPROP_STYLE,STYLE_SOLID);
      ObjectSetInteger(eChartId,eName,OBJPROP_WIDTH,eWidth);
      ObjectSetInteger(eChartId,eName,OBJPROP_BACK,true);
      ObjectSetInteger(eChartId,eName,OBJPROP_SELECTABLE,false);
      ObjectSetInteger(eChartId,eName,OBJPROP_SELECTED,false);
      ObjectSetInteger(eChartId,eName,OBJPROP_HIDDEN,true);
      }
   if(ObjectFind(eChartId,eName)==-1) return;   
   if(NormalizeDouble(ObjectGetDouble(eChartId,eName,OBJPROP_PRICE)-ePrice,eDigits)!=0) ObjectSetDouble(eChartId,eName,OBJPROP_PRICE,ePrice);
   if(ObjectGetInteger(eChartId,eName,OBJPROP_COLOR)!=eColor) ObjectSetInteger(eChartId,eName,OBJPROP_COLOR,eColor);
   if(ObjectGetString(eChartId,eName,OBJPROP_TOOLTIP)!=eTooltip) ObjectSetString(eChartId,eName,OBJPROP_TOOLTIP,eTooltip);
   }

//перерисовываем текст по новым координатам, если его нет, то создаём
void RedrawText(long eChartId, int eWindow, string eName, datetime eTime, double ePrice, string eText, ENUM_ANCHOR_POINT eAnchor, string eFont, int eSize, color eColor, string eTooltip, int eDigits)
   {
   if(ObjectFind(eChartId,eName)==-1)
      {
      if(!ObjectCreate(eChartId,eName,OBJ_TEXT,eWindow,0,0)) return;
      ObjectSetString(eChartId,eName,OBJPROP_FONT,eFont);
      ObjectSetInteger(eChartId,eName,OBJPROP_FONTSIZE,eSize);
      ObjectSetDouble(eChartId,eName,OBJPROP_ANGLE,0.0);
      ObjectSetInteger(eChartId,eName,OBJPROP_ANCHOR,eAnchor);
      //на переднем  плане
      ObjectSetInteger(eChartId,eName,OBJPROP_BACK,false);
      ObjectSetInteger(eChartId,eName,OBJPROP_SELECTABLE,false);
      ObjectSetInteger(eChartId,eName,OBJPROP_SELECTED,false);
      ObjectSetInteger(eChartId,eName,OBJPROP_HIDDEN,true);
      ObjectSetString(eChartId,eName,OBJPROP_TOOLTIP,eTooltip);
      }
   if(ObjectFind(eChartId,eName)==-1) return;
   //координаты метки
   if(ObjectGetInteger(eChartId,eName,OBJPROP_TIME)!=eTime) ObjectSetInteger(eChartId,eName,OBJPROP_TIME,eTime);
   if(NormalizeDouble(ObjectGetDouble(eChartId,eName,OBJPROP_PRICE)-ePrice,eDigits)!=0) ObjectSetDouble(eChartId,eName,OBJPROP_PRICE,ePrice);
   if(ObjectGetInteger(eChartId,eName,OBJPROP_COLOR)!=eColor) ObjectSetInteger(eChartId,eName,OBJPROP_COLOR,eColor);
   if(ObjectGetString(eChartId,eName,OBJPROP_TEXT)!=eText) ObjectSetString(eChartId,eName,OBJPROP_TEXT,eText);
   }
 

Saluti a tutti !!!

Sono stato via per lavoro.

Il processo è in pieno svolgimento.

 

Testato!

Il risultato è il seguente.

Fermato il tester è passato attraverso la storia manualmente. Il valore Max_D dovrebbe essere preso da qui.

 

Non capisco cosa c'è che non va. È una linea di minimo.

Per sicurezza, copiate di nuovo il codice, l'ho cambiato periodicamente, forse avete una vecchia versione

 
Valeriy Yastremskiy:

Sì, non ha senso trascinare tutti e sei gli indicatori della barra se ne serve solo uno. Basso.

E non ha senso andare in profondità su una scala (TF). Dopo un quarto si può passare alle settimane, poi ai mesi, e 132 mesi, cioè 11 anni.

In generale, l'idea che non ha senso contare su tutto il grafico, la quantità di dati storici è essenzialmente casuale, può essere dell'anno 70, e può essere dell'anno 2000, diversi fornitori di dati hanno dati diversi su diversi strumenti, e la logica è sempre migliore quando è la stessa per tutti i casi.

Cercherò di essere più specifico.

1. questa non è un'idea, ma un'esperienza di 5 anni nel trading che ho deciso di automatizzare (cioè non è bene stare seduti al monitor tutto il tempo, lo si capisce con gli anni).

2. Usiamo queste linee per formare un segnale di falsa rottura, e funziona (devi solo sapere come applicarle), potresti non uscirne affatto in futuro.

3. Nel 2020, il 10 febbraio, per la prima volta ho notato questa imprecisione, che voi ritenete inutile da una storia così lontana

Nota dove si trova Min_D e può essere una volta all'anno o anche 10 anni (come risulta ).

Inoltre si vede lo sviluppo di eventi 12000 punti breve (penso che non è accettabile perdere una tale mossa) In questo caso, l'uscita oltre la matrice e non mi ha lasciato perdere questa opportunità.

È così che funziona fino ad oggi e in generale non ha causato alcun problema


Ma ora è il momento di andare avanti e studiare MQL4


4. Per quanto riguarda il carico o qualsiasi cosa ci (una volta al giorno alle 24.00 può essere ricalcolato e 10 volte non commercio il venerdì dopo 20.00, e nei giorni feriali da 23.00 a 3.00) mi lasci contare.

5. l'idea non è ancora stata espressa TopikStarter.

Se si legge dall'inizio del post, non dal centro, tutto è chiaro.

1. Low_D1 e High_D1 (D1 Ultimo giorno), Min_D e Max_D (questo è lo storico più vicino, che è disponibile per il simbolo) Min_D < Low_D1 eMax_D > High_D1

2. Low_W1 e High_W1 (inoltre è simile a quello descritto sopra solo per le settimane)

3. Low_MN1 e High_MN1 (il mese è relativamente simile)

 

Nel codice a per // leggere la descrizione

È venuto per un consiglio su come risolvere il problema, forse qualcosa che non so (come caricare qualche file di storia, o l'array stesso non supporta, o forse 16 giga di aperitivo non è sufficiente, questa è la domanda, ecc)

al momento è solo Alert quando la linea non cambia valore.

//+------------------------------------------------------------------+
//|                                                   Test_Level.mq4 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
double   Bar_data_D1 [][6]; // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров D1
double   Low_D1_Level;      // Возвращает значение минимальной цены бара  D1
double   Min_D_Level ;      // ближайшей минимальный  D уровень
datetime  Time_Day;
int      A_C_R;             // возвращает количество скопированных баров D1
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Level();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
  On_Timer();
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                        Функция Level 
//+------------------------------------------------------------------+
void Level()
{
  A_C_R = ArrayCopyRates(Bar_data_D1,_Symbol,PERIOD_D1); // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров

 Low_D1_Level   = iLow (_Symbol,PERIOD_D1,1);   // Возвращает значение минимальной цены бара  D1
    
//--- Min_D_Leve  
 //for(int i = 1; i<ArrayRange(Bar_data_D1,0) ;i++) // или так то ошибки нет и линия не перерисовывается 
   for(int i = 1; ;i++)                             // а так выход за массив 
    {
     Print(" i = ",i," Bar_data_D1 [i][2] = ",Bar_data_D1 [i][2]);
     if(Bar_data_D1 [i][2]>=0)
       {
        if( Bar_data_D1 [i][2] < Low_D1_Level)
          {
           Min_D_Level = Bar_data_D1 [i][2];break;
          }
       }   
    } 

 //+-------------------------Low_D1_Level----------------------------+ 
 if(ObjectFind("Low_D1")!=Low_D1_Level) 
   {
    ObjectDelete("Low_D1");
    if(ObjectFind("Low_D1")!=0)
      {
       ObjectCreate("Low_D1",OBJ_HLINE, 0, Time[0],Low_D1_Level);
       ObjectSet("Low_D1", OBJPROP_COLOR, clrMaroon);
       ObjectSet("Low_D1", OBJPROP_WIDTH, 1);
      }
   } 
   
 if(ObjectFind("Low_D1_label")!=Low_D1_Level)
   {
    ObjectDelete("Low_D1_label"); 
    if(ObjectFind("Low_D1_label") != 0)
      {
       ObjectCreate("Low_D1_label", OBJ_TEXT, 0, Time[13], Low_D1_Level);
       ObjectSetText("Low_D1_label", "Low_D1: " + DoubleToStr(Low_D1_Level,_Digits), 8,"Verdana", Brown);
      }
   } 
   
 //+-------------------------Min_D_Level----------------------------+ 
 if(ObjectFind("Min_D")!= Min_D_Level) 
   {
    ObjectDelete("Min_D");
    if(ObjectFind("Min_D")!=0)
      {
       ObjectCreate("Min_D",OBJ_HLINE, 0, Time[0],Min_D_Level);
       ObjectSet("Min_D", OBJPROP_COLOR, clrMaroon);
       ObjectSet("Min_D", OBJPROP_WIDTH, 1);
      }
   } 
   
 if(ObjectFind("Min_D_label")!=Min_D_Level)
   {
    ObjectDelete("Min_D_label"); 
    if(ObjectFind("Min_D_label") != 0)
      {
       ObjectCreate("Min_D_label", OBJ_TEXT, 0, Time[30], Min_D_Level);
       ObjectSetText("Min_D_label", "Min_D: " + DoubleToStr(Min_D_Level,_Digits), 8,"Verdana", Brown);
      }
   }  
 
}
//+------------------------------------------------------------------+
//|        функция удаление всех объектов созданных советником
//+------------------------------------------------------------------+
void DestroyObject()
{
 int tot=ObjectsTotal();
 for( int i=tot; i>=0; i--)
    {
     
     if(ObjectName(i)=="Low_MN1"){ObjectDelete(0,"Low_MN1");Print("<< Объект Low_MN удалён >>");}
     if(ObjectName(i)=="Low_MN1_label"){ObjectDelete(0,"Low_MN1_label");Print("<< Объект Low_MN1_label удалён >>");}
     

     if(ObjectName(i)=="Min_D"){ObjectDelete(0,"Min_D");Print("<< Объект Min_D удалён >>");}
     if(ObjectName(i)=="Min_D_label"){ObjectDelete(0,"Min_D_label");Print("<< Объект Min_D_label удалён >>");}


   }
}
//+-------------------------------------------------------------------------+   
//                         функция Timer                    
//+-------------------------------------------------------------------------+
void On_Timer()
{

     
 if(Day()!= Time_Day)
   {
    Level();
    Time_Day = Day();
   }
}
 
Aleksei Stepanenko:

Non capisco cosa c'è che non va. È una linea di minimo.

Per sicurezza, copiate di nuovo il codice, l'ho cambiato periodicamente, forse avete una vecchia versione

Ok, ci riprovo.