У меня есть робот на MT5, который работает сессиями с пачками рыночных позиций. В очередном апдейте я хочу его научить, чтобы он учитывал историю закрытых сделок не только непосредственно закрытых им самим (по Magic_ID), но и закрытых вручную (при условии, что робот их открывал). Общая блок схема: 1. При изменении истории сделок робот собирает первичную информацию по сделкам закрытия(DEAL_ENTRY_OUT) с начала своей сессии. 2. С помощью DEAL_POSITION_ID получаем тикет открывающей сделки. 3. С помощью DEAL_MAGIC получаем Magic_ID открывающей сделки 4. Если Magic_ID открывающей позиции равен заданному в настройках, то считаем закрывающую сделку нашей и фиксируем сведения о ней. 5. Отрисовываем метки открытия и закрытия позиции и линию жизни позиции. (Это удобно, когда на одной паре стоит несколько роботов, чтобы графически видеть нужную часть истории).
По этой блок-схеме я сделал инклюд. На тестере работает как задумано. В журнал пишет:
Но на реале как надо не работает. Путем последовательно исключения выяснил, что DEAL_MAGIC не считывает у сделки открытия. И условие if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер // (строка 94) дальше не пускает
Прошу вас указать в чем причина и как её победить? Код инклюда прилагаю.
//+------------------------------------------------------------------+//| DataHistory.mqh |//| Ваш % |//| vashprocent@bk.ru |//+------------------------------------------------------------------+#property strictint HistoryCountOrders; //последнее известное количество ордеров в истории double BalanceHistory, //баланс В $ по закрытым ордерам
LotsHistory; //объем лота по всем закрытым ордерам с начала сессии//=================================================================================================struct HistoryOrders // структура массива с данными по истории ордеров
{
int Deal_type_out[]; // тип сделки закрытия datetime Close_time[]; // время закрытия позиции double Close_price[]; // цена закрытия позицииdouble Close_lot[]; // лот закрытияulong Deal_ticket_out[]; // тикет сделки закрытияlong ID_deal_out[]; // ID сделки закрытия (если 0 - значит вручную)int Deal_type_in[]; // тип сделки открытия datetime Open_time[]; // время открытия позицииdouble Open_price[]; // цена открытияdouble Open_lot[]; // лот открытияulong Deal_ticket_in[]; // тикет сделки открытияlong ID_deal_in[]; // ID сделки открытия
}; HistoryOrders ActualHistoryOrders;
// ActualHistoryOrders.Deal_type_out[1]=//+------------------------------------------------------------------+//| Обработка ордеров в истории сессии |//+------------------------------------------------------------------+void DataHistory(datetime startTimeSessin, int id_Orders)
{
int totalPos; // кол-во закрытыхпозиций за время сессииif(!HistorySelect(startTimeSessin, TimeCurrent())){ // запрашиваем историю сделок с начала сессии до настоящего моментаPrint("HistorySelect() failed. Error ", GetLastError());
return;
}
totalPos=HistoryDealsTotal(); // запоминаем текущее количество ордеров в историиPrint("DataHistory: Кол-во сделок в истории сессии ",totalPos);
BalanceHistory=0; // обнуляем баланс по закрытым позициям
LotsHistory=0; // обнуляем сумму лотов по всем закрытым позициям с начала сессии
HistoryCountOrders=0; // кол-во закрытых позиций за это время ArrayResize(ActualHistoryOrders.Deal_type_out, totalPos, 1); // задаем изначальные размеры массивов истории сделокArrayResize(ActualHistoryOrders.Close_time, totalPos, 1);
ArrayResize(ActualHistoryOrders.Close_price, totalPos, 1);
ArrayResize(ActualHistoryOrders.Close_lot, totalPos, 1);
ArrayResize(ActualHistoryOrders.Deal_ticket_out,totalPos, 1);
ArrayResize(ActualHistoryOrders.ID_deal_out, totalPos, 1);
ArrayResize(ActualHistoryOrders.Deal_type_in, totalPos, 1);
ArrayResize(ActualHistoryOrders.Open_time, totalPos, 1);
ArrayResize(ActualHistoryOrders.Open_price, totalPos, 1);
ArrayResize(ActualHistoryOrders.Open_lot, totalPos, 1);
ArrayResize(ActualHistoryOrders.Deal_ticket_in, totalPos, 1);
ArrayResize(ActualHistoryOrders.ID_deal_in, totalPos, 1);
ArrayInitialize(ActualHistoryOrders.Deal_type_out, -1); // обнуляем данные по типам сделок закрытияArrayInitialize(ActualHistoryOrders.Close_time, -1);
ArrayInitialize(ActualHistoryOrders.Close_price, -1);
ArrayInitialize(ActualHistoryOrders.Close_lot, -1);
ArrayInitialize(ActualHistoryOrders.Deal_ticket_out,-1);
ArrayInitialize(ActualHistoryOrders.ID_deal_out, -1);
ArrayInitialize(ActualHistoryOrders.Deal_type_in, -1);
ArrayInitialize(ActualHistoryOrders.Open_time, -1);
ArrayInitialize(ActualHistoryOrders.Open_price, -1);
ArrayInitialize(ActualHistoryOrders.Open_lot, -1);
ArrayInitialize(ActualHistoryOrders.Deal_ticket_in,-1);
ArrayInitialize(ActualHistoryOrders.ID_deal_in, -1);
//--- СКАНИРУЕМ ИСТОРИЮ СДЕЛОК --- for(int i=0; i<totalPos; i++){ // перебираем все закрытые позицииulong deal_ticket = HistoryDealGetTicket(i); // фиксируем тикет сделки//Print("DataHistory: deal_ticket=",deal_ticket);if(deal_ticket==0) continue; // если тикет нулевой, то пропускаем этот ордерif(HistoryDealGetString(deal_ticket,DEAL_SYMBOL) !=_Symbol){continue;} // если символ не наш, выбираем следующий ордер //Print("DataHistory: _Symbol=",_Symbol); long deal_type = HistoryDealGetInteger(deal_ticket, DEAL_TYPE); // считываем тип сделки if(!(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)){continue;} // если сделка была НЕ рыночный BUY или SELL, то пропускаем этот ордер//Print("DataHistory: deal_type=",deal_type); //Print("DataHistory: deal_entry=",HistoryDealGetInteger(deal_ticket,DEAL_ENTRY)); if(HistoryDealGetInteger(deal_ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT) // если направление сделки - это выход из рынка
{
//Print("DataHistory: deal_entry=",HistoryDealGetInteger(deal_ticket,DEAL_ENTRY)); ulong deal_ticket_in = HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID); // получаем тикет cделки открытия int deal_id_in = (int)HistoryDealGetInteger(deal_ticket_in,DEAL_MAGIC); // получаем ID cделки открытия Print("DataHistory: deal_ticket_out=",(string)deal_ticket," deal_type_out=",(string)deal_type," deal_ticket_in=",(string)deal_ticket_in," deal_id_in=",(string)deal_id_in);
if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер long deal_id_out = HistoryDealGetInteger(deal_ticket_in, DEAL_MAGIC); // получаем ID cделки закрытия //Print("DataHistory: deal_ticket=",(string)deal_ticket," deal_type=",(string)deal_type," deal_ticket_in=",deal_ticket_in," deal_id_in=",deal_id_in," deal_id_out=",deal_id_out);
{
HistoryCountOrders++; // число наших закрытых позиций//--- собираем сведения о каждой закрытой сделке ---
ActualHistoryOrders.Deal_ticket_out [HistoryCountOrders-1]=(ulong)deal_ticket; // фиксируем тикет сделки закрытия
ActualHistoryOrders.Deal_type_out [HistoryCountOrders-1]=(int)deal_type; // тип сделки закрытия
ActualHistoryOrders.Close_time [HistoryCountOrders-1]=(datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME); // время сделки закрытия
ActualHistoryOrders.Close_price [HistoryCountOrders-1]=(double)NormalizeDouble(HistoryDealGetDouble(deal_ticket,DEAL_PRICE),_Digits); // цена сделки закрытия
ActualHistoryOrders.Close_lot [HistoryCountOrders-1]=(double)NormalizeDouble(HistoryDealGetDouble(deal_ticket,DEAL_VOLUME),2); // лот сделки закрытия
ActualHistoryOrders.ID_deal_out [HistoryCountOrders-1]=(int)deal_id_out; // id сделки закрытия
ActualHistoryOrders.Deal_ticket_in [HistoryCountOrders-1]=(ulong)deal_ticket_in; // тикет сделки открытия
ActualHistoryOrders.Deal_type_in [HistoryCountOrders-1]=(int)(deal_type==DEAL_TYPE_SELL? 0 : 1); // тип сделки открытия
ActualHistoryOrders.Open_time [HistoryCountOrders-1]=(datetime)HistoryDealGetInteger(deal_ticket_in,DEAL_TIME); // время открытия позиции
ActualHistoryOrders.Open_price [HistoryCountOrders-1]=(double)NormalizeDouble(HistoryDealGetDouble(deal_ticket_in,DEAL_PRICE),_Digits); // цена открытия
ActualHistoryOrders.Open_lot [HistoryCountOrders-1]=(double)NormalizeDouble(HistoryDealGetDouble(deal_ticket_in,DEAL_VOLUME),2); // лот открытия
ActualHistoryOrders.ID_deal_in [HistoryCountOrders-1]=(int)deal_id_in; // id сделки открытия
}
} // конец условия if(HistoryDealGetInteger(deal_ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT)
} // конец цикла for(int hi=total; hi>=0; hi--){ //перебираем все закрытые ордера//---------- if(HistoryCountOrders>0){ // если есть закрытые сделки в историиArrayResize(ActualHistoryOrders.Deal_type_out, HistoryCountOrders, 1); // задаем новые размеры массивов истории сделокArrayResize(ActualHistoryOrders.Close_time, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Close_price, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Close_lot, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Deal_ticket_out,HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.ID_deal_out, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Deal_type_in, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Open_time, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Open_price, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Open_lot, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.Deal_ticket_in, HistoryCountOrders, 1);
ArrayResize(ActualHistoryOrders.ID_deal_in, HistoryCountOrders, 1);
for(int hi=0; hi<HistoryCountOrders; hi++){ // перебираем все наши закрытые позиции
LotsHistory+=NormalizeDouble(ActualHistoryOrders.Close_lot[hi],2); // подсчитываем общий объем лота закрытых ордеров
BalanceHistory+= HistoryDealGetDouble(ActualHistoryOrders.Deal_ticket_out[hi],DEAL_PROFIT) // подсчет баланса по закрытым ордерам с начала сессии
+HistoryDealGetDouble(ActualHistoryOrders.Deal_ticket_out[hi],DEAL_COMMISSION)*2// предполагается, что если брокер берет комиссию,
+HistoryDealGetDouble(ActualHistoryOrders.Deal_ticket_out[hi],DEAL_SWAP); // то он делит её пополам (за открытие и за закрытие сделки) Print("DataHistory: Deal_ticket_out=",(string)ActualHistoryOrders.Deal_ticket_out[hi],", Deal_type_out=",(string)ActualHistoryOrders.Deal_type_out[hi],", ID_deal_out=",ActualHistoryOrders.ID_deal_out[hi],
", Deal_ticket_in =",(string)ActualHistoryOrders.Deal_ticket_in[hi], ", Deal_type_in =",(string)ActualHistoryOrders.Deal_type_in[hi], ", ID_deal_in =",ActualHistoryOrders.ID_deal_in[hi] );
//--- рисуем знак открытия, если его нет//ObjectOrderSend(deal_type_in, op_lot, op_price, deal_ticket_in); // закоментировал, потому что это в другом инклюде ObjectOrderSend(ActualHistoryOrders.Deal_type_in[hi], ActualHistoryOrders.Open_lot[hi], ActualHistoryOrders.Open_price[hi], ActualHistoryOrders.Deal_ticket_in[hi]); //--- рисуем знак закрытия и линию жизни позиции //ObjectOrderDelete(int in_type, ulong in_ticket, double in_price, datetime in_time, double out_price, datetime out_time ) // закоментировал, потому что это в другом инклюде ObjectOrderDelete(ActualHistoryOrders.Deal_type_in[hi], ActualHistoryOrders.Deal_ticket_in[hi], ActualHistoryOrders.Open_price[hi], ActualHistoryOrders.Open_time[hi], ActualHistoryOrders.Close_price[hi], ActualHistoryOrders.Close_time[hi]);
}
//----------//int index_open_time=ArrayMinimum(ActualHistoryOrders.Open_time,0); // смотрим индекс ячейки с самым ранним временем открытия позиции //if(MathAbs((int)GlobalVariableGet(StartTimeSessin)-(int)ActualHistoryOrders.Open_time[index_open_time])>=1) // если время в ГП StartTimeSessin отличается от времени из истории на 1сек и более//{ // Print("DataHistory: Время начала сессии скорректировано по историческим данным с "+(string)((datetime)GlobalVariableGet(StartTimeSessin))+" на "+(string)(ActualHistoryOrders.Open_time[index_open_time]-1)); // GlobalVariableSet(StartTimeSessin, (double)(ActualHistoryOrders.Open_time[index_open_time]-1)); // корректируем время начала сессии по историческим данным //}Print("DataHistory: Кол-во закрытых сделок в истории сессии HistoryCountOrders = ",HistoryCountOrders,". BalanceHistory = ",DoubleToString(BalanceHistory,2),". LotsHistory = ",DoubleToString(LotsHistory,2));
}
}
//========================================================================
У меня есть робот на MT5, который работает сессиями с пачками рыночных позиций. В очередном апдейте я хочу его научить, чтобы он учитывал историю закрытых сделок не только непосредственно закрытых им самим (по Magic_ID), но и закрытых вручную (при условии, что робот их открывал). Общая блок схема: 1. При изменении истории сделок робот собирает первичную информацию по сделкам закрытия(DEAL_ENTRY_OUT) с начала своей сессии. 2. С помощью DEAL_POSITION_ID получаем тикет открывающей сделки. 3. С помощью DEAL_MAGIC получаем Magic_ID открывающей сделки 4. Если Magic_ID открывающей позиции равен заданному в настройках, то считаем закрывающую сделку нашей и фиксируем сведения о ней. 5. Отрисовываем метки открытия и закрытия позиции и линию жизни позиции. (Это удобно, когда на одной паре стоит несколько роботов, чтобы графически видеть нужную часть истории).
По этой блок-схеме я сделал инклюд. На тестере работает как задумано. В журнал пишет:
Но на реале как надо не работает. Путем последовательно исключения выяснил, что DEAL_MAGIC не считывает у сделки открытия. И условие if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер // (строка 94) дальше не пускает
Прошу вас указать в чем причина и как её победить? Код инклюда прилагаю.
На беглый взгляд, первый и второй логи выводятся _разными_ кодами.
И приведённому коду соответствует только первый лог, а второй выводится каким-то другим кодом.
У меня есть робот на MT5, который работает сессиями с пачками рыночных позиций. В очередном апдейте я хочу его научить, чтобы он учитывал историю закрытых сделок не только непосредственно закрытых им самим (по Magic_ID), но и закрытых вручную (при условии, что робот их открывал). Общая блок схема: 1. При изменении истории сделок робот собирает первичную информацию по сделкам закрытия(DEAL_ENTRY_OUT) с начала своей сессии. 2. С помощью DEAL_POSITION_ID получаем тикет открывающей сделки. 3. С помощью DEAL_MAGIC получаем Magic_ID открывающей сделки 4. Если Magic_ID открывающей позиции равен заданному в настройках, то считаем закрывающую сделку нашей и фиксируем сведения о ней. 5. Отрисовываем метки открытия и закрытия позиции и линию жизни позиции. (Это удобно, когда на одной паре стоит несколько роботов, чтобы графически видеть нужную часть истории).
По этой блок-схеме я сделал инклюд. На тестере работает как задумано. В журнал пишет:
Но на реале как надо не работает. Путем последовательно исключения выяснил, что DEAL_MAGIC не считывает у сделки открытия. И условие if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер // (строка 94) дальше не пускает
Прошу вас указать в чем причина и как её победить? Код инклюда прилагаю.
Так и думал, что никто ничего путёвого не подскажет. Видимо баг MQL5. Как иначе обьяснить, что на тестере (с визуалом и без) работает как надо, а на реале - нет.
Так и думал, что никто ничего путёвого не подскажет. Видимо баг MQL5. Как иначе обьяснить, что на тестере (с визуалом и без) работает как надо, а на реале - нет.
Я пытался разобраться в вашем коде, но написано так, что мой мозг не воспринимает этого.
Вы зря не пользуетесь функцией OnTradeTransaction. Это избавило бы вас от перебора всех позиций.
Я пытался разобраться в вашем коде, но написано так, что мой мозг не воспринимает этого.
Вы зря не пользуетесь функцией OnTradeTransaction. Это избавило бы вас от перебора всех позиций.
И вот это
почему на втором снимке написано подругому? Наверное печатает из другого места кода.
Здравствуйте. ))) Спасибо за проявленный интерес. Я уже писал выше, что поскольку на реале до конечного лога не добираемся, то я раскоментил строку 92, чтобы было видно докуда доходим и почему дальше не проходим: условие по DEAL_MAGIC не выполняется в строке 94. И вопрос в том, почему это работает на тестере (в том числе с визуализацией), а на реале идет затык. Ведь такого не должно быть.
HistoryDealGetInteger(deal_ticket_in,DEAL_MAGIC); // получаем ID cделки открытия
Перефразирую вопрос. Как вы думаете, почему эта строка на визуальном тестере выдает Magic, а на реале выдает 0 ? Вероятно "ларчик то просто открывается", и я упускаю какую-то мелочь. Ну или это всё-таки баг MQL5? Что думаете - СУПЕРПРОФИ ?
Посмотрел функцию OnTradeTransaction. Если мне идти по этому пути, то будет совсем другой код. И не факт, что он будет проще. Мне ведь надо не просто сделать обработку результатов выполнения торгового запроса. А выполнить прикладную задачу - связать ручную сделку закрытия со сделкой открытия с помощью эксперта.
Oleg Shangin #: Здравствуйте. ))) Спасибо за проявленный интерес. Я уже писал выше, что поскольку на реале до конечного лога не добираемся, то я раскоментил строку 92, чтобы было видно докуда доходим и почему дальше не проходим: условие по DEAL_MAGIC не выполняется в строке 94. И вопрос в том, почему это работает на тестере (в том числе с визуализацией), а на реале идет затык. Ведь такого не должно быть.
Перефразирую вопрос. Как вы думаете, почему эта строка на визуальном тестере выдает Magic, а на реале выдает 0 ? Вероятно "ларчик то просто открывается", и я упускаю какую-то мелочь. Ну или это всё-таки баг MQL5? Что думаете - СУПЕРПРОФИ ?
Посмотрел функцию OnTradeTransaction. Если мне идти по этому пути, то будет совсем другой код. И не факт, что он будет проще. Мне ведь надо не просто сделать обработку результатов выполнения торгового запроса. А выполнить прикладную задачу - связать ручную сделку закрытия со сделкой открытия с помощью эксперта.
В тестере всё совсем не так как в реале.
Вот эта строка
ulong deal_ticket_in = HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID); // получаем тикет cделки открытия
почему вы решили, что это тикет сделки?
Внимательно прочтите что такое DEAL_POSITION_ID и как выбрать ордера и сделки относящиеся к одной позиции.
Посмотрел функцию OnTradeTransaction. Если мне идти по этому пути, то будет совсем другой код. И не факт, что он будет проще. Мне ведь надо не просто сделать обработку результатов выполнения торгового запроса. А выполнить прикладную задачу - связать ручную сделку закрытия со сделкой открытия с помощью эксперта.
Да, это будет другой код. И будет гораздо проще. Посмотрите структуры функции
structMqlTradeTransaction
{
ulong deal; // Тикет сделки ulong order; // Тикет ордера string symbol; // Имя торгового инструмента ENUM_TRADE_TRANSACTION_TYPE type; // Тип торговой транзакции ENUM_ORDER_TYPE order_type; // Тип ордера ENUM_ORDER_STATE order_state; // Состояние ордера ENUM_DEAL_TYPE deal_type; // Тип сделки ENUM_ORDER_TYPE_TIME time_type; // Тип ордера по времени действия datetime time_expiration; // Срок истечения ордера double price; // Цена double price_trigger; // Цена срабатывания стоп-лимитного ордера double price_sl; // Уровень Stop Loss double price_tp; // Уровень Take Profit double volume; // Объем в лотах ulong position; // Тикет позиции ulong position_by; // Тикет встречной позиции
};
Вам не придётся на каждом тике проверять не изменилась ли история. Вы сразу получаете событие, проверяете что это и код выполняется в определённом направлении.
Alexey Viktorov #: В тестере всё совсем не так как в реале.
Вы общими расхожими фразами выражаетесь вместо конкретики. Определенные различия между тестером и реалом в MQL5 конечно есть. Они описаны. Но в данном случае, в чем именно разница на реале и визуале в обработке этой строки?
ulong deal_ticket_in = HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID); // получаем тикет cделки открытия
Alexey Viktorov #: почему вы решили, что это тикет сделки?
Потому что так написано в мануале.
DEAL_POSITION_ID
Идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка. Каждая позиция имеет уникальный идентификатор, который присваивается всем сделкам, совершенным на инструменте в течение всей жизни позиции.
"Идентификатор позиции - это уникальное число, которое присваивается каждой вновь открытой позиции и не изменяется в течение всей ее жизни. Соответствует тикету ордера, которым была открыта позиция." Значит тикет сделки открытия рыночной позиции это и будет для всех остальных ордеров идентификатором позиции (т.е. DEAL_POSITION_ID). Тестер с визуализацией это подтверждают.
Alexey Viktorov #: Вам не придётся на каждом тике проверять не изменилась ли история.
И тут тоже вы не угадали. Разве я не понимаю?))) Запрос истории у меня идет не на каждом тике. И даже не по времени вообще, а при изменении суммарного обьема лотов по инструменту.
Идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка. Каждая позиция имеет уникальный идентификатор, который присваивается всем сделкам, совершенным на инструменте в течение всей жизни позиции.
"Идентификатор позиции - это уникальное число, которое присваивается каждой вновь открытой позиции и не изменяется в течение всей ее жизни. Соответствует тикету ордера, которым была открыта позиция."
POSITION_TICKET
Тикет позиции. Уникальное число, которое присваивается каждой вновь открытой позиции. Как правило, соответствует тикету ордера, в результате которого она была открыта, за исключением случаев изменения тикета в результате служебных операций на сервере. Например, начисления свопов переоткрытием позиции. Для нахождения ордера, которым была открыта позиция, следует использовать свойство POSITION_IDENTIFIER.
Идентификатор позиции - это уникальное число, которое присваивается каждой вновь открытой позиции и не изменяется в течение всей ее жизни. Соответствует тикету ордера, которым была открыта позиция.
Идентификатор позиции указывается в каждом ордере (ORDER_POSITION_ID) и сделке (DEAL_POSITION_ID), которая ее открыла, изменила или закрыла. Используйте это свойство для поиска ордеров и сделок, связанных с позицией.
При развороте позиции в режиме неттинга (единой сделкой in/out) идентификатор позиции POSITION_IDENTIFIER не изменяется. Однако при этом POSITION_TICKET изменяется на тикет ордера, в результате которого произошел разворот. В режиме хеджинга разворот позиции не предусмотрен.
long
Вот разница между тикетом позиции и идентификатором позиции.
Когда-то в этом описании была оговорка «…как правило соответствует тикету ордера…»
А в тестере это просто совпадение. Случайное попадание в цель…
Здравствуйте, уважаемые знатоки...

У меня есть робот на MT5, который работает сессиями с пачками рыночных позиций.
В очередном апдейте я хочу его научить, чтобы он учитывал историю закрытых сделок не только непосредственно закрытых им самим (по Magic_ID), но и закрытых вручную (при условии, что робот их открывал).
Общая блок схема:
1. При изменении истории сделок робот собирает первичную информацию по сделкам закрытия (DEAL_ENTRY_OUT) с начала своей сессии.
2. С помощью DEAL_POSITION_ID получаем тикет открывающей сделки.
3. С помощью DEAL_MAGIC получаем Magic_ID открывающей сделки
4. Если Magic_ID открывающей позиции равен заданному в настройках, то считаем закрывающую сделку нашей и фиксируем сведения о ней.
5. Отрисовываем метки открытия и закрытия позиции и линию жизни позиции. (Это удобно, когда на одной паре стоит несколько роботов, чтобы графически видеть нужную часть истории).
По этой блок-схеме я сделал инклюд. На тестере работает как задумано. В журнал пишет:
Но на реале как надо не работает. Путем последовательно исключения выяснил, что DEAL_MAGIC не считывает у сделки открытия.

И условие if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер // (строка 94) дальше не пускает
Прошу вас указать в чем причина и как её победить?
Код инклюда прилагаю.
Здравствуйте, уважаемые знатоки...
У меня есть робот на MT5, который работает сессиями с пачками рыночных позиций.
В очередном апдейте я хочу его научить, чтобы он учитывал историю закрытых сделок не только непосредственно закрытых им самим (по Magic_ID), но и закрытых вручную (при условии, что робот их открывал).
Общая блок схема:
1. При изменении истории сделок робот собирает первичную информацию по сделкам закрытия (DEAL_ENTRY_OUT) с начала своей сессии.
2. С помощью DEAL_POSITION_ID получаем тикет открывающей сделки.
3. С помощью DEAL_MAGIC получаем Magic_ID открывающей сделки
4. Если Magic_ID открывающей позиции равен заданному в настройках, то считаем закрывающую сделку нашей и фиксируем сведения о ней.
5. Отрисовываем метки открытия и закрытия позиции и линию жизни позиции. (Это удобно, когда на одной паре стоит несколько роботов, чтобы графически видеть нужную часть истории).
По этой блок-схеме я сделал инклюд. На тестере работает как задумано. В журнал пишет:
Но на реале как надо не работает. Путем последовательно исключения выяснил, что DEAL_MAGIC не считывает у сделки открытия.
И условие if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер // (строка 94) дальше не пускает
Прошу вас указать в чем причина и как её победить?
Код инклюда прилагаю.
На беглый взгляд, первый и второй логи выводятся _разными_ кодами.
И приведённому коду соответствует только первый лог, а второй выводится каким-то другим кодом.
На беглый взгляд, первый и второй логи выводятся _разными_ кодами.
И приведённому коду соответствует только первый лог, а второй выводится каким-то другим кодом.
Код тот же.
Но поскольку на реале до конечного лога не добираемся, то я раскоментил строку 92, чтобы было видно докуда доходим.
Здравствуйте, уважаемые знатоки...
У меня есть робот на MT5, который работает сессиями с пачками рыночных позиций.
В очередном апдейте я хочу его научить, чтобы он учитывал историю закрытых сделок не только непосредственно закрытых им самим (по Magic_ID), но и закрытых вручную (при условии, что робот их открывал).
Общая блок схема:
1. При изменении истории сделок робот собирает первичную информацию по сделкам закрытия (DEAL_ENTRY_OUT) с начала своей сессии.
2. С помощью DEAL_POSITION_ID получаем тикет открывающей сделки.
3. С помощью DEAL_MAGIC получаем Magic_ID открывающей сделки
4. Если Magic_ID открывающей позиции равен заданному в настройках, то считаем закрывающую сделку нашей и фиксируем сведения о ней.
5. Отрисовываем метки открытия и закрытия позиции и линию жизни позиции. (Это удобно, когда на одной паре стоит несколько роботов, чтобы графически видеть нужную часть истории).
По этой блок-схеме я сделал инклюд. На тестере работает как задумано. В журнал пишет:
Но на реале как надо не работает. Путем последовательно исключения выяснил, что DEAL_MAGIC не считывает у сделки открытия.
И условие if(deal_id_in != id_Orders){continue;} // если ID входящей сделки не наш, выбираем следующий ордер // (строка 94) дальше не пускает
Прошу вас указать в чем причина и как её победить?
Код инклюда прилагаю.
Так и думал, что никто ничего путёвого не подскажет. Видимо баг MQL5. Как иначе обьяснить, что на тестере (с визуалом и без) работает как надо, а на реале - нет.
Так и думал, что никто ничего путёвого не подскажет. Видимо баг MQL5. Как иначе обьяснить, что на тестере (с визуалом и без) работает как надо, а на реале - нет.
Я пытался разобраться в вашем коде, но написано так, что мой мозг не воспринимает этого.
Вы зря не пользуетесь функцией OnTradeTransaction. Это избавило бы вас от перебора всех позиций.
И вот это
почему на втором снимке написано подругому? Наверное печатает из другого места кода.
Я пытался разобраться в вашем коде, но написано так, что мой мозг не воспринимает этого.
Вы зря не пользуетесь функцией OnTradeTransaction. Это избавило бы вас от перебора всех позиций.
И вот это
почему на втором снимке написано подругому? Наверное печатает из другого места кода.
Я уже писал выше, что поскольку на реале до конечного лога не добираемся, то я раскоментил строку 92, чтобы было видно докуда доходим и почему дальше не проходим: условие по DEAL_MAGIC не выполняется в строке 94.
И вопрос в том, почему это работает на тестере (в том числе с визуализацией), а на реале идет затык. Ведь такого не должно быть.
Перефразирую вопрос. Как вы думаете, почему эта строка на визуальном тестере выдает Magic, а на реале выдает 0 ?
Вероятно "ларчик то просто открывается", и я упускаю какую-то мелочь. Ну или это всё-таки баг MQL5? Что думаете - СУПЕРПРОФИ ?
Посмотрел функцию OnTradeTransaction. Если мне идти по этому пути, то будет совсем другой код. И не факт, что он будет проще.
Мне ведь надо не просто сделать обработку результатов выполнения торгового запроса. А выполнить прикладную задачу - связать ручную сделку закрытия со сделкой открытия с помощью эксперта.
Здравствуйте. ))) Спасибо за проявленный интерес.
Я уже писал выше, что поскольку на реале до конечного лога не добираемся, то я раскоментил строку 92, чтобы было видно докуда доходим и почему дальше не проходим: условие по DEAL_MAGIC не выполняется в строке 94.
И вопрос в том, почему это работает на тестере (в том числе с визуализацией), а на реале идет затык. Ведь такого не должно быть.
Перефразирую вопрос. Как вы думаете, почему эта строка на визуальном тестере выдает Magic, а на реале выдает 0 ?
Вероятно "ларчик то просто открывается", и я упускаю какую-то мелочь. Ну или это всё-таки баг MQL5? Что думаете - СУПЕРПРОФИ ?
Посмотрел функцию OnTradeTransaction. Если мне идти по этому пути, то будет совсем другой код. И не факт, что он будет проще.
Мне ведь надо не просто сделать обработку результатов выполнения торгового запроса. А выполнить прикладную задачу - связать ручную сделку закрытия со сделкой открытия с помощью эксперта.
В тестере всё совсем не так как в реале.
Вот эта строка
почему вы решили, что это тикет сделки?
Внимательно прочтите что такое DEAL_POSITION_ID и как выбрать ордера и сделки относящиеся к одной позиции.
Посмотрел функцию OnTradeTransaction. Если мне идти по этому пути, то будет совсем другой код. И не факт, что он будет проще.
Мне ведь надо не просто сделать обработку результатов выполнения торгового запроса. А выполнить прикладную задачу - связать ручную сделку закрытия со сделкой открытия с помощью эксперта.
Да, это будет другой код. И будет гораздо проще. Посмотрите структуры функции
Вам не придётся на каждом тике проверять не изменилась ли история. Вы сразу получаете событие, проверяете что это и код выполняется в определённом направлении.
Но дело ваше, не нравится, не ешьте…😊
В тестере всё совсем не так как в реале.
Вы общими расхожими фразами выражаетесь вместо конкретики. Определенные различия между тестером и реалом в MQL5 конечно есть. Они описаны. Но в данном случае, в чем именно разница на реале и визуале в обработке этой строки?
почему вы решили, что это тикет сделки?
Потому что так написано в мануале.
DEAL_POSITION_ID
Идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка. Каждая позиция имеет уникальный идентификатор, который присваивается всем сделкам, совершенным на инструменте в течение всей жизни позиции.
"Идентификатор позиции - это уникальное число, которое присваивается каждой вновь открытой позиции и не изменяется в течение всей ее жизни. Соответствует тикету ордера, которым была открыта позиция."
Значит тикет сделки открытия рыночной позиции это и будет для всех остальных ордеров идентификатором позиции (т.е. DEAL_POSITION_ID). Тестер с визуализацией это подтверждают.
Вам не придётся на каждом тике проверять не изменилась ли история.
И тут тоже вы не угадали. Разве я не понимаю?))) Запрос истории у меня идет не на каждом тике. И даже не по времени вообще, а при изменении суммарного обьема лотов по инструменту.
Потому что так написано в мануале.
DEAL_POSITION_ID
Идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка. Каждая позиция имеет уникальный идентификатор, который присваивается всем сделкам, совершенным на инструменте в течение всей жизни позиции.
"Идентификатор позиции - это уникальное число, которое присваивается каждой вновь открытой позиции и не изменяется в течение всей ее жизни. Соответствует тикету ордера, которым была открыта позиция."
POSITION_TICKET
Тикет позиции. Уникальное число, которое присваивается каждой вновь открытой позиции. Как правило, соответствует тикету ордера, в результате которого она была открыта, за исключением случаев изменения тикета в результате служебных операций на сервере. Например, начисления свопов переоткрытием позиции. Для нахождения ордера, которым была открыта позиция, следует использовать свойство POSITION_IDENTIFIER.
Значение POSITION_TICKET соответствует MqlTradeRequest::position.
long
POSITION_IDENTIFIER
Идентификатор позиции - это уникальное число, которое присваивается каждой вновь открытой позиции и не изменяется в течение всей ее жизни. Соответствует тикету ордера, которым была открыта позиция.
Идентификатор позиции указывается в каждом ордере (ORDER_POSITION_ID) и сделке (DEAL_POSITION_ID), которая ее открыла, изменила или закрыла. Используйте это свойство для поиска ордеров и сделок, связанных с позицией.
При развороте позиции в режиме неттинга (единой сделкой in/out) идентификатор позиции POSITION_IDENTIFIER не изменяется. Однако при этом POSITION_TICKET изменяется на тикет ордера, в результате которого произошел разворот. В режиме хеджинга разворот позиции не предусмотрен.
long
Вот разница между тикетом позиции и идентификатором позиции.
Когда-то в этом описании была оговорка «…как правило соответствует тикету ордера…»
А в тестере это просто совпадение. Случайное попадание в цель…