Discussão do artigo "Usando a API de Dados JSON em seus projetos MQL" - página 2

 
Sara Sabaghi #:

As reclamações não eram para você, é claro, mas para os provedores de conteúdo. Que, por algum motivo, não fornecem dados binários, mas dados de texto ))))

Infelizmente, não podemos mudar esse fato.

 
Edgar Akhmadeev #:

As reclamações não eram para você, é claro, mas para os provedores de conteúdo. Que, por algum motivo, não fornecem dados binários, mas dados de texto ))))

Infelizmente, não podemos mudar esse fato.

porque eles precisam de compatibilidade.

 
Sara Sabaghi #:

Este artigo trata da API e de como usá-la. Você conhece uma API que lhe fornece dados binários de forex? Então, apresente-a.

No próximo ponto, você critica por que usar um computador normal para jogar FIFA2024 quando um computador quântico é mais rápido. A resposta é simples: eu não preciso desse tipo de poder de processamento.
Portanto, a resposta a esse argumento é que a maioria dos dados trocados nessa área na API está na faixa de alguns megabytes, e não há necessidade de velocidade. Além disso, todos os provedores de dados Forex usam padrões como XML, JSON...

Não sou contra o uso do JSON. Eu mesmo o utilizo, mas somente no estágio de desenvolvimento, pois sempre é possível ver uma resposta bem legível no PostMan ou no WireShark.
Eu estava apenas apontando que o artigo, injustamente, nem sequer mencionou o formato binário. Além disso, o formato binário JSON (JSONB), de melhor desempenho, está ganhando força.
Se eu tiver acesso a um servidor, sempre uso dados binários na troca entre o servidor e o cliente. Há apenas um motivo pelo qual o JSON é usado em todos os lugares: legível (para o usuário, mas não para o computador). Para ter menos perguntas idiotas dos usuários.
Mesmo em websockets, onde, em geral, os dados transferidos são muito pequenos, acho razoável usar dados binários. Pelo menos porque é um sistema mais produtivo com menos carga no servidor e no cliente. E se você usar tecnologias de nuvem, o que é razoável na realidade altamente competitiva de hoje, você economizará muito dinheiro no pagamento delas. Afinal de contas, a serialização consome muitos recursos e economiza muito tráfego.
 
Nikolai Semko #:
Não sou contra o uso de JSON. Eu mesmo o utilizo, mas somente no estágio de desenvolvimento, pois sempre é possível ver uma resposta bem legível no PostMan ou no WireShark.
Eu estava apenas apontando que o artigo, injustamente, nem sequer mencionou o formato binário. Além disso, o formato binário JSON (JSONB), de melhor desempenho, está ganhando força.
Se eu tiver acesso a um servidor, sempre uso dados binários na troca entre o servidor e o cliente. Há apenas um motivo pelo qual o JSON é usado em todos os lugares: legível (para o usuário, mas não para o computador). Para ter menos perguntas idiotas dos usuários.
Mesmo em websockets, onde, via de regra, os dados transferidos são muito pequenos, acho razoável usar dados binários. Pelo menos porque é um sistema mais produtivo com menos carga no servidor e no cliente. E se você usar tecnologias de nuvem, o que é razoável na realidade altamente competitiva de hoje, você economizará muito dinheiro no pagamento delas. Afinal de contas, a serialização consome muitos recursos e economiza muito tráfego.

Muito obrigado por dedicar seu tempo para compartilhar suas ideias conosco. Entendo perfeitamente seu ponto de vista, e os pontos que você levantou sobre o uso de formatos binários e JSONB são muito válidos. Você tem razão quando diz que o JSON, em comparação com os formatos binários, não é tão otimizado para o desempenho do sistema, e isso é algo de que muitos desenvolvedores estão cientes.

No artigo que escrevemos, nosso foco principal foi o JSON porque 99% dos provedores de dados financeiros, especialmente no domínio Forex, usam esse padrão para troca de dados, e muitas plataformas e serviços fornecem dados nesse formato. Por esse motivo, não abordamos outros padrões.

Mais uma vez, obrigado por compartilhar sua perspectiva e por apontar esse detalhe importante.

 
Edgar Akhmadeev #:

As reclamações não eram para você, é claro, mas para os provedores de conteúdo. Que, por algum motivo, não fornecem dados binários, mas dados de texto ))))

Infelizmente, não podemos mudar esse fato.

Sim, eu entendo perfeitamente. Além disso, somos obrigados a usar esse padrão porque quase todos os provedores de dados financeiros usam esse método.

 
Olá, aqui está, então o que eu pedi foi que eu o publicasse na comunidade mql5 =.
 //+------------------------------------------------------------------+
 //|API e estratégia técnica da ZIWOX.mq5
 //|Copyright 2024, ssabbaghi |
 //| https://www.mql5.com/pt/users/ssabbaghi
 //+------------------------------------------------------------------+
 #property   copyright    "Sara Sabbaghi"
 #property   link          "https://www.mql5.com/pt/users/ssabbaghi"
 #property   version      "1.0"
 #property   strict

 //---- parâmetros de entrada
 input      string       APIKey         =   "xxxxaquisuakey" ;       // Sua chave de API exclusiva
 input      string       SymbolPrefix   =   "" ;       // Prefixo do símbolo da conta de sua corretora
 input      string       SymbolSuffiex  =   "m" ;       // Sufixo do símbolo da conta de sua corretora
 input      int          shortMAPeriod  =   50 ;       // Período de MA lenta
 input      int          longMAPeriod   =   200 ;     // Período MA rápido
 input      double       Lots           =   0.01 ;     // Volume estático do pedido
 input      int          APICallInterval = 300 ;     // Intervalo entre chamadas de API em segundos (5 minutos)

 // Bibliotecas CatBoost
 #include <JAson.mqh>
CJAVal JsonValue;

 string    OBJPREFIX      =   "ZXAPI" ,
         SymbolRequest  =   "" ,
         APIJSON[];
 bool      APIOK =   false ;
 datetime LastAPICallTime = 0 ; // Armazena o tempo da última chamada à API

 //+------------------------------------------------------------------+
 //| função de inicialização de especialista|
 //+------------------------------------------------------------------+
 int OnInit ()
{
   EventSetTimer ( 30 );
   ArrayResize (APIJSON, 15 );
   SymbolRequest = PureSymbol( Symbol (), SymbolSuffiex, SymbolPrefix); // Preparar o nome real do símbolo 
   Comment ( "Wait a sec, to Get API data..." );
   return ( INIT_SUCCEEDED );
}

 //+------------------------------------------------------------------+
 //| Função de desinicialização de especialista|
 //+------------------------------------------------------------------+
 void OnDeinit ( const int reason)
{
   Comment ( "" );
   ObjectsDeleteAll ( 0 );
}

 //+------------------------------------------------------------------+
 //| Função OnTick() do tique do especialista|
 //+------------------------------------------------------------------+
 void OnTick ()
{
   if (!APIOK) return ;

   double shortMA, longMA;
   long ticket = - 1 ;

   if (IsNewCandle())
   {
      shortMA = iMA ( Symbol (), PERIOD_CURRENT , shortMAPeriod, 0 , MODE_SMA , PRICE_CLOSE );
      longMA = iMA ( Symbol (), PERIOD_CURRENT , longMAPeriod, 0 , MODE_SMA , PRICE_CLOSE );

       // Verificação de sinais de crossover 
       if ( int (APIJSON[ 3 ]) >= 60 ) // se a previsão de alta for maior que 60% 
      {
         if (shortMA > longMA)   // COMPRAR tendência 
         {
             if ( OrdersTotal () == 0 ) {
               MqlTradeRequest request;
               MqlTradeResult result;
               request.action = TRADE_ACTION_DEAL ; // Use TRADE_ACTION_DEAL para comprar 
               request.symbol = Symbol ();
               request.volume = Lots;
               request.type = ORDER_TYPE_BUY ; // Use ORDER_BUY para comprar 
               request.price = SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
               request.sl = 0 ;
               request.tp = 0 ;
               request.deviation = 3 ;
               request.comment = "Buy Order" ;
               if (! OrderSend (request, result)) {
                   Print ( "Error opening buy order: " , GetLastError ());
               }
            }
         }
      }
       if ( int (APIJSON[ 4 ]) >= 60 ) // se a previsão de baixa for maior que 60% 
      {
         if (shortMA < longMA)   // Tendência de venda 
         {
             if ( OrdersTotal () == 0 )
            {
               MqlTradeRequest request;
               MqlTradeResult result;
               request.action = TRADE_ACTION_DEAL ; // Use TRADE_ACTION_DEAL para vender 
               request.symbol = Symbol ();
               request.volume = Lots;
               request.type = ORDER_TYPE_SELL ; // Use ORDER_SELL para vender 
               request.price = SymbolInfoDouble ( Symbol (), SYMBOL_BID );
               request.sl = 0 ;
               request.tp = 0 ;
               request.deviation = 3 ;
               request.comment = "Sell Order" ;
               if (! OrderSend (request, result)) {
                   Print ( "Error opening sell order: " , GetLastError ());
               }
            }
         }
      }
   }
}

 //+------------------------------------------------------------------+
 //| Função OnTimer especializada|
 //+------------------------------------------------------------------+
 void OnTimer ()
{
   // Verifica se o tempo decorrido desde a última chamada à API é maior que o intervalo definido 
   if ( TimeCurrent () - LastAPICallTime >= APICallInterval)
   {
       string APIfilename = SymbolRequest + "_API_Data.json" ; // Nome do arquivo de armazenamento da API 
      APIOK = GetAPI(SymbolRequest, APIKey, APIfilename);   // Obtenha os dados da API e salve-os em APIfilename 
       if (APIOK) JsonDataParse(APIfilename, APIJSON);     // ler os dados JSON e armazená-los na matriz API_DATA 
       Comment ((APIOK ? "API OK" : "API FAILED" ),
               "\nAPI:\n" ,
               "\nBullish Forecast: " , APIJSON[ 3 ],
               "\nBearish Forecast: " , APIJSON[ 4 ],
               "\nRetail traders Long: " , APIJSON[ 5 ],
               "\nRetail traders Short: " , APIJSON[ 6 ],
               "\nMarket Sentiment: " , APIJSON[ 14 ]
              );

       // Atualiza o tempo da última chamada à API 
      LastAPICallTime = TimeCurrent ();
   }
}

 //+------------------------------------------------------------------+
 //| Nova função de verificação de velas|
 //+------------------------------------------------------------------+
 datetime NewCandleTime = TimeCurrent ();
 bool IsNewCandle()
{
   if (NewCandleTime == iTime ( Symbol (), 0 , 0 ))
       return false ;
   else 
   {
      NewCandleTime = iTime ( Symbol (), 0 , 0 );
       return true ;
   }
}

 //+------------------------------------------------------------------+
 //| Função de símbolo puro|
 //+------------------------------------------------------------------+
 string PureSymbol( string symbol, string suffiex, string prefix)
{
   string puresymbol = symbol;
   if (prefix != "" || suffiex != "" )
   {
       StringReplace (puresymbol, suffiex, "" );
       StringReplace (puresymbol, prefix, "" );
   }
   return puresymbol;
}

 //+------------------------------------------------------------------+
 //| Obter dados do fundo do ziwox|
 //+------------------------------------------------------------------+
 datetime LastWebRequest = 0 ; // use essa variável datetime para limitar a API de solicitação com falha
 bool GetAPI( string symbolname, string apikey, string filename)
{
   Print ( "Get API Update" );
   bool NeedToUpdate = false ;

   // Verificar se o arquivo de dados da API está disponível 
   if ( FileGetInteger (filename, FILE_EXISTS , true ) >= 0 )
   {
       // Verifique a hora da última atualização a partir da data e hora de modificação do arquivo 
       if ( TimeLocal () - ( datetime ) FileGetInteger (filename, FILE_MODIFY_DATE , true ) > 900 ) // atualizar dados a cada 15 minutos 
         NeedToUpdate = true ;
   }
   else 
      NeedToUpdate = true ;

   if (NeedToUpdate && TimeLocal () - LastWebRequest > 300 )   // tentar novamente a solicitação de API com falha a cada 5 minutos 
   {
       string cookie = NULL , headers;
       char post[], result[];
       int res;
       string URL = "https://www.ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&amp;apikey=" + apikey + "&apitype=json&pair=" + symbolname;
       ResetLastError ();
       int timeout = 5000 ;
      res = WebRequest ( "GET" , URL, cookie, NULL , timeout, post, 0 , result, headers);
       if (res == - 1 )
      {
         LastWebRequest = TimeLocal ();
         int error = GetLastError ();
         if (error == 4060 )
             Print ( "API data Webrequest Error " , error, " Check your webrequest on Metatrader Expert option." );
         else if (error == 5203 )
             Print ( "HTTP request for " + symbolname + " Data failed!" );
         else 
             Print ( "Unknown HTTP request error(" + string (error) + ")! " + symbolname + " Data" );
         return false ;
      }
       else if (res == 200 )
      {
         LastWebRequest = TimeLocal ();
         string HTTPString = CharArrayToString (result, 0 , 0 , CP_UTF8 );
         Print ( "HTTP request for " + symbolname + " Data successful!" );
         Print (HTTPString);
         if ( StringFind (HTTPString, "invalid api key" , 0 ) != - 1 ) {
             Alert ( "Invalid API key" );
             return false ;
         }
         // Armazene os dados da API em um arquivo de pasta comum 
         int filehandle = FileOpen (filename, FILE_READ | FILE_SHARE_READ | FILE_WRITE | FILE_SHARE_WRITE | FILE_BIN | FILE_COMMON );
         if (filehandle != INVALID_HANDLE )
         {
             FileWriteArray (filehandle, result, 0 , ArraySize (result));
             FileClose (filehandle);
         }
      }
   }
   return true ;
}

 //+------------------------------------------------------------------+
 //| Função de análise de dados JSON|
 //+------------------------------------------------------------------+
 void JsonDataParse( string filename, string &_APIJSON[])
{
   for ( int arraIn = 0 ; arraIn < ArraySize (APIJSON); arraIn++) APIJSON[arraIn] = "" ;

   if ( FileGetInteger (filename, FILE_EXISTS , true ) >= 0 )
   {
       int FileHandle = FileOpen (filename, FILE_READ | FILE_SHARE_READ | FILE_WRITE | FILE_SHARE_WRITE | FILE_BIN | FILE_COMMON );
       char jsonarray[];
       FileReadArray (FileHandle, jsonarray);
       FileClose (FileHandle);

      JsonValue.Clear();
      JsonValue.Deserialize( CharArrayToString (jsonarray, 0 , 0 , CP_UTF8 ));

      _APIJSON[ 0 ] = JsonValue[ 0 ][ "Symbol" ].ToStr();
      _APIJSON[ 1 ] = JsonValue[ 0 ][ "Fundamental Bias" ].ToStr();
      _APIJSON[ 2 ] = JsonValue[ 0 ][ "Fundamental Power" ].ToStr();
      _APIJSON[ 3 ] = JsonValue[ 0 ][ "AI Bullish Forecast" ].ToStr();
      _APIJSON[ 4 ] = JsonValue[ 0 ][ "AI Bearish Forecast" ].ToStr();
      _APIJSON[ 5 ] = JsonValue[ 0 ][ "Retail Long Ratio" ].ToStr();
      _APIJSON[ 6 ] = JsonValue[ 0 ][ "Retail Short Ratio" ].ToStr();
      _APIJSON[ 7 ] = JsonValue[ 0 ][ "Retail Short Lot" ].ToStr();
      _APIJSON[ 8 ] = JsonValue[ 0 ][ "Retail Short pos" ].ToStr();
      _APIJSON[ 9 ] = JsonValue[ 0 ][ "Base COT NET" ].ToStr();
      _APIJSON[ 10 ] = JsonValue[ 0 ][ "Base COT change" ].ToStr();
      _APIJSON[ 11 ] = JsonValue[ 0 ][ "Quote COT NET" ].ToStr();
      _APIJSON[ 12 ] = JsonValue[ 0 ][ "Quote COT change" ].ToStr();
      _APIJSON[ 13 ] = JsonValue[ 0 ][ "COT chng Ratio" ].ToStr();
      _APIJSON[ 14 ] = JsonValue[ 0 ][ "Risk Sentiment" ].ToStr();
   }
}
 //+------------------------------------------------------------------+

Versão para MQL5 METATRADER 5 Fiz alterações no código para que ele funcionasse no Metatrader 5. As alterações também foram feitas com relação à codificação para obter melhores condições na situação comercial atual. Todas as alterações foram feitas para adaptar o código ao Metatrader 5. Ele é funcional. Basta fazer o download desse arquivo e executá-lo. Se necessário, a biblioteca JAson.mqh, que se encontra no código original do nosso companheiro. Meu nome é Ney Borges. Sou do Brasil, estado de Goiás, cidade de Caldas Novas, no meio da floresta do Brasil. Foi muito difícil aprender sozinho, sem ninguém para ajudar, mas aqui na comunidade eu aprendi muito. Obrigado a vocês.

Versão para MQL5 METATRADER 5 Fiz alterações no código para que ele funcionasse no Metatrader 5. As alterações também foram feitas com relação à codificação para melhores condições na situação comercial atual. Todas as alterações foram feitas para adaptar o código ao Metatrader 5. Ele é funcional. Basta fazer o download desse arquivo e executá-lo. Se necessário, a biblioteca JAson.mqh, que se encontra no código original do nosso companheiro. Meu nome é Ney Borges. Sou do Brasil, estado de Goiás, cidade de Caldas Novas, no meio da floresta do Brasil. Foi muito difícil aprender sozinho, sem ninguém para ajudar, mas aqui na comunidade eu aprendi muito. Obrigado a vocês.

Brasil - Goiás - Caldas Novas - Ney Borges

Sara Sabaghi
Sara Sabaghi
  • 2025.01.13
  • www.mql5.com
Trader's profile
 
Ney Borges #:
Se necessário, você pode usar a biblioteca JAson.mqh, que pode ser encontrada no código original do nosso companheiro.

Que maneira horrível de o Google Tradutor funcionar.

Sem a biblioteca JAson, é claro, ele não funcionará.

A biblioteca não está em seu código, ela está aqui, e o autor especificou isso.

JSON Serialization and Deserialization (native MQL)
JSON Serialization and Deserialization (native MQL)
  • www.mql5.com
Сериализация и десериализация JSON протокола. Портированный код со скоростной библиотеки С++.
 
Sara Sabaghi #:

Sim, eu entendo perfeitamente. Além disso, somos obrigados a usar esse padrão porque quase todos os provedores de dados financeiros usam esse método.

Ney Borges #:
Olá, aqui está, então o que eu pedi é que eu postasse na comunidade mql5 =.

Versão para MQL5 METATRADER 5 Fiz alterações no código para que ele funcionasse no Metatrader 5. As alterações também foram feitas com relação à codificação para obter melhores condições na situação comercial atual. Todas as alterações foram feitas para adaptar o código ao Metatrader 5. Ele é funcional. Basta fazer o download desse arquivo e executá-lo. Se necessário, a biblioteca JAson.mqh, que se encontra no código original do nosso companheiro. Meu nome é Ney Borges. Sou do Brasil, estado de Goiás, cidade de Caldas Novas, no meio da floresta do Brasil. Foi muito difícil aprender sozinho, sem ninguém para ajudar, mas aqui na comunidade eu aprendi muito. Obrigado a vocês.

Versão para MQL5 METATRADER 5 Fiz alterações no código para que ele funcionasse no Metatrader 5. As alterações também foram feitas com relação à codificação para melhores condições na situação comercial atual. Todas as alterações foram feitas para adaptar o código ao Metatrader 5. Ele é funcional. Basta fazer o download desse arquivo e executá-lo. Se necessário, a biblioteca JAson.mqh, que se encontra no código original do nosso companheiro. Meu nome é Ney Borges. Sou do Brasil, estado de Goiás, cidade de Caldas Novas, no meio da floresta do Brasil. Foi muito difícil aprender sozinho, sem ninguém para ajudar, mas aqui na comunidade eu aprendi muito. Obrigado a vocês.

Brasil - Goiás - Caldas Novas - Ney Borges

Fiz algumas correções ao código para funcionar no MQL5 gostaria que uma pessoa gentil verificasse e retornasse, obrigado - Sara Sabaghi

//+------------------------------------------------------------------+
//| Ney Borges versão mql5 de ZIWOX API and Technical Strategy.mq5
//|Copyright 2024, ssabbaghi |
//| https://www.mql5.com/pt/users/ssabbaghi
//+------------------------------------------------------------------+
#property   copyright   "Sara Sabbaghi"
#property   link        "https://www.mql5.com/pt/users/ssabbaghi"
#property   version     "1.0"
#property   strict
#property   description "Especialista com funções de rede para a API do ZIWOX"

// Bibliotecas
#include <JAson.mqh>
CJAVal JsonValue;

// Propriedades do Expert para permitir funções de rede
//#propriedade script_show_inputs
//#property script_show_confirm

//---- parâmetros de entrada
input    string      APIKey         =  "sua Key aqui xxxxxxxx";      // Sua chave de API exclusiva
input    string      SymbolPrefix   =  "";      // Prefixo do símbolo da conta de sua corretora
input    string      SymbolSuffiex  =  "m";      // Sufixo do símbolo da conta de sua corretora
input    int         shortMAPeriod  =  50;      // Período de MA lenta
input    int         longMAPeriod   =  200;     // Período MA rápido
input    double      Lots           =  0.01;    // Volume estático do pedido
input    double      BullishThreshold = 60.0;   // Limite para previsão de alta
input    double      BearishThreshold = 60.0;   // Limite para previsão de baixa
input    int         APICallInterval = 300;     // Intervalo entre chamadas de API em segundos (5 minutos)

string   OBJPREFIX      =  "ZXAPI",
         SymbolRequest  =  "",
         APIJSON[];
bool     APIOK          =  false;
datetime LastAPICallTime = 0; // Armazena o tempo da última chamada à API

//+------------------------------------------------------------------+
//| Função para testar a conexão HTTP|
//+------------------------------------------------------------------+
bool TestHTTPConnection()
{
   string cookie=NULL,headers;
   char post[],result[];
   string url="https://www.ziwox.com";
   
   ResetLastError();
   int timeout=5000; 
   
   int res=WebRequest("GET",url,cookie,NULL,timeout,post,0,result,headers);
   
   if(res==-1)
   { 
      int error=GetLastError();
      string msg = "Falha ao conectar, erro "+IntegerToString(error);
      
      // Se houver erro de permissão, mostra mensagem específica
      if(error==4014)
         msg = "Adicione "+url+" em Ferramentas -> Opções -> Expert Advisors -> Permitir WebRequest";
         
      Print("DEBUG: ", msg);
      return(false);
   }
   
   Print("DEBUG: Conexão HTTP testada com sucesso");
   return(true);
}

//+------------------------------------------------------------------+
//| função de inicialização de especialista|
//+------------------------------------------------------------------+
int OnInit()
{
   Print("=== Iniciando Expert Advisor ===");
   
   // Verifica configurações básicas
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      Print("AVISO: Negociação Algorítmica não é permitida");
      // Continua mesmo assim
   }
   
   if(!TerminalInfoInteger(TERMINAL_CONNECTED))
   {
      Print("AVISO: O terminal não está conectado à Internet");
      // Continua mesmo assim
   }
   
   // Configuração do EA
   EventSetTimer(30);
   ArrayResize(APIJSON, 15);
   SymbolRequest = PureSymbol(Symbol(), SymbolSuffiex, SymbolPrefix);
   
   // Prepara e mostra a URL que será usada
   string cleanSymbol = SymbolRequest;
   StringReplace(cleanSymbol, "m", "");
   string apiUrl = StringFormat("https://www.ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&amp;apikey=%s&apitype=json&pair=%s", 
                              APIKey, cleanSymbol);
   
   Print("URL configurada: ", apiUrl);
   Print("IMPORTANTE: Adicione a URL https://www.ziwox.com em:");
   Print("Ferramentas -> Opções -> Expert Advisors -> Permitir WebRequest");
   
   Comment("Iniciando EA...\n",
           "URL que será usada:\n",
           apiUrl,
           "\n\nIMPORTANTE: Configure a URL nas opções do Expert Advisor");
   
   // Testa conexão HTTP, mas não falha se der erro
   if(!TestHTTPConnection())
   {
      Print("AVISO: O teste de conexão HTTP falhou");
      Print("O EA continua tentando se conectar...");
      // Continua mesmo assim
   }
   
   Print("=== Inicialização concluída ===");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Função de desinicialização de especialista|
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Comment("");
   ObjectsDeleteAll(0);
}

//+------------------------------------------------------------------+
//| Função OnTick() do tique do especialista|
//+------------------------------------------------------------------+
void OnTick()
{
   if (!APIOK) return;
   
   double shortMA, longMA;
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   if (IsNewCandle())
   {
      shortMA = iMA(Symbol(),PERIOD_CURRENT, shortMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
      longMA = iMA(Symbol(),PERIOD_CURRENT, longMAPeriod, 0, MODE_SMA, PRICE_CLOSE);

      // Analisando dados JSON para decisões de negociação
      double aiBullishForecast = StringToDouble(APIJSON[3]); // Previsão de alta
      double aiBearishForecast = StringToDouble(APIJSON[4]); // Previsão de baixa

      // Verificação de sinais de crossover
      if (aiBullishForecast >= BullishThreshold && shortMA > longMA) // Se a previsão de alta for maior que o limite
      {
         if (OrdersTotal() == 0) {
            request.action = TRADE_ACTION_DEAL;
            request.symbol = _Symbol;
            request.volume = Lots;
            request.type = ORDER_TYPE_BUY;
            request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            request.deviation = 3;
            request.magic = 123456;
            request.comment = "Buy Order";
            request.type_filling = ORDER_FILLING_FOK;
            
            if(!OrderSend(request, result))
               Print("Error opening buy order: ", GetLastError());
         }
      }
      if (aiBearishForecast >= BearishThreshold && shortMA < longMA) // Se a previsão de baixa for maior que o limite
      {
         if (OrdersTotal() == 0) {
            request.action = TRADE_ACTION_DEAL;
            request.symbol = _Symbol;
            request.volume = Lots;
            request.type = ORDER_TYPE_SELL;
            request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            request.deviation = 3;
            request.magic = 123456;
            request.comment = "Sell Order";
            request.type_filling = ORDER_FILLING_FOK;
            
            if(!OrderSend(request, result))
               Print("Error opening sell order: ", GetLastError());
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Função para verificar se a URL está permitida
//+------------------------------------------------------------------+
bool IsURLAllowed()
{
   string url = "https://www.ziwox.com";
   string cookie=NULL, headers;
   char post[], result[];
   ResetLastError();
   
   int res = WebRequest("GET", url, cookie, NULL, 5000, post, 0, result, headers);
   
   if(res == -1)
   {
      int error = GetLastError();
      if(error == 4014)
      {
         Comment("ATENÇÃO: URL não permitida",
                 "1. Vá em Ferramentas -> Opções -> Expert Advisors\n",
                 "2. Marque 'Permitir WebRequest para as URLs listadas abaixo'\n",
                 "3. Adicione a URL: ", url, "\n",
                 "4. Clique em OK");
         return false;
      }
   }
   return true;
}

//+------------------------------------------------------------------+
//| Função OnTimer especializada|
//+------------------------------------------------------------------+
void OnTimer()
{
   // Verifica se a URL está permitida antes de fazer a chamada
   if(!IsURLAllowed())
   {
      Print("DEBUG: URL não está permitida. Aguardando configuração...");
      return;
   }

   if (TimeCurrent() - LastAPICallTime >= APICallInterval)
   {
      string APIfilename = SymbolRequest + "_API_Data.json";
      
      // Prepara a URL para mostrar no comentário
      string cleanSymbol = SymbolRequest;
      StringReplace(cleanSymbol, "m", "");
      string apiUrl = StringFormat("https://www.ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&amp;apikey=%s&apitype=json&pair=%s", 
                                 APIKey, cleanSymbol);
      
      // Mostra que está fazendo a chamada
      Comment("Fazendo chamada à API...\n",
              "URL: ", apiUrl,
              "\n\nAguarde...");
      
      APIOK = GetAPI(SymbolRequest, APIKey, APIfilename);
      
      if (APIOK) {
         JsonDataParse(APIfilename, APIJSON);
         Comment("=== API OK ===\n",
                 "URL: ", apiUrl, "\n",
                 "Última atualização: ", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), "\n",
                 "\nDados recebidos:",
                 "\nSymbol: ", APIJSON[0],
                 "\nÚltimo Preço: ", APIJSON[1],
                 "\nViés Fundamental: ", APIJSON[2],
                 "\nPrevisão de Alta: ", APIJSON[3], "%",
                 "\nPrevisão de Baixa: ", APIJSON[4], "%",
                 "\nPosições Compradas: ", APIJSON[5],
                 "\nPosições Vendidas: ", APIJSON[6],
                 "\nTendência D1: ", APIJSON[7],
                 "\nRSI D1: ", APIJSON[8],
                 "\nPermitido Operar: ", APIJSON[9]
                 );
      } else {
         Comment("=== FALHA NA API ===\n",
                 "URL tentada: ", apiUrl, "\n",
                 "Hora: ", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), "\n",
                 "\nVerifique:",
                 "\n1. Se a URL for permitida em Ferramentas -> Opções -> Expert Advisors -> WebRequest",
                 "\n2. Se sua conexão com a Internet estiver funcionando",
                 "\n3. Se o símbolo estiver correto"
                 );
      }

      LastAPICallTime = TimeCurrent();
   }
}

//+------------------------------------------------------------------+
//| Função para verificar se é um novo candle
//+------------------------------------------------------------------+
bool IsNewCandle()
{
   static datetime lastCandleTime = 0;
   datetime currentCandleTime = iTime(Symbol(), 0, 0);
   if (currentCandleTime != lastCandleTime)
   {
      lastCandleTime = currentCandleTime;
      return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| Função de símbolo puro|
//+------------------------------------------------------------------+
string PureSymbol(string symbol, string suffiex, string prefix)
{
   string puresymbol = symbol;
   if (prefix != "" || suffiex != "")
   {
      StringReplace(puresymbol, suffiex, "");
      StringReplace(puresymbol, prefix, "");
   }
   return puresymbol;
}

//+------------------------------------------------------------------+
//| Função para verificar a configuração do WebRequest
//+------------------------------------------------------------------+
bool CheckWebRequestSettings()
{
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
   {
      Print("ERRO: DLLs não são permitidas!");
      return false;
   }
   
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      Print("ERRO: Negociação Algorítmica não é permitida!");
      return false;
   }
   
   if(!MQLInfoInteger(MQL_DLLS_ALLOWED))
   {
      Print("ERRO: DLLs não são permitidas para este Expert!");
      return false;
   }
   
   return true;
}

//+------------------------------------------------------------------+
//| Função para verificar a conexão com o servidor
//+------------------------------------------------------------------+
bool CheckServerConnection()
{
   int socket = SocketCreate();
   
   if(socket != INVALID_HANDLE)
   {
      // Tenta se conectar ao servidor da ZIWOX (porta 80 para HTTP)
      if(SocketConnect(socket, "www.ziwox.com", 80, 1000))
      {
         Print("DEBUG: Conexão com servidor testada com sucesso");
         // Verifica se está realmente conectado
         if(SocketIsConnected(socket))
         {
            SocketClose(socket);
            return true;
         }
      }
      else
      {
         Print("DEBUG: Falha ao conectar com o servidor: ", GetLastError());
      }
      SocketClose(socket);
   }
   else
   {
      Print("DEBUG: Falha ao criar socket: ", GetLastError());
   }
   return false;
}

//+------------------------------------------------------------------+
//| Função para obter dados da API|
//+------------------------------------------------------------------+
bool GetAPI(string symbolname, string apikey, string filename)
{
   if(!TestHTTPConnection())
   {
      Print("DEBUG: Falha no teste de conexão HTTP");
      return false;
   }

   string headers = "Content-Type: application/json\r\nAccept: application/json\r\n";
   char post[], result[];
   string cookie=NULL;
   int res;
   
   // Remover o sufixo 'm' do símbolo para a API
   string cleanSymbol = symbolname;
   StringReplace(cleanSymbol, "m", "");
   
   string URL = "https://www.ziwox.com/terminal/services/API/V1/fulldata.php";
   string params = StringFormat("?expn=ziwoxuser&apikey=%s&apitype=json&pair=%s", 
                              apikey, cleanSymbol);
   
   Print("DEBUG: Preparando requisição...");
   Print("DEBUG: URL completa: ", URL + params);
   
   URL = URL + params;
   
   string body = StringFormat("{\"apikey\":\"%s\",\"pair\":\"%s\"}", apikey, cleanSymbol);
   StringToCharArray(body, post, 0, WHOLE_ARRAY, CP_UTF8);
   
   Print("DEBUG: Corpo da requisição: ", body);
   
   // Tenta fazer a requisição
   Print("DEBUG: Iniciando WebRequest...");
   res = WebRequest("GET", URL, cookie, NULL, 5000, post, 0, result, headers);
   Print("DEBUG: Código de resposta WebRequest: ", res);
   
   if(res == -1)
   {
      int error = GetLastError();
      Print("DEBUG: GetLastError retornou: ", error);
      return false;
   }
   
   if(res != 200)
   {
      Print("DEBUG: Resposta HTTP diferente de 200: ", res);
      return false;
   }
   
   string response = CharArrayToString(result, 0, WHOLE_ARRAY, CP_UTF8);
   
   // Remover uma tag <pre> da resposta
   StringReplace(response, "<pre>", "");
   StringReplace(response, "</pre>", "");
   
   Print("DEBUG: Resposta recebida (primeiros 500 caracteres): ", StringSubstr(response, 0, 500));
   Print("DEBUG: Tamanho total da resposta: ", StringLen(response));
   
   if(StringFind(response, "invalid api key") >= 0)
   {
      Print("DEBUG: Chave de API inválida encontrada na resposta");
      Alert("Invalid API key");
      return false;
   }
   
   // Tenta salvar a resposta
   Print("DEBUG: Tentando salvar resposta no arquivo: ", filename);
   int filehandle = FileOpen(filename, FILE_WRITE|FILE_BIN|FILE_COMMON);
   if(filehandle != INVALID_HANDLE)
   {
      // Converte a resposta para array de caracteres
      char responseArray[];
      StringToCharArray(response, responseArray, 0, StringLen(response));
      
      // Salva no arquivo
      FileWriteArray(filehandle, responseArray);
      FileClose(filehandle);
      Print("DEBUG: Arquivo salvo com sucesso");
      return true;
   }
   
   Print("DEBUG: Falha ao salvar arquivo");
   return false;
}

//+------------------------------------------------------------------+
//| Função para analisar dados JSON|
//+------------------------------------------------------------------+
void JsonDataParse(string filename, string &_APIJSON[])
{
   for (int arraIn = 0; arraIn < ArraySize(APIJSON); arraIn++) 
      APIJSON[arraIn] = "";

   if (FileGetInteger(filename, FILE_EXISTS, true) >= 0)
   {
      int FileHandle = FileOpen(filename, FILE_READ|FILE_BIN|FILE_COMMON);
      if(FileHandle != INVALID_HANDLE)
      {
         char jsonarray[];
         FileReadArray(FileHandle, jsonarray);
         FileClose(FileHandle);

         JsonValue.Clear();
         string jsonString = CharArrayToString(jsonarray, 0, WHOLE_ARRAY, CP_UTF8);
         Print("JSON Recebido: ", jsonString); // Depurar
         
         if(JsonValue.Deserialize(jsonString))
         {
            _APIJSON[0] = JsonValue[0]["Symbol"].ToStr();
            _APIJSON[1] = JsonValue[0]["Last Price"].ToStr();
            _APIJSON[2] = JsonValue[0]["Base Fundamental Bias"].ToStr();
            _APIJSON[3] = JsonValue[0]["AI Bullish Forecast"].ToStr();
            _APIJSON[4] = JsonValue[0]["AI Bearish Forecast"].ToStr();
            _APIJSON[5] = JsonValue[0]["Retail Long Ratio"].ToStr();
            _APIJSON[6] = JsonValue[0]["Retail Short Ratio"].ToStr();
            _APIJSON[7] = JsonValue[0]["D1 Trend"].ToStr();
            _APIJSON[8] = JsonValue[0]["D1 RSI"].ToStr();
            _APIJSON[9] = JsonValue[0]["Allow To Trade"].ToStr();
            
            Print("Dados processados:");
            Print("Symbol: ", _APIJSON[0]);
            Print("Last Price: ", _APIJSON[1]);
Discussing the article: "Using JSON Data API in your MQL projects"
Discussing the article: "Using JSON Data API in your MQL projects"
  • 2025.01.17
  • Edgar Akhmadeev
  • www.mql5.com
Check out the new article: Using JSON Data API in your MQL projects . Author: Sara Sabaghi...
 
Ney Borges #:

Fiz algumas correções ao código para funcionar no MQL5 gostaria que uma pessoa gentil verificasse e retornasse, obrigado - Sara Sabaghi

Olá, cara

Obrigado por compartilhar seu código. Sim, eu o testei. Ele funciona bem

API de dados Forex da Ziwox

 
Nikolai Semko #:

Mudou para binário. O tamanho dos mesmos dados agora é de 1,2 Mb. A análise das matrizes de estruturas necessárias agora leva 5 milissegundos.

Isso é um pouco demais para você. Aqui são necessários 12 ms, mas os dados são de 80 Mb.