Правильно написанные условия - залог не преднамеренной оптимизации кода

 

Когда пишем условия if(... && ..), то мало кто задумывается об очерёдности исполнения кода, но разработчики позаботились о том, что правильно расставленные приоритеты - залог минимизации исполнения кода по времени и ресурсам.

Возьмём к примеру простой советник на трёх условиях для входа в рынок, пусть это будет МА55, 2 белых свечи и RSI.

Дальше условие выглядит так: 

if( MA55()== 1 && RSI() > 45 && Open()== 1 )
 {
  // BUY
 }

По сути условие правильное и выполниться без проблем, но если учесть тот факт, что условие if имеет спецификацию очерёдности проверки исполнения, nо этот код лучше записать так:

if( Open()==1 && RSI() > 45 && MA55()==1 )
{
  // BUY
}

Условие if начинает проверять условия поочерёдно, и если первое выполнилось, то идёт дальше, если второе не выполнилось - выход и третье уже не проверяет, что экономит время и системные ресурсы.

При написании нужно учитывать какие условия первостепенные, а какие второстепенны, и проверку начинать именно с главных. В первом коде у нас стоит проверка МА самой первой, потом RSI и в конце проверка по свечам. Но если рассмотреть пример, то не сложно понять, что в самую первую очередь нужно проверять именно свечи, потом  RSI и МА, тем более если она тяжёлая. Почему? Потому, что в самую первую очередь изменятся свечи, потом показания RSI и МА.

Если будет первой стоять проверка на свечи (Open[i])  и она не выполнится, то условие на вход уже не выполнено, и делать проверку дальше не имеет смысла, просчитывать RSI и МА.

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

Простые примеры, которые можно проверить:

Alert не сработает, потому что Flag==false, и тратить ресурсы на дальнейшую проверку функции GetFunc() не имеет смысла

bool Flag; // false

void OnTick()
 {
//--
   if( Flag && GetFunc()==1 ) {
     Alert("До меня очередь не дошла");
   }

//-
}

int GetFunc()
 {
  // ...
   Alert("GetAlert()");
  
//-
  return(1);
}

 

А вот этот код вызовет функцию GetFunc() и сработает Alert("GetAlert()"), но дальше не пойдёт, потому что Flag==false. В итоге условие if не выполнено, но дёрнули функцию GetFunc() затратив ресурсы, она выполнилась в полном объёме, но код внутри if не выполнен.

bool Flag; // false

void OnTick()
 {
//--
   if( GetFunc()==1 && Flag ) {
     Alert("До меня очередь не дошла");
   }

//-
}

int GetFunc()
 {
  // ...
   Alert("GetAlert()");
  
//-
  return(1);
}

 

Вот тут всё отработает: условия проверку прошли, и код внутри if выполнится, так-же сработаю два Alert:

bool Flag=true;

void OnTick()
{
//--
   if( Flag && GetFunc()==1 ) {
     Alert("До меня очередь тоже дошла");
   }

//-
}

int GetFunc()
{
  // ...
   Alert("GetAlert()");
  
//-
  return(1);
}


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

Возможно когда-то напишу о циклах, профи это не нужно, а вот начинающим может пригодится.

 

Зачем Вы пытаетесть микросеккудты искать ? Я как старый ассемблерщик это понимаю. Есле уж так приспичило, то думайте как в бинарке проц обрабатывает.
 

к чему так много скобок и if`ов ?

   flag&&GetFunc()?Alert("Alert!"):;

так тоже можно..если бы Alert() возвращать хоть что, было-бы ещё короче..

:-)

 
Maxim Kuznetsov:

к чему так много скобок и if`ов ?

   flag&&GetFunc()?Alert("Alert!"):;

так тоже можно..если бы Alert() возвращать хоть что, было-бы ещё короче..

:-)

Скобки всегда нужны для правильной компиляции. И отсутвии багов.
 
Vladimir Zubov:
Зачем Вы пытаетесть микросеккудты искать ? Я как старый ассемблерщик это понимаю. Есле уж так приспичило, то думайте как в бинарке проц обрабатывает.
Тут вопрос не только в выигранных микросекундах, но и в потреблении системных ресурсов. Не все пишут простые коды, в которых один цикл и четыре if , есть коды в которые заложены нейросети, куча проверок и условий, и там возможно не так важны микросекунды, как ресурсо-потребление, потому что вы такой код поставите в 6-10 окон, и компьютер через полчаса начнёт жужжать, а тем более если будет быстрый рынок и условия просчитываются на каждом тике, а не на новом баре. Вот в таких случаях и нужно писать экономно.
 
Maxim Kuznetsov:

к чему так много скобок и if`ов ?

   flag&&GetFunc()?Alert("Alert!"):;

так тоже можно..если бы Alert() возвращать хоть что, было-бы ещё короче..

:-)

Ну есть у меня и такое, но это не всегда можно применить, и не каждый это поймёт:

// Рисуем
  int WidthOC = UseCandleBar==2?1:ChartGetInteger(0,CHART_SCALE,0)<2?1:ChartGetInteger(0,CHART_SCALE,0)>=3?ChartGetInteger(0,CHART_SCALE,0)>=4?9:5:3;
 
Круто! Птицы летают.. рыбы плавают...
 
а если в условии стоит не && а || как поведет себя ф-я? будут же проверяться оба условия по любому... а если там более сложное логическое условие, ф-я же не знает заранее, сколько там условий понапихано... так что что-то мне почему-то не верится что проверяется только одно в случае с &&. А если там дальше затаилось где-то || а нас уже дропнуло из ф-ии
 
Maxim Dmitrievsky:
а если в условии стоит не && а || как поведет себя ф-я? будут же проверяться оба условия по любому... а если там более сложное логическое условие, ф-я же не знает заранее, сколько там условий понапихано... так что что-то мне почему-то не верится что проверяется только одно в случае с &&. А если там дальше затаилось где-то || а нас уже дропнуло из ф-ии
До первого true
 
Dmitry Fedoseev:
До первого true
а, ну тогда хорошо. тогда надо грамотно разделять вложенные условия скобками, что бы интерпретатор не сбился
 

Идея правильная.

Однако, я бы в первую очередь обращал внимание на легкость понимания и прозрачность кода.

В частности, обсуждаемое условие вначале темы - я бы разбил на три отдельных if'a, и работал бы с ними по очереди:

if(Open() != 1) return; // Не выполняется первое условие

if(RSI()<45) return; // Не выполняется второе условие

if(MA55()!=1 return; // Не выполняется третье условие

// Все условия выполняются - входим.

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

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