Características del lenguaje mql5, sutilezas y técnicas - página 3

 
fxsaber:

¿Qué OnTradeTransaction puede haber en un script de trading? No en tu código, sino en el script de comercio de otra persona.
¿De verdad cree que se puede escribir un robot de trading completo en un script?
 
Amigos, por favor, acerquémonos al tema: me gustaría ver ejemplos de aplicación de tal o cual afirmación. No necesariamente el código, si hay mucho, se puede describir la lógica, por ejemplo, enviar la solicitud para asegurarse de que se envía, mirar allí, si se obtiene tal y tal código de retorno, hacer tal y tal. Es decir, ejemplos de la forma más fiable de obtener datos.

De lo contrario, si discutimos, pasaremos de un tema útil a varias páginas de discusiones. Luego hay que limpiarlo todo para dejar la esencia... Exactamente me gustaría la esencia de tal o cual proceso. Que haya varias versiones de alguna implementación de algo. Se podrán discutir las ventajas y desventajas de cada método.

Luego, cuando se acumula suficiente información útil diferente, se piensa en acumularla toda en una tabla. Y reponerla constantemente cuando se acumulen las próximas fichas útiles.
Creo que esto será útil para todos.
 
Pregunta: cómo convertir un número a los sistemas octal y hexadecimal.

Respuestas:
1.

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

8 y 16 ricas

Taras Slobodyanik, 2017.02.24 22:16

string DecToHex(int n)
  {
   string s = "", c;
   while(n != 0)
     {
      if(n%16<10)
         c=CharToStr(n%16+'0');
      else
         c=CharToStr(n%16+'A'-10);
      s = c + s;
      n = n / 16;
     }
   return(s);
  }
2.

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

8 y 16 ricas

Maxim Kuznetsov, 2017.02.24 22:20

De repente, StringFormat, PrintFormat :-)

PrintFormat("Hex %x y octal %o",1122,1122);
3.

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

8 y 16 ricas

fxsaber, 2017.02.24 22:21

string NumToString( uint Num, const uint Scale = 10 )
{
  static const string digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                                  "A", "B", "C", "D", "E", "F", "G", "H", "I", "K",
                                  "L", "M", "N", "O", "P", "Q", "R", "S", "T", "V", "X", "Y", "Z"};
  
  string Str = (Num == 0) ? "0" : "";
  
  while (Num > 0)
  {
    Str = digits[Num % Scale] + Str;
    
    Num /= Scale;
  }
  
  return(Str);
}

void OnStart()
{
  Print(NumToString(123, 8));
  Print(NumToString(123, 16));
}



 
prostotrader:
¿De verdad cree que se puede escribir un robot de trading completo en un script?
Puedes
 
Alexey Kozitsyn:

Mueve la discusión de los compañeros fxsaber y prostotrader a un hilo aparte, si hay discusiones aquí, el hilo perderá su relevancia práctica. Cuando den con una solución real, la publicarán aquí. Y en mi opinión, esto no debería ser una rama de dudas o de investigación. Debe ser una rama de soluciones prácticas. Y si algunas personas tienen visiones diferentes del tema, que lo discutan en otro lugar.

<puesto a eliminar

Dejemos que se encuentre la verdad. Tuve tiempo de pensarlo y decidí publicarlo, y Vitya (Vinin) a quien pregunté y pedí que disipara mis dudas, también sugirió publicar una discusión (confirmando mis dudas sobre la eliminación) - que se encuentre la verdad. Creo que eso sería lo correcto. De todos modos, voy a empezar a tabularlo más tarde, así que puedo publicarlo aquí a medida que se vaya llenando.
 
prostotrader:

No hay que esperar unos milisegundos.

El mensaje llegará en OnTradeTransaction

ver código

¿Cuál es el objetivo de su mensaje? Llegará en OnTradeTransaction(), y qué, significa que tenemos que esperar el evento. Esperamos de todos modos. El significado del mensaje de fxsaber es que después de ejecutar OrderSend(), la información sobre la acción ejecutada no aparece inmediatamente en el terminal. A algunos les gusta esperar a OnTradeTransaction(), mientras que a otros les gusta ver una orden o una transacción en la lista. Esta es la diferencia con respecto a MT4, como ejemplo. En M4, después de OrderSend(), la orden ya está en la lista de órdenes, y después de OrderClose(), la orden siempre está en el historial.

 
Artyom Trishkin:
Dejemos que se encuentre la verdad. Tuve tiempo de pensarlo y decidí dejarlo, y Vitya (Vinin), a quien pedí y pedí que disipara mis dudas, también sugirió dejar la discusión (confirmando mis dudas sobre el borrado) - que nazca la verdad. Creo que eso sería lo correcto. De todos modos, voy a empezar a tabularlo más tarde, para publicarlo aquí a medida que se vaya llenando.
En las discusiones con prostotrader puede que no surja la verdad, no es por eso que las inicia. Como siempre, no sabe ni de qué habla.
 
¿Qué tipo de argumento hay de todas formas? En este caso no hay disputa. fxsaber nos ha recordado una característica del terminal que está realmente indocumentada y que todo el mundo necesita conocer, ya que de lo contrario habrá problemas a la hora de desarrollar EAs, que tendrás que encontrar y limpiar después.
 
Artyom Trishkin:
Dejemos que se encuentre la verdad...

¡Artyom!

Es usted un hombre razonable y políticamente correcto.

¿Qué verdad? Sabes exactamente de qué estamos hablando.

fxsaber escribió un guión (no está mal), pero nadie lo alabó, así que

intenta recordarlo en cada hilo.

¡Bien hecho!

Pero aquí está el problema, no se puede utilizar OnTradeTransaction en este script, por lo que tiene que "rodar bolas" (como Sleep u otro temporizador) de "Sr. OnTradeTransaction".

¡Y por supuesto, "preocuparse" por otros usuarios que aún no saben que SCRIPT es mejor que COUNTER!

YDmitry Fedoseev siempre está en contra de lo que digo, sin importar si tengo razón o no.

La verdad no se puede encontrar aquí porque no es una causa, sino una causa personal la que sale a relucir.

 
class ORDERSEND  
{
private:
  static const bool IsTester;
  
  static bool Waiting( const bool FlagInit = false )
  {
    static ulong StartTime = 0;

    const bool Res = FlagInit ? false : (::GetMicrosecondCount() - StartTime < ORDERSEND::OrderSend_MaxPause);

    if (FlagInit)
      StartTime = ::GetMicrosecondCount();
    else if (Res)
      ::Sleep(0);

    return(Res);
  }

  static bool EqualPrices( const double Price1, const double Price2, const int digits)
  {
    return(::NormalizeDouble(Price1 - Price2, digits) == 0);
  }

  static bool HistoryDealSelect( MqlTradeResult &Result )
  {
    if ((Result.deal == 0) && (Result.order != 0))
    {
      if (::HistorySelectByPosition(::HistoryOrderGetInteger(Result.order, ORDER_POSITION_ID)))
        for (int i = ::HistoryDealsTotal() - 1; i >= 0; i--)
        {
          const ulong DealTicket = ::HistoryDealGetTicket(i);

          if (Result.order == ::HistoryDealGetInteger(DealTicket, DEAL_ORDER))
          {
            Result.deal = DealTicket;

            break;
          }
        }
    }

    return(::HistoryDealSelect(Result.deal));
  }

#define TMP_ORDERSEND_BENCHMARK(A) \
  static ulong Max##A = 0;         \
                                   \
  if (Interval##A > Max##A)        \
  {                                \
    ORDERSEND_BENCHMARK            \
                                   \
    Max##A = Interval##A;          \
  }

  static void OrderSend_Benchmark( const ulong Interval1, const ulong Interval2 = 0 )
  {
    #ifdef ORDERSEND_BENCHMARK
      TMP_ORDERSEND_BENCHMARK(1)
      TMP_ORDERSEND_BENCHMARK(2)
    #endif // ORDERSEND_BENCHMARK

    return;
  }

#undef TMP_ORDERSEND_BENCHMARK

#define WHILE(A) while ((!(Res = (A))) && ORDERSEND::Waiting())

public:
  static uint OrderSend_MaxPause; // максимальное время на синхронизацию в мкс.
  
  // Полностью синхронизированный с торговым окружением OrderSend.
  // По окончании работы ГАРАНТИРОВАННО и за МИНИМАЛЬНОЕ время доступно корректное торговое окружение.
  // По скорости ничем не уступает связке OrderSendAsync + OnTradeTransaction.
  // Учтены MT5-нюансы: Result.deal == 0, STATE_STARTED и STATE_MODIFY pending.
  // В тестере/оптимизаторе производительность равна штатной OrderSend.

  static bool OrderSendSync( const MqlTradeRequest &Request, MqlTradeResult &Result )
  {
    const ulong StartTime1 = ::GetMicrosecondCount();

    bool Res = ::OrderSend(Request, Result);

    const ulong Interval1 = ::GetMicrosecondCount() - StartTime1;

    const ulong StartTime2 = ::GetMicrosecondCount();

    if (Res && !ORDERSEND::IsTester && (Result.retcode < TRADE_RETCODE_ERROR) && (ORDERSEND::OrderSend_MaxPause > 0))
    {
      Res = (Result.retcode == TRADE_RETCODE_DONE);
      ORDERSEND::Waiting(true);

      if (Request.action == TRADE_ACTION_DEAL)
      {
        WHILE(::HistoryOrderSelect(Result.order))
          ;

        Res = Res && (((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_FILLED) ||
                      ((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_PARTIAL));

        if (Res)
          WHILE(ORDERSEND::HistoryDealSelect(Result))
            ;
      }
      else if (Request.action == TRADE_ACTION_PENDING)
      {
        if (Res)
          WHILE(::OrderSelect(Result.order) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED))
            ;
        else
        {
          WHILE(::HistoryOrderSelect(Result.order))
            ;

          Res = false;
        }
      }
      else if (Request.action == TRADE_ACTION_SLTP)
      {
        if (Res)
        {
          bool EqualSL = false;
          bool EqualTP = false;

          const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

          if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
          {
            EqualSL = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
            EqualTP = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
          }

          WHILE((EqualSL && EqualTP))
            if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
            {
              EqualSL = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
              EqualTP = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
            }
        }
      }
      else if (Request.action == TRADE_ACTION_MODIFY)
      {
        if (Res)
        {
          bool EqualSL = false;
          bool EqualTP = false;
          bool EqualPrice = false;

          const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

          if (::OrderSelect(Result.order))
          {
            EqualSL = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
            EqualTP = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
            EqualPrice = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
          }

          WHILE((EqualSL && EqualTP && EqualPrice))
            if (::OrderSelect(Result.order) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) != ORDER_STATE_REQUEST_MODIFY))
            {
              EqualSL = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
              EqualTP = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
              EqualPrice = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
            }
        }
      }
      else if (Request.action == TRADE_ACTION_REMOVE)
        if (Res)
          WHILE(::HistoryOrderSelect(Result.order))
            ;
    }

    const ulong Interval2 = ::GetMicrosecondCount() - StartTime2;

    Result.comment += " " + ::DoubleToString(Interval1 / 1000.0, 3) + " + " + ::DoubleToString(Interval2 / 1000.0, 3) + " ms";

    ORDERSEND::OrderSend_Benchmark(Interval1, Interval2);

    return(Res);
  }

#undef WHILE
};

static const bool ORDERSEND::IsTester = (::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_OPTIMIZATION) ||
                                         ::MQLInfoInteger(MQL_VISUAL_MODE) || ::MQLInfoInteger(MQL_FRAME_MODE));

static uint ORDERSEND::OrderSend_MaxPause = 1000000; // максимальное время на синхронизацию в мкс.

// Эта строчка позволяет сделать все OrderSend корректными.
#define OrderSend ORDERSEND::OrderSendSync

Todo se envuelve deliberadamente en el aula para reducir el número de problemas potenciales.

Utilizando

OrderSend(Request, Result); // Все так же, как со штатной OrderSend

Es decir, para que todos los OrderSend estén sincronizados con el entorno comercial y evitar las trampas, basta con escribir este código fuente como un archivo mqh y utilizar el correspondiente #include en sus programas.