Dovremmo cercare di evitare cicli inutili. Abbiamo una marea di citazioni, ed è necessario fare le voci giuste al volo, in modo da non dover scavare nella storia e sprecare risorse del computer.
Mi sento come un bambino di prima elementare, anche se ho 42 anni.
Dovremmo cercare di evitare i loop inutili. Abbiamo citazioni che arrivano a fiumi, e abbiamo bisogno di fare le voci giuste al volo, in modo da non dover scavare nella storia e sprecare risorse del computer.
Ho eseguito il tuo codice.
C'è qualcosa di sbagliato qui?
#property version"1.00"#property strict//символ и таймфрейм текущего графикаstring symbol;
ENUM_TIMEFRAMES frame;
datetime time;
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)
{
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(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(eHigh-max>0)
{
for(int i=index+1; i>=0; i--)
{
if(Arr[index].high-eHigh>0)
{
max=Arr[index].high;
time_max=Arr[index].time_high;
break;
}
}
}
//если произошло обновление предыдущего минимумаif(min-eLow>0)
{
for(int i=index+1; i>=0; i--)
{
if(eLow-Arr[index].low>0)
{
min=Arr[index].low;
time_min=Arr[index].time_low;
break;
}
}
}
}
} day, month, year;
intOnInit()
{
symbol=Symbol();
frame=(ENUM_TIMEFRAMES)Period();
return(INIT_SUCCEEDED);
}
voidOnTick()
{
//текущее время закрытого бара
time=iTime(symbol,frame,1);
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);
//теперь имеем значения Comment(TimeToString(day.time_max)+" : "+DoubleToString(day.max)+" : "+DoubleToString(day.Arr[day.index].high)+"\n"+TimeToString(day.time_min)+" : "+DoubleToString(day.Arr[day.index].low)+" : "+DoubleToString(day.min));
}
Ecco come appare
1) Livello Low_D1 del giorno precedente
2) Min_D il minimo giornaliero più vicino sulla storia
//+------------------------------------------------------------------+//| 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 strictdouble Bar_data_D1 [][6]; // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров D1double Low_D1_Level; // Возвращает значение минимальной цены бара D1double Min_D_Level ; // ближайшей минимальный D уровеньdatetime Time_Day;
//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+intOnInit()
{
Level();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Expert deinitialization function |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
On_Timer();
}
//+------------------------------------------------------------------+//+------------------------------------------------------------------+//| Функция Level //+------------------------------------------------------------------+void Level()
{
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();
}
}
L'algoritmo non sempre disegna e conta come previsto, ma come scritto. Scrivere come scritto è di solito difficile.
Nell'immagine hai mostrato i minimi, e nella condizione hai il prezzo minimo della barra giornaliera Low. E l'algoritmo l'ha trovato nella zona di tendenza, e non è il minimo tra 2 barre adiacenti.
Mi sento come un bambino di 1a elementare anche se ho 42 anni.
:) tutto viene con l'esperienza, anch'io non capisco molte cose e sto imparando man mano che vado avanti. Non dovrebbe essere una struttura, dovrebbe essere una classe. Siamo quasi al livello di OOP. In cui sto ancora galleggiando.
Per quanto riguarda ArrayCopyRates, Alexey ha detto correttamente. È scritto nell'aiuto:
Копирует в двумерный массив вида double RateInfo[][6] данные баров указанного графика и возвращает количество скопированных баров.
Quindi devi scriverlo:
int total=ArrayCopyRates(Bar_data_D1,_Symbol,PERIOD_D1); // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров
Low_D1_Level = iLow (_Symbol,PERIOD_D1,1); // Возвращает значение минимальной цены бара D1for(int i = 1; i<total ;i++)
{
È stato seduto qui per un po':
Dovremmo cercare di evitare cicli inutili. Abbiamo una marea di citazioni, ed è necessario fare le voci giuste al volo, in modo da non dover scavare nella storia e sprecare risorse del computer.Mi sento come un bambino di prima elementare, anche se ho 42 anni.
Mi sento come un bambino di prima elementare, anche se ho 42 anni.
Questa è una buona cosa. Significa che tutto è davanti a me.
Questo è un bene. Quindi tutto è davanti a noi.
La cosa più importante è il risultato!!!
3.47 Vado a letto.
Digerirò tutto domani e se avrò delle domande te lo farò sapere!
Grazie mille a tutti!
Omsk?
Sedersi per un po':
Dovremmo cercare di evitare i loop inutili. Abbiamo citazioni che arrivano a fiumi, e abbiamo bisogno di fare le voci giuste al volo, in modo da non dover scavare nella storia e sprecare risorse del computer.Ho eseguito il tuo codice.
C'è qualcosa di sbagliato qui?
Ecco come appare
1) Livello Low_D1 del giorno precedente
2) Min_D il minimo giornaliero più vicino sulla storia
Omsk?
Sì
Sì
a +3 in qualche modo non molte città)
L'algoritmo non sempre disegna e conta come previsto, ma come scritto. Scrivere come scritto è di solito difficile.
Nell'immagine hai mostrato i minimi, e nella condizione hai il prezzo minimo della barra giornaliera Low. E l'algoritmo l'ha trovato nella zona di tendenza, e non è il minimo tra 2 barre adiacenti.
Ho eseguito il tuo codice.
C'è qualcosa che non va qui?
Per farlo contare dall'inizio della storia, è necessario inserire un ciclo in OnTick. Qualcosa del genere:
E nella funzione di record bar aggiungere un controllo per la data zero:
E in secondo luogo, in day.Arr[day.index].high è il giorno corrente. Se vuoi ieri, è nell'elemento precedente:
Credo che la logica dovrebbe essere corretta ora. Non ho controllato troppo bene, ma sembra essere corretto.
Mi sento come un bambino di 1a elementare anche se ho 42 anni.
Per quanto riguarda ArrayCopyRates, Alexey ha detto correttamente. È scritto nell'aiuto:
Копирует в двумерный массив вида double RateInfo[][6] данные баров указанного графика и возвращает количество скопированных баров.
Quindi devi scriverlo:
Ma questo non è un codice economico.