создание магического числа - страница 3

 
//|                                                      This_EA.mq4 |
//|                      Copyright © 2010, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+

#define This_EA  101
#define That_EA  102
#define Other_EA 103 // put this list of ea names to each of your ea's header, or...
                     // .. alternatively you can use a number suffix to your ea's file name 
                     // so it can be identified with --> StringSubstr(WindowExpertName(),x,y);
double This_EA_qty;
string magic_prefix;

int init()
  {

   if(GlobalVariableGet(This_EA_qty) >= 0.0){
            GlobalVariableSet("This_EA_qty", This_EA_qty + 1);
   }
   magic_prefix = StringConcatenate(This_EA, DoubleToStr(This_EA_qty,0));

   return(0);
  }

int deinit()
  {

      GlobalVariableSet("This_EA_qty", This_EA_qty - 1);
   
   return(0);
  }

int start()
  {
      double lots, SL, TP; int slip, time_stamp ;
      bool BuyCondition;
   
      if( BuyCondition == true )
      {
         time_stamp  = TimeCurrent(); 
         string magic_name = StringConcatenate(magic_prefix, time_stamp );
         int magic = StrToInteger(magic_name);
         
                                      // Integers range from -2147483648 to 2147483647
                                      // the resulting magic integer would most probably exceed that 
                                      // so we cut the number returned with TimeCurrent() short with 
                                      // MathMod(time_stamp,x) x being years, months not necessary for 
                                      // magic unique-ness. I don't include this calculation, 
                                      // since I'm short in time for testing it...
      
      
         OrderSend(Symbol(),0, lots, Ask, slip, SL, TP, NULL, magic, 0, CLR_NONE);
      }
//----
   return(0);
  }
//+------------------------------------------------------------------+
занимает немного больше времени, чем я думал ...
редактировать : GVget условие != -1.0 к >= 0.0; редактировать
 
cameofx:
[...] занимает немного больше времени, чем я думал ...

Это все больше становится повторением (извините за каламбур) предыдущей темы, которую я уже упоминал: https://www.mql5.com/en/forum/120034. Все, что связано с глобальными переменными, поднимает вопросы о резервном копировании и аварийном восстановлении. Если торговля должна быть перенесена в спешке на новый сервер, то либо должна быть доступна свежая резервная копия gvariables.dat, либо пользователь должен быть в состоянии воссоздать глобальные переменные вручную.

Я не изучал ваш код внимательно, но я также не уверен, что произойдет, если существует несколько копий советника и MT4 будет перезапущен. Похоже, что код может предполагать, что советники будут автоматически перезагружены в том же порядке, в котором они были первоначально загружены вручную. Другими словами, несколько копий советника могут получить разные значения This_EA_qty при перезагрузке, и тогда я не могу понять, как они правильно определят свои исторические ордера в списке MT4. Но я могу ошибаться в этом.

 
cameofx:
занимает немного больше времени, чем я думал ...
редактировать : GVget условие != -1.0 к >= 0.0
// TimeCurrent() in seconds since 1970 would most probably exceed that 

TimeCurrent() возвращает 32-битное целое число. Тип datatime является псевдонимом для типа int, int также является 32-битным целым числом.


Еще одна вещь, которую я не понимаю в вашем коде - почему вы используете разные MN для каждой открытой сделки? Это противоположно тому, для чего предназначены MN. Идея MN заключается в том, что вы можете идентифицировать все сделки определенного советника, просто взглянув на MN. В чем причина случайной части MN? Как бы выглядел код в вашем советнике, который закрывал бы все открытые сделки этого советника или отслеживал все стопы этого советника?
 
Если я правильно понимаю, ваше решение для двух разных экспертов, случайно имеющих одинаковый ID, заключается в том, чтобы поместить все ID экспертов в заголовок каждого эксперта. Это своего рода боль в заднице... Даже если вы поместите эту часть в включаемый файл, вам все равно придется перекомпилировать все эксперты для каждого нового эксперта.

Вопрос о постоянстве все еще остается. Я не знаю, как это будет работать после перезапуска терминала или после переключения на совершенно другой терминал...
 
jjc:

Это все больше становится повторением (извините за каламбур) предыдущей темы, которую я уже упоминал: https://www.mql5.com/en/forum/120034. Все, что связано с глобальными переменными, поднимает вопросы о резервном копировании и аварийном восстановлении. Если торговля должна быть перенесена в спешке на новый сервер, то либо должна быть доступна свежая резервная копия gvariables.dat, либо пользователь должен быть в состоянии воссоздать глобальные переменные вручную.

Я не изучал ваш код внимательно, но я также не уверен, что произойдет, если существует несколько копий советника и MT4 будет перезапущен. Похоже, что код может предполагать, что советники будут автоматически перезагружены в том же порядке, в котором они были первоначально загружены вручную. Другими словами, несколько копий советника могут получить разные значения This_EA_qty при перезагрузке, и тогда я не могу понять, как они правильно определят свои исторические ордера в списке MT4. Но я могу ошибаться.

Вот такие отзывы я ожидаю... спасибо gordon, 7bit & jjc...

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

- если эксперт This_EA уже был прикреплен однажды на другом графике, magic_number тогда будет иметь значение : 101-1-time_stamp (тире для ясности).

- содержащаяся информация будет 101 - идентификатор эксперта; 1 - количество This_EA, действующее на данный момент; time_stamp - время отправки ордера.

- Затем мы можем просканировать его с помощью StringSubStr и узнать, что конкретный ордер был открыт This_EA, в то время как был прикреплен 1 другой This_EA.

 
7bit:

TimeCurrent() возвращает 32-битное целое число. Тип datatime является псевдонимом для типа int, int также является 32-битным целым числом.


Другая вещь, которую я не понимаю в вашем коде - почему вы используете разные MN для каждой открытой сделки? Это противоположно тому, для чего предназначены MN. Идея MN заключается в том, что вы можете идентифицировать все сделки определенного советника, просто взглянув на MN. В чем причина случайной части MN? Как бы выглядел код в вашем советнике, который закрывал бы все открытые сделки этого советника или отслеживал все стопы этого советника?

Извините, я имел в виду, что результирующий int magic_name превысит это распределение. Я перенесу комментарий в коде соответствующим образом.

Чтобы уравнять наше восприятие. Я бы предложил такие требования к этому "автоматизированному" magic_number. MN должен иметь следующее:

- Вы можете определить, каким советником был открыт данный конкретный ордер с указанным MN.

- Советник, содержащий эту технику - если он подключен к множеству (более 1), не будет генерировать одно и то же магическое число, если эти советники открывают ордера одновременно за пределами 1-секундного интервала.

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

- пожалуйста, добавьте, если мой список не полон...

 
cameofx:
- содержащаяся информация будет 101 - идентификатор эксперта; 1 - количество This_EA, действующее на данный момент; time_stamp - время отправки ордера.

- Затем мы можем просканировать его с помощью StringSubStr и узнать, что определенный ордер был открыт This_EA, в то время как был прикреплен 1 другой This_EA.

Но для чего нужна временная часть в MN? Почему бы просто не использовать только номера экспертов? И не использовать substr? Использование substr потребует преобразования int в строку, затем некоторых строковых операций и сравнения строк, временная часть MN отбрасывается, потому что она никогда не нужна. Строковые операции с целыми числами обычно выглядят по-дилетантски, потому что в большинстве случаев их можно было бы лучше решить, закодировав информацию в разных битах 32-битного слова и используя побитовые операции для манипулирования или проверки, что было бы на порядки быстрее и элегантнее.

Почему бы просто не использовать (EA-instance-unique) значение int для mn и использовать простое целочисленное сравнение для сравнения либо всего числа, либо определенных его битов?

Например, пусть первые 28 бит будут идентификатором, а последние четыре бита - числом от 0 до 15 для идентификации различных типов сделок (например, если он может открывать 3 различных типа ордеров: начальный, уровень1, уровень2 и хедж).

ID = hash & 0xFFFFFFF0  // this has the 4 low bits always zero


// generate the mn for level 1 trades
MN = (ID + 1);
OrderSend(..., MN, "level 1");


// generate the mn for hedge trades
MN = (ID + 15);
OrderSend(..., MN, "hedge the whole mess");


// this strategy may not make any sense, only to illustrate the code:
// close the hedge trades and trail the stops of all levels
for(...){
   if (OrderMagicNumber() & 0xFFFFFFF0 == ID){  // this trade belongs to us
      if (OrderMagicNumber() & 0x0000000F == 15){ // this is a hedge trade
         OrderClose(...)
      }else{ // this is one of the other levels
         Trail(OrderTicket());
      }
   }
}

// or even easier:
MN = (ID + 15); // all our hedge trades have this MN
for(...){
   if (OrderMagicNumber() == MN){
      OrderClose(...)
   }
}
 
gordon:
Если я правильно понял - ваше решение для двух разных экспертов, случайно имеющих одинаковый ID, заключается в том, чтобы поместить все ID экспертов в заголовок каждого эксперта. Это своего рода боль в заднице... Даже если вы поместите эту часть в включаемый файл, вам все равно придется перекомпилировать все эксперты для каждого нового эксперта.

Вопрос о постоянстве все еще остается. Я не знаю, как это будет работать после перезапуска терминала или после переключения на совершенно другой терминал...

Нет, не понял :) пожалуйста, прочитайте комментарии в коде относительно WindowExpertName().

При вызове из эксперта он будет получать имя файла эксперта/скрипта/индикатора без ".mq4" или ".ex4", вам не нужно ставить никаких include, просто назовите свои советники соответствующим образом.

PS : извините за спамный ответ :)

 
7bit:

Но для чего нужна часть времени в MN? Почему бы просто не использовать только числа EA? И не использовать substr? При использовании substr нужно преобразовать int в строку, затем выполнить несколько строковых операций и сравнить строки, а временная часть MN отбрасывается, потому что она никогда не нужна. Строковые операции с целыми числами обычно выглядят по-дилетантски, потому что в большинстве случаев их можно было бы лучше решить, закодировав информацию в разных битах 32-битного слова и используя побитовые операции для манипулирования или проверки, что было бы на порядки быстрее и элегантнее.

Почему бы просто не использовать (EA-instance-unique) значение int для mn и использовать простое целочисленное сравнение для сравнения либо всего числа, либо определенных его битов?

Например, пусть первые 28 бит будут ID, а последние четыре бита - числом от 0 до 15 для идентификации различных типов сделок (например, если советник может открывать 3 различных типа ордеров: начальный, уровень1, уровень2 и хедж).


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

Предпосылкой было бы: Если советник открыл два (более) ордера одновременно с одним и тем же магическим номером, они не могут иметь одинаковый MN, иначе это будет конфликтовать при обработке ордеров и идентификации...

идентификации ордеров... возможно, я ошибочно путаю это с захватом OrderTicket (или нет?).

- включение стратегии в MN было бы следующим шагом, естественно.

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

Спасибо. Возможно, позже мне придется обратиться к вам за разъяснениями :)))

 
cameofx:

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

Нет, они могут быть какими угодно. так же как и комментарий. рассматривайте их как своего рода числовой комментарий. Все ручные сделки, открытые с помощью обычного пользовательского интерфейса MT4, будут иметь магическое число 0, поэтому вы можете, например, перебрать все ордера и закрыть/удалить все ручные сделки и ордера, оставив все сделки советника нетронутыми.

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

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

Для уникальной идентификации только одного определенного ордера всегда есть номер тикета.