Biblioteca para criação simples e rápida de programas para MetaTrader (Parte XVII): interatividade de objetos de biblioteca
Sumário
- Métodos para controlar eventos do objeto base da biblioteca
- Renovando a classe de símbolos e a coleção de símbolos
- Teste da funcionalidade do evento do objeto base de todos os objetos da biblioteca
- O que vem agora?
No último artigo, criamos o objeto base de todos os objetos da biblioteca, por
isso, agora qualquer objeto herdado do objeto base recebe a funcionalidade de evento, assim, é possível rastrear facilmente os eventos que
ocorrem nas propriedades da classe-herdeiro do objeto base.
Hoje, vamos um pouco mais longe e forneceremos esse objeto e, portanto, qualquer outro objeto de biblioteca, definindo exatamente as
propriedades cujas alterações serão controladas externamente, o tamanho da alteração controlada e o nível controlado da propriedade do
objeto. Assim, a todos os objetos da biblioteca será adicionada uma funcionalidade que permitirá ao usuário interagir com os objetos da
biblioteca.
Por exemplo, para abrir uma posição, gostaríamos de levar em consideração o tamanho do spread e o nível do preço. Podemos facilmente
estabelecer o tamanho de spread controlado e rastrear o cruzamento do preço num determinado nível e, em seguida, abrir uma posição. Basta
definir programaticamente o tamanho do spread, abaixo do qual é possível a negociação, bem como o nível de preço, em cuja interseção nosso
programa receberá o evento do objeto-símbolo sobre um sinal indicando o tamanho do spread e o preço que cruza o nível controlado para
negociação.
No entanto, é importante nos livrarmos da necessidade de usar sinalizadores de eventos (o que impõe um limite no número de eventos que podem
ser rastreados e requer o armazenamento de listas-enumerações de todos os tipos possíveis de eventos para cada objeto). Agora, o número de
eventos possíveis corresponderá ao número de propriedades do objeto — inteiras e reais. As propriedades que não precisam ser controladas
serão inicializadas com o valor
LONG_MAX, e, consequentemente, não devem ser
envolvidas na pesquisa de eventos do objeto.
Como os objetos da biblioteca são armazenados em suas coleções, atualizamos as propriedades dos objetos na coleção no temporizador da
biblioteca usando os métodos Refresh() das coleções, onde, por sua vez, são chamados os métodos Refresh() dos objetos armazenados na
lista-coleções. Portanto, se rastrearmos as alterações nos valores definidos para as propriedades do objeto-herdeiro no objeto base, no
seu método Refresh(), assim podemos criar um modelo de evento simples para cada um dos objetos da biblioteca. Cada um dos objetos enviará sua
lista de eventos para o objeto principal da biblioteca
CEngine.
Dessa maneria, programas criados com base na biblioteca
sempre saberá sobre todos os eventos ocorridos em qualquer um dos objetos de qualquer coleção. Sempre, para cada objeto de qualquer
coleção, podemos programaticamente definir e alterar o tamanho do valor controlado de qualquer propriedade.
Tudo isso com a ajuda de uma classe simples do objeto base de todos os objetos de
biblioteca.
Métodos para controlar eventos do objeto base da biblioteca
Trabalharemos com o evento de objeto base de biblioteca, assim: anteriormente, para definir os eventos de uma classe concreta, criamos seus próprios
métodos de controle de evento, bem como sinalizadores de eventos e enumerações de possíveis eventos de objeto. Agora que o controle de
eventos das classes-herdeiros será feito em sua única classe base, precisamos criar um controle universal de eventos, por exemplo, para
evento de símbolo ou evento de conta, ou eventos de qualquer outra classe que será criada no futuro. Por essa razão, neste caso, é apropriado o
controle de alterações no estado das propriedades do objeto: reais e inteiros — cada classe-herdeiro tem uma lista única que será em si um
identificador de evento. Também precisaremos considerar a direção da mudança nas propriedades (aumento/diminuição do valor da
propriedade), vamos chamá-la de
causa do evento, e o valor da alteração na propriedade do objeto. Registraremos o identificador, a causa e a
magnitude da alteração do evento numa classe simples do evento base do objeto e armazenaremos numa lista eventos que ocorrem
simultaneamente.
Anteriormente, decidimos que, para enviar eventos ao programa, íamos enviar um evento com parâmetros estritamente especificados
(identificador de evento, valor long, valor double e valor de string do evento), e enviávamos o tempo do evento em milissegundos ao
parâmetro long. Agora, como mudado o conceito de como determinar eventos, precisamos determinar com precisão o evento de acordo com vários
de seus parâmetros:
- Identificador do evento — propriedade do evento alterado. Cada objeto tem suas próprias propriedades, e num programa que não saiba nada em qual objeto alterada a propriedade e quais as propriedades desse objeto alteradas (inteiro ou real), não é possível determinar isso exclusivamente a partir do identificador de evento.
- Causa do evento — aumento ou diminuição no valor da propriedade ou do cruzamento do nível controlado. Esse valor também não nos permite
determinar com precisão o evento. Mas graças ao identificador do evento e à sua causa, já podemos determinar o
aumento/diminuição/cruzamento na propriedade de um objeto com um valor controlado predeterminado. Por isso, para uma
identificação precisa do evento, precisamos indicar o identificador da classe no objeto em que o evento acontece.
Um identificador da lista de coleções (indica precisamente que o objeto pertence a uma determinada classe), um símbolo, uma conta ou um objeto de coleção criado no futuro pode servir como identificador. Portanto, para o evento também deve ser enviado:
- Identificador de coleção — assim todos os três identificadores acima permitirão identificar exclusivamente o evento.
- Propriedade de string do evento — nome do objeto em que acontecido o evento.
Assim, vemos que, para determinar o evento, precisamos obter três parâmetros inteiros, mas, também, a hora do evento, transferida através de um
valor long. Enquanto nós temos apenas uma propriedade long do evento. Como devemos proceder? A solução é simples, num parâmetro long
transferiremos de vez três eventos inteiros com tipo ushort. O tipo long possui oito bytes e o tipo ushort, dois bytes. Portanto, num
contêiner long, podemos armazenar três números ushort escritos em 0,1 bytes, 2,3 bytes, 4,5 bytes de um número long, e ainda temos mais dois
bytes 6 e 7 para transferir outro valor ushort, se necessário mais tarde.
Para determinar a hora do evento, basta transmitir apenas milissegundos de tempo em 0 e 1 bytes do parâmetro long.
- É possível obter a data e a hora do evento em TimeCurrent()
após o recebimento do evento e adicionar a esse tempo o número de milissegundos transmitidos no bytes zero e um do valor long do evento.
- Escreveremos o motivo do evento nos 2º e 3º bytes do parâmetro long do evento e
- o identificador de classe, nos 4º e 5º bytes do parâmetro long do evento.
Assim, ao obter o evento, do parâmetro long extraímos três valores ushort para que possamos definir a hora do evento e obter dados adicionais a fim de identificar ao certo o evento segundo o identificador de evento, transferido como parâmetro ushort custom_event_id para EventChartCustom(), e gerar o identificador exato do evento acontecido, com ajuda do identificador de evento e de dois valores obtidos adicionalmente de lparam .
Para determinar os eventos nas propriedades do objeto herdeiro no objeto pai (no objeto base de todos os objetos da biblioteca), no temporizador verificaremos o estado atual de cada uma das propriedades do objeto e o compararemos com o estado anterior dessa propriedade. Antes de tudo, verificaremos se definido o valor cuja magnitude deve ser comparada com o valor da alteração da propriedade. Se o valor marcado não estiver definido (LONG_MAX está definido para ele), essa propriedade será ignorada.
Como verificarmos listas de propriedades de objetos com tipos diferentes (long e double), para armazenar o estado atual e anterior das propriedades do objeto, decidi que é mais conveniente usar arrays bidimensionais em vez de uma estrutura. Na primeira dimensão do array, serão armazenados os índices de propriedade do objeto e na segunda, os valores da propriedade cujo índice inserido na primeira dimensão, o valor da alteração da propriedade, os valores controlados e os sinalizadores de evento dessa propriedade.
Deixe-me explicar por que é mais conveniente usar arryas do que estruturas:
Não sabemos antecipadamente qual
o tipo da propriedade que verificaremos, mas podemos entender seu tipo no índice da propriedade (as propriedades double do objeto sempre
estão localizadas após as propriedades long), o que significa que não precisamos duplicar os campos na estrutura para valores long e double
do mesmo valor verificado da propriedade do objeto. Simplesmente vamos registrar no array do tipo necessário (em conformidade com o tipo de
propriedade definida pelo seu índice) todos os dados requeridos para controlar o estado da propriedade do objeto com o tipo certo, e não será
preciso selecionar o campo da estrutura para inserir o valor transferido (long ou double).
Assim que determinada a alteração em qualquer uma das propriedades do objeto, nós a adicionamos à lista de eventos básicos do objeto
(como a pesquisa é realizada no objeto base, o evento será básico e não deverá ser confundido com o evento da classe herdeira, que será
determinada pela lista de eventos básicos e que será criada a partir de eventos básicos cujos ponteiros estão armazenados nela).
Nos métodos Refresh() de cada classe herdeira do objeto base, o temporizador verifica as listas de alterações de propriedades (listas de eventos básicos) e, se esses eventos estiverem nas listas de objetos, cada evento será convertido num evento de biblioteca e enviado ao programa de controle.
E para complementar, precisaremos criar métodos que nos permitam estabelecer programaticamente valores controlados de alterações para qualquer propriedade de qualquer objeto de biblioteca criado com base no objeto base. Sengo assim, a qualquer momento, podemos alterar rapidamente as condições necessárias para gerar eventos a partir dos objetos dos quais precisamos.
O conjunto de medidas tomadas hoje para modificar o objeto básico da biblioteca permitirá que não pensemos mais na criação de um controle de eventos para todos os objetos criados posteriormente, pois usaremos apenas a funcionalidade preparada hoje.
Então, vamos começar.
Como agora trabalharemos com eventos no objeto base dos objetos de biblioteca, precisamos criar uma enumeração das causas do evento para
identificação.
No arquivo \MQL5\Include\DoEasy\ Defines.mqh depois das opções para escolha de tempo
escrevemos a enumeração
de possíveis causas de eventos do objeto base:
//+------------------------------------------------------------------+ //| Possible options of selecting by time | //+------------------------------------------------------------------+ enum ENUM_SELECT_BY_TIME { SELECT_BY_TIME_OPEN, // By open time (in milliseconds) SELECT_BY_TIME_CLOSE, // By close time (in milliseconds) }; //+------------------------------------------------------------------+ //| Possible event reasons of the object library base object | //+------------------------------------------------------------------+ enum ENUM_BASE_EVENT_REASON { BASE_EVENT_REASON_INC, // Increase in the object property value BASE_EVENT_REASON_DEC, // Decrease in the object property value BASE_EVENT_REASON_MORE_THEN, // Object property value exceeds the control value BASE_EVENT_REASON_LESS_THEN, // Object property value is less than the control value BASE_EVENT_REASON_EQUALS // Object property value is equal to the control value }; //+------------------------------------------------------------------+
Como não precisaremos de sinalizadores de eventos, em vez de listas de sinalizadores de eventos de símbolo
escreveremos a
lista de possíveis eventos de símbolos na janela Observação do Mercado:
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of possible symbol events in the Market Watch window | //+------------------------------------------------------------------+ enum ENUM_MW_EVENT { MARKET_WATCH_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // No event MARKET_WATCH_EVENT_SYMBOL_ADD, // Adding a symbol to the Market Watch window MARKET_WATCH_EVENT_SYMBOL_DEL, // Removing a symbol from the Market Watch window MARKET_WATCH_EVENT_SYMBOL_SORT, // Sorting symbols in the Market Watch window }; #define SYMBOL_EVENTS_NEXT_CODE (MARKET_WATCH_EVENT_SYMBOL_SORT+1) // The code of the next event after the last symbol event code //+------------------------------------------------------------------+
E removemos a lista de possíveis eventos do símbolo por ser desnecessária:
//+------------------------------------------------------------------+ //| List of possible symbol events | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_EVENT { SYMBOL_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // No event SYMBOL_EVENT_MW_ADD, // Adding a symbol to the Market Watch window SYMBOL_EVENT_MW_DEL, // Removing a symbol from the Market Watch window SYMBOL_EVENT_MW_SORT, // Sorting symbols in the Market Watch window SYMBOL_EVENT_TRADE_DISABLE, // Disable order execution SYMBOL_EVENT_TRADE_LONGONLY, // Allow buy only SYMBOL_EVENT_TRADE_SHORTONLY, // Allow sell only SYMBOL_EVENT_TRADE_CLOSEONLY, // Enable close only SYMBOL_EVENT_TRADE_FULL, // No trading limitations SYMBOL_EVENT_SESSION_DEALS_INC, // The increase in the number of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_DEALS_DEC, // The decrease in the number of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORDERS_INC, // The increase in the total number of buy orders currently exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORDERS_DEC, // The decrease in the total number of buy orders currently exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORDERS_INC, // The increase in the total number of sell orders currently exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORDERS_DEC, // The decrease in the total number of sell orders currently exceeds the specified value SYMBOL_EVENT_VOLUME_INC, // Volume increase in the last deal exceeds the specified value SYMBOL_EVENT_VOLUME_DEC, // Volume decrease in the last deal exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_DAY_INC, // The increase in the maximum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_DAY_DEC, // The decrease in the maximum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_DAY_INC, // The increase in the minimum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_DAY_DEC, // The decrease in the minimum volume per day exceeds the specified value SYMBOL_EVENT_SPREAD_INC, // The increase in a spread exceeds the specified change SYMBOL_EVENT_SPREAD_DEC, // The decrease in a spread exceeds the specified change SYMBOL_EVENT_STOPLEVEL_INC, // The increase of a Stop order level exceeds the specified value SYMBOL_EVENT_STOPLEVEL_DEC, // The decrease of a Stop order level exceeds the specified value SYMBOL_EVENT_FREEZELEVEL_INC, // The increase in the freeze level exceeds the specified value SYMBOL_EVENT_FREEZELEVEL_DEC, // The decrease in the freeze level exceeds the specified value SYMBOL_EVENT_BID_LAST_INC, // The increase in the Bid or Last price exceeds the specified value SYMBOL_EVENT_BID_LAST_DEC, // The decrease in the Bid or Last price exceeds the specified value SYMBOL_EVENT_BID_LAST_HIGH_INC, // The increase in the maximum Bid or Last price per day exceeds the specified value SYMBOL_EVENT_BID_LAST_HIGH_DEC, // The decrease in the maximum Bid or Last price per day exceeds the specified value relative to the specified price SYMBOL_EVENT_BID_LAST_LOW_INC, // The increase in the minimum Bid or Last price per day exceeds the specified value relative to the specified price SYMBOL_EVENT_BID_LAST_LOW_DEC, // The decrease in the minimum Bid or Last price per day exceeds the specified value SYMBOL_EVENT_ASK_INC, // The increase in the Ask price exceeds the specified value SYMBOL_EVENT_ASK_DEC, // The decrease in the Ask price exceeds the specified value SYMBOL_EVENT_ASK_HIGH_INC, // The increase in the maximum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_HIGH_DEC, // The decrease in the maximum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_LOW_INC, // The increase in the minimum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_LOW_DEC, // The decrease in the minimum Ask price per day exceeds the specified value SYMBOL_EVENT_VOLUME_REAL_DAY_INC, // The increase in the real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_REAL_DAY_DEC, // The decrease in the real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_INC, // The increase in the maximum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_DEC, // The decrease in the maximum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_INC, // The increase in the minimum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_DEC, // The decrease in the minimum real volume per day exceeds the specified value SYMBOL_EVENT_OPTION_STRIKE_INC, // The increase in the strike price exceeds the specified value SYMBOL_EVENT_OPTION_STRIKE_DEC, // The decrease in the strike price exceeds the specified value SYMBOL_EVENT_VOLUME_LIMIT_INC, // The increase in the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_VOLUME_LIMIT_DEC, // The decrease in the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_SWAP_LONG_INC, // The increase in the swap long SYMBOL_EVENT_SWAP_LONG_DEC, // The decrease in the swap long SYMBOL_EVENT_SWAP_SHORT_INC, // The increase in the swap short SYMBOL_EVENT_SWAP_SHORT_DEC, // The decrease in the swap short SYMBOL_EVENT_SESSION_VOLUME_INC, // The increase in the total volume of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_VOLUME_DEC, // The decrease in the total volume of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_TURNOVER_INC, // The increase in the total turnover in the current session exceeds the specified value SYMBOL_EVENT_SESSION_TURNOVER_DEC, // The decrease in the total turnover in the current session exceeds the specified value SYMBOL_EVENT_SESSION_INTEREST_INC, // The increase in the total volume of open positions in the current session exceeds the specified value SYMBOL_EVENT_SESSION_INTEREST_DEC, // The decrease in the total volume of open positions in the current session exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_INC, // The increase in the total volume of buy orders exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_DEC, // The decrease in the total volume of buy orders exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_INC, // The increase in the total volume of sell orders exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_DEC, // The decrease in the total volume of sell orders exceeds the specified value SYMBOL_EVENT_SESSION_OPEN_INC, // The increase in the session open price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_OPEN_DEC, // The decrease in the session open price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_CLOSE_INC, // The increase in the session close price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_CLOSE_DEC, // The decrease in the session close price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_AW_INC, // The increase in the average weighted session price exceeds the specified value SYMBOL_EVENT_SESSION_AW_DEC, // The decrease in the average weighted session price exceeds the specified value }; #define SYMBOL_EVENTS_NEXT_CODE (SYMBOL_EVENT_SESSION_AW_DEC+1) // The code of the next event after the last symbol event code //+------------------------------------------------------------------+
O código do próximo evento foi mudado para o valor seguinte ao da
constante
MARKET_WATCH_EVENT_SYMBOL_SORT da enumeração ENUM_MW_EVENT.
Agora vamos implementar a funcionalidade planejada.
No arquivo do objeto base \MQL5\Include\DoEasy\Objects\BaseObj.mqh escrevemos a nova classe do evento base:
//+------------------------------------------------------------------+ //| Library object's base event class | //+------------------------------------------------------------------+ 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; } //--- Constructor 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){} //--- Comparison method to search for identical event objects 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 ); } }; //+------------------------------------------------------------------+
Na seção privada da classe, existem variáveis para armazenamento das causas
do evento, do ID do evento (corresponde ao valor do índice
da propriedade alterada do objeto) e da
magnitude da mudança na propriedade do evento.
A seção
pública da classe contém métodos para retornar as variáveis-membro da classe mencionadas acima.
Aos parâmetros formais dentro do construtor da classe são
transferidos os valores destas propriedades, e imediatamente na lista de inicialização às variáveis-membros de classe correspondentes
são atribuídos os valores transferidos.
Também a classe tem o método para comparar dois objetos de classe
para busca na
lista de ponteiros dinâmicos para objetos,
sobre a qual falamos mais de uma vez.
Como vamos armazenar a lista de propriedades controladas dos objetos em arrays de dois dimensões, adicionamos
substituição de macros indicando o tamanho da segunda dimensão dos arrays, e na seção privada da classe declaramos dois variáveis,
nas quais armazenaremos o
número de propriedades inteiras e reais
do objeto, que será herdado da classe em questão (afinal, a classe base não sabe nada sobre as quantidades de propriedades que possuem
seus descendentes e essas quantidades precisarão ser especificadas explicitamente). E
declaramos um método para preencher arrays de propriedades e
para procurar alterações nas propriedades de objetos herdados.
//+------------------------------------------------------------------+ //| Base object class for all library objects | //+------------------------------------------------------------------+ #define CONTROLS_TOTAL (10) class CBaseObj : public CObject { private: int m_long_prop_total; int m_double_prop_total; //--- Fill in the object property array template<typename T> bool FillPropertySettings(const int index,T &array[][CONTROLS_TOTAL],T &array_prev[][CONTROLS_TOTAL],int &event_id); protected:
Na seção protegida da classe declaramos uma lista para armazenar ponteiros para
instâncias dos do objeto, uma variável para armazenar o ID do evento, o sinalizador
da primeira inicialização e uma variável para armazenar o tipo de objeto
herdado.
Também adicionamos quatro arrays bidimensionais para
armazenar propriedades e controlar suas alterações (as propriedades inteiras e reais - atuais e anteriores - do objeto herdeiro) e
o
método que retorna apenas milissegundos armazenados na hora do evento
(para MQL4, retornamos 0 e para MQL5, o restante da divisão por 1000 valores de tempo long).
Como a classe base não sabe
nada sobre o número de propriedades de objetos herdeiros e os tamanhos precisam ser definidos a partir de classes herdeiras (onde são
conhecidos), declararemos
métodos de definição e verificação
de tamanhos de array:
protected: CArrayObj m_list_events_base; // Object base event list CArrayObj m_list_events; // Object event list MqlTick m_tick; // Tick structure for receiving quote data double m_hash_sum; // Object data hash sum double m_hash_sum_prev; // Object data hash sum during the previous check int m_digits_currency; // Number of decimal places in an account currency int m_global_error; // Global error code long m_chart_id; // Control program chart ID bool m_is_event; // Object event flag int m_event_code; // Object event code int m_event_id; // Event ID (equal to the object property value) string m_name; // Object name string m_folder_name; // Name of the folder storing CBaseObj descendant objects bool m_first_start; // First launch flag int m_type; // Object type (corresponds to the collection IDs) //--- Data in the array cells //--- Data for storing, controlling and returning tracked properties: //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the control level long m_long_prop_event[][CONTROLS_TOTAL]; // The array for storing object's integer properties values and controlled property change values double m_double_prop_event[][CONTROLS_TOTAL]; // The array for storing object's real properties values and controlled property change values long m_long_prop_event_prev[][CONTROLS_TOTAL]; // The array for storing object's controlled integer properties values during the previous check double m_double_prop_event_prev[][CONTROLS_TOTAL]; // The array for storing object's controlled real properties values during the previous check //--- Return (1) time in milliseconds, (2) milliseconds from the MqlTick time value 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 ; } //--- return the flag of the event code presence in the event object bool IsPresentEventFlag(const int change_code) const { return (this.m_event_code & change_code)==change_code; } //--- Return the number of decimal places of the account currency int DigitsCurrency(void) const { return this.m_digits_currency; } //--- Returns the number of decimal places in the 'double' value int GetDigits(const double value) const; //--- Set the size of the array of controlled (1) integer and (2) real object properties bool SetControlDataArraySizeLong(const int size); bool SetControlDataArraySizeDouble(const int size); //--- Check the array size of object properties bool CheckControlDataArraySize(bool check_long=true); //--- Set the (1) controlled value and (2) object property change value template<typename T> void SetControlledValue(const int property,const T value); template<typename T> void SetControlledChangedValue(const int property,const T value); //--- Set the value of the pbject property controlled (1) increase, (2) decrease, (3) control level 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); //--- Set the flag of a property change exceeding the (1) increase and (2) decrease values template<typename T> void SetControlledFlagINC(const int property,const T value); template<typename T> void SetControlledFlagDEC(const int property,const T value); //--- Set the flag of a property change (1) exceeding, (2) being less than the control level, (3) being equal to the level 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); //--- Return the set value of the controlled (1) integer and (2) real object properties increase 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]; } //--- Return the set value of the controlled (1) integer and (2) real object properties decrease 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]; } //--- Return the control level of object's (1) integer and (2) real properties 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]; } //--- Return the value of the object (1) integer and (2) real property 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]; } //--- Return the change value of the controlled (1) integer and (2) real object property 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]; } //--- Return the flag of an (1) integer and (2) real property value change exceeding the increase value 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]; } //--- Return the flag of an (1) integer and (2) real property value change exceeding the decrease value 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]; } //--- Return the flag of an (1) integer and (2) real property value increase exceeding the control level 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]; } //--- Return the flag of an (1) integer and (2) real property value decrease being less than the control level 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]; } //--- Return the flag of an (1) integer and (2) real property being equal to the control level 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) Pack a 'ushort' number to a passed 'long' number //--- (2) convert a 'ushort' value to a specified 'long' number byte long UshortToLong(const ushort ushort_value,const uchar index,long &long_value); long UshortToByte(const ushort value,const uchar index) const; public:
Aqui, na seção privada da classe, são declarados métodos para definir e
retornar propriedades controladas e seus valores, bem como métodos para
empacotamento do número ushort em bytes especificados de um contêiner long segundo o índice. (Índice 0 => bytes 0-1,
Índice 1 => bytes 2-3, Índice 2 => bytes 4-5)
Na seção pública da classe, declaramos os métodos para redefinir
valores de propriedades mutáveis e valores das propriedades controladas do
objeto, método para adicionar um evento base à lista, método
de obter o objeto base de uma lista por índice, método que retorna o número de na
lista, método virtual retornando o tipo de um objeto e método
que retorna a descrição de string do evento base:
public: //--- Reset the variables of (1) tracked and (2) controlled object data (can be reset in the descendants) void ResetChangesParams(void); virtual void ResetControlsParams(void); //--- Add the (1) object event and (2) the object event reason to the list 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); //--- Return the occurred event flag to the object data bool IsEvent(void) const { return this.m_is_event; } //--- Return (1) the list of events, (2) the object event code and (3) the global error code 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; } //--- Return (1) an event object and (2) a base event by its number in the list CEventBaseObj *GetEvent(const int shift=WRONG_VALUE,const bool check_out=true); CBaseEvent *GetEventBase(const int index); //--- Return the number of (1) object events int GetEventsTotal(void) const { return this.m_list_events.Total(); } //--- (1) Set and (2) return the chart ID of the control program void SetChartID(const long id) { this.m_chart_id=id; } long GetChartID(void) const { return this.m_chart_id; } //--- (1) Set the sub-folder name, (2) return the folder name for storing descendant object files void SetSubFolderName(const string name) { this.m_folder_name=DIRECTORY+name; } string GetFolderName(void) const { return this.m_folder_name; } //--- Return the object name string GetName(void) const { return this.m_name; } //--- Update the object data to search for changes (Calling from the descendants: CBaseObj::Refresh()) virtual void Refresh(void); //--- Return an object type virtual int Type(void) const { return this.m_type; } //--- Return an object event description string EventDescription(const int property, const ENUM_BASE_EVENT_REASON reason, const int source, const string value, const string property_descr, const int digits); //--- Constructor CBaseObj(); }; //+------------------------------------------------------------------+
Agora, revisaremos brevemente todos os métodos declarados acima.
Construtor de classe:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ 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(); } //+------------------------------------------------------------------+
Neste caso, como agora não temos códigos dos eventos que coletamos anteriormente a partir de sinalizadores e nos quais o valor zero indicava a
ausência de evento, precisamos substituir a inicialização do código de evento na lista de inicialização da classe por uma diferente de zero
(já que zero indica um evento da primeira propriedade na enumeração das propriedades inteiras de objeto, mais de zero indica os seguintes
eventos na lista de propriedades de objeto e quantos deles não são conhecidos na classe pai),
definimos o valor do código do evento como -1.
Inicializamos
o nome do objeto com o nome da classe (o nome é reatribuído nos herdeiros), iniciamos o número
de propriedades de inteiras e reais do objeto herdeiro com
valores nulos e
definimos o sinalizador da primeira inicialização.
No corpo
da classe
definimos os tamanhos de arrays de propriedades inteiras e reais como zero, limpamos
a lista de eventos básicos e definimos o sinalizador da lista classificada.
A implementação do método virtual Refresh() da classe, que declaramos anteriormente, foi atribuída às classes herdeiras. Agora, criaremos uma implementação desse método para a classe do objeto base, assim, nela, rastrearemos as alterações nas propriedades dos objetos herdeiros e, ao definir um evento, criaremos eventos básicos e os adicionaremos à lista de eventos básicos para processamento subsequente e criação de eventos de objetos para enviá-los ao programa:
//+------------------------------------------------------------------+ //| Update the object data to search changes in them | //| Call from descendants: CBaseObj::Refresh() | //+------------------------------------------------------------------+ void CBaseObj::Refresh(void) { //--- Check the size of the arrays, Exit if it is zero if(!this.CheckControlDataArraySize() || !this.CheckControlDataArraySize(false)) return; //--- Reset the event flag and clear all lists 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(); //--- Fill in the array of integer properties and control their changes 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; //--- Fill in the array of real properties and control their changes 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; //--- First launch 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; } } //+------------------------------------------------------------------+
Aqui, todas as ações estão escritas nos comentários do código e tudo o que é feito no método — são limpas preliminarmente as listas de eventos, são
chamados os métodos para preencher os arrays de propriedades inteiras e reais do objeto herdeiro e são verificadas suas alterações.
Se esta for a primeira inicialização, o estado atual dos arrays de propriedades é copiado para o estado anterior (para que não haja
diferença entre eles e, portanto, não haja log de eventos), é redefinido o sinalizador da primeira inicialização e é limpa a lista de eventos
básicos que já podem ter sido criados ao chamar métodos
FillPropertySettings().
Implementação do método que preenche os arrays de propriedades do objeto herdeiro e que controla suas alterações:
//+------------------------------------------------------------------+ //| Fill in the object property array | //+------------------------------------------------------------------+ template<typename T> bool CBaseObj::FillPropertySettings(const int index,T &array[][CONTROLS_TOTAL],T &array_prev[][CONTROLS_TOTAL],int &event_id) { //--- Data in the array cells //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the control level //--- If controlled values are not set, exit with 'false' if(this.m_first_start) return false; //--- Set the shift of the 'double' property index and the event ID event_id=index+(typename(T)=="double" ? this.m_long_prop_total : 0); //--- Reset all event flags for(int j=5;j<CONTROLS_TOTAL;j++) array[index][j]=false; //--- Property change value T value=array[index][3]-array_prev[index][3]; array[index][4]=value; //--- If the controlled property increase value is set if(array[index][0]<LONG_MAX) { //--- If the property change value exceeds the controlled increase value - there is an event, //--- add the event to the list, set the flag and save the new property value size 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 the controlled property decrease value is set if(array[index][1]<LONG_MAX) { //--- If the property change value exceeds the controlled decrease value - there is an event, //--- add the event to the list, set the flag and save the new property value size 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 the controlled level value is set if(array[index][2]<LONG_MAX) { value=array[index][3]-array[index][2]; //--- If a property value exceeds the control level, there is an event //--- add the event to the list and set the flag 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; } //--- If a property value is less than the control level, there is an event, //--- add the event to the list and set the flag 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; } //--- If a property value is equal to the control level, there is an event, //--- add the event to the list and set the flag 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; } } //--- Save the current property value as a previous one array_prev[index][3]=array[index][3]; return true; } //+------------------------------------------------------------------+
Aqui, todas as ações estão explicitadas nos comentários do código. A única coisa que quero explicar é a seleção do deslocamento do índice da propriedade double do objeto para obter o ID do evento. Como temos as propriedades reais de todos os objetos após as propriedades inteiras, o início da primeira propriedade real é igual ao número de propriedades inteiras (se o número de propriedades long for três, a primeira propriedade do material terá o índice 3 (0,1,2, 3)). Em nossos arrays, a contagem regressiva começa, naturalmente, do zero. Portanto, no caso de trabalhar com propriedades double, nós precisamos adicionar ao índice do array o número de propriedades inteiras do objeto.
Métodos para definir os tamanhos arrays de propriedades inteiras e reais de objetos herdeiros:
//+------------------------------------------------------------------+ //| Set the size of the arrays of the object integer properties | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Set the size of the arrays of the object real properties | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+
Os métodos retornam o resultado do redimensionamento de arrays pelo valor passado ao método.
Ressalto uma particularidade de redimensionar um array multidimensional em MQL4. A função ArrayResize() em MQL4 retorna o tamanho total de todas as dimensões do array. Em MQL5, é o tamanho da primeira dimensão que muda. Por exemplo, se nossa segunda dimensão tiver um tamanho igual a dois, ao redimensionar a primeira dimensão do array para 10, a função retornará 20, o que não é lógico (apenas redimensionamos a primeira dimensão). Mas em MQL5, a função retorna o valor correto, assim, para o exemplo acima, retornará 10, conforme o esperado.
Por isso, nos métodos foi criado um divisor
pelo qual em MQL4 é preciso dividir o valor retornado pela função —
pelo tamanho da
segunda dimensão.
Método para verificar o tamanho de um array de propriedades inteiras ou reais de um objeto herdeiro:
//+------------------------------------------------------------------+ //| Check the array size of object properties | //+------------------------------------------------------------------+ 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 should first set size of array equal to number of object integer properties"); txt3=TextByLanguage("Для этого используйте метод CBaseObj::SetControlDataArraySizeLong()","To do this, use CBaseObj::SetControlDataArraySizeLong() method"); txt4=TextByLanguage("со значением количества integer-свойств объекта в параметре \"size\"","with value of number of integer properties of object in \"size\" parameter"); 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 should first set size of array equal to number of object double properties"); txt3=TextByLanguage("Для этого используйте метод CBaseObj::SetControlDataArraySizeDouble()","To do this, use CBaseObj::SetControlDataArraySizeDouble() method"); txt4=TextByLanguage("со значением количества double-свойств объекта в параметре \"size\"","with value of number of double properties of object in \"size\" parameter"); 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; } //+------------------------------------------------------------------+
Para o método é transferido o sinalizador indicando o tamanho da matriz
verificada.
Se true , é verificada um array de propriedades long, se false
, um array de propriedades double.
Se o tamanho do array a ser verificado não estiver definido, é gerada uma mensagem que será exibida no log e será retornado false. Se o tamanho do array já estiver definido, será retornado true.
Métodos para redefinir os valores monitorados e alterar os valores dos dados monitorados das propriedades do objeto:
//+------------------------------------------------------------------+ //| Reset the variables of controlled object data values | //+------------------------------------------------------------------+ void CBaseObj::ResetControlsParams(void) { if(!this.CheckControlDataArraySize(true) || !this.CheckControlDataArraySize(false)) return; //--- Data in the array cells //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level 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; } //+------------------------------------------------------------------+ //| Reset the variables of tracked object data | //+------------------------------------------------------------------+ 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(); //--- Data in the array cells //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the controlled value 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); } //+------------------------------------------------------------------+
Nos métodos de dois ciclos, segundo os arrays de propriedades inteiras e reais do objeto herdeiro, são definidos os valores de inicialização
para as células necessárias da segunda dimensão de arrays. As células inicializadas são explicitadas nos comentários do código.
Método que adiciona o evento base à lista de do objeto:
//+------------------------------------------------------------------+ //| Add the object base event to the list | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+
Para o método é transferido o identificador do evento, o motivo
do evento e o tamanho da alteração da propriedade do objeto herdeiro.
Depois, é criado um novo evento base, e se
exatamente o mesmo evento já estiver na lista de eventos básicos, esse evento será excluído e será retornado
false indicando que o evento
não foi adicionado. Caso contrário,
será retornado o resultado da adição do novo evento à lista de eventos básicos do
objeto.
Método que retorna o evento base por seu índice na lista de do objeto:
//+------------------------------------------------------------------+ //| Return a base event by its index in the list | //+------------------------------------------------------------------+ 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); }
Para o método é transferido o índice do evento necessário, e se a lista tiver tamanho zero ou o índice ficar fora da lista de eventos básicos, será retornado NULL, caso contrário, obtemos o evento da lista por índice e retornamos o ponteiro para o objeto recebido.
Para a classe do objeto base, é necessário criar métodos pelos quais possamos definir rapidamente os valores necessários para a alteração nas
propriedades, valores esses que excedidos leva à geração de eventos. E métodos para definir novos valores de propriedades de objetos
herdeiros e para retornar sinalizadores sobre eventos 'controlados' de objetos. Como a classe base não sabe nada sobre as propriedades de
seus descendentes, é necessário criar métodos universais que permitam fazer alterações na propriedade desejada do objeto herdeiro. Como
indicaremos o número de propriedades inteiras e reais para cada uma das classes sucessoras, não será difícil determinar para qual
propriedade estaremos definindo o valor, por tanto, será necessário apenas verificar o índice da propriedade alterável. Se o índice for
menor que o número de propriedades inteiras, serão feitas alterações na propriedade inteira do objeto, caso contrário, na propriedade
real.
Implementação de métodos para definir as propriedades controladas de objetos herdeiros:
//+------------------------------------------------------------------+ //| Methods of setting controlled parameters | //+------------------------------------------------------------------+ //--- Data for storing, controlling and returning tracked properties: //--- [Property index][0] Controlled property increase value //--- [Property index][1] Controlled property decrease value //--- [Property index][2] Controlled property value level //--- [Property index][3] Property value //--- [Property index][4] Property value change //--- [Property index][5] Flag of a property change exceeding the increase value //--- [Property index][6] Flag of a property change exceeding the decrease value //--- [Property index][7] Flag of a property increase exceeding the control level //--- [Property index][8] Flag of a property decrease being less than the control level //--- [Property index][9] Flag of a property value being equal to the control level //+------------------------------------------------------------------+ //| Set the value of the controlled increase of object properties | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Set the value of the controlled decrease of object properties | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Set the control level of object properties | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Set the object property 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; } //+------------------------------------------------------------------+ //| Set the object property change 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; } //+------------------------------------------------------------------+ //| Set the flag of the property value change | //| exceeding the increase 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; } //+------------------------------------------------------------------+ //| Set the flag of the property value change | //| exceeding the decrease 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; } //+------------------------------------------------------------------+ //| Set the flag of the property value increase | //| exceeding the control level | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Set the flag of the property value decrease | //| being less than the control level | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Set the flag of the property value being equal to the | //| control level | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+
Consideremos o último método: para o método é transferida a
propriedade em cujo valor é necessário inserir o valor padrão T
value. Se o índice de propriedade for menor que o número de propriedades
inteiras do objeto herdeiro, inserimos o T value na célula desejada no array de
propriedades inteiras do objeto, caso contrário, calculamos o índice pelo
qual essa propriedade é armazenada no array de propriedades reais (o índice de uma propriedade double é sempre - o número de
propriedades inteiras do objeto - maior que o índice da mesma propriedade no array) e
inserimos o T value na célula desejada no array de propriedades reais do objeto. As
células necessárias da segunda dimensão do aray para cada um dos métodos são listadas antes da lista de métodos.
Método que converte um valor ushort num valor long deslocado um número de bytes necessário para empacotamento subsequente num contêiner
long:
//+------------------------------------------------------------------+ //| Convert a 'ushort' value to a specified 'long' number byte | //+------------------------------------------------------------------+ long CBaseObj::UshortToByte(const ushort value,const uchar index) const { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. \"index\" value should be between 0 - 3")); return 0; } return(long)value<<(16*index); } //+------------------------------------------------------------------+
Imagine um número long de oito bytes, dividido em células de dois bytes (cada uma dessas células tem seu próprio índice):
Bytes 6-7 (índice 3) |
Bytes 4-5 (índice 2) | Bytes 2-3 (índice 1) |
Bytes 0-1 (índice 0) |
---|---|---|---|
ushort 4 |
ushort 3 |
ushort 2 |
ushort 1 |
Podemos colocar quatro números ushort nela. Devemos deslocar cada número subsequente para a esquerda 16 bits * índice (1 byte = 8 bits) e, em
seguida, adicionar o valor resultante ao número long. Dessa forma, obtemos alguns valores ushort compactados num contêiner long.
Para o método são transferidos um número ushort e o índice
no qual é necessário armazenar o valor ushort num contêiner long.
O índice é verificado e, se for mais de 3, será exibida uma mensagem de índice inválido e será retornado 0.
Se
o índice for válido, o
número ushort será deslocado para a esquerda 16
bits * índice (num byte há 8 bits, e é necessário deslocar um número de dois bytes),
e
o resultado do deslocamento será retornado do método.
Método que compacta o valor ushort deslocado um número necessário de bytes num contêiner long:
//+------------------------------------------------------------------+ //| Pack a 'ushort' number to a passed 'long' number | //+------------------------------------------------------------------+ long CBaseObj::UshortToLong(const ushort ushort_value,const uchar index,long &long_value) { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. \"index\" value should be between 0 - 3")); return 0; } return(long_value |= UshortToByte(ushort_value,index)); } //+------------------------------------------------------------------+
Para o método são transferidos um número ushort, que é
necessário armazenar num
contêiner long transferido para o método pela referência, e o índice
de bytes no qual é necessário armazenar o valor ushort no contêiner long.
Igual ao método acima, é
verificado o índice e, após verificação bem-sucedida do índice,
ao
número long é adicionado o número ushort
deslocado o número de bytes necessário pelo método UshortToByte()com
ajuda do bit a bit "OR",
e o resultado será retornado ao programa de chamada..
Método que retorna uma descrição de string do evento do objeto herdeiro:
//+------------------------------------------------------------------+ //| Return an object event description | //+------------------------------------------------------------------+ 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) { //--- Depending on the collection ID, create th object type description string type= ( this.Type()==COLLECTION_SYMBOLS_ID ? TextByLanguage("символа: ","symbol property: ") : this.Type()==COLLECTION_ACCOUNT_ID ? TextByLanguage("аккаунта: ","account property: ") : "" ); //--- Depending on the property type, create the property change value description string level= ( property<this.m_long_prop_total ? ::DoubleToString(this.GetControlledValueLongLEVEL(property),digits) : ::DoubleToString(this.GetControlledValueDoubleLEVEL(property),digits) ); //--- Depending on the event reason, create the event description text 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 the object name+created event description text return this.m_name+": "+res; } //+------------------------------------------------------------------+
Como a classe do objeto base não sabe nada sobre seus descendentes, para descrever o evento na classe herdeira, precisamos apontar para o
objeto descendente no qual o evento ocorre.
Para fazer isso, para o método é transferido
- propriedade do objeto em que registrado o evento,
- motivo do evento — aumento/diminuição do valor da
propriedade,
- fonte de evento — identificador da coleção em que ocorrido o
evento,
- valor da alteração da propriedade do objeto,
- descrição textual da propriedade do objeto herdeiro
(disponível no herdeiro) e
- casas decimais na representação digital da propriedade alterada (também disponível no herdeiro).
Todas as etapas para criar uma descrição do evento do objeto herdeiro são comentadas no código, espero que sejam claras.
Isso conclui as alterações necessárias na classe de objeto base (durante o desenvolvimento da biblioteca e a criação
de novas coleções, novos identificadores de coleção serão adicionados ao último método para criar uma descrição correta dos eventos).
Renovando a classe de símbolos e a coleção de símbolos
Hoje, revisaremos a operação da classe de símbolos e da coleção de símbolos tendo os novos eventos de objeto base em mente. Para fazer isso,
fazemos alterações nas classes de símbolos e nas coleções de símbolos.
Abrimos o arquivo \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh e começamos a fazer alterações.
Como agora todos os eventos dos objetos herdeiros do objeto base estão definidos na classe pai, não há necessidade de controlar a alteração de
propriedades do objeto na classe herdeira. Isso significa que agora não é mais necessária a estrutura de dados das propriedades
controladas do objeto.
Da classe do objeto-símbolo excluímos a estrutura e dois objetos com o tipo dessa estrutura:
struct MqlDataSymbol
{
//--- Symbol integer properties
ENUM_SYMBOL_TRADE_MODE trade_mode; // SYMBOL_TRADE_MODE Order filling modes
long session_deals; // SYMBOL_SESSION_DEALS The number of deals in the current session
long session_buy_orders; // SYMBOL_SESSION_BUY_ORDERS The total number of current buy orders
long session_sell_orders; // SYMBOL_SESSION_SELL_ORDERS The total number of current sell orders
long volume; // SYMBOL_VOLUME Last deal volume
long volume_high_day; // SYMBOL_VOLUMEHIGH Maximum volume within a day
long volume_low_day; // SYMBOL_VOLUMELOW Minimum volume within a day
int spread; // SYMBOL_SPREAD Spread in points
int stops_level; // SYMBOL_TRADE_STOPS_LEVEL Minimum distance in points from the current close price for setting Stop orders
int freeze_level; // SYMBOL_TRADE_FREEZE_LEVEL Freeze distance for trading operations (in points)
//--- Symbol real properties
double bid_last; // SYMBOL_BID/SYMBOL_LAST Bid - the best sell offer/Last deal price
double bid_last_high; // SYMBOL_BIDHIGH/SYMBOL_LASTHIGH Maximum Bid within the day/Maximum Last per day
double bid_last_low; // SYMBOL_BIDLOW/SYMBOL_LASTLOW Minimum Bid within the day/Minimum Last per day
double ask; // SYMBOL_ASK Ask - nest buy offer
double ask_high; // SYMBOL_ASKHIGH Maximum Ask of the day
double ask_low; // SYMBOL_ASKLOW Minimum Ask of the day
double volume_real_day; // SYMBOL_VOLUME_REAL Real Volume of the day
double volume_high_real_day; // SYMBOL_VOLUMEHIGH_REAL Maximum real Volume of the day
double volume_low_real_day; // SYMBOL_VOLUMELOW_REAL Minimum real Volume of the day
double option_strike; // SYMBOL_OPTION_STRIKE Strike price
double volume_limit; // SYMBOL_VOLUME_LIMIT Maximum permissible total volume for a position and pending orders in one direction
double swap_long; // SYMBOL_SWAP_LONG Long swap value
double swap_short; // SYMBOL_SWAP_SHORT Short swap value
double session_volume; // SYMBOL_SESSION_VOLUME The total volume of deals in the current session
double session_turnover; // SYMBOL_SESSION_TURNOVER The total turnover in the current session
double session_interest; // SYMBOL_SESSION_INTEREST The total volume of open positions
double session_buy_ord_volume; // SYMBOL_SESSION_BUY_ORDERS_VOLUME The total volume of Buy orders at the moment
double session_sell_ord_volume; // SYMBOL_SESSION_SELL_ORDERS_VOLUME The total volume of Sell orders at the moment
double session_open; // SYMBOL_SESSION_OPEN Session open price
double session_close; // SYMBOL_SESSION_CLOSE Session close price
double session_aw; // SYMBOL_SESSION_AW The average weighted price of the session
};
MqlDataSymbol m_struct_curr_symbol; // Current symbol data
MqlDataSymbol m_struct_prev_symbol; // Previous symbol data
//---
Excluímos todas as variáveis-membro da classe para armazenar as propriedades controladas e alteradas do objeto-símbolo, assim, agora todos esses dados são armazenados em arrays da classe do objeto base:
//--- Current session deals
long m_control_session_deals_inc; // Controlled value of the growth of the number of deals
long m_control_session_deals_dec; // Controlled value of the decrease in the number of deals
long m_changed_session_deals_value; // Value of change in the number of deals
bool m_is_change_session_deals_inc; // Flag of a change in the number of deals exceeding the growth value
bool m_is_change_session_deals_dec; // Flag of a change in the number of deals exceeding the decrease value
//--- Buy orders of the current session
long m_control_session_buy_ord_inc; // Controlled value of the increase of the number of Buy orders
long m_control_session_buy_ord_dec; // Controlled value of the decrease in the number of Buy orders
long m_changed_session_buy_ord_value; // Buy orders change value
bool m_is_change_session_buy_ord_inc; // Flag of a change in the number of Buy orders exceeding the increase value
bool m_is_change_session_buy_ord_dec; // Flag of a change in the number of Buy orders being less than the increase value
//--- Sell orders of the current session
long m_control_session_sell_ord_inc; // Controlled value of the increase of the number of Sell orders
long m_control_session_sell_ord_dec; // Controlled value of the decrease in the number of Sell orders
long m_changed_session_sell_ord_value; // Sell orders change value
bool m_is_change_session_sell_ord_inc; // Flag of a change in the number of Sell orders exceeding the increase value
bool m_is_change_session_sell_ord_dec; // Flag of a change in the number of Sell orders exceeding the decrease value
//--- Volume of the last deal
long m_control_volume_inc; // Controlled value of the volume increase in the last deal
long m_control_volume_dec; // Controlled value of the volume decrease in the last deal
long m_changed_volume_value; // Value of the volume change in the last deal
bool m_is_change_volume_inc; // Flag of the volume change in the last deal exceeding the increase value
bool m_is_change_volume_dec; // Flag of the volume change in the last deal being less than the increase value
//--- Maximum volume within a day
long m_control_volume_high_day_inc; // Controlled value of the maximum volume increase for a day
long m_control_volume_high_day_dec; // Controlled value of the maximum volume decrease for a day
long m_changed_volume_high_day_value; // Maximum volume change value within a day
bool m_is_change_volume_high_day_inc; // Flag of the maximum day volume exceeding the increase value
bool m_is_change_volume_high_day_dec; // Flag of the maximum day volume exceeding the decrease value
//--- Minimum volume within a day
long m_control_volume_low_day_inc; // Controlled value of the minimum volume increase for a day
long m_control_volume_low_day_dec; // Controlled value of the minimum volume decrease for a day
long m_changed_volume_low_day_value; // Minimum volume change value within a day
bool m_is_change_volume_low_day_inc; // Flag of the minimum day volume exceeding the increase value
bool m_is_change_volume_low_day_dec; // Flag of the minimum day volume exceeding the decrease value
//--- Spread
int m_control_spread_inc; // Controlled spread increase value in points
int m_control_spread_dec; // Controlled spread decrease value in points
int m_changed_spread_value; // Spread change value in points
bool m_is_change_spread_inc; // Flag of spread change in points exceeding the increase value
bool m_is_change_spread_dec; // Flag of spread change in points exceeding the decrease value
//--- StopLevel
int m_control_stops_level_inc; // Controlled StopLevel increase value in points
int m_control_stops_level_dec; // Controlled StopLevel decrease value in points
int m_changed_stops_level_value; // StopLevel change value in points
bool m_is_change_stops_level_inc; // Flag of StopLevel change in points exceeding the increase value
bool m_is_change_stops_level_dec; // Flag of StopLevel change in points exceeding the decrease value
//--- Freeze distance
int m_control_freeze_level_inc; // Controlled FreezeLevel increase value in points
int m_control_freeze_level_dec; // Controlled FreezeLevel decrease value in points
int m_changed_freeze_level_value; // FreezeLevel change value in points
bool m_is_change_freeze_level_inc; // Flag of FreezeLevel change in points exceeding the increase value
bool m_is_change_freeze_level_dec; // Flag of FreezeLevel change in points exceeding the decrease value
//--- Bid/Last
double m_control_bid_last_inc; // Controlled value of Bid or Last price increase
double m_control_bid_last_dec; // Controlled value of Bid or Last price decrease
double m_changed_bid_last_value; // Bid or Last price change value
bool m_is_change_bid_last_inc; // Flag of Bid or Last price change exceeding the increase value
bool m_is_change_bid_last_dec; // Flag of Bid or Last price change exceeding the decrease value
//--- Maximum Bid/Last of the day
double m_control_bid_last_high_inc; // Controlled increase value of the maximum Bid or Last price of the day
double m_control_bid_last_high_dec; // Controlled decrease value of the maximum Bid or Last price of the day
double m_changed_bid_last_high_value; // Maximum Bid or Last change value for the day
bool m_is_change_bid_last_high_inc; // Flag of the maximum Bid or Last price change for the day exceeding the increase value
bool m_is_change_bid_last_high_dec; // Flag of the maximum Bid or Last price change for the day exceeding the decrease value
//--- Minimum Bid/Last of the day
double m_control_bid_last_low_inc; // Controlled increase value of the minimum Bid or Last price of the day
double m_control_bid_last_low_dec; // Controlled decrease value of the minimum Bid or Last price of the day
double m_changed_bid_last_low_value; // Minimum Bid or Last change value for the day
bool m_is_change_bid_last_low_inc; // Flag of the minimum Bid or Last price change for the day exceeding the increase value
bool m_is_change_bid_last_low_dec; // Flag of the minimum Bid or Last price change for the day exceeding the decrease value
//--- Ask
double m_control_ask_inc; // Controlled value of the Ask price increase
double m_control_ask_dec; // Controlled value of the Ask price decrease
double m_changed_ask_value; // Ask price change value
bool m_is_change_ask_inc; // Flag of the Ask price change exceeding the increase value
bool m_is_change_ask_dec; // Flag of the Ask price change exceeding the decrease value
//--- Maximum Ask price for the day
double m_control_ask_high_inc; // Controlled increase value of the maximum Ask price of the day
double m_control_ask_high_dec; // Controlled decrease value of the maximum Ask price of the day
double m_changed_ask_high_value; // Maximum Ask price change value for the day
bool m_is_change_ask_high_inc; // Flag of the maximum Ask price change for the day exceeding the increase value
bool m_is_change_ask_high_dec; // Flag of the maximum Ask price change for the day exceeding the decrease value
//--- Minimum Ask price for the day
double m_control_ask_low_inc; // Controlled increase value of the minimum Ask price of the day
double m_control_ask_low_dec; // Controlled decrease value of the minimum Ask price of the day
double m_changed_ask_low_value; // Minimum Ask price change value for the day
bool m_is_change_ask_low_inc; // Flag of the minimum Ask price change for the day exceeding the increase value
bool m_is_change_ask_low_dec; // Flag of the minimum Ask price change for the day exceeding the decrease value
//--- Real Volume for the day
double m_control_volume_real_inc; // Controlled value of the real volume increase of the day
double m_control_volume_real_dec; // Controlled value of the real volume decrease of the day
double m_changed_volume_real_value; // Real volume change value of the day
bool m_is_change_volume_real_inc; // Flag of the real volume change for the day exceeding the increase value
bool m_is_change_volume_real_dec; // Flag of the real volume change for the day exceeding the decrease value
//--- Maximum real volume for the day
double m_control_volume_high_real_day_inc; // Controlled value of the maximum real volume increase of the day
double m_control_volume_high_real_day_dec; // Controlled value of the maximum real volume decrease of the day
double m_changed_volume_high_real_day_value; // Maximum real volume change value of the day
bool m_is_change_volume_high_real_day_inc; // Flag of the maximum real volume change for the day exceeding the increase value
bool m_is_change_volume_high_real_day_dec; // Flag of the maximum real volume change for the day exceeding the decrease value
//--- Minimum real volume for the day
double m_control_volume_low_real_day_inc; // Controlled value of the minimum real volume increase of the day
double m_control_volume_low_real_day_dec; // Controlled value of the minimum real volume decrease of the day
double m_changed_volume_low_real_day_value; // Minimum real volume change value of the day
bool m_is_change_volume_low_real_day_inc; // Flag of the minimum real volume change for the day exceeding the increase value
bool m_is_change_volume_low_real_day_dec; // Flag of the minimum real volume change for the day exceeding the decrease value
//--- Strike price
double m_control_option_strike_inc; // Controlled value of the strike price increase
double m_control_option_strike_dec; // Controlled value of the strike price decrease
double m_changed_option_strike_value; // Strike price change value
bool m_is_change_option_strike_inc; // Flag of the strike price change exceeding the increase value
bool m_is_change_option_strike_dec; // Flag of the strike price change exceeding the decrease value
//--- Total volume of positions and orders
double m_changed_volume_limit_value; // Minimum total volume change value
bool m_is_change_volume_limit_inc; // Flag of the minimum total volume increase
bool m_is_change_volume_limit_dec; // Flag of the minimum total volume decrease
//--- Swap long
double m_changed_swap_long_value; // Swap long change value
bool m_is_change_swap_long_inc; // Flag of the swap long increase
bool m_is_change_swap_long_dec; // Flag of the swap long decrease
//--- Swap short
double m_changed_swap_short_value; // Swap short change value
bool m_is_change_swap_short_inc; // Flag of the swap short increase
bool m_is_change_swap_short_dec; // Flag of the swap short decrease
//--- The total volume of deals in the current session
double m_control_session_volume_inc; // Controlled value of the total trade volume increase in the current session
double m_control_session_volume_dec; // Controlled value of the total trade volume decrease in the current session
double m_changed_session_volume_value; // The total deal volume change value in the current session
bool m_is_change_session_volume_inc; // Flag of total trade volume change in the current session exceeding the increase value
bool m_is_change_session_volume_dec; // Flag of total trade volume change in the current session exceeding the decrease value
//--- The total turnover in the current session
double m_control_session_turnover_inc; // Controlled value of the total turnover increase in the current session
double m_control_session_turnover_dec; // Controlled value of the total turnover decrease in the current session
double m_changed_session_turnover_value; // Total turnover change value in the current session
bool m_is_change_session_turnover_inc; // Flag of total turnover change in the current session exceeding the increase value
bool m_is_change_session_turnover_dec; // Flag of total turnover change in the current session exceeding the decrease value
//--- The total volume of open positions
double m_control_session_interest_inc; // Controlled value of the total open position volume increase in the current session
double m_control_session_interest_dec; // Controlled value of the total open position volume decrease in the current session
double m_changed_session_interest_value; // Change value of the open positions total volume in the current session
bool m_is_change_session_interest_inc; // Flag of total open positions' volume change in the current session exceeding the increase value
bool m_is_change_session_interest_dec; // Flag of total open positions' volume change in the current session exceeding the decrease value
//--- The total volume of Buy orders at the moment
double m_control_session_buy_ord_volume_inc; // Controlled value of the current total buy order volume increase
double m_control_session_buy_ord_volume_dec; // Controlled value of the current total buy order volume decrease
double m_changed_session_buy_ord_volume_value; // Change value of the current total buy order volume
bool m_is_change_session_buy_ord_volume_inc; // Flag of changing the current total buy orders volume exceeding the increase value
bool m_is_change_session_buy_ord_volume_dec; // Flag of changing the current total buy orders volume exceeding the decrease value
//--- The total volume of Sell orders at the moment
double m_control_session_sell_ord_volume_inc; // Controlled value of the current total sell order volume increase
double m_control_session_sell_ord_volume_dec; // Controlled value of the current total sell order volume decrease
double m_changed_session_sell_ord_volume_value; // Change value of the current total sell order volume
bool m_is_change_session_sell_ord_volume_inc; // Flag of changing the current total sell orders volume exceeding the increase value
bool m_is_change_session_sell_ord_volume_dec; // Flag of changing the current total sell orders volume exceeding the decrease value
//--- Session open price
double m_control_session_open_inc; // Controlled value of the session open price increase
double m_control_session_open_dec; // Controlled value of the session open price decrease
double m_changed_session_open_value; // Session open price change value
bool m_is_change_session_open_inc; // Flag of the session open price change exceeding the increase value
bool m_is_change_session_open_dec; // Flag of the session open price change exceeding the decrease value
//--- Session close price
double m_control_session_close_inc; // Controlled value of the session close price increase
double m_control_session_close_dec; // Controlled value of the session close price decrease
double m_changed_session_close_value; // Session close price change value
bool m_is_change_session_close_inc; // Flag of the session close price change exceeding the increase value
bool m_is_change_session_close_dec; // Flag of the session close price change exceeding the decrease value
//--- The average weighted session price
double m_control_session_aw_inc; // Controlled value of the average weighted session price increase
double m_control_session_aw_dec; // Controlled value of the average weighted session price decrease
double m_changed_session_aw_value; // The average weighted session price change value
bool m_is_change_session_aw_inc; // Flag of the average weighted session price change value exceeding the increase value
bool m_is_change_session_aw_dec; // Flag of the average weighted session price change value exceeding the decrease value
Removemos os métodos realçados, por serem desnecessários:
//--- Initialize the variables of (1) tracked, (2) controlled symbol data virtual void InitChangesParams(void); virtual void InitControlsParams(void); //--- Check symbol changes, return a change code virtual int SetEventCode(void); //--- Set an event type and fill in the event list virtual void SetTypeEvent(void); //--- Return description of symbol events string EventDescription(const ENUM_SYMBOL_EVENT event);
Em vez do método virtual para definir o código que altera as propriedades do símbolo, declaramos
um método para verificar alterações nas propriedades do símbolo e para criar um evento:
//--- Initialize the variables of controlled symbol data virtual void InitControlsParams(void); //--- Check the list of symbol property changes and create an event void CheckEvents(void);
Na seção pública da classe, inserimos as declarações dos métodos que estabelecem os valores monitorados e que retornam os valores de
controle estabelecidos das propriedades controladas, os valores da alteração nas propriedades e os sinalizadores:
public: //--- Set the change value of the controlled symbol property template<typename T> void SetControlChangedValue(const int property,const T value); //--- Set the value of the controlled symbol property (1) increase, (2) decrease and (3) control level 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); //--- Set the flag of a symbol property change exceeding the (1) increase and (2) decrease values template<typename T> void SetControlFlagINC(const int property,const T value); template<typename T> void SetControlFlagDEC(const int property,const T value); //--- Return the set value of the (1) integer and (2) real symbol property controlled increase 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); } //--- Return the set value of the (1) integer and (2) real symbol property controlled decrease 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); } //--- Return the flag of an (1) integer and (2) real symbol property value change exceeding the increase value 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); } //--- Return the flag of an (1) integer and (2) real symbol property value change exceeding the decrease value 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); } //--- Return the change value of the controlled (1) integer and (2) real object property 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); } //+------------------------------------------------------------------+
Cada método é feito como dois métodos sobrecarregados que chamam os métodos do objeto base correspondentes ao tipo da propriedade
definida/verificada do objeto-símbolo.
Anteriormente, escrevemos métodos de acesso simplificado a algumas propriedades do objeto-símbolo. Vamos adicionar ai métodos para definir níveis de controle de valores de propriedade e declarar métodos de definição/obtenção para Bid/Last e parâmetros relacionados (anteriormente, era selecionado automaticamente Bid ou Last, dependendo dos preços do gráfico. Agora precisamos criar métodos para trabalhar com esses dados):
//+------------------------------------------------------------------+ //| Get and set the parameters of tracked property changes | //+------------------------------------------------------------------+ //--- Execution //--- Flag of changing the trading mode for a symbol bool IsChangedTradeMode(void) const { return this.m_is_change_trade_mode; } //--- Current session deals //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the number of deals during the current session //--- getting (3) the number of deals change value during the current session, //--- getting the flag of the number of deals change during the current session exceeding the (4) increase, (5) decrease value 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 orders of the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current number of Buy orders //--- getting (4) the current number of Buy orders change value, //--- getting the flag of the current Buy orders' number change exceeding the (5) growth, (6) decrease value 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 orders of the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current number of Sell orders //--- getting (4) the current number of Sell orders change value, //--- getting the flag of the current Sell orders' number change exceeding the (5) growth, (6) decrease value 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); } //--- Volume of the last deal //--- setting the last deal volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) volume change values in the last deal, //--- getting the flag of the volume change in the last deal exceeding the (5) growth, (6) decrease value 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); } //--- Maximum volume within a day //--- setting the maximum day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the maximum volume change value within a day, //--- getting the flag of the maximum day volume change exceeding the (5) growth, (6) decrease value 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); } //--- Minimum volume within a day //--- setting the minimum day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the minimum volume change value within a day, //--- getting the flag of the minimum day volume change exceeding the (5) growth, (6) decrease value 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); } //--- Spread //--- setting the controlled spread (1) increase, (2) decrease value and (3) control level in points //--- getting (4) spread change value in points, //--- getting the flag of the spread change in points exceeding the (5) growth, (6) decrease value 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 //--- setting the controlled StopLevel (1) increase, (2) decrease value and (3) control level in points //--- getting (4) StopLevel change value in points, //--- getting the flag of StopLevel change in points exceeding the (5) growth, (6) decrease value 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); } //--- Freeze distance //--- setting the controlled FreezeLevel (1) increase, (2) decrease value and (3) control level in points //--- getting (4) FreezeLevel change value in points, //--- getting the flag of FreezeLevel change in points exceeding the (5) growth, (6) decrease value 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 //--- setting the controlled Bid price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (5) growth, (6) decrease value 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); } //--- The highest Bid price of the day //--- setting the controlled maximum Bid price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (5) growth, (6) decrease value 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); } //--- The lowest Bid price of the day //--- setting the controlled minimum Bid price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (5) growth, (6) decrease value 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 //--- setting the controlled Last price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (5) growth, (6) decrease value 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); } //--- The highest Last price of the day //--- setting the controlled maximum Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (5) growth, (6) decrease value 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); } //--- The lowest Last price of the day //--- setting the controlled minimum Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (5) growth, (6) decrease value 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 //--- setting the controlled Bid or Last price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (5) growth, (6) decrease value 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; //--- Maximum Bid/Last of the day //--- setting the controlled maximum Bid or Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (5) growth, (6) decrease value 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; //--- Minimum Bid/Last of the day //--- setting the controlled minimum Bid or Last price (1) increase, (2) decrease value and (3) control level in points //--- getting the (4) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (5) growth, (6) decrease value 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 //--- setting the controlled Ask price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) Ask price change value, //--- getting the flag of the Ask price change exceeding the (5) growth, (6) decrease value 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); } //--- Maximum Ask price for the day //--- setting the maximum day Ask controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the maximum Ask change value within a day, //--- getting the flag of the maximum day Ask change exceeding the (5) growth, (6) decrease value 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); } //--- Minimum Ask price for the day //--- setting the minimum day Ask controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the minimum Ask change value within a day, //--- getting the flag of the minimum day Ask change exceeding the (5) growth, (6) decrease value 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); } //--- Real Volume for the day //--- setting the real day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the change value of the real day volume, //--- getting the flag of the real day volume change exceeding the (5) growth, (6) decrease value 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); } //--- Maximum real volume for the day //--- setting the maximum real day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the change value of the maximum real day volume, //--- getting the flag of the maximum real day volume change exceeding the (5) growth, (6) decrease value 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); } //--- Minimum real volume for the day //--- setting the minimum real day volume controlled (1) increase, (2) decrease and (3) control level //--- getting (4) the change value of the minimum real day volume, //--- getting the flag of the minimum real day volume change exceeding the (5) growth, (6) decrease value 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); } //--- Strike price //--- setting the controlled strike price (1) increase, (2) decrease value and (3) control level in points //--- getting (4) the change value of the strike price, //--- getting the flag of the strike price change exceeding the (5) growth, (6) decrease value 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); } //--- Maximum allowed total volume of unidirectional positions and orders //--- (1) Setting the control level //--- (2) getting the change value of the maximum allowed total volume of unidirectional positions and orders, //--- getting the flag of (3) increasing, (4) decreasing the maximum allowed total volume of unidirectional positions and orders 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); } //--- Swap long //--- (1) Setting the control level //--- (2) getting the swap long change value, //--- getting the flag of (3) increasing, (4) decreasing the swap long 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); } //--- Swap short //--- (1) Setting the control level //--- (2) getting the swap short change value, //--- getting the flag of (3) increasing, (4) decreasing the swap short 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); } //--- The total volume of deals in the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the total volume of deals during the current session //--- getting (4) the total deal volume change value in the current session, //--- getting the flag of the total deal volume change during the current session exceeding the (5) growth, (6) decrease value 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); } //--- The total turnover in the current session //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the total turnover during the current session //--- getting (4) the total turnover change value in the current session, //--- getting the flag of the total turnover change during the current session exceeding the (5) growth, (6) decrease value 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); } //--- The total volume of open positions //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the total volume of open positions during the current session //--- getting (4) the change value of the open positions total volume in the current session, //--- getting the flag of the open positions total volume change during the current session exceeding the (5) growth, (6) decrease value 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); } //--- The total volume of Buy orders at the moment //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current total buy order volume //--- getting (4) the change value of the current total buy order volume, //--- getting the flag of the current total buy orders' volume change exceeding the (5) growth, (6) decrease value 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); } //--- The total volume of Sell orders at the moment //--- setting the controlled value of (1) growth, (2) decrease and (3) control level of the current total sell order volume //--- getting (4) the change value of the current total sell order volume, //--- getting the flag of the current total sell orders' volume change exceeding the (5) growth, (6) decrease value 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); } //--- Session open price //--- setting the controlled session open price (1) increase, (2) decrease and (3) control value //--- getting (4) the change value of the session open price, //--- getting the flag of the session open price change exceeding the (5) growth, (6) decrease value 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); } //--- Session close price //--- setting the controlled session close price (1) increase, (2) decrease and (3) control value //--- getting (4) the change value of the session close price, //--- getting the flag of the session close price change exceeding the (5) growth, (6) decrease value 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); } //--- The average weighted session price //--- setting the controlled session average weighted price (1) increase, (2) decrease and (3) control value //--- getting (4) the change value of the average weighted session price, //--- getting the flag of the average weighted session price change exceeding the (5) growth, (6) decrease value 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); } //---
Vejamos a implementação de métodos declarados e de alterações nos existentes.
Faremos pequenas alterações no construtor da classe:
//+------------------------------------------------------------------+ //| Closed parametric constructor | //+------------------------------------------------------------------+ 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. 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 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); } //--- Initialize control data this.SetControlDataArraySizeLong(SYMBOL_PROP_INTEGER_TOTAL); this.SetControlDataArraySizeDouble(SYMBOL_PROP_DOUBLE_TOTAL); this.ResetChangesParams(); this.ResetControlsParams(); //--- Initialize symbol data 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 //--- Save integer properties 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(); //--- Save real properties 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; //--- Save string properties 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(); //--- Save additional integer properties this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); //--- if(!select) this.RemoveFromMarketWatch(); } //+------------------------------------------------------------------------------------------------------------+ //|Compare CSymbol objects by all possible properties (for sorting lists by a specified symbol object property)| //+------------------------------------------------------------------------------------------------------------+
Para identificar com precisão eventos de objetos na classe de objeto base, atribuímos o identificador de coleção de símbolos ao tipo de objeto-símbolo e definimos tamanhos de arrays inteiras e de dados reais para rastrear eventos nas propriedades do objeto-símbolo pelo objeto pai. Em seguida, inicializamos os parâmetros mutáveis e de controle em arrays de propriedades inteiras e reais.
Também foi alterado o método Refresh() do objeto-símbolo:
//+------------------------------------------------------------------+ //| Update all symbol data | //+------------------------------------------------------------------+ void CSymbol::Refresh(void) { //--- Update quote data if(!this.RefreshRates()) return; #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); return; } #endif //--- Initialize event data this.m_is_event=false; this.m_hash_sum=0; //--- Update integer properties 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(); //--- Update real properties 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; //--- Fill in the symbol current data 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(); } //+------------------------------------------------------------------+
Neste caso, como nos livramos da necessidade de criar estruturas para armazenar os estados atuais e anteriores das propriedades do símbolo,
aqui foi excluído o preenchimento da estrutura de dados do estado atual do símbolo e, em vez disso, realizamos o
preenchimento de arrays de propriedades inteiras e reais
no objeto base.
Em seguida, quando os arrays estiverem preenchidos, precisamos chamar
o método Refresh() do
objeto base CBaseObj, no qual são procuradas as alterações
ocorridas e é criada uma lista de eventos básicos do objeto herdeiro.
Depois que a lista de na classe pai é criada (se houver critérios para gerar eventos), nós verificamos
eventos básicos usando o método CheckEvents() e, se houver, criamos uma lista de eventos de símbolos.
Implementando o método de verificação de eventos:
//+------------------------------------------------------------------+ //| Check the list of symbol property changes and create an event | //+------------------------------------------------------------------+ 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; } } //+------------------------------------------------------------------+
Neste caso, se a lista de eventos básicos estiver vazia ,
saímos.
No ciclo da lista de eventos básicos obtemos
o próximo evento e, se o evento for recebido, criamos um evento de símbolo:
- obtemos apenas milissegundos a partir da hora atual em milissegundos e adicionamo-los nos primeiros dois bytes do parâmetro long do evento
- obtemos o motivo do evento (aumento/diminuição/acima/abaixo do nível) e adicionamo-lo nos segundos dois bytes do parâmetro lon do evento
- adicionamos o identificador da coleção de símbolos nos terceiros dois bytes do parâmetro long do evento
- adicionamos um evento de símbolo à lista de eventos de símbolo e definimos o sinalizador de presença de evento no símbolo
Método para inicializar as variáveis dos dados controlados do símbolo:
//+------------------------------------------------------------------+ //| Initialize the variables of controlled symbol data | //+------------------------------------------------------------------+ void CSymbol::InitControlsParams(void) { this.ResetControlsParams(); } //+------------------------------------------------------------------+
Simplesmente chama o método para redefinir as variáveis de valores controlados dos dados do objeto, que consideramos acima.
Métodos para definir valores controlados e sinalizadores das alterações ocorridas e métodos para obter o tamanho das alterações
ocorridas e sinalizadores:
//+------------------------------------------------------------------+ //| Set the value of the controlled property increase | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Set the value of the controlled property decrease | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Set the value of the controlled property level | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Set the flag of the symbol property value change | //| exceeding the increase 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); } //+------------------------------------------------------------------+ //| Set the flag of the symbol property value change | //| exceeding the decrease 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); } //+------------------------------------------------------------------+ //| Set the change value of the controlled symbol property | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Set the Bid or Last price controlled increase | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //|Set the Bid or Last price controlled decrease | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the Bid or Last price control level | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLevel(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BID : SYMBOL_PROP_LAST),::fabs(value)); } //+------------------------------------------------------------------+ //| Return the Bid or Last price change value | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BID) : this.GetControlChangedValue(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Return the flag of the Bid or Last price change | //| exceeding the increase value | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BID) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Return the flag of the Bid or Last price change | //| exceeding the decrease value | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BID) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Set the controlled increase value | //| of the maximum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the controlled decrease value | //| of the maximum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the maximum Bid or Last price control level | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastHighLevel(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDHIGH : SYMBOL_PROP_LASTHIGH),::fabs(value)); } //+------------------------------------------------------------------+ //| Return the maximum Bid or Last price change value | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BIDHIGH) : this.GetControlChangedValue(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the maximum | //| Bid or Last price exceeding the increase value | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDHIGH) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the maximum | //| Bid or Last price exceeding the decrease value | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDHIGH) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Set the controlled increase value | //| of the minimum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowInc(const double value) { this.SetControlPropertyINC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the controlled decrease value | //| of the minimum Bid or Last price | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowDec(const double value) { this.SetControlPropertyDEC((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Set the minimum Bid or Last price control level | //+------------------------------------------------------------------+ void CSymbol::SetControlBidLastLowLevev(const double value) { this.SetControlPropertyLEVEL((this.ChartMode()==SYMBOL_CHART_MODE_BID ? SYMBOL_PROP_BIDLOW : SYMBOL_PROP_LASTLOW),::fabs(value)); } //+------------------------------------------------------------------+ //| Return the minimum Bid or Last price change value | //+------------------------------------------------------------------+ double CSymbol::GetValueChangedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetControlChangedValue(SYMBOL_PROP_BIDLOW) : this.GetControlChangedValue(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the minimum | //| Bid or Last price exceeding the increase value | //+------------------------------------------------------------------+ bool CSymbol::IsIncreasedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagINC(SYMBOL_PROP_BIDLOW) : (bool)this.GetControlFlagINC(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+ //| Return the flag of a change of the minimum | //| Bid or Last price exceeding the decrease value | //+------------------------------------------------------------------+ bool CSymbol::IsDecreasedBidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? (bool)this.GetControlFlagDEC(SYMBOL_PROP_BIDLOW) : (bool)this.GetControlFlagDEC(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+
Vimos métodos semelhantes ao finalizar a classe do objeto base, e os métodos que acabamos ver exatamente os que chamamos aqui dependendo da propriedade requerida do objeto-símbolo.
Assim fica concluída a modificação da classe do objeto-símbolo.
Agora resta modificar ligeiramente a classe de coleção de símbolos.
Abrimos o arquivo
\MQL5\Include\DoEasy\Collections\
SymbolsCollection.mqh e fazemos as alterações necessárias:
Como não precisamos mais criar enumerações de eventos separadas para cada objeto, definimos o tipo 'int' para a variável "último evento do símbolo" e o método GetLastEvent() em vez do método anterior ENUM_SYMBOL_EVENT:
int m_last_event; // The last event
int GetLastEvent(void) const { return this.m_last_event; }
Como todos os eventos do símbolo (assim como os eventos de qualquer objeto herdeiro) agora são manipulados na classe do objeto base,
renomeamos
o método EventDescription() para
EventMWDescription() e transferimos a variável com o tipo
de enumeração dos eventos da janela Observação do Mercado para o método:
//--- Return the description of the (1) Market Watch window event, (2) mode of working with symbols string EventMWDescription(const ENUM_MW_EVENT event); string ModeSymbolsListDescription(void);
Como os nomes da enumeração foram alterados,
o método para trabalhar com a janela Observação do Mercado passou por
pequenas alterações (os
nomes da enumeração e o tipo
de variável de evento foram alterados):
//+------------------------------------------------------------------+ //| Working with market watch window events | //+------------------------------------------------------------------+ void CSymbolsCollection::MarketWatchEventsControl(const bool send_events=true) { ::ResetLastError(); //--- If no current prices are received, exit if(!::SymbolInfoTick(::Symbol(),this.m_tick)) { this.m_global_error=::GetLastError(); return; } uchar array[]; int sum=0; this.m_hash_sum=0; //--- Calculate the hash sum of all visible symbols in the Market Watch window this.m_total_symbols=this.SymbolsTotalVisible(); //--- In the loop by all Market Watch window symbols int total_symbols=::SymbolsTotal(true); for(int i=0;i<total_symbols;i++) { //--- get a symbol name by index string name=::SymbolName(i,true); //--- skip if invisible if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- write symbol name (characters) codes to the uchar array ::StringToCharArray(name,array); //--- in a loop by the resulting array, sum up the values of all array cells creating the symbol code for(int j=::ArraySize(array)-1;j>WRONG_VALUE;j--) sum+=array[j]; //--- add the symbol code and the loop index specifying the symbol index in the market watch list to the hash sum m_hash_sum+=i+sum; } //--- If sending events is disabled, create the collection list and exit saving the current hash some as the previous one if(!send_events) { //--- Clear the list this.m_list_all_symbols.Clear(); //--- Clear the collection list this.CreateSymbolsList(true); //--- Clear the market watch window snapshot this.CopySymbolsNames(); //--- save the current hash some as the previous one this.m_hash_sum_prev=this.m_hash_sum; //--- save the current number of visible symbols as the previous one this.m_total_symbol_prev=this.m_total_symbols; return; } //--- If the hash sum of symbols in the Market Watch window has changed if(this.m_hash_sum!=this.m_hash_sum_prev) { //--- Define the Market Watch window event 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) ); //--- Adding a symbol to the Market Watch window if(event_id==MARKET_WATCH_EVENT_SYMBOL_ADD) { string name=""; //--- In the loop by all Market Watch window symbols int total=::SymbolsTotal(true), index=WRONG_VALUE; for(int i=0;i<total;i++) { //--- get the symbol name and check its "visibility". Skip it if invisible name=::SymbolName(i,true); if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- If there is no symbol in the collection symbol list yet if(!this.IsPresentSymbolInList(name)) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- recreate the collection list this.CreateSymbolsList(true); //--- create the symbol collection snapshot this.CopySymbolsNames(); //--- get a new symbol index in the Market Watch window index=this.GetSymbolIndexByName(name); //--- If the "Adding a new symbol" event is successfully added to the event list if(this.EventAdd(event_id,this.TickTime(),index,name)) { //--- send the event to the chart: //--- long value = event time in milliseconds, double value = symbol index, string value = added symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,name); } } } //--- Save the new number of visible symbols in the market watch window this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Remove a symbol from the Market Watch window else if(event_id==MARKET_WATCH_EVENT_SYMBOL_DEL) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- recreate the collection list this.CreateSymbolsList(true); //--- In a loop by the market watch window snapshot int total=this.m_list_names.Total(); for(int i=0; i<total;i++) { //--- get a symbol name string name=this.m_list_names.At(i); if(name==NULL) continue; //--- if no symbol with such a name exists in the collection symbol list if(!this.IsPresentSymbolInList(name)) { //--- If the "Removing a symbol" event is successfully added to the event list if(this.EventAdd(event_id,this.TickTime(),WRONG_VALUE,name)) { //--- send the event to the chart: //--- long value = event tine in milliseconds, double value = -1 for an absent symbol, string value = a removed symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),WRONG_VALUE,name); } } } //--- Recreate the market watch snapshot this.CopySymbolsNames(); //--- Save the new number of visible symbols in the market watch window this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Sorting symbols in the Market Watch window else if(event_id==MARKET_WATCH_EVENT_SYMBOL_SORT) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- set sorting of the collection list as sorting by index this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_INDEX_MW); //--- recreate the collection list this.CreateSymbolsList(true); //--- get the current symbol index in the Market Watch window int index=this.GetSymbolIndexByName(Symbol()); //--- send the event to the chart: //--- long value = event time in milliseconds, double value = current symbol index, string value = current symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,::Symbol()); } //--- save the current number of visible symbols as the previous one this.m_total_symbol_prev=this.m_total_symbols; //--- save the current hash some as the previous one this.m_hash_sum_prev=this.m_hash_sum; } } //+------------------------------------------------------------------+
O tipo de variável de evento também foi alterado no
método para trabalhar com a lista de eventos da coleção de símbolos:
//+------------------------------------------------------------------+ //| Working with the events of the collection symbol list | //+------------------------------------------------------------------+ void CSymbolsCollection::SymbolsEventsControl(void) { this.m_is_event=false; this.m_list_events.Clear(); this.m_list_events.Sort(); //--- The full update of all collection symbols 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()); } } } } //+------------------------------------------------------------------+
No método que retorna uma descrição de string do evento da janela Observação do Mercado, também foram alterados
os nomes de constantes de enumeração de eventos:
//+------------------------------------------------------------------+ //| Return the Market Watch window event description | //+------------------------------------------------------------------+ string CSymbolsCollection::EventMWDescription(const ENUM_MW_EVENT event) { return ( event==MARKET_WATCH_EVENT_SYMBOL_ADD ? TextByLanguage("В окно \"Обзор рынка\" добавлен символ","Added symbol to \"Market Watch\" window") : event==MARKET_WATCH_EVENT_SYMBOL_DEL ? TextByLanguage("Из окна \"Обзор рынка\" удалён символ","Removed symbol from \"Market Watch\" window") : event==MARKET_WATCH_EVENT_SYMBOL_SORT ? TextByLanguage("Изменено расположение символов в окне \"Обзор рынка\"","Changed arrangement of symbols in \"Market Watch\" window") : EnumToString(event) ); } //+------------------------------------------------------------------+
Agora modificamos a classe CEngine. Abrimos o arquivo \MQL5\Include\DoEasy\Engine.mqh e fazemos as alterações necessárias:
A variável que armazena o último evento nas propriedades do símbolo e o método que retorna o valor da variável também serão do tipo int:
int m_last_symbol_event; // Last event in the symbol properties
int LastSymbolsEvent(void) const { return this.m_last_symbol_event; }
Na seção pública da classe, adicionamos a declaração do método que recupera um número ushort do contêiner long segundo o índice de armazenamento especificado no parâmetro long do número ushort:
//--- Retrieve a necessary 'ushort' number from the packed 'long' value ushort LongToUshortFromByte(const long source_value,const uchar index) const;
Além disso, escrevemos os três métodos retornando imediatamente milissegundos de evento, motivo e origem do parâmetro long do evento:
//--- Return event (1) milliseconds, (2) reason and (3) source from its 'long' value 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); }
Como o valor zero é a primeira propriedade inteira de qualquer objeto, na lista de inicialização do seu construtor da classe alteramos
o valor de inicialização da variável que armazena o último evento do símbolo,
assim, agora ele será inicializado com um valor negativo:
//+------------------------------------------------------------------+ //| CEngine constructor | //+------------------------------------------------------------------+ 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) {
Implementação do método de recuperação de um número ushort do contêiner long pelo índice de bytes de sua localização no contêiner long:
//+------------------------------------------------------------------+ //| Retrieve a necessary 'ushort' number from the packed 'long' value| //+------------------------------------------------------------------+ ushort CEngine::LongToUshortFromByte(const long source_value,const uchar index) const { if(index>3) { ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. \"index\" value should be between 0 - 3")); return 0; } long res=source_value>>(16*index); return ushort(res &=0xFFFF); } //+------------------------------------------------------------------+
O método recebe um valor long do qual deve ser extraído um número de ushort
e o índice de bytes em que está localizado o número (a
tabela de localização dos números de ushort no contêiner long foi considerada acima). Em seguida,
é verificada a validade da especificação do índice. Se o
índice for inválido, será exibida uma mensagem de erro e
será retornado 0.
Em seguida, deslocamos
os bits de número long 16 * bits de índice para a direita, aplicamos uma
máscara para "extinguir" os bits maiores restantes e retornamos o número
ushort extraído dessa maneira.
Para trabalhar em MQL4, precisamos informar o compilador sobre o erro de tamanho zero do array ERR_ZEROSIZE_ARRAY.
O erro mais adequado para o tamanho zero do array daqueles conhecidos pelo compilador MQL4 é "array inválido". Vamos configurá-lo
como uma alternativa ao erro de tamanho zero do array.
Abrimos o arquivo \MQL5\Include\DoEasy\ToMQL4.mqh e fazemos as alterações necessárias:
//+------------------------------------------------------------------+ //| ToMQL4.mqh | //| Copyright 2017, Artem A. Trishkin, Skype artmedia70 | //| https://www.mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70" #property link "https://www.mql5.com/en/users/artmedia70" #property strict #ifdef __MQL4__ //+------------------------------------------------------------------+ //| Error codes | //+------------------------------------------------------------------+ #define ERR_SUCCESS (ERR_NO_ERROR) #define ERR_MARKET_UNKNOWN_SYMBOL (ERR_UNKNOWN_SYMBOL) #define ERR_ZEROSIZE_ARRAY (ERR_ARRAY_INVALID) //+------------------------------------------------------------------+
Essas são todas as alterações que precisamos fazer para começar a trabalhar com símbolos tendo em mente a nova funcionalidade de evento fornecida pelo objeto CBaseObj a todos os seus herdeiros.
Teste da funcionalidade do evento do objeto base de todos os objetos da biblioteca
Para testar a nova funcionalidade de evento, pegamos no EA do último artigo e o salvamos com o novo nome TestDoEasyPart17.mq5 na pasta MQL5\Experts\TestDoEasy\Part17.
Testaremos a variação do spread atual em 4 pontos (aumento e diminuição), além de controlar o tamanho do spread em 15 pontos. Para o preço Bid, controlaremos seu aumento/redução em +/- 10 pontos e acompanharemos o cruzamento do preço no nível de 1.13700.
Para definir os valores monitorados mencionados acima, é suficiente para este exemplo no manipulador OnInit() especificar essas strings:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Calling the function displays the list of enumeration constants in the journal //--- (the list is set in the strings 22 and 25 of the DELib.mqh file) for checking the constants validity //EnumNumbersTest(); //--- Set EA global variables 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; //--- Check if working with the full list is selected 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; } } //--- Fill in the array of used symbols used_symbols=InpUsedSymbols; CreateUsedSymbolsArray((ENUM_SYMBOLS_MODE)used_symbols_mode,used_symbols,array_used_symbols); //--- Set the type of the used symbol list in the symbol collection engine.SetUsedSymbols(array_used_symbols); //--- Displaying the selected mode of working with the symbol object collection Print(engine.ModeSymbolsListDescription(),TextByLanguage(". Количество используемых символов: ",". Number of symbols used: "),engine.GetSymbolsCollectionTotal()); //--- Set controlled values for the current symbol CSymbol* symbol=engine.GetSymbolCurrent(); if(symbol!=NULL) { //--- Set control of the current symbol price increase by 10 points symbol.SetControlBidInc(10*Point()); //--- Set control of the current symbol price decrease by 10 points symbol.SetControlBidDec(10*Point()); //--- Set control of the current symbol spread increase by 4 points symbol.SetControlSpreadInc(4); //--- Set control of the current symbol spread decrease by 4 points symbol.SetControlSpreadDec(4); //--- Set control of the current spread by the value of 15 points symbol.SetControlSpreadLevel(15); //--- Set control of the price crossing the level of 1.13700 symbol.SetControlBidLevel(1.13700); } //--- Check and remove remaining EA graphical objects if(IsPresentObects(prefix)) ObjectsDeleteAll(0,prefix); //--- Create the button panel if(!CreateButtons(InpButtShiftX,InpButtShiftY)) return INIT_FAILED; //--- Set trailing activation button status ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on); //--- Set CTrade trading class parameters #ifdef __MQL5__ trade.SetDeviationInPoints(slippage); trade.SetExpertMagicNumber(magic_number); trade.SetTypeFillingBySymbol(Symbol()); trade.SetMarginMode(); trade.LogLevel(LOG_LEVEL_NO); #endif //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Este é um exemplo de teste de configuração de parâmetros de símbolos controlados, portanto, definimos imediatamente os valores de
controle necessários em OnInit().
No entanto, nada nos impede de alterar rapidamente os valores dos símbolos controlados com base em alguns critérios atuais durante
a operação, pois todos os métodos estão presentes no objeto base. Resta obter acesso a qualquer um dos objetos herdados do CBaseObj para
obter os métodos para definir parâmetros controlados e métodos para receber parâmetros alterados, bem como alterar parâmetros
controlados de acordo com a lógica incorporada no programa - programaticamente ou da shell gráfica da biblioteca a ser criada
posteriormente.
No manipulador OnTick() do EA, removemos a variável que armazena o último
evento de símbolo. Temos outras ferramentas para rastrear eventos de símbolos, em vez de uma simples comparação dos estados
atual e anterior.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Initializing the last events 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 working in the tester if(MQLInfoInteger(MQL_TESTER)) {
Alteramos o manipulador de eventos da biblioteca em termos de manipulação de eventos da coleção de símbolos:
//+------------------------------------------------------------------+ //| Handling DoEasy library events | //+------------------------------------------------------------------+ void OnDoEasyEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { int idx=id-CHARTEVENT_CUSTOM; string event="::"+string(idx); //--- Retrieve (1) event time milliseconds, (2) reason and (3) source from lparam, as well as (4) set the exact event time ushort msc=engine.EventMSC(lparam); ushort reason=engine.EventReason(lparam); ushort source=engine.EventSource(lparam); long time=TimeCurrent()*1000+msc; //--- Handling market watch window events if(idx>MARKET_WATCH_EVENT_NO_EVENT && idx<SYMBOL_EVENTS_NEXT_CODE) { string name=""; //--- Market Watch window event string descr=engine.GetMWEventDescription((ENUM_MW_EVENT)idx); name=(idx==MARKET_WATCH_EVENT_SYMBOL_SORT ? "" : ": "+sparam); Print(TimeMSCtoString(lparam)," ",descr,name); } //--- Handling symbol events if(source==COLLECTION_SYMBOLS_ID) { CSymbol *symbol=engine.GetSymbolObjByName(sparam); if(symbol==NULL) return; //--- Number of decimal places in the event value - in case of a 'long' event, it is 0, otherwise - Digits() of a symbol int digits=(idx<SYMBOL_PROP_INTEGER_TOTAL ? 0 : symbol.Digits()); //--- Event text description string id_descr=(idx<SYMBOL_PROP_INTEGER_TOTAL ? symbol.GetPropertyDescription((ENUM_SYMBOL_PROP_INTEGER)idx) : symbol.GetPropertyDescription((ENUM_SYMBOL_PROP_DOUBLE)idx)); //--- Property change text value string value=DoubleToString(dparam,digits); //--- Check event reasons and display its description in the journal 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)); } } //--- Handling trading events 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); } //--- Handling account events else if(idx>ACCOUNT_EVENT_NO_EVENT && idx<ACCOUNT_EVENTS_NEXT_CODE) { Print(TimeMSCtoString(lparam)," ",sparam,": ",engine.GetAccountEventDescription((ENUM_ACCOUNT_EVENT)idx)); //--- if this is an equity increase if((ENUM_ACCOUNT_EVENT)idx==ACCOUNT_EVENT_EQUITY_INC) { //--- Close a position with the highest profit exceeding zero when the equity exceeds the value, //--- specified in the CAccountsCollection::InitControlsParams() method for //--- the m_control_equity_inc variable tracking the equity increase by 15 units (by default) //--- AccountCollection file, InitControlsParams() method, string 1199 //--- Get the list of all open positions CArrayObj* list_positions=engine.GetListMarketPosition(); //--- Select positions with the profit exceeding zero list_positions=CSelect::ByOrderProperty(list_positions,ORDER_PROP_PROFIT_FULL,0,MORE); if(list_positions!=NULL) { //--- Sort the list by profit considering commission and swap list_positions.Sort(SORT_BY_ORDER_PROFIT_FULL); //--- Get the position index with the highest profit int index=CSelect::FindOrderMax(list_positions,ORDER_PROP_PROFIT_FULL); if(index>WRONG_VALUE) { COrder* position=list_positions.At(index); if(position!=NULL) { //--- Get a ticket of a position with the highest profit and close the position by a ticket #ifdef __MQL5__ trade.PositionClose(position.Ticket()); #else PositionClose(position.Ticket(),position.Volume()); #endif } } } } } } //+------------------------------------------------------------------+
Todas as alterações são comentadas no código e são reduzidas apenas para obter uma descrição do evento do objeto-símbolo e enviá-lo para o log, dependendo da causa do evento. Num manipulador que não é de teste, em vez de exibir uma mensagem no log, precisamos escrever um manipulador de eventos normal.
Compilamos e iniciamos o EA no testador:
Como se pode ver, ao reduzir ou aumentar o tamanho do spread além dos valores de controle especificados, no log são exibidas as entradas sobre isso. Da mesma forma, no log são exibidas informações sobre alterações no preço Bid - aumento ou diminuição em mais de 10 pontos. E finalmente, quando o preço Bid cruza o nível de controle especificado, também é enviado um evento e no log aparece uma entrada sobre ele.
Assim, criamos um objeto básico que permite rastrear os eventos de qualquer um de seus objetos herdeiros e enviá-los ao programa de controle, em
que é possível monitorá-los e reagir a eles de acordo com a lógica estabelecida no programa, além de definir novos valores e níveis
rastreados, o que permite flexibilidade ao gerenciar a lógica do programa.
O que vem agora?
No próximo artigo, implementaremos o trabalho do objeto-conta e seus eventos com base na funcionalidade de evento da classe de objeto base
CBaseObj.
Abaixo estão anexados todos os arquivos da versão atual da biblioteca e os arquivos do EA de teste. Você pode baixá-los e testar tudo sozinho.
Se você tiver perguntas, comentários e sugestões, poderá expressá-los nos comentários do artigo.
Artigos desta série:
Parte 1. Conceito, gerenciamento de dados e primeiros resultados
Parte
2. Coleção do histórico de ordens e negócios
Parte 3. Coleção de ordens e posições de
mercado, busca e ordenação
Parte 4. Eventos de Negociação. Conceito
Parte 5. Classes e coleções de eventos de negociação. Envio de eventos para o programa
Parte
6. Eventos da conta netting
Parte 7. Eventos de ativação da ordem stoplimit,
preparação da funcionalidade para os eventos de modificação de ordens e posições
Parte
8. Eventos de modificação de ordens e posições
Parte 9. Compatibilidade com a MQL4 -
preparação dos dados
Parte 10. Compatibilidade com a MQL4 - eventos de abertura de
posição e ativação de ordens pendentes
Parte 11. Compatibilidade com a MQL4 -
eventos de encerramento de posição
Parte 12. Implementação da classe de objeto
"conta" e da coleção de objetos da conta
Parte 13. Eventos do objeto conta
Parte 14. O objeto símbolo
Parte
15. Coleção de objetos-símbolos
Parte 16. Eventos de coleção de símbolos
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/7124
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso