English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
preview
Разработка торгового советника с нуля (Часть 13): Время и торговля (II)

Разработка торгового советника с нуля (Часть 13): Время и торговля (II)

MetaTrader 5Торговые системы | 1 июля 2022, 10:29
1 244 1
Daniel Jose
Daniel Jose

Введение

В предыдущей статье Times & Trade ( I ) мы рассмотрели альтернативную систему для организации графика, чтобы создать индикатор, позволяющий интерпретировать совершаемые на рынке операции как можно быстрее. Но мы не завершили эту систему полностью — в ней не реализована возможность показать, как можно получить доступ к определенной информации, а такой доступ помог бы лучше понять, что происходит. Эта информация не может быть представлена непосредственно на графике. На самом деле это можно было бы реализовать, но интерпретация была бы очень запутанной, поэтому лучше всего иметь данные, представленные классическим образом, то есть значения в текстовом формате. В нашем советнике нет системы, способной выполнить эту задачу. Поэтому её необходимо реализовать.

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


Планирование

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

Заметили что-то странное на этом изображении? Что-то, что может не иметь особого смысла, но оно там есть... посмотрите очень внимательно...

Если вы до сих пор не заметили ничего странного, внимательно посмотрите на выделенную область.


Теперь, может быть, вы видите, что происходит. Обратите внимание, что в этот момент были изменения значений BID и ASK, но в данной точке была совершена только одна сделка. Даже если изменилось значение BID или ASK, не имеет большого смысла иметь только одну сделку, хотя на самом деле это встречается чаще, чем кажется — подобные вещи не видны при использовании режима чтения, показанного ниже:

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

Наша система Times & Trade будет выглядить так, как показано на изображении ниже:

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

Почему же иногда тень не касается тела свечи? Почему это происходит? Бывает что тень получается с помощью значения спреда, который в свою очередь получается по разнице между BID и ASK, но в случае если внутри спреда происходит операция, то как будет выглядеть свеча? Это будет пятый тип, показанный ниже:

Другими словами, это свеча DOJI. По этой причине в системе не видны прямые ордера, но это не объясняет, почему в некоторых случаях тело не касается тени. Объяснение заключается в том, что произошло что-то, из-за чего цена двигалась слишком быстро, и по этой причине тело оторвано от свечи. Можно подумать, что это системный сбой, ведь цене нет смысла это делать. Но здесь есть смысл  — это происходит именно тогда, когда срабатывают стоп-ордера. Чтобы увидеть это, давайте посмотрим на изображение ниже:

Посмотрите, что происходит серия моментов, где есть ордера, при этом нет касания ни BID, ни ASK. Все эти точки — сработавшие стоп-ордера. Когда это происходит, цена обычно скачет, это можно увидеть на графике. Но на Times & Trade это будет заметно только в том случае, если вы используете режим графика для оценки движений, в противном случае вы не видите стопы и думаете, что теперь движение набрало силу, хотя на самом деле оно может развернуть и вы станете жертвой стопа.

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

Деталь: если эту информацию можно увидеть только с помощью свечей, а их уже достаточно, то почему же так необходимо иметь больше информации?

Большая деталь заключается в том, что бывают моменты, когда рынок замедляется, ожидая некоторой информации, которая может появиться в данный момент, и просто просмотр Times & Trade со свечами не позволяет это понять. Нужно что-то большее. Эта информация уже есть в самой системе, но ее трудно интерпретировать в том виде, в каком она поступает. Нужно моделировать данные таким образом, чтобы их было легче анализировать.

Это моделирование является причиной для написания этой статьи: после того, как это моделирование будет выполнено, Times & Trade изменится и будет выглядеть так, как показано на рисунке ниже:

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


Реализация

Для реализации системы нам нужно добавить несколько новых переменных в класс C_TimesAndTrade, их можно увидеть в следующем фрагменте:

#include <NanoEA-SIMD\Auxiliar\C_FnSubWin.mqh>
#include <NanoEA-SIMD\Auxiliar\C_Canvas.mqh>
//+------------------------------------------------------------------+
class C_TimesAndTrade : private C_FnSubWin
{
//+------------------------------------------------------------------+
#define def_SizeBuff 
2048 
#define macro_Limits(A) (A & 0xFF)
#define def_MaxInfos 257
//+------------------------------------------------------------------+
        private :
                string          m_szCustomSymbol,
                                m_szObjName;
                char            m_ConnectionStatus;
                datetime        m_LastTime;
                ulong           m_MemTickTime;
                int             m_CountStrings;
                struct st0
                {
                        string  szTime;
                        int     flag;
                }m_InfoTrades[def_MaxInfos];
                struct st1
                {
                        C_Canvas Canvas;
                        int      WidthRegion,
                                 PosXRegion,
                                 MaxY;
                        string   szNameCanvas;
                }m_InfoCanvas;

Все выделенные точки — это части, которые были добавлены в исходный код. Как видите, нам нужно использовать класс C_Canvas, но в нем нет всех нужных нам элементов,фактически мы должны добавить 4 подпрограммы в этот класс C_Canvas, и эти подпрограммы показаны во фрагменте ниже:

// ... Código da classe C_Canvas

inline void FontSet(const string name, const int size, const uint flags = 0, const uint angle = 0)
{
        if(!TextSetFont(name, size, flags, angle)) return;
        TextGetSize("M", m_TextInfos.width, m_TextInfos.height);
}
//+------------------------------------------------------------------+
inline void TextOutFast(int x, int y, string text, const uint clr, uint alignment = 0)
{
        TextOut(text, x, y, alignment, m_Pixel, m_width, m_height, clr, COLOR_FORMAT_ARGB_NORMALIZE);
}
//+------------------------------------------------------------------+
inline int TextWidth(void) const { return m_TextInfos.width; }
//+------------------------------------------------------------------+
inline int TextHeight(void) const { return m_TextInfos.height; }
//+------------------------------------------------------------------+

// ... Restante do código ...

Эти строки создают для текст, это очень просто, ничего чересчур элегантного.

Следующая заслуживающая упоминания функция в классе C_TimesAndTrade показана чуть ниже:

void PrintTimeTrade(void)
{
        int ui1;
        
        m_InfoCanvas.Canvas.Erase(clrBlack, 220);
        for (int c0 = 0, c1 = m_CountStrings - 1, y = 2; (c0 <= 255) && (y < m_InfoCanvas.MaxY); c0++, c1--, y += m_InfoCanvas.Canvas.TextHeight())
        if (m_InfoTrades[macro_Limits(c1)].szTime == NULL) break; else
        {
                ui1 = m_InfoTrades[macro_Limits(c1)].flag;
                m_InfoCanvas.Canvas.TextOutFast(2, y, m_InfoTrades[macro_Limits(c1)].szTime, macroColorRGBA((ui1 == 0 ? clrLightSkyBlue : (ui1 > 0 ? clrForestGreen : clrFireBrick)), 220));
        }
        m_InfoCanvas.Canvas.Update();
}

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

void Init(const int iScale = 2)
{
        if (!ExistSubWin())
        {
                m_InfoCanvas.Canvas.FontSet("Lucida Console", 13);
                m_InfoCanvas.WidthRegion = (18 * m_InfoCanvas.Canvas.TextWidth()) + 4;
                CreateCustomSymbol();
                CreateChart();
                m_InfoCanvas.Canvas.Create(m_InfoCanvas.szNameCanvas, m_InfoCanvas.PosXRegion, 0, m_InfoCanvas.WidthRegion, TerminalInfoInteger(TERMINAL_SCREEN_HEIGHT), GetIdSubWinEA());
                Resize();
                m_ConnectionStatus = 0;
        }
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_CHART_SCALE, (iScale > 5 ? 5 : (iScale < 0 ? 0 : iScale)));
}

Необходимо изменить подпрограмму замен в измерениях Times & Trade, и эти замены также заслуживают внимания, их можно увидеть во фрагменте ниже:

void Resize(void)
{
        static int MaxX = 0;
        int x = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WIDTH_IN_PIXELS, GetIdSubWinEA());
        
        m_InfoCanvas.MaxY = (int) ChartGetInteger(Terminal.Get_ID(), CHART_HEIGHT_IN_PIXELS, GetIdSubWinEA());
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_YSIZE, m_InfoCanvas.MaxY);
        if (MaxX != x)
        {
                MaxX = x;
                x -= m_InfoCanvas.WidthRegion;
                ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_XSIZE, x);
                ObjectSetInteger(Terminal.Get_ID(), m_InfoCanvas.szNameCanvas, OBJPROP_XDISTANCE, x);
        }
        PrintTimeTrade();
}

При всем этом система практически готова, но еще не хватает подпрограммы, которая является сердцем системы и которая также претерпела изменения.

inline void Update(void)
{
        MqlTick Tick[];
        MqlRates Rates[def_SizeBuff];
        int i0, p1, p2 = 0;
        int iflag;
        long lg1;
        static int nSwap = 0;
        static long lTime = 0;

        if (m_ConnectionStatus < 3) return;
        if ((i0 = CopyTicks(Terminal.GetFullSymbol(), Tick, COPY_TICKS_ALL, m_MemTickTime, def_SizeBuff)) > 0)
        {
                for (p1 = 0, p2 = 0; (p1 < i0) && (Tick[p1].time_msc == m_MemTickTime); p1++);
                for (int c0 = p1, c1 = 0; c0 < i0; c0++)
                {
                        lg1 = Tick[c0].time_msc - lTime;
                        nSwap++;
                        if (Tick[c0].volume == 0) continue;
                        iflag = 0;
                        iflag += ((Tick[c0].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY ? 1 : 0);
                        iflag -= ((Tick[c0].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL ? 1 : 0);
                        if (iflag == 0) continue;
                        Rates[c1].high = Tick[c0].ask;
                        Rates[c1].low = Tick[c0].bid;
                        Rates[c1].open = Tick[c0].last;
                        Rates[c1].close = Tick[c0].last + ((Tick[c0].volume > 200 ? 200 : Tick[c0].volume) * (Terminal.GetTypeSymbol() == C_Terminal::WDO ? 0.02 : 1.0) * iflag);
                        Rates[c1].time = m_LastTime;
                        m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume);
                        m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag;
                        m_CountStrings++;
                        nSwap = 0;
			lTime = Tick[c0].time_msc;
                        p2++;
                        c1++;
                        m_LastTime += 60;
                }
                CustomRatesUpdate(m_szCustomSymbol, Rates, p2);
                m_MemTickTime = Tick[i0 - 1].time_msc;
        }
        PrintTimeTrade();
}

Все выделенные строки — это код, добавленный в подпрограмму для моделирования нужных нам данных, следующий фрагмент

lg1 = Tick[c0].time_msc - lTime;
nSwap++;

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

Теперь фрагмент

m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume);
m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag;
m_CountStrings++;
nSwap = 0;                                      
lTime = Tick[c0].time_msc;

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

После того, как все реализовали, компилируем советника и получаем примерно следующее:


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

Этот индикатор настолько мощный и такой информативный, что я решил сделать видео, показывающее небольшое сравнение между ним и РЕАЛЬНЫМИ данными, которые показал актив на момент записи... Я хочу показать, что он фильтрует много информации, позволяя читать данные намного быстрее и лучше понимать происходящее... Надеюсь, вам понравится, и вы воспользуетесь преимуществами этого фантастического и мощного индикатора.




Заключение

Предлагаемая здесь система является просто модификацией системы графиков, присутствующей в самой платформе MetaTrader 5, только с немного другим моделированием данных. Может быть несколько любопытно посмотреть, как закрытые операции влияют на направление цен, формируя микроструктуры во временных рамках самого низкого значения, доступного на платформах, которое составляет 1 минуту. Многие люди любят говорить, что они торгуют на минутном таймфрейме, как будто это означает, что они обладают высоким уровнем знаний о рыночных операциях, но когда мы внимательно присматриваемся и понимаем торговые процессы, мы видим, что за 1 минуту происходит много вещей, и, несмотря на то, что это кажется коротким промежутком времени, это то, что пропускает многие потенциально прибыльные операции. Помните, что в этой системе Times & Trade мы не смотрим на то, что происходит за 1 минуту, значения, которые появляются на экране, котируются в миллисекундах...


Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/10412

Прикрепленные файлы |
EA_-_Times_m_Trade.zip (5983.76 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (1)
Sergei Poliukhov
Sergei Poliukhov | 3 июл. 2022 в 16:03
подскажите пожалуйста , метатреййдер какого брокера используете ?
Разработка торговой системы на основе индикатора MACD Разработка торговой системы на основе индикатора MACD
В этой статье мы познакомимся с очередным инструментом из нашей серии: мы узнаем, как создать торговую систему на основе одного из самых популярных технических индикаторов — Moving Average Convergence Divergence (MACD).
Нейросети — это просто (Часть 18): Ассоциативные правила Нейросети — это просто (Часть 18): Ассоциативные правила
В продолжение данной серии статей предлагаю познакомиться ещё с одним типом задач из методов обучения без учителя — поиск ассоциативных правил. Данный тип задач впервые был применен в ритейле для анализа корзин покупателей. О возможностях использования подобных алгоритмов в рамках трейдинга мы и поговорим в этой статье.
Видео: Простая автоматизированная торговля – Как создать простой торговый советник с помощью MQL5 Видео: Простая автоматизированная торговля – Как создать простой торговый советник с помощью MQL5
Большинство слушателей моих курсов считали, что язык MQL5 сложен для понимания. Кроме того, они искали простые способы автоматизации некоторых процессов. В этой статье вы узнаете как сходу начать работать в MQL5 даже без навыков программирования и даже если в прошлом у вас уже были неудачные попытки освоить эту тему.
DoEasy. Элементы управления (Часть 9): Реорганизация методов WinForms-объектов, элементы управления "RadioButton" и "Button" DoEasy. Элементы управления (Часть 9): Реорганизация методов WinForms-объектов, элементы управления "RadioButton" и "Button"
В статье наведём порядок в наименованиях методов классов WinForms-объектов и создадим WinForms-объекты Button и RadioButton.