Перебор параметров счетчика

 

Часто возникает необходимость в переборе параметров индикатора или групп индикаторов либо иных настроек, которые нужно либо включить, либо напротив исключить из работы советника. Тут предполагается, что параметры взаимозависимые и по этой причине их надо исследовать вместе. Могут быть и иные причины.

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

Ранее на мою просьбу: "Прошу Вас помочь с кодом перебора, допустим у нас есть переменные с диапазонами: "А" от 2 до 6 с шагом 2, "Б" от 1 до 3  с шагом 1, "В" от 0 до 1 с шагом 1 и "Г" от 16 до 48 с шагом 4. Необходимо организовать перебор параметров, при этом будет перебираться вариант комбинации (внешняя переменная - дающая доступ к любой из комбинаций). Как такой механизм правильно реализовать?", мне помогли и код имеет такой вид:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Любые вопросы новичков по MQL4, помощь и обсуждение по алгоритмам и кодам

Victor Nikolaev, 2017.05.09 13:10


Небольшой скрипт

//+------------------------------------------------------------------+
//|                                                       Decode.mq4 |
//|                                            Copyright 2017, Vinin |
//|                                             http://vinin.ucoz.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Vinin"
#property link      "http://vinin.ucoz.ru"
#property version   "1.00"
#property strict
#property script_show_inputs
//--- input parameters
input int N=162;  //0..162
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   for (int n=0;n<N;n++)
   {
      int tmp=n;
      int a=MathMod(tmp,3);
      tmp=(tmp-a)/3;
      int b=MathMod(tmp,3);
      tmp=(tmp-b)/3;
      int c=MathMod(tmp,2);
      tmp=(tmp-c)/2;
      int d=tmp;
   
      Print("N=",n,"; A=", 2+2*a, "; B=", b+1,"; C=",c,"; D=", 16+4*d);
   }
  }
//+------------------------------------------------------------------+


Однако, сейчас встала новая задача:

"

У меня есть переменные и диапазон их изменения - получаю их расчетным путем:

Vektor -1 или 1

Situation от 1 до 5

N_Etalon от 1 и больше 1


Кроме того, есть переменные для непосредственных действий:

   bool SellPrIMA //запрет на покупку

   bool BuyPrIMA//запрет на продажу

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

Цель - сделать счетчик, который перебирать будет все варианты комбинаций при оптимизации, потом выявить плохие варианты, составить список таких комбинаций, в результате чего должен получится фильтр.

Прошу Вас помочь понять, как сделать такой счетчик! Какой алгоритм действия для составления счетчика?

 

Думаю, что переменную Vektor -1 или 1 можно просто заменить на bool переменную, а потом уже интерпретировать значение - если 0, то -1, а если 1, то 1. Если же надо использовать определенный шаг, то видимо удобно будет загнать переменные сначала в массив, а потом просто перебирать индекс массива.

 
Aleksey Vyazmikin:

Думаю, что переменную Vektor -1 или 1 можно просто заменить на bool переменную, а потом уже интерпретировать значение - если 0, то -1, а если 1, то 1. Если же надо использовать определенный шаг, то видимо удобно будет загнать переменные сначала в массив, а потом просто перебирать индекс массива.

#property strict
#property script_show_inputs
input int N=80;

void OnStart()
{
   Alert(" --------------------------------------------------- "  );
   for (int n=0;n<N;n++)
   {
      bool SellPrIMA= n & 1;   // Младший двоичный разряд
      bool BuyPrIMA = n & 2;   // Второй разряд с краю
      int  vect     = (n & 4)/4; /*Это 0 и 1*/  vect= 2*vect-1;  /* Теперь -1 и 1  */
      int  sit      = (n /8);   // Отбросить три младших уже использованных разряда
      int N_eta     = sit /5  + 1;   // Меняется до 5 начиная с 1
      sit = sit % 5 +1;              // меняется начиная с 1
      Alert(SellPrIMA, "     ", BuyPrIMA, "          ", vect, "            ", sit, "           ", N_eta);
   }

   Alert("Sell      Buy          vect        sit        N_eta "  );
}
Файлы:
PROBKA.mq4  2 kb
 
STARIJ:

Замечательно! Спасибо!

А вот как же это все описать словами - какая тут логика? Как Вы все это организовали? Можете написать свои размышления?

 
Aleksey Vyazmikin:  как же это все описать словами - какая тут логика? Как Вы все это организовали? Можете написать свои размышления?

Это двоичная арифметика Числа представлены в памяти в двоичном виде. Всего для int 32 разряда   вот младшая часть

0=0000   1=0001   2=0010   3=0011  4=0100  5=0101  6=0110   7=0111  8=1000  9=1001   10=1010    11=1011    12=1100   13=1101   14=1110   15=1111   16=10000   17=10001

n & 1 путем поразрядного умножения выделяет младший,   n & 2 второй     n & 4  третий разряд. Видно, они меняются по очереди 0 и 1.

n / 8 отбрасывает 3 младших разряда

 
STARIJ:

Это двоичная арифметика Числа представлены в памяти в двоичном виде. Всего для int 32 разряда   вот младшая часть

0=0000   1=0001   2=0010   3=0011  4=0100  5=0101  6=0110   7=0111  8=1000  9=1001   10=1010    11=1011    12=1100   13=1101   14=1110   15=1111   16=10000   17=10001

n & 1 путем поразрядного умножения выделяет младший,   n & 2 второй     n & 4  третий разряд. Видно, они меняются по очереди 0 и 1.

n / 8 отбрасывает 3 младших разряда


Гммм.... сложно. Можно с простого? Вот мы запланировали счетчик, какой первый наш шаг? Возможна ли универсальность решения задачи?

 

Если в выражении n & 1; поставить курсор перед амперсандом и нажать F1 - попадем в раздел справки Побитовые операции, где сложно что понять.
Прежде всего надо согласиться, что числа в компьютере представлены в двоичном коде - т.е. состоят из нулей и единиц. В привычной десятичной системе младший правый разряд означает единицы, второй - десятки и т.д. Увеличение в 10 раз (основание системы).
В двоичной системе младший правый разряд означает единицы, второй - двойки, третий - четверки и т.д. Увеличение в 2 раза (основание системы).
Двоичное число 1111 = 8 + 4 + 2 + 1 = 15. Числа можно поразрядно умножать. Для примера: 10 & 6 = 1010 & 0110 = 1*0  0*1  1*1  0*0 = 0010 = 2
Интереснее поразрядное умножение на числа 1=0001  2=0010  4=0100  8=1000 ...  Это приводит к выделению одного двоичного разряда числа.
Теперь живой пример. Надо перебрать все комбинации четырех логических переменных.
Всего будет 16 комбинаций. N будет меняться от 0 до 15, т.е. N = 0000...1111. Распределим разряды так: DCBA
for(N=0; N<=15; N++)
{
   bool A= N & 1;  //  0=false   1=true
   bool B= N & 2;  //  0=false   2=true
   bool C= N & 4;  //  0=false   4=true
   bool D= N & 8;  //  0=false   8=true
}
// Если нужно, чтоб были целые числа 0 и 1 то надо так
for(N=0; N<=15; N++)
{
   int  A=  N & 1;
   int  B= (N & 2)/2;
   int  C= (N & 4)/4;
   int  D= (N & 8)/8;
}
Масштабирование умножение и сдвиг (+ или 1) меняет значение переменных. Если A принимает значения 0 и 1 (размах = 1), а надо -1 и 1 (размах 2), то умножаем на 2.  A*2 принимает значения 0 и 2.  Сдвинем в минус вычитанием 1.  A*2-1 принимает значения -1 и 1
Речь шла о двоичных переменных принимающих 2 значения. Если значений больше, надо использовать остаток от деления (это операция %)
Можно в одном счетчике совместить двоичные переменные, отведя им нужное число
последних двоичных разрядов, а старшую часть счетчика использовать для других - будет универсальное решение.

Первый шаг - отделить двоичные переменные и назначить им последние разряды.

 
Konstantin Erin:

Первый шаг - отделить двоичные переменные и назначить им последние разряды.

Спасибо за развернутый ответ! Даже не могу осмыслить Ваш гений!

Столкнулся вот с такой проблемой, есть у меня в оптимизации куча параметров для исключения, да так много, что самих параметров для оптимизации остаётся всего то примерно 15% от всех комбинаций, очень хочется экономить время, так как оно всё ж таки уходит на проверку параметров оптимизации. Решением был бы счетчик, последовательный перебор которого генерировал набор для перебора, исключая те значения, которые не нужно перебирать. Как это можно сделать?

Вот, к примеру, набор комбинаций

input int Usl_01=0; //от -1 до 1
input int Usl_02=0; //от 0 до 5
input int Usl_03=0; //от 1 до 5
input int Usl_04=0; //от -1 до 1
input int Usl_05=0; //от 1 до 8
input int Usl_06=0; //от -1 до -8
input int Usl_07=0; //от -8 до 8
input int Usl_08=0; //от -8 до 8


Вот исключение

if(Usl_08>Usl_05){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_08<Usl_06){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_07>Usl_05){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_07<Usl_06){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_08>0)if(Usl_07>Usl_08){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_08<0)if(Usl_07<Usl_08){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_01==0){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_04==0){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_07==0){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_08==0){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_03>5){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
if(Usl_03==0){Print("iDeltaP - INIT_PARAMETERS_INCORRECT");return(INIT_PARAMETERS_INCORRECT);}
 
Aleksey Vyazmikin:

Спасибо за развернутый ответ! Даже не могу осмыслить Ваш гений!

Столкнулся вот с такой проблемой, есть у меня в оптимизации куча параметров для исключения, да так много, что самих параметров для оптимизации остаётся всего то примерно 15% от всех комбинаций, очень хочется экономить время, так как оно всё ж таки уходит на проверку параметров оптимизации. Решением был бы счетчик, последовательный перебор которого генерировал набор для перебора, исключая те значения, которые не нужно перебирать. Как это можно сделать?

Вот, к примеру, набор комбинаций.  Вот исключение

Случайно заметил продолжение темы. К сожалению, я не гений - просто изучал информатику, булеву алгебру, ... Бегло глянул - вроде Вы правильно рассуждаете. Так в чем вопрос? Пишите в личку. Вряд ли это всем интересно. Насчет оптимизации - использую группы. В каждой 1 или максимум 3 параметра. С полученными значениями оптимизирую следующую группу. И так до конца. Потом сначала. И так 3 или 4 раза - параметры перестают меняться. Экономия времени - преогромнейшая. Вот простой пример - у нас 4 параметра по 10 значений - всего 10000 вариантов. Оптимизируем по первому параметру, по второму, третьему, четвертому - всего 40 вариантов. Повторим 10 раз - 400 вариантов

До этого пробовал на бесплатном VPS запускать оптимизацию на сутки и много больше. Превысил лимит процессорного времени, сняли с банковской карты ... долларов. А теперь РосКомНадзор заблокировал адреса в интернете - потерял доступ к VPS - нужно ставить VPN

 
Konstantin Erin:

Случайно заметил продолжение темы. К сожалению, я не гений - просто изучал информатику, булеву алгебру, ... Бегло глянул - вроде Вы правильно рассуждаете. Так в чем вопрос? Пишите в личку. Вряд ли это всем интересно. Насчет оптимизации - использую группы. В каждой 1 или максимум 3 параметра. С полученными значениями оптимизирую следующую группу. И так до конца. Потом сначала. И так 3 или 4 раза - параметры перестают меняться. Экономия времени - преогромнейшая. Вот простой пример - у нас 4 параметра по 10 значений - всего 10000 вариантов. Оптимизируем по первому параметру, по второму, третьему, четвертому - всего 40 вариантов. Повторим 10 раз - 400 вариантов

До этого пробовал на бесплатном VPS запускать оптимизацию на сутки и много больше. Превысил лимит процессорного времени, сняли с банковской карты ... долларов. А теперь РосКомНадзор заблокировал адреса в интернете - потерял доступ к VPS - нужно ставить VPN

Так я думаю, наоборот, тема может быть многим полезна!

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

Оптимизацию конечно лучше запускать на своём ПК, или использовать сеть ПК, в том числе и удаленную.

 
Konstantin Erin:

Вряд ли это всем интересно.

интересно!

сижу голову ломаю над похожей задачей 

https://www.mql5.com/ru/forum/245636

принципы те же - есть несколько параметров, но хочу сделать массив с признаками параметров и потом посчитать число повторений каждого параметра

Не могу проинициализировать массив (задача на комбинаторику)
Не могу проинициализировать массив (задача на комбинаторику)
  • 2018.05.19
  • www.mql5.com
Который час пытаюсь составить алгоритм инициализации массива по заданному примеру: примерно такие должны получиться данные, массив трехмерный: #de...
Причина обращения: