Автоматическое магическое число - страница 4

 
cloudbreaker:

Я подумал, что было бы полезно задокументировать (очень кратко):

1. Критерии для принятия решения о внедрении магических чисел

2. Критерии для принятия решения об использовании автоматической генерации магических чисел

3. Критерии для принятия решения о внедрении слоя постоянства

4. Критерии для принятия решения о выборе глобальных файлов против доступа к файлам для персистентности

Краткие, полностью личные ответы...


(2) зависит от любого количества факторов, включая то, хочет ли пользователь иметь возможность контролировать магические числа, чтобы использовать их как способ группировки результатов различных стратегий.

(3) - это то, чего я бы избегал, если бы мог, но я почти никогда не могу (см. "внешние переменные и изменение таймфрейма?"). Было бы хорошо, если бы MT4 предоставлял помощь в сохранении и восстановлении состояния советников. Но этого не происходит.

(4) приводит к довольно сильным личным предпочтениям: Мне не нравятся глобальные файлы. Пользователи могут удалять их; хранение ограничено числами; а формат gvariables.dat непонятен. Я предпочитаю файлы, которые, в крайнем случае, при необходимости, можно изменить с помощью текстового редактора.


- У меня осталось всего 8 сообщений, прежде чем я сделаю перерыв на некоторое время.

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

 

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

Вот что у меня есть:

string GetSymbol=Symbol();
int MNSymbol,MNSymbolCalc,MagicNumber;
for(int a=0;a<6;a++)//превращаем Symbol() в ASCII строку и добавляем каждый символ в MNSymbol
{
MNSymbolCalc=StringGetChar(GetSymbol, a);
MNSymbolCalc=((MNSymbolCalc-64)*(MathPow(10,(a))));//вычитаем 64, т.к. ASCII символы начинаются с 65, умножаем результат на a-ую степень для аккуратности (хотя это и не нужно)
MNSymbol = MNSymbol+MNSymbolCalc;
}
int MNPeriod=Period();

int MNEACode=100000;//Сделайте это число разным для каждого советника, чтобы два разных типа советников не выбрали одно и то же магическое число
MagicNumber=MNSymbol+MNPeriod+MNEACode;

 

JT, да... проблемы дублирования - это предмет ночных кошмаров ;)


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

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

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

В попытках сделать мульти ccy,per используются локальные функции. т.е. надоело постоянно кодировать один и тот же код заголовка функции для проверки пустых актуалий: ccy,per

поэтому я использую _Symbol() и _Period(). Соображения скорости/размера, имхо, даже на MT4 интерпретаторе просто не стоят того, чтобы тратить на это силы...

В любом случае, может это даст пищу для размышлений...


Я рассуждаю так, чтобы сделать ниже [и документировать в функции]:

Это удобный способ гарантировать, что если советник остановится на CCY,PER, то при повторном запуске позже против того же CCY,PER

он сгенерирует идентичный giExpertId (он же Magic#). Это означает, что он может возобновить управление незавершенными сделками в пуле...

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

Таким образом, OrderPools будут иметь тикеты с magic#, специфичным для советника, что позволит отображать тикеты только для каждого советника.


Ваше замечание о >1 "одноименном" советнике на одном и том же ccy,per действительно является проблемой. Я наконец-то решил, что HEY! будьте реальны... если я совершу эту ошибку, то заслуживаю пинка под зад за то, что был таким неразумным, lol

в конце концов, как показано в этой теме, есть миллионы идей/методов, каждый со своими сильными и слабыми сторонами.

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

Я никогда не задумывался о том, что крах EA/CT приводит к перезапуску, и о том, что можно продолжить работу с того места, где остановился. Теперь это решено, пока советник автоматически генерирует свой EAid/magic# с данными, уникальными для его среды графика R/T. Он всегда будет генерировать один и тот же номер...

ну что ж, развлекайтесь!


int iMakeExpertId (string sSymbol="",int iPeriod=EMPTY)
{

  return( iMakeHash(_Symbol( sSymbol), getPeriodStr(_Period( iPeriod)),WindowExpertName()) );

}//iMakeExpertId()
//
//
//


//+------------------------------------------------------------------+
//
int iMakeHash (string s1, string s2= EMPTYSTRING, string s3= EMPTYSTRING, string s4= EMPTYSTRING, string s5= EMPTYSTRING
			,string s6= EMPTYSTRING, string s7= EMPTYSTRING, string s8= EMPTYSTRING, string s9= EMPTYSTRING, string s10= EMPTYSTRING)
{
  /*
  Produce 32bit int hash code from  a string composed of up to TEN concatenated input strings.
  WebRef: http://www.cse.yorku.ca/~oz/hash.html
  KeyWrd: "djb2"
  FirstParaOnPage:
  "  Hash Functions
  A comprehensive collection of hash functions, a hash visualiser and some test results [see Mckenzie
  et al. Selecting a Hashing Algorithm, SP&E 20(2):209-224, Feb 1990] will be available someday. If
  you just want to have a good hash function, and cannot wait, djb2 is one of the best string hash
  functions i know. it has excellent distribution and speed on many different sets of keys and table
  sizes. you are not likely to do better with one of the "well known" functions such as PJW, K&R[1],
  etc. Also see tpop pp. 126 for graphing hash functions.
  "

  NOTES: 
  0. WARNING - mql4 strings maxlen=255 so... unless code changed to deal with up to 10 string parameters
     the total length of contactenated string must be <=255
  1. C source uses "unsigned [char|long]", not in MQL4 syntax
  2. When you hash a value, you cannot 'unhash' it. Hashing is a one-way process.
     Using traditional symetric encryption techniques (such as Triple-DES) provide the reversible encryption behaviour you require.
     Ref:http://forums.asp.net/t/886426.aspx subj:Unhash password when using NT Security poster:Participant
  //
  Downside?
  original code uses UNSIGNED - MQL4 not support this, presume could use type double and then cast back to type int.
*/
  string s = StringConcatenate( s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
  int iHash = 5381;
  int iLast = StringLen( s)-1;
  int iPos=0;

  while( iPos <= iLast )		//while (c = *str++)	[ consume str bytes until EOS hit {myWord! isn't C concise! Pity MQL4 is"!"} ]
  {
    //original C code: hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    iHash = (( iHash << 5) + iHash) + StringGetChar( s, iPos);		//StringGetChar() returns int
    iPos++;
  }
  return(MathAbs( iHash));
}//iMakeHash()
 
fbj:
  NOTES: 
  0. WARNING - mql4 strings maxlen=255 so... unless code changed to deal with up to 10 string parameters
     the total length of contactenated string must be <=255

Хотя лично я предпочитаю ручную установку магического числа, ваше решение довольно элегантно. Отличный код.


Одна поправка - строковые константы имеют максимальную длину 255, строковые переменные могут быть гораздо больше, см. -> https://www.mql5.com/en/forum/123551.

 

Спасибо, Гордон, код, похоже, работает нормально, но в конечном итоге, конечно, не является пуленепробиваемым, если я запущу тот же советник на том же графике - так что да... ручная установка magic# является окончательным методом защиты от дурака - без сомнения!


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

Кроме того, я помню, как irusoh1 говорил/напоминал, что "вот оно", так что живите с этим... Ну, для себя я всегда помню этот первый абзац в содержании его поста, и он *всегда* в моей голове, когда я добираюсь до точки с MT, где свободная воля к жизни :))


В MQL4 online/offline говорится о базовых типах данных. Ссылка на строку в обоих случаях ведет к строковым константам, и мы все знаем, что написано на этой странице... т.е. 255 байт.

Я полностью понимаю, о чем вы говорите, но поток 29373, как и работа MQL4 со строками во время выполнения, неубедителен и, как убедился jjc и, несомненно, многие другие, несколько сомнителен.

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

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

 
fbj:

В MQL4 online/offline говорится о базовых типах данных. Ссылка на строку в обоих документах ведет к строковым константам, и мы все знаем, что написано на этой странице... т.е. 255 байт.

Я полностью понимаю, о чем вы говорите, но поток 29373, как и обработка строк во время выполнения MQL4, неубедителен и, как убедились jjc и, несомненно, многие другие, несколько сомнителен.

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

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

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

Я знаю, что документация немного неясна по этому вопросу, но если вы попробуете просмотреть русские форумы (с помощью Google translate), я помню, что читал официальный комментарий одного из модераторов о том, что строковые переменные поддерживают более 255 байт, но я не могу найти его сейчас... Ну что ж, думаю, "вот оно" и нам придется с этим жить :)

 
fbj:

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

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

" Длина строковой константы лежит в пределах от 0 до 255 символов. Если строковая константа длиннее, лишние символы справа будут отброшены, и компилятор выдаст соответствующее предупреждение.

Ее внутреннее представление представляет собой структуру из 8 байт. Первый элемент структуры - длинное целое число, содержащее размер буфера, распределенного для строки. Второй элемент структуры - 32-порядковый адрес буфера, содержащего строку."

Цитата из словаря MetaEditor Типы данных - Строковые константы

увлекательный материал, ребята...

 

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

Разместите это в верхней части советника:

#define EAName "Вставьте имя советника сюда".

Когда вы проверяете наличие открытых ордеров, поместите это:

if (OrderType() <= OP_SELL && OrderSymbol() == Symbol() && OrderComment() == EAName && OrderMagicNumber() == MagicNumber)

Когда ваша сделка будет размещена, убедитесь, что она размещает EAName для комментария, как показано ниже:

Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0, EAName, MagicNumber, 0, Blue);

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

int MagicNumber = Period();