Функция MathRand()

 

В этой ветке хотелось бы поговорить на тему реализации функции MathRand() в коде. Практическиие варианты применения. Идеи появились после прочтения статей Rosh'a.

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

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

Вариант советника, который случайным образом открывается, случайным образом закрывается. Какую прибыль/убыток он сможет принести при включении в его работу стоп-лосса? И как он себя поведёт при включении тейк-профита? Тестирование прогоняется 100 раз для единственного параметра: либо стоп-лосса, либо тейк-профита. Лот определённый и постоянный: его значение в дальнейшем понадобится для вычисления математического ожидания сделки в пунктах, при отсутствии комиссии по спреду. Есть и минус в подходе. А точнее: имеются не рандомные параметры, задающие среднюю частоту случайных открытий позиций и средний случайный период удержания позиции в рынке. Как обойти это пока не знаю. Но всё равно, и в этом случае, ответ дадут полученные результаты.

Ниже приводится код:

/*
Изменённый RandomTrade-4
Изменения:
1. Случайные открываемые сделки теперь будут открываться независимо от наличия ранее открытых позиций.
2. Переменные отношений SL и TP убираются полностью. Вместо этого будет (п.3 и 4):
3. Определение оптимального SL при случайном закрытии открытой позиции.
4. Определение оптимального TP при случайном закрытии открытой позиции.
5. Средняя частота открытия случайных позиций будет браться как одна позиция на каждые OpRandPeriod баров.
6. Среднее случайное время удержания открытых позиций  будет равно ClRandPeriod баров.
Предназначен для минутных баров.
*/

extern int Balk=1; // прогоняемая переменная оптимизатора
extern int SL=50; // значение стоп-лосса
extern int TP=50; // значение тейк-профита
extern int OpRandPeriod=30; // средний период времени в барах между открытиями случайных позиций
extern int ClRandPeriod=300; // средний период времени в барах удержания открытых позиций
extern bool Take_NotStop=true; // при true оптимизируется уровень цели, при false оптимизируется уровень стопа

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   MathSrand( GetTickCount());
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   MathSrand( GetTickCount());   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| возвращает тикет , при удачном открытиии ордера                  |
//+------------------------------------------------------------------+
int GetOrder()
  {
   int ticket;
   double StopLoss, TakeProfit;
   double Random=MathRand()/32768.0; // случайное значение в диапазоне [0;1)
   if (Random<0.5)
         {
         // Покупка
         if (Take_NotStop) {TakeProfit=NormalizeDouble(Bid+TP*Point,Digits); StopLoss=0;}
         else {StopLoss=NormalizeDouble(Bid-SL*Point,Digits); TakeProfit=0;}
         ticket=OrderSend(Symbol(),OP_BUY,0.1,Ask,3,StopLoss,TakeProfit,"",OP_BUY,0,Blue);
         }
   else
         {
         // Продажа
         if (Take_NotStop) {TakeProfit=NormalizeDouble(Ask-TP*Point,Digits); StopLoss=0;}
         else {StopLoss=NormalizeDouble(Ask+SL*Point,Digits); TakeProfit=0;}
         ticket=OrderSend(Symbol(),OP_SELL,0.1,Bid,3,StopLoss,TakeProfit,"",OP_SELL,0,Red);
         }
   return(ticket);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
  if(Volume[0]>1) return(0); 
  int ticket, RandCl;
  int RandOp=MathRand()*OpRandPeriod/32768; // случайное значение в диапазоне [0;OpRandPeriod)

  for(int i=0;i<OrdersTotal();i++)
     {
      RandCl=MathRand()*ClRandPeriod/32768; // случайное значение в диапазоне [0;ClRandPeriod)
      if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) {Print("Oшибка при выборе ордера #",GetLastError()); continue;}
      if (OrderSymbol()!=Symbol()) continue;
      if (RandCl !=0) continue;
      if (OrderType()==0) OrderClose(OrderTicket(),0.1,Bid,3,Blue);
      if (OrderType()==1) OrderClose(OrderTicket(),0.1,Ask,3,Red);
     }
  
   if (RandOp==0) ticket=GetOrder();

   return(0);
  }
//+------------------------------------------------------------------+
Хочу также отметить, что любая критика по теме будет мной приветствоваться. Результаты следуют.
Файлы:
 
if (Take_NotStop)
Я конечно не программер, но if - else условный оператор т.е. что то с чем то должно сравниваться, или я не прав?
 
Murman писал(а) >>
Я конечно не программер, но if - else условный оператор т.е. что то с чем то должно сравниваться, или я не прав?

Если переменная типа bool то так можно. Тоже самое, что if(Take_NotStop==true)

 
Murman писал(а) >>
Я конечно не программер, но if - else условный оператор т.е. что то с чем то должно сравниваться, или я не прав?

После if проверяется истинность/ложность условия/выражения, стоящего в скобках.

Если Булева переменная bool (как указал Integer), то она может иметь только два значения true/false = истина/ложь.

 

Протестировав советник на EUR/USD-М1 за годовой ближайший период истории, при десятичасовом среднем случайном периоде удержания позиции (ClRandPeriod=600) получим следующие результаты:

На верхней картинке график МО промасштабирован по максимальным полученным значениям (по пику).

Видно, что если бы мы имели ТС со статистическим средним периодом удержания позиции - около 10 часов, то наличие в ТС стоп-лосса размером в 37-38 пунктов приводит к положительному математическому ожиданию, чуть-более 0.5 пунктов на сделку. Т.е. при отсутствии комиссии по спреду, рандомная система с наличием стоп-лосса будет приносить нам прибыль.

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

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

Утверждение "Ограничивай убытки, давай прибыли расти" подтверждается.

П.С.

Так как прогон оптимизатора с Balk=1,2,....,100 для каждого фиксированного значения стопа/цели длится продолжительное время, то неплохо было бы увидеть другие валютные пары, другие периоды тестирования и другие значения среднего периода удержания позиции. Буду рад, если ув. форумчане поделятся своими результатами для более наглядного представления данной закономерности.

При тестировании желательно выбрать максимальный размер депозита: 50000 (чтобы депозит не достиг "дна" и при наихудшем случае). Для нахождения МО необходимо к  полученной прибыли (она скорее будет отрицательной, т.к. учитываются комиссионные) прибавить количество сделок*спред (для исключения комиссионных), результат перевести в пункты, а полученное значение  разделить на количество сделок. Аналогичную процедуру проделываем 100 раз для Balk=1,2,...,100. Итоговым значением будет среднее МО для отдельно взятого значения стопа/цели. Для нахождения МО последующих значений стопов/целей всю процедуру я уже привёл выше.

 

Следующий вариант применения функции:
Очень часто бывает не понятно: почему ТС на тестере получает прибыль, а когда выпускаем её на работу, то сразу начинает "буксовать"?
Один из множества вариантов ответа такой: мы тестировали её в идеальных условиях, а реал - есть реал.
Данная попытка смоделировать реал, заключается в том, чтобы тестируемая система ещё на стадии тестирования временами получала отказ на открытие позиции.
В итоге мы должны будем увидеть, насколько качество реала способно повлиять на наши основные характеристики системы.
Я называю эту проверку: проверкой ТС на качество связи.
Т.е. важно понять, что перед выпуском ТС, сначала следует её "поиметь" со всех сторон. Чем больше испытаний для неё придумаете, тем закалённей она будет в реале.
Вариант кода, включаемого в советник для проведения указанного испытания (опять же - минутный таймфрейм, наверно любымый потому-что):

/* 
Вспомогательный код, включаемый в торговую систему при её испытаниях на качество связи с сервером.
Если математическое ожидание результатов при использовании этого испытания останется равным
результатам тестирования без использования этого испытания, то система испытание прошла.
Если математическое ожидание результатов при использовании этого испытания будет меньше
результатов тестирования без использования этого испытания, то система не допускается к работе на реале.
*/
extern int Balk=1; // прогоняемая переменная оптимизатора
extern int K=90; // среднестатистический период беспроблемной торговли (в барах)
extern int T=5; // максимальное статистическое проблемное время (в барах)
//----
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   MathSrand( GetTickCount());
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   MathSrand( GetTickCount());   
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   if (Volume[0]>1 || K<=0 || T<=0) return(0); // внутрибарное тестирование не производится или некорректно заданы параметры К и Т
   static int RandomT; // период форсмажорного бездействия
   static int RNDcounter; // счётчик форсмажорного бездействия
   // при RandomT==RNDcounter нет никаких "проблем"
   if (RNDcounter<RandomT) {RNDcounter++; return(0);} // "глухо как в танке"
   else {RNDcounter=0; RandomT=0;} // всё ОК. Торгуем.
   int RandomK=MathRand()*K/32768; // int [0;K) Светофор "неприятностей"
   if (RandomK==0) // если случилась "неприятность", то смоделируем её продолжение
       {
       RandomT=MathRand()*T/32768; // int [0;Т) определение проблемного периода
       return (0);
       }
  //----    
   return(0);    
  }


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

Файлы:
 
coaster >>:

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

Утверждение "Ограничивай убытки, давай прибыли расти" подтверждается.

вставлю свои 5 копеек и собственную цитату из другой темы

"при первых же опытах убедился что прибыльные сделки должны быть длиннее убыточных и тогда можно на входе играть в орлянку"

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

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


 
blend >>:

посчитав, пришел к выводу, что соотношение тренда и флета состовляет 5 к 1


А подсчёты можете показать? Там должны быть указаны Ваши критерии тренда и флета, а также диапазон временной выборки (т.е. ширина временного шаблона, накладываемого на любой участок времени для указанного Вами статистического расчёта). А то у меня другая информация имеется.

 
coaster >>:

А подсчёты можете показать? Там должны быть указаны Ваши критерии тренда и флета, а также диапазон временной выборки (т.е. временной шаблон накладываемый на любой участок времени).

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

 
coaster >>:

А то у меня другая информация имеется.

про информацию подробнее, интересно

 
blend >>:

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

:)

Опять же. Прошу не забыть учесть одну немаловажную деталь. У меня в примере среднестатистическая продолжительность жизни сделки десятичасовая (ClRandPeriod=600), т.е. более приближённая к интрадею. А это и есть параметр, способный повлиять на результаты.

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