MT5 y trans2quik.dll - página 15

 
Konstantin Nikitin:

Pues bien, puede enviar la información necesaria desde QUIK a través de un fichero, como opción.

Sí tsu escribí todo hace mucho tiempo para el quickie, pero no funciona rápido,

Quería hacerlo más rápido...

 
prostotrader:

Sí tsu se ha escrito durante mucho tiempo para quickie, pero no funciona rápido,

Quería hacerlo más rápido...

Puedes simplemente lanzar otro script en el Quicksilver y dejar que alimente continuamente la información que necesitas en el archivo. Y lo que está escrito, que funcione tal cual, si le conviene.

 
prostotrader:

No hay nada que explicar todavía, hay un problema con las órdenes pendientes, no hay callbacks en MT5.

Quiero tener órdenes pendientes en mi arsenal.

Saludos a los habituales de la zona. Puede probar las plantillas de programación(http://cpp-reference.ru/patterns/behavioral-patterns/observer/).
También me interesa la conexión de varios mercados, quiero preguntar por su conexión. Por lo que he entendido del ejemplo, toda la información se obtiene de MT5 y la vista rápida se utiliza sólo para la apertura de órdenes a través de Trans2Quick dll, ¿verdad?

¿O intentará utilizar otra forma de recibir datos del corredor? Según recuerdo es mejor usar lua para obtener datos del Quicksilver, pero hay que aumentar la conexión con el terminal...

Паттерн (шаблон) проектирования Observer (наблюдатель)
Паттерн (шаблон) проектирования Observer (наблюдатель)
  • cpp-reference.ru
Паттерн Observer определяет зависимость "один-ко-многим" между объектами так, что при изменении состояния одного объекта все зависящие от него объекты уведомляются и обновляются автоматически. Паттерн Observer инкапсулирует главный (независимый) компонент в абстракцию Subject и изменяемые (зависимые) компоненты в иерархию Observer. Паттерн...
 
Andrey Azatskiy:

Saludos de los habituales de la zona. Puede intentar utilizar plantillas de programación(http://cpp-reference.ru/patterns/behavioral-patterns/observer/).
También me interesa el tema de la vinculación de varios mercados, me gustaría preguntar por su vinculación. Por lo que he entendido del ejemplo, toda la información se obtiene de MT5 y la vista rápida se utiliza sólo para la apertura de órdenes a través de Trans2Quick dll, ¿verdad?

¿O va a intentar utilizar otra forma de recibir datos del corredor? Según recuerdo es mejor usar lua para obtener datos del Quicksilver, pero hay que aumentar la conexión con el terminal...

Ya escribí que escribí todo por DDE - Mi programa - trans2quik.dll

Pero esta combinación no funciona lo suficientemente rápido (a ojo se puede ver cómo quik va por detrás de MT5 en la pila).

Quería recibir datos de mercado a través de MT5 y enviar órdenes a través de trans2quik.dll,

Pero me olvidé de la deposición, sólo se puede obtener desde la vista rápida.

No quiero ir más allá.

 

Apareció una "ventana" en construcción y decidí seguir exportando datos de MT5 en tiempo real.

He implementado la exportación de postMessageW, funciona bastante rápido, pero a veces los datos se "atascan".

Código del Asesor Experto

//+------------------------------------------------------------------+
//|                                                     PostMess.mq5 |
//|                                      Copyright 2021 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021 prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.00"

#define  HANDLE  long
#define  PVOID   long
#define  WM_USER 0x400
#define  WM_PR_ASK WM_USER + 10
#define  WM_PR_BID WM_USER + 20

#import "User32.dll"
bool PostMessageW(HANDLE hWnd, uint Msg, PVOID wParam, PVOID lParam);
#import

input long HWND = 111111111; //Hahdle window

PVOID wPar, lPar;
HANDLE Wnd;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Wnd = HWND;
   wPar = Digits();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| OnTick function                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   lPar = 0;
   double s_ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
   if(wPar > 0)
     {
      double a_val = MathPow(10, double(wPar));
      lPar = long(s_ask * a_val);
     }
   else
      lPar = long(s_ask);
   bool result = PostMessageW(Wnd, WM_PR_ASK, wPar, lPar);
//---
   lPar = 0;
   s_ask = SymbolInfoDouble(Symbol(), SYMBOL_BID);
   if(wPar > 0)
     {
      double a_val = MathPow(10, double(wPar));
      lPar = long(s_ask * a_val);
     }
   else
      lPar = long(s_ask);
   result = PostMessageW(Wnd, WM_PR_BID, wPar, lPar);
  }  
//+------------------------------------------------------------------+

Código de la aplicación (Delphi XE4)

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Math;

const
  WM_PR_ASK = WM_USER + 10;
  WM_PR_BID = WM_USER + 20;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    procedure ResiveMessPrAsk(var Msg: TMessage); message WM_PR_ASK;
    procedure ResiveMessPrBid(var Msg: TMessage); message WM_PR_BID;
  public

    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Label1.Caption:= 'Handle: ' + intToStr(integer(Form1.Handle));
end;

procedure TForm1.ResiveMessPrAsk;
var
  a_ask: double;
begin
  if(Msg.WParam > 0) then
  begin
    a_ask:= IntPower(10, Msg.WParam);
    a_ask:= Msg.lParam/a_ask;
  end else
  begin
    a_ask:= Msg.lParam;
  end;
  Label2.Caption:= 'Ask: ' + FloatToStr(a_ask);
  Label2.Update();
end;

procedure TForm1.ResiveMessPrBid;
var
  a_bid: double;
begin
  if(Msg.WParam > 0) then
  begin
    a_bid:= IntPower(10, Msg.WParam);
    a_bid:= Msg.lParam/a_bid;
  end else
  begin
    a_bid:= Msg.lParam;
  end;
  Label3.Caption:= 'Bid: ' + FloatToStr(a_bid);
  Label3.Update();
end;

end.

Al principio pensé que era un error de división, para obtener el DOBLE, pero MT5 multiplica el número por 10 a la potencia de n,

y en la aplicación el número resultante se divide por 10 a la potencia de n.

No debería haber ningún error.

¿Quizás estoy haciendo algo mal?

(se adjunta un apéndice compilado)

Añadido por

¿Es por esto?


Archivos adjuntos:
Mess_test.zip  997 kb
 

Todo funciona



Ventajas de

1 La exportación funciona muy rápido y no carga el terminal ni el sistema

2. Código mínimo.

3. No se necesita DLL.

Desventajas

1. Sólo puede transferir LONG, ULONG, DOUBLE (con limitación de valor numérico) y hasta 127 bits de texto ANSI (sólo en inglés)

Añadido

Queda por enviar PostMessage con depósito a Quickie vía LUA.

¿Alguien ha probado PostMessage de Quick (LUA)?

Esto es necesario para las cuentas EBS.

 
prostotrader:

Todo funciona.

¿Puede decirme más sobre cómo usarlo, qué hacer?

 
Aleksey Vyazmikin:

¿Puede decirme más sobre cómo utilizarlo y qué hacer?

Todos estos "artilugios" son necesarios para operar a través de Quick en las cuentas EBS (o para el análisis en tiempo real de los datos fuera de MT5).

La salida de datos a mi aplicación desde el lento KVIK vía DDE es muy lenta,

por lo que los datos se toman de MT5, y las órdenes de trading se envían a Kvik a través de su API (trans2quik.dll).

El mecanismo es

MT5 --> Aplicación propia <--> trans2quik.dll <--> Quick

Este es un ejemplo de negociación de futuros rápidos frente a acciones


Документация по MQL5: Константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Типы торговых операций - Торговые константы - Константы, перечисления и структуры - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
prostotrader:

Todos estos "gadgets" son necesarios para operar a través de QuickBooks en cuentas EBS (o para el análisis en tiempo real de los datos fuera de MT5).

La salida de datos a su aplicación desde el lento Quik vía DDE es muy lenta,

por lo que los datos se toman de MT5, y las órdenes de trading se envían a Kvik a través de su API (trans2quik.dll).

El mecanismo es

MT5 --> Aplicación propia <--> trans2quik.dll <--> Quick

Este es un ejemplo de negociación en Kvik para futuros frente a acciones


¿No es más fácil poner el segundo terminal MT5 a la bolsa y pasar la información entre dos terminales a través del canal PIPE para esta tarea específica?

Voy a hacer bolsa este año según este esquema.

 
Dmi3:

¿No es más fácil poner un segundo terminal MT5 en la bolsa y transferir la información entre los dos terminales a través de un canal PIPE para esta tarea específica?

Voy a hacer la bolsa este año según este esquema.

Estás proponiendo un "lío" aún mayor, la cuenta EBS es buena porque el dinero no se divide en secciones.

Lo que has visto en el vídeo funciona, ¡pero muy lentamente!

Quick --> DDE --> Mi pad <--> trans2quik.dl <--> Quick

He sustituido Quick --> DDE --> por MT5 --> PostMessage -->.

Se hizo mucho más rápido.

Lo dicho, 2 líneas de código y ninguna carga para el terminal y el sistema.

Envío de mensajes

//+------------------------------------------------------------------+
//| OnBookvent function                                              |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
{
  if(symbol == Symbol())
  {
    GetBook(Symbol(), book_data);
    if((book_data.ask_vol > 0) && (book_data.bid_vol > 0))
    {
      lPar = 0;
      wPar = 0;
      long a_vol = book_data.ask_vol;
      wPar += a_vol<<=8;
      long a_val = long(MathPow(10, double(s_digits)));
      lPar = long(NormalizeDouble((book_data.ask * a_val), 0));
      wPar += ulong(s_digits);
      bool result = PostMessageW(Wnd, WM_PR_ASK, wPar, lPar);
      lPar = 0;
      wPar = 0;
      a_vol = book_data.bid_vol;
      wPar += a_vol<<=8;
      a_val = long(MathPow(10, double(s_digits)));
      lPar = long(NormalizeDouble((book_data.bid * a_val), 0));
      wPar += ulong(s_digits);
      result = PostMessageW(Wnd, WM_PR_BID, wPar, lPar);
      lPar = 0;
      wPar = 0;
      double last = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_LAST), s_digits);
      a_val = long(MathPow(10, double(s_digits)));
      lPar = long(NormalizeDouble(last * a_val, 0));
      wPar += ulong(s_digits);
      result = PostMessageW(Wnd, WM_LAST, wPar, lPar);
      lPar = 0;
      wPar = 0;
      double f_money = NormalizeDouble(AccountInfoDouble(ACCOUNT_MARGIN_FREE), 2);
      a_val = long(MathPow(10, double(2)));
      lPar = long(NormalizeDouble(f_money * a_val, 0));
      wPar += 2;
      result = PostMessageW(Wnd, WM_FREE_MONEY, wPar, lPar);
    }
  }  
} 

Recepción de mensajes

procedure TForm1.AppMessages;
var
  a_value: double;
  s: string;
  i: Integer;
  val, m_val, a_vol: int64;
  is_comma: boolean;
begin
  if(Msg.message = WM_EBS_MONEY) then
  begin
    //beep;
  end else
  begin
    if(Msg.hwnd = Handle) then      //Check message handle
    case Msg.message of
      WM_NAME:
        begin
          is_comma:= false;
          s:= '';
          for i := 0 to 7 do
          begin
            val:= Msg.wParam;
            val:= (val shr (56 - i*8) and 255);
            if(val = 46) then is_comma:= true;
            if((val >= 45) and (val <= 122)) then
              s:= s + string(AnsiChar(val)) else
              if((val > 0) and (is_comma = false)) then s:= s + IntToStr(val) else
                if(is_comma = true) then s:= s + IntToStr(val);
          end;
          Label1.Caption:= 'Name: ' + s;
          Label1.Update();
        end;
        WM_SPOT_NAME:
        begin
          s:= '';
          if(Msg.wParam > 0) then
          for i := 0 to 7 do
          begin
            val:= Msg.wParam;
            val:= (val shr (56 - i*8) and 255);
            if((val >= 45) and (val <= 122)) then
              s:= s + string(AnsiChar(val));
          end;
          if(Msg.lParam > 0) then
          for i := 0 to 7 do
          begin
            val:= Msg.lParam;
            val:= (val shr (56 - i*8) and 255);
            if((val >= 45) and (val <= 122)) then
              s:= s + string(AnsiChar(val));
          end;
          Label4.Caption:= 'SPOT Name: ' + s;
          Label4.Update();
        end;
      WM_PR_ASK:
        begin
          m_val:= Msg.WParam;
          m_val:= m_val and 255;
          a_vol:= Msg.WParam;
          a_vol:= (a_vol shr 8) and $FFFF;
          if(m_val > 0) then
          begin
            a_value:= IntPower(10, integer(m_val));
            a_value:= Msg.lParam/a_value;
          end else a_value:= Msg.lParam;
          Label2.Caption:= 'Ask: ' + FloatToStr(a_value) + ' Volume: ' + IntToStr(a_vol);
          Label2.Update();
        end;
      WM_PR_BID:
        begin
          m_val:= Msg.WParam;
          m_val:= m_val and 255;
          a_vol:= Msg.WParam;
          a_vol:= (a_vol shr 8) and $FFFF;
          if(m_val > 0) then
          begin
            a_value:= IntPower(10, integer(m_val));
            a_value:= Msg.lParam/a_value;
          end else a_value:= Msg.lParam;
          Label3.Caption:= 'Bid: ' + FloatToStr(a_value) + ' Volume: ' + IntToStr(a_vol);
          Label3.Update();
        end;
      WM_LAST:
        begin
          m_val:= Msg.WParam;
          m_val:= m_val and 255;
          if(m_val > 0) then
          begin
            a_value:= IntPower(10, integer(m_val));
            a_value:= Msg.lParam/a_value;
          end else a_value:= Msg.lParam;
          Label5.Caption:= 'Last: ' + FloatToStr(a_value);
          Label5.Update();
        end;
      WM_FREE_MONEY:
        begin
          m_val:= Msg.WParam;
          m_val:= m_val and 255;
          if(m_val > 0) then
          begin
            a_value:= IntPower(10, integer(m_val));
            a_value:= Msg.lParam/a_value;
          end else a_value:= Msg.lParam;
          Label6.Caption:= 'Free money: ' + FloatToStr(a_value);
          Label6.Update();
        end;
    end;
  end;
end;