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

 
fxsaber:

Наверное, чтобы обнаружить такое, нужно было в поисках ошибки в своем коде дойти до внутреннего состояния/упорства "здесь ничего не может не работать, но все равно проверю".

Код парсил поток байтов под определенный протокол.
Не сходились размеры распакованных и не распакованных данных (данных для следующего уровня инкапсуляции).

 
Sergey Dzyublik:

Код парсил поток байтов под определенный протокол.
Не сходились размеры распакованных и не распакованных данных (данных для следующего уровня инкапсуляции).

С такой задачей не сложно обнаружить. Повезло.
 
Sergey Dzyublik:
Гистерезис в действии... на примере работы неявного оператора копирования в структурах.

А в чем вопрос?

void OnStart()
{
        int a[]; ArrayResize( a, 3 ); ArrayInitialize( a, 3 );
        int b[]; ArrayResize( b, 2 ); ArrayInitialize( b, 2 );

в MQL условная запись

//                 a = b;

равносильна

        ArrayCopy( a,  b );

Результат:

        ArrayPrint( a );
}

2 2 3

 
A100:

А в чем вопрос?


Оператор копирования присваивания, на мой взгляд, должен копировать не только сами элементы массива, но и их количество, оставив действительным количество зарезервированной памяти.

А сейчас происходит практически следующее:

int size;
size = 4; // size == 4
size = 8; // size == 8
size = 4; // size == 8



Исходный код:

struct MyArray{
   uchar 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 8 8 8 8
}
 
Sergey Dzyublik:


Оператор копирования должен копировать не только сами элементы массива, но и их количество, оставив действительным количество зарезервированной памяти.

А почему тогда

struct MyArray {
        uchar data[];
};
void OnStart()
{
        { uchar   a[], b[]; a = b; } //(1) Error
        { MyArray a,   b;   a = b; } //(2) нормально
}

в (1) случае ошибка, а во (2) все нормально!? Какая разница?

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

Не по правилам a = b, потому что его нету, если бы оно было, то ошибки (1) не было бы


 
Igor Zakharov:

Если считать на каждом тике - это ресурсоёмко, особенно заметно в тестере стратегий. Не правильнее ли пересчёт делать только при событии Trade, т.е. когда реально меняется что-то в перечне открытых позиций? С OnTradeTransaction() упрощается контроль за вмешательством пользователя в работу советника. (есть прецеденты :)

В данном роботе тестил возможность закрытия сеток по схеме: убыточная + прибыльная > Х , то закрыть обе (как правило, на разных символах). Но сбой получается, т.к. не смотря на то, что они закрыты, тестер не знает об этом, и переходит к следующей итерации, ошибочно "спаривая" существующие с уже закрытыми. Т.е. пришлось добавить пересчёт после каждого закрытия.

Пересчёт у меня со сбросом счётчика и сначала по всем отрытым, не +1 / -1

Согласен, рисковано было изначально использовать OnTradeTransaction() Вообще, наверное, откажусь от неё в случаях когда запросы не асинхронные - одни проблемы от неё.

Нисколько не рискованно. Вопрос только в организации последовательности действий и событий. Барабашка правильно дальше сказал, закрыл пару и вышел из цикла до следующего тика. На следующем тике не факт что цены будут хуже чем есть. Может и лучше будет закрыть чуть позже, зато не будет путаницы что с чем закрылось.

Второй вариант: цикл организовать не по PositionsTotal, а по массиву созданному заранее. И при закрытии какой-то пары эти тикеты удалять из массива. Это не даст попасть закрытым позициям повторно на закрытие. В общем полёт фантазии и логика действий.

 
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            
}