Expert Advisor Multiplataforma: Stops
Índice
- Introdução
- COrder
- CStop
- CStops
- COrderStop
- COrderStops
- Representação dos Stops no Gráfico
- Verificação da Ordem de Stop
- Exemplos
- Conclusão
- Programas Utilizados no Artigo
- Arquivos das Classes Apresentados no Artigo
Introdução
Conforme discutido em um artigo anterior, para um expert advisor multiplataforma, nós criamos um gerenciador de ordens (COrderManager) que cuida da maioria das diferenças entre a MQL4 e MQL5 no que diz respeito à entrada e encerramento de posições. Em ambas as versões, o expert advisor salva as informações das negociações na memória criando instâncias da COrder. Os containers de ponteiros dinâmicos para as instâncias deste objeto de classe também estão disponíveis como membros da classe COrderManager (para o histórico de negociações e as negociações atuais).
É possível que o gerenciador de ordens gerencie diretamente os níveis de stop de cada operação. No entanto, fazer isso há certas limitações:
- A COrderManager provavelmente teria que ser estendida para personalizar como ela lida com os níveis de stop para cada operação.
- Os métodos existentes da COrderManager tratam apenas da entrada das posições principais.
É possível que a COrderManager seja estendida para que ela possa lidar com os níveis de stop para cada transação (ordem executada) por conta própria. No entanto, isso não se limita apenas à colocação dos níveis, mas também a outras tarefas relacionadas ao monitoramento desses stops, como modificação e verificação se o mercado já atingiu um determinado nível. Essas funções tornariam a COrderManager muito mais complexa que atualmente ela é, sem mencionar as implementações divididas.
O gerenciador de ordens só lida com a entrada das operações principais, enquanto que alguns níveis de stop exigem que o EA realize outras operações de negociação, como a colocação de ordens pendentes e o fechamento das posições atuais. Embora seja possível para o gerenciador de ordens lidar com isso por conta própria, seria melhor fazê-lo concentrar-se na entrada de posições principais e deixar outro objeto de classe lidar com os níveis de stop.
Neste artigo, nós discutiremos a implementação em que a COrderManager trataria exclusivamente a entrada e saída das operações principais (como atualmente é) e, em seguida, a implementação dos níveis de stop tratados separadamente por outro objeto da classe (CStop).
COrder
Como nós aprendemos do artigo anterior (veja Expert Advisor Multiplataforma: Ordens), uma instância da COrder é criada após uma operação de negociação bem-sucedida (entrada). Tanto para a MetaTrader 4 como para a MetaTrader 5, as informações relativas ao stoploss e takeprofit podem ser salvas na ponta da corretora. No entanto, no caso dos stops estarem ocultos da corretora ou envolvidos em vários níveis de stop, as informações sobre a maioria dessas paradas devem ser salvas localmente. Assim, no último caso, após uma entrada bem sucedida de uma posição, a instância da COrder deve ser criada primeiro, seguido das instâncias de objeto que representam seus níveis de stoploss e takeprofit. Em um artigo anterior, nós demonstramos como as instâncias COrder são adicionadas ao gerenciador de ordens após a criação, conforme mostrado na figura a seguir:
Os níveis de stop são adicionados da mesma maneira. Para fazer isso, nós precisamos apenas inserir o método após a nova instância COrder ser criada e antes de ser adicionada à lista de negociações em andamento (COrders). Assim, nós precisamos apenas modificar a ilustração acima, conforme mostrado na ilustração a seguir:
O funcionamento geral da criação dos níveis de stop é exibido na figura a seguir:
Conforme exibido acima nos dois fluxogramas anteriores, assim que uma negociação for inserida com sucesso, uma nova instância da COrder será criada representando-a. Depois disso, as instâncias da COrderStop serão criadas para cada um dos níveis de stoploss e takeprofit definidos. Se não houvesse uma instância da CStop declarada na inicialização do EA, esse processo específico seria ignorado. Por outro lado, se as instâncias da COrderStop foram criadas, os ponteiros para essas instâncias serão armazenados sob a instância COrder criada anteriormente. Nós podemos encontrar esta operação dentro do método Init da COrder:
bool COrderBase::Init(COrders *orders,CStops *stops) { if(CheckPointer(orders)) SetContainer(GetPointer(orders)); if(CheckPointer(stops)) CreateStops(GetPointer(stops)); m_order_stops.SetContainer(GetPointer(this)); return true; }
Para a criação dos níveis de stop para a instância da COrder, nós podemos ver que ele chama o método CreateStops, que é mostrado abaixo:
void COrderBase::CreateStops(CStops *stops) { if(!CheckPointer(stops)) return; if(stops.Total()>0) { for(int i=0;i<stops.Total();i++) { CStop *stop=stops.At(i); if(CheckPointer(stop)==POINTER_INVALID) continue; m_order_stops.NewOrderStop(GetPointer(this),stop); } } }O método itera sobre todas as instâncias disponíveis da CStop, que representa cada par dos níveis de stoploss e takeprofit. Cada uma dessas instâncias da CStop é passada para uma instância da COrderStops, que é simplesmente um container para todos os níveis de stop para uma determinada ordem. Nós podemos então construir a hierarquia dos objetos de classe da seguinte maneira:
Para cada instância da COrder, existe um membro do tipo COrderStops. Esta instância COrderStops é um container (uma extensão da CArrayObj), que contém os ponteiros para instâncias da COrderStop. Cada instância da COrderStop representa um nível de stop (CStop) para apenas essa operação em específico (instância COrder).
CStop
Conforme discutido anteriormente, nós gostaríamos de ter um certo nível de liberdade de personalização de como os níveis de stop de cada negociação são tratados, sem ter que modificar o código fonte do gerenciador de ordens. Isso é amplamente realizado pela classe CStop. Entre as responsabilidades desta classe estão as seguintes:
- definir os níveis de stoploss e takeprofit
- realizar os cálculos necessários para calcular os níveis de stop
- implementar os níveis de stoploss e takeprofit para a operação principal
- verificar se o nível de stop foi disparado
- conciliar as diferenças entre a MQL4 e MQL5 na implementação dos níveis de stoploss e takeprofit
- definir como os stops devem ser tratados ao longo do tempo (por exemplo, breakeven, stop móvel, etc.)
Os pontos 1-5 serão discutidos neste artigo, enquanto que o 6 será discutido em um artigo separado.
Tipos
Três tipos de stop serão discutidos neste artigo:
- Stop na ponta da corretora - stops que são enviados à corretora juntamente com a solicitação de negociação
- Ordem Stop Pendente - stops que utilizam ordens pendentes que agem como hedge total ou parcial contra a posição principal (MetaTrader 4, MetaTrader 5 no modo hedge) ou como realização parcial ou total da posição principal (MetaTrader 5 no modo netting).
- Stop virtual (stop oculto) - stops que são ocultos da corretora e que são gerenciados localmente pelo EA.
Na MetaTrader 4, o stop na ponta da corretora são as ordens de stoploss e takeprofit e que os traders estão mais familiarizados. Estes são os preços ou os níveis de stop que são enviados à corretora junto com a operação principal. Na versão da MetaTrader 5, o modo hedge usa o mesmo mecanismo que a versão da MetaTrader 4. Por outro lado, para o modo netting, uma ordem de stop pendente será usada para este tipo da CStop, uma vez que o stoploss e o takeprofit são diferentes (aplicados em toda a posição do símbolo ou instrumento).
Uma ordem stop pendente usa ordens pendentes para imitar de alguma forma um stop na ponta da corretora. Assim que as ordens pendentes forem executadas, o EA executaria uma operação de negociação (OrderCloseBy) para fechar a posição principal usando o volume da ordem pendente que foi acionada. Isso é verdade para a versão da MetaTrader 4 e a MetaTrader 5 no modo de hedge. Para a MetaTrader 5 na versão modo netting, a realização parcial ou total da posição principal é feita automaticamente, uma vez que só pode haver uma posição mantida a qualquer momento por símbolo.
Stop principal
O stop principal é o nível de stop que desencadeia a saída de uma posição inteira. Normalmente, este é o stop na ponta da corretora. Quando o stoploss ou takeprofit na ponta da corretora é desencadeada, toda a posição é encerada a mercado, independente se o EA pretende continuar trabalhando nisso ou não. No entanto, se houver vários níveis de stop e não há stop na ponta da corretora, deixar o EA decidir qual é o stop principal provavelmente é uma má ideia. Nesse caso, o programador deve selecionar qual instância da CStop é o stop principal da posição. Isso é útil especialmente para algumas funções e recursos que dependem do stop principal da posição, como o gerenciamento de dinheiro. Uma vez que o stoploss do nível de stop principal leva à saída de toda a posição, ele representa o risco máximo ao abrir uma posição. E, sabendo da instância do stop principal, o EA poderá calcular os lotes em conformidade.
Vale ressaltar que quando um stop é atribuído como stop principal, seu volume sempre será igual ao volume inicial da operação principal. Isso funcionaria bem com stops virtuais e na ponta da corretora, mas não em stops que se baseiam em ordens pendentes. Existem dois problemas associados que levam a essa abordagem.
O primeiro motivo é que, na MetaTrader 4, o preço de entrada da ordem pendente pode ser modificada enquanto a ordem pendente ainda não for acionada. Na MetaTrader 5, isso não é possível, uma vez que uma registro claro das operações de negociação deve ser mantido. Uma nova ordem pendente deve ser emitida e, se bem-sucedida, a antiga deve ser excluída e, a partir daí, o EA deve usar a nova ordem pendente como um novo nível de stop.
O segundo problema é a possibilidade da antiga ordem pendente ser acionada enquanto a ordem pendente de substituição está sendo enviada à corretora. Uma vez que o EA não tem controle sobre o desencadeamento das ordens pendentes (a corretora possui), isso pode levar a problemas como posições remanescentes ou um nível de stop encerrar a posição principal com um volume maior que o devido.
Para evitar esses problemas, a abordagem mais simples seria alocar o volume das ordens pendentes na execução das mesmas, em vez de ajustar o volume das ordens pendentes dinamicamente ao longo da vida da posição principal. No entanto, isso requer que não haja outro ordem stop pendente se o stop principal for do tipo ordem stop pendente.
Volume
Para o nível de stop principal, não há necessidade de atribuir o tamanho do lote deduzido da posição principal, pois assim que ela for acionada, toda a posição deverá ser fechada. No entanto, para os outros tipos de níveis de stop, o volume deveria ser considerado, pois geralmente eles devem ser destinados apenas para o fechamento parcial da posição principal. A alocação é dividida em quatro tipos diferentes:
- Fixa - tamanho do lote fixo
- Porcentagem remanescente - percentual remanescente da posição principal
- Percentagem Total - percentual do lote total (volume inicial) da operação principal
- Restante - o volume remanescente da operação principal.
O lote fixo é a forma mais simples de alocação de volume. No entanto, isso não funcionaria de forma ótima se o EA estiver usando alguma forma de cálculo de lotes dinâmico para cada posição, ou seja, gerenciamento de dinheiro. Isso é ideal apenas para uso quando o lote é fixo durante a operação do EA.
A Percentagem remanescente e o restante são melhor utilizados quando o stop principal é virtual. O Restante impedirá o EA de criar posições remanescentes a partir de volumes que não foram encerrados ou da execução de uma operação de encerramento com um volume superior a transação principal. A Percentagem Remanescente, por outro lado, é usada quando o EA deve fechar a operação não com base no volume inicial da ordem, mas sim no volume atual da posição originada pela ordem.
O percentual total pode ser usado com os stops na ponta da corretora, virtual e pendentes. Os cálculos usando este método são baseados no volume inicial da transação principal.
Uma-Cancela-a-Outra (OCO)
A CStop é sempre representada por um par de valores, sendo cada valor representando o stoploss ou o takeprofit. No entanto, é possível haver um nível unilateral (possuindo o takeprofit e não o stoploss, ou vice-versa) atribuindo o valor zero para qualquer campo. Por padrão, quando um nível de stop é acionado, acontece o cancelamento do outro. A única exceção para isso é quando a instância CStop é um stop principal.
Classe base
A classe base para a CStop (CStopBase) é exibida no seguinte código:
class CStopBase : public CObject { protected: //--- parâmetros da ordem stop bool m_active; bool m_main; string m_name; bool m_oco; double m_stoploss; string m_stoploss_name; ENUM_STOP_TYPE m_stop_type; double m_takeprofit; string m_takeprofit_name; int m_delay; //--- parâmetros de negociação da ordem stop ENUM_VOLUME_TYPE m_volume_type; double m_volume; int m_magic; int m_deviation; string m_comment; //--- parâmetros dos objetos da ordem stop bool m_entry_visible; bool m_stoploss_visible; bool m_takeprofit_visible; color m_entry_color; color m_stoploss_color; color m_takeprofit_color; ENUM_LINE_STYLE m_entry_style; ENUM_LINE_STYLE m_stoploss_style; ENUM_LINE_STYLE m_takeprofit_style; //--- objetos CSymbolManager *m_symbol_man; CSymbolInfo *m_symbol; CAccountInfo *m_account; CTradeManager m_trade_man; CExpertTradeX *m_trade; CTrails *m_trails; CEventAggregator *m_event_man; CStops *m_stops; public: CStopBase(void); ~CStopBase(void); virtual int Type(void) const {return CLASS_TYPE_STOP;} //--- Inicialização virtual bool Init(CSymbolManager*,CAccountInfo*,CEventAggregator*); virtual bool InitAccount(CAccountInfo*); virtual bool InitEvent(CEventAggregator*); virtual bool InitSymbol(CSymbolManager*); virtual bool InitTrade(void); virtual CStops *GetContainer(void); virtual void SetContainer(CStops*); virtual bool Validate(void) const; //--- getters e setters bool Active(void); void Active(const bool); bool Broker(void) const; void Comment(const string); string Comment(void) const; void Delay(int delay); int Delay(void) const; void SetDeviation(const int); int SetDeviation(void) const; void EntryColor(const color clr); void EntryStyle(const ENUM_LINE_STYLE); void EntryVisible(const bool); bool EntryVisible(void) const; void Magic(const int); int Magic(void) const; void Main(const bool); bool Main(void) const; void Name(const string); string Name(void) const; void OCO(const bool oco); bool OCO(void) const; bool Pending(void) const; void StopLoss(const double); double StopLoss(void) const; void StopLossColor(const color); bool StopLossCustom(void); void StopLossName(const string); string StopLossName(void) const; void StopLossVisible(const bool); bool StopLossVisible(void) const; void StopLossStyle(const ENUM_LINE_STYLE); void StopType(const ENUM_STOP_TYPE); ENUM_STOP_TYPE StopType(void) const; string SymbolName(void); void TakeProfit(const double); double TakeProfit(void) const; void TakeProfitColor(const color); bool TakeProfitCustom(void); void TakeProfitName(const string); string TakeProfitName(void) const; void TakeProfitStyle(const ENUM_LINE_STYLE); void TakeProfitVisible(const bool); bool TakeProfitVisible(void) const; bool Virtual(void) const; void Volume(double); double Volume(void) const; void VolumeType(const ENUM_VOLUME_TYPE); ENUM_VOLUME_TYPE VolumeType(void) const; //--- verificação da ordem stop virtual bool CheckStopLoss(COrder*,COrderStop*); virtual bool CheckTakeProfit(COrder*,COrderStop*); virtual bool CheckStopOrder(ENUM_STOP_MODE,COrder*,COrderStop*)=0; virtual bool DeleteStopOrder(const ulong)=0; virtual bool DeleteMarketStop(const ulong)=0; virtual bool OrderModify(const ulong,const double); //--- criação do objeto da ordem stop virtual CStopLine *CreateEntryObject(const long,const string,const int,const double); virtual CStopLine *CreateStopLossObject(const long,const string,const int,const double); virtual CStopLine *CreateTakeProfitObject(const long,const string,const int,const double); //--- cálculo do preço da ordem stop virtual bool Refresh(const string); virtual double StopLossCalculate(const string,const ENUM_ORDER_TYPE,const double); virtual double StopLossCustom(const string,const ENUM_ORDER_TYPE,const double); virtual double StopLossPrice(COrder*,COrderStop*); virtual double StopLossTicks(const ENUM_ORDER_TYPE,const double); virtual double TakeProfitCalculate(const string,const ENUM_ORDER_TYPE,const double); virtual double TakeProfitCustom(const string,const ENUM_ORDER_TYPE,const double); virtual double TakeProfitPrice(COrder*,COrderStop*); virtual double TakeProfitTicks(const ENUM_ORDER_TYPE,const double); //--- stop móvel virtual bool Add(CTrails*); virtual double CheckTrailing(const string,const ENUM_ORDER_TYPE,const double,const double,const ENUM_TRAIL_TARGET); protected: //--- criação de objetos virtual CStopLine *CreateObject(const long,const string,const int,const double); //--- cálculo do preço da ordem stop virtual double LotSizeCalculate(COrder*,COrderStop*); //--- entrada da ordem stop virtual bool GetClosePrice(const string,const ENUM_ORDER_TYPE,double&); //--- saída da ordem stop virtual bool CloseStop(COrder*,COrderStop*,const double)=0; //--- desinicialização virtual void Deinit(void); virtual void DeinitSymbol(void); virtual void DeinitTrade(void); virtual void DeinitTrails(void); };
Para os níveis de stoploss e takeprofit com base no número de pips ou pontos, há pelo menos quatro métodos de classe que precisam ser lembrados:
- O tipo do stop (na ponta da corretora, ordem pendente ou virtual), usando o método StopType
- O tipo do cálculo do volume utilizado, usando o método VolumeType
- O nível de stoploss em pontos (sempre que necessário), usando o método StopLoss
- O nível de takeprofit em pontos (sempre que necessário), usando o método TakeProfit
Todos esses são meros setters sobre os membros de classe, portanto, não há necessidade de detalhar mais esses métodos. Grande parte do restante dos métodos são necessários apenas pela classe em seus cálculos internos. Entre os mais importantes desses métodos protegidos estão os métodos StopLossCalculate e TakeProfitCalculate, cujo código é exibido abaixo:
double CStopBase::StopLossCalculate(const string symbol,const ENUM_ORDER_TYPE type,const double price) { if(!Refresh(symbol)) return 0; if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_LIMIT) return price-m_stoploss*m_symbol.Point(); else if(type==ORDER_TYPE_SELL || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_LIMIT) return price+m_stoploss*m_symbol.Point(); return 0; } double CStopBase::TakeProfitCalculate(const string symbol,const ENUM_ORDER_TYPE type,const double price) { if(!Refresh(symbol)) return 0; if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_LIMIT) return price+m_takeprofit*m_symbol.Point(); else if(type==ORDER_TYPE_SELL || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_LIMIT) return price-m_takeprofit*m_symbol.Point(); return 0; }
Ambos os métodos precisam de três argumentos, todos os quais estão relacionados a operação principal. Os métodos começam primeiro a atualizar o símbolo através do método Refresh, que simplesmente atualiza o gerenciador de símbolos com o símbolo correto a ser usado. Uma vez que o símbolo foi atualizado, ele retorna o valor do stoploss ou takeprofit com base no valor do ponto fornecido para a instância da classe durante a inicialização.
CStops
A classe CStops servirá como container para as instâncias da CStop. Uma instância desta classe terá que ser adicionada dinamicamente ao gerenciador de ordens como um de seus membros. O código a seguir mostra a CStopsBase, que é a classe base para a CStops:
class CStopsBase : public CArrayObj { protected: bool m_active; CEventAggregator *m_event_man; CObject *m_container; public: CStopsBase(void); ~CStopsBase(void); virtual int Type(void) const {return CLASS_TYPE_STOPS;} //--- Inicialização virtual bool Init(CSymbolManager*,CAccountInfo*,CEventAggregator*); virtual CObject *GetContainer(void); virtual void SetContainer(CObject*); virtual bool Validate(void) const; //--- setters e getters virtual bool Active(void) const; virtual void Active(const bool); virtual CStop *Main(void); //--- recuperação virtual bool CreateElement(const int); };
Esta classe é muito semelhante aos outros containers descritos até agora nesta série de artigos.
COrderStop
A COrderStop representa a implementação da CStop para uma operação em específico. Para uma determinada posição, uma CStop pode criar no máximo uma COrderStop. No entanto, um número arbitrário de instâncias da COrderStop pode compartilhar a mesma instância da CStop. Assim, se um EA tiver 3 instâncias diferentes da CStop, normalmente esperamos que cada instância da COrder tenha o mesmo número de instâncias da COrderStop. Se o EA tiver realizado 1000 negociações, o número de instâncias da COrderStop criada será 1000 * 3 = 3000, enquanto o número de instâncias CStop criadas ainda seriam de 3.
A definição da COrderStopBase, a partir da qual a COrderStop se baseia, é exibida no código abaixo:
class COrderStopBase : public CObject { protected: bool m_active; //--- parâmetros do stop double m_volume; CArrayDouble m_stoploss; CArrayDouble m_takeprofit; ulong m_stoploss_ticket; ulong m_takeprofit_ticket; bool m_stoploss_closed; bool m_takeprofit_closed; bool m_closed; ENUM_STOP_TYPE m_stop_type; string m_stop_name; //--- objeto da ordem principal COrder *m_order; //--- objetos do stop CStop *m_stop; CStopLine *m_objentry; CStopLine *m_objsl; CStopLine *m_objtp; COrderStops *m_order_stops; public: COrderStopBase(void); ~COrderStopBase(void); virtual int Type(void) const {return CLASS_TYPE_ORDERSTOP;} //--- Inicialização virtual void Init(COrder*,CStop*,COrderStops*); virtual COrderStops *GetContainer(void); virtual void SetContainer(COrderStops*); virtual void Show(bool); //--- getters e setters bool Active(void) const; void Active(bool active); string EntryName(void) const; ulong MainMagic(void) const; ulong MainTicket(void) const; double MainTicketPrice(void) const; ENUM_ORDER_TYPE MainTicketType(void) const; COrder *Order(void); void Order(COrder*); CStop *Stop(void); void Stop(CStop*); bool StopLoss(const double); double StopLoss(void) const; double StopLoss(const int); void StopLossClosed(const bool); bool StopLossClosed(void); double StopLossLast(void) const; string StopLossName(void) const; void StopLossTicket(const ulong); ulong StopLossTicket(void) const; void StopName(const string); string StopName(void) const; bool TakeProfit(const double); double TakeProfit(void) const; double TakeProfit(const int); void TakeProfitClosed(const bool); bool TakeProfitClosed(void); double TakeProfitLast(void) const; string TakeProfitName(void) const; void TakeProfitTicket(const ulong); ulong TakeProfitTicket(void) const; void Volume(const double); double Volume(void) const; //--- verificação virtual void Check(double&)=0; virtual bool Close(void); virtual bool CheckTrailing(void); virtual bool DeleteChartObject(const string); virtual bool DeleteEntry(void); virtual bool DeleteStopLines(void); virtual bool DeleteStopLoss(void); virtual bool DeleteTakeProfit(void); virtual bool IsClosed(void); virtual bool Update(void) {return true;} virtual void UpdateVolume(double) {} //--- desinicialização virtual void Deinit(void); //--- recuperação virtual bool Save(const int); virtual bool Load(const int); virtual void Recreate(void); protected: virtual bool IsStopLossValid(const double) const; virtual bool IsTakeProfitValid(const double) const; virtual bool Modify(const double,const double); virtual bool ModifyStops(const double,const double); virtual bool ModifyStopLoss(const double) {return true;} virtual bool ModifyTakeProfit(const double){return true;} virtual bool UpdateOrderStop(const double,const double){return true;} virtual bool MoveStopLoss(const double); virtual bool MoveTakeProfit(const double); };
COrderStop está contida pela COrderStops (a ser discutida na próxima seção), que por sua vez é contida pela COrder. No desenvolvimento atual do EA, não há mais necessidade de declarar uma instância da COrderStop. Isso é criado automaticamente pela COrder com base em uma instância particular da CStop.
COrderStops
class COrderStopsBase : public CArrayObj { protected: bool m_active; CArrayInt m_types; COrder *m_order; public: COrderStopsBase(void); ~COrderStopsBase(void); virtual int Type(void) const {return CLASS_TYPE_ORDERSTOPS;} void Active(bool); bool Active(void) const; //--- Inicialização virtual CObject *GetContainer(void); virtual void SetContainer(COrder*); virtual bool NewOrderStop(COrder*,CStop*)=0; //--- verificação virtual void Check(double &volume); virtual bool CheckNewTicket(COrderStop*); virtual bool Close(void); virtual void UpdateVolume(const double) {} //--- ocultando e exibindo as linhas de stop virtual void Show(const bool); //--- recuperação virtual bool CreateElement(const int); virtual bool Save(const int); virtual bool Load(const int); };
Assim como a CStop, isso se parece apenas com um container típico. No entanto, ele contém alguns métodos que refletem os métodos dos objetos cujos ponteiros destinam-se ao armazenamento (COrderStop).
Representação dos Stops no Gráfico
CStopLine é um membro da classe da CStop, cuja principal responsabilidade é a representação gráfica dos níveis de stop no gráfico. Ele possui três funções principais em um EA:
- Mostra os níveis de stop na inicialização de uma instância da COrder
- Atualiza os níveis de stop no evento onde um ou ambos os níveis de stop foram alterados
- Remove as linhas de stop assim que a operação principal é encerrada
Todas essas funções são implementadas através da classe CStop.
A definição da CStopLineBase, a partir da qual a CStopLine é baseado, é exibida abaixo:
class CStopLineBase : public CChartObjectHLine { protected: bool m_active; CStop *m_stop; public: CStopLineBase(void); ~CStopLineBase(void); virtual int Type(void) const {return CLASS_TYPE_STOPLINE;} virtual void SetContainer(CStop*); virtual CStop *GetContainer(void); bool Active(void) const; void Active(const bool); virtual bool ChartObjectExists(void) const; virtual double GetPrice(const int); virtual bool Move(const double); virtual bool SetStyle(const ENUM_LINE_STYLE); virtual bool SetColor(const color); };
Nas versões mais antigas da MetaTrader 4, os níveis de stoploss e takeprofit não são modificáveis pelo método de arraste. Esses níveis tiveram de ser modificados através da janela de ordens ou através do uso de EA's ou scripts. No entanto, a representação gráfica desses níveis ainda pode ser útil, especialmente quando se trata dos stops virtuais.
Verificação da Ordem de Stop
Depois que os níveis de stop foram criados com sucesso para uma determinada posição, o próximo passo seria verificar se o mercado atingiu um determinado nível de stop. Para os stops na ponta da corretora, o processo não é necessário, uma vez que a operação de fechamento é realizada pelo lado do servidor. No entanto, para os stops virtuais e pendentes, na maioria dos casos, cabe ao EA realizar a operação de encerramento.
Para os stops virtuais, o expert advisor é inteiramente responsável por monitorar o movimento do mercado e para verificar se o mercado atingiu ou não um determinado nível de parada. A figura a seguir mostra a operação geral. Assim que o mercado atingir um nível de stop, o expert advisor executa a operação de fechamento apropriada.
Para stops com base nas ordens pendentes, o processo é um pouco mais complexo. A ativação de um nível de stop leva ao acionamento de uma ordem pendente, ou seja, se tornando uma posição. Isso é feito automaticamente na ponta da corretora. Assim, seria da responsabilidade do EA detectar se a ordem pendente ainda está pendente ou se ela foi executada a mercado. Se a ordem pendente já tiver sido acionada, o expert advisor será responsável por fechar a posição principal com o volume da ordem pendente que acabou de ser acionada - uma operação de encerramento por uma ordem oposta.
Em todos os casos, assim que um determinado nível de ordem stop é acionado, o nível de stop é marcado como fechado. Isso é para impedir que um determinado nível de stop seja executado mais de uma vez.
Exemplos
Exemplo 1: Um EA usando Heiken Ashi e Média Móvel, com um único nível de stop (stop principal)
Na maioria dos expert advisors, um stoploss e takeprofit são, muitas vezes suficientes. Nós vamos agora estender o exemplo no artigo anterior (veja Expert Advisor Multiplataforma: Filtros de Tempo) para a adição de stoploss e takeprofit no código fonte. Para fazer isso, primeiro, nós criamos uma nova instância do container (CStops). Em seguida, crie uma instância da CStop e, em seguida, adicione o ponteiro ao container. O ponteiro para o container será eventualmente adicionado ao gerenciador de ordens. O código é exibido abaixo:
int OnInit() { //--- outro código CStops *stops=new CStops(); CStop *main=new CStop("main"); main.StopType(stop_type_main); main.VolumeType(VOLUME_TYPE_PERCENT_TOTAL); main.Main(true); main.StopLoss(stop_loss); main.TakeProfit(take_profit); stops.Add(GetPointer(main)); order_manager.AddStops(GetPointer(stops)); //--- outro código }
A seguir, é exibido os resultados do teste do stop na ponta da corretora na MetaTrader 4. Isso é o que os traders normalmente esperam das operações executadas por um expert advisor na plataforma.
# | Hora | Tipo | Ordem | Tamanho | Preço | S / L | T / P | Lucro | Saldo |
1 | 2017.01.03 10:00 | sell | 1 | 0.30 | 1.04597 | 1.05097 | 1.04097 | ||
2 | 2017.01.03 11:34 | t/p | 1 | 0.30 | 1.04097 | 1.05097 | 1.04097 | 150.00 | 3150.00 |
3 | 2017.01.05 11:00 | sell | 2 | 0.30 | 1.05149 | 1.05649 | 1.04649 | ||
4 | 2017.01.05 17:28 | s/l | 2 | 0.30 | 1.05649 | 1.05649 | 1.04649 | -150.00 | 3000.00 |
Para as ordens stop pendentes, os stops são colocados antecipadamente, como no sl/tp padrão, mas na forma de ordens pendentes. Assim que a ordem pendente for acionada, o expert advisor irá então executar uma operação de encerramento, encerrando a posição principal pelo volume da ordem pendente acionada. No entanto, ao contrário do sl/tp padrão, o EA executa isso no lado do cliente. Isso não será executado a menos que a plataforma de negociação esteja em execução e o EA esteja sendo executado em um gráfico.
# | Hora | Tipo | Ordem | Tamanho | Preço | S / L | T / P | Lucro | Saldo |
1 | 2017.01.03 10:00 | sell | 1 | 0.30 | 1.04597 | 0.00000 | 0.00000 | ||
2 | 2017.01.03 10:00 | buy stop | 2 | 0.30 | 1.05097 | 0.00000 | 0.00000 | ||
3 | 2017.01.03 10:00 | buy limit | 3 | 0.30 | 1.04097 | 0.00000 | 0.00000 | ||
4 | 2017.01.03 11:34 | buy | 3 | 0.30 | 1.04097 | 0.00000 | 0.00000 | ||
5 | 2017.01.03 11:34 | close by | 1 | 0.30 | 1.04097 | 0.00000 | 0.00000 | 150.00 | 3150.00 |
6 | 2017.01.03 11:34 | close by | 3 | 0.00 | 1.04097 | 0.00000 | 0.00000 | 0.00 | 3150.00 |
7 | 2017.01.03 11:34 | delete | 2 | 0.30 | 1.05097 | 0.00000 | 0.00000 | ||
8 | 2017.01.05 11:00 | sell | 4 | 0.30 | 1.05149 | 0.00000 | 0.00000 | ||
9 | 2017.01.05 11:00 | buy stop | 5 | 0.30 | 1.05649 | 0.00000 | 0.00000 | ||
10 | 2017.01.05 11:00 | buy limit | 6 | 0.30 | 1.04649 | 0.00000 | 0.00000 | ||
11 | 2017.01.05 17:28 | buy | 5 | 0.30 | 1.05649 | 0.00000 | 0.00000 | ||
12 | 2017.01.05 17:28 | close by | 4 | 0.30 | 1.05649 | 0.00000 | 0.00000 | -150.00 | 3000.00 |
13 | 2017.01.05 17:28 | close by | 5 | 0.00 | 1.05649 | 0.00000 | 0.00000 | 0.00 | 3000.00 |
14 | 2017.01.05 17:28 | delete | 6 | 0.30 | 1.04649 | 0.00000 | 0.00000 |
Os stops virtuais não enviam nada sobre os stops na operação principal. A corretora só é informada assim que o EA executa uma ordem de encerramento. A tabela a seguir mostra o comportamento do EA usando os stops virtuais. Aqui, assim que o preço-alvo para um nível de stop é acionado, o EA envia uma solicitação de negociação ao servidor para encerrar a operação principal.
# | Hora | Tipo | Ordem | Tamanho | Preço | S / L | T / P | Lucro | Saldo |
1 | 2017.01.03 10:00 | sell | 1 | 0.30 | 1.04597 | 0.00000 | 0.00000 | ||
2 | 2017.01.03 11:34 | close | 1 | 0.30 | 1.04097 | 0.00000 | 0.00000 | 150.00 | 3150.00 |
3 | 2017.01.05 11:00 | sell | 2 | 0.30 | 1.05149 | 0.00000 | 0.00000 | ||
4 | 2017.01.05 17:28 | close | 2 | 0.30 | 1.05649 | 0.00000 | 0.00000 | -150.00 | 3000.00 |
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 1.05097 | 1.04097 | 2017.01.03 10:00:00 | filled | |||
2017.01.03 11:34:38 | 3 | EURUSD | buy | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | tp 1.04097 | ||||
2017.01.05 11:00:00 | 4 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 1.05649 | 1.04649 | 2017.01.05 11:00:00 | filled | |||
2017.01.05 17:28:37 | 5 | EURUSD | buy | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | sl 1.05649 | ||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.30 | 1.04097 | 3 | 0.00 | 0.00 | 150.00 | 3 150.00 | tp 1.04097 |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.30 | 1.05149 | 4 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 5 | EURUSD | buy | out | 0.30 | 1.05649 | 5 | 0.00 | 0.00 | -150.00 | 3 000.00 | sl 1.05649 |
0.00 | 0.00 | 0.00 | 3 000.00 | |||||||||
No modo hedge, as ordens pendentes funcionam basicamente da mesma maneira que a MetaTrader 4, então o EA também executará uma operação de encerramento quando uma ordem pendente tiver sido acionada.
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 10:00:00 | 3 | EURUSD | buy stop | 0.30 / 0.00 | 1.05097 | 2017.01.03 11:34:38 | canceled | |||||
2017.01.03 10:00:00 | 4 | EURUSD | buy limit | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.03 11:34:38 | 5 | EURUSD | close by | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | close #2 by #4 | ||||
2017.01.05 11:00:00 | 6 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 11:00:00 | 7 | EURUSD | buy stop | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | |||||
2017.01.05 11:00:00 | 8 | EURUSD | buy limit | 0.30 / 0.00 | 1.04649 | 2017.01.05 17:28:37 | canceled | |||||
2017.01.05 17:28:37 | 9 | EURUSD | close by | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | close #6 by #7 | ||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | in | 0.30 | 1.04097 | 4 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 4 | EURUSD | buy | out by | 0.30 | 1.04097 | 5 | 0.00 | 0.00 | 150.00 | 3 150.00 | close #2 by #4 |
2017.01.03 11:34:38 | 5 | EURUSD | sell | out by | 0.30 | 1.04597 | 5 | 0.00 | 0.00 | 0.00 | 3 150.00 | close #2 by #4 |
2017.01.05 11:00:00 | 6 | EURUSD | sell | in | 0.30 | 1.05149 | 6 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 7 | EURUSD | buy | in | 0.30 | 1.05649 | 7 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 9 | EURUSD | sell | out by | 0.30 | 1.05149 | 9 | 0.00 | 0.00 | 0.00 | 3 150.00 | close #6 by #7 |
2017.01.05 17:28:37 | 8 | EURUSD | buy | out by | 0.30 | 1.05649 | 9 | 0.00 | 0.00 | -150.00 | 3 000.00 | close #6 by #7 |
0.00 | 0.00 | 0.00 | 3 000.00 | |||||||||
Usando os stops virtuais, normalmente não vemos a marca "close" da maneira que vemos na MetaTrader 4. Em vez disso, a operação de fechamento usa o tipo oposto da operação principal, mas podemos ver no histórico de transações, seja ela comprada/vendida e de entrada ou saída (in/out).
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 11:34:38 | 3 | EURUSD | buy | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.05 11:00:00 | 4 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 17:28:37 | 5 | EURUSD | buy | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | |||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.30 | 1.04097 | 3 | 0.00 | 0.00 | 150.00 | 3 150.00 | |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.30 | 1.05149 | 4 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 5 | EURUSD | buy | out | 0.30 | 1.05649 | 5 | 0.00 | 0.00 | -150.00 | 3 000.00 | |
0.00 | 0.00 | 0.00 | 3 000.00 | |||||||||
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 10:00:00 | 3 | EURUSD | buy stop | 0.30 / 0.00 | 1.05097 | 2017.01.03 11:34:38 | canceled | |||||
2017.01.03 10:00:00 | 4 | EURUSD | buy limit | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.05 11:00:00 | 5 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 11:00:00 | 6 | EURUSD | buy stop | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | |||||
2017.01.05 11:00:00 | 7 | EURUSD | buy limit | 0.30 / 0.00 | 1.04649 | 2017.01.05 17:28:37 | canceled | |||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.30 | 1.04097 | 4 | 0.00 | 0.00 | 150.00 | 3 150.00 | |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.30 | 1.05149 | 5 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 5 | EURUSD | buy | out | 0.30 | 1.05649 | 6 | 0.00 | 0.00 | -150.00 | 3 000.00 | |
0.00 | 0.00 | 0.00 | 3 000.00 | |||||||||
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 10:00:00 | 3 | EURUSD | buy stop | 0.30 / 0.00 | 1.05097 | 2017.01.03 11:34:38 | canceled | |||||
2017.01.03 10:00:00 | 4 | EURUSD | buy limit | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.05 11:00:00 | 5 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 11:00:00 | 6 | EURUSD | buy stop | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | |||||
2017.01.05 11:00:00 | 7 | EURUSD | buy limit | 0.30 / 0.00 | 1.04649 | 2017.01.05 17:28:37 | canceled | |||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.30 | 1.04097 | 4 | 0.00 | 0.00 | 150.00 | 3 150.00 | |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.30 | 1.05149 | 5 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 5 | EURUSD | buy | out | 0.30 | 1.05649 | 6 | 0.00 | 0.00 | -150.00 | 3 000.00 | |
0.00 | 0.00 | 0.00 | 3 000.00 | |||||||||
A tabela a seguir mostra o uso de stops virtuais na MetaTrader 5 no modo netting. Os níveis de stop virtual no modo netting podem parecer os mesmos em modo de hedge, mas o funcionamento interno é diferente.
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 11:34:38 | 3 | EURUSD | buy | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.05 11:00:00 | 4 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 17:28:37 | 5 | EURUSD | buy | 0.30 / 0.30 | 1.05649 | 2017.01.05 17:28:37 | filled | |||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.30 | 1.04097 | 3 | 0.00 | 0.00 | 150.00 | 3 150.00 | |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.30 | 1.05149 | 4 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 17:28:37 | 5 | EURUSD | buy | out | 0.30 | 1.05649 | 5 | 0.00 | 0.00 | -150.00 | 3 000.00 | |
0.00 | 0.00 | 0.00 | 3 000.00 | |||||||||
Exemplo 2: Um EA usando Heiken Ashi e média móvel, com três níveis de stop
Os expert advisors mais complexos muitas vezes exigem mais de um mercado de stoploss e takeprofit. Nós usamos o mesmo método que o exemplo anterior na adição de níveis de stop adicionais, ou seja, os níveis de stop chamados de "stop1" e "stop2":
int OnInit() { //--- outro código CStops *stops=new CStops(); CStop *main=new CStop("main"); main.StopType(stop_type_main); main.VolumeType(VOLUME_TYPE_PERCENT_TOTAL); main.Main(true); main.StopLoss(stop_loss); main.TakeProfit(take_profit); stops.Add(GetPointer(main)); CStop *stop1=new CStop("stop1"); stop1.StopType(stop_type1); stop1.VolumeType(VOLUME_TYPE_PERCENT_TOTAL); stop1.Volume(0.35); stop1.StopLoss(stop_loss1); stop1.TakeProfit(take_profit1); stops.Add(GetPointer(stop1)); CStop *stop2=new CStop("stop2"); stop2.StopType(stop_type2); stop2.VolumeType(VOLUME_TYPE_PERCENT_TOTAL); stop2.Volume(0.35); stop2.StopLoss(stop_loss2); stop2.TakeProfit(take_profit2); stops.Add(GetPointer(stop2)); order_manager.AddStops(GetPointer(stops)); //--- outro código }
A tabela a seguir mostra os resultados de um teste na MetaTrader 4:
# | Hora | Tipo | Ordem | Tamanho | Preço | S / L | T / P | Lucro | Saldo |
1 | 2017.01.03 10:00 | sell | 1 | 0.30 | 1.04597 | 1.05097 | 1.04097 | ||
2 | 2017.01.03 10:00 | buy stop | 2 | 0.11 | 1.04847 | 0.00000 | 0.00000 | ||
3 | 2017.01.03 10:00 | buy limit | 3 | 0.11 | 1.04347 | 0.00000 | 0.00000 | ||
4 | 2017.01.03 10:21 | buy | 3 | 0.11 | 1.04347 | 0.00000 | 0.00000 | ||
5 | 2017.01.03 10:21 | close by | 1 | 0.11 | 1.04347 | 1.05097 | 1.04097 | 27.50 | 3027.50 |
6 | 2017.01.03 10:21 | sell | 4 | 0.19 | 1.04597 | 1.05097 | 1.04097 | ||
7 | 2017.01.03 10:21 | close by | 3 | 0.00 | 1.04347 | 0.00000 | 0.00000 | 0.00 | 3027.50 |
8 | 2017.01.03 10:21 | delete | 2 | 0.11 | 1.04847 | 0.00000 | 0.00000 | ||
9 | 2017.01.03 10:34 | close | 4 | 0.11 | 1.04247 | 1.05097 | 1.04097 | 38.50 | 3066.00 |
10 | 2017.01.03 10:34 | sell | 5 | 0.08 | 1.04597 | 1.05097 | 1.04097 | ||
11 | 2017.01.03 11:34 | t/p | 5 | 0.08 | 1.04097 | 1.05097 | 1.04097 | 40.00 | 3106.00 |
12 | 2017.01.05 11:00 | sell | 6 | 0.30 | 1.05149 | 1.05649 | 1.04649 | ||
13 | 2017.01.05 11:00 | buy stop | 7 | 0.11 | 1.05399 | 0.00000 | 0.00000 | ||
14 | 2017.01.05 11:00 | buy limit | 8 | 0.11 | 1.04899 | 0.00000 | 0.00000 | ||
15 | 2017.01.05 12:58 | buy | 8 | 0.11 | 1.04899 | 0.00000 | 0.00000 | ||
16 | 2017.01.05 12:58 | close by | 6 | 0.11 | 1.04899 | 1.05649 | 1.04649 | 27.50 | 3133.50 |
17 | 2017.01.05 12:58 | sell | 9 | 0.19 | 1.05149 | 1.05649 | 1.04649 | ||
18 | 2017.01.05 12:58 | close by | 8 | 0.00 | 1.04899 | 0.00000 | 0.00000 | 0.00 | 3133.50 |
19 | 2017.01.05 12:58 | delete | 7 | 0.11 | 1.05399 | 0.00000 | 0.00000 | ||
20 | 2017.01.05 16:00 | close | 9 | 0.19 | 1.05314 | 1.05649 | 1.04649 | -31.35 | 3102.15 |
21 | 2017.01.05 16:00 | buy | 10 | 0.30 | 1.05314 | 1.04814 | 1.05814 | ||
22 | 2017.01.05 16:00 | sell stop | 11 | 0.11 | 1.05064 | 0.00000 | 0.00000 | ||
23 | 2017.01.05 16:00 | sell limit | 12 | 0.11 | 1.05564 | 0.00000 | 0.00000 | ||
24 | 2017.01.05 17:09 | sell | 12 | 0.11 | 1.05564 | 0.00000 | 0.00000 | ||
25 | 2017.01.05 17:09 | close by | 10 | 0.11 | 1.05564 | 1.04814 | 1.05814 | 27.50 | 3129.65 |
26 | 2017.01.05 17:09 | buy | 13 | 0.19 | 1.05314 | 1.04814 | 1.05814 | ||
27 | 2017.01.05 17:09 | close by | 12 | 0.00 | 1.05564 | 0.00000 | 0.00000 | 0.00 | 3129.65 |
28 | 2017.01.05 17:09 | delete | 11 | 0.11 | 1.05064 | 0.00000 | 0.00000 | ||
29 | 2017.01.05 17:28 | close | 13 | 0.11 | 1.05664 | 1.04814 | 1.05814 | 38.50 | 3168.15 |
30 | 2017.01.05 17:28 | buy | 14 | 0.08 | 1.05314 | 1.04814 | 1.05814 | ||
31 | 2017.01.05 17:40 | t/p | 14 | 0.08 | 1.05814 | 1.04814 | 1.05814 | 40.00 | 3208.15 |
Conforme mostrado na tabela acima, todos os três níveis de stop foram ativados para o primeiro comércio. Para o nível de stop virtual, o EA realizou um fechamento parcial na operação principal como esperado. Para o nível de stop usando ordens pendentes, assim que a ordem pendente foi executada, o EA realizou um fechamento por operação e deduziu seu volume opreação principal. Finalmente, para o nível de stop principal, que é um stop na ponta da corretora, A principal operação deixou o mercado com o volume restante de 0.08 lotes.
A tabela a seguir mostra os resultados de um teste na MetaTrader 5 no modo hedge:
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 1.05097 | 1.04097 | 2017.01.03 10:00:00 | filled | |||
2017.01.03 10:00:00 | 3 | EURUSD | buy stop | 0.11 / 0.00 | 1.04847 | 2017.01.03 10:21:32 | canceled | |||||
2017.01.03 10:00:00 | 4 | EURUSD | buy limit | 0.11 / 0.11 | 1.04347 | 2017.01.03 10:21:32 | filled | |||||
2017.01.03 10:21:32 | 5 | EURUSD | close by | 0.11 / 0.11 | 1.04347 | 2017.01.03 10:21:32 | filled | close #2 by #4 | ||||
2017.01.03 10:33:40 | 6 | EURUSD | buy | 0.11 / 0.11 | 1.04247 | 2017.01.03 10:33:40 | filled | |||||
2017.01.03 11:34:38 | 7 | EURUSD | buy | 0.08 / 0.08 | 1.04097 | 2017.01.03 11:34:38 | filled | tp 1.04097 | ||||
2017.01.05 11:00:00 | 8 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 1.05649 | 1.04649 | 2017.01.05 11:00:00 | filled | |||
2017.01.05 11:00:00 | 9 | EURUSD | buy stop | 0.11 / 0.00 | 1.05399 | 2017.01.05 12:58:27 | canceled | |||||
2017.01.05 11:00:00 | 10 | EURUSD | buy limit | 0.11 / 0.11 | 1.04899 | 2017.01.05 12:58:27 | filled | |||||
2017.01.05 12:58:27 | 11 | EURUSD | close by | 0.11 / 0.11 | 1.04896 | 2017.01.05 12:58:27 | filled | close #8 by #10 | ||||
2017.01.05 16:00:00 | 12 | EURUSD | buy | 0.19 / 0.19 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 13 | EURUSD | buy | 0.30 / 0.30 | 1.05307 | 1.04807 | 1.05807 | 2017.01.05 16:00:00 | filled | |||
2017.01.05 16:00:00 | 14 | EURUSD | sell stop | 0.11 / 0.00 | 1.05057 | 2017.01.05 17:09:40 | canceled | |||||
2017.01.05 16:00:00 | 15 | EURUSD | sell limit | 0.11 / 0.11 | 1.05557 | 2017.01.05 17:09:40 | filled | |||||
2017.01.05 17:09:40 | 16 | EURUSD | close by | 0.11 / 0.11 | 1.05557 | 2017.01.05 17:09:40 | filled | close #13 by #15 | ||||
2017.01.05 17:28:47 | 17 | EURUSD | sell | 0.11 / 0.11 | 1.05660 | 2017.01.05 17:28:47 | filled | |||||
2017.01.05 17:29:15 | 18 | EURUSD | sell | 0.08 / 0.08 | 1.05807 | 2017.01.05 17:29:15 | filled | tp 1.05807 | ||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 10:21:32 | 3 | EURUSD | buy | in | 0.11 | 1.04347 | 4 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 10:21:32 | 4 | EURUSD | buy | out by | 0.11 | 1.04347 | 5 | 0.00 | 0.00 | 27.50 | 3 027.50 | close #2 by #4 |
2017.01.03 10:21:32 | 5 | EURUSD | sell | out by | 0.11 | 1.04597 | 5 | 0.00 | 0.00 | 0.00 | 3 027.50 | close #2 by #4 |
2017.01.03 10:33:40 | 6 | EURUSD | buy | out | 0.11 | 1.04247 | 6 | 0.00 | 0.00 | 38.50 | 3 066.00 | |
2017.01.03 11:34:38 | 7 | EURUSD | buy | out | 0.08 | 1.04097 | 7 | 0.00 | 0.00 | 40.00 | 3 106.00 | tp 1.04097 |
2017.01.05 11:00:00 | 8 | EURUSD | sell | in | 0.30 | 1.05149 | 8 | 0.00 | 0.00 | 0.00 | 3 106.00 | |
2017.01.05 12:58:27 | 9 | EURUSD | buy | in | 0.11 | 1.04896 | 10 | 0.00 | 0.00 | 0.00 | 3 106.00 | |
2017.01.05 12:58:27 | 10 | EURUSD | buy | out by | 0.11 | 1.04896 | 11 | 0.00 | 0.00 | 27.83 | 3 133.83 | close #8 by #10 |
2017.01.05 12:58:27 | 11 | EURUSD | sell | out by | 0.11 | 1.05149 | 11 | 0.00 | 0.00 | 0.00 | 3 133.83 | close #8 by #10 |
2017.01.05 16:00:00 | 12 | EURUSD | buy | out | 0.19 | 1.05307 | 12 | 0.00 | 0.00 | -30.02 | 3 103.81 | |
2017.01.05 16:00:00 | 13 | EURUSD | buy | in | 0.30 | 1.05307 | 13 | 0.00 | 0.00 | 0.00 | 3 103.81 | |
2017.01.05 17:09:40 | 14 | EURUSD | sell | in | 0.11 | 1.05557 | 15 | 0.00 | 0.00 | 0.00 | 3 103.81 | |
2017.01.05 17:09:40 | 16 | EURUSD | buy | out by | 0.11 | 1.05307 | 16 | 0.00 | 0.00 | 0.00 | 3 103.81 | close #13 by #15 |
2017.01.05 17:09:40 | 15 | EURUSD | sell | out by | 0.11 | 1.05557 | 16 | 0.00 | 0.00 | 27.50 | 3 131.31 | close #13 by #15 |
2017.01.05 17:28:47 | 17 | EURUSD | sell | out | 0.11 | 1.05660 | 17 | 0.00 | 0.00 | 38.83 | 3 170.14 | |
2017.01.05 17:29:15 | 18 | EURUSD | sell | out | 0.08 | 1.05807 | 18 | 0.00 | 0.00 | 40.00 | 3 210.14 | tp 1.05807 |
0.00 | 0.00 | 210.14 | 3 210.14 | |||||||||
Conforme mostrado na tabela acima, o EA funciona de forma um tanto similar na MetaTrader 5 no modo hedge. A mecânica foi a mesma que na MetaTrader 4 para os três tipos de níveis de stop.
A tabela a seguir mostra os resultados de um teste na MetaTrader 5, modo netting:
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 10:00:00 | 3 | EURUSD | buy stop | 0.30 / 0.00 | 1.05097 | 2017.01.03 11:34:38 | canceled | |||||
2017.01.03 10:00:00 | 4 | EURUSD | buy limit | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.03 10:00:00 | 5 | EURUSD | buy stop | 0.11 / 0.00 | 1.04847 | 2017.01.03 10:21:32 | canceled | |||||
2017.01.03 10:00:00 | 6 | EURUSD | buy limit | 0.11 / 0.11 | 1.04347 | 2017.01.03 10:21:32 | filled | |||||
2017.01.03 10:33:40 | 7 | EURUSD | buy | 0.11 / 0.11 | 1.04247 | 2017.01.03 10:33:40 | filled | |||||
2017.01.05 11:00:00 | 8 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 11:00:00 | 9 | EURUSD | buy stop | 0.30 / 0.00 | 1.05649 | 2017.01.05 16:00:00 | canceled | |||||
2017.01.05 11:00:00 | 10 | EURUSD | buy limit | 0.30 / 0.00 | 1.04649 | 2017.01.05 16:00:00 | canceled | |||||
2017.01.05 11:00:00 | 11 | EURUSD | buy stop | 0.11 / 0.00 | 1.05399 | 2017.01.05 12:58:27 | canceled | |||||
2017.01.05 11:00:00 | 12 | EURUSD | buy limit | 0.11 / 0.11 | 1.04899 | 2017.01.05 12:58:27 | filled | |||||
2017.01.05 16:00:00 | 13 | EURUSD | buy | 0.19 / 0.19 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 14 | EURUSD | buy | 0.30 / 0.30 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 15 | EURUSD | sell stop | 0.30 / 0.00 | 1.04807 | 2017.01.05 17:29:15 | canceled | |||||
2017.01.05 16:00:00 | 16 | EURUSD | sell limit | 0.30 / 0.30 | 1.05807 | 2017.01.05 17:29:15 | filled | |||||
2017.01.05 16:00:00 | 17 | EURUSD | sell stop | 0.11 / 0.00 | 1.05057 | 2017.01.05 17:09:40 | canceled | |||||
2017.01.05 16:00:00 | 18 | EURUSD | sell limit | 0.11 / 0.11 | 1.05557 | 2017.01.05 17:09:40 | filled | |||||
2017.01.05 17:28:47 | 19 | EURUSD | sell | 0.11 / 0.11 | 1.05660 | 2017.01.05 17:28:47 | filled | |||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 5 | EURUSD | buy | in/out | 0.30 | 1.04097 | 4 | 0.00 | 0.00 | 40.00 | 3 040.00 | |
2017.01.03 10:21:32 | 3 | EURUSD | buy | out | 0.11 | 1.04347 | 6 | 0.00 | 0.00 | 27.50 | 3 067.50 | |
2017.01.03 10:33:40 | 4 | EURUSD | buy | out | 0.11 | 1.04247 | 7 | 0.00 | 0.00 | 38.50 | 3 106.00 | |
2017.01.05 11:00:00 | 6 | EURUSD | sell | in/out | 0.30 | 1.05149 | 8 | 0.00 | -0.61 | 231.44 | 3 336.83 | |
2017.01.05 12:58:27 | 7 | EURUSD | buy | in/out | 0.11 | 1.04896 | 12 | 0.00 | 0.00 | 20.24 | 3 357.07 | |
2017.01.05 16:00:00 | 8 | EURUSD | buy | in | 0.19 | 1.05307 | 13 | 0.00 | 0.00 | 0.00 | 3 357.07 | |
2017.01.05 16:00:00 | 9 | EURUSD | buy | in | 0.30 | 1.05307 | 14 | 0.00 | 0.00 | 0.00 | 3 357.07 | |
2017.01.05 17:29:15 | 12 | EURUSD | sell | out | 0.30 | 1.05807 | 16 | 0.00 | 0.00 | 157.11 | 3 514.18 | |
2017.01.05 17:09:40 | 10 | EURUSD | sell | out | 0.11 | 1.05557 | 18 | 0.00 | 0.00 | 30.11 | 3 544.29 | |
2017.01.05 17:28:47 | 11 | EURUSD | sell | out | 0.11 | 1.05660 | 19 | 0.00 | 0.00 | 41.44 | 3 585.73 | |
0.00 | -0.61 | 586.34 | 3 585.73 | |||||||||
Aqui, nós encontramos um problema. O nível de stop final fechou em 0.30 lotes em vez de 0.08 lotes como observado nos dois testes anteriores.
Conforme discutido anteriormente, o stoploss e takeprofit padrão na MetaTrader 5 no modo hedge, é diferente dos dos dois anteriores. Assim, o EA converteria a o stop na ponta da corretora em um stop baseado em ordem pendente. No entanto, com esta configuração, o EA já possui dois níveis de stop baseados em ordens pendentes, e um deles é um stop principal. Como também discutido anteriormente, isso levaria a posições remanescentes. O nível de stop loss final ou principal sempre terá um volume igual ao volume inicial da operação principal. E uma vez que houve outros níveis de stop envolvidos, ele pode levar ao nível de stop principal para encerrar a operação principal por um volume maior que a posição remanescente.
Para corrigir isso, uma maneira é configurar o stop principal para ser virtual, ao invés de ser baseado na ponta da corretar ou em ordem pendente. Com esta nova configuração, o EA agora tem 2 stops que são virtuais e um stop que é baseado em ordens pendentes. O resultado de um teste usando esta nova configuração é exibido abaixo.
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 2017.01.03 10:00:00 | filled | |||||
2017.01.03 10:00:00 | 3 | EURUSD | buy stop | 0.11 / 0.00 | 1.04847 | 2017.01.03 10:21:32 | canceled | |||||
2017.01.03 10:00:00 | 4 | EURUSD | buy limit | 0.11 / 0.11 | 1.04347 | 2017.01.03 10:21:32 | filled | |||||
2017.01.03 10:33:40 | 5 | EURUSD | buy | 0.11 / 0.11 | 1.04247 | 2017.01.03 10:33:40 | filled | |||||
2017.01.03 11:34:38 | 6 | EURUSD | buy | 0.08 / 0.08 | 1.04097 | 2017.01.03 11:34:38 | filled | |||||
2017.01.05 11:00:00 | 7 | EURUSD | sell | 0.30 / 0.30 | 1.05149 | 2017.01.05 11:00:00 | filled | |||||
2017.01.05 11:00:00 | 8 | EURUSD | buy stop | 0.11 / 0.00 | 1.05399 | 2017.01.05 12:58:27 | canceled | |||||
2017.01.05 11:00:00 | 9 | EURUSD | buy limit | 0.11 / 0.11 | 1.04899 | 2017.01.05 12:58:27 | filled | |||||
2017.01.05 16:00:00 | 10 | EURUSD | buy | 0.19 / 0.19 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 11 | EURUSD | buy | 0.30 / 0.30 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 12 | EURUSD | sell stop | 0.11 / 0.00 | 1.05057 | 2017.01.05 17:09:40 | canceled | |||||
2017.01.05 16:00:00 | 13 | EURUSD | sell limit | 0.11 / 0.11 | 1.05557 | 2017.01.05 17:09:40 | filled | |||||
2017.01.05 17:28:47 | 14 | EURUSD | sell | 0.11 / 0.11 | 1.05660 | 2017.01.05 17:28:47 | filled | |||||
2017.01.05 17:29:15 | 15 | EURUSD | sell | 0.08 / 0.08 | 1.05807 | 2017.01.05 17:29:15 | filled | |||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 10:21:32 | 3 | EURUSD | buy | out | 0.11 | 1.04347 | 4 | 0.00 | 0.00 | 27.50 | 3 027.50 | |
2017.01.03 10:33:40 | 4 | EURUSD | buy | out | 0.11 | 1.04247 | 5 | 0.00 | 0.00 | 38.50 | 3 066.00 | |
2017.01.03 11:34:38 | 5 | EURUSD | buy | out | 0.08 | 1.04097 | 6 | 0.00 | 0.00 | 40.00 | 3 106.00 | |
2017.01.05 11:00:00 | 6 | EURUSD | sell | in | 0.30 | 1.05149 | 7 | 0.00 | 0.00 | 0.00 | 3 106.00 | |
2017.01.05 12:58:27 | 7 | EURUSD | buy | out | 0.11 | 1.04896 | 9 | 0.00 | 0.00 | 27.83 | 3 133.83 | |
2017.01.05 16:00:00 | 8 | EURUSD | buy | out | 0.19 | 1.05307 | 10 | 0.00 | 0.00 | -30.02 | 3 103.81 | |
2017.01.05 16:00:00 | 9 | EURUSD | buy | in | 0.30 | 1.05307 | 11 | 0.00 | 0.00 | 0.00 | 3 103.81 | |
2017.01.05 17:09:40 | 10 | EURUSD | sell | out | 0.11 | 1.05557 | 13 | 0.00 | 0.00 | 27.50 | 3 131.31 | |
2017.01.05 17:28:47 | 11 | EURUSD | sell | out | 0.11 | 1.05660 | 14 | 0.00 | 0.00 | 38.83 | 3 170.14 | |
2017.01.05 17:29:15 | 12 | EURUSD | sell | out | 0.08 | 1.05807 | 15 | 0.00 | 0.00 | 40.00 | 3 210.14 | |
0.00 | 0.00 | 210.14 | 3 210.14 | |||||||||
O volume total obtido pelos níveis de stop é agora igual ao volume inicial da operação principal.
Exemplo 3: Stops com Gerenciamento de Dinheiro
Em um artigo anterior (veja Expert Advisor Multiplataforma: Controle de Capital), discutiu-se que alguns métodos de controle de capital dependem de um determinado nível de stop (é possível utilizar o takeprofit, mas normalmente se usa o stoploss). Métodos de controle de capital, como o risco fixo fracionado, risco fixo e risco fixo por ponto/pip, muitas vezes exigem um nível de stoploss finito. Não definir esse nível sugere um risco muito grande ou mesmo infinito e, portanto, o volume calculado também seria grande. Para mostrar um expert advisor capaz de usar os objetos de classe mencionados neste artigo com controle de capital, nós modificaremos o primeiro exemplo para que as linhas de código comentadas anteriormente sejam incluídas na compilação.
Primeiro, nós removemos as tags do comentário nas linhas de código para os métodos de controle de capital, conforme mostrado no código abaixo, dentro da função OnInit:
int OnInit() { //--- outro código order_manager=new COrderManager(); money_manager= new CMoneys(); CMoney *money_fixed=new CMoneyFixedLot(0.05); CMoney *money_ff=new CMoneyFixedFractional(5); CMoney *money_ratio=new CMoneyFixedRatio(0,0.1,1000); CMoney *money_riskperpoint=new CMoneyFixedRiskPerPoint(0.1); CMoney *money_risk=new CMoneyFixedRisk(100); money_manager.Add(money_fixed); money_manager.Add(money_ff); money_manager.Add(money_ratio); money_manager.Add(money_riskperpoint); money_manager.Add(money_risk); order_manager.AddMoneys(money_manager); //--- outro código }
Então, no topo do código fonte, nós declaramos uma enumeração personalizada para que possamos criar um parâmetro externo que nos permita selecionar o método de controle de capital a ser usado, na ordem em que foram apresentados no código fonte:
enum ENUM_MM_TYPE { MM_FIXED=0, MM_FIXED_FRACTIONAL, MM_FIXED_RATIO, MM_FIXED_RISK_PER_POINT, MM_FIXED_RISK };
Em seguida, nós declaramos um novo parâmetro de entrada para esta enumeração:
input ENUM_MM_TYPE mm_type=MM_FIXED_FRACTIONAL;
Finalmente, nós devemos vincular esse parâmetro à seleção atual do método de controle de capital dentro da função OnTick:
void OnTick() { //--- manage_trades(); if(symbol_info.RefreshRates()) { signals.Check(); if(signals.CheckOpenLong()) { close_last(); if(time_filters.Evaluate(TimeCurrent())) { Print("Entering buy trade.."); money_manager.Selected((int)mm_type); //use mm_type, cast to 'int' type order_manager.TradeOpen(Symbol(),ORDER_TYPE_BUY,symbol_info.Ask()); } } else if(signals.CheckOpenShort()) { close_last(); if(time_filters.Evaluate(TimeCurrent())) { Print("Entering sell trade.."); money_manager.Selected((int)mm_type); //use mm_type, cast to 'int' type order_manager.TradeOpen(Symbol(),ORDER_TYPE_SELL,symbol_info.Bid()); } } } }
Uma vez que os métodos de controle de capital lidam apenas com o cálculo puro, não há nenhum problema em relação à compatibilidade entre a MQL4 e a MQL5. Os dois exemplos anteriores já mostraram como os níveis de stop funcionam nas duas plataformas. As tabelas a seguir mostram os resultados dos testes na MetaTrader 5 no modo hedge.
A tabela a seguir mostra o resultado do teste usando o controle de capital fracionado fixo. O programado é arriscar 5% da conta. Com um saldo inicial de $3000, nós esperamos que o valor seja de cerca de $150 se ele atingir o stoploss para a primeiro operação. Uma vez que o stoploss e o takeprofit têm o mesmo valor (500 pontos), nós esperamos que a operação seja lucrativa em $150 se atingir o takeprofit.
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.30 / 0.30 | 1.04597 | 1.05097 | 1.04097 | 2017.01.03 10:00:00 | filled | |||
2017.01.03 11:34:38 | 3 | EURUSD | buy | 0.30 / 0.30 | 1.04097 | 2017.01.03 11:34:38 | filled | tp 1.04097 | ||||
2017.01.05 11:00:00 | 4 | EURUSD | sell | 0.32 / 0.32 | 1.05149 | 1.05649 | 1.04649 | 2017.01.05 11:00:00 | filled | |||
2017.01.05 16:00:00 | 5 | EURUSD | buy | 0.32 / 0.32 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 6 | EURUSD | buy | 0.31 / 0.31 | 1.05307 | 1.04807 | 1.05807 | 2017.01.05 16:00:00 | filled | |||
2017.01.05 17:29:15 | 7 | EURUSD | sell | 0.31 / 0.31 | 1.05807 | 2017.01.05 17:29:15 | filled | tp 1.05807 | ||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.30 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.30 | 1.04097 | 3 | 0.00 | 0.00 | 150.00 | 3 150.00 | tp 1.04097 |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.32 | 1.05149 | 4 | 0.00 | 0.00 | 0.00 | 3 150.00 | |
2017.01.05 16:00:00 | 5 | EURUSD | buy | out | 0.32 | 1.05307 | 5 | 0.00 | 0.00 | -50.56 | 3 099.44 | |
2017.01.05 16:00:00 | 6 | EURUSD | buy | in | 0.31 | 1.05307 | 6 | 0.00 | 0.00 | 0.00 | 3 099.44 | |
2017.01.05 17:29:15 | 7 | EURUSD | sell | out | 0.31 | 1.05807 | 7 | 0.00 | 0.00 | 155.00 | 3 254.44 | tp 1.05807 |
0.00 | 0.00 | 254.44 | 3 254.44 | |||||||||
Note que o valor calculado do volume também dependeria da precisão do lote da corretora, determinado pelos parâmetros de lote mínimo e o passo mínimo do lote. Não podemos esperar que o expert advisor sempre faça os cálculos precisos. Com essas restrições, o expert advisor pode achar necessário arredondar o valor em algum momento. O mesmo é verdade para os outros métodos de controle de capital.
Para o controle de capital por risco fixo por ponto, a configuração programada é arriscar $0.1 por ponto de stoploss. Com a configuração de 500 pontos tanto para o stoploss quanto para o takeprofit, nós esperamos que o lucro/perda seja de $50 de qualquer forma.
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.10 / 0.10 | 1.04597 | 1.05097 | 1.04097 | 2017.01.03 10:00:00 | filled | |||
2017.01.03 11:34:38 | 3 | EURUSD | buy | 0.10 / 0.10 | 1.04097 | 2017.01.03 11:34:38 | filled | tp 1.04097 | ||||
2017.01.05 11:00:00 | 4 | EURUSD | sell | 0.10 / 0.10 | 1.05149 | 1.05649 | 1.04649 | 2017.01.05 11:00:00 | filled | |||
2017.01.05 16:00:00 | 5 | EURUSD | buy | 0.10 / 0.10 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 6 | EURUSD | buy | 0.10 / 0.10 | 1.05307 | 1.04807 | 1.05807 | 2017.01.05 16:00:00 | filled | |||
2017.01.05 17:29:15 | 7 | EURUSD | sell | 0.10 / 0.10 | 1.05807 | 2017.01.05 17:29:15 | filled | tp 1.05807 | ||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.10 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.10 | 1.04097 | 3 | 0.00 | 0.00 | 50.00 | 3 050.00 | tp 1.04097 |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.10 | 1.05149 | 4 | 0.00 | 0.00 | 0.00 | 3 050.00 | |
2017.01.05 16:00:00 | 5 | EURUSD | buy | out | 0.10 | 1.05307 | 5 | 0.00 | 0.00 | -15.80 | 3 034.20 | |
2017.01.05 16:00:00 | 6 | EURUSD | buy | in | 0.10 | 1.05307 | 6 | 0.00 | 0.00 | 0.00 | 3 034.20 | |
2017.01.05 17:29:15 | 7 | EURUSD | sell | out | 0.10 | 1.05807 | 7 | 0.00 | 0.00 | 50.00 | 3 084.20 | tp 1.05807 |
0.00 | 0.00 | 84.20 | 3 084.20 | |||||||||
Para o controle de capital de risco fixo, a configuração programada é arriscar $100. O EA, por sua vez, teria que calcular um volume que corresponderia a esse risco estabelecido. O resultado é exibido abaixo.
Ordens |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Horário de abertura | Ordem | Símbolo | Tipo | Volume | Preço | S / L | T / P | Hora | Estado | Comentário | ||
2017.01.03 10:00:00 | 2 | EURUSD | sell | 0.20 / 0.20 | 1.04597 | 1.05097 | 1.04097 | 2017.01.03 10:00:00 | filled | |||
2017.01.03 11:34:38 | 3 | EURUSD | buy | 0.20 / 0.20 | 1.04097 | 2017.01.03 11:34:38 | filled | tp 1.04097 | ||||
2017.01.05 11:00:00 | 4 | EURUSD | sell | 0.20 / 0.20 | 1.05149 | 1.05649 | 1.04649 | 2017.01.05 11:00:00 | filled | |||
2017.01.05 16:00:00 | 5 | EURUSD | buy | 0.20 / 0.20 | 1.05307 | 2017.01.05 16:00:00 | filled | |||||
2017.01.05 16:00:00 | 6 | EURUSD | buy | 0.20 / 0.20 | 1.05307 | 1.04807 | 1.05807 | 2017.01.05 16:00:00 | filled | |||
2017.01.05 17:29:15 | 7 | EURUSD | sell | 0.20 / 0.20 | 1.05807 | 2017.01.05 17:29:15 | filled | tp 1.05807 | ||||
Ofertas |
||||||||||||
Hora | Oferta | Símbolo | Tipo | Direção | Volume | Preço | Ordem | Comissão | Swap | Lucro | Saldo | Comentário |
2017.01.01 00:00:00 | 1 | Saldo | 0.00 | 0.00 | 3 000.00 | 3 000.00 | ||||||
2017.01.03 10:00:00 | 2 | EURUSD | sell | in | 0.20 | 1.04597 | 2 | 0.00 | 0.00 | 0.00 | 3 000.00 | |
2017.01.03 11:34:38 | 3 | EURUSD | buy | out | 0.20 | 1.04097 | 3 | 0.00 | 0.00 | 100.00 | 3 100.00 | tp 1.04097 |
2017.01.05 11:00:00 | 4 | EURUSD | sell | in | 0.20 | 1.05149 | 4 | 0.00 | 0.00 | 0.00 | 3 100.00 | |
2017.01.05 16:00:00 | 5 | EURUSD | buy | out | 0.20 | 1.05307 | 5 | 0.00 | 0.00 | -31.60 | 3 068.40 | |
2017.01.05 16:00:00 | 6 | EURUSD | buy | in | 0.20 | 1.05307 | 6 | 0.00 | 0.00 | 0.00 | 3 068.40 | |
2017.01.05 17:29:15 | 7 | EURUSD | sell | out | 0.20 | 1.05807 | 7 | 0.00 | 0.00 | 100.00 | 3 168.40 | tp 1.05807 |
0.00 | 0.00 | 168.40 | 3 168.40 | |||||||||
Conclusão
Neste artigo, nós discutimos a adição dos níveis de stop em um expert advisor em multiplataforma. As duas plataformas de negociação, apesar de ter muitos recursos paralelos, variam significativamente na forma como os níveis de stop são implementados. Este artigo forneceu um método onde essas diferenças podem ser reconciliadas para que um expert advisor seja compatível com ambas as plataformas.
Programas Usados no Artigo
# |
Nome |
Tipo |
Descrição |
---|---|---|---|
1. |
stops_ha_ma1.mqh |
Arquivo de Cabeçalho |
Arquivo de cabeçalho principal usado para o expert advisor no primeiro exemplo |
2. |
stops_ha_ma1.mq4 | Expert Advisor |
Arquivo fonte principal usado para o expert advisor em MQL4 no primeiro exemplo |
3. |
stops_ha_ma1.mq5 | Expert Advisor | Arquivo fonte principal usado para o expert advisor em MQL5 no primeiro exemplo |
4. | stops_ha_ma2.mqh | Arquivo de Cabeçalho | Arquivo de cabeçalho principal usado para o expert advisor no segundo exemplo |
5. | stops_ha_ma2.mq4 | Expert Advisor |
Arquivo fonte principal usado para o expert advisor em MQL4 no segundo exemplo |
6. | stops_ha_ma2.mq5 | Expert Advisor |
Arquivo fonte principal usado para o expert advisor em MQL5 no segundo exemplo |
7. | stops_ha_ma3.mqh | Arquivo de Cabeçalho | Arquivo de cabeçalho principal usado para o expert advisor no terceiro exemplo |
8. | stops_ha_ma3.mq4 | Expert Advisor |
Arquivo fonte principal usado para o expert advisor em MQL4 no terceiro exemplo |
9. | stops_ha_ma3.mq5 | Expert Advisor |
Arquivo fonte principal usado para o expert advisor em MQL5 no terceiro exemplo |
Arquivos de Classe Apresentados no Artigo
# |
Nome |
Tipo |
Descrição |
---|---|---|---|
1. |
MQLx\Base\Stop\StopBase.mqh |
Arquivo de Cabeçalho |
CStop (classe base) |
2. |
MQLx\MQL4\Stop\Stop.mqh | Arquivo de Cabeçalho | CStop (versão MQL4) |
3. |
MQLx\MQL5\Stop\Stop.mqh | Arquivo de Cabeçalho | CStop (versão MQL5) |
4. | MQLx\Base\Stop\StopsBase.mqh | Arquivo de Cabeçalho | CStops (container CStop, classe base) |
5. | MQLx\MQL4\Stop\Stops.mqh | Arquivo de Cabeçalho | CStops (versão MQL4) |
6. | MQLx\MQL5\Stop\Stops.mqh | Arquivo de Cabeçalho | CStops (versão MQL5) |
7. | MQLx\Base\Stop\StopLineBase.mqh | Arquivo de Cabeçalho | CStopLine (representação gráfica, classe base) |
8. | MQLx\MQL4\Stop\StopLine.mqh | Arquivo de Cabeçalho | CStopLine (versão MQL4) |
9. | MQLx\MQL5\Stop\StopLine.mqh | Arquivo de Cabeçalho | CStopLine (versão MQL5) |
10. | MQLx\Base\Order\OrderStopBase.mqh | Arquivo de Cabeçalho | COrderStop (classe base) |
11. | MQLx\MQL4\Order\OrderStop.mqh | Arquivo de Cabeçalho | COrderStop (versão MQL4) |
12. | MQLx\MQL5\Order\OrderStop.mqh | Arquivo de Cabeçalho | COrderStop (versão MQL5) |
13. |
MQLx\Base\Order\OrderStopVirtualBase.mqh | Arquivo de Cabeçalho |
COrderStopVirtual (nível de stop virtual, classe base) |
14. | MQLx\Base\Order\OrderStopVirtual.mqh | Arquivo de Cabeçalho |
COrderStopVirtual (versão MQL4) |
15. |
MQLx\Base\Order\OrderStopVirtual.mqh | Arquivo de Cabeçalho |
COrderStopVirtual (versão MQL5) |
16. | MQLx\Base\Order\OrderStopPendingBase.mqh | Arquivo de Cabeçalho |
COrderStopPending (nível da ordem stop pendente, classe base) |
17. | MQLx\Base\Order\OrderStopPending.mqh | Arquivo de Cabeçalho |
COrderStopPending (versão MQL4) |
18. |
MQLx\Base\Order\OrderStopPending.mqh | Arquivo de Cabeçalho |
COrderStopPending (versão MQL5) |
19. |
MQLx\Base\Order\OrderStopBroker.mqh | Arquivo de Cabeçalho |
COrderStopBroker (nível da ordem stop na ponta da corretora, classe base) |
20. | MQLx\Base\Order\OrderStopBroker.mqh | Arquivo de Cabeçalho |
COrderStopBroker (versão MQL4) |
21. | MQLx\Base\Order\OrderStopBroker.mqh | Arquivo de Cabeçalho |
COrderStopBroker (versão MQL5) |
22. | MQLx\Base\Order\OrderStopsBase.mqh | Arquivo de Cabeçalho |
COrderStops (container COrderStop, classe base) |
23. | MQLx\Base\Order\OrderStops.mqh | Arquivo de Cabeçalho |
COrderStops (versão MQL4) |
24. | MQLx\Base\Order\OrderStops.mqh | Arquivo de Cabeçalho |
COrderStops (versão MQL5) |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/3620
- 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