Librerías: Expert - página 2

 
fxsaber:

Oh, esos hackers rusos.... Bueno, ¿por qué detener a todos los expertos cuando estás un poco jodido?

Por cierto, también tienes un bug. La estática no funciona.

 
Алексей Тарабанов:

Por cierto, también tienes un error. La estática no funciona.

No he visto un error aquí

Foro sobre trading, sistemas automatizados de trading y prueba de estrategias de trading.

Preguntas de principiantes MQL5 MT5 MetaTrader 5

fxsaber, 2018.08.02 17:09

// Detiene todos los Asesores Expertos si SL se activa.

#include <MT4Orders.mqh>      // https://www.mql5.com/es/code/16006
#include <fxsaber\Expert.mqh> // https://www.mql5.com/es/code/19003

void OnTrade()
{
  static int PrevTotal = OrdersHistoryTotal();
  const int Total = OrdersHistoryTotal();
  
  for (int i = Total - 1; i >= PrevTotal; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderCloseReason() == DEAL_REASON_SL))
    {
      long Chart = ChartFirst();
  
      while (Chart != -1)
      {
        if ((Chart != ChartID()) && EXPERT::Is(Chart))
          EXPERT::Remove(Chart);
  
        Chart = ChartNext(Chart);
      }

      break;
    }        
    
  PrevTotal = Total;
}
 
// El indicador corta todos los intentos de comercio a través de Asesores Expertos. Sólo permite operar con las manos.
// Para evitar la tentación de apagarlo mientras el Terminal está en marcha, el indicador está en modo invisible.

#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0

#include <Symbol.mqh>         // https://www.mql5.com/es/code/18855
#include <fxsaber\Expert.mqh> // https://www.mql5.com/es/code/19003

void MyAlert( const string Str )
{
  string StrArray[];
  
  for (int i = StringSplit(Str, '\n', StrArray) - 1; i >= 0; i--)
    Alert(StrArray[i]);
}

bool NextOnCalculate( const string SymbName = NULL )
{
  const SYMBOL Symb(SymbName);
  
  MqlRates Rates[1] = {0};
  Rates[0].time = TimeCurrent();
          
  return(Symb.IsCustom() ? Symb.CloneRates(Rates) : ChartSetSymbolPeriod(0, _Symbol, _Period));
}

const SYMBOL SymbTimer("Timer");

void OnInit()
{
  if (_Symbol == SymbTimer.Name)
    ChartIndicatorGet(0, 0, ChartIndicatorName(0, 0, 0));    
  else if (SymbTimer.IsExist() && SymbTimer.On() && NextOnCalculate(SymbTimer.Name))
  {
    iCustom(SymbTimer.Name, PERIOD_CURRENT,
            ".." + StringSubstr(MQLInfoString(MQL_PROGRAM_PATH), StringLen(TerminalInfoString(TERMINAL_PATH)) + 5));
    
    SymbTimer.Off(); 
  }
}

string GetExpertData( const ulong Chart = 0 )
{
  string Str = NULL;

  MqlParam Parameters[];
  string Names[];

  if (EXPERT::Parameters(Chart, Parameters, Names))
  {
    Str += "\n" + ::ChartSymbol(Chart) + " " + ::EnumToString(::ChartPeriod(Chart)) + " " + Parameters[0].string_value + "\n";

    const int Amount = ::ArraySize(Names);

    for (int i = 0; i < Amount; i++)
      Str += (string)i + ": "+ Names[i] + " = " + Parameters[i + 1].string_value + "\n";
  }

  return(Str);
}

void Active( const int AlertTime = 5 )
{
  static const uint StartTime = GetTickCount();
  static uint PrevInterval = 0;
  const uint Interval = (GetTickCount() - StartTime) / 1000;
  const string Str = MQLInfoString(MQL_PROGRAM_NAME) + ": I've been watching you for " + TimeToString(Interval, TIME_SECONDS);
    
  long Chart = ChartFirst();

  if (Chart != -1)  
    do
    {
      if (EXPERT::Is(Chart))
        MyAlert(GetExpertData(Chart) + "Removed - " + (string)EXPERT::Remove(Chart));
        
      ChartSetString(Chart, CHART_COMMENT,  Str);
      ChartRedraw(Chart);
    }
    while ((Chart = ChartNext(Chart)) != -1);    
  else if (!(Interval % AlertTime) && (Interval != PrevInterval))
  {
    MyAlert(Str);
    
    PrevInterval = Interval;
  }
}

int OnCalculate( const int, const int, const int, const double &[] )
{
  static int i = 0;
  
  if ((_Symbol == SymbTimer.Name) && NextOnCalculate())
    Active();
  else if (i++ > 0)
    ChartIndicatorDelete(0, 0, ChartIndicatorName(0, 0, ChartIndicatorsTotal(0, 0) - 1));           
    
  return(0);
}


ZY Si reinicia el terminal, a veces puede encontrar (MT5 build 1881) que se cuelga en los procesos. Se puede superar mediante la eliminación forzada de la terminal64.exe proceso correspondiente y la eliminación de MetaTrader 5\Bases\Custom\history\Timer\*.hcc.

 
Gracias. ¡Impresionante!
 

En el artículo, el autor ha destacado con gran detalle los matices de los resultados de esta biblioteca. Recomiendo su lectura.

Методы дистанционного управления работой советников
Методы дистанционного управления работой советников
  • www.mql5.com
В наше время информационных технологий использование различных роботов и электронных экспертов для торговли на финансовых рынках стало довольно обычным явлением. Главными преимуществами электронных экспертов принято считать безукоризненное выполнение алгоритма и безустанная работа 24 часа в сутки. Для их круглосуточного использования арендуются...
 
Andrey Khatimlianskii:

Resulta que a MT4 le falta mucho más que FileSave y FileLoad (que están escritos en 3 líneas cada uno):

  1. No hay CHART_EXPERT_NAME (y no hay nada con qué sustituirlo, salvo después de arreglar todos los demás matices: la etiqueta name).

En mi proyecto, lo resolví de esta manera (con la etiqueta "name"):

      void Update()
      {                
         long chartId = ChartFirst();
         
         while(chartId > 0)
         {
            #ifdef __MQL4__
            string chartEAName = GetChartEAName(chartId);
            #endif 
            
            #ifdef __MQL5__     
            string chartEAName = ChartGetString(chartId, CHART_EXPERT_NAME);
            #endif
            
            if(chartEAName == m_eaName)
            {
               // ...
            }
            
            chartId = ChartNext(chartId);
         }
      }
      
      #ifdef __MQL4__
      string GetChartEAName(const long chartId)
      {
         if(!SaveTemplate(chartId))
         {
            return "";
         }
         
         string result = "";
         
         int handle = FileOpen("ea_name_checking.tpl",FILE_TXT|FILE_READ);
         if(handle == INVALID_HANDLE)
         {
            Print
            (
               "Error in ", __FILE__,", line ", __LINE__,
               ": can't open template file 'ea_name_checking.tpl', error code = ", GetLastError()
            );
         }
         else
         {
            string text = "";
            
            while(!FileIsEnding(handle)) 
            { 
               text = text + FileReadString(handle, (uint)FileSize(handle)) +"\r\n";
            }
            
            SubstringParser eaSectionTextParser(text, "<expert>", "</expert>");            
            string eaSectionText = eaSectionTextParser.Get();
            
            if(StringTrimLeft(StringTrimRight(eaSectionText)) != "")
            {
               SubstringParser eaNameParser(eaSectionText, "name=","\r\n");
               string eaName = StringTrimLeft(StringTrimRight(eaNameParser.Get()));
               
               if(eaName != "")               
               {
                  result = eaName;
               }
            }            
         }
         
         FileClose(handle);
         FileDelete("ea_name_checking.tpl");
         
         return result;
      }
      
      bool SaveTemplate(const long chartId)
      {
         ResetLastError();
         
         if(!ChartSaveTemplate(chartId, "\\Files\\ea_name_checking.tpl"))
         {            
            Print
            (
               "Error in ", __FILE__,", line ", __LINE__,
               ": can't save template to the file 'ea_name_checking.tpl', error code = ", GetLastError()
            );
            
            return false;
         }
         
         return true;
      }      
      #endif

Donde SubstringParser tiene este código:

#property strict

class SubstringParser
{
   private:
      string m_text;
      string m_subStart;
      string m_subEnd;
   
   public:
      SubstringParser(const string text, const string subStart, const string subEnd)
      {
         m_text = text;
         m_subStart = subStart;
         m_subEnd = subEnd;
      }
      
      string Get()
      {
         int startPhraseLengt = StringLen(m_subStart);
         int startPos = StringFind(m_text, m_subStart) + startPhraseLengt;
         int endPos = StringFind(m_text, m_subEnd, startPos);
                 
         if(startPos >= startPhraseLengt && endPos > startPos)
         {
            return StringSubstr(m_text, startPos, endPos - startPos);      
         }
         else
         {
            return "";
         }
      }
};

Es decir, guarda la plantilla del gráfico, la lee, la analiza y encuentra el nombre del Asesor Experto. Sigue siendo una muleta, pero funciona bien hasta ahora (durante un par de meses). Creo que si utiliza un disco duro regular, usted no debe hacer esto con demasiada frecuencia (por ejemplo, en cada tick). Espero CHART_EXPERT_NAME aparecerá en MQL4 algún día .

 
¿Habrá una nueva versión con soporte para ejecutar scripts?
 
Stanislav Korotky:
¿Habrá una nueva versión con soporte para ejecutar scripts?

¿No funcionaeste ejemplo?

 
fxsaber:

¿Este ejemplo no funciona?

No es muy similar a mi caso de uso. La pregunta principal sobre el ejemplo es ¿qué pasa si el nombre del archivo de música se especifica en un parámetro del script, en lugar de lanzarlo a través de variables globales? Puedo enviarte mi proyecto en un mensaje privado.

 
Stanislav Korotky:

No es muy similar a mi caso de uso. La pregunta principal sobre el ejemplo es ¿qué pasa si el nombre del archivo de música se especifica en un parámetro de script en lugar de ser lanzado a través de variables globales?

No recuerdo en absoluto las razones, pero la opción con un parámetro de entrada se sugiere inmediatamente. Dado que el ejemplo es tan retorcido, debe ser una limitación de MT5.