MT5 e trans2quik.dll - página 15

 
Konstantin Nikitin:

Bem, você pode enviar as informações necessárias do QUIK através de um arquivo, como opção.

Sim tsu eu escrevi tudo há muito tempo para a rapidinha, mas não funciona rápido,

Queria que fosse mais rápido...

 
prostotrader:

Sim tsu eu escrevi tudo há muito tempo para a rapidinha, mas não funciona rápido,

Queria que fosse mais rápido...

Você pode simplesmente colocar outro roteiro no Quicksilver e deixá-lo continuamente alimentar o arquivo com as informações que você precisa. E o que está escrito, deixe-o trabalhar como está, se lhe convém.

 
prostotrader:

Ainda não há nada a explicar, há um problema com pedidos pendentes, não há chamadas de retorno no MT5.

Eu quero ter ordens pendentes em meu arsenal.

Saudações aos clientes regulares locais. Você pode experimentar os modelos de programação(http://cpp-reference.ru/patterns/behavioral-patterns/observer/).
Também estou interessado na conexão de vários mercados, gostaria de perguntar sobre sua conexão. Pelo que entendi do exemplo, todas as informações são obtidas do MT5 e a visualização rápida é usada apenas para abrir pedidos via Trans2Quick dll, certo?

Ou você vai tentar usar outra maneira de receber dados do corretor? Como lembro é melhor usar lua para obter dados do Quicksilver, mas é preciso aumentar a conexão com o terminal...

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

Saudações dos freqüentadores locais. Você pode tentar usar os modelos de programação(http://cpp-reference.ru/patterns/behavioral-patterns/observer/).
Também estou interessado na questão da ligação de vários mercados, gostaria de perguntar sobre a sua ligação. Pelo que entendi do exemplo, todas as informações são obtidas do MT5 e a visualização rápida é usada apenas para abrir pedidos via Trans2Quick dll, certo?

Ou você vai tentar usar outra maneira de receber dados do corretor? Como lembro, é melhor usar lua para receber dados do Quicksilver, mas é preciso aumentar a conexão com o terminal...

Já escrevi que escrevi tudo pela DDE - Meu programa - trans2quik.dll

Mas esta combinação não funciona com rapidez suficiente (de olho você pode ver como o quik fica atrás do MT5 na pilha).

Eu queria receber dados de mercado via MT5 e enviar pedidos via trans2quik.dll,

Mas esqueci-me do depoimento, ele só pode ser obtido a partir da visualização rápida.

Eu não quero ir mais longe.

 

Uma "janela" apareceu na construção e decidi continuar exportando dados da MT5 em tempo real.

Eu implementei a exportação pós-MessageW, ela funciona rápido o suficiente, mas às vezes os dados ficam "presos".

Código de conselheiro especializado

//+------------------------------------------------------------------+
//|                                                     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 aplicação (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.

No início pensei que era um erro de divisão, para conseguir o DOBRO, mas o MT5 multiplica o número por 10 até a potência de n,

e no apêndice, o número resultante é dividido por 10, com o poder de n.

Não deve haver um erro.

Talvez eu esteja fazendo algo errado?

(anexo compilado em anexo)

Adicionado por

É por causa disso?


Arquivos anexados:
Mess_test.zip  997 kb
 

Tudo funciona



Vantagens de

1. As exportações funcionam muito rapidamente e não carregam o terminal ou o sistema

2. Código mínimo.

3. não é necessário DLL.

Desvantagens

1. Você só pode transferir LONG, ULONG, DOUBLE (com limitação de valor numérico) e até 127 bits de texto ANSI (somente em inglês)

Adicionado

Permanece para enviar PostMessage com depósito para Quickie via LUA.

Alguém tentou o PostMessage da Quick (LUA)?

Isto é necessário para as contas EBS.

 
prostotrader:

Tudo funciona.

Você pode me dizer mais sobre como utilizá-lo, o que fazer?

 
Aleksey Vyazmikin:

Você pode me dizer mais sobre como usar isso e o que fazer?

Todos esses "gadgets" são necessários para negociação via Quick nas contas de EBS (ou para análise em tempo real de dados fora do MT5).

A saída de dados para minha aplicação do lento KVIK via DDE é muito lenta,

Assim, os dados são retirados da MT5 e as ordens de negociação são enviadas para Kvik via seu API (trans2quik.dll).

O mecanismo é

MT5 --> Aplicação própria <--> trans2quik.dll <--> Rápido

Aqui está um exemplo de negociação em futuros rápidos versus ações


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

Todos esses "gadgets" são necessários para negociar via QuickBooks em contas EBS (ou para análise em tempo real de dados fora do MT5).

A saída de dados para sua aplicação do lento Quik via DDE é muito lenta,

Assim, os dados são retirados da MT5 e as ordens de negociação são enviadas para Kvik via seu API (trans2quik.dll).

O mecanismo é

MT5 --> Aplicação própria <--> trans2quik.dll <--> Rápido

Aqui está um exemplo de negociação em Kvik para futuros vs ações


Não é mais fácil colocar o segundo terminal MT5 no mercado de ações e passar as informações entre dois terminais através do canal PIPE para esta tarefa específica?

Este ano, vou fazer o mercado de ações de acordo com este esquema.

 
Dmi3:

Não é mais fácil colocar um segundo terminal MT5 no mercado de ações e transferir informações entre os dois terminais através de um canal PIPE para esta tarefa específica?

Vou fazer o mercado de ações este ano de acordo com este esquema.

Você está propondo uma "bagunça" ainda maior, a conta EBS é boa porque o dinheiro não está dividido em seções.

O que você viu no vídeo funciona, mas muito lentamente!

Rápido --> DDE --> Meu bloco <--> trans2quik.dl <--> Rápido

Substitui Quick --> DDE --> por MT5 --> PostMessage -->.

Tornou-se muito mais rápido.

Dito isto, 2 linhas de código e nenhuma carga no terminal e no sistema.

Envio de mensagens

//+------------------------------------------------------------------+
//| 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);
    }
  }  
} 

Recepção de mensagens

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;