Библиотека для простого и быстрого создания программ для MetaTrader (Часть XVII): Интерактивность объектов библиотеки
Содержание
- Методы контроля событий базового объекта библиотеки
- Ставим класс символа и коллекцию символов на новые рельсы
- Тест событийного функционала базового объекта всех объектов библиотеки
- Что дальше
В прошлой статье нами был создан базовый объект всех объектов библиотеки, и
теперь любой объект, унаследованный от базового, получает событийный функционал — можно легко отслеживать события, происходящие в
свойствах класса-наследника базового объекта.
Сегодня пойдём чуть далее, и наделим этот объект, а значит — и любые другие объекты библиотеки, возможностью устанавливать какие
именно свойства будут контролироваться извне на предмет их изменений, размера контролируемого изменения и величину контролируемого
уровня значения свойства объекта. Таким образом, всем объектам библиотеки будет добавлен функционал, позволяющий пользователю
интерактивно взаимодействовать с объектами библиотеки.
Например, чтобы открыть позицию, нам хочется учесть размер спреда и уровень цены. Мы легко сможем установить контролируемый размер
спреда и отследить пересечение ценой заданного уровня, после чего открыть позицию. Достаточно программно установить размер спреда,
меньше которого возможна торговля, и значение уровня цены, при пересечении которого нам будет послано событие от объекта-символа в
программу о разрешении торговли по размеру спреда и пересечению ценой контролируемого уровня.
И ещё, что немаловажно, мы избавимся от необходимости использования флагов событий (что накладывает ограничение на количество
возможных для отслеживания событий и обязывает хранить списки-перечисления всех возможных типов событий для каждого объекта). Теперь
количество возможных событий будет соответствовать количеству свойств объекта — целочисленных и вещественных. Те свойства, которые
отслеживать не нужно, будут инициализироваться значением
LONG_MAX, и соответственно — не участвовать в
поиске событий объекта.
Так как объекты библиотеки хранятся в своих коллекциях, то обновление свойств объектов в коллекции мы производим в таймере библиотеки при
помощи методов Refresh() коллекций, где в свою очередь вызываются методы Refresh() объектов, хранящихся в списке-коллекции. Так вот,
если мы будем отслеживать в базовом объекте, в его методе Refresh() изменение свойств объекта-наследника на предмет их изменения на
заданные величины, то таким образом у нас получится создать простую событийную модель для каждого из объектов библиотеки. И каждый из
объектов будет отправлять в главный объект библиотеки
CEngine список своих событий.
Таким образом, программа,
построенная на базе библиотеки, всегда будет знать о всех событиях, произошедших в любом из объектов любой коллекции. И мы всегда сможем
для каждого объекта любой коллекции программно задавать и изменять размер контролируемой величины для любого свойства.
И всё это при помощи простого класса базового объекта всех объектов библиотеки.
Методы контроля событий базового объекта библиотеки
Работа с событиями базовых объектов библиотеки будет организована следующим образом: ранее для определения событий конкретного класса мы
делали для него свои методы контроля событий, создавали флаги событий и перечисления возможных событий объектов. Теперь же, когда
контроль событий классов-наследников будет организован в их единственном базовом классе, нам необходимо сделать универсальный
контроль событий — будь то, например, события символа или события аккаунта, либо события любого другого класса, который будет создан в
будущем. Поэтому здесь подходит контроль за изменением состояний свойств объекта: целочисленных и вещественных — их список для каждого
класса-наследника уникален и будет представлять собою
идентификатор события. Также нам необходимо будет учитывать направление изменения свойств — увеличение или уменьшение значения
свойства — назовём это
причиной события, и величину, на которую было изменено свойство объекта. Идентификатор события, его причину и
величину изменения будем записывать в простой класс базового события объекта и сохранять в списке одновременно произошедших событий.
Ранее мы определились, что для отправки событий в программу мы будем использовать событие со строго заданными параметрами
(идентификатор события, long-значение, double-значение и string-значение события), и в long-параметре мы отправляли время события в
милисекундах. А сейчас, в связи с изменившейся концепцией определения событий, нам необходимо точно определять событие по нескольким
его параметрам:
- Идентификатор события — свойство объекта, которое было изменено. У каждого объекта имеются свои уникальные свойства, и нет возможности в программе, которая ничего не знает в каком из объектов изменено свойство, и какое из свойств этого объекта изменено — целочисленное или вещественное, поэтому по идентификатору события однозначно его определить нет возможности
- Причина события — увеличение или уменьшение значения свойства, либо пересечение контролируемого уровня. Данное значение так же не даёт
нам возможности точно определить событие. Но по идентификатору события и по его причине мы можем уже определить, что такое-то
свойство некоего объекта было либо увеличено, либо уменьшено, либо пересекло заданную контролируемую величину. Поэтому нам
необходимо для точной идентификации события указать на идентификатор класса, в объекте которого произошло событие.
Таким идентификатором однозначно может служить идентификатор списка коллекции — от точно указывает на принадлежность объекта к определённому классу — символ, аккаунт, либо ещё какой-то иной, созданный в будущем объект коллекции. Поэтому в событие необходимо отправить ещё:
- Идентификатор коллекции — тогда все три вышеназванных идентификатора позволят однозначно определить событие.
- Строковое свойство события — наименование объекта, в котором произошло событие.
Итак, мы видим, что для определения события нам необходимо получить три целочисленных параметра, но ещё и как-то получить время события,
которое так же передаётся посредством long-значения. А у нас есть лишь одно long-свойство события. Как быть? Выход простой: мы будем
передавать в одном long-параметре сразу три целочисленных события, но с типом ushort. Тип long имеет восемь байтов, а тип ushort — два
байта. Значит в long-контейнере мы можем хранить три ushort-числа, записанные в 0,1 байты, 2,3 байты, 4,5 байты long-числа, и у нас
останется ещё два байта 6 и 7 для передачи ещё одного ushort-значения если это потребуется в дальнейшем.
Для определения времени события, на котором оно произошло, нам достаточно передать лишь милисекунды времени в 0 и 1 байтах
long-параметра.
- Дату и время события можно будет взять из TimeCurrent() при
получении события и прибавить к этому времени количество милисекунд, переданных в нулевом и первом байтах long-значения события.
- Причину события мы будем записывать во 2-й и 3-й байты long-параметра события, а
- идентификатор класса — в 4-й и 5-й байты long-параметра события.
Таким образом, при получении события, мы извлечём из long-параметра три ushort-значения и по ним сможем определить время события и получить дополнительные данные для точной идентификации события по идентификатору события, передаваемому в качестве ushort-параметра custom_event_id в EventChartCustom() и составить из идентификатора события и двух дополнительно-полученных значений из lparam точный идентификатор произошедшего события.
Для определения событий в свойствах объекта-наследника в объекте-родителе (в базовом объекте всех объектов библиотеки) будем в таймере проверять текущее состояние каждого из свойств объекта и сравнивать его с прошлым состоянием этого свойства. В первую очередь будем проверять задано ли значение, величину которого нужно сравнивать с величиной, на которую изменилось значение свойства. Если проверяемое значение не задано (установлено для него LONG_MAX), то это свойство игнорируется.
Ввиду того, что мы будем проверять списки свойств объекта, имеющие разные типы — long и double, то для хранения текущего и прошлого состояний свойств объекта я решил, что целесообразнее использовать двумерные массивы, а не структуру. В первом измерении массива будут храниться индексы свойств объекта, а во втором — значения свойства, индекс которого вписан в первое измерение, величина изменения свойства, контролируемые значения и флаги событий данного свойства.
Поясню почему удобнее использовать массивы, а не структуру:
Мы заранее не знаем свойство какого типа будем
проверять, но можем понять о его типе из индекса свойства (double-свойства объекта всегда расположены после long-свойств), а значит — нам
не придётся в структуре дублировать поля — для long- и для double-значений одного и того же проверяемого значения свойства объекта. Мы
просто будем записывать в массив нужного типа (соответствующий типу свойства, определённому из индекса свойства) все необходимые
данные для контроля состояний свойства объекта с их правильным типом, и не нужно будет выбирать в какое поле структуры вписывать
переданное значение - в long или double.
Как только определено изменение любого из свойств объекта, мы его добавляем в список базовых событий объекта (так как поиск ведётся в
базовом объекте, то и событие будет базовым, и его не нужно путать с событием класса-наследника, которое далее будет определяться по
списку базовых событий и создаваться из базовых событий, указатели на которые хранятся в этом списке).
В методах Refresh() каждого класса-наследника базового объекта проверяются в таймере списки произошедших изменений свойств (списки базовых событий) и при наличии в списках объектов этих событий, каждое событие преобразуется в событие библиотеки и отправляется в управляющую программу.
И для "полноты картины" нам необходимо будет создать методы, позволяющие программно установить контролируемые величины изменений для любого свойства любого объекта библиотеки, созданного на основе базового объекта. Тогда мы в любой момент времени сможем оперативно изменять необходимые в программе условия генерации событий от нужных нам объектов.
Комплекс всех проведённых сегодня мероприятий по доработке базового объекта библиотеки позволит нам далее не задумываться о создании контроля событий для всех впоследствии создаваемых объектов — мы будем лишь пользоваться подготовленным сегодня функционалом.
Итак, приступим.
Так как мы теперь будем работать с событиями в базовом объекте всех объектов библиотеки, то для идентификации событий нужно создать
перечисление причин события.
В файл \MQL5\Include\DoEasy\ Defines.mqh после вариантов выбора по времени
впишем перечисление
возможных причин событий базового объекта:
//+------------------------------------------------------------------+ //| Возможные варианты выбора по времени | //+------------------------------------------------------------------+ enum ENUM_SELECT_BY_TIME { SELECT_BY_TIME_OPEN, // По времени открытия (в милисекундах) SELECT_BY_TIME_CLOSE, // По времени закрытия (в милисекундах) }; //+------------------------------------------------------------------+ //| Возможные причины событий базового объекта объектов библиотеки | //+------------------------------------------------------------------+ enum ENUM_BASE_EVENT_REASON { BASE_EVENT_REASON_INC, // Увеличение значения свойства объекта BASE_EVENT_REASON_DEC, // Уменьшение значения свойства объекта BASE_EVENT_REASON_MORE_THEN, // Значение свойства объекта стало больше контрольного значения BASE_EVENT_REASON_LESS_THEN, // Значение свойства объекта стало меньше контрольного значения BASE_EVENT_REASON_EQUALS // Значение свойства объекта стало равно контрольному значению }; //+------------------------------------------------------------------+
Так как теперь нам не нужны будут флаги событий, то вместо списков флагов событий символа
впишем список
возможных событий символов в окне "Обзор рынка":
//+------------------------------------------------------------------+ //| Данные для работы с символами | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Список возможных событий символов в окне "Обзор рынка" | //+------------------------------------------------------------------+ enum ENUM_MW_EVENT { MARKET_WATCH_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // Нет события MARKET_WATCH_EVENT_SYMBOL_ADD, // Добавление символа в окно "Обзор рынка" MARKET_WATCH_EVENT_SYMBOL_DEL, // Удаление символа из окна "Обзор рынка" MARKET_WATCH_EVENT_SYMBOL_SORT, // Сортировка символов в окне "Обзор рынка" }; #define SYMBOL_EVENTS_NEXT_CODE (MARKET_WATCH_EVENT_SYMBOL_SORT+1) // Код следующего события после последнего кода события символа //+------------------------------------------------------------------+
А список возможных событий символа просто удалим за ненадобностью:
//+------------------------------------------------------------------+ //| Список возможных событий символа | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_EVENT { SYMBOL_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // Нет события SYMBOL_EVENT_MW_ADD, // Добавление символа в окно "Обзор рынка" SYMBOL_EVENT_MW_DEL, // Удаление символа из окна "Обзор рынка" SYMBOL_EVENT_MW_SORT, // Сортировка символов в окне "Обзор рынка" SYMBOL_EVENT_TRADE_DISABLE, // Запрет исполнения ордеров SYMBOL_EVENT_TRADE_LONGONLY, // Разрешены только операции покупки SYMBOL_EVENT_TRADE_SHORTONLY, // Разрешены только продажи SYMBOL_EVENT_TRADE_CLOSEONLY, // Разрешены только операции закрытия позиций SYMBOL_EVENT_TRADE_FULL, // Нет ограничений на торговые операции SYMBOL_EVENT_SESSION_DEALS_INC, // Увеличение количества сделок в текущей сессии больше заданной величины SYMBOL_EVENT_SESSION_DEALS_DEC, // Уменьшение количества сделок в текущей сессии больше заданной величины SYMBOL_EVENT_SESSION_BUY_ORDERS_INC, // Увеличение общего числа ордеров на покупку в текущий момент больше заданной величины SYMBOL_EVENT_SESSION_BUY_ORDERS_DEC, // Уменьшение общего числа ордеров на покупку в текущий момент больше заданной величины SYMBOL_EVENT_SESSION_SELL_ORDERS_INC, // Увеличение общего числа ордеров на продажу в текущий момент больше заданной величины SYMBOL_EVENT_SESSION_SELL_ORDERS_DEC, // Уменьшение общего числа ордеров на продажу в текущий момент больше заданной величины SYMBOL_EVENT_VOLUME_INC, // Увеличение объёма в последней сделке больше заданной величины SYMBOL_EVENT_VOLUME_DEC, // Уменьшение объёма в последней сделке больше заданной величины SYMBOL_EVENT_VOLUME_HIGH_DAY_INC, // Увеличение максимального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_HIGH_DAY_DEC, // Уменьшение максимального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_LOW_DAY_INC, // Увеличение минимального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_LOW_DAY_DEC, // Уменьшение минимального объёма за день больше заданной величины SYMBOL_EVENT_SPREAD_INC, // Увеличение размера спреда больше заданной величины SYMBOL_EVENT_SPREAD_DEC, // Уменьшение размера спреда больше заданной величины SYMBOL_EVENT_STOPLEVEL_INC, // Увеличение уровня Stop-ордеров больше заданной величины SYMBOL_EVENT_STOPLEVEL_DEC, // Уменьшение уровня Stop-ордеров больше заданной величины SYMBOL_EVENT_FREEZELEVEL_INC, // Увеличение уровня заморозки больше заданной величины SYMBOL_EVENT_FREEZELEVEL_DEC, // Уменьшение уровня заморозки больше заданной величины SYMBOL_EVENT_BID_LAST_INC, // Увеличение цены Bid или Last больше заданной величины SYMBOL_EVENT_BID_LAST_DEC, // Уменьшение цены Bid или Last больше заданной величины SYMBOL_EVENT_BID_LAST_HIGH_INC, // Увеличение максимальной цены Bid или Last за день больше заданной величины SYMBOL_EVENT_BID_LAST_HIGH_DEC, // Уменьшение максимальной цены Bid или Last за день больше заданной величины по отношению к заданной цене SYMBOL_EVENT_BID_LAST_LOW_INC, // Увеличение минимальной цены Bid или Last за день больше заданной величины по отношению к заданной цене SYMBOL_EVENT_BID_LAST_LOW_DEC, // Уменьшение минимальной цены Bid или Last за день больше заданной величины SYMBOL_EVENT_ASK_INC, // Увеличение цены Ask больше заданной величины SYMBOL_EVENT_ASK_DEC, // Уменьшение цены Ask больше заданной величины SYMBOL_EVENT_ASK_HIGH_INC, // Увеличение максимальной цены Ask за день больше заданной величины SYMBOL_EVENT_ASK_HIGH_DEC, // Уменьшение максимальной цены Ask за день больше заданной величины SYMBOL_EVENT_ASK_LOW_INC, // Увеличение минимальной цены Ask за день больше заданной величины SYMBOL_EVENT_ASK_LOW_DEC, // Уменьшение минимальной цены Ask за день больше заданной величины SYMBOL_EVENT_VOLUME_REAL_DAY_INC, // Увеличение реального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_REAL_DAY_DEC, // Уменьшение реального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_INC, // Увеличение максимального реального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_DEC, // Уменьшение максимального реального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_INC, // Увеличение минимального реального объёма за день больше заданной величины SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_DEC, // Уменьшение минимального реального объёма за день больше заданной величины SYMBOL_EVENT_OPTION_STRIKE_INC, // Увеличение цены исполнения опциона больше заданной величины SYMBOL_EVENT_OPTION_STRIKE_DEC, // Уменьшение цены исполнения опциона больше заданной величины SYMBOL_EVENT_VOLUME_LIMIT_INC, // Увеличение максимально допустимого совокупного объема позиции и отложенных ордеров в одном направлении SYMBOL_EVENT_VOLUME_LIMIT_DEC, // Уменьшение максимально допустимого совокупного объема позиции и отложенных ордеров в одном направлении SYMBOL_EVENT_SWAP_LONG_INC, // Увеличение свопа длинных позиций SYMBOL_EVENT_SWAP_LONG_DEC, // Уменьшение свопа длинных позиций SYMBOL_EVENT_SWAP_SHORT_INC, // Увеличение свопа коротких позиций SYMBOL_EVENT_SWAP_SHORT_DEC, // Уменьшение свопа коротких позиций SYMBOL_EVENT_SESSION_VOLUME_INC, // Увеличение суммарного объёма сделок в текущую сессию больше заданной величины SYMBOL_EVENT_SESSION_VOLUME_DEC, // Уменьшение суммарного объёма сделок в текущую сессию больше заданной величины SYMBOL_EVENT_SESSION_TURNOVER_INC, // Увеличение суммарного оборота в текущую сессию больше заданной величины SYMBOL_EVENT_SESSION_TURNOVER_DEC, // Уменьшение суммарного оборота в текущую сессию больше заданной величины по отношению к заданному обороту SYMBOL_EVENT_SESSION_INTEREST_INC, // Увеличение суммарного объёма открытых позиций в текущую сессию больше заданной величины SYMBOL_EVENT_SESSION_INTEREST_DEC, // Уменьшение суммарного объёма открытых позиций в текущую сессию больше заданной величины по отношению к заданному объёму SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_INC, // Увеличение общего объёма ордеров на покупку больше заданной величины SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_DEC, // Уменьшение общего объёма ордеров на покупку больше заданной величины SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_INC, // Увеличение общего объёма ордеров на продажу больше заданной величины SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_DEC, // Уменьшение общего объёма ордеров на продажу больше заданной величины SYMBOL_EVENT_SESSION_OPEN_INC, // Увеличение цены открытия сессии больше заданной величины по отношению к заданной цене SYMBOL_EVENT_SESSION_OPEN_DEC, // Уменьшение цены открытия сессии больше заданной величины по отношению к заданной цене SYMBOL_EVENT_SESSION_CLOSE_INC, // Увеличение цены закрытия сессии больше заданной величины по отношению к заданной цене SYMBOL_EVENT_SESSION_CLOSE_DEC, // Уменьшение цены закрытия сессии больше заданной величины по отношению к заданной цене SYMBOL_EVENT_SESSION_AW_INC, // Увеличение средневзвешенной цены сессии больше заданной величины SYMBOL_EVENT_SESSION_AW_DEC, // Уменьшение средневзвешенной цены сессии больше заданной величины }; #define SYMBOL_EVENTS_NEXT_CODE (SYMBOL_EVENT_SESSION_AW_DEC+1) // Код следующего события после последнего кода события символа //+------------------------------------------------------------------+
Код следующего события, естественно, был изменён на значение,
следующее за значением константы
MARKET_WATCH_EVENT_SYMBOL_SORT из перечисления ENUM_MW_EVENT.
Теперь займёмся реализацией задуманного функционала.
В файл базового объекта \MQL5\Include\DoEasy\Objects\BaseObj.mqh впишем новый класс базового события:
//+------------------------------------------------------------------+ //| Класс базового события объекта библиотеки | //+------------------------------------------------------------------+ class CBaseEvent : public CObject { private: ENUM_BASE_EVENT_REASON m_reason; int m_event_id; double m_value; public: ENUM_BASE_EVENT_REASON Reason(void) const { return this.m_reason; } int ID(void) const { return this.m_event_id; } double Value(void) const { return this.m_value; } //--- Конструктор CBaseEvent(const int event_id,const ENUM_BASE_EVENT_REASON reason,const double value) : m_reason(reason), m_event_id(event_id), m_value(value){} //--- Метод сравнения для поиска одинаковых объектов-событий virtual int Compare(const CObject *node,const int mode=0) const { const CBaseEvent *compared=node; return ( this.Reason()>compared.Reason() ? 1 : this.Reason()<compared.Reason() ? -1 : this.ID()>compared.ID() ? 1 : this.ID()<compared.ID() ? -1 : 0 ); } }; //+------------------------------------------------------------------+
В приватной секции класса расположены переменные для хранения причины
события, идентификатора события (совпадает со значением
индекса изменённого свойства объекта) и
величины изменения свойства события.
В публичной секции
класса расположены методы для возврата вышеперечисленных переменных-членов класса.
В конструктор класса, в его формальных параметрах, передаются
значения этих свойств, и в списке инициализации сразу же присваиваются переданные значения соответствующим переменным-членам класса.
Также класс имеет метод сравнения двух объектов класса
для поиска в
списке динамических указателей на объекты,
который уже не раз нами обсуждался.
Так как хранить список контролируемых свойств объектов мы будем в двумерных массивах, то добавим
макроподстановку, указывающую на размер второго измерения массивов, и в приватной секции класса объявим две переменные, в
которых будем хранить
количество целочисленных и вещественных
свойств объекта, который будет наследоваться от данного класса (ведь базовый класс ничего не знает о количествах свойств,
имеющихся у его наследников, и эти количества необходимо будет явно указывать). И
объявим метод для заполнения массивов свойств и
поиска изменений в свойствах объектов-наследников.
//+------------------------------------------------------------------+ //| Класс базового объекта для всех объектов библиотеки | //+------------------------------------------------------------------+ #define CONTROLS_TOTAL (10) class CBaseObj : public CObject { private: int m_long_prop_total; int m_double_prop_total; //--- Заполняет массив свойств объекта template<typename T> bool FillPropertySettings(const int index,T &array[][CONTROLS_TOTAL],T &array_prev[][CONTROLS_TOTAL],int &event_id); protected:
В защищённой секции класса объявим список для хранения указателей на
экземпляры базовых событий объекта, переменную для хранения идентификатора
события, флаг первого запуска и переменную
для хранения типа объекта-наследника.
Также мы добавили четыре
двумерных массива для хранения свойств и контроля их изменения (текущие и прошлые целочисленные и вещественные свойства
объекта-наследника) и
метод, возвращающий только милисекунды, хранящиеся во времени события
(для MQL4 возвращаем 0, а для MQL5 — остаток от деления на 1000 long-значения времени).
Так как базовый класс ничего не
знает о количестве свойств объектов-наследников, и размеры нужно устанавливать из классов-наследников (где они известны), то объявим
методы для установки и проверки
размеров массивов:
protected: CArrayObj m_list_events_base; // Список базовых событий объекта CArrayObj m_list_events; // Список событий объекта MqlTick m_tick; // Структура тика для получения котировочных данных double m_hash_sum; // Хэш-сумма данных объекта double m_hash_sum_prev; // Хэш-сумма данных объекта на прошлой проверке int m_digits_currency; // Число знаков после запятой валюты счёта int m_global_error; // Код глобальной ошибки long m_chart_id; // Идентификатор графика управляющей программы bool m_is_event; // Флаг события объекта int m_event_code; // Код события объекта int m_event_id; // Идентификатор события (равен значению свойства объекта) string m_name; // Наименование объекта string m_folder_name; // Имя папки хранения объектов-наследников CBaseObj bool m_first_start; // Флаг первого запуска int m_type; // Тип объекта (соответствует идентификаторам коллекций) //--- Данные в ячейках массива //--- Данные для хранения, контроля и возврата отслеживаемых свойств: //--- [Индекс свойства][0] Контролируемая величина прироста значения свойства //--- [Индекс свойства][1] Контролируемая величина уменьшения значения свойства //--- [Индекс свойства][2] Контрольный уровень значения свойства //--- [Индекс свойства][3] Значение свойства //--- [Индекс свойства][4] Величина изменения значения свойства //--- [Индекс свойства][5] Флаг изменения значения свойства больше, чем на величину прироста //--- [Индекс свойства][6] Флаг изменения значения свойства больше, чем на величину уменьшения //--- [Индекс свойства][7] Флаг увеличения значения свойства больше контрольного уровня //--- [Индекс свойства][8] Флаг уменьшения значения свойства меньше контрольного уровня //--- [Индекс свойства][9] Флаг равенства значения свойства контрольному уровню long m_long_prop_event[][CONTROLS_TOTAL]; // Массив для хранения величин целочисленных свойств объекта и контролируемых значений изменения свойств double m_double_prop_event[][CONTROLS_TOTAL]; // Массив для хранения величин вещественных свойств объекта и контролируемых значений изменения свойств long m_long_prop_event_prev[][CONTROLS_TOTAL]; // Массив для хранения величин контролируемых целочисленных свойств объекта на прошлой проверке double m_double_prop_event_prev[][CONTROLS_TOTAL]; // Массив для хранения величин контролируемых вещественных свойств объекта на прошлой проверке //--- Возвращает (1) время в милисекундах, (2) милисекунды из значения времени из MqlTick long TickTime(void) const { return #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; } ushort MSCfromTime(const long time_msc) const { return #ifdef __MQL5__ ushort(this.TickTime()%1000) #else 0 #endif ; } //--- возвращает факт наличия кода события в событии объекта bool IsPresentEventFlag(const int change_code) const { return (this.m_event_code & change_code)==change_code; } //--- Возвращает число знаков после запятой валюты счёта int DigitsCurrency(void) const { return this.m_digits_currency; } //--- Возвращает количество знаков после запятой в double-значении int GetDigits(const double value) const; //--- Устанавливает размер массива (1) целочисленных, (2) вещественных контролируемых свойств объекта bool SetControlDataArraySizeLong(const int size); bool SetControlDataArraySizeDouble(const int size); //--- Проверяет размер массива свойств объекта bool CheckControlDataArraySize(bool check_long=true); //--- Устанавливает (1) значение контролируемой величины, (2) величину изменения значения свойства объекта template<typename T> void SetControlledValue(const int property,const T value); template<typename T> void SetControlledChangedValue(const int property,const T value); //--- Устанавливает величину контролируемого (1) приращения, (2) уменьшения, (3) контрольный уровень значения свойства объекта template<typename T> void SetControlledValueINC(const int property,const T value); template<typename T> void SetControlledValueDEC(const int property,const T value); template<typename T> void SetControlledValueLEVEL(const int property,const T value); //--- Устанавливает Флаг изменения значения свойства больше, чем на величину (1) прироста, (2) уменьшения template<typename T> void SetControlledFlagINC(const int property,const T value); template<typename T> void SetControlledFlagDEC(const int property,const T value); //--- Устанавливает Флаг изменения значения свойства (1) больше, (2) меньше контрольного уровня, (3) равенства уровню template<typename T> void SetControlledFlagMORE(const int property,const T value); template<typename T> void SetControlledFlagLESS(const int property,const T value); template<typename T> void SetControlledFlagEQUAL(const int property,const T value); //--- Возвращает установленную величину контролируемого приращения (1) целочисленных, (2) вещественных свойств объекта long GetControlledValueLongINC(const int property) const { return this.m_long_prop_event[property][0]; } double GetControlledValueDoubleINC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][0]; } //--- Возвращает установленную величину контролируемого уменьшения (1) целочисленных, (2) вещественных свойств объекта long GetControlledValueLongDEC(const int property) const { return this.m_long_prop_event[property][1]; } double GetControlledValueDoubleDEC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][1]; } //--- Возвращает контрольный уровень (1) целочисленных, (2) вещественных свойств объекта long GetControlledValueLongLEVEL(const int property) const { return this.m_long_prop_event[property][2]; } double GetControlledValueDoubleLEVEL(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][2]; } //--- Возвращает значение (1) целочисленного, (2) вещественного свойства объекта long GetControlledValueLong(const int property) const { return this.m_long_prop_event[property][3]; } double GetControlledValueDouble(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][3]; } //--- Возвращает величину изменения контролируемого (1) целочисленного, (2) вещественного свойства объекта long GetControlledChangedValueLong(const int property) const { return this.m_long_prop_event[property][4]; } double GetControlledChangedValueDouble(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][4]; } //--- Возвращает Флаг изменения значения (1) целочисленного, (2) вещественного свойства больше, чем на величину прироста long GetControlledFlagLongINC(const int property) const { return this.m_long_prop_event[property][5]; } double GetControlledFlagDoubleINC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][5]; } //--- Возвращает Флаг изменения значения (1) целочисленного, (2) вещественного свойства больше, чем на величину уменьшения long GetControlledFlagLongDEC(const int property) const { return this.m_long_prop_event[property][6]; } double GetControlledFlagDoubleDEC(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][6]; } //--- Возвращает Флаг увеличения значения (1) целочисленного, (2) вещественного свойства больше контрольного уровня long GetControlledFlagLongMORE(const int property) const { return this.m_long_prop_event[property][7]; } double GetControlledFlagDoubleMORE(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][7]; } //--- Возвращает Флаг уменьшения значения (1) целочисленного, (2) вещественного свойства меньше контрольного уровня long GetControlledFlagLongLESS(const int property) const { return this.m_long_prop_event[property][8]; } double GetControlledFlagDoubleLESS(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][8]; } //--- Возвращает Флаг равенства значений (1) целочисленного, (2) вещественного свойства и контрольного уровня long GetControlledFlagLongEQUAL(const int property) const { return this.m_long_prop_event[property][9]; } double GetControlledFlagDoubleEQUAL(const int property) const { return this.m_double_prop_event[property-this.m_long_prop_total][9]; } //--- (1) Упаковывает ushort-число в переданное long-число //--- (2) преобразует ushort-значение в заданный байт long-числа long UshortToLong(const ushort ushort_value,const uchar index,long &long_value); long UshortToByte(const ushort value,const uchar index) const; public:
Здесь же — в приватной секции класса, объявлены методы для установки и возврата
контролируемых свойств и их величин, а также методы для упаковки
ushort-числа в указанные байты long-контейнера по индексу. (Индекс 0 => байты 0-1, Индекс 1 =>
байты
2-3, Индекс 2 => байты 4-5)
В публичной секции класса объявим методы сброса значений
изменяемых свойств и значений контролируемых свойств объекта,
метод добавления базового события в список, метод
получения базового объекта из списка по индексу, и метод, возвращающий
количество базовых событий в списке, виртуальный метод, возвращающий тип
объекта и метод, возвращающий строковое описание базового события:
public: //--- Сбрасывает переменные (1) отслеживаемых, (2) контролируемых данных объекта (переназначить можно в наследниках) void ResetChangesParams(void); virtual void ResetControlsParams(void); //--- Добавляет (1) событие объекта в список, (2) причину события объекта в список bool EventAdd(const ushort event_id,const long lparam,const double dparam,const string sparam); bool EventBaseAdd(const int event_id,const ENUM_BASE_EVENT_REASON reason,const double value); //--- Возвращает флаг произошедшего события в данных объекта bool IsEvent(void) const { return this.m_is_event; } //--- Возвращает (1) список событий, (2) код события объекта, (3) код глобальной ошибки CArrayObj *GetListEvents(void) { return &this.m_list_events; } int GetEventCode(void) const { return this.m_event_code; } int GetError(void) const { return this.m_global_error; } //--- Возвращает (1) объект-событие, (2) базовое событие по его номеру в списке CEventBaseObj *GetEvent(const int shift=WRONG_VALUE,const bool check_out=true); CBaseEvent *GetEventBase(const int index); //--- Возвращает количество (1) событий объекта int GetEventsTotal(void) const { return this.m_list_events.Total(); } //--- (1) Устанавливает, (2) возвращает идентификатор графика управляющей программы void SetChartID(const long id) { this.m_chart_id=id; } long GetChartID(void) const { return this.m_chart_id; } //--- (1) Устанавливает имя подпапки, (2) возвращает имя папки для хранения файлов объектов-наследников void SetSubFolderName(const string name) { this.m_folder_name=DIRECTORY+name; } string GetFolderName(void) const { return this.m_folder_name; } //--- Возвращает наименование объекта string GetName(void) const { return this.m_name; } //--- Обновляет данные объекта для поиска изменений в данных объекта (Вызов из наследников: CBaseObj::Refresh()) virtual void Refresh(void); //--- Возвращает тип объекта virtual int Type(void) const { return this.m_type; } //--- Возвращает описание события объекта string EventDescription(const int property, const ENUM_BASE_EVENT_REASON reason, const int source, const string value, const string property_descr, const int digits); //--- Конструктор CBaseObj(); }; //+------------------------------------------------------------------+
Теперь рассмотрим вкратце все объявленные выше методы.
Коструктор класса:
//+------------------------------------------------------------------+ //| Конструктор | //+------------------------------------------------------------------+ CBaseObj::CBaseObj() : m_global_error(ERR_SUCCESS), m_hash_sum(0),m_hash_sum_prev(0), m_is_event(false),m_event_code(WRONG_VALUE), m_chart_id(::ChartID()), m_folder_name(DIRECTORY), m_name(__FUNCTION__), m_long_prop_total(0), m_double_prop_total(0), m_first_start(true) { ::ArrayResize(this.m_long_prop_event,0,100); ::ArrayResize(this.m_double_prop_event,0,100); ::ArrayResize(this.m_long_prop_event_prev,0,100); ::ArrayResize(this.m_double_prop_event_prev,0,100); ::ZeroMemory(this.m_tick); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); this.m_list_events.Clear(); this.m_list_events.Sort(); this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); } //+------------------------------------------------------------------+
Здесь: так как теперь у нас нет кодов событий, которые ранее мы собирали из флагов, и где нулевое значение указывало на отсутствие события, то нам
нужно заменить в списке инициализации класса инициализацию кода события на ненулевое (так как ноль обозначает событие самого первого
свойства в перечислении целочисленных свойств объекта, а больше нуля — следующие события по списку свойств объекта, а сколько их — в
родительском классе не известно) —
зададим для кода события значение -1.
Имя
объекта инициализируем наименованием класса (имя переназначается в наследниках), инициализируем количество
целочисленных и вещественных свойств
объекта-наследника нулевыми значениями и
поставим флаг первого запуска.
В теле класса установим
размеры массивов целочисленных и вещественных свойств в нулевой размер, очистим
список базовых событий и установим ему флаг сортированного списка.
Виртуальный метод Refresh() класса ранее у нас был просто объявлен, и его реализация возлагалась на классы-наследники. Сейчас создадим и реализацию данного метода для класса базового объекта — в нём будем отслеживать изменения свойств объектов-наследников и при определении события создавать базовые события и добавлять их в список базовых событий для последующей их обработки и создания событий объектов для отправки их в программу:
//+------------------------------------------------------------------+ //| Обновляет данные объекта для поиска в них изменений | //| Вызов из наследников: CBaseObj::Refresh() | //+------------------------------------------------------------------+ void CBaseObj::Refresh(void) { //--- Проверка размеров массивов, и если нулевые - выход if(!this.CheckControlDataArraySize() || !this.CheckControlDataArraySize(false)) return; //--- Сброс флага события и очистка всех списков this.m_is_event=false; this.m_list_events.Clear(); this.m_list_events.Sort(); this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); //--- Заполнение массива целочисленных свойств и контроль их изменений for(int i=0;i<this.m_long_prop_total;i++) if(!this.FillPropertySettings(i,this.m_long_prop_event,this.m_long_prop_event_prev,this.m_event_id)) continue; //--- Заполнение массива вещественных свойств и контроль их изменений for(int i=0;i<this.m_double_prop_total;i++) if(!this.FillPropertySettings(i,this.m_double_prop_event,this.m_double_prop_event_prev,this.m_event_id)) continue; //--- Первый запуск if(this.m_first_start) { ::ArrayCopy(this.m_long_prop_event_prev,this.m_long_prop_event); ::ArrayCopy(this.m_double_prop_event_prev,this.m_double_prop_event); this.m_hash_sum_prev=this.m_hash_sum; this.m_first_start=false; this.m_is_event=false; this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); return; } } //+------------------------------------------------------------------+
Здесь все действия прописаны в комментариях к коду, и всё что делается в методе — предварительно очищаются списки событий и вызываются методы
заполнения массивов целочисленных и вещественных свойств объекта-наследника с проверкой их изменений.
Если это первый запуск, то текущее состояние массивов свойств копируется в прошлое состояние (чтобы не было разницы между ними, и
соответственно — не было регистрации событий), сбрасывается флаг первого запуска и очищается список базовых событий, который возможно
уже был создан при вызове методов
FillPropertySettings().
Реализация метода, заполняющего массивы свойств объекта-наследника и контролирующего их изменения:
//+------------------------------------------------------------------+ //| Заполняет массив свойств объекта | //+------------------------------------------------------------------+ template<typename T> bool CBaseObj::FillPropertySettings(const int index,T &array[][CONTROLS_TOTAL],T &array_prev[][CONTROLS_TOTAL],int &event_id) { //--- Данные в ячейках массива //--- [Индекс свойства][0] Контролируемая величина прироста значения свойства //--- [Индекс свойства][1] Контролируемая величина уменьшения значения свойства //--- [Индекс свойства][2] Контрольный уровень значения свойства //--- [Индекс свойства][3] Значение свойства //--- [Индекс свойства][4] Величина изменения значения свойства //--- [Индекс свойства][5] Флаг изменения значения свойства больше, чем на величину прироста //--- [Индекс свойства][6] Флаг изменения значения свойства больше, чем на величину уменьшения //--- [Индекс свойства][7] Флаг увеличения значения свойства больше контрольного уровня //--- [Индекс свойства][8] Флаг уменьшения значения свойства меньше контрольного уровня //--- [Индекс свойства][9] Флаг равенства значения свойства контрольному уровню //--- Если не установлены контролируемые значения - уходим с возвратом false if(this.m_first_start) return false; //--- Устанавливаем смещение индекса double-свойства и задаём идентификатор события event_id=index+(typename(T)=="double" ? this.m_long_prop_total : 0); //--- Обнуляем все флаги событий for(int j=5;j<CONTROLS_TOTAL;j++) array[index][j]=false; //--- Величина изменения свойства T value=array[index][3]-array_prev[index][3]; array[index][4]=value; //--- Если контролируемая величина прироста значения свойства установлена if(array[index][0]<LONG_MAX) { //--- Если величина изменения свойства больше контролируемой величины увеличения - есть событие, //--- добавляем событие в список, ставим флаг и сохраняем новый размер значения свойства if(value>0 && value>array[index][0]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_INC,value)) { array[index][5]=true; array_prev[index][4]=value; } } } //--- Если контролируемая величина уменьшения значения свойства установлена if(array[index][1]<LONG_MAX) { //--- Если величина изменения свойства больше контролируемой величины уменьшения - есть событие, //--- добавляем событие в список, ставим флаг и сохраняем новый размер значения свойства if(value<0 && fabs(value)>array[index][1]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_DEC,value)) { array[index][6]=true; array_prev[index][4]=value; } } } //--- Если значение контролируемого уровня установлено if(array[index][2]<LONG_MAX) { value=array[index][3]-array[index][2]; //--- Если значение свойства стало больше контрольного уровня - есть событие, //--- добавляем событие в список и ставим флаг if(value>0 && array_prev[index][3]<=array[index][2]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_MORE_THEN,array[index][2])) array[index][7]=true; } //--- Если значение свойства стало меньше контрольного уровня - есть событие, //--- добавляем событие в список и ставим флаг else if(value<0 && array_prev[index][3]>=array[index][2]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_LESS_THEN,array[index][2])) array[index][8]=true; } //--- Если значение свойства стало равно контрольному уровню - есть событие, //--- добавляем событие в список и ставим флаг else if(value==0 && array_prev[index][3]!=array[index][2]) { if(this.EventBaseAdd(event_id,BASE_EVENT_REASON_EQUALS,array[index][2])) array[index][9]=true; } } //--- Сохраняем текущее значение свойства как прошлое array_prev[index][3]=array[index][3]; return true; } //+------------------------------------------------------------------+
Здесь все действия прописаны в комментариях к коду. Единственное, что хочу пояснить — выбор смещения индекса double-свойства объекта для получения идентификатора события. Так как у нас вещественные свойства всех объектов располагаются следом за целочисленными свойствам, то начало первого вещественного свойства равно количеству целочисленных свойств (если количество long-свойств равно трём, то первое вещественное свойство будет иметь индекс 3 (0,1,2, 3)). А в массивах у нас отсчёт начинается, естественно, с нуля. Поэтому в случае работы с double-свойствами нам необходимо прибавить к индексу массива количество целочисленных свойств объекта.
Методы установки размеров массивов целочисленных и вещественных свойств объектов-наследников:
//+------------------------------------------------------------------+ //| Устанавливает размер массивов целочисленных свойств объекта | //+------------------------------------------------------------------+ bool CBaseObj::SetControlDataArraySizeLong(const int size) { int x=(#ifdef __MQL4__ CONTROLS_TOTAL #else 1 #endif ); this.m_long_prop_total=::ArrayResize(this.m_long_prop_event,size,100)/x; return((::ArrayResize(this.m_long_prop_event_prev,size,100)/x)==size && this.m_long_prop_total==size ? true : false); } //+------------------------------------------------------------------+ //| Устанавливает размер массивов вещественных свойств объекта | //+------------------------------------------------------------------+ bool CBaseObj::SetControlDataArraySizeDouble(const int size) { int x=(#ifdef __MQL4__ CONTROLS_TOTAL #else 1 #endif ); this.m_double_prop_total=::ArrayResize(this.m_double_prop_event,size,100)/x; return((::ArrayResize(this.m_double_prop_event_prev,size,100)/x)==size && this.m_double_prop_total==size ? true : false); } //+------------------------------------------------------------------+
Методы возвращают результат изменения размеров массивов на переданную в метод величину.
Отмечу одну особенность изменения размера многомерного массива в MQL4. Функция ArrayResize() в MQL4 возвращает суммарный размер всех измерений массива. В MQL5 — размер первого измерения, который и меняется. Например, если у нас второе измерение имеет размер, равный двум, то при изменении размера первого измерения массива до 10, функция вернёт 20, что не логично (мы же изменяем размер только первого измерения). А вот в MQL5 функция возвращает правильное значение — для вышеописанного примера она вернёт 10, как и ожидалось.
Поэтому в методах был создан делитель,
на который в MQL4 нужно разделить возвращаемое функцией значение —
на размер
второго измерения.
Метод проверки размера массива целочисленных или вещественных свойств объекта-наследника:
//+------------------------------------------------------------------+ //| Проверяет размер массива свойств объекта | //+------------------------------------------------------------------+ bool CBaseObj::CheckControlDataArraySize(bool check_long=true) { string txt1=""; string txt2=""; string txt3=""; string txt4=""; bool res=true; if(check_long) { if(this.m_long_prop_total==0) { txt1=TextByLanguage("Массив данных контролируемых integer-свойств имеет нулевой размер","Controlled integer-properties data array has zero size"); txt2=TextByLanguage("Необходимо сначала установить размер массива равным количеству integer-свойств объекта","You must first set the size of the array equal to the number of object integer-properties"); txt3=TextByLanguage("Для этого используйте метод CBaseObj::SetControlDataArraySizeLong()","To do this, use the CBaseObj::SetControlDataArraySizeLong() method"); txt4=TextByLanguage("со значением количества integer-свойств объекта в параметре \"size\"","with the value of the number of integer-properties of the object in the parameter \"size\""); res=false; } } else { if(this.m_double_prop_total==0) { txt1=TextByLanguage("Массив данных контролируемых double-свойств имеет нулевой размер","Controlled double-properties data array has zero size"); txt2=TextByLanguage("Необходимо сначала установить размер массива равным количеству double-свойств объекта","You must first set the size of the array equal to the number of object double-properties"); txt3=TextByLanguage("Для этого используйте метод CBaseObj::SetControlDataArraySizeDouble()","To do this, use the CBaseObj::SetControlDataArraySizeDouble() method"); txt4=TextByLanguage("со значением количества double-свойств объекта в параметре \"size\"","with the value of the number of double-properties of the object in the parameter \"size\""); res=false; } } if(res) return true; #ifdef __MQL5__ ::Print(DFUN,"\n",txt1,"\n",txt2,"\n",txt3,"\n",txt4); #else ::Print(DFUN); ::Print(txt1); ::Print(txt2); ::Print(txt3); ::Print(txt4); #endif this.m_global_error=ERR_ZEROSIZE_ARRAY; return false; } //+------------------------------------------------------------------+
В метод передаётся флаг, указывающий размер какого массива
проверяется.
При true — проверяется массив long-свойств, при false
— массив double-свойств.
Если размер проверяемого массива не задан, то создаётся текст сообщения, сообщение выводится в журнал и возвращается false. В случае, когда размер массива уже задан — возвращается true.
Методы сброса контролируемых значений и величин изменения отслеживаемых данных свойств объекта:
//+------------------------------------------------------------------+ //| Сбрасывает переменные контролируемых значений данных объекта | //+------------------------------------------------------------------+ void CBaseObj::ResetControlsParams(void) { if(!this.CheckControlDataArraySize(true) || !this.CheckControlDataArraySize(false)) return; //--- Данные в ячейках массива //--- [Индекс свойства][0] Контролируемая величина прироста значения свойства //--- [Индекс свойства][1] Контролируемая величина уменьшения значения свойства //--- [Индекс свойства][2] Контрольный уровень значения свойства for(int i=this.m_long_prop_total-1;i>WRONG_VALUE;i--) for(int j=0; j<3; j++) this.m_long_prop_event[i][j]=LONG_MAX; for(int i=this.m_double_prop_total-1;i>WRONG_VALUE;i--) for(int j=0; j<3; j++) this.m_double_prop_event[i][j]=(double)LONG_MAX; } //+------------------------------------------------------------------+ //| Сбрасывает переменные отслеживаемых данных объекта | //+------------------------------------------------------------------+ void CBaseObj::ResetChangesParams(void) { if(!this.CheckControlDataArraySize(true) || !this.CheckControlDataArraySize(false)) return; this.m_list_events.Clear(); this.m_list_events.Sort(); this.m_list_events_base.Clear(); this.m_list_events_base.Sort(); //--- Данные в ячейках массива //--- [Индекс свойства][3] Значение свойства //--- [Индекс свойства][4] Величина изменения значения свойства //--- [Индекс свойства][5] Флаг изменения значения свойства больше, чем на величину прироста //--- [Индекс свойства][6] Флаг изменения значения свойства больше, чем на величину уменьшения //--- [Индекс свойства][7] Флаг увеличения значения свойства больше контрольного уровня //--- [Индекс свойства][8] Флаг уменьшения значения свойства меньше контрольного уровня //--- [Индекс свойства][9] Флаг равенства значения свойства контролируемому значению for(int i=this.m_long_prop_total-1;i>WRONG_VALUE;i--) for(int j=3; j<CONTROLS_TOTAL; j++) this.m_long_prop_event[i][j]=(j<5 ? LONG_MAX : 0); for(int i=this.m_double_prop_total-1;i>WRONG_VALUE;i--) for(int j=3; j<CONTROLS_TOTAL; j++) this.m_double_prop_event[i][j]=(j<5 ? (double)LONG_MAX : 0); } //+------------------------------------------------------------------+
В методах в двух циклах по массивам целочисленных и вещественных свойств объекта-наследника задаются инициализирующие значения в
необходимые ячейки второго измерения массивов. Инициализируемые ячейки прописаны в комментариях к коду.
Метод, добавляющий базовое событие в список базовых событий объекта:
//+------------------------------------------------------------------+ //| Добавляет базовое событие объекта в список | //+------------------------------------------------------------------+ bool CBaseObj::EventBaseAdd(const int event_id,const ENUM_BASE_EVENT_REASON reason,const double value) { CBaseEvent* event=new CBaseEvent(event_id,reason,value); if(event==NULL) return false; this.m_list_events_base.Sort(); if(this.m_list_events_base.Search(event)>WRONG_VALUE) { delete event; return false; } return this.m_list_events_base.Add(event); } //+------------------------------------------------------------------+
В метод передаётся идентификатор события, причина
события и величина, на которую было изменено свойство объекта-наследника.
Далее создаётся новое базовое событие, и если
точно такое же событие уже есть в списке базовых событий, то это событие удаляется и возвращается
false — событие не добавлено.
Иначе —
возвращается результат добавления нового события в список базовых событий объекта.
Метод, возвращающий базовое событие по его индексу в списке базовых событий объекта:
//+------------------------------------------------------------------+ //| Возвращает базовое событие по его индексу в списке | //+------------------------------------------------------------------+ CBaseEvent *CBaseObj::GetEventBase(const int index) { int total=this.m_list_events_base.Total(); if(total==0 || index<0 || index>total-1) return NULL; CBaseEvent *event=this.m_list_events_base.At(index); return(event!=NULL ? event : NULL); } //+------------------------------------------------------------------+
В метод передаётся индекс требуемого события, затем, если список имеет нулевой размер или индекс выходит за пределы списка базовых событий, то возвращается NULL, иначе — получаем событие из списка по индексу и возвращаем указатель на полученный объект.
Для класса базового объекта необходимо создать методы, при помощи которых мы сможем оперативно задавать нужные величины изменения
свойств, превышение которых приводит к генерации событий. И методы для установки новых значений свойствам объектов-наследников и
возврата флагов о произошедших "подконтрольных" событиях объектов. Так как базовый класс ничего не знает о свойствах его наследников, то
необходимо создать универсальные методы, позволяющие вносить изменения в нужное свойство объекта-наследника. Так как мы можем, и будем
указывать количество целочисленных и вещественных свойств для каждого из классов-наследников, то определить для какого свойства мы
задаём значение не составляет труда — нужно лишь проверить индекс изменяемого свойства. Если индекс меньше количества целочисленных
свойств, то изменения вносятся в целочисленное свойство объекта, иначе — в вещественное.
Реализация методов установки контролируемых свойств объектов-наследников:
//+------------------------------------------------------------------+ //| Методы установки контролируемых параметров | //+------------------------------------------------------------------+ //--- Данные для хранения, контроля и возврата отслеживаемых свойств: //--- [Индекс свойства][0] Контролируемая величина прироста значения свойства //--- [Индекс свойства][1] Контролируемая величина уменьшения значения свойства //--- [Индекс свойства][2] Контрольный уровень значения свойства //--- [Индекс свойства][3] Значение свойства //--- [Индекс свойства][4] Величина изменения значения свойства //--- [Индекс свойства][5] Флаг изменения значения свойства больше, чем на величину прироста //--- [Индекс свойства][6] Флаг изменения значения свойства больше, чем на величину уменьшения //--- [Индекс свойства][7] Флаг увеличения значения свойства больше контрольного уровня //--- [Индекс свойства][8] Флаг уменьшения значения свойства меньше контрольного уровня //--- [Индекс свойства][9] Флаг равенства значения свойства контрольному уровню //+------------------------------------------------------------------+ //| Устанавливает величину контролируемого прироста свойств объекта | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValueINC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][0]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][0]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает величину контролируемого уменьшения свойств объекта| //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValueDEC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][1]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][1]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает контрольный уровень свойств объекта | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValueLEVEL(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][2]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][2]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает значение свойства объекта | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledValue(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][3]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][3]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает величину изменения значения свойства объекта | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledChangedValue(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][4]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][4]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает Флаг изменения значения свойства | //| больше, чем на величину прироста | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagINC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][5]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][5]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает Флаг изменения значения свойства | //| больше, чем на величину уменьшения | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagDEC(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][6]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][6]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает Флаг увеличения значения свойства | //| больше контрольного уровня | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagMORE(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][7]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][7]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает Флаг уменьшения значения свойства | //| меньше контрольного уровня | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagLESS(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][8]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][8]=(double)value; } //+------------------------------------------------------------------+ //| Устанавливает Флаг равенства значения свойства | //| и контрольного уровня | //+------------------------------------------------------------------+ template<typename T> void CBaseObj::SetControlledFlagEQUAL(const int property,const T value) { if(property<this.m_long_prop_total) this.m_long_prop_event[property][9]=(long)value; else this.m_double_prop_event[property-this.m_long_prop_total][9]=(double)value; } //+------------------------------------------------------------------+
Рассмотрим последний метод: в метод передаётся свойство, в
значение которого необходимо вписать шаблонное значение
T value. Если
индекс свойства меньше, чем количество целочисленных свойств объекта-наследника, то
T-значение вписываем в нужную ячейку массива целочисленных свойств объекта, иначе — рассчитываем
индекс, по которому в массиве вещественных свойств хранится данное свойство (индекс double-свойства всегда больше индекса
этого же свойства в массиве на величину количества целочисленных свойств объекта), и
вписываем T-значение в нужную ячейку массива вещественных свойств объекта.
Требуемые ячейки второго измерения массива для каждого из методов перечислены перед списком методов.
Метод, преобразующий ushort-значение в long-значение, смещённое на нужное количество байт для последующей упаковки его в
long-контейнер:
//+------------------------------------------------------------------+ //| Преобразует ushort-значение в заданный байт long-числа | //+------------------------------------------------------------------+ long CBaseObj::UshortToByte(const ushort value,const uchar index) const { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. The \"index\" value must be between 0 - 3")); return 0; } return(long)value<<(16*index); } //+------------------------------------------------------------------+
Представим себе восьмибайтовое long-число, разбитое на ячейки по два байта (каждой такой ячейке присвоен свой индекс):
Байты 6-7 (индекс 3) |
Байты 4-5 (индекс 2) | Байты 2-3 (индекс 1) |
Байты 0-1 (индекс 0) |
---|---|---|---|
ushort 4 |
ushort 3 |
ushort 2 |
ushort 1 |
В него мы можем разместить четыре ushort-числа. Каждое последующее число нам необходимо сметить влево на 16 бит * индекс (1 байт = 8 бит), а
затем полученное значение добавить к long-числу. Таким образом мы получим упакованные в long-контейнер несколько ushort-значений.
В метод передаётся ushort-число и индекс,
по которому нужно хранить ushort-значение в long-контейнере.
Проверяется индекс, и если он болше 3, то выводится сообщение о неверном индексе и возвращается 0.
Если
индекс правильный, то
ushort-число смещается влево на 16
бит * индекс (в одном байте 8 бит, а сместить нужно двухбайтовое ushort-число),
и
результат смещения возвращается из метода.
Метод, упаковывающий смещённое на нужное количество байт ushort-значение в long-контейнер:
//+------------------------------------------------------------------+ //| Упаковывает ushort-число в переданное long-число | //+------------------------------------------------------------------+ long CBaseObj::UshortToLong(const ushort ushort_value,const uchar index,long &long_value) { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. The \"index\" value must be between 0 - 3")); return 0; } return(long_value |= UshortToByte(ushort_value,index)); } //+------------------------------------------------------------------+
В метод передаётся ushort-число, которое необходимо упаковать в long-контейнер,
передаваемый в метод по ссылке и индекс байт, в которые необходимо
поместить ushort-значение в long-контейнере.
Так же, как и в вышеописанном методе проверяется
индекс, а затем, при успешной проверке индекса,
к
long-числу добавляется
смещённое на нужное количество байт методом UshortToByte()
ushort-число
при помощи побитового "ИЛИ",
и результат возвращается в
вызывающую программу.
Метод, возвращающий строковое описание события объекта-наследника:
//+------------------------------------------------------------------+ //| Возвращает описание события объекта | //+------------------------------------------------------------------+ string CBaseObj::EventDescription(const int property, const ENUM_BASE_EVENT_REASON reason, const int source, const string value, const string property_descr, const int digits) { //--- В зависимости от ID коллекции создаём описание типа объекта string type= ( this.Type()==COLLECTION_SYMBOLS_ID ? TextByLanguage("символа: ","symbol property: ") : this.Type()==COLLECTION_ACCOUNT_ID ? TextByLanguage("аккаунта: ","account property: ") : "" ); //--- В зависимости от типа свойства создаём описание величины изменения свойства string level= ( property<this.m_long_prop_total ? ::DoubleToString(this.GetControlledValueLongLEVEL(property),digits) : ::DoubleToString(this.GetControlledValueDoubleLEVEL(property),digits) ); //--- В зависимости от причины события создаём текст описания события string res= ( reason==BASE_EVENT_REASON_INC ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" увеличено на "," increased by ")+value : reason==BASE_EVENT_REASON_DEC ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" уменьшено на "," decreased by ")+value : reason==BASE_EVENT_REASON_MORE_THEN ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" стало больше "," became more than ")+level : reason==BASE_EVENT_REASON_LESS_THEN ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" стало меньше "," became less than ")+level : reason==BASE_EVENT_REASON_EQUALS ? TextByLanguage("Значение свойства ","Value of the ")+type+property_descr+TextByLanguage(" равно "," is equal to ")+level : TextByLanguage("Неизвестное событие ","Unknown ")+type ); //--- Возвращаем наименование объекта+созданный текст описания события return this.m_name+": "+res; } //+------------------------------------------------------------------+
Так как класс базового объекта не знает ничего о своих наследниках, то для описания события в классе-наследнике нам необходимо указать на
объект-наследник, в котором произошло событие.
Для этого в метод передаётся
- свойство объекта, в котором зарегистрировано событие,
- причина события — увеличение/уменьшение значения свойства
на заданную величину/пересечение заданного уровня значением свойства,
- источник события — идентификатор коллекции, в объекте
которой произошло событие,
- значение, на которое было изменено свойство объекта,
- текстовое описание свойства объекта-наследника
(доступно в наследнике) и
- количество знаков после запятой в цифровом представлении изменённого свойства (так же доступно в наследнике).
Все шаги создания описания события объекта-наследника прокомментированы в коде, надеюсь они понятны для самостоятельного разбора.
На этом требуемые изменения класса базового объекта завершены (при дальнейшей разработке библиотеки и создании новых
коллекций, в последний метод будут добавляться новые идентификаторы коллекций для создания верного описания событий).
Ставим класс символа и коллекцию символов на новые рельсы
Сегодня мы переведём работу класса символа и коллекции символов с работой с новыми событиями базового объекта. Для этого внесём изменения в
классы символа и коллекции символов.
Откроем файл \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh и начнём вносить изменения.
Так как теперь все события объектов-наследников базового объекта определяются в родительском классе, то отпала необходимость
контролировать изменение свойств объекта в классе-наследнике. А значит — теперь не нужна структура данных отслеживаемых свойств
объекта.
Удалим структуру и два объекта с типом этой структуры из класса объекта-символа:
struct MqlDataSymbol
{
//--- Целочисленные свойства символа
ENUM_SYMBOL_TRADE_MODE trade_mode; // SYMBOL_TRADE_MODE Режимы исполнения ордеров
long session_deals; // SYMBOL_SESSION_DEALS Количество сделок в текущей сессии
long session_buy_orders; // SYMBOL_SESSION_BUY_ORDERS Общее число ордеров на покупку в текущий момент
long session_sell_orders; // SYMBOL_SESSION_SELL_ORDERS Общее число ордеров на продажу в текущий момент
long volume; // SYMBOL_VOLUME Volume - объем в последней сделке
long volume_high_day; // SYMBOL_VOLUMEHIGH Максимальный Volume за день
long volume_low_day; // SYMBOL_VOLUMELOW Минимальный Volume за день
int spread; // SYMBOL_SPREAD Размер спреда в пунктах
int stops_level; // SYMBOL_TRADE_STOPS_LEVEL Минимальный отступ в пунктах от текущей цены закрытия для установки Stop ордеров
int freeze_level; // SYMBOL_TRADE_FREEZE_LEVEL Дистанция заморозки торговых операций (в пунктах)
//--- Вещественные свойства символа
double bid_last; // SYMBOL_BID/SYMBOL_LAST Bid - лучшее предложение на продажу/Цена, по которой совершена последняя сделка
double bid_last_high; // SYMBOL_BIDHIGH/SYMBOL_LASTHIGH Максимальный Bid за день/Максимальный Last за день
double bid_last_low; // SYMBOL_BIDLOW/SYMBOL_LASTLOW Минимальный Bid за день/Минимальный Last за день
double ask; // SYMBOL_ASK Ask - лучшее предложение на покупку
double ask_high; // SYMBOL_ASKHIGH Максимальный Ask за день
double ask_low; // SYMBOL_ASKLOW Минимальный Ask за день
double volume_real_day; // SYMBOL_VOLUME_REAL Реальный Volume за день
double volume_high_real_day; // SYMBOL_VOLUMEHIGH_REAL Максимальный реальный Volume за день
double volume_low_real_day; // SYMBOL_VOLUMELOW_REAL Минимальный реальный Volume за день
double option_strike; // SYMBOL_OPTION_STRIKE Цена исполнения опциона
double volume_limit; // SYMBOL_VOLUME_LIMIT Максимально допустимый совокупный объем позиции и отложенных ордеров в одном направлении
double swap_long; // SYMBOL_SWAP_LONG Значение свопа в покупку
double swap_short; // SYMBOL_SWAP_SHORT Значение свопа в продажу
double session_volume; // SYMBOL_SESSION_VOLUME Cуммарный объём сделок в текущую сессию
double session_turnover; // SYMBOL_SESSION_TURNOVER Cуммарный оборот в текущую сессию
double session_interest; // SYMBOL_SESSION_INTEREST Cуммарный объём открытых позиций
double session_buy_ord_volume; // SYMBOL_SESSION_BUY_ORDERS_VOLUME Общий объём ордеров на покупку в текущий момент
double session_sell_ord_volume; // SYMBOL_SESSION_SELL_ORDERS_VOLUME Общий объём ордеров на продажу в текущий момент
double session_open; // SYMBOL_SESSION_OPEN Цена открытия сессии
double session_close; // SYMBOL_SESSION_CLOSE Цена закрытия сессии
double session_aw; // SYMBOL_SESSION_AW Средневзвешенная цена сессии
};
MqlDataSymbol m_struct_curr_symbol; // Текущие данные символа
MqlDataSymbol m_struct_prev_symbol; // Прошлые данные символа
//---
Удалим все переменные-члены класса для хранения контролируемых и изменённых свойств объекта-символа — теперь все эти данные хранятся в массивах класса базового объекта:
//--- Сделки текущей сессии
long m_control_session_deals_inc; // Контролируемая величина прироста количества сделок
long m_control_session_deals_dec; // Контролируемая величина уменьшения количества сделок
long m_changed_session_deals_value; // Величина изменения количества сделок
bool m_is_change_session_deals_inc; // Флаг изменения количества сделок больше, чем на величину прироста
bool m_is_change_session_deals_dec; // Флаг изменения количества сделок больше, чем на величину уменьшения
//--- Ордера Buy текущей сессии
long m_control_session_buy_ord_inc; // Контролируемая величина прироста количества Buy-ордеров
long m_control_session_buy_ord_dec; // Контролируемая величина уменьшения количества Buy-ордеров
long m_changed_session_buy_ord_value; // Величина изменения количества Buy-ордеров
bool m_is_change_session_buy_ord_inc; // Флаг изменения количества Buy-ордеров больше, чем на величину прироста
bool m_is_change_session_buy_ord_dec; // Флаг изменения количества Buy-ордеров больше, чем на величину уменьшения
//--- Ордера Sell текущей сессии
long m_control_session_sell_ord_inc; // Контролируемая величина прироста количества Sell-ордеров
long m_control_session_sell_ord_dec; // Контролируемая величина уменьшения количества Sell-ордеров
long m_changed_session_sell_ord_value; // Величина изменения количества Sell-ордеров
bool m_is_change_session_sell_ord_inc; // Флаг изменения количества Sell-ордеров больше, чем на величину прироста
bool m_is_change_session_sell_ord_dec; // Флаг изменения количества Sell-ордеров больше, чем на величину уменьшения
//--- Объем в последней сделке
long m_control_volume_inc; // Контролируемая величина прироста объема в последней сделке
long m_control_volume_dec; // Контролируемая величина уменьшения объема в последней сделке
long m_changed_volume_value; // Величина изменения объема в последней сделке
bool m_is_change_volume_inc; // Флаг изменения объема в последней сделке больше, чем на величину прироста
bool m_is_change_volume_dec; // Флаг изменения объема в последней сделке больше, чем на величину уменьшения
//--- Максимальный Volume за день
long m_control_volume_high_day_inc; // Контролируемая величина прироста максимального объема за день
long m_control_volume_high_day_dec; // Контролируемая величина уменьшения максимального объема за день
long m_changed_volume_high_day_value; // Величина изменения максимального объема за день
bool m_is_change_volume_high_day_inc; // Флаг изменения максимального объема за день больше, чем на величину прироста
bool m_is_change_volume_high_day_dec; // Флаг изменения максимального объема за день больше, чем на величину уменьшения
//--- Минимальный Volume за день
long m_control_volume_low_day_inc; // Контролируемая величина прироста минимального объема за день
long m_control_volume_low_day_dec; // Контролируемая величина уменьшения минимального объема за день
long m_changed_volume_low_day_value; // Величина изменения минимального объема за день
bool m_is_change_volume_low_day_inc; // Флаг изменения минимального объема за день больше, чем на величину прироста
bool m_is_change_volume_low_day_dec; // Флаг изменения минимального объема за день больше, чем на величину уменьшения
//--- Спред
int m_control_spread_inc; // Контролируемая величина прироста спреда в пунктах
int m_control_spread_dec; // Контролируемая величина уменьшения спреда в пунктах
int m_changed_spread_value; // Величина изменения спреда в пунктах
bool m_is_change_spread_inc; // Флаг изменения спреда в пунктах больше, чем на величину прироста
bool m_is_change_spread_dec; // Флаг изменения спреда в пунктах больше, чем на величину уменьшения
//--- StopLevel
int m_control_stops_level_inc; // Контролируемая величина прироста StopLevel в пунктах
int m_control_stops_level_dec; // Контролируемая величина уменьшения StopLevel в пунктах
int m_changed_stops_level_value; // Величина изменения StopLevel в пунктах
bool m_is_change_stops_level_inc; // Флаг изменения StopLevel в пунктах больше, чем на величину прироста
bool m_is_change_stops_level_dec; // Флаг изменения StopLevel в пунктах больше, чем на величину уменьшения
//--- Дистанция заморозки
int m_control_freeze_level_inc; // Контролируемая величина прироста FreezeLevel в пунктах
int m_control_freeze_level_dec; // Контролируемая величина уменьшения FreezeLevel в пунктах
int m_changed_freeze_level_value; // Величина изменения FreezeLevel в пунктах
bool m_is_change_freeze_level_inc; // Флаг изменения FreezeLevel в пунктах больше, чем на величину прироста
bool m_is_change_freeze_level_dec; // Флаг изменения FreezeLevel в пунктах больше, чем на величину уменьшения
//--- Bid/Last
double m_control_bid_last_inc; // Контролируемая величина прироста цены Bid или Last
double m_control_bid_last_dec; // Контролируемая величина уменьшения цены Bid или Last
double m_changed_bid_last_value; // Величина изменения цены Bid или Last
bool m_is_change_bid_last_inc; // Флаг изменения цены Bid или Last больше, чем на величину прироста
bool m_is_change_bid_last_dec; // Флаг изменения цены Bid или Last больше, чем на величину уменьшения
//--- Максимальный Bid/Last за день
double m_control_bid_last_high_inc; // Контролируемая величина прироста максимального Bid или Last за день
double m_control_bid_last_high_dec; // Контролируемая величина уменьшения максимального Bid или Last за день
double m_changed_bid_last_high_value; // Величина изменения максимального Bid или Last за день
bool m_is_change_bid_last_high_inc; // Флаг изменения максимального Bid или Last за день больше, чем на величину прироста
bool m_is_change_bid_last_high_dec; // Флаг изменения максимального Bid или Last за день больше, чем на величину уменьшения
//--- Минимальный Bid/Last за день
double m_control_bid_last_low_inc; // Контролируемая величина прироста минимального Bid или Last за день
double m_control_bid_last_low_dec; // Контролируемая величина уменьшения минимального Bid или Last за день
double m_changed_bid_last_low_value; // Величина изменения минимального Bid или Last за день
bool m_is_change_bid_last_low_inc; // Флаг изменения минимального Bid или Last за день больше, чем на величину прироста
bool m_is_change_bid_last_low_dec; // Флаг изменения минимального Bid или Last за день больше, чем на величину уменьшения
//--- Ask
double m_control_ask_inc; // Контролируемая величина прироста цены Ask
double m_control_ask_dec; // Контролируемая величина уменьшения цены Ask
double m_changed_ask_value; // Величина изменения цены Ask
bool m_is_change_ask_inc; // Флаг изменения цены Ask больше, чем на величину прироста
bool m_is_change_ask_dec; // Флаг изменения цены Ask больше, чем на величину уменьшения
//--- Максимальный Ask за день
double m_control_ask_high_inc; // Контролируемая величина прироста максимального Ask за день
double m_control_ask_high_dec; // Контролируемая величина уменьшения максимального Ask за день
double m_changed_ask_high_value; // Величина изменения максимального Ask за день
bool m_is_change_ask_high_inc; // Флаг изменения максимального Ask за день больше, чем на величину прироста
bool m_is_change_ask_high_dec; // Флаг изменения максимального Ask за день больше, чем на величину уменьшения
//--- Минимальный Ask за день
double m_control_ask_low_inc; // Контролируемая величина прироста минимального Ask за день
double m_control_ask_low_dec; // Контролируемая величина уменьшения минимального Ask за день
double m_changed_ask_low_value; // Величина изменения минимального Ask за день
bool m_is_change_ask_low_inc; // Флаг изменения минимального Ask за день больше, чем на величину прироста
bool m_is_change_ask_low_dec; // Флаг изменения минимального Ask за день больше, чем на величину уменьшения
//--- Реальный Volume за день
double m_control_volume_real_inc; // Контролируемая величина прироста реального Volume за день
double m_control_volume_real_dec; // Контролируемая величина уменьшения реального Volume за день
double m_changed_volume_real_value; // Величина изменения реального Volume за день
bool m_is_change_volume_real_inc; // Флаг изменения реального Volume за день больше, чем на величину прироста
bool m_is_change_volume_real_dec; // Флаг изменения реального Volume за день больше, чем на величину уменьшения
//--- Максимальный реальный Volume за день
double m_control_volume_high_real_day_inc; // Контролируемая величина прироста максимального реального Volume за день
double m_control_volume_high_real_day_dec; // Контролируемая величина уменьшения максимального реального Volume за день
double m_changed_volume_high_real_day_value; // Величина изменения максимального реального Volume за день
bool m_is_change_volume_high_real_day_inc; // Флаг изменения максимального реального Volume за день больше, чем на величину прироста
bool m_is_change_volume_high_real_day_dec; // Флаг изменения максимального реального Volume за день больше, чем на величину уменьшения
//--- Минимальный реальный Volume за день
double m_control_volume_low_real_day_inc; // Контролируемая величина прироста минимального реального Volume за день
double m_control_volume_low_real_day_dec; // Контролируемая величина уменьшения минимального реального Volume за день
double m_changed_volume_low_real_day_value; // Величина изменения минимального реального Volume за день
bool m_is_change_volume_low_real_day_inc; // Флаг изменения минимального реального Volume за день больше, чем на величину прироста
bool m_is_change_volume_low_real_day_dec; // Флаг изменения минимального реального Volume за день больше, чем на величину уменьшения
//--- Цена исполнения опциона
double m_control_option_strike_inc; // Контролируемая величина прироста цены исполнения опциона
double m_control_option_strike_dec; // Контролируемая величина уменьшения цены исполнения опциона
double m_changed_option_strike_value; // Величина изменения цены исполнения опциона
bool m_is_change_option_strike_inc; // Флаг изменения цены исполнения опциона больше, чем на величину прироста
bool m_is_change_option_strike_dec; // Флаг изменения цены исполнения опциона больше, чем на величину уменьшения
//--- Совокупный объём позиций и ордеров
double m_changed_volume_limit_value; // Величина изменения минимального совокупного объёма
bool m_is_change_volume_limit_inc; // Флаг увеличения минимального совокупного объёма
bool m_is_change_volume_limit_dec; // Флаг уменьшения минимального совокупного объёма
//--- Своп на покупку
double m_changed_swap_long_value; // Величина изменения свопа на покупку
bool m_is_change_swap_long_inc; // Флаг увеличения свопа на покупку
bool m_is_change_swap_long_dec; // Флаг уменьшения свопа на покупку
//--- Своп на продажу
double m_changed_swap_short_value; // Величина изменения свопа на продажу
bool m_is_change_swap_short_inc; // Флаг увеличения свопа на продажу
bool m_is_change_swap_short_dec; // Флаг уменьшения свопа на продажу
//--- Cуммарный объём сделок в текущую сессию
double m_control_session_volume_inc; // Контролируемая величина прироста суммарного объёма сделок в текущую сессию
double m_control_session_volume_dec; // Контролируемая величина уменьшения суммарного объёма сделок в текущую сессию
double m_changed_session_volume_value; // Величина изменения суммарного объёма сделок в текущую сессию
bool m_is_change_session_volume_inc; // Флаг изменения суммарного объёма сделок в текущую сессию больше, чем на величину прироста
bool m_is_change_session_volume_dec; // Флаг изменения суммарного объёма сделок в текущую сессию больше, чем на величину уменьшения
//--- Cуммарный оборот в текущую сессию
double m_control_session_turnover_inc; // Контролируемая величина прироста суммарного оборота в текущую сессию
double m_control_session_turnover_dec; // Контролируемая величина уменьшения суммарного оборота в текущую сессию
double m_changed_session_turnover_value; // Величина изменения суммарного оборота в текущую сессию
bool m_is_change_session_turnover_inc; // Флаг изменения суммарного оборота в текущую сессию больше, чем на величину прироста
bool m_is_change_session_turnover_dec; // Флаг изменения суммарного оборота в текущую сессию больше, чем на величину уменьшения
//--- Cуммарный объём открытых позиций
double m_control_session_interest_inc; // Контролируемая величина прироста суммарного объёма открытых позиций в текущую сессию
double m_control_session_interest_dec; // Контролируемая величина уменьшения суммарного объёма открытых позиций в текущую сессию
double m_changed_session_interest_value; // Величина изменения суммарного объёма открытых позиций в текущую сессию
bool m_is_change_session_interest_inc; // Флаг изменения суммарного объёма открытых позиций в текущую сессию больше, чем на величину прироста
bool m_is_change_session_interest_dec; // Флаг изменения суммарного объёма открытых позиций в текущую сессию больше, чем на величину уменьшения
//--- Общий объём ордеров на покупку в текущий момент
double m_control_session_buy_ord_volume_inc; // Контролируемая величина прироста общего объёма ордеров на покупку в текущий момент
double m_control_session_buy_ord_volume_dec; // Контролируемая величина уменьшения общего объёма ордеров на покупку в текущий момент
double m_changed_session_buy_ord_volume_value; // Величина изменения общего объёма ордеров на покупку в текущий момент
bool m_is_change_session_buy_ord_volume_inc; // Флаг изменения общего объёма ордеров на покупку в текущий момент больше, чем на величину прироста
bool m_is_change_session_buy_ord_volume_dec; // Флаг изменения общего объёма ордеров на покупку в текущий момент больше, чем на величину уменьшения
//--- Общий объём ордеров на продажу в текущий момент
double m_control_session_sell_ord_volume_inc; // Контролируемая величина прироста общего объёма ордеров на продажу в текущий момент
double m_control_session_sell_ord_volume_dec; // Контролируемая величина уменьшения общего объёма ордеров на продажу в текущий момент
double m_changed_session_sell_ord_volume_value; // Величина изменения общего объёма ордеров на продажу в текущий момент
bool m_is_change_session_sell_ord_volume_inc; // Флаг изменения общего объёма ордеров на продажу в текущий момент больше, чем на величину прироста
bool m_is_change_session_sell_ord_volume_dec; // Флаг изменения общего объёма ордеров на продажу в текущий момент больше, чем на величину уменьшения
//--- Цена открытия сессии
double m_control_session_open_inc; // Контролируемая величина прироста цены открытия сессии
double m_control_session_open_dec; // Контролируемая величина уменьшения цены открытия сессии
double m_changed_session_open_value; // Величина изменения цены открытия сессии
bool m_is_change_session_open_inc; // Флаг изменения цены открытия сессии больше, чем на величину прироста
bool m_is_change_session_open_dec; // Флаг изменения цены открытия сессии больше, чем на величину уменьшения
//--- Цена закрытия сессии
double m_control_session_close_inc; // Контролируемая величина прироста цены закрытия сессии
double m_control_session_close_dec; // Контролируемая величина уменьшения цены закрытия сессии
double m_changed_session_close_value; // Величина изменения цены закрытия сессии
bool m_is_change_session_close_inc; // Флаг изменения цены закрытия сессии больше, чем на величину прироста
bool m_is_change_session_close_dec; // Флаг изменения цены закрытия сессии больше, чем на величину уменьшения
//--- Средневзвешенная цена сессии
double m_control_session_aw_inc; // Контролируемая величина прироста средневзвешенной цены сессии
double m_control_session_aw_dec; // Контролируемая величина уменьшения средневзвешенной цены сессии
double m_changed_session_aw_value; // Величина изменения средневзвешенной цены сессии
bool m_is_change_session_aw_inc; // Флаг изменения средневзвешенной цены сессии больше, чем на величину прироста
bool m_is_change_session_aw_dec; // Флаг изменения средневзвешенной цены сессии больше, чем на величину уменьшения
Удалим за ненадобностью выделенные методы:
//--- Инициализирует переменные (1) отслеживаемых, (2) контролируемых данных символа virtual void InitChangesParams(void); virtual void InitControlsParams(void); //--- Проверяет изменения символа, возвращает код изменения virtual int SetEventCode(void); //--- Устанавливает тип события и заполняет список событий virtual void SetTypeEvent(void);
//--- Возвращает описание события символа string EventDescription(const ENUM_SYMBOL_EVENT event);
А вместо виртуального метода установки кода изменения свойства символа объявим
метод проверки изменения свойств символа и создания события:
//--- Инициализирует переменные контролируемых данных символа virtual void InitControlsParams(void); //--- Проверяет список изменений свойств символа и создаёт событие void CheckEvents(void);
В публичную секцию класса впишем объявления методов, устанавливающих отслеживаемые величины, и возвращающих установленные
контрольные значения отслеживаемых свойств, величины изменения свойств и флаги:
public: //--- Устанавливает величину изменения контролируемого свойства символа template<typename T> void SetControlChangedValue(const int property,const T value); //--- Устанавливает величину контролируемого (1) приращения, (2) уменьшения свойства символа, (3) контрольного уровня template<typename T> void SetControlPropertyINC(const int property,const T value); template<typename T> void SetControlPropertyDEC(const int property,const T value); template<typename T> void SetControlPropertyLEVEL(const int property,const T value); //--- Устанавливает Флаг изменения значения свойства символа больше, чем на величину (1) прироста, (2) уменьшения template<typename T> void SetControlFlagINC(const int property,const T value); template<typename T> void SetControlFlagDEC(const int property,const T value); //--- Возвращает установленную величину контролируемого приращения (1) целочисленного, (2) вещественного свойства символа long GetControlParameterINC(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledValueLongINC(property); } double GetControlParameterINC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledValueDoubleINC(property); } //--- Возвращает установленную величину контролируемого уменьшения (1) целочисленного, (2) вещественного свойства символа long GetControlParameterDEC(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledValueLongDEC(property); } double GetControlParameterDEC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledValueDoubleDEC(property); } //--- Возвращает Флаг изменения значения (1) целочисленного, (2) вещественного свойства символа больше, чем на величину прироста long GetControlFlagINC(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledFlagLongINC(property); } double GetControlFlagINC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledFlagDoubleINC(property); } //--- Возвращает Флаг изменения значения (1) целочисленного, (2) вещественного свойства символа больше, чем на величину уменьшения bool GetControlFlagDEC(const ENUM_SYMBOL_PROP_INTEGER property) const { return (bool)this.GetControlledFlagLongDEC(property); } bool GetControlFlagDEC(const ENUM_SYMBOL_PROP_DOUBLE property) const { return (bool)this.GetControlledFlagDoubleDEC(property); } //--- Возвращает величину изменения контролируемого (1) целочисленного, (2) вещественного свойства объекта long GetControlChangedValue(const ENUM_SYMBOL_PROP_INTEGER property) const { return this.GetControlledChangedValueLong(property); } double GetControlChangedValue(const ENUM_SYMBOL_PROP_DOUBLE property) const { return this.GetControlledChangedValueDouble(property); } //+------------------------------------------------------------------+
Каждый метод выполнен в виде двух перегруженных методов, вызывающих методы базового объекта, соответствующие типу
устанавливаемого/проверяемого свойства объекта-символа.
Ранее мы уже писали методы упрощённого доступа к некоторым свойствам объекта-символа. Допишем туда же методы установки величин контрольных уровней значений свойств и объявим методы установки/получения данных для Bid/Last и связанных с ними параметров (ранее автоматически выбиралось что использовать Bid или Last в зависимости от цен, по которым строится график. Теперь же необходимо создать методы для работы с этими данными):
//+------------------------------------------------------------------+ //| Получение и установка параметров отслеживаемых изменений свойств | //+------------------------------------------------------------------+ //--- Исполнение //--- Флаг изменения режима торговли для символа bool IsChangedTradeMode(void) const { return this.m_is_change_trade_mode; } //--- Сделки текущей сессии //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня количества сделок в текущую сессию //--- получение (3) величины изменения количества сделок в текущую сессию, //--- получение флага изменения количества сделок в текущую сессию больше, чем на величину (4) прироста, (5) уменьшения void SetControlSessionDealsInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_DEALS,(long)::fabs(value)); } void SetControlSessionDealsDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_DEALS,(long)::fabs(value)); } void SetControlSessionDealsLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_DEALS,(long)::fabs(value)); } long GetValueChangedSessionDeals(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_DEALS); } bool IsIncreasedSessionDeals(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_DEALS); } bool IsDecreasedSessionDeals(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_DEALS); } //--- Ордера Buy текущей сессии //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня количества Buy-ордеров в текущий момент //--- получение (4) величины изменения количества Buy-ордеров в текущий момент, //--- получение флага изменения количества Buy-ордеров в текущий момент больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionBuyOrdInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_BUY_ORDERS,(long)::fabs(value)); } void SetControlSessionBuyOrdDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_BUY_ORDERS,(long)::fabs(value)); } void SetControlSessionBuyOrdLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_BUY_ORDERS,(long)::fabs(value)); } long GetValueChangedSessionBuyOrders(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_BUY_ORDERS); } bool IsIncreasedSessionBuyOrders(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_BUY_ORDERS); } bool IsDecreasedSessionBuyOrders(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_BUY_ORDERS); } //--- Ордера Sell текущей сессии //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня количества Sell-ордеров в текущий момент //--- получение (4) величины изменения количества Sell-ордеров в текущий момент, //--- получение флага изменения количества Sell-ордеров в текущий момент больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionSellOrdInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_SELL_ORDERS,(long)::fabs(value)); } void SetControlSessionSellOrdDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_SELL_ORDERS,(long)::fabs(value)); } void SetControlSessionSellOrdLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_SELL_ORDERS,(long)::fabs(value));} long GetValueChangedSessionSellOrders(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_SELL_ORDERS); } bool IsIncreasedSessionSellOrders(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_SELL_ORDERS); } bool IsDecreasedSessionSellOrders(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_SELL_ORDERS); } //--- Объем в последней сделке //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня объема в последней сделке //--- получение (4) величины изменения объема в последней сделке, //--- получение флага изменения объема в последней сделке больше, чем на величину (5) прироста, (6) уменьшения void SetControlVolumeInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUME,(long)::fabs(value)); } void SetControlVolumeDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUME,(long)::fabs(value)); } void SetControlVolumeLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUME,(long)::fabs(value)); } long GetValueChangedVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUME); } bool IsIncreasedVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUME); } bool IsDecreasedVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUME); } //--- Максимальный Volume за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня максимального объема за день //--- получение (4) величины изменения максимального объема за день, //--- получение флага изменения максимального объема за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlVolumeHighInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMEHIGH,(long)::fabs(value)); } void SetControlVolumeHighDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMEHIGH,(long)::fabs(value)); } void SetControlVolumeHighLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMEHIGH,(long)::fabs(value)); } long GetValueChangedVolumeHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMEHIGH); } bool IsIncreasedVolumeHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMEHIGH); } bool IsDecreasedVolumeHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMEHIGH); } //--- Минимальный Volume за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня минимального объема за день //--- получение (4) величины изменения минимального объема за день, //--- получение флага изменения минимального объема за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlVolumeLowInc(const long value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMELOW,(long)::fabs(value)); } void SetControlVolumeLowDec(const long value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMELOW,(long)::fabs(value)); } void SetControlVolumeLowLevel(const long value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMELOW,(long)::fabs(value)); } long GetValueChangedVolumeLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMELOW); } bool IsIncreasedVolumeLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMELOW); } bool IsDecreasedVolumeLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMELOW); } //--- Спред //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня спреда в пунктах //--- получение (4) величины изменения спреда в пунктах, //--- получение флага изменения спреда в пунктах больше, чем на величину (5) прироста, (6) уменьшения void SetControlSpreadInc(const int value) { this.SetControlPropertyINC(SYMBOL_PROP_SPREAD,(long)::fabs(value)); } void SetControlSpreadDec(const int value) { this.SetControlPropertyDEC(SYMBOL_PROP_SPREAD,(long)::fabs(value)); } void SetControlSpreadLevel(const int value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SPREAD,(long)::fabs(value)); } int GetValueChangedSpread(void) const { return (int)this.GetControlChangedValue(SYMBOL_PROP_SPREAD); } bool IsIncreasedSpread(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SPREAD); } bool IsDecreasedSpread(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SPREAD); } //--- StopLevel //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня StopLevel в пунктах //--- получение (4) величины изменения StopLevel в пунктах, //--- получение флага изменения StopLevel в пунктах больше, чем на величину (5) прироста, (6) уменьшения void SetControlStopLevelInc(const int value) { this.SetControlPropertyINC(SYMBOL_PROP_TRADE_STOPS_LEVEL,(long)::fabs(value)); } void SetControlStopLevelDec(const int value) { this.SetControlPropertyDEC(SYMBOL_PROP_TRADE_STOPS_LEVEL,(long)::fabs(value)); } void SetControlStopLevelLevel(const int value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_TRADE_STOPS_LEVEL,(long)::fabs(value)); } int GetValueChangedStopLevel(void) const { return (int)this.GetControlChangedValue(SYMBOL_PROP_TRADE_STOPS_LEVEL); } bool IsIncreasedStopLevel(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_TRADE_STOPS_LEVEL); } bool IsDecreasedStopLevel(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_TRADE_STOPS_LEVEL); } //--- Дистанция заморозки //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня FreezeLevel в пунктах //--- получение (4) величины изменения FreezeLevel в пунктах, //--- получение флага изменения FreezeLevel в пунктах больше, чем на величину (5) прироста, (6) уменьшения void SetControlFreezeLevelInc(const int value) { this.SetControlPropertyINC(SYMBOL_PROP_TRADE_FREEZE_LEVEL,(long)::fabs(value)); } void SetControlFreezeLevelDec(const int value) { this.SetControlPropertyDEC(SYMBOL_PROP_TRADE_FREEZE_LEVEL,(long)::fabs(value)); } void SetControlFreezeLevelLevel(const int value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_TRADE_FREEZE_LEVEL,(long)::fabs(value)); } int GetValueChangedFreezeLevel(void) const { return (int)this.GetControlChangedValue(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } bool IsIncreasedFreezeLevel(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } bool IsDecreasedFreezeLevel(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } //--- Bid //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены Bid //--- получение (4) величины изменения цены Bid или Last, //--- получение флага изменения цены Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlBidInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_BID,::fabs(value)); } void SetControlBidDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_BID,::fabs(value)); } void SetControlBidLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_BID,::fabs(value)); } double GetValueChangedBid(void) const { return this.GetControlChangedValue(SYMBOL_PROP_BID); } bool IsIncreasedBid(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_BID); } bool IsDecreasedBid(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_BID); } //--- Максимальный Bid за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня максимального Bid //--- получение (4) величины изменения максимального Bid или Last, //--- получение флага изменения максимального Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlBidHighInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_BIDHIGH,::fabs(value)); } void SetControlBidHighDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_BIDHIGH,::fabs(value)); } void SetControlBidHighLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_BIDHIGH,::fabs(value)); } double GetValueChangedBidHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_BIDHIGH); } bool IsIncreasedBidHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDHIGH); } bool IsDecreasedBidHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDHIGH); } //--- Минимальный Bid за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня минимального Bid //--- получение (4) величины изменения минимального Bid или Last, //--- получение флага изменения минимального Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlBidLowInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_BIDLOW,::fabs(value)); } void SetControlBidLowDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_BIDLOW,::fabs(value)); } void SetControlBidLowLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_BIDLOW,::fabs(value)); } double GetValueChangedBidLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_BIDLOW); } bool IsIncreasedBidLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDLOW); } bool IsDecreasedBidLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDLOW); } //--- Last //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены Last //--- получение (4) величины изменения цены Bid или Last, //--- получение флага изменения цены Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlLastInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_LAST,::fabs(value)); } void SetControlLastDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_LAST,::fabs(value)); } void SetControlLastLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_LAST,::fabs(value)); } double GetValueChangedLast(void) const { return this.GetControlChangedValue(SYMBOL_PROP_LAST); } bool IsIncreasedLast(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_LAST); } bool IsDecreasedLast(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_LAST); } //--- Максимальный Last за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня максимального Last //--- получение (4) величины изменения максимального Bid или Last, //--- получение флага изменения максимального Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlLastHighInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_LASTHIGH,::fabs(value)); } void SetControlLastHighDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_LASTHIGH,::fabs(value)); } void SetControlLastHighLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_LASTHIGH,::fabs(value)); } double GetValueChangedLastHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_LASTHIGH); } bool IsIncreasedLastHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTHIGH); } bool IsDecreasedLastHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTHIGH); } //--- Минимальный Last за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня минимального Last //--- получение (4) величины изменения минимального Bid или Last, //--- получение флага изменения минимального Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlLastLowInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_LASTLOW,::fabs(value)); } void SetControlLastLowDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_LASTLOW,::fabs(value)); } void SetControlLastLowLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_LASTLOW,::fabs(value)); } double GetValueChangedLastLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_LASTLOW); } bool IsIncreasedLastLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTLOW); } bool IsDecreasedLastLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTLOW); } //--- Bid/Last //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены Bid или Last //--- получение (4) величины изменения цены Bid или Last, //--- получение флага изменения цены Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlBidLastInc(const double value); void SetControlBidLastDec(const double value); void SetControlBidLastLevel(const double value); double GetValueChangedBidLast(void) const; bool IsIncreasedBidLast(void) const; bool IsDecreasedBidLast(void) const; //--- Максимальный Bid/Last за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня максимального Bid или Last //--- получение (4) величины изменения максимального Bid или Last, //--- получение флага изменения максимального Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlBidLastHighInc(const double value); void SetControlBidLastHighDec(const double value); void SetControlBidLastHighLevel(const double value); double GetValueChangedBidLastHigh(void) const; bool IsIncreasedBidLastHigh(void) const; bool IsDecreasedBidLastHigh(void) const; //--- Минимальный Bid/Last за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня минимального Bid или Last //--- получение (4) величины изменения минимального Bid или Last, //--- получение флага изменения минимального Bid или Last больше, чем на величину (5) прироста, (6) уменьшения void SetControlBidLastLowInc(const double value); void SetControlBidLastLowDec(const double value); void SetControlBidLastLowLevev(const double value); double GetValueChangedBidLastLow(void) const; bool IsIncreasedBidLastLow(void) const; bool IsDecreasedBidLastLow(void) const; //--- Ask //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены Ask //--- получение (4) величины изменения цены Ask, //--- получение флага изменения цены Ask больше, чем на величину (5) прироста, (6) уменьшения void SetControlAskInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_ASK,::fabs(value)); } void SetControlAskDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_ASK,::fabs(value)); } void SetControlAskLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_ASK,::fabs(value)); } double GetValueChangedAsk(void) const { return this.GetControlChangedValue(SYMBOL_PROP_ASK); } bool IsIncreasedAsk(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_ASK); } bool IsDecreasedAsk(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_ASK); } //--- Максимальный Ask за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня максимального Ask за день //--- получение (4) величины изменения максимального Ask за день, //--- получение флага изменения максимального Ask за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlAskHighInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_ASKHIGH,::fabs(value)); } void SetControlAskHighDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_ASKHIGH,::fabs(value)); } void SetControlAskHighLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_ASKHIGH,::fabs(value)); } double GetValueChangedAskHigh(void) const { return this.GetControlChangedValue(SYMBOL_PROP_ASKHIGH); } bool IsIncreasedAskHigh(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_ASKHIGH); } bool IsDecreasedAskHigh(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_ASKHIGH); } //--- Минимальный Ask за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня минимального Ask за день //--- получение (4) величины изменения минимального Ask за день, //--- получение флага изменения минимального Ask за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlAskLowInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_ASKLOW,::fabs(value)); } void SetControlAskLowDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_ASKLOW,::fabs(value)); } void SetControlAskLowLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_ASKLOW,::fabs(value)); } double GetValueChangedAskLow(void) const { return this.GetControlChangedValue(SYMBOL_PROP_ASKLOW); } bool IsIncreasedAskLow(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_ASKLOW); } bool IsDecreasedAskLow(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_ASKLOW); } //--- Реальный Volume за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня реального Volume за день //--- получение (4) величины изменения реального Volume за день, //--- получение флага изменения реального Volume за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlVolumeRealInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUME_REAL,::fabs(value)); } void SetControlVolumeRealDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUME_REAL,::fabs(value)); } void SetControlVolumeRealLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUME_REAL,::fabs(value)); } double GetValueChangedVolumeReal(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUME_REAL); } bool IsIncreasedVolumeReal(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUME_REAL); } bool IsDecreasedVolumeReal(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUME_REAL); } //--- Максимальный реальный Volume за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня максимального реального Volume за день //--- получение (4) величины изменения максимального реального Volume за день, //--- получение флага изменения максимального реального Volume за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlVolumeHighRealInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMEHIGH_REAL,::fabs(value)); } void SetControlVolumeHighRealDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMEHIGH_REAL,::fabs(value)); } void SetControlVolumeHighRealLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMEHIGH_REAL,::fabs(value)); } double GetValueChangedVolumeHighReal(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMEHIGH_REAL); } bool IsIncreasedVolumeHighReal(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMEHIGH_REAL); } bool IsDecreasedVolumeHighReal(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMEHIGH_REAL); } //--- Минимальный реальный Volume за день //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня минимального реального Volume за день //--- получение (4) величины изменения минимального реального Volume за день, //--- получение флага изменения минимального реального Volume за день больше, чем на величину (5) прироста, (6) уменьшения void SetControlVolumeLowRealInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_VOLUMELOW_REAL,::fabs(value)); } void SetControlVolumeLowRealDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_VOLUMELOW_REAL,::fabs(value)); } void SetControlVolumeLowRealLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUMELOW_REAL,::fabs(value)); } double GetValueChangedVolumeLowReal(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUMELOW_REAL); } bool IsIncreasedVolumeLowReal(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUMELOW_REAL); } bool IsDecreasedVolumeLowReal(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUMELOW_REAL); } //--- Цена исполнения опциона //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены исполнения опциона //--- получение (4) величины изменения цены исполнения опциона, //--- получение флага изменения цены исполнения опциона больше, чем на величину (5) прироста, (6) уменьшения void SetControlOptionStrikeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_OPTION_STRIKE,::fabs(value)); } void SetControlOptionStrikeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_OPTION_STRIKE,::fabs(value)); } void SetControlOptionStrikeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_OPTION_STRIKE,::fabs(value)); } double GetValueChangedOptionStrike(void) const { return this.GetControlChangedValue(SYMBOL_PROP_OPTION_STRIKE); } bool IsIncreasedOptionStrike(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_OPTION_STRIKE); } bool IsDecreasedOptionStrike(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_OPTION_STRIKE); } //--- Максимально-допустимый совокупный объём позиций и ордеров в одном направлении //--- (1) Установка контрольного уровня //--- (2) получение величины изменения максимально-допустимого совокупного объёма позиций и ордеров в одном направлении, //--- получение флага (3) увеличения, (4) уменьшения максимально-допустимого совокупного объёма позиций и ордеров в одном направлении void SetControlVolumeLimitLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_VOLUME_LIMIT,::fabs(value)); } double GetValueChangedVolumeLimit(void) const { return this.GetControlChangedValue(SYMBOL_PROP_VOLUME_LIMIT); } bool IsIncreasedVolumeLimit(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_VOLUME_LIMIT); } bool IsDecreasedVolumeLimit(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_VOLUME_LIMIT); } //--- Своп на покупку //--- (1) Установка контрольного уровня //--- (2) получение величины изменения свопа на покупку, //--- получение флага (3) увеличения, (4) уменьшения свопа на покупку void SetControlSwapLongLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SWAP_LONG,::fabs(value)); } double GetValueChangedSwapLong(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SWAP_LONG); } bool IsIncreasedSwapLong(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SWAP_LONG); } bool IsDecreasedSwapLong(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SWAP_LONG); } //--- Своп на продажу //--- (1) Установка контрольного уровня //--- (2) получение величины изменения свопа на продажу, //--- получение флага (3) увеличения, (4) уменьшения свопа на продажу void SetControlSwapShortLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SWAP_SHORT,::fabs(value)); } double GetValueChangedSwapShort(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SWAP_SHORT); } bool IsIncreasedSwapShort(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SWAP_SHORT); } bool IsDecreasedSwapShort(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SWAP_SHORT); } //--- Cуммарный объём сделок в текущую сессию //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня суммарного объёма сделок в текущую сессию //--- получение (4) величины изменения суммарного объёма сделок в текущую сессию, //--- получение флага изменения суммарного объёма сделок в текущую сессию больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionVolumeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_VOLUME,::fabs(value)); } void SetControlSessionVolumeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_VOLUME,::fabs(value)); } void SetControlSessionVolumeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_VOLUME,::fabs(value)); } double GetValueChangedSessionVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_VOLUME); } bool IsIncreasedSessionVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_VOLUME); } bool IsDecreasedSessionVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_VOLUME); } //--- Cуммарный оборот в текущую сессию //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня суммарного оборота в текущую сессию //--- получение (4) величины изменения суммарного оборота в текущую сессию, //--- получение флага изменения суммарного оборота в текущую сессию больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionTurnoverInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_TURNOVER,::fabs(value)); } void SetControlSessionTurnoverDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_TURNOVER,::fabs(value)); } void SetControlSessionTurnoverLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_TURNOVER,::fabs(value)); } double GetValueChangedSessionTurnover(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_TURNOVER); } bool IsIncreasedSessionTurnover(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_TURNOVER); } bool IsDecreasedSessionTurnover(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_TURNOVER); } //--- Cуммарный объём открытых позиций //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня суммарного объёма открытых позиций в текущую сессию //--- получение (4) величины изменения суммарного объёма открытых позиций в текущую сессию, //--- получение флага изменения суммарного объёма открытых позиций в текущую сессию больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionInterestInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_INTEREST,::fabs(value)); } void SetControlSessionInterestDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_INTEREST,::fabs(value)); } void SetControlSessionInterestLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_INTEREST,::fabs(value)); } double GetValueChangedSessionInterest(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_INTEREST); } bool IsIncreasedSessionInterest(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_INTEREST); } bool IsDecreasedSessionInterest(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_INTEREST); } //--- Общий объём ордеров на покупку в текущий момент //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня общего объёма ордеров на покупку в текущий момент //--- получение (4) величины изменения общего объёма ордеров на покупку в текущий момент, //--- получение флага изменения общего объёма ордеров на покупку в текущий момент больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionBuyOrdVolumeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionBuyOrdVolumeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionBuyOrdVolumeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME,::fabs(value));} double GetValueChangedSessionBuyOrdVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } bool IsIncreasedSessionBuyOrdVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } bool IsDecreasedSessionBuyOrdVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } //--- Общий объём ордеров на продажу в текущий момент //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня общего объёма ордеров на продажу в текущий момент //--- получение (4) величины изменения общего объёма ордеров на продажу в текущий момент, //--- получение флага изменения общего объёма ордеров на продажу в текущий момент больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionSellOrdVolumeInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionSellOrdVolumeDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME,::fabs(value)); } void SetControlSessionSellOrdVolumeLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME,::fabs(value));} double GetValueChangedSessionSellOrdVolume(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } bool IsIncreasedSessionSellOrdVolume(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } bool IsDecreasedSessionSellOrdVolume(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } //--- Цена открытия сессии //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены открытия сессии //--- получение (4) величины изменения цены открытия сессии, //--- получение флага изменения цены открытия сессии больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionPriceOpenInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_OPEN,::fabs(value)); } void SetControlSessionPriceOpenDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_OPEN,::fabs(value)); } void SetControlSessionPriceOpenLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_OPEN,::fabs(value)); } double GetValueChangedSessionPriceOpen(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_OPEN); } bool IsIncreasedSessionPriceOpen(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_OPEN); } bool IsDecreasedSessionPriceOpen(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_OPEN); } //--- Цена закрытия сессии //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня цены закрытия сессии //--- получение (4) величины изменения цены закрытия сессии, //--- получение флага изменения цены закрытия сессии больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionPriceCloseInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_CLOSE,::fabs(value)); } void SetControlSessionPriceCloseDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_CLOSE,::fabs(value)); } void SetControlSessionPriceCloseLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_CLOSE,::fabs(value)); } double GetValueChangedSessionPriceClose(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_CLOSE); } bool IsIncreasedSessionPriceClose(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_CLOSE); } bool IsDecreasedSessionPriceClose(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_CLOSE); } //--- Средневзвешенная цена сессии //--- установка контролируемой величины (1) прироста, (2) уменьшения, (3) контрольного уровня средневзвешенной цены сессии //--- получение (4) величины изменения средневзвешенной цены сессии, //--- получение флага изменения средневзвешенной цены сессии больше, чем на величину (5) прироста, (6) уменьшения void SetControlSessionPriceAWInc(const double value) { this.SetControlPropertyINC(SYMBOL_PROP_SESSION_AW,::fabs(value)); } void SetControlSessionPriceAWDec(const double value) { this.SetControlPropertyDEC(SYMBOL_PROP_SESSION_AW,::fabs(value)); } void SetControlSessionPriceAWLevel(const double value) { this.SetControlPropertyLEVEL(SYMBOL_PROP_SESSION_AW,::fabs(value)); } double GetValueChangedSessionPriceAW(void) const { return this.GetControlChangedValue(SYMBOL_PROP_SESSION_AW); } bool IsIncreasedSessionPriceAW(void) const { return (bool)this.GetControlFlagINC(SYMBOL_PROP_SESSION_AW); } bool IsDecreasedSessionPriceAW(void) const { return (bool)this.GetControlFlagDEC(SYMBOL_PROP_SESSION_AW); } //---
Рассмотрим реализацию объявленных методов и изменения в уже существующих.
В конструктор класса внесём небольшие изменения:
//+------------------------------------------------------------------+ //| Закрытый параметрический конструктор | //+------------------------------------------------------------------+ CSymbol::CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index) { this.m_name=name; this.m_type=COLLECTION_SYMBOLS_ID; if(!this.Exist()) { ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\"",": ",TextByLanguage("Ошибка. Такого символа нет на сервере","Error. There is no such symbol on the server")); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; } bool select=::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); ::ResetLastError(); if(!select) { if(!this.SetToMarketWatch()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\": ",TextByLanguage("Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in the market watch. Error: "),this.m_global_error); } } ::ResetLastError(); if(!::SymbolInfoTick(this.m_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); } //--- Инициализация контролируемых данных this.SetControlDataArraySizeLong(SYMBOL_PROP_INTEGER_TOTAL); this.SetControlDataArraySizeDouble(SYMBOL_PROP_DOUBLE_TOTAL); this.ResetChangesParams(); this.ResetControlsParams(); //--- Инициализация данных символа this.Reset(); this.InitMarginRates(); #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "),this.m_global_error); return; } #endif //--- Сохранение целочисленных свойств this.m_long_prop[SYMBOL_PROP_STATUS] = symbol_status; this.m_long_prop[SYMBOL_PROP_INDEX_MW] = index; this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_DIGITS] = ::SymbolInfoInteger(this.m_name,SYMBOL_DIGITS); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_SPREAD_FLOAT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD_FLOAT); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_TRADE_MODE] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_MODE); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_EXEMODE] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_EXEMODE); this.m_long_prop[SYMBOL_PROP_SWAP_ROLLOVER3DAYS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SWAP_ROLLOVER3DAYS); this.m_long_prop[SYMBOL_PROP_TIME] = this.TickTime(); this.m_long_prop[SYMBOL_PROP_EXIST] = this.SymbolExists(); this.m_long_prop[SYMBOL_PROP_CUSTOM] = this.SymbolCustom(); this.m_long_prop[SYMBOL_PROP_MARGIN_HEDGED_USE_LEG] = this.SymbolMarginHedgedUseLEG(); this.m_long_prop[SYMBOL_PROP_ORDER_MODE] = this.SymbolOrderMode(); this.m_long_prop[SYMBOL_PROP_FILLING_MODE] = this.SymbolOrderFillingMode(); this.m_long_prop[SYMBOL_PROP_EXPIRATION_MODE] = this.SymbolExpirationMode(); this.m_long_prop[SYMBOL_PROP_ORDER_GTC_MODE] = this.SymbolOrderGTCMode(); this.m_long_prop[SYMBOL_PROP_OPTION_MODE] = this.SymbolOptionMode(); this.m_long_prop[SYMBOL_PROP_OPTION_RIGHT] = this.SymbolOptionRight(); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); this.m_long_prop[SYMBOL_PROP_CHART_MODE] = this.SymbolChartMode(); this.m_long_prop[SYMBOL_PROP_TRADE_CALC_MODE] = this.SymbolCalcMode(); this.m_long_prop[SYMBOL_PROP_SWAP_MODE] = this.SymbolSwapMode(); //--- Сохранение вещественных свойств this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_POINT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_POINT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- Сохранение строковых свойств this.m_string_prop[this.IndexProp(SYMBOL_PROP_NAME)] = this.m_name; this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_BASE)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_BASE); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_PROFIT)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_PROFIT); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_MARGIN)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_MARGIN); this.m_string_prop[this.IndexProp(SYMBOL_PROP_DESCRIPTION)] = ::SymbolInfoString(this.m_name,SYMBOL_DESCRIPTION); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PATH)] = ::SymbolInfoString(this.m_name,SYMBOL_PATH); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BASIS)] = this.SymbolBasis(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BANK)] = this.SymbolBank(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_ISIN)] = this.SymbolISIN(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_FORMULA)] = this.SymbolFormula(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PAGE)] = this.SymbolPage(); //--- Сохранение дополнительных целочисленных свойств this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); //--- if(!select) this.RemoveFromMarketWatch(); } //+------------------------------------------------------------------+ //|Сравнивает объекты CSymbol между собой по всем возможным свойствам| //+------------------------------------------------------------------+
Для точной идентификации событий объектов в классе базового объекта, типу объекта-символа присваиваем идентификатор коллекции символов и устанавливаем размеры массивов целочисленных и вещественных данных для отслеживания событий в свойствах объекта-символа базовым родительским объектом. Далее инициализируем изменяемые и контрольные параметры в массивах целочисленных и вещественных свойств.
Также был изменён метод Refresh() объекта-символа:
//+------------------------------------------------------------------+ //| Обновляет все данные символа | //+------------------------------------------------------------------+ void CSymbol::Refresh(void) { //--- Обновление котировочных данных if(!this.RefreshRates()) return; #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); return; } #endif //--- Инициализация событийных данных this.m_is_event=false; this.m_hash_sum=0; //--- Обновление целочисленных свойств this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); //--- Обновление вещественных свойств this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- Заполнение текущих данных символа for(int i=0;i<SYMBOL_PROP_INTEGER_TOTAL;i++) this.m_long_prop_event[i][3]=this.m_long_prop[i]; for(int i=0;i<SYMBOL_PROP_DOUBLE_TOTAL;i++) this.m_double_prop_event[i][3]=this.m_double_prop[i]; CBaseObj::Refresh(); this.CheckEvents(); } //+------------------------------------------------------------------+
Здесь: Так как мы избавились от необходимости создания структур для хранения текущего и прошлого состояний свойств символа, то здесь было
удалено заполнение структуры данных текущего состояния символа, а вместо этого мы организовали
заполнение массивов целочисленных и вещественных
свойств в базовом объекте.
Затем, когда массивы заполнены, нам необходимо вызвать
метод Refresh()
базового объекта CBaseObj, в котором проводится поиск
произошедших изменений и создаётся список базовых событий объекта-наследника.
После того, как список базовых событий в родительском классе создан (при наличии критериев для генерации событий), мы проверяем
базовые события методом CheckEvents(), и при их наличии — создаём список событий символа.
Реализация метода проверки событий:
//+------------------------------------------------------------------+ //| Проверяет список изменений свойств символа и создаёт событие | //+------------------------------------------------------------------+ void CSymbol::CheckEvents(void) { int total=this.m_list_events_base.Total(); if(total==0) return; for(int i=0;i<total;i++) { CBaseEvent *event=this.GetEventBase(i); if(event==NULL) continue; long lvalue=0; this.UshortToLong(this.MSCfromTime(this.TickTime()),0,lvalue); this.UshortToLong(event.Reason(),1,lvalue); this.UshortToLong(COLLECTION_SYMBOLS_ID,2,lvalue); if(this.EventAdd((ushort)event.ID(),lvalue,event.Value(),this.Name())) this.m_is_event=true; } } //+------------------------------------------------------------------+
Здесь: Если список базовых событий пуст —
выходим.
В цикле по списку базовых событий получаем
очередное событие, и если событие получено — то создаём событие символа:
- получаем только милисекунды из текущего времени в милисекундах и добавляем их в первые два байта long-параметра события
- получаем причину события (увеличение/уменшение/больше/меньше уровня) и добавляем её во вторые два байта long-параметра события
- идентификатор коллекции символов добавляем в третьи два байта long-параметра события
- добавляем событие символа в список событий символа и ставим флаг наличия события на символе
Метод инициализации переменных контролируемых данных символа:
//+------------------------------------------------------------------+ //| Инициализирует переменные контролируемых данных символа | //+------------------------------------------------------------------+ void CSymbol::InitControlsParams(void) { this.ResetControlsParams(); } //+------------------------------------------------------------------+
Просто вызывает метод сброса переменных контролируемых значений данных объекта, рассмотренный нами выше.
Методы установки контролируемых величин и флагов произошедших изменений и методы получения размера произошедших изменений и
флагов:
//+------------------------------------------------------------------+ //| Устанавливает величину контролируемого приращения свойства | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlPropertyINC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledValueINC(property,(long)value); else this.SetControlledValueINC(property,(double)value); } //+------------------------------------------------------------------+ //| Устанавливает величину контролируемого уменьшения свойства | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlPropertyDEC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledValueDEC(property,(long)value); else this.SetControlledValueDEC(property,(double)value); } //+------------------------------------------------------------------+ //| Устанавливает величину контрольного уровня свойства | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlPropertyLEVEL(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledValueLEVEL(property,(long)value); else this.SetControlledValueLEVEL(property,(double)value); } //+------------------------------------------------------------------+ //| Устанавливает Флаг изменения значения свойства символа больше, | //| чем на величину прироста | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlFlagINC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledFlagINC(property,(long)value); else this.SetControlledFlagINC(property,(double)value); } //+------------------------------------------------------------------+ //| Устанавливает Флаг изменения значения свойства символа больше, | //| чем на величину уменьшения | //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlFlagDEC(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledFlagDEC(property,(long)value); else this.SetControlledFlagDEC(property,(double)value); } //+------------------------------------------------------------------+ //| Устанавливает величину изменения контролируемого свойства символа| //+------------------------------------------------------------------+ template<typename T> void CSymbol::SetControlChangedValue(const int property,const T value) { if(property<SYMBOL_PROP_INTEGER_TOTAL) this.SetControlledChangedValue(property,(long)value); else this.SetControlledChangedValue(property,(double)value); } //+------------------------------------------------------------------+ //| Устанавливает контролируемую величину прироста цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //|Устанавливает контролируемую величину уменьшения цены Bid или Last| //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //| Устанавливает контрольный уровень цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLevel(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //| Возвращает величину изменения цены Bid или Last | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BID) : this.GetControlChangedValue(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Возвращает флаг изменения цены Bid или Last больше, | //| чем на величину прироста | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BID) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Возвращает флаг изменения цены Bid или Last больше, | //| чем на величину уменьшения | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BID) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Устанавливает контролируемую величину прироста | //| максимальной цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Устанавливает контролируемую величину уменьшения | //| максимальной цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Устанавливает контрольный уровень максимальной цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighLevel(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Возвращает величину изменения максимальной цены Bid или Last | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BIDHIGH) : this.GetControlChangedValue(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Возвращает флаг изменения максимальной цены | //| Bid или Last больше, чем на величину прироста | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDHIGH) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Возвращает флаг изменения максимальной цены | //| Bid или Last больше, чем на величину уменьшения | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDHIGH) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Устанавливает контролируемую величину прироста | //| минимальной цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Устанавливает контролируемую величину уменьшения | //| минимальной цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Устанавливает контрольный уровень минимальной цены Bid или Last | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowLevev(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Возвращает величину изменения минимальной цены Bid или Last | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BIDLOW) : this.GetControlChangedValue(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+ //| Возвращает флаг изменения минимальной цены | //| Bid или Last больше, чем на величину прироста | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDLOW) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+ //| Возвращает флаг изменения минимальной цены | //| Bid или Last больше, чем на величину уменьшения | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDLOW) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+
Похожие методы рассматривались нами при доработке класса базового объекта, и здесь вызываются как раз рассмотренные нами эти методы в зависимости от требуемого свойства объекта-символа.
На этом доработка класса объекта-символа завершена.
Теперь осталось немного доработать класс коллекции символов.
Откроем файл \MQL5\Include\DoEasy\Collections\SymbolsCollection.mqh
и внесём необходимые изменения.
Так как мы избавились от необходимости создавать для каждого объекта свои перечисления его событий, то
переменной "последнее
событие символа" и методу GetLastEvent() вместо
бывшего ранее типа ENUM_SYMBOL_EVENT задатим типы int:
int m_last_event; // Последнее событие
int GetLastEvent(void) const { return this.m_last_event; }
Так как теперь все события символа (да и любого иного объекта-наследника) обрабатываются в классе базового объекта, то
метод
EventDescription()
переименуем в EventMWDescription(), и передавать в метод будем
переменную с
типом перечисления событий окна "Обзор рынка":
//--- Возвращает описание (1) события окна "Обзор рынка", (2) режима работы с символами string EventMWDescription(const ENUM_MW_EVENT event); string ModeSymbolsListDescription(void);
В связи с тем, что наименование перечислений у нас поменялись, то
метод работы с окном "Обзор рынка" претерпел
небольшие изменения (
изменены наименования перечислений и тип
переменной-события):
//+------------------------------------------------------------------+ //| Работа с событиями окна обзора рынка | //+------------------------------------------------------------------+ void CSymbolsCollection::MarketWatchEventsControl(const bool send_events=true) { ::ResetLastError(); //--- Если текущие цены не получены - уходим if(!::SymbolInfoTick(::Symbol(),this.m_tick)) { this.m_global_error=::GetLastError(); return; } uchar array[]; int sum=0; this.m_hash_sum=0; //--- Расчёт хэш-суммы всех видимых символов в окне "Обзор рынка" this.m_total_symbols=this.SymbolsTotalVisible(); //--- В цикле по всем символам окна "Обзор рынка" int total_symbols=::SymbolsTotal(true); for(int i=0;i<total_symbols;i++) { //--- получаем имя символа по индексу string name=::SymbolName(i,true); //--- если невидимый - пропускаем if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- записываем в uchar-массив коды символов (букв) названия символа ::StringToCharArray(name,array); //--- в цикле по получившемуся массиву складываем значения всех ячеек массива, тем самым создавая код символа for(int j=::ArraySize(array)-1;j>WRONG_VALUE;j--) sum+=array[j]; //--- добавляем к хэш-сумме код символа и индекс цикла, указывающий на индекс символа в списке обзора рынка m_hash_sum+=i+sum; } //--- Если запрет отправки событий - создаём список-коллекцию и выходим с сохранением текущей хэш-суммы как прошлой if(!send_events) { //--- Очищаем список this.m_list_all_symbols.Clear(); //--- Создаём список-коллекцию this.CreateSymbolsList(true); //--- Создаём слепок окна обзора рынка this.CopySymbolsNames(); //--- сохраняем текущую хэш-сумму как прошлую this.m_hash_sum_prev=this.m_hash_sum; //--- сохраняем текущее количество видимых символов как прошлое this.m_total_symbol_prev=this.m_total_symbols; return; } //--- Если хэш-сумма символов в окне "Обзор рынка" изменилась if(this.m_hash_sum!=this.m_hash_sum_prev) { //--- Определяем событие окна "Обзор рынка" this.m_delta_symbol=this.m_total_symbols-this.m_total_symbol_prev; ushort event_id= (ushort( this.m_total_symbols>this.m_total_symbol_prev ? MARKET_WATCH_EVENT_SYMBOL_ADD : this.m_total_symbols<this.m_total_symbol_prev ? MARKET_WATCH_EVENT_SYMBOL_DEL : MARKET_WATCH_EVENT_SYMBOL_SORT) ); //--- Добавление символа в окно "Обзор рынка" if(event_id==MARKET_WATCH_EVENT_SYMBOL_ADD) { string name=""; //--- В цикле по всем символам окна "Обзор рынка" int total=::SymbolsTotal(true), index=WRONG_VALUE; for(int i=0;i<total;i++) { //--- получаем имя символа и проверяем его "видимость", если невидимый - пропускаем name=::SymbolName(i,true); if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- Если символа ещё нет в списке символов коллекции if(!this.IsPresentSymbolInList(name)) { //--- очищаем список-коллекцию this.m_list_all_symbols.Clear(); //--- пересоздаём список-коллекцию this.CreateSymbolsList(true); //--- создаём слепок коллекции символов this.CopySymbolsNames(); //--- получаем индекс нового символа в окне "Обзор рынка" index=this.GetSymbolIndexByName(name); //--- Если событие "Добавление нового символа" успешно добавлено в список событий if(this.EventAdd(event_id,this.TickTime(),index,name)) { //--- отправляем событие на график: //--- long-значение = время события в милисекундах, double-значение = индекс символа, string-значение = имя добавленного символа ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,name); } } } //--- Сохраняем новое количество видимых символов в окне обзора рынка this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Удаление символа из окна "Обзор рынка" else if(event_id==MARKET_WATCH_EVENT_SYMBOL_DEL) { //--- очищаем список-коллекцию this.m_list_all_symbols.Clear(); //--- пересоздаём список-коллекцию this.CreateSymbolsList(true); //--- В цикле по слепку окна обзора рынка int total=this.m_list_names.Total(); for(int i=0; i<total;i++) { //--- получаем имя символа string name=this.m_list_names.At(i); if(name==NULL) continue; //--- если симвоа с таким именем не существует в списке символов коллекции if(!this.IsPresentSymbolInList(name)) { //--- Если событие "Удаление символа" успешно добавлено в список событий if(this.EventAdd(event_id,this.TickTime(),WRONG_VALUE,name)) { //--- отправляем событие на график: //--- long-значение = время события в милисекундах, double-значение = -1 для отсутствующего символа, string-значение = имя удалённого символа ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),WRONG_VALUE,name); } } } //--- Пересоздаём слепок обзора рынка this.CopySymbolsNames(); //--- Сохраняем новое количество видимых символов в окне обзора рынка this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Сортировка символов в окне "Обзор рынка" else if(event_id==MARKET_WATCH_EVENT_SYMBOL_SORT) { //--- очищаем список-коллекцию this.m_list_all_symbols.Clear(); //--- устанавливаем сортировку списка коллекции как сортировку по индексу this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_INDEX_MW); //--- пересоздаём список-коллекцию this.CreateSymbolsList(true); //--- получаем индекс текущего символа в окне "Обзор рынка" int index=this.GetSymbolIndexByName(Symbol()); //--- отправляем событие на график: //--- long-значение = время события в милисекундах, double-значение = индекс текущего символа, string-значение = имя текущего символа ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,::Symbol()); } //--- сохраняем текущее количество видимых символов как прошлое this.m_total_symbol_prev=this.m_total_symbols; //--- сохраняем текущую хэш-сумму как прошлую this.m_hash_sum_prev=this.m_hash_sum; } } //+------------------------------------------------------------------+
И точно так же изменён тип переменной-события в
методе работы со списком событий коллекции символов:
//+------------------------------------------------------------------+ //| Работа с событиями списка символов коллекции | //+------------------------------------------------------------------+ void CSymbolsCollection::SymbolsEventsControl(void) { this.m_is_event=false; this.m_list_events.Clear(); this.m_list_events.Sort(); //--- Полное обновление всех символов коллекции int total=this.m_list_all_symbols.Total(); for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.Refresh(); if(!symbol.IsEvent()) continue; this.m_is_event=true; CArrayObj *list=symbol.GetListEvents(); if(list==NULL) continue; this.m_event_code=symbol.GetEventCode(); int n=list.Total(); for(int j=0; j<n; j++) { CEventBaseObj *event=list.At(j); if(event==NULL) continue; ushort event_id=event.ID(); this.m_last_event=event_id; if(this.EventAdd((ushort)event.ID(),event.LParam(),event.DParam(),event.SParam())) { ::EventChartCustom(this.m_chart_id,(ushort)event_id,event.LParam(),event.DParam(),event.SParam()); } } } } //+------------------------------------------------------------------+
В методе, возвращающем строковое описание события окна обзора рынка, так же заменены
наименования констант перечисления собитий:
//+------------------------------------------------------------------+ //| Возвращает описание события окна "Обзор рынка" | //+------------------------------------------------------------------+ string CSymbolsCollection::EventMWDescription(const ENUM_MW_EVENT event) { return ( event==MARKET_WATCH_EVENT_SYMBOL_ADD ? TextByLanguage("В окно \"Обзор рынка\" добавлен символ","Added a symbol to the \"Market Watch\" window") : event==MARKET_WATCH_EVENT_SYMBOL_DEL ? TextByLanguage("Из окна \"Обзор рынка\" удалён символ","From the \"Market Watch\" window was removed") : event==MARKET_WATCH_EVENT_SYMBOL_SORT ? TextByLanguage("Изменено расположение символов в окне \"Обзор рынка\"","Changed the arrangement of symbols in the \"Market Watch\" window") : EnumToString(event) ); } //+------------------------------------------------------------------+
Теперь доработаем класс CEngine. Откроем файл\MQL5\Include\DoEasy\Engine.mqh и внесём в него изменения:
Переменная, хранящая последнее событие в свойствах символа и метод, возвращающий значение этой переменной тоже будут иметь тип int:
int m_last_symbol_event; // Последнее событие в свойствах символа
int LastSymbolsEvent(void) const { return this.m_last_symbol_event; }
В публичную секцию класса впишем объявление метода, извлекающего ushort-число из long-контейнера по указанному индексу хранения в long-параметре ushort-числа:
//--- Извлекает нужное ushort-число из упакованного long-значения ushort LongToUshortFromByte(const long source_value,const uchar index) const;
И там же напишем три метода, сразу же возвращающих значения милисекунд, причину и источник события из long-параметра события:
//--- Возвращает (1) милисекунды, (2) причину, (3) источник события из его long-значения ushort EventMSC(const long lparam) const { return this.LongToUshortFromByte(lparam,0); } ushort EventReason(const long lparam) const { return this.LongToUshortFromByte(lparam,1); } ushort EventSource(const long lparam) const { return this.LongToUshortFromByte(lparam,2); }
Так как нулевое значение является самым первым целочисленным свойством любого объекта, то в конструкторе класса, в его списке
инициализации
изменим инициализирующее значение для переменной, хранящей последнее
событие символа — теперь инициализироваться она будет
отрицательным значением:
//+------------------------------------------------------------------+ //| CEngine конструктор | //+------------------------------------------------------------------+ CEngine::CEngine() : m_first_start(true), m_last_trade_event(TRADE_EVENT_NO_EVENT), m_last_account_event(ACCOUNT_EVENT_NO_EVENT), m_last_symbol_event(WRONG_VALUE), m_global_error(ERR_SUCCESS) {
Реализация метода, извлекающий ushort-число из long-контейнера по индексу байтов его расположения в составе long-контейнера:
//+------------------------------------------------------------------+ //| Извлекает нужное ushort-число из упакованного long-значения | //+------------------------------------------------------------------+ ushort CEngine::LongToUshortFromByte(const long source_value,const uchar index) const { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. The \"index\" value must be between 0 - 3")); return 0; } long res=source_value>>(16*index); return ushort(res &=0xFFFF); } //+------------------------------------------------------------------+
В метод передаётся long-значение, из которого необходимо извлечь ushort-число
и индекс байт, в которых число располагается (таблицу
расположения ushort-чисел в long-контейнере рассматривали выше), затем
проверяется корректность указания индекса и выводится
сообщение об ошибке если индекс не корректен, и
возвращается 0.
Далее смещаем
биты long-числа на 16 * index бит вправо, накладываем маску для "погашения"
оставшихся старших бит и возвращаем извлечённое таким образом
ushort-число.
Для работы в MQL4, нам необходимо указать компилятору об ошибке нулевого размера массива ERR_ZEROSIZE_ARRAY,
о которой он не знает.
Наиболее подходящая для нулевого размера массива ошибка из известных MQL4-компилятору — это "неверный массив". Её и зададим в
качестве альтернативы ошибке нулевого размера массива.
Откроем файл \MQL5\Include\DoEasy\ToMQL4.mqh и впишем неизвестный для компилятора MQL4 код ошибки:
//+------------------------------------------------------------------+ //| ToMQL4.mqh | //| Copyright 2017, Artem A. Trishkin, Skype artmedia70 | //| https://www.mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70" #property link "https://www.mql5.com/ru/users/artmedia70" #property strict #ifdef __MQL4__ //+------------------------------------------------------------------+ //| Коды ошибок | //+------------------------------------------------------------------+ #define ERR_SUCCESS (ERR_NO_ERROR) #define ERR_MARKET_UNKNOWN_SYMBOL (ERR_UNKNOWN_SYMBOL) #define ERR_ZEROSIZE_ARRAY (ERR_ARRAY_INVALID) //+------------------------------------------------------------------+
Это все изменения, которые нам необходимо было сделать, чтобы запустить символы в работу с новым событийным функционалом, предоставляемым объектом CBaseObj всем своим наследникам.
Тест событийного функционала базового объекта всех объектов библиотеки
Для тестирования нового событийного функционала базового объекта возьмём советник из прошлой статьи и сохраним его под новым именем TestDoEasyPart17.mq5 в папке \MQL5\Experts\TestDoEasy\Part17.
Будем тестировать изменение спреда текущего символа на 4 пункта (увеличение и уменьшение), а также контролировать размер спреда на 15 пунктов. Для цены Bid будем контролировать увеличение/уменьшение её значения на +/- 10 пунктов, и отследим пересечение ценой уровня 1.13700.
Для установки вышеназванных контролируемых значений достаточно в данном примере прописать в обработчике OnInit() такие строки:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Вызов данной функции выводит в журнал список констант перечисления, //--- заданного в файле DELib.mqh в строках 22 и 25, для проверки корректности констант //EnumNumbersTest(); //--- Установка глобальных переменных советника prefix=MQLInfoString(MQL_PROGRAM_NAME)+"_"; for(int i=0;i<TOTAL_BUTT;i++) { butt_data[i].name=prefix+EnumToString((ENUM_BUTTONS)i); butt_data[i].text=EnumToButtText((ENUM_BUTTONS)i); } lot=NormalizeLot(Symbol(),fmax(InpLots,MinimumLots(Symbol())*2.0)); magic_number=InpMagic; stoploss=InpStopLoss; takeprofit=InpTakeProfit; distance_pending=InpDistance; distance_stoplimit=InpDistanceSL; slippage=InpSlippage; trailing_stop=InpTrailingStop*Point(); trailing_step=InpTrailingStep*Point(); trailing_start=InpTrailingStart; stoploss_to_modify=InpStopLossModify; takeprofit_to_modify=InpTakeProfitModify; //--- Проверка на выбор работы с полным списком used_symbols_mode=InpModeUsedSymbols; if((ENUM_SYMBOLS_MODE)used_symbols_mode==SYMBOLS_MODE_ALL) { int total=SymbolsTotal(false); string ru_n="\nКоличество символов на сервере "+(string)total+".\nМаксимальное количество: "+(string)SYMBOLS_COMMON_TOTAL+" символов."; string en_n="\nThe number of symbols on server "+(string)total+".\nMaximal number: "+(string)SYMBOLS_COMMON_TOTAL+" symbols."; string caption=TextByLanguage("Внимание!","Attention!"); string ru="Выбран режим работы с полным списком.\nВ этом режиме первичная подготовка списка коллекции символов может занять длительное время."+ru_n+"\nПродолжить?\n\"Нет\" - работа с текущим символом \""+Symbol()+"\""; string en="Full list mode selected.\nIn this mode, the initial preparation of the collection symbols list may take a long time."+en_n+"\nContinue?\n\"No\" - working with the current symbol \""+Symbol()+"\""; string message=TextByLanguage(ru,en); int flags=(MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2); int mb_res=MessageBox(message,caption,flags); switch(mb_res) { case IDNO : used_symbols_mode=SYMBOLS_MODE_CURRENT; break; default: break; } } //--- Заполнение массива используемых символов used_symbols=InpUsedSymbols; CreateUsedSymbolsArray((ENUM_SYMBOLS_MODE)used_symbols_mode,used_symbols,array_used_symbols); //--- Установка типа используемого списка символов в коллекции символов engine.SetUsedSymbols(array_used_symbols); //--- Отображение выбранного режима работы с коллекцией объектов-символов Print(engine.ModeSymbolsListDescription(),TextByLanguage(". Количество используемых символов: ",". The number of symbols used: "),engine.GetSymbolsCollectionTotal()); //--- Установка контрольных значений для текущего символа CSymbol* symbol=engine.GetSymbolCurrent(); if(symbol!=NULL) { //--- Установка контроля увеличения цены текущего символа на 10 пунктов symbol.SetControlBidInc(10*Point()); //--- Установка контроля уменьшения цены текущего символа на 10 пунктов symbol.SetControlBidDec(10*Point()); //--- Установка контроля увеличения спреда текущего символа на 4 пункт symbol.SetControlSpreadInc(4); //--- Установка контроля уменьшения спреда текущего символа на 4 пункта symbol.SetControlSpreadDec(4); //--- Установка контроля размера спреда по значению 15 пунктов symbol.SetControlSpreadLevel(15); //--- Установка контроля пересечения ценой значения 1.13700 symbol.SetControlBidLevel(1.13700); } //--- Проверка и удаление неудалённых графических объектов советника if(IsPresentObects(prefix)) ObjectsDeleteAll(0,prefix); //--- Создание панели кнопок if(!CreateButtons(InpButtShiftX,InpButtShiftY)) return INIT_FAILED; //--- Установка состояния кнопки активизации трейлингов ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on); //--- Установка параметров торгового класса CTrade #ifdef __MQL5__ trade.SetDeviationInPoints(slippage); trade.SetExpertMagicNumber(magic_number); trade.SetTypeFillingBySymbol(Symbol()); trade.SetMarginMode(); trade.LogLevel(LOG_LEVEL_NO); #endif //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Пример задания отслеживаемых параметров символа здесь тестовый, поэтому мы сразу задали требуемые контрольные значения в OnInit().
Но ничто не мешает оперативно менять отслеживаемые значения символа исходя из неких текущих критериев во время процесса работы — все
методы есть в базовом объекте, и достаточно получить доступ к любому из объектов, унаследованных от CBaseObj, чтобы получить в
распоряжение методы установки контролируемых параметров и методы получения изменённых параметров, и далее изменять
контролируемые параметры по заложенной в программу логике — программно или из графической оболочки библиотеки, которая
впоследствии также будет создана.
Из обработчика OnTick() советника удалим переменную, хранящую последнее
событие символа — для отслеживания событий символов у нас имеются иные инструменты, нежели простое сравнение текущего и
прошлого состояния.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Инициализация последних событий static ENUM_TRADE_EVENT last_trade_event=WRONG_VALUE; static ENUM_ACCOUNT_EVENT last_account_event=WRONG_VALUE; static ENUM_SYMBOL_EVENT last_symbol_event=WRONG_VALUE; //--- Если работа в тестере if(MQLInfoInteger(MQL_TESTER)) {
Изменим обработчик событий библиотеки в части обработки событий коллекции символов:
//+------------------------------------------------------------------+ //| Обработка событий библиотеки DoEasy | //+------------------------------------------------------------------+ void OnDoEasyEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { int idx=id-CHARTEVENT_CUSTOM; string event="::"+string(idx); //--- Извлекаем из lparam (1) милисекунды времени события, (2) причину, (3) источник события и (4) устанавливаем точное время события ushort msc=engine.EventMSC(lparam); ushort reason=engine.EventReason(lparam); ushort source=engine.EventSource(lparam); long time=TimeCurrent()*1000+msc; //--- Обработка событий окна обзор рынка if(idx>MARKET_WATCH_EVENT_NO_EVENT && idx<SYMBOL_EVENTS_NEXT_CODE) { string name=""; //--- Событие окна "Обзор рынка" string descr=engine.GetMWEventDescription((ENUM_MW_EVENT)idx); name=(idx==MARKET_WATCH_EVENT_SYMBOL_SORT ? "" : ": "+sparam); Print(TimeMSCtoString(lparam)," ",descr,name); } //--- Обработка событий символов if(source==COLLECTION_SYMBOLS_ID) { CSymbol *symbol=engine.GetSymbolObjByName(sparam); if(symbol==NULL) return; //--- Количество знаков после запятой в значении события - если long-событие, то 0, иначе - Digits() символа int digits=(idx<SYMBOL_PROP_INTEGER_TOTAL ? 0 : symbol.Digits()); //--- Текстовое описание события string id_descr=(idx<SYMBOL_PROP_INTEGER_TOTAL ? symbol.GetPropertyDescription((ENUM_SYMBOL_PROP_INTEGER)idx) : symbol.GetPropertyDescription((ENUM_SYMBOL_PROP_DOUBLE)idx)); //--- Текстовое значение величины изменения свойства string value=DoubleToString(dparam,digits); //--- Проверка причин события и просто вывод в журнал его описания if(reason==BASE_EVENT_REASON_INC) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_DEC) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_MORE_THEN) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_LESS_THEN) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } if(reason==BASE_EVENT_REASON_EQUALS) { Print(symbol.EventDescription(idx,(ENUM_BASE_EVENT_REASON)reason,source,value,id_descr,digits)); } } //--- Обработка торговых событий if(idx>TRADE_EVENT_NO_EVENT && idx<TRADE_EVENTS_NEXT_CODE) { event=EnumToString((ENUM_TRADE_EVENT)ushort(idx)); int digits=(int)SymbolInfoInteger(sparam,SYMBOL_DIGITS); } //--- Обработка событий аккаунта else if(idx>ACCOUNT_EVENT_NO_EVENT && idx<ACCOUNT_EVENTS_NEXT_CODE) { Print(TimeMSCtoString(lparam)," ",sparam,": ",engine.GetAccountEventDescription((ENUM_ACCOUNT_EVENT)idx)); //--- если это увеличение средств if((ENUM_ACCOUNT_EVENT)idx==ACCOUNT_EVENT_EQUITY_INC) { //--- Закроем позицию с самой большой прибылью больше нуля при увеличении средств больше, //--- чем задано в методе CAccountsCollection::InitControlsParams() для //--- переменной m_control_equity_inc, контролирующей прирост средств на 15 единиц (по умолчанию) //--- Файл AccountCollection, метод InitControlsParams(), строка 1199 //--- Получаем список всех открытых позиций CArrayObj* list_positions=engine.GetListMarketPosition(); //--- Выбираем позиции с прибылью болше нуля list_positions=CSelect::ByOrderProperty(list_positions,ORDER_PROP_PROFIT_FULL,0,MORE); if(list_positions!=NULL) { //--- Сортируем список по прибыли с учётом комиссии и свопа list_positions.Sort(SORT_BY_ORDER_PROFIT_FULL); //--- Получаем индекс позиции с наибольшей прибылью int index=CSelect::FindOrderMax(list_positions,ORDER_PROP_PROFIT_FULL); if(index>WRONG_VALUE) { COrder* position=list_positions.At(index); if(position!=NULL) { //--- Получаем тикет позиции с наибольшей прибылью и закрываем позицию по тикету #ifdef __MQL5__ trade.PositionClose(position.Ticket()); #else PositionClose(position.Ticket(),position.Volume()); #endif } } } } } } //+------------------------------------------------------------------+
Все изменения прокомментированы в коде и сводятся лишь к получению описания события из объекта-символа и выводу его в журнал в зависимости от причины события. В нетестовом обработчике вместо вывода сообщения в журнал необходимо написать нормальный обработчик события.
Скомпилируем и запустим советник в тестере:
Как видно, при уменьшении или увеличении размера спреда больше заданных контрольных значений в журнал выводятся записи об этом. Точно также об изменениях цены Bid — увеличении или уменьшении её значения больше 10 пунктов— выводятся записи в журнал. И наконец — при пересечении ценой Bid заданного контрольного уровня — тоже отсылается событие, и о нём выводится запись в журнал.
Таким образом, мы создали базовый объект, позволяющий отслеживать события любого своего объекта-наследника и посылать эти события в
управляющую программу, где их можно отслеживать и реагировать на них согласно заложенной в программу логики, а также задавать новые
отслеживаемые значения и уровни, что позволит гибко управлять логикой работы программы.
Что дальше
В следующей статье сделаем работу объекта-аккаунта и его событий на основе событийного функционала класса базового объекта CBaseObj.
Ниже прикреплены все файлы текущей версии библиотеки и файлы тестового советника. Их можно скачать и протестировать всё
самостоятельно.
При возникновении вопросов, замечаний и пожеланий, вы можете озвучить их в комментариях к статье.
Статьи этой серии:
Часть 1. Концепция, организация данных
Часть
2. Коллекция исторических ордеров и сделок
Часть 3. Коллекция рыночных ордеров и
позиций, организация поиска
Часть 4. Торговые события. Концепция
Часть 5. Классы и коллекция торговых событий. Отправка событий в программу
Часть 6. События на счёте с типом неттинг
Часть
7. События срабатывания StopLimit-ордеров, подготовка функционала для регистрации событий модификации ордеров и позиций
Часть
8. События модификации ордеров и позиций
Часть 9. Совместимость с MQL4 -
Подготовка данных
Часть 10. Совместимость с MQL4 - События открытия позиций и
активации отложенных ордеров
Часть 11. Совместимость с MQL4 - События закрытия
позиций
Часть 12. Класс объекта "аккаунт", коллекция объектов-аккаунтов
Часть 13. События объекта "аккаунт"
Часть
14. Объект "Символ"
Часть 15. Коллекция объектов-символов
Часть
16. События коллекции символов
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Классическая ошибка авторов статей, - считать, что если им материал понятен, то он понятен всем.) Но, это не так.
...А классическая ошибка некоторых читателей - что они не читают, но сразу задают вопросы :)
Если начать читать с первой статьи, то таких вопросов точно не будет, ведь вся "философия" - там, и она разъяснена.
Артем, спасибо!
Не надо, не останавливайся, пиши - получается классно.
С интересом прочитал вашу дискуссию с Петром. Очень корректно и по делу.
Написал письмо в компанию "AMD",- Я хоть и не занимаюсь проектированием и выпуском процессоров, но, ребята, ерунду вы спороли в 8-нм техпроцессе...
Жду ответа
Вы ушли в слишком глубокую философию в вашей разработке, забыв о практической целесообразности построения подобной "идеальной схемы". ...
Философия здесь вот в чём: индукция (от частного к общему) или дедукция (от общего к частному).
Артём использует индуктивный метод подачи материала.
Шеф: Нус, Глеб Георгиевич, имеется пуля. Ваши суждения...
Жеглов: Ну, что скажешь, "разведка"?
Шарапов: Ну что, пуля как пуля, обыкновенная, пистолетная...
Жеглов: Да, хорошо бы еще гильзу найти.
Шеф: Лучше уж посмотреть само оружие.
Жеглов: Верно. ну значится так: пуля выпущенная из импортного оружия калибра 6.35 системы "Баярд" или, скажем, "Омега".
Шеф: А сие из чего следует?
Жеглов: Из пули, Сергей Ипатич, из пули. Шесть левых верликальных нарезов, вот они - почерк вполне "самостоятельный".
Шеф: А что вы скажете на это? Судя по маркировке - гильза наша, отечественная.
Жеглов: Да. А где нашли?
Шеф: Там где и следует. Слева от тела. Нормально сработал отражатель.
Жеглов: Да, гильза наша. Хм. Ну что же, запишем в загадки. И всё равно надо искать оружие. Надя, вы не знаете, в доме было оружие?
Надежда: Не знаю.
[Вайнеры. Эра милосердия]
Артем, спасибо!
Не надо, не останавливайся, пиши - получается классно.
С интересом прочитал вашу дискуссию с Петром. Очень корректно и по делу.
Написал письмо в компанию "AMD",- Я хоть и не занимаюсь проектированием и выпуском процессоров, но, ребята, ерунду вы спороли в 8-нм техпроцессе...
Жду ответа
Привет, Алексей.
Зачем останавливаться в начале пути? Уже все остановки на раздумье были - теперь только вперёд по кочкам ;)
Ну и как, ответили тебе из AMD ?
Философия здесь вот в чём: индукция (от частного к общему) или дедукция (от общего к частному).
Артём использует индуктивный метод подачи материала.
Шеф: Нус, Глеб Георгиевич, имеется пуля. Ваши суждения...
Жеглов: Ну, что скажешь, "разведка"?
Шарапов: Ну что, пуля как пуля, обыкновенная, пистолетная...
Жеглов: Да, хорошо бы еще гильзу найти.
Шеф: Лучше уж посмотреть само оружие.
Жеглов: Верно. ну значится так: пуля выпущенная из импортного оружия калибра 6.35 системы "Баярд" или, скажем, "Омега".
Шеф: А сие из чего следует?
Жеглов: Из пули, Сергей Ипатич, из пули. Шесть левых верликальных нарезов, вот они - почерк вполне "самостоятельный".
Шеф: А что вы скажете на это? Судя по маркировке - гильза наша, отечественная.
Жеглов: Да. А где нашли?
Шеф: Там где и следует. Слева от тела. Нормально сработал отражатель.
Жеглов: Да, гильза наша. Хм. Ну что же, запишем в загадки. И всё равно надо искать оружие. Надя, вы не знаете, в доме было оружие?
Надежда: Не знаю.
[Вайнеры. Эра милосердия]
О как... Не знал, что так вот...
А Вайнеров ещё в детстве прочёл.