Bibliotecas: MT4Orders - página 33

 
fxsaber:

Todas as alterações estão escritas no cabeçalho.

Sim, mas você não consegue ver quais são elas. Eu lhe mostrarei quando fizer isso.


fxsaber:

ZY: Olhou meus trabalhos na KB... é melhor esquecer o zip.

Exatamente. Os zips não são atualizados (

 
// Lista de modificações:
// 08.02.2019
// Adicionar: o comentário da posição é salvo quando parcialmente fechado via OrderClose.
// Se for necessário alterar o comentário de uma posição aberta no fechamento parcial, ele pode ser definido em OrderClose.
 

Há tarefas que não podem ser resolvidas apenas com MQL4.

Mas o estilo MT4 e o estilo MT5 podem ser usados em paralelo. Aqui está um exemplo dessa combinação.

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação.

Processamento de transações OnTradeTransaction

fxsaber, 2019.02.08 12:37 pm.

Tarefa

As ordens pendentes são colocadas em Netting (podem ser multidirecionais e qualquer número de cada tipo). É necessário colocar seu SL/TP na forma de ordens pendentes Stop/Limit a cada acionamento da ordem pendente original. Nesse caso, as ordens SL/TP devem ser dependentes: se uma ordem for acionada, a segunda será excluída. As ordens pendentes inicial e SL/TP podem ser acionadas parcialmente. O Expert Advisor pode ser recarregado a qualquer momento, incluindo a transferência para outro terminal.


Solução

#include <MT4Orders.mqh> // https://www.mql5.com/pt/code/16006

input int inTP = 100;
input int inSL = 200;
sinput MAGIC_TYPE inMagicNumber = 0;
sinput string inStrKey = "SLTP";

int GetAmountDeals()
{
  return(HistorySelect(0, INT_MAX) ? HistoryDealsTotal() : 0);
}

bool IsMyString( const string Str, const string Key )
{
  return(StringSubstr(Str, 0, StringLen(Key)) == Key);
}

string ToMyString( const string Str, const string Key )
{
  return(Key + Str);
}

struct ORDER
{
  int Type;
  TICKET_TYPE Ticket;
  double Lots;
  double OpenPrice;
  MAGIC_TYPE Magic;
  string Comment;
  
  ORDER() : Type(OrderType()), Ticket(OrderTicket()), Lots(OrderLots()),
            OpenPrice(OrderOpenPrice()), Magic(OrderMagicNumber()), Comment(OrderComment())
  {
  }
};

#define _CS(A) ((!::IsStopped()) && (A))

bool GetPairOrder()
{
  bool Res = false;

  ORDER Order;
  Order.Type = 6 - Order.Type + ((Order.Type & 1) << 1);
  
  for (int i = OrdersTotal() - 1; _CS((i >= 0) && (!Res)); i--)
    Res = OrderSelect(i, SELECT_BY_POS) && (OrderType() == Order.Type) &&
          (OrderMagicNumber() == Order.Magic) && (OrderComment() == Order.Comment);
    
  return(Res);
}

void CheckSLTP( const string Symb, const MAGIC_TYPE Magic, const string Key, const int Slip = 100 )
{    
  for (int i = OrdersTotal() - 1; _CS(i >= 0); i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() > OP_SELL)  &&
        (OrderMagicNumber() == Magic) && (OrderSymbol() == Symb) && IsMyString(OrderComment(), Key))
    {
      const ORDER Order;      
      
      if (!_CS(GetPairOrder()))
      {
        OrderDelete(Order.Ticket);
        
        i = OrdersTotal();
      }
      else if (_CS(OrderLots() < Order.Lots))
      {
        if (OrderDelete(Order.Ticket))
          OrderSend(OrderSymbol(), Order.Type, OrderLots(), Order.OpenPrice, Slip, 0, 0, Order.Comment, Order.Magic);
          
        i = OrdersTotal();          
      }
    }
}

void CheckFill( const string Symb, const MAGIC_TYPE Magic, const string Key, const int SL, const int TP )
{    
  static int PrevDeals = GetAmountDeals();
  
  const double point = SymbolInfoDouble(Symb, SYMBOL_POINT);
  const int NewDeals = GetAmountDeals();
  
  while (_CS(PrevDeals < NewDeals))
  {
    const ulong Ticket = HistoryDealGetTicket(PrevDeals);
    
    if (Ticket && (HistoryDealGetInteger(Ticket, DEAL_MAGIC) == Magic) &&
                  (HistoryDealGetString(Ticket, DEAL_SYMBOL) == Symb) &&
                  !IsMyString(HistoryDealGetString(Ticket, DEAL_COMMENT), Key))
    {
      const double Lots = HistoryDealGetDouble(Ticket, DEAL_VOLUME);
      const double Price = HistoryDealGetDouble(Ticket, DEAL_PRICE);
      const int Type = 1 - (int)HistoryDealGetInteger(Ticket, DEAL_TYPE);
      const double Koef = Type ? -point : point;
      const string Comment = ToMyString((string)Ticket, Key);
      
      if (OrderSend(Symb, Type + OP_BUYLIMIT, Lots, Price - Koef * TP, 0, 0, 0, Comment))
        OrderSend(Symb, Type + OP_BUYSTOP, Lots, Price + Koef * SL, 0, 0, 0, Comment);
    }
    
    PrevDeals++;
  }
}

void System()
{
  CheckFill(_Symbol, inMagicNumber, inStrKey, inSL, inTP);
  CheckSLTP(_Symbol, inMagicNumber, inStrKey);
}

void OnTrade()
{
  System();
}

void OnInit()
{
  OnTrade();
}
 

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Bibliotecas: MT4Orders

fxsaber, 2019.01.13 17:23 PM.

As funções de Kim no MT4 são bastante populares, então baixei todas as fontes do site dele e escrevi um "conversor" simples para elas no MT5.
#include <KimIVToMT5.mqh> // https://c.mql5.com/3/263/KimIVToMT5.mqh

#include "e-Trailing.mq4" // http://www.kimiv.ru/index.php?option=com_remository&Itemid=13&func=fileinfo&id=14

void OnTick() { start(); }

Acontece que o conversor de Kim faz com que alguns outros consultores do MT4 também funcionem no MT5

#include <KimIVToMT5.mqh> // https://c.mql5.com/3/263/KimIVToMT5.mqh

#include "Reaction.mq4"   // https://www.mql5.com/pt/code/24609

void OnTick() { start(); }
 
// Lista de modificações:
// 20.02.2019
// Correção: se não houver nenhuma ordem MT5 de uma transação MT5 existente, a biblioteca aguardará a sincronização do histórico. Em caso de falha, ela informará sobre isso.


Contornou essa armadilha no MT5

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Nova versão do MetaTrader 5 build 2005: calendário econômico, programas MQL5 como serviços e API para linguagem R

fxsaber, 2019.02.20 21:06

Olá, Serviços
// O script captura situações em que uma ordem de transação está ausente no histórico.

#define _CS(A) ((!::IsStopped()) && (A))
#define  TOSTRING(A) #A + " = " + (string)(A) + " "
#define  OFFSET 100

void OnStart()
{
  datetime PrevTime = OFFSET;
  
  while (_CS(true))
  {
    if (HistorySelect(PrevTime - OFFSET, INT_MAX))
    {
      const int Total = HistoryDealsTotal();
      
      for (int i = 0; _CS(i < Total); i++)
      {
        const ulong DealTicket = HistoryDealGetTicket(i);
        const ulong OrderTicket = HistoryDealGetInteger(DealTicket, DEAL_ORDER);        
        
        int Count = 0;
        const ulong StartTime = GetMicrosecondCount();
        
        while ((HistoryOrderGetInteger(OrderTicket, ORDER_TICKET) != OrderTicket) && !HistoryOrderSelect(OrderTicket)) // Se não houver ordem de transação
          Count++;
        
        if (Count)
          Alert(TOSTRING(DealTicket) + TOSTRING(OrderTicket) + TOSTRING(Count) + TOSTRING(GetMicrosecondCount() - StartTime)); // Imprimir a situação
        
        PrevTime = (datetime)HistoryDealGetInteger(DealTicket, DEAL_TIME);
      }
    }
    
    Sleep(0); // Sem isso, o Terminal é suspenso instantaneamente.
  }
}


Se você comentar o Sleep, você eliminará instantaneamente o Terminal ao executá-lo. Mas isso será sobre outra coisa.

Descobriu-se que é fácil detectar uma situação em que uma ordem de negociação está faltando no histórico: há uma negociação, mas sua ordem não está.

O resultado do script no MQ-Demo

Alert: DealTicket = 336236873 OrderTicket = 356249474 Count = 1614408 GetMicrosecondCount()-StartTime = 229880 
Alert: DealTicket = 336236882 OrderTicket = 356249486 Count = 1565921 GetMicrosecondCount()-StartTime = 229998 
Alert: DealTicket = 336236887 OrderTicket = 356249492 Count = 1559345 GetMicrosecondCount()-StartTime = 229788 
Alert: DealTicket = 336236898 OrderTicket = 356249505 Count = 157107 GetMicrosecondCount()-StartTime = 22878 
Alert: DealTicket = 336236901 OrderTicket = 356249508 Count = 1544271 GetMicrosecondCount()-StartTime = 220879 

São necessários mais de 200 ms para esperar que uma ordem de negociação apareça no histórico! Durante todo esse tempo, é impossível determinar, por exemplo, a derrapagem e a duração da execução.

Imagine uma situação em que você precise de um serviço que grave dados apenas sobre posições fechadas em um arquivo. Devido a esse "recurso", é simplesmente impossível fazer isso.


Estou certo de que esse recurso arquitetônico do MT5 não pode ser corrigido de forma alguma?


É difícil contar quantas coisas desse tipo são levadas em consideração na biblioteca.

 
Andrey Khatimlianskii:

Sim, mas você não pode ver em que eles estão. Eu lhe mostrarei quando o fizer.


Exatamente. Os zips não são atualizados.

Quando você baixa os arquivos um a um, as datas de modificação são perdidas. Tenho que navegar por tamanho, mas nem todas as correções alteram o tamanho.

Aqui está uma sugestão:

Adicionar no cabeçalho de TODOS os arquivos a data de modificação, opcionalmente o número da versão e, opcionalmente, o histórico de alterações.

Além dos arquivos, publique seu zip/rar, como algumas pessoas fazem.

 
bool IsTradeAllowed(void)
  {
   return(::MQLInfoInteger(::MQL_TRADE_ALLOWED));       // expressão não booleana
  }
 
Edgar:

A biblioteca está contida em apenas um arquivo. Todo o resto é um enfeite, que não é atualizado há muito tempo.

No entanto, há também o OrderSend_Test2.mq5, que é um teste de estresse do MT5 e da biblioteca. Ele envia spams ao servidor de negociação de modo a interromper a negociação automática.

 

Eu sei. Nesse caso, sim. Mas 3 arquivos foram alterados desde a última vez.

Estou me referindo à metodologia geral que simplifica o controle de versão. Eu mesmo sempre adiciono a data ao cabeçalho do mqh, a data e a versão ao mq5.

E incluir meu arquivo completo (para salvar as datas de modificação) permitirá atualizar tudo sem pensar.
 
Edgar:

Eu sei. Nesse caso, sim. Mas 3 arquivos foram alterados desde a última vez.

Estou me referindo à metodologia geral que simplifica o controle de versão. Eu mesmo sempre adiciono a data ao cabeçalho do mqh, a data e a versão ao mq5.

Ofereceram-me um análogo público do github, já pronto para o trabalho com o QB, onde tudo isso está no modo automático. Mas a velhice não é uma alegria: é complicado.

Talvez essa opção funcione para você.

Eu anuncio as alterações e até mesmo mantenho um chapéu apenas para o MT4Orders, pois não sou o único a usá-lo.

Quanto a outros trabalhos, faço-os silenciosamente.