Meu primeiro "graal"
"... a arte não pode ser programada, não se pode desenvolver dois sentidos
de poesia. Talentos não podem ser
cultivados pelo plantio
em fileiras. Eles nascem. Eles são um tesouro
nacional, como depósitos de rádio,
como o setembro em Sigulda, ou Bethesda ..."
(Andrey Voznesenskiy)
O Santo Graal é considerado por muitos a taça da qual Cristo bebeu durante a última ceia, mais tarde usada por José de Arimatéia para colher o seu sangue quando ele foi crucificado. Alguns escritores representam o graal como uma pedra que fornece sustento e que previne, durante uma semana, a morte de qualquer um que a veja. Você pode ler mais sobre o assunto aqui ou fazer uma pesquisa em qualquer mecanismo de busca.
Hoje em dia, a palavra "graal" é frequentemente usada entre programadores modernos de forma irônica. Para eles, ela representa a impossibilidade de se criar um programa "universal", adequado a todas as ocasiões. Especificamente em relação à programação no MQL4, esta palavra significa a impossibilidade de se criar um expert capaz de ter efeitos fantásticos em transações reais.
Na realidade, o Forex é o reflexo de um complexo conglomerado de fenômenos: relações econômicas e industriais, personalidades humanas, política. Além disso, e mais importante, ele não pode ser simplesmente formalizado. Trader experientes recomendam a entrada no mercado apenas caso haja de três a cinco, ou até mais, sinais indicando a possível tendência.
Ao mesmo tempo, as regularidades até hoje determinadas não são capazes de fornecer por completo uma base sólida para previsões de mercado com alta probabilidade de sucesso. As previsões contraditórias feitas por famosos analistas de bancos e organizações financeiras eminentes confirmam este fato. Todos os analistas, sem exceção, podem interpretar os eventos que já ocorreram, mas apenas alguns deles podem apresentar uma sequência de previsões realmente sólidas.
Vamos ser justos: Estas pessoas fazem o que podem. A maioria deles possui uma longa experiência trabalhando com transações e um volume invejável de conhecimento. Contudo, vamos ser claros: praticamente todos eles cometem erros com frequência. Eles podem parecer imponentes, desfrutar de popularidade, muitas vezes acumular uma grande fortuna (gurus de todos os tipos são muito bem escritos no livro de Alexander Elder intitulado Transações comerciais como um meio de vida: Psicologia, táticas de transações, gerenciamento financeiro), mas a verdade é que analistas experientes cometem erros com frequência.
Portanto, considerando essas circunstâncias, que chances tem um programador de primeira viagem que está dando os seus primeiros passos no mercado de transações em Forex? Vamos tentar reexaminar a jornada empreendida por aquele iniciante que parte em busca do seu "graal".
1. O que o "graal" compreende
Na lógica forma, a alegação de autoridade não é considerada uma evidência. Com base nisso, o programador de primeira viagem raciocina do seguinte modo: "É possível provar que a criação de "graal" é impossível? Não? Então é possível!". O iniciante não leva em consideração que a possibilidade de criação de tal objeto também nunca foi provada. Assim, sem considerar ou muitas vezes sem sequer examinar a experiência de outros "garimpeiros", mas inspirado pela ideia de "ser capaz", e tendo como base exclusivamente o seu entusiasmo e falta de experiência, começa o trabalho de programação.
1.1. Estratégia formal
Na maior parte dos casos, o programador de primeira viagem não se impõe a tarefa de criar uma estratégia de transações super lucrativa dentro de um curto espaço de tempo. Mesmo empolgado pelo sonho de obter lucros grandes e rápidos no Forex, ele percebe que um conjunto preciso de critérios de transação é necessário para que um expert seja lucrativo.
Para encontrar bons critérios, nosso programador abre o terminal do cliente do MetaTrader 4 e examina o cronograma de M1 no gráfico EURUSD. É bastante fácil notar que as alterações na taxa de câmbio se dão em ondas: para cima e para baixo, para cima e para baixo. O programador decide lucrar com essas ondas. Mas para "pegar" uma onda, é preciso saber, de algum modo, que a onda parou de subir, por exemplo, e começou a descer.
- Considerar que deve-se entrar no mercado na direção descendente (venda) caso a taxa tiver se movido um determinado número de pontos para cima, por exemplo, de 10 a 15 (movimento A-B na figura 1) e então parado de se mover para cima e se movido alguns pontos para baixo (movimento B-C na figura 1), por exemplo, cerca de 3 pontos. Além disso, o movimento descendente do mercado é previsto (C-D na figura1). O mesmo critério deve ser usado para o fechamento da compra.
-
Considerar que deve-se entrar no mercado na direção ascendente (compra) caso a taxa tiver se movido um determinado número de pontos para baixo, por exemplo, de 10 a 15 (movimento C-D na figura 1) e então parado de se mover para baixo e se movido alguns pontos para cima (movimento D-E na figura 1), também cerca de 3 pontos. Além disso, o movimento ascendente do mercado é previsto (E-F na figura1). O mesmo critério deve ser usado para o fechamento da venda.
Bem, às vezes a vida nos coloca em situações incríveis e inesperadas: O programador novato levou apenas 3 dias para criar o seu primeiro "graal".
extern int TP=100; extern int SL=100; extern int lim=1; extern int prodvig=3; extern double Prots= 10; int total, bb=0,ss=0; double max,min,lmax,lmin,Lot; int start(){ total=OrdersTotal(); if (total==0){bb=0;ss=0;} if (max<Bid) max=Bid;if (min>Ask) min=Ask; if (((max-Bid)>=lim*Point)&&(Bid>lmax )) { for (int i=total;i>=0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY) {OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE); bb=0;}} Strateg(1); } if (((Ask-min)>=lim*Point)&&(lmin>Ask )) { for (i=total;i>=0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL) {OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);ss=0;}} Strateg(2);}return;} void Strateg (int vv) {if (vv==1 && ss==0) {OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red); ss=1;} if (vv==2 && bb==0) {OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);bb=1;} lmax=Ask+prodvig*Point; lmin=Bid-prodvig*Point; return; } double Lots(){ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1); double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); if (Lot==0 ) Lot=Min_Lot; return(Lot); }
Então não devemos criar grandes expectativas. Vamos ser justos: esta é a primeira experiência do programador de primeira viagem, cujo estilo ainda não foi moldado. E vamos respeitar este expert, pois ele funciona e exibe resultados realmente fantásticos.
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Graal_1.mq4 (Grail 1). // Used as an example in the article My First "Grail". // Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/ //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int TP = 100; // TakeProfit orders extern int SL = 100; // StopLoss orders extern int lim= 1; // Distance of the rate return extern int prodvig=3; // Distance of the rate progress extern double Prots= 10; // Percentage of the liquid assets //-------------------------------------------------------------------------------------------- int total, // Count of lots bb=0, // 1 = the Buy order is available ss=0; // 1 = the Sell order is available //-------------------------------------------------------------------------------------------- double max, // Maximum price at the peak (abs.) min, // Minimum price in the trough(abs.) lmax, // Limiting price after the exceeding // of which we consider selling(abs.) lmin, // The same for buying Lot; // Count of lots //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Count of lots if (total==0) // If there are no orders, .. { bb=0; // .. no Buys ss=0; // .. no Sells } if (max<Bid) max=Bid; // Calculate the max. price at the peak if (min>Ask) min=Ask; // Calculate the min. price in the trough //------------------------------------------------------------- The price turns down ---- if (((max-Bid)>=lim*Point)&&(Bid>lmax )) // Turn at a high level { for (int i=total;i>=0;i--) // On all orders { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY) { OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE);// Close Buy bb=0; // No Buys anymore } } Strateg(1); // Opening function } //------------------------------------------------------------ The price turns up ---- if (((Ask-min)>=lim*Point)&&(lmin>Ask )) // Turn at the deep bottom { for (i=total;i>=0;i--) // On all orders { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL) { OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);// Close Sell ss=0; // No Sells anymore } } Strateg(2); // Opening function } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Strateg (int vv) // Opening function { //============================================================================================ if (vv==1 && ss==0) // Sell situation and no Sells { OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red);// Open ss=1; // Now, there is a Sell } //-------------------------------------------------------------------------------------------- if (vv==2 && bb==0) // Buy situation and no Buys { OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);// Open bb=1; // Now, there is a Buy } //-------------------------------------------------------------------------------------------- lmax=Ask+prodvig*Point; // Redefine the new limiting .. lmin=Bid-prodvig*Point; // .. levels for open and close //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // Calculation of lots { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amoung of lots double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Minimum permissible cost of lots if (Lot == 0 ) Lot = Min_Lot; // For testing on const.min.lots //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /*
Em geral, o conteúdo do expert é bastante compreensível.
Na parte superior, antes da função start(), estão dispostas as variáveis. Na função start(), a posição atual da taxa no declive de um pico (baixa) é calculada primeiro, e então a situação a analisada para o acionamento dos critérios de transações. E, caso os critérios sejam acionados, o pedido já processado será fechado. Duas outras funções são usadas no expert: Strateg() para abrir novos pedidos e Lots() para determinar a quantidade de lotes. As variáveis ss e bb são usadas para registrar pedidos abertos.
O provador de estratégia é uma ferramenta muito importante no terminal do cliente MetaTrader 4. O nosso programador testou o expert cuidadosamente de modo a otimizar as entradas, e um dos melhores resultados foi o seguinte:Nós podemos facilmente imaginar a felicidade do programador: Ele foi capaz de criar esta obra prima com as suas próprias mãos! Aqui está: Novo, elevado e brilhante em suas várias facetas perfeitas: o seu primeiro "graal"! E o nosso programador chega a uma conclusão simples: "Apenas eu!"
1.2. Investimento avançado
Figura 3. Investimentos agressivos podem resultar em perdas injustificadas
Nosso herói ficou pasmo ao se deparar com este resultado. Ele racionalizou da seguinte forma: "Se o expert é lucrativo, quanto mais você investir nele, mais você irá lucrar!". Mas os resultados do provador mostraram que frequentemente isto não é verdade.
1.2.1. Progressão geométrica
Vamos observar a tecnologia do cálculo de valor do pedido. De acordo com o código acima, o valor do pedido cresce proporcionalmente em relação à quantidade de bens líquidos: O nosso programador está bastante irritado. Ele não compreende as razões desse tratamento injusto dos funcionários, e discorda de quaisquer explicações. Ele se pergunta: Que "limitações técnicas"? O que o "deslizamento" tem a ver com isso?! Como resultado desta primeira experiencia real com transações, o nosso programador chegou a conclusão de que este é um "centro de negócios ruim", e que o(a) trapacearam. Ele rompe o contrato com o centro de negócios.
Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Minimum allowed lot value if (Lot == 0 ) Lot = Min_Lot; // For testing on const.min.lots
Este algoritmo representa uma progressão geométrica. A variável Prots (porcentagem) permite a regulagem do valor do pedido dependendo da quantidade atual de bens líquidos. Essa forma de calcular os valores de pedidos não é completamente correta, pois ela não leva em consideração as chamadas de margem ao trabalhar com um fornecedor específico. Por outro lado, o fragmento de código acima permite a resolução do problema principal: o problema relativo aos investimentos proporcionais. Portanto, o valor de cada pedido subsequente será proporcionalmente dependente dos resultados obtidos: o valor irá crescer após cada transação lucrativa e diminuir após cada transação desvantajosa. O valor do pedido no código Graal_1.mq4 (graal 1) acima representa 10% dos bens líquidos.
Vamos configurar o valor da variável Prots como 0 e, em acordo com o código abaixo,
if (Lot == 0 ) Lot = Min_Lot; // For testing on const.min. lots
testar o expert a um valor constante de pedido.
Neste caso, o resultado será o seguinte:
Figura 4. Resultados dos testes do Expert Graal_1.mq4 (graal 1) a valores constantes de lote
A exclusão dos valores progressivos de pedido exibe a verdadeira natureza das mudanças na curva de balanço: surtos, profundos levantamentos de crédito, etc.
1.2.2. Reinvestimento agressivo
Qualquer expert lucrativo sempre irá caçar uma vantagem entre o lucro e a perda. Atualmente não existe tecnologia que permita a realização de apenas transações lucrativas. Transações desvantajosas são uma norma para qualquer estratégia de transações em funcionamento real. O que importa é a razão entre as operações lucrativas e desvantajosas.
В. Abaixo temos um exemplo das situações bastante prováveis nas quais há distribuição não uniforme de transações com lucro e com perda durante transações reais:
Uma série de 5 perdas consecutivas é mostrada acima, mas uma série do tipo pode ser ainda mais longa. Você deve notar que, em um caso como este, a razão entre os pedidos lucrativos e desvantajosos mantém-se em 3 : 1.
No que pode resultar essa aleatoriedade regular? A resposta depende da qualidade da estratégia de transações escolhida pelo trader. É uma coisa caso o trader realize transações de forma deliberada, respeitando precauções razoáveis, segundo as quais o valor total dos seus pedidos não exceda de 10 a 15% do depósito; mas é outra, completamente diferente, caso o trader permita reinvestimentos agressivos, investindo a maior parte do seu depósito, e apenas uma vez, mas sempre que lucrar.
-
Alternativa 1. O valor do pedido equivale a 10% dos bens líquidos (Prots=10;). Sob tais circunstâncias, o teste permite que o expert atinja um bom ritmo de trabalho, aumentando o balanço de modo deliberado, mas permanente. Você pode ver os resultados desse modo de trabalho na figura 2. Você também pode notar na figura 2 que o expert trabalhou por um longo período de tempo (cerca de 10.000 pedidos).
-
Alternativa 2. O valor do pedido equivale a 70% dos bens líquidos (Prots=70;). Os resultados do teste são exibidos na figura 3. Duas ou três séries de pedidos desvantajosos sucessivos fizeram com que o depósito ficasse completamente vazo antes do expert ter feito 400 transações.
Por favor, preste atenção ao relatório sobre os resultados do teste: A quantidade máxima de perdas consecutivas (uma série de pedidos desvantajosos) para o expert Graal_1.mq4 (graal 1) é de apenas 10. Outras séries desvantajosas ocorreram durante o período inteiro do teste, mas a quantidade de pedidos desvantajosos em cada uma delas não excedeu 10. Estas séries desvantajosas não influenciaram de modo significativo o resultado total das transações na alternativa 1, mas foram desastrosas para a alternativa 2.
Portanto, uma série curta de perdas nos investimentos errados pode resultar em um desastre completo. Há um sistema eficiente desenvolvido para o gerenciamento adequado de capital: O gerenciamento financeiro. De acordo com esse sistema, o valor de um pedido não deve exceder 15% do balanço total, e a quantidade total de investimentos não deve exceder 50% dele. Esse sistema oferece algumas outras regras úteis, que foram lidas pelo nosso programador.
Tendo aperfeiçoado o seu "graal", assegurando-se de que tudo está funcionando direito, o nosso programador abre uma conta real e parte para "fazer dinheiro". Após alguns pedidos terem sido abertos e fechados com sucesso, ele percebe que o balanço não está em crescimento, mas em constante queda. Além disso, os funcionários do centro de negócios desabilitam o expert do nosso programador ao fim do dia.
Contudo, o nosso programador não desiste, decide examinar o processo em detalhes, e entra em contato com colegas mais experientes no fórum especializado no MQL4, onde lhe pedem para mostrar o código. Apesar do ressentimento que sente em relação ao código, ele finalmente concorda, pois de todo modo o expert não parece ser lucrativo... O nosso programador entende o seguinte após o assunto ter sido discutido no fórum.
1.3. Erros
O meta editor confirmou constantemente que não havia erros,
mas, ainda assim, havia.
1.3.1. Digressão da estratégia formal
Ainda que uma estratégia bastante consciente tenha sido usada como base para a criação do expert, ela foi alterada durante a codificação e otimização das variáveis genéricas. Portanto a ideia inicial agora está presente no "graal" em miniatura. De fato, a ideia era lucrar em ondas de 15 a 20 pontos de comprimento, mas este parâmetro se dá com o minúsculo valor de 3 na versão atual do "graal". Não chegam a ser altos e baixos...
Observe a forma com que os pedidos são considerados nas variáveis ss e bb. Esta é a forma errada de se considerar pedidos. O pedido é considerado como se já estivesse aberto ao ser formado. Mas não é possível saber de antemão se o pedido será ou não aberto. Para se assegurar deste fato, é preciso esperar até que o servidor responda, e então analisar a disponibilidade do pedido no terminal. Para se adequar a transações reais, esta parte do código deveria ser reescrita, ainda que a modificação apresentada funcione na maioria dos casos, incluindo no provador de estratégia (ver o artigo Consideração de pedidos em um programa amplo).
1.4. Restrições de hardware
O expert foi testado no cronograma para o qual foi projetado: em M1. É preciso ter muita atenção ao modelar a realização de transações do expert no cronograma M1, especialmente em relação a experts sensíveis a preços.
A principal diferença entre um modelo de teste e uma estratégia de transações real consiste no fato de que o modo de teste não apresenta deslizamento e novas cotações (quando o fornecedor dá um preço novo, diferente daquele apresentado no pedido do trader).
Centros de transações diferentes trabalham com fluxos de dados diferentes (a serem considerados mais tarde). Quanto mais frequentes forem as mudanças na taxa, o mais provável é que o fornecedor proponha ao trader executar o pedido a um preço diferente. Por outro lado, quanto mais "suave" o tráfego parecer, menos provável é o surgimento de novas cotações. Mas neste caso também há menos espaço para experts que realizem transações com frequência e com lucros pequenos.
O nosso programador testou o Graal_1 (graal 1) no histórico de 1 minuto de outro centro de negócios (com a mesma margem) e viu com seus próprios olhos que o resultado depende muito do tipo de tráfego.
Figura 6. Resultados de testes do Graal_1.mq4 (graal 1) no histórico M1 de EURUSD entre 4 de abril e 26 de julho de 2006 nos termos de transações comerciais do servidor demonstrativo do FX Integralbank a custos constantes de pedidos
A presença de profundos levantamentos de crédito e desenvolvimento de lucro instável mostra que o expert está à beira do prejuízo.
Como regra, os preços de novas cotações diferem em 1 a 2 pontos (mas a quantidade de pontos pode ser maior em um mercado veloz). Esse fenômeno não será capaz influenciar fundamentalmente o sucesso do expert caso o seu lucro esperado for muito maior. Por exemplo, de 10 - 15. Mas não se pode esperar seriamente que um expert que tenha um lucro esperado pequeno, especialmente caso este seja inferior a 2, obtenha sucesso geral, pois ele depende demais da natureza da cota e das novas cotações relacionadas.
A possibilidade de um fornecedor específico realizar ou não novas cotações no tick atual é uma questão separada, que só pode ser respondida pelo próprio fornecedor. Mas, ao iniciar os trabalhos no mercado real, é preciso assumir que a realização de novas cotações é um fenômeno normal e natural, e uma tecnologia de transações que trabalhe em uma conta real deve levar isso em consideração.
1.5. Aspectos econômicos
- Preço baixo de pedidos
Uma situação na qual a atenção do trader está completamente focada na sua conta de transações e nos eventos relativos a ela, incluindo estratégias de transações, experts, etc., é comumente encontrada. Contudo, além das preocupações do trader, há as preocupações econômicas do fornecedor.
Em transações "normais", ambas as partes podem ganhar: o trader que utiliza uma estratégia bem pensada e o fornecedor que recebe juros das transações realizadas pelo trader. Neste caso, as partes estão preocupadas uma com a outra, e prontas para apoiar uma a outra.
Contudo, podem ocorrer situações nas quais as atividades de uma parte se opõem aos interesses da outra parte. Por exemplo, se o fornecedor aumentar a margem, desabilitar a realização automática de transações, ou não abrir (fechar) pedidos unilateralmente no momento em que o preço é atingido, ele estará se opondo aos interesses do trader.
Ao mesmo tempo, algumas possíveis atividades do trader podem ir de encontro aos interesses econômicos do fornecedor. Uma dessas atividades é a realização frequente de operações de negociação com o uso de pequenas quantidades de dinheiro.
No todo, a tecnologia de trabalho do fornecedor é bastante simples. O fornecedor recolhe os pedidos de compra e venda do trader e cria relações com um banco ou outra instituição financeira para processar as diferenças em seus preços. Vamos examinar um exemplo simples. Vamos supor que um fornecedor serve um total de 100 traders, sendo que 60 deles compraram por 1 lote de EURUSD, e 40 venderam por 1 lote do mesmo par cambial. Neste caso, o fornecedor deve comprar 20 lotes (a diferença entre 60 e 40) do banco. Além disso, a direção para a qual o preço irá se mover não faz diferença para o fornecedor. Em todo caso, o fornecedor irá receber a totalidade de 80 lotes (40+40) e uma entrega parcial de 20 lotes (uma parte será dada ao banco em troca dos seus serviços).
Neste caso, a fonte do lucro/prejuízo de 40 trader é o prejuízo/lucro de outros 40 traders. A fonte do lucro/prejuízo dos 20 traders restantes é o banco ou, para ser mais preciso, pessoas jurídicas trabalhando com o banco e vendendo/comprando moedas para as suas operações de exportação-importação. Essa é uma forma normal de inter-relação entre os participantes do mercado financeiro.
Mas há mais um detalhe a respeito da forma com que o fornecedor se inter-relaciona com o banco ou a instituição financeira. A questão é que o fornecedor não se interrelaciona com o banco em todas as operações de venda ou compra caso o trader venda ou compre uma quantia insignificante de dinheiro. Operações de negociação entre o fornecedor e o banco são realizadas com uma frequência um pouco menor do que os cliques dos traders no terminal MT4. Normalmente, a quantia mínima nas relações entre o fornecedor e o banco não excede os US$50.000, o que, traduzido ao preço de pedido com uma alavancagem de 1:100, resulta em 0,5 lote. É por isso que, caso o trader sempre trabalhe com quantias pequenas de dinheiro, ele sempre irá, na prática, fazer transações com o fornecedor. Neste caso, a fonte do lucro do trader é o dinheiro do fornecedor!
O fornecedor participa tanto do mercado financeiro quanto qualquer outro. O fornecedor deve observar e analisar o trabalho de todos os traders. É claro que fornecedores, no escopo de suas preocupações financeiras, podem fazer vista grossa a investimentos repetidos irregulares caso eles resultem em prejuízos evidentes ao trader ou o seu resultado total seja neutro por um determinado período de tempo (o resultado diário, por exemplo). Mas nenhum fornecedor razoável permitirá que interrelações continuem caso elas resultem em perdas para ele. Neste caso, o fornecedor precisa reagir de alguma forma, do contrário ele não deveria estar no território econômico do mercado financeiro.
Note, por favor, que a rotina moderna no mercado financeiro não se dá em função das animosidades ou caprichos de um fornecedor. As relações do fornecedor com o banco também são contratuais. E o fornecedor se esforça para ganhar a margem de forma justa (abusos da parte do fornecedor não são discutidos no presente artigo). O fornecedor provavelmente ficaria feliz em realizar transações com o banco o tempo todo, mas tal possibilidade não existe no momento.
Quando operações de negociação pequenas e frequentes são realizadas por um trader, o fornecedor precisa tomar alguma medida. Ela pode vir sob a forma de uma notificação enviada ou comunicada ao trader, dizendo que aquele seu trabalho específico está à beira do prejuízo. O fornecedor pode também desabilitar a realização automática de transações para este trader, ou aumentar a quantidade de operações com novas cotações.
- Preço alto de pedidos
Há mais uma limitação que diferencia transações reais de testes ou transações em uma conta demonstrativa. Trata-se do valor máximo do preço do lote. Nenhum centro de negócios, seja um banco, um agiota ou uma instituição financeira, pode operar de maneira prática com quantidades muito grandes de dinheiro.
Se pedidos custarem cerca de US$10.000 a 20.000 (note, por favor, que há uma alavancagem, geralmente igual a 100), o centro de negócios irá vender/comprar por até US$1.000.000. Essa é uma quantia bastante grande, mas os fornecedores aprenderam a lidar com esse tipo de volume de dinheiro de forma bem sucedida.
Algumas dificuldades podem ocorrer em uma instituição financeira média, caso o preço do pedido chegar a US$50.000 ou mesmo US$100.000. Neste caso, a quantia de 5 a 10 milhões de dólares americanos figura no mercado interbancário. Não é fácil vender/comprar essa quantia de dinheiro em um único movimento.
Podem ocorrer problemas caso o preço de pedido exceder a quantia de US$ 300.000 a 500.000. Neste caso, o centro de negócios certamente irá trabalhar com o trader individualmente. Bem, 50 milhões de dólares é uma quantia bastante grande para qualquer instituição.
No caso de preços de pedido enormes, as garantias firmes do centro de negócios estão fora de questão, e a própria realização de transações tem como base o fato de que o trader entende e aceita isso. (De fato, que fornecedor pode tomar a liberdade de abrir um pedido que custa uma enorme quantia de dinheiro imediatamente sob condições de movimentos de mercado imprevisíveis e fortes?)
Por esta razão, experts de scalping realizando transações envolvendo milhões são evidência de um grande erro por parte do trader e não tem nada a ver com o mundo real.
Esse raciocínio sugeriu ao nosso programador ganhar as cem mil "pratas" iniciais aqui e então procurar um "escritório pior". O programador ficou quieto, pensando que "está tudo sob controle".
Não vamos nos esquecer de que fornecedores são pessoas normais, com seus níveis culturais e de instrução, com negócios sendo geridos de uma ou outra forma. A mesma tecnologia, não lucrativa para fornecedores, pode ser imediatamente detectada quando analistas trabalham com eficiência, e não pode ser facilmente detectada por fornecedores que fazem o seu trabalho pela metade, não possuem experiência o bastante, ou não tem o software necessário. Mas, na maioria dos casos, fornecedores já buscaram o seu "graal" no passado, possuem experiência no mercado e geralmente compreendem muito bem todas as nuances das transações nos mercados financeiros. Então eles sabem o que é progressão geométrica, preocupação financeira, reinvestimento agressivo, e preços de pedidos baixos e altos. Em geral, todo trader precisa enfrentar a afirmação de que as qualificações dos fornecedores são maiores do que as suas, e que qualquer posição ou posição pragmática do fornecedor é fundamentada.
Vocês mesmos podem julgar: Quais (sob as condições econômicas e técnicas acima) podem ser os resultados do trabalho de um expert que abre mais de 20.000 pedidos por ano?
O cérebro do nosso programador flutua entre todos esses ticks, barras, pontos, margens, fornecedores e bancos. Ele decide não examinar os detalhes ou "questões únicas". Basta a sua compreensão de que "os resultados dos testes não coincidem com a realização de transações real". E ele decide que uma tecnologia adequada será desenvolvida com base em pedidos pendentes. "Bom, eles não vão conseguir me pegar aqui!", ele pensa.
2. O segundo "graal"
2.1 Estratégia
A ideia de construir o expert com base em pedidos pendentes chega à mente do nosso programador após ele ter estudado o comportamento das taxas cruzadas EURGBP e EURCHF em gráficos de 1 minuto.
Figura 8. Regiões históricas de taxas cruzadas com desvios significativos de preço (picos)
Como é possível notar facilmente, à noite, quando a sessão européia já terminou e a asiática ainda não começou, alguns gráficos de símbolos contêm barras com preços inesperados que são absolutamente diferentes de fluxos de preços "normais". A partir da lógica formal, basta colocar pedidos pendentes do tipo "limite" um pouco acima e um pouco abaixo do fluxo principal, e uma parte deles irá ser aberta, com uma probabilidade alta de sucesso. Para que pedidos pendentes reajam de forma adequada a mudanças no fluxo principal, eles devem ser "arrastados" ao longo de uma determinada linha média e apoiados constantemente a uma dada distância da linha MA (média móvel). O nosso programador escreveu um expert para realizar essa ideia:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Graal_2.mq4 (Grail 2). // Used as an example in the article My First "Grail". // Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/ //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int TakeProfit=5; // TakeProfit orders extern int StopLoss= 29; // StopLoss orders extern int Distan = 2; // Distance from the МА line extern int Cls = 2; // Close at ** points of profit extern int period_MA=16; // MA period //extern int Time_1 = 0; // Starting time //extern int Time_2 = 0; // Finishing time extern int Prots = 0; // Percentage of free assets //-------------------------------------------------------------------------------------------- int Nom_bl, // BuyLimit order number Nom_sl, // SellLimit total, // Count of lots bl = 0, // 1 = BuyLimit order availability sl = 0, // 1 = SellLimit order availability b = 0, // 1 = Buy order availability s = 0; // 1 = Sell order availability //-------------------------------------------------------------------------------------------- double OP, // OpenPrice (absolute points) SL, // StopLoss orders (relative points) TP, // TakeProfit orders (relative points) dist, // Distance from МА (relative points) Level, // Min.allowed distance of a pending order OP_bl, // OpenPrice BuyLimit (absolute points) OP_sl, // OpenPrice SellLimit(absolute points) cls, // Close at ** profit (absolute points) MA, // MA value (rate) spred, // Spread (absolute points) Lot; // Count of lots //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { Level=MarketInfo(Symbol(),MODE_STOPLEVEL); // Check what the server shows us Level=(Level+1)*Point; // ?:) SL=StopLoss*Point; // StopLoss orders (relative points) TP=TakeProfit*Point; // TakeProfit orders (relative points) dist=Distan*Point; // Distance from the MA line(relative points) cls=Cls*Point; // Close at ** profit (absolute points) spred=Ask-Bid; // Spread (absolute points) return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Count of lots bl=0; // Zeroize at the start of the pass sl=0; // Zeroize at the start of the pass b=0; // Zeroize at the start of the pass s=0; // Zeroize at the start of the pass //-------------------------------------------------------------------------------------------- for (int i=total; i>=0; i--) // For all orders { if (OrderSelect(i,SELECT_BY_POS)==true && // Select an order OrderSymbol()==Symbol()) { //-------------------------------------------------------------------------------------------- if (OrderType()==OP_BUY) // Buy order { b =1; // The order found Close_B(OrderTicket(),OrderLots()); // Close the order (the function decides // whether it is necessary) } //-------------------------------------------------------------------------------------------- if (OrderType()==OP_SELL) // Sell order { s =1; // The order found Close_S(OrderTicket(),OrderLots()); // Close the order (if necessary) } //-------------------------------------------------------------------------------------------- if (OrderType()==OP_BUYLIMIT) // BuyLimit order { OP_bl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice BuyLimit(absolute points) Nom_bl=OrderTicket(); bl=1; // The order found } //-------------------------------------------------------------------------------------------- if (OrderType()==OP_SELLLIMIT) // SellLimit order { OP_sl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice SellLimit(absolute points) Nom_sl=OrderTicket(); sl=1; // The order found } //-------------------------------------------------------------------------------------------- } } //-------------------------------------------------------------------------------------------- MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// The MA current value Modify_order(); // Activate modification Open_order() ; // Activate opening //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Close_B(int Nomber, double lots) // Close Buy orders { //============================================================================================ if (NormalizeDouble(Bid-OrderOpenPrice(),Digits)>=cls)// If the preset profit is reached { OrderClose( Nomber, lots, Bid, 1, Yellow); // Close b = 0; // No Buy order anymore } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Close_S(int Nomber, double lots) // Close Sell orders { //============================================================================================ if (NormalizeDouble(OrderOpenPrice()-Ask,Digits)>=cls)// If the preset order is reached { OrderClose( Nomber, lots, Ask, 1, Yellow); // Close s = 0; // No Sell order anymore } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Modify_order() // Modification of orders { //============================================================================================ if (bl==1) // If there is BuyLimit { OP=MA-dist; // it must be located here if (MathAbs(OP_bl-OP)>0.5*Point) // if it is not located here { OrderModify(Nom_bl,OP,OP-SL,OP+TP,0,DeepSkyBlue);// The order modification } } //-------------------------------------------------------------------------------------------- if (sl==1) // If there is SeelLimit { OP=MA+spred+dist; // It must be located here if (MathAbs(OP_sl-OP)>0.5*Point) // If it is not located here { OrderModify( Nom_sl, OP, OP+SL, OP-TP, 0, Pink);// The order modification } } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Open_order() // An opening function { // int Tek_Time=TimeHour(CurTime()); // To test by the time // if (Tek_Time>Time_2 && Tek_Time> //============================================================================================ if (b==0 && bl==0) // No Buy orders, open bl { OP=MA-dist; // bl order open rate if(OP>Ask-Level) OP=Ask-Level; // OP precision according to the tolerance OP=NormalizeDouble(OP,Digits); // Normalizing (MA gives the 5th digit) OrderSend(Symbol(),OP_BUYLIMIT, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Open bl=1; // Now there is a Buy order b1 } //-------------------------------------------------------------------------------------------- if (s==0 && sl==0) // No Sell orders, open sl { OP=MA+spred+dist; // sl order open rate if(OP<Bid+Level) OP=Bid+Level; // OP precision according to the tolerance OP=NormalizeDouble(OP,Digits); // Normalizing (MA gives the 5th digit) OrderSend(Symbol(),OP_SELLLIMIT,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// Open sl=1; // Now there is a Sell order sl } ///============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // Calculation of lots { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Minimum lot values if (Lot == 0 ) Lot = Min_Lot; // For testing on const.min.lots //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /*
StopLoss, TakeProfit, Distan (a distância na qual o pedido acompanha o fluxo principal), Cls (a quantidade mínima de pontos ganhos no pedido; o pedido deve ser fechado quando a quantidade de pontos alcançar este valor), period_MA (o período MA; o MA aqui é a linha média de taxas do histórico mais recente), e Prots (a porcentagem de ativos disponíveis) foram escolhidos como variáveis ajustáveis. É mais do que o suficiente para realizar a ideia.
-
Na função especial start(), os pedidos são analisados (os métodos de consideração dos pedidos são descritos aqui) e a decisão sobre o que fazer com alguns deles é tomada simultaneamente. Casa haja um pedido aberto no terminal, a função correspondente Close_*() será chamada imediatamente, então a necessidade de fechar é analisada e o pedido é fechado.
-
Ao fim da função start(), as funções Modify_order() e Open_order() são abertas para, respectivamente, modificar e abrir pedidos pendentes do tipo "limite". Outros pedidos não são abertos.
-
Na função Modify_order(), a localização do pedido é calculada (a alguma distância da linha média), e, caso ele não esteja em um local adequado, é movido para lá.
-
Na função Open_order(), o local desejado para se colocar o pedido pendente também é determinado. Além disso, as limitações do servidor são consideradas e, caso não haja nenhum pedido, ele é feito.
Figura 9. Resultados de testes do Graal_2.mq4 (graal 2) no histórico de março de 2005 a junho de 2006, no gráfico М1 EURUSD sob as condições de transação da companhia MIG Investments
2.2. Progressão geométrica
Figura 10. Resultados de testes do Graal_2.mq4 (graal 2) no histórico de março de 2005 a junho de 2006, no gráfico М1 EURUSD sob as condições de transação da companhia MIG Investments a preços constantes de pedidos
Originalmente, o nosso programador planejava ganhar dinheiro apenas durante a noite, mas então ele foi surpreendido pelo fato do expert trabalhar de forma bem sucedida durante todo o dia de comércio. Precisamos dizer que depois disso ele repetiu: "Apenas eu!" e partiu para "fazer dinheiro" novamente? Mas nada do tipo acabou acontecendo... Desta vez, o programador precisa se familiarizar com "picos".
2.3. Erros
No exemplo de expert acima, há uma grande quantidade de defeitos e de soluções de programação incorretas. No Modify_order(), a distância mínima permitida para pedidos pendentes não é levada em consideração, a consideração dos pedidos abertos é organizada incorretamente, o TakeProfit não é modificado separadamente para "enfatizar" o lucro para o Cls, a parte analítica do expert está "espalhada" por todo o código, etc.
A programação incorreta e, mais do que isso, pouco cuidadosa, frequentemente resulta em erros indistintos e, às vezes, na replicação do erro, caso o código seja integrado a outros experts.
2.4. Restrições técnicas (picos)
Todas as restrições, técnicas ou organizacionais, se transformarão, no fim, em perdas econômicas, como regra. Surge a questão: à custa de quem essas perdas serão cobertas?
Um gráfico de candle normal, que é visto pelo trader no seu monitor, é um resultado médio do desenvolvimento do mescado em um território específico (entre bancos europeus, por exemplo). O comportamento da taxa durante um curto período do histórico com diferentes fornecedores pode ser analisado. Além disso, como se pode ver facilmente, todos esses gráficos serão diferentes uns dos outros, mesmo que sutilmente. Alguns gráficos de fornecedores irão conter várias candles longas multidirecionais, enquanto outros gráficos de fornecedores exibirão "calma e sossego".
Um gráfico de ticks também é um objeto de venda. Ele é o resultado do trabalho de algum programa de processamento que filtra ticks de preço excessivos e não-naturais. E eles (os ticks "não-naturais") surgem. Isso acontece quando uma pessoa em um banco, por algum motivo pessoal (tudo pode acontecer, certo?), realiza uma compra ou venda de uma certa quantia a um preço muito diferente do preço do mercado. O programa de processamento aceita esta informação e, caso uma transação do tipo só tenha ocorrido uma vez, não a considera na formação do gráfico final. Em alguns casos, o programa encontra dificuldades em entender qual preço é "normal" e qual não é. Por este motivo, candles simples de comprimentos diferentes (dependendo do algoritmo do programa de processamento) aparecem às vezes no gráfico. Esses são os picos. Há diferentes tipos deles, mas eles não mostram a situação real do mercado financeiro.
Não é muito difícil criar um expert capaz de detectar esses "pinos", "espinhas" e "picos", e abrir pedidos quando o preço é mais lucrativo. Mas é preciso compreender que, sob os contratos fechados entre o fornecedor e o banco, o banco geralmente não paga este tipo de transação ao fornecedor. Isso significa que a fonte de lucro do trader é, novamente, o bolso do fornecedor! E o fornecedor não quer que isso aconteça, é claro, então ele se esforça para fazer com que os traders realizem operações comerciais a preços de mercado "normais".
Em relação a medidas que criem essa oportunidade ao fornecedor, o contrato entre ele e o trader geralmente contém clausulas a respeito dos direitos do fornecedor, incluindo a possibilidade de mudanças na cotação, a abertura não garantida de pedidos quando há movimentos fortes nos preços, a abertura de pedidos pendentes no segundo toque, e outras precauções. Em alguns casos, o fornecedor pode cancelar um pedido já aberto caso, na sua opinião, ele tiver sido aberto durante um pico.
É isso o que ocorreu com o nosso personagem. Por melhor que fosse na conta demonstrativa, o graal foi novamente corrigido pela vida real. Desta vez, o nosso programador não bate o telefone, e dá ouvidos aos fornecedores, prestando bastante atenção a cada explicação dos motivos pelos quais pedidos foram fechados forçosamente. Mas quando o fornecedor desabilitou os experts, o programador não aguentou e novamente rompeu o seu contrato.
Agora o nosso personagem imagina que os cronogramas de um minuto são os culpados pelos seus vários fracassos. Após ler postagens em fóruns e se comunicar com outros traders, o programador nota que a maioria deles trabalha em cronogramas maiores com os mesmos símbolos. "Isso deve fazer sentido", ele pensa. Gradualmente o programador chega à conclusão de "Mozart e eu" e parte para desenvolver a sua terceira criação ("nunca, nunca mais!").
3. O terceiro "graal"
3.1 Estratégia formal
Após estudar cuidadosamente o gráfico H1 EURUSD e usar vários indicadores para analisá-lo, o nosso programador descobriu uma regularidade bastante atraente: Caso a MA (média móvel) de um período menor se encontre com a MA de um período maior, o mercado geralmente se move na direção à qual o MA do período menor se move.Figura 11. Representação gráfica da estratégia baseada no entrecruzamento de MAs com períodos diferentes
O nosso programador também notou que essa correlação surge em todos os cronogramas, mas decidiu trabalhar apenas com os maiores. Para ele, resta apenas traduzir o conhecimento extraído ao MQL4, para informar ao expert em qual direção e sob quais condições este deve abrir pedidos. E, quando o expert estiver pronto, será necessário otimizar os seus parâmetros, de modo a encontrar os comprimentos de MA mais eficientes e colocar o StopLoss e o TakeProfit de modo correto.
Desta vez, o seguinte expert foi criado://жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Graal_3.mq4 (Grail 3). // Used as an example in the article My First "Grail". // Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/ //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int MA1 = 11; // Period of the first MA extern int MA2 = 23; // Period of the second MA extern double TP = 50; // TakeProfit orders extern double SL = 15; // StopLoss orders extern double Prots= 0; // Percentage of free assets //-------------------------------------------------------------------------------------------- int ret, // Direction of intersection total; // Count of open orders //-------------------------------------------------------------------------------------------- double Lot, // Count of lots Pred, // Preceding value of the 1st MA(red) Tek, // Current value of the 1st MA (red) Golub; // Current value of the 2nd MA (blue) //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { //============================================================================================ SL = SL*Point; // StopLoss in points TP = TP*Point; // TakeProfit in points return; //============================================================================================ } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Total amount of orders if (total==2)return; // Both orders are already open //-------------------------------------------------------------------------------------------- Tek =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 1st MA Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Preceding value of the 2nd MA Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 2nd MA //-------------------------------------------------------------------------------------------- if (Peresechenie()==1) Open_Buy(); // Movement bottom-up = open Buy if (Peresechenie()==2) Open_Sell(); // Movement top-down = open Sell //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() // Function determining intersection { //============================================================================================ if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // Intersection bottom-up //-------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // Intersection top-down //============================================================================================ return(ret); // Return the intersection direction } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Buy() // Function opening Buy { //============================================================================================ if (total==1) // If there is only one order... { // ... it means another can be opened OrderSelect(0, SELECT_BY_POS); // Select the order if (OrderType()==0)return; // If it is Buy, do not open } OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// open //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Sell() // Function opening Sell { //============================================================================================ if (total==1) // If there is only one order... { // ... it means another can be opened OrderSelect(0, SELECT_BY_POS); // Select the order if (OrderType()==1)return; // If it is Sell, do not open } OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Open //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // Calculation of lots { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Minimum lot values if (Lot == 0 ) Lot = Min_Lot; // For testing on const. min. lots //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /*
Este expert, como todos os seus predecessores, é bastante simples.
O expert começa com um bloco que descreve variáveis. Na função start(), é definida a quantidade total de pedidos, assim como os valores de MA dos períodos maior e menor Caso os MAs se encontrem, a função correspondente é chamada, e esta irá abrir pedidos: Open_*(). Para a afirmação de que os MAs se encontraram, a função Peresechenie() é usada. Para descobrir os valores do lote, a função Lots() é usada.
no gráfico H1 EURUSD sob as condições de transação do servidor demonstrativo da MetaQuotes Software Corp
Três milhões em cinco meses! Maravilha! Mas alguma coisa neste diagrama de balanço lembra o nosso personagem da sua amarga experiência anterior. E o programador decide ir com mais calma.
3.2. Progressão
Após o mesmo expert ser testado a preços constantes de pedido, ele exibiu um diagrama de balanço bastante aceitável.
sob as condições de transação do servidor demonstrativo da MetaQuotes Software Corp a preços constantes de lotes
Seis mil pontos em cinco meses. É possível sentir a eletricidade no ar. Mais de mil pontos por mês! Mas o nosso personagem fica em dúvida em relação a usar o expert em transações reais. Afinal, ele já esteve errado duas vezes...
3.3. Erros
"Que estranho! Deve haver algo de errado com o MetaEditor!" foi o que lhe ocorreu. Mas então, após estudar gradualmente e repetidamente o código, o programador volta a encontrar erros. Vamos entendê-los também.
3.3.1 Desvios da estratégia inicial - Erros algorítmicos
Veja a função simples abaixo:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() // Function that detects the intersection { //================================================================================================= if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // Bottom-up intersection //------------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // Top-down intersection //================================================================================================= return(ret); // Return the intersection direction } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
Tudo parece estar bastante claro, o que poderíamos estar procurando ali? Mas ainda há um erro ali. Ele consiste no fato de que, quando a variável global ret é utilizada, o seu valor é armazenado como igual ao último calculado, ou seja, 1 ou 2. Por este motivo, a função Peresechenie(), independentemente da situação atual, simplesmente devolve o último valor calculado. É por isso que se ordena constantemente que ela abra na função start().
if (Peresechenie()==1) Open_Buy(); // Bottom-up movement = open Buy if (Peresechenie()==2) Open_Sell(); // Top-down movement = open Sell
Para fazer mudanças, basta "zeroizar" a variável ret no início da função Peresechenie(). Tendo encontrado o erro algorítmico, o nosso personagem o corrige e simultaneamente escreve um fragmento que permite a abertura apenas em uma barra. Agora, o expert está assim:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Graal_31.mq4 (Grail 31) // Used as an example in the article My First "Grail" // Sergey Kovalyov, Dnepropetrovsk, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/. //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int MA1 = 11; // Period of the 1st MA extern int MA2 = 23; // Period of the 2nd MA extern double TP = 50; // TakeProfit orders extern double SL = 15; // StopLoss orders extern double Prots= 0; // Percentage of free assets //-------------------------------------------------------------------------------------------- int New_Bar, // 0/1 The fact of new bar forming Time_0, // The new bar beginning time ret, // Intersection direction total; // Count of open orders //-------------------------------------------------------------------------------------------- double Lot, // Count of lots Pred, // Previous value of the 1st MA (red) Tek, // Current value of the 1st MA (red) Golub; // Current value of the 2nd MA (blue) //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { //============================================================================================ SL = SL*Point; // SL in points TP = TP*Point; // ТР in points return; //============================================================================================ } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Total count of orders if (total==2)return; // Both orders already opened //----------------------------------------------------------------------------- New bar ------ New_Bar=0; // First zeroize if (Time_0 != Time[0]) // If the bar beginning time changed { New_Bar= 1; // Here we have a new bar Time_0 = Time[0]; // Remember the new bar beginning time } //-------------------------------------------------------------------------------------------- Tek =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 1st MA Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Previous value of the 2nd MA Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 2nd MA //-------------------------------------------------------------------------------------------- if (Peresechenie()==1 && New_Bar==1) Open_Buy(); // Bottom-up movement = open Buy if (Peresechenie()==2 && New_Bar==1) Open_Sell(); // Top-down movement = open Sell //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() { ret=0; // That's the heart of the matter!:) //============================================================================================ if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // Bottom-up intersection //-------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // Top-down intersection //============================================================================================ return(ret); // Return the intersection direction } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Buy() { if (total==1) { OrderSelect(0, SELECT_BY_POS); // Select the order if (OrderType()==0)return; // If it is buy, don't open } OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// Open return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Sell() { if (total==1) { OrderSelect(0, SELECT_BY_POS); // Select the order if (OrderType()==1)return; // If it is sell, don't open } OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Open return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() { Lot = NormalizeDouble( AccountEquity()*Prots/100/1000, 1);// Calculate the amount of lots if (Lot<0.1)Lot = 0.1; // For testing on const. min. lots return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
Os testes deste expert a preços constantes de lotes tiveram um sucesso limitado:
sob as condições de transação do servidor demonstrativo da MetaQuotes Software Corp a preços constantes de lotes
Nosso programador fica completamente desanimado. Tanto trabalho, e tudo em vão. O tempo passa, e o nosso programador continua em sua busca pelo "graal". Após alguns meses, ele decide voltar a trabalhar no expert chamado Graal_3.mq4 (graal 3). "Bem, ele tinha um erro, mas criou bons resultados. Talvez tudo seja assim mesmo! O expert pode abrir os pedidos que quiser, contanto que apenas os bons resultados sejam mantidos". E os testes começam novamente.
sob as condições de transação do servidor demonstrativo da MetaQuotes Software Corp a preços constantes de lotes
3.4. Ajuste de resultados
O nosso personagem começa a ignorar as más notícias. Ele percebe que não é difícil colocar parâmetros otimizados em um expert pouco eficiente em um segmento de histórico. O mesmo expert sempre fornecerá resultados diferentes em diferentes períodos do histórico.
A questão se torna simplesmente a seguinte: como encontrar este tipo de entrada otimizada para o expert, sendo que, se possível, pequenas flutuações do mercado em relação à velocidade do preço não devem influenciar o funcionamento e a eficiência do expert. Em geral, é preciso focar em uma estratégia que resista a quaisquer mudanças no mercado, e a otimização de parâmetros deve apenas auxiliar em parte a se chegar aos melhores resultados possíveis.
A busca pelas configurações ideais do expert chamado Graal_3.mq4 (graal 3) não resultou em nada. O teste do expert com diferentes valores de variáveis externas resultou ou em perdas ou em configurações significativamente diferentes para diferentes períodos do histórico. Por este motivo, o nosso personagem não conseguiu encontrar as configurações ideais. Então ele concluiu que esta estratégia não possui configurações universais para todas as ocasiões.
Ele voltou a trabalhar no expert chamado Graal_31.mq4 (graal 31), agonizando para conseguir os resultados desejados. Mas os melhores resultados foram os seguintes:
sob as condições de transação do servidor demonstrativo da MetaQuotes Software Corp a preços constantes de lotes
Isto não lhe parece nem um pouco com um "graal". Por conta da profunda redução, visível a olho nu, no meio do gráfico, o expert não pode ser utilizado em uma conta real. Mas ele ainda é um expert funcional que mostra resultados positivos, ainda que nada fantásticos.
4. Conclusão
A desilusão sempre é dura, especialmente se as ilusões forem otimistas e alegres. Mas a vida põe tudo em seu devido lugar, cedo ou tarde. As preocupações constantes acabaram afetando o nosso personagem: O programador prejudicou as suas relações com dois centros de negócios, além de perder uma certa quantia de dinheiro suado... Tendo adquirido uma experiência inestimável em relação à programação e à realização de transações no Forex, o nosso personagem quase chega à conclusão de que "Apenas Mozart...", mas se detém e decide parar de tirar conclusões precipitadas.
Ao invés disso, ele pega uma folha de papel limpa e formula as conclusões às quais chegou com base nas lições tomadas:
-
Investimentos progressivos são normais em transações reais. Contudo, os pedidos não podem ter um preço muito alto.
-
Aderir à estratégia inicial
Caso, durante o desenvolvimento do expert, mudanças significativas em parâmetros ajustáveis resultarem em mudanças significativas nos resultados, isso significa que a estratégia inicial é aumentada ou reduzida. É muito possível que o nova estratégia resultante seja mais eficiente. Neste caso, ela deve ser suspensa por um curto período de tempo, e então chamada, após as razões deste sucesso inesperado serem bem examinadas. Mas é preciso voltar à ideia original primeiro, de modo a investigar a sua funcionalidade completa, admitindo mudanças em parâmetros apenas dentro dos limites razoáveis. -
Busque erros algorítmicos com atenção
A presença de erros algorítmicos é um fenômeno bastante natural. Às vezes é preciso ter bastante experiência para encontrar tais erros. Além disso, alguns deles podem e devem ser encontrados nos resultados finais do trabalho do expert. Aberturas muito frequentes ou aberturas "fora do eixo" são uma forte evidência da presença de um erro algorítmico. -
Interprete adequadamente os resultados dos testes do expert no provador de estratégias
O trabalho do expert em uma conta real e na sua modelagem no provador de estratégias são coisas diferentes. A diferença consiste no fato de que a modelagem não considera rejeições para executar pedidos e mudanças de cotação, que ocorrem em transações reais. Isso não importa em relação a experts com lucro esperado alto, mas em relação a experts com lucro esperado baixo, os resultados do trabalho podem ser significativamente diferentes daqueles obtidos durante os testes. Em muitos casos, um expert com lucro esperado baixo que apresente lucros fantásticos durante os testes podem resultar em perdas durante transações reais. -
Nada de investimentos agressivos
Qualquer estratégia de transação deve considerar operações desvantajosas. Se os preços dos pedidos forem incrivelmente altos, até mesmo uma curta série de perdas pode causar danos irreparáveis ao balanço total e, em alguns casos, até mesmo a perda total do depósito. Permitir reinvestimentos agressivos não supervisionados significa ignorar más notícias de forma voluntária, o que é uma garantia de falência. - Não de tentar lucrar com flutuações casuais
Picos não refletem as taxas de mercado normais e naturais. Se os traders lucrarem nestes picos, o fonte do lucro é o dinheiro do fornecedor. Este fato será descoberto pelo fornecedor cedo ou tarde, e terá consequências: o cancelamento de transações, a desabilitação de experts, o bloqueio da conta. - Verifique os resultados de testes em diferentes períodos do histórico
Cada expert irá ter resultados diferentes em cronogramas diferentes. É possível encontrar as suas configurações ideais para cada intervalo do histórico, com as quais ele obterá os melhores resultados. É preciso prestar muita atenção aos testes, e não ignorar más notícias (ajustar os parâmetros do expert), mas verificar os resultados obtidos em tantos intervalos do histórico quanto for possível.
SK. Dnepropetrovsk. 2006.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1413
- 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