Debemos intentar evitar los ciclos innecesarios. Tenemos una avalancha de citas, y hay que hacer las entradas correctas sobre la marcha, para no tener que rebuscar en el historial y desperdiciar recursos informáticos.
Me siento como un niño de primer grado, aunque tenga 42 años.
Debemos intentar evitar los bucles innecesarios. Nosllegan citas a raudales y tenemos que hacer las entradas correctas sobre la marcha, para no tener que rebuscar en el historial y desperdiciar recursos informáticos.
He ejecutado tu código.
¿Hay algo mal aquí?
#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));
}
Así es como se ve
1) Nivel bajo_D1 del día anterior
2) Min_D mínimo diario más cercano en el historial
//+------------------------------------------------------------------+//| 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();
}
}
El algoritmo no siempre dibuja y cuenta como se pretende, sino como está escrito. Escribir como se escribe suele ser difícil.
En la imagen has mostrado los mínimos, y en la condición tienes el precio mínimo de la barra diaria Low. Y el algoritmo lo encontró en la zona de tendencia, y no es el mínimo entre 2 barras adyacentes.
El primer matiz, hasta ahora el algoritmo no cuenta desde el principio del historial del probador, sino desde el principio. Por lo tanto, aparece la fecha 1970.01.01, que es cero.
Para que cuente desde el principio de la historia, hay que insertar un bucle en OnTick. Algo así:
datetime time=0, current;
voidOnTick()
{
//текущее время закрытого бара
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));} elsebreak;
}
while(time<=current);
//теперь имеем значения 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));
}
Y en la función de registro de barras añadir una comprobación de la fecha cero:
Me siento como un niño de primer grado aunque tenga 42 años.
:) todo viene con la experiencia, yo tampoco entiendo muchas cosas y voy aprendiendo sobre la marcha. No se supone que sea una estructura, sino una clase. Estamos casi al nivel de la OOP. En el que todavía estoy flotando.
Con respecto a ArrayCopyRates, Alexey dijo correctamente. Está escrito en la ayuda:
Копирует в двумерный массив вида double RateInfo[][6] данные баров указанного графика и возвращает количество скопированных баров.
Así que tienes que escribirlo:
int total=ArrayCopyRates(Bar_data_D1,_Symbol,PERIOD_D1); // Копирует в массив данные баров указанного графика и возвращает количество скопированных баров
Low_D1_Level = iLow (_Symbol,PERIOD_D1,1); // Возвращает значение минимальной цены бара D1for(int i = 1; i<total ;i++)
{
He estado sentado aquí durante un tiempo:
Debemos intentar evitar los ciclos innecesarios. Tenemos una avalancha de citas, y hay que hacer las entradas correctas sobre la marcha, para no tener que rebuscar en el historial y desperdiciar recursos informáticos.Me siento como un niño de primer grado, aunque tenga 42 años.
Me siento como un niño de primer grado, aunque tenga 42 años.
Eso es algo bueno. Significa que todo está por delante de mí.
Eso es bueno. Así que todo está por delante.
¡¡¡Lo más importante es el resultado!!!
3.47 Me voy a la cama.
¡Mañana lo digeriré todo y si tengo alguna duda os lo haré saber !
Muchas gracias a todos.
¿Omsk?
Sentado durante un tiempo:
Debemos intentar evitar los bucles innecesarios. Nosllegan citas a raudales y tenemos que hacer las entradas correctas sobre la marcha, para no tener que rebuscar en el historial y desperdiciar recursos informáticos.He ejecutado tu código.
¿Hay algo mal aquí?
Así es como se ve
1) Nivel bajo_D1 del día anterior
2) Min_D mínimo diario más cercano en el historial
¿Omsk?
Sí
Sí
en +3 de alguna manera no muchas ciudades)
El algoritmo no siempre dibuja y cuenta como se pretende, sino como está escrito. Escribir como se escribe suele ser difícil.
En la imagen has mostrado los mínimos, y en la condición tienes el precio mínimo de la barra diaria Low. Y el algoritmo lo encontró en la zona de tendencia, y no es el mínimo entre 2 barras adyacentes.
He ejecutado tu código.
¿Hay algo que no está bien aquí?
Para que cuente desde el principio de la historia, hay que insertar un bucle en OnTick. Algo así:
Y en la función de registro de barras añadir una comprobación de la fecha cero:
Y segundo, en day.Arr[day.index].high es el día actual. Si necesitas ayer, está en el elemento anterior:
Supongo que la lógica debería ser correcta ahora. No lo he comprobado demasiado, pero parece que es correcto.
Me siento como un niño de primer grado aunque tenga 42 años.
Con respecto a ArrayCopyRates, Alexey dijo correctamente. Está escrito en la ayuda:
Копирует в двумерный массив вида double RateInfo[][6] данные баров указанного графика и возвращает количество скопированных баров.
Así que tienes que escribirlo:
Pero eso no es un código económico.