English 中文 Español Deutsch 日本語 Português
Моделирование беттинга как средство развития "чувства рынка"

Моделирование беттинга как средство развития "чувства рынка"

MetaTrader 4Трейдинг | 14 января 2008, 17:25
3 610 28
Eryomin Sergey
Eryomin Sergey

Введение

В данной статье рассказывается о простом механизме моделирования беттинга в режиме реального времени. Что же такое беттинг? Финансовый беттинг – от англ. Bet – ставка, пари: прогноз относительно дальнейшего хода (увеличения или уменьшения) курса того или иного финансового инструмента и получение вознаграждения, если прогноз сбывается (источник - беттинг).

Фактически, при беттинге нас интересует только одно: вырастет или упадёт финансовый инструмент. Величина этого движения нас не интересует.

Если использовать подобие беттинга, в форме игры, на малых таймфреймах, то можно развить "чувство рынка". Можно научиться "видеть" вырастет пара или упадёт. Об этом и пойдёт речь.



Концепция

Принято считать, что для трейдера очень важно знание технического анализа, фундаментального анализа, знание правил управления капиталом и многого другого. Безусловно, это всё очень важно. Однако есть ещё такое понятие, как "чувство рынка". Когда трейдер смотрит на голый ценовой график (без нанесённых индикаторов), и примерно представляет, в какую сторону далее пойдёт валютная пара. Разумеется, не всегда такое "видение" является правильным, но ошибки возможны при любом подходе к торговле. Но умение "видеть" рынок очень полезно, особенно в ситуациях, когда нужно быстро оценить ситуацию на рынке.

Обычно "чувство рынка" людям приходит с опытом, ценой многочасовых торговых экспериментов. Не редко цена этих экспериментов также исчисляется не одной тысячей долларов США.

Однако я считаю, есть способы развить это чувство более быстро и вкладывая меньше ресурсов. Один из способов – создание игры, где будет нужно угадывать направление движения торгового инструмента. Ещё лучше, если эта игра будет сопряжена с реальными торговыми условиями. Не плохо, если она будет происходить параллельно с реально идущими торгами.

Умения человека тренируемы, это не поддаётся сомнению. Мы можем научиться рисовать, петь, играть на музыкальных инструментах. Я уверен, что научиться "видеть" рынок так же можно научиться. Как можно играть в компьютерные игры, так можно научиться играть в игру "предскажи направление". Однако нужно знать, с чего начать, как это умение развивать. Для начала, нужна сама игра.



Постановка задачи

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

Под эти критерии мог бы подойти беттинг, о котором уже писалось ранее. Однако на практике это не самый лучший вариант. Существует достаточно мало Диллинговых Центров, которые предоставляют такую возможность своим клиентам. Даже если и использовать такой вариант, можно столкнуться с неудобствами. Использовать демо-счета не очень практично, т.к. это может мешать реальной торговле (отвлекать), а на реальных счетах это уже будет более опасная игра. Также, обычно, ставки при торговле через беттинг невозможно сделать на период, меньший, чем один час.

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



Реализация

Начать стоит с простого вопроса. Как это должно выглядеть? Очевидно, пользователю нужно выбрать один вариант из двух – вверх или вниз пойдёт пара, по его мнению. После этого программа должна засчитать очко, если он угадал, и убавить очко, если не угадал.

Реализация выбора, как я считаю, лучше всего будет исполнена через объекты - SYMBOL_ARROWDOWN и SYMBOL_ARROWUP (стрелочка вниз и стрелочка вверх). Можно предложить пользователю наносить нужную стрелочку на график. Но так будет много времени и внимания уходить на само нанесение стрелочки и на указание её имени. Этот вариант не подходит.

Было решено автоматически в начале новой свечи наносить стрелочку вверх и стрелочку вниз. Пользователь должен удалить одну из стрелочек. Оставшаяся стрелочка должна символизировать предположительное направление движения пары. Далее, в начале новой свечи, советник должен проверить – сбылся прогноз за предыдущую свечу или нет. Вести будем общий счёт, счёт положительных ответов и счёт отрицательных ответов. Для этого будет использована запись во внешний файл.

Звучит достаточно просто, также весьма просто реализуемо.

//+------------------------------------------------------------------+
//|                                                       trener.mq4 |
//|                                       Copyright © 2008, FXRaider |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FXRaider"
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
extern int gap=5;
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//------------------------------
string solution="none"; 
int point, 
    point_neg, 
    point_pos;
//------------------------------    
//+---------------------------------------------------------------+
//|                      поиск выбора "вверх"                     | 
 if(
    ObjectGet("up", OBJPROP_PRICE1)==Open[1]+gap*Point
    &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==1
    &&ObjectFind("down") != 0
    &&ObjectFind("up") == 0
    )
    {
     solution="up";
    }
//|                      поиск выбора "вверх"                     |  
//+---------------------------------------------------------------+
  
//+---------------------------------------------------------------+
//|                      поиск выбора "вниз"                      |     
 if(
    ObjectGet("down", OBJPROP_PRICE1)==Open[1]-gap*Point
    &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==1    
    &&ObjectFind("up") != 0
    &&ObjectFind("down") == 0
    )
    {
     solution="down";
    }
//|                      поиск выбора "вниз"                      |       
//+---------------------------------------------------------------+    
 
//+---------------------------------------------------------------+
//|             расчёт очков при положительном ответе             |
    if((solution=="up"&&Open[1]<Close[1])
      ||(solution=="down"&&Open[1]>Close[1]))
    {
     point=1;
     point_pos=1;
     point_neg=0;     
    }  
//|             расчёт очков при положительном ответе             |   
//+---------------------------------------------------------------+
 
//+---------------------------------------------------------------+
//|             расчёт очков при отрицательном ответе             |    
    if((solution=="up"&&Open[1]>Close[1])
      ||(solution=="down"&&Open[1]<Close[1]))
    {
     point=-1;
     point_pos=0;
     point_neg=1;     
    } 
//|             расчёт очков при отрицательном ответе             |
//+---------------------------------------------------------------+
 
//+----------------------------------------------------------------------------------+
//|                              работа с внешним файлом                             |       
      int handle; 
      double points,     //общий счёт
             points_pos, //счёт положительных ответов
             points_neg; //счёт отрицательных ответов 
       handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                       FILE_CSV|FILE_WRITE|FILE_READ,";");
       if(handle>0) //если файл есть, то читаем его
       { 
        points=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_pos=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_neg=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits);       
        FileClose(handle);
       } 
       
    if(solution!="none") //если выбор сделан 
    {        
      handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                      FILE_CSV|FILE_WRITE|FILE_READ,";");
      FileWrite(handle ,points+point);         //записываем общий счёт
      FileWrite(handle ,points_pos+point_pos); //записываем счёт положительных ответов
      FileWrite(handle ,points_neg+point_neg); //записываем счёт отрицательных ответов                    
      FileClose(handle); 
    } 
//|                              работа с внешним файлом                             | 
//+----------------------------------------------------------------------------------+    
 
//+------------------------------------------------------------------------------------+
//|                                 работа с объектами                                 |   
  if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0
     ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) 
    {
     ObjectDelete("down"); 
    }  
 if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0
    ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point) 
    { 
     ObjectDelete("up"); 
    } 
    
   if(ObjectFind("down") != 0&&ObjectFind("up") != 0) //если объектов нет
   {
     ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //рисуем стрелку вниз
     ObjectSet("down", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("down", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
     ObjectSet("down", OBJPROP_COLOR, Red);
 
     ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //рисуем стрелку вверх
     ObjectSet("up", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("up", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("up", OBJPROP_COLOR, Blue);
    }
//|                                 работа с объектами                                 |   
//+------------------------------------------------------------------------------------+
 
Comment("Счёт: ", points," (",points_pos,"/",points_neg,   //выводим счёт
        ") | Time: ", Hour(),":", Minute(),":", Seconds());//выводим время (для удобства) 
//----
   return(0);
  }
//+------------------------------------------------------------------+

Код снабжён комментариями.

После присоединения к графику мы получим такой результат:




На последнем баре видны две стрелочки. Одна вверх, другая вниз. Слева-вверху комментарием выводится счёт игры и терминальное время последнего тика. Счёт отображается тремя числами. Первое - общий счёт, второе (первое в скобочках) - количество положительных ответов (сбывшихся прогнозов), третье (второе в скобках) - количество отрицательных ответов (несбывшихся прогнозов). Время я решил выводить для удобства работы в полнооконном режиме (F11).


Для того, чтобы "сыграть", нужно выделить "лишнюю" стрелку двойным (по умолчанию) кликом и нажать Delete (удалить её). Останется одна, которая будет символизировать наш прогноз:



Теперь останется только ждать начала следующей свечи. Если прогноз сбудется, то "Счёт" получит вид "Счёт: 1(1/0)". Если прогноз не сбудется, то "Счёт" получит вид "Счёт: -1(0/1)". Если же цена открытия будет равна цене закрытия, то счёт не изменится. В приведённом примере прогноз не оправдался:





Усовершенствование

Поставленная задача выполнена. Однако стоит отметить один недостаток этой реализации. Выбор можно сделать на протяжении всей свечи, в том числе и в последние секунды. А это ставит под сомнение всю концепцию. Намного лучше, если выбор можно сделать, например, в течение первых 30-ти секунд после начала свечи. Введём для этого extern int переменную – "time_limit". Её значение будет представлять количество секунд, в течение которых нужно успеть сделать выбор. Если в течение указанного времени пользователь не успел сделать выбор, то обе стрелочки удаляются и не наносятся на график до следующей свечи.

Изменения затронут блок "работа с объектами" (выделено комментариями). Получившийся код:

//+------------------------------------------------------------------+
//|                                                       trener.mq4 |
//|                                       Copyright © 2008, FXRaider |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FXRaider"
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
extern int gap=5;
extern int time_limit=30;
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//------------------------------
string solution="none"; 
int point, 
    point_neg, 
    point_pos;
//------------------------------    
//+---------------------------------------------------------------+
//|                      поиск выбора "вверх"                     | 
 if(
    ObjectGet("up", OBJPROP_PRICE1)==Open[1]+gap*Point
    &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==1
    &&ObjectFind("down") != 0
    &&ObjectFind("up") == 0
    )
    {
     solution="up";
    }
//|                      поиск выбора "вверх"                     |  
//+---------------------------------------------------------------+
  
//+---------------------------------------------------------------+
//|                      поиск выбора "вниз"                      |     
 if(
    ObjectGet("down", OBJPROP_PRICE1)==Open[1]-gap*Point
    &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==1    
    &&ObjectFind("up") != 0
    &&ObjectFind("down") == 0
    )
    {
     solution="down";
    }
//|                      поиск выбора "вниз"                      |       
//+---------------------------------------------------------------+    
 
//+---------------------------------------------------------------+
//|             расчёт очков при положительном ответе             |
    if((solution=="up"&&Open[1]<Close[1])
      ||(solution=="down"&&Open[1]>Close[1]))
    {
     point=1;
     point_pos=1;
     point_neg=0;     
    }  
//|             расчёт очков при положительном ответе             |   
//+---------------------------------------------------------------+
 
//+---------------------------------------------------------------+
//|             расчёт очков при отрицательном ответе             |    
    if((solution=="up"&&Open[1]>Close[1])
      ||(solution=="down"&&Open[1]<Close[1]))
    {
     point=-1;
     point_pos=0;
     point_neg=1;     
    } 
//|             расчёт очков при отрицательном ответе             |
//+---------------------------------------------------------------+
 
//+----------------------------------------------------------------------------------+
//|                              работа с внешним файлом                             |       
      int handle; 
      double points,     //общий счёт
             points_pos, //счёт положительных ответов
             points_neg; //счёт отрицательных ответов 
       handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                       FILE_CSV|FILE_WRITE|FILE_READ,";");
       if(handle>0) //если файл есть, то читаем его
       { 
        points=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_pos=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); 
        points_neg=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits);       
        FileClose(handle);
       } 
       
    if(solution!="none") //если выбор сделан 
    {        
      handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv",
                      FILE_CSV|FILE_WRITE|FILE_READ,";");
      FileWrite(handle ,points+point);         //записываем общий счёт
      FileWrite(handle ,points_pos+point_pos); //записываем счёт положительных ответов
      FileWrite(handle ,points_neg+point_neg); //записываем счёт отрицательных ответов                    
      FileClose(handle); 
    } 
//|                              работа с внешним файлом                             | 
//+----------------------------------------------------------------------------------+    
 
//+------------------------------------------------------------------------------------+
//|                                 работа с объектами                                 |   
  if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0
     ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) 
    {
     ObjectDelete("down"); 
    }  
 if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0
    ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point)            
    { 
     ObjectDelete("up"); 
    } 
   
  int sec_lim;  
  if(!time_limit)
  {
   sec_lim=0; 
  }
  else
  {
   sec_lim=TimeCurrent()-time_limit;
  }
  if(sec_lim>ObjectGet("up",OBJPROP_TIME1)
     &&sec_lim>ObjectGet("down",OBJPROP_TIME1) 
     &&ObjectFind("down") == 0&&ObjectFind("up") == 0
     &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==0
     &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==0)            
    { 
     ObjectDelete("up"); 
     ObjectDelete("down");      
    } 
  
   if((ObjectFind("down") != 0&&ObjectFind("up") != 0) //если объектов нет
      &&sec_lim<Time[0])
   {
     ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //рисуем стрелку вниз
     ObjectSet("down", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("down", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
     ObjectSet("down", OBJPROP_COLOR, Red);
 
     ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //рисуем стрелку вверх
     ObjectSet("up", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("up", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("up", OBJPROP_COLOR, Blue);
    }      
//|                                 работа с объектами                                 |   
//+------------------------------------------------------------------------------------+
 
Comment("Счёт: ", points," (",points_pos,"/",points_neg,   //выводим счёт
        ") | Time: ", Hour(),":", Minute(),":", Seconds());//выводим время (для удобства) 
//----
   return(0);
  }
//+------------------------------------------------------------------+

Таким образом, во входных параметрах мы получаем уже две изменяемые переменные:



Переменная "gap" отвечает за количество пунктов, на которые отдалены стрелочки от цены открытия свечи. Переменная "time_limit" отвечает за количество секунд, в течение которых пользователь должен успеть сделать выбор. Если поставить значение "0", то ограничения не будет, т.е. можно делать выбор в течение всей свечи.



Заключение

В итоге получена простая версия моделирования финансового беттинга посредством MQL4. Данная игра может сильно помочь в развитии умения "видеть" рынок, помочь изучить многие закономерности при движении торговых инструментов. Реализация выполнена таким образом, чтобы внимание трейдера максимально было сосредоточено именно на ценовом графике. Операции, которые совершает трейдер, занимают очень мало времени и интуитивно понятны.

Хотелось бы сказать о результатах применения игры. Мной были достигнуты результаты в успешном прогнозировании 5-10 свечей подряд. Использовалось на пятиминутном графике.

Применяя эту игру, трейдер может научиться отвечать на один из важных вопросов. Куда именно пойдёт данный торговый инструмент? Однако есть ещё множество других важных вопросов. Сюда входит вопрос о фиксации прибыли, вопрос о фиксации убытка, вопрос об объёме открываемой сделки и многие другие вопросы. Лишь умение отвечать на все эти вопросы может дать трейдеру уверенный результат.

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

Прикрепленные файлы |
trener.mq4 (6.72 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (28)
Vitaliy Khokhlov
Vitaliy Khokhlov | 19 янв. 2008 в 05:17

Спасибо за статью и советника.

Есть над чем поразмыслить!

:)

Хочу внести пару предложений:

1. Возможность установки пределов вверх и вниз. Тоесть я могу скажем поставить на 10 пунктов вверх и 30 вниз. Пораздельности или вместе. Возможно сбудутся оба прогноза! :) Но это наверное для более высоких таймфреймов применимо.

2. Возможность установки временной границы. Тоесть делать прогноз не на следующий бар, а мкажем на несколько.

3. Для облегчения реализации вышеуказанных функций возможно поможет следующая ссылка: http://articles.mql4.com/ru/articles/1378

FXraider:
А вот об этом будет следующая статья, и будет там всё ;)
Немножко терпения)
Впрочем, могу на мыло или ещё куда скинуть этого советника уже сейчас... который я сам использую
Можно мне на мыло wito_hoh@mail.ru
[Удален] | 15 февр. 2008 в 07:43

Спасибо за статью и советник. Попробовал. Занятно. Но почувствовал определённое неудобство. НУЖНО  ВВЕСТИ ЗВУК!

Первый звуковой сигнал должен звучать за 5 сек до появления срелок.

Второй за 5 секунд до их исчезновения.

Eryomin Sergey
Eryomin Sergey | 15 февр. 2008 в 09:04
YuriF:

Спасибо за статью и советник. Попробовал. Занятно. Но почувствовал определённое неудобство. НУЖНО  ВВЕСТИ ЗВУК!

Первый звуковой сигнал должен звучать за 5 сек до появления срелок.

Второй за 5 секунд до их исчезновения.

Я подумаю об этом... только если на выходных сделаю...
Пока мне видится исполнение такое: с началом свечи появляется звук, через 5 секунд стрелочки, ещё через 5 - звук. Но, увы, точно 5 секунд выдержать будет сложно, ибо действия в советниках происходят потиково (т.е. при выполнении условия - на следующем тике).
Apelsin
Apelsin | 18 февр. 2008 в 13:34

Если использовать подобие беттинга, в форме игры, на малых таймфреймах, то можно развить "чувство рынка". Можно научиться "видеть" вырастет пара или упадёт. Об этом и пойдёт речь.
 что-то сомнительно  :(
Alex W
Alex W | 23 мая 2016 в 05:49
Binary..
Новый взгляд на эквиобъемные графики Новый взгляд на эквиобъемные графики
В статье рассматривается метод построения графиков, при котором каждый бар состоит из одинакового количества тиков.
Язык MQL4 для "чайников". Пользовательские индикаторы (часть 2) Язык MQL4 для "чайников". Пользовательские индикаторы (часть 2)
Это пятая статья из цикла "Язык MQL4 для 'чайников'". Сегодня мы научимся использовать графические объекты - очень мощное средство разработки, которое позволяет существенно расширить возможности индикаторов. Кроме того, вы можете использовать их также в скриптах и советниках. Мы узнаем как создавать объекты, изменять их параметры, проверять ошибки. Конечно, мне не удастся описать полностью все объекты, их слишком много. Но вы получите все необходимые знания, чтобы разобраться в этом самостоятельно. Также в этой статье содержится пошаговое руководство-пример по созданию сложного сигнального индикатора. При этом, многие параметры будут доступны пользователю для настройки, что позволит гибко изменять внешний вид.
Предсказание финансовых временных рядов Предсказание финансовых временных рядов
Предсказание финансовых временных рядов - необходимый элемент любой инвестиционной деятельности. Сама идея инвестиций - вложения денег сейчас с целью получения дохода в будущем - основывается на идее прогнозирования будущего. Соответственно, предсказание финансовых временных рядов лежит в основе деятельности всей индустрии инвестиций - всех бирж и небиржевых систем торговли ценными бумагами.
Отображение новостного календаря Отображение новостного календаря
В этой статье Вы можете прочитать о написании простого и удобного индикатора, отображающего в рабочей области основные экономические события, взятые с внешнего ресурса из Интернета.