English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
preview
Desenvolvendo um EA de negociação do zero (Parte 20): Um novo sistema de ordens (III)

Desenvolvendo um EA de negociação do zero (Parte 20): Um novo sistema de ordens (III)

MetaTrader 5Sistemas de negociação | 20 junho 2022, 16:24
530 2
Daniel Jose
Daniel Jose

1.0 - Introdução

No artigo anterior, Desenvolvendo um EA de negociação do zero ( Parte 19), eu fiquei mais focado em mostrar as mudanças que ocorreram no código para promover o novo sistema de ordens, uma vez que aquelas mudanças foram implementadas, posso focar 100% no real problema, implementar um sistema de ordens que seja 100% visual e de fácil compreensão para quem está operando, sem a necessidade de saber quanto vale um tick ou onde devo colocar a ordem para ganhar X tanto, ou onde fica o stop para uma perda de Y.

A criação deste sistema é algo que demanda um bom domínio do MQL5, além de entender como de fato a plataforma MetaTrader 5 funciona e os recursos que ela nos fornece.


2.0 - Planejamento

2.0.1 - Desenhando os indicadores

Bem a ideia aqui, e não somente a ideia, o que vou fazer de fato é mostrar como implementar o sistema neste artigo, é criar algo que no gráfico se apresente conforme a figura abaixo:

Veja que é bem simples saber do que se trata, mesmo sem eu explicar você consegue perceber que existe um botão para fechar, um valor e um ponto para facilitar arrastar a ordem de lugar, mas não é somente isto, quando o Stop Loss passar a ser um Stop Gain o sistema irá cuidar para mostrar isto, e ficará da forma como é visto logo abaixo:

ou seja, será bem simples saber quando, quanto, onde, e se vale ou não apena segurar uma determinada posição.

As figuras acima mostram apenas os objetos dos limites das ordens OCO ou posição OCO, mas não me esqueci da parte relacionada ao preço de abertura, pois este também é igualmente importante.

No caso da ordem pendente ele terá a seguinte aparência:

Já para uma posição a aparência será ligeiramente diferente, conforme pode ser visto abaixo:

Bem as proporções não estão lá muito animadoras .... mas esta é a ideia que será implementada, a questão das cores, irei utilizar estas, mas você pode modificar elas caso assim deseje de forma a ficar mais do seu gosto.

Continuando a parte do planejamento, podemos notar que basicamente teremos 5 objetos em cada indicador, ou seja teremos que fazer o MetaTrader 5 lidar com 5 objetos ao mesmo tempo, isto para cada indicador, no caso de uma ordem pendente do tipo OCO, o MetaTrader 5 irá ter que lidar com 15 objetos, assim como no caso de uma posição OCO, o MetaTrader 5 terá que lidar com 15 objetos, e isto por ordem ou posição, ou seja se você tiver 4 ordens OCO pendentes e 1 posição aberta também OCO, o MetaTrader 5 terá que lidar com 25 objetos, fora os outros que também estarão no gráfico do ativo, e isto se você estiver utilizando apenas um único ativo na plataforma.

Digo isto pois é importante saber como será o consumo tanto de memória, quando de processamento para cada ordem que você for colocar no ativo, não que isto seja um problema para os computadores modernos, mas é preciso saber o que você estará de fato exigindo do equipamento, pois até então estávamos lidando com apenas 1 único objeto na tela isto por ponto de ordem, mas agora cada um dos pontos terá 5 objetos e estes deverão permanecer conectados de alguma forma, e quem irá fazer esta conexão será a plataforma, nos apenas iremos informa como eles devem ser conectados, e o que acontece quando um evento for disparado em cada um dos objetos.


2.0.2 - Escolhendo os objetos

A próxima questão é escolher quais os objetos que iremos usar, apesar de parecer simples, está é uma questão de suma importância, pois isto irá definir como de fato será feita a implementação, a primeira escolha será baseada na forma de posicionar os objetos na tela.

Bem para isto temos 2 tipos, ou modos de fazer isto, e felizmente o MetaTrader 5 cobre ambos: o primeiro é usando posição por coordenadas de tempo e preço, e o segundo é por meio da posição por coordenadas cartesianas de tela X e Y.

Bem, mas antes de tentar fazer qualquer tipo de aprofundamento entre um e outro, já logo descarto o modelo por coordenadas de tempo e preço, que apesar de ser a primeira vista ideal, ele não será nada útil quando estamos lidando com muitos objetos que estarão ligados e que devem permanecer juntos, então teremos que usar o sistema cartesiano.

Em um outro artigo eu já explorei este sistema e mostrei como selecionar os objetos, para mais detalhes veja Indicadores múltiplos em um gráfico (Parte 05).

Bem feito este planejamento, podemos finalmente ir para a parte da codificação em si, hora de implementar as coisas na prática.


3.0 - Implementação

Já que eu não quero simplesmente implementar um sistema, na verdade quero que vocês entendam o que esta acontecendo, para assim conseguirem também fazer o seu próprio sistema em cima deste que estou mostrando, vou mostrar as coisas aos pouco para que você entendam de fato como a coisa vai sendo criada, lembrando que tudo que vemos no caso de ordens pendentes também servirá para posições, já que o sistema segue os mesmos princípios e compartilha um código em comum.


3.0.1 - Criando a base da interface

O resultado desta primeira etapa pode ser visto abaixo, isto é minha forma de passar mel de modo que vocês se empolguem como eu fiquei ao desenvolver e decidir compartilhar estes códigos com todos vocês, espero que isto sirva de motivação para aqueles que queiram aprender programação ou em desenvolver um conhecimento mais avançado no assunto.


Olhando a imagem acima você pode estar pensando que isto foi construído de forma convencional, abandonando todo o código até aqui criado, mas não, iremos usar exatamente o que já foi construído até aqui.

Então partindo do código do artigo anterior, vamos fazer algumas modificações, como eu havia dito lá, que seria de fato necessário fazer, e vamos adicionar algumas classes, neste primeiro momento iremos adicionar 3 classes novas.


3.0.1.1 - A classe C_Object_Base

Começaremos criando uma nova classe, a C_Object_Base, está é a classe mais baixa no nosso sistema, os primeiros códigos desta classe podem ser vistos abaixo:

class C_Object_Base
{
        public  :
//+------------------------------------------------------------------+
void Create(string szObjectName, ENUM_OBJECT typeObj)
{
        ObjectCreate(Terminal.Get_ID(), szObjectName, typeObj, 0, 0, 0);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_SELECTABLE, false);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_SELECTED, false);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BACK, true);
        ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TOOLTIP, "\n");
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BACK, false);
        ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TOOLTIP, "\n");
        PositionAxleY(szObjectName, 9999);
};

// ... Restante do código da classe

notem que temos um código de criação genérico, isto irá facilitar muito a nossa vida. Seguindo dentro desta mesma classe teremos os código de posicionamento padrão nos eixos X e Y

void PositionAxleX(string szObjectName, int X)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XDISTANCE, X);
};
//+------------------------------------------------------------------+
virtual void PositionAxleY(string szObjectName, int Y)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y);
};

O código de posicionamento no eixo Y irá depender de cada objeto especifico, mas mesmo que o objeto não tenha um especifico, a classe fornece um genérico. Também temos uma forma genérica de indicar a cor do objeto, que é feito pelo código

virtual void SetColor(string szObjectName, color cor)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, cor);
}

e uma forma de definir as dimensões dos objetos

void Size(string szObjectName, int Width, int Height)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XSIZE, Width);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE, Height);
};

Desta forma teremos a classe C_Object_Base, concluída por enquanto, depois voltaremos novamente a ela.


3.0.1.2 - A classe C_Object_BackGround

Agora iremos criar outras duas classes para dar suporte aos nossos objetos gráficos, a primeira será a classe C_Object_BackGround, esta classe irá criar uma caixa de fundo para receber outros elementos, depois, bem o código dela é bem simples e pode ser visto na integra logo abaixo:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#include "C_Object_Base.mqh"
//+------------------------------------------------------------------+
class C_Object_BackGround : public C_Object_Base
{
        public:
//+------------------------------------------------------------------+
		void Create(string szObjectName, color cor)
                        {
                                C_Object_Base::Create(szObjectName, OBJ_RECTANGLE_LABEL);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, clrNONE);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BGCOLOR, cor);
                        }
//+------------------------------------------------------------------+
virtual void PositionAxleY(string szObjectName, int Y)
                        {
                                int desl = (int)(ObjectGetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE) / 2);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y - desl);
                        }
//+------------------------------------------------------------------+
};

Observem que utilizamos a herança para conseguir montar o objeto com um mínimo de código, desta forma, apenas fazemos com que a classe modifique e modele a si mesma conforme necessário, de forma que depois não precisaremos ficar fazendo estes ajustes, isto pode ser notado no código em destaque, onde a classe irá se posicionar automaticamente no local correto, bastando para isto que informemos o valor do eixo Y, ela irá verificar sua dimensão e irá se posicionar de forma a ficar no meio do eixo que estamos passando para ela.


3.0.1.3 - A Classe C_Object_TradeLine

A classe C_Object_TradeLine, é a responsável por substituir aquela linha horizontal que era utilizada antes para informa onde estava a linha de preço das ordens, esta classe é bastante curiosa, então atenção ao código da mesma, primeiramente teremos uma variável privativa estática nela, esta pode ser vista no fragmento abaixo.

#property copyright "Daniel Jose"
#include "C_Object_BackGround.mqh"
//+------------------------------------------------------------------+
class C_Object_TradeLine : public C_Object_BackGround
{
        private :
                static string m_MemNameObj;
        public  :
//+------------------------------------------------------------------+

// ... Código interno da classe

//+------------------------------------------------------------------+
};
//+------------------------------------------------------------------+
string C_Object_TradeLine::m_MemNameObj = NULL;
//+------------------------------------------------------------------+

ela esta em destaque para que você veja como ela deverá declarada e a forma correta de ser inicializada, de certa forma você poderia criar uma variável global para substituir o que está variável estática irá fazer, mas quero manter as coisas dentro do controle, então cada objeto terá aquilo que precisa, e as informações serão mantidas por eles, de forma que se eu desejar trocar um objeto por outro não terei um grande sobre trabalho para fazer isto.

Continuando a próxima coisa a ser vista é o código de criação do objeto

void Create(string szObjectName, color cor)
{
        C_Object_BackGround::Create(szObjectName, cor);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XSIZE, TerminalInfoInteger(TERMINAL_SCREEN_WIDTH));
        SpotLight(szObjectName);
};

para fazer isto de maneira adequado usamos a classe C_Object_BackGround onde de fato iremos criar uma caixa que servirá de linha, novamente isto é por conta que se fosse usado outro tipo de objeto não teremos o mesmo comportamento que iremos ter, e o único objeto que faz a coisa como é desejado, é o que esta presente na classe C_Object_Background, então iremos modificar ele de forma a ele se adaptar as nossas necessidades, e assim criar uma linha.

Depois disto vemos o código que é responsável por destacar uma linha

void SpotLight(string szObjectName = NULL)
{
        if (szObjectName != NULL) ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE, (szObjectName != NULL ? 4 : 3));
        if (m_MemNameObj != NULL) ObjectSetInteger(Terminal.Get_ID(), m_MemNameObj, OBJPROP_YSIZE, 3);
        m_MemNameObj = szObjectName;
};

agora este código é bastante interessante, já que quando destacamos uma linha não precisamos saber qual estava em destaque, o próprio objeto faz isto para nos, e quando uma nova linha merece ser destacada, automaticamente a linha que estava em destaque perde este status e a nova linha toma o seu lugar, agora caso nenhuma linha deva esta destacada, apenas fazemos a chamada da função, e ela se encarregará de retirar o destaque de qualquer linha, não importando qual seja ela.

Sabendo disto o código acima juntamente como o próximo, faz com que o antigo código de seleção possa desaparecer, desta forma o próprio MetaTrader 5 irá nos informar qual o indicador que estaremos manipulando.

string GetObjectSelected(void) const { return m_MemNameObj; }

Mas ainda falta uma rotina para ser vista, a que produz o posicionamento da linha no eixo Y, e esta rotina é vista logo abaixo

virtual void PositionAxleY(string szObjectName, int Y)
{
        int desly = (m_MemNameObj == szObjectName ? 2 : 1);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y - desly);
};

igual a rotina vista no objeto BackGround, esta também irá se auto ajustar ao ponto correto dependendo se a linha esta ou não destacada.

E desta forma temos nossos dois objetos já totalmente concluídos, mas antes que possamos de fato os ver na tela como foi mostrado antes, precisamos fazer algumas coisas na classe C_ObjectsTrade.


3.0.2 - Modificando a classe C_ObjectsTrade

As modificações a serem feitas não são muito complicadas a primeira vista, mas a quantidade de vezes que teremos que repetir o mesmo código, chega a dar um pouco de desanimo as vezes, então tentei achar uma forma de contornar isto, e a forma foi utilizando macros, mas se você achar confuso acompanhar um código cheio de macros, sinta-se a vontade de fazer a mudança de macros para funções, ou procedimentos, e em casos extremos substituindo as macros por seus devidos códigos internos, mas eu prefiro usar macros por costume de já fazer isto por muitos anos.

A primeira coisa que iremos fazer é criar uma enumeração de eventos

enum eEventType {EV_GROUND = 65, EV_LINE};

conforme os objetos vão sendo criados, novos eventos devem ser adicionados aqui, mas eles tem que ser algo relevante, mas cada objeto irá ter um único tipo de evento, e este evento será gerado pelo MetaTrader 5, nosso código apenas irá cuidar para que o evento seja corretamente tratado.

Uma vez feito isto vamos criar as variáveis que nos darão acesso a cada um dos objetos

C_Object_BackGround     m_BackGround;
C_Object_TradeLine      m_TradeLine;

estas estão no âmbito global da classe, mas são privadas, poderíamos declarar estas em cada função que de fato usa-se elas, mas isto não faz muito sentido, já que a classe inteira irá tomar conta dos objetos.

Agora de fato teremos a primeira mudança com relação ao código do artigo anterior

inline string MountName(ulong ticket, eIndicatorTrade it, eEventType ev)
{
        return StringFormat("%s%c%c%c%d%c%c", def_NameObjectsTrade, def_SeparatorInfo, (char)it, def_SeparatorInfo, ticket, def_SeparatorInfo, (char)ev);
}

Os pontos destacados não existiam antes, mas agora vão ajudar o MetaTrader 5 a nos manter informados sobre o que esta acontecendo.

E uma nova rotina apareceu

void SetPositionMinimalAxleX(void)
{
        m_PositionMinimalAlxeX = (int)(ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) * 0.2);
}

Esta irá gerar um ponto inicial no eixo X para os objetos, cada um terá um ponto especifico, mas aqui damos a eles uma referencia inicial, você pode modificar isto para mudar esta posição inicial, bastará modificar o ponto neste fragmento acima.

Já a rotina de seleção passou por um enorme mudança, mas ela irá mais para frente mudar mais um pouquinho, mas por enquanto ficará conforme visto abaixo

inline void Select(const string &sparam)
{
        ulong tick;
        double price;
        eIndicatorTrade it;
        eEventType ev;
        string sz = sparam;
                                
        if (!GetInfosOrder(sparam, tick, price, it, ev)) sz = NULL;
        m_TradeLine.SpotLight(sz);
}

Outra rotina que também sofreu mudança foi a que cria o indicador

inline void CreateIndicatorTrade(ulong ticket, double price, eIndicatorTrade it, bool select)
{
        if (price <= 0) RemoveIndicatorTrade(ticket, it); else
        {
                CreateIndicatorTrade(ticket, it, select);
                PositionAxlePrice(price, ticket, it, -1, -1, 0, false);
        }
}

mas o fragmento acima não é o principal, a que de fato faz todo o trabalho pesado é vista a seguir

inline void CreateIndicatorTrade(ulong ticket, eIndicatorTrade it)
{
        color cor1, cor2;
        string sz0;
                                
        switch (it)
        {
                case IT_TAKE    :
                        cor1 = clrPaleGreen;
                        cor2 = clrDarkGreen;
                        break;
                case IT_STOP    :
                        cor1 = clrCoral;
                        cor2 = clrMaroon;
                        break;
                case IT_PENDING:
                default:
                        cor1 = clrGold;
                        cor2 = clrDarkGoldenrod;
                        break;
        }                               
        m_TradeLine.Create(MountName(ticket, it, EV_LINE), cor2);
        if (ticket == def_IndicatorTicket0) m_TradeLine.SpotLight(MountName(ticket, IT_PENDING, EV_LINE));
        m_BackGround.Create(sz0 = MountName(ticket, it, EV_GROUND), cor1);
        switch (it)
        {
                case IT_TAKE:
                case IT_STOP:
                        m_BackGround.Size(sz0, 92, 22);
                        break;
                case IT_PENDING:
                        m_BackGround.Size(sz0, 110, 22);
                        break;
        }
}

Nesta rotina definimos as cores, e a sequencia de criação dos objetos, definimos também as dimensões dos mesmos, qualquer objeto que seja adicionado ao indicador deverá ser colocado usando esta rotina de forma a termos tudo centralizado e sempre sendo testado, se você começar a criar rotinas para criar os indicadores irá acabar criando um tipo de código difícil de ser mantido e pior, ele em alguns momentos não será testado, só sendo de fato testado quando você achar que esta tudo bem e colocar ele em uma conta real, ai irá notar tardiamente que algumas coisas não estão funcionando conforme o esperado. Então fica a dica, sempre tente reunir funções dentro de coisas que fazem o mesmo trabalho, mesmo que pareça não fazer sentido no inicio com o tempo a coisa fará sentido, já que você sempre estará testando o que esta sendo mudado.

A próxima rotina que foi modificada e que merece destaque é vista abaixo

#define macroDelete(A)  {                                                               \
                ObjectDelete(Terminal.Get_ID(), MountName(ticket, A, EV_GROUND));       \
                ObjectDelete(Terminal.Get_ID(), MountName(ticket, A, EV_LINE));         \
                        }
                                        
inline void RemoveIndicatorTrade(ulong ticket, eIndicatorTrade it = IT_NULL)
                        {
                                ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, false);
                                if ((it != NULL) && (it != IT_PENDING) && (it != IT_RESULT)) macroDelete(it)
                                else
                                {
                                        macroDelete(IT_PENDING);
                                        macroDelete(IT_RESULT);
                                        macroDelete(IT_TAKE);
                                        macroDelete(IT_STOP);
                                }
                                ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, true);
                        }
#undef macroDelete

Esta rotina igual a próxima que será vista a seguir, é um pouco chata, isto por que ela tem que trabalhar no nível de você selecionar cada um dos objetos que foram criados, um a um, e isto para cada um dos indicadores. Pense bem. Se não fosse o uso de uma macro para facilitar as coisas, a coisa irá ser um pesadelo, seria extremamente cansativo fazer a codificação desta rotina, já que cada indicador, quando o código ficar finalizado, contará com 5 objetos, e sabendo que cada conjunto em uma ordem OCO terá 3 indicadores isto nos levaria a ter que fazer um código com 15 objetos, e neste caso as chances de se cometer algum erro, já que a diferença entre eles é somente o nome, seria enorme, desta forma usando a macro o código fica reduzido ao que esta em destaque, ou seja iremos codificar apenas 5 objetos no final, mas isto daqui é a primeira fase, de forma a ter o resultado que é mostrado lá atras.

E para finalizar esta primeira fase temos uma outra rotina igualmente tediosa de ser feita se não existissem as macros, é bem verdade que poderíamos usar procedimentos no lugar das macros, mas, gosto é gosto e não se discute.

#define macroSetAxleY(A)        {                                               \
                m_BackGround.PositionAxleY(MountName(ticket, A, EV_GROUND), y); \
                m_TradeLine.PositionAxleY(MountName(ticket, A, EV_LINE), y);    \
                                }
                                                                        
#define macroSetAxleX(A, B)     {                                               \
                m_BackGround.PositionAxleX(MountName(ticket, A, EV_GROUND), B); \
                m_TradeLine.PositionAxleX(MountName(ticket, A, EV_LINE), B);    \
                                }

inline void PositionAxlePrice(double price, ulong ticket, eIndicatorTrade it, int FinanceTake, int FinanceStop, int Leverange, bool isBuy)
                        {
                                double ad;
                                int x, y;
                                
                                ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price, x, y);
                                macroSetAxleY(it);
                                macroSetAxleX(it, m_PositionMinimalAlxeX);
                                if (Leverange == 0) return;
                                if (it == IT_PENDING)
                                {
                                        ad = Terminal.GetAdjustToTrade() / (Leverange * Terminal.GetVolumeMinimal());
                                        ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price + Terminal.AdjustPrice(FinanceTake * (isBuy ? ad : (-ad))), x, y);
                                        macroSetAxleY(IT_TAKE);
                                        macroSetAxleX(IT_TAKE, m_PositionMinimalAlxeX + 120);
                                        ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price + Terminal.AdjustPrice(FinanceStop * (isBuy ? (-ad) : ad)), x, y);
                                        macroSetAxleY(IT_STOP);
                                        macroSetAxleX(IT_STOP, m_PositionMinimalAlxeX + 220);
                                }
                        }
#undef macroSetAxleX
#undef macroSetAxleY

Se você pensa que a rotina anterior era um tedio, pense nesta, aqui o trabalho seria dobrado, as graças aos códigos destacados a coisa se torna aceitável.

Bem existem outras pequenas mudanças que tiveram que ocorrer, mas elas não merecem tanto destaque assim, então quando executamos este código, obtemos exatamente o que esperamos, ou seja os indicadores começaram a surgir na tela.


4.0 - Conclusão

Agora falta pouco para o sistema ficar de fato completo, no que diz respeito ao modo de visualizar as ordens diretamente no gráfico, mas agora temos que fazer isto de uma única vez, já que é necessário fazer mudanças bem significativas em outros pontos do código.

Desta forma isto ficará para o próximo artigo, já que as mudanças serão bem profundas, e caso algo dê errado, você terá como recuar um passo para trás e tentar novamente até conseguir modificar o sistema da forma como você deseja que ele fique, desta forma você conseguirá personalizar ele deixando ele com a sua cara, mas no próximo artigo iremos deixar o sistema conforme mostrado abaixo:


Parece ser algo simples de conseguir, não é mesmo, mas acreditem, é preciso fazer muitas mudanças para de fato conseguir isto e de forma que funcione, então ficará para o próximo artigo, vejo você lá .

Arquivos anexados |
Últimos Comentários | Ir para discussão (2)
Sidjkcleto
Sidjkcleto | 27 jun 2022 em 20:04

Boa tarde.


Parabéns pelo projeto, mas necessariamente não consigo fixar o EA no gráfico..

Daniel Jose
Daniel Jose | 29 jun 2022 em 16:12
Sidjkcleto #:

Boa tarde.


Parabéns pelo projeto, mas necessariamente não consigo fixar o EA no gráfico..

O Algotrading tem que estar habilitado, caso contrário o EA não irá funcionar ... ele ficará desabilitado não permitindo a sua utilização ...

Usando a classe CCanvas em aplicativos MQL Usando a classe CCanvas em aplicativos MQL
Neste artigo falaremos sobre o uso da classe CCanvas em aplicações MQL, com uma descrição detalhada e exemplos, para que o usuário tenha uma compreensão básica de como usar esta ferramenta
O padrão de design MVC e suas possibilidades de uso (Parte 2): Esquema de interação entre três componentes O padrão de design MVC e suas possibilidades de uso (Parte 2): Esquema de interação entre três componentes
Este artigo dá continuação e complemento ao tópico que vimos no artigo anterior, isto é, ao padrão MVC em programas escritos em MQL. Neste artigo, estudaremos um possível esquema de interação entre esses três componentes.
Tutorial DirectX (Parte I): Desenhando o primeiro triângulo Tutorial DirectX (Parte I): Desenhando o primeiro triângulo
Este é um artigo introdutório sobre o DirectX, que descreve as especificidades da operação com a API. Ele deve ajudar a entender a ordem em que seus componentes são inicializados. O artigo contém um exemplo de como escrever um script MQL5 que renderiza um triângulo usando o DirectX.
Desenvolvendo um EA de negociação do zero (Parte 19): Um novo sistema de ordens (II) Desenvolvendo um EA de negociação do zero (Parte 19): Um novo sistema de ordens (II)
Aqui vamos desenvolver um sistema gráfico de ordens, do tipo veja o que esta acontecendo. Mas não iremos partir do zero, iremos modificar o sistema já existente adicionando ainda mais objetos e eventos ao gráfico do ativo que estamos operando.