Ошибки, баги, вопросы - страница 2452

 
A100:

А такая что копированиe массивов происходит не по правилам a = b, а по правилам ArrayCopy( a,  b )

Сами придумали, или где-то написано?
Напомню, речь идет работе неявного оператора присваивания для структур с динамическими массивами.

 
Sergey Dzyublik:

Сами придумали, или где-то написано?
Напомню, речь идет работе неявного оператора присваивания для структур с динамическими массивами.

Это не я придумал, а Разработчики

        uchar a[], b[]; a = b; //Error: invalid array access
Почему ошибка? Обернули в структуру и ошибка исчезла? А почему? Что принципиально изменилось? Мои ответы выше
 
Alexey Viktorov:

Вопрос только в организации последовательности действий и событий.

Вы же сами привели цитату из мануала, где сказано, что последовательность не гарантируется. Потому и рисковано.

Я уже начал было переписывать код по совету Владимира, но споткнулся о случай, когда закрытие дольше тика - опять двойной подсчёт (узел фильтра в подсчёте уж очень тяжеловестный получился). Пока не придумал ничего лучше, чем остановка до полного закрытия, ради компромисса со скоростью оптимизации. 

Пятница же :) Может отдохнув что-то соображу.

В любом случае, спасибо за идеи - они не пропадут!

 
A100:

Это не я придумал, а Разработчики

Так и не понял, где это написано, но не суть важно...
Спасибо за холивар.

Подперли костылем и побежал дальше:

struct MyArray{
   uchar data[];
   
   void operator=(MyArray &bytes){
      ArrayCopy(this.data, bytes.data);
      ArrayResize(this.data, ArraySize(bytes.data));
   }
};


MyArray GetArray(int i){
   MyArray arr;
   
   if (i%2 == 0){
      ArrayResize(arr.data, 8);
      ArrayInitialize(arr.data, 0x8);
   }else{
      ArrayResize(arr.data, 4);
      ArrayInitialize(arr.data, 0x4);
   }
   return arr;
}


void OnStart(){
   MyArray arr_1 = GetArray(1);
   ArrayPrint(arr_1.data);        // 4 4 4 4
   
   MyArray arr_2 = GetArray(2);
   ArrayPrint(arr_2.data);        // 8 8 8 8 8 8 8 8
   
   arr_2 = arr_1;
   ArrayPrint(arr_2.data);        // 4 4 4 4            
}
 
Igor Zakharov:

Вы же сами привели цитату из мануала, где сказано, что последовательность не гарантируется. Потому и рисковано.

Я уже начал было переписывать код по совету Владимира, но споткнулся о случай, когда закрытие дольше тика - опять двойной подсчёт (узел фильтра в подсчёте уж очень тяжеловестный получился). Пока не придумал ничего лучше, чем остановка до полного закрытия, ради компромисса со скоростью оптимизации. 

Пятница же :) Может отдохнув что-то соображу.

В любом случае, спасибо за идеи - они не пропадут!

Я говорил о своей собственной последовательности.

По моим наблюдениям получается что после OnTick, когда происходит транзакция выполнение кода не дожидаясь следующего тика передаётся функции OnTradeTransaction. Следовательно нет никакой разницы обрабатывать факт закрытия собственными функциями или в OnTradeTransaction. Но мне больше нравится работать с OnTradeTransaction. Главное правильно организовать последовательность действий без зависимости от последовательности транзакций поступающих с сервера. И немаловажно правильно понимать эту последовательность. Опять-же по моим наблюдениям последовательность может быть нарушена в типе транзакции. То-есть может быть сначала TRADE_TRANSACTION_DEAL_ADD а потом TRADE_TRANSACTION_HISTORY_ADD, а по логике вроде-бы должно быть сначала добавление ордера в историю и следом за этим сделка.

ps; Потом, как я уже сказал, отсеяв транзакцию TRADE_TRANSACTION_DEAL_ADD можно отсеять по открытию позиции и по закрытию позиции. Ведь мы говорим о советнике для рынка форекс и счёте hadge так ведь? Соответственно нет никакой необходимости при каждом чихе пересчитывать все позиции. Достаточно добавить одну, если было открытие, или одну удалить из посчитанных, если было закрытие.
 
Alexey Viktorov:

рынка форекс и счёте hadge так ведь?

Сетка же :) Да.

Текущая логика такая: есть структура в которой хранится вся информация по каждой сетке: символ-количество позиций-суммарный лот-профит и ещё несколько неважных для этой беседы вещей... По таймеру пересчитывается профит, если есть ордера (мультисимвольный робот). А вот лоты и количество пересчитывалось в OnTradeTransaction (на случай, если пользователь "помог").

Я хотел проверить случай, когда одна сетка, например, в плюсе на 100$, а другая в минусе на 50 - закрыть обе с профитом 50, чтоб не дать ей расти.

На данный момент сделано так:

void  OnTradeTransaction(
   const MqlTradeTransaction&    trans,     // trade transaction structure 
   const MqlTradeRequest&        reqst,     // request structure 
   const MqlTradeResult&         reslt      // response structure 
    )
{
 int index=-1;
 for(index=0;index<symbols_total;index++)
  if(ARRAY[index].symbol==trans.symbol) break; //нашли индекс символа по которому прошла трансакция в массиве структур
 
 if(index>=0) CountOrders(index); //пересчитали элемент
}

Пока добавил CountOrders() после закрытия пары сеток. Для тестера - работает. Для реала сделаю по схеме Владимира (с массивом закрываемых тикетов)

Кстати, парное закрытие не оправдало себя - просадку не сильно уменьшает, а профит режет прилично.

 
Vladimir Karputov:

Я бы отказался от ВСЕХ while, Sleep and OnTimer для задачи закрытия позиций. Я бы делал так: выстрелил приказы на закрытие - вышел из OnTick, на следуующем тике проверка: если позиции с нужными тикетами ещё живы - снова выстрелить приказы на закрытие и так по кругу через взход/выход в onTick.

Логика такая: закрытие позиции - первоочередая задача, поэтому цикл закрытия в самом начале OnTick. А формирование массива тикетов закрытия может быть в любом месте OnTick - хоть в самом конце.

И рано или поздно получите следующее: нужно закрыть позицию, послали ордер на закрытие (MQL5), т.е. послали ордер противоположного типа, раз Вы не отслеживаете торговые действия в соответствующем обработчике (или не сохраняете состояние позиции в советнике), на следующем тике ордер на закрытие может быть в процессе отправки, а Вы пуляете еще один ордер. В итоге - позиция противоположного направления.

 
Alexey Kozitsyn:

И рано или поздно получите следующее: нужно закрыть позицию, послали ордер на закрытие (MQL5), т.е. послали ордер противоположного типа, раз Вы не отслеживаете торговые действия в соответствующем обработчике (или не сохраняете состояние позиции в советнике), на следующем тике ордер на закрытие может быть в процессе отправки, а Вы пуляете еще один ордер. В итоге - позиция противоположного направления.

Для такого случая есть:

10036

TRADE_RETCODE_POSITION_CLOSED

Position with the specified POSITION_IDENTIFIER has already been closed

Закрывающая позиция отправляется с тикетом закрываемой, поэтому описанное вами вряд ли произойдёт.

 
Sergey Dzyublik:

Так и не понял, где это написано, но не суть важно...
Спасибо за холивар.

Подперли костылем и побежал дальше:

Ну вообще странно массивы копируется, но кому-то даже нравится ...

Я себе сделал более менее адекватную обвёртку над массивом и бед не знаю.

https://www.mql5.com/ru/forum/221917/page26#comment_11233214

 
A100:

Это не я придумал, а Разработчики

Не припомню, чтобы они когда-либо говорили такое.

Оператор присваивания предназначен для создания идентичной копии объекта.  В этом его смысл.  Когда ты что-то приравниваешь чему-то, то очевидно в левой части должна получиться полная копия, а не чёрти что.  Поэтому здесь явный баг.

Причина обращения: