МТ5 и trans2quik.dll - страница 15

 
Konstantin Nikitin:

Ну из QUIK можно через файл скинуть нужную информацию, как вариант.

Да ц меня все написано давно под квик, но не быстро работает,

хотел сделать побыстрее...

 
prostotrader:

Да ц меня все написано давно под квик, но не быстро работает,

хотел сделать побыстрее...

Так в квике можно просто подкинуть еще один скрипт и пусть постоянно гоняет в файл нужную вам информацию. А то что написано, пусть так и работает, если устраивает.

 
prostotrader:

Да нечего еще пояснять, затык с отложенными ордерами, коллбэков-то в МТ5 нет, а 

хочется иметь в арсенале отложенные ордера.

Приветствую местных завсегдатых. Можно попробовать через шаблоны программирования обойти (http://cpp-reference.ru/patterns/behavioral-patterns/observer/)
Меня тоже тема связки нескольких рынков интересует, по Вашей стыковке спросить хотел. Как я понял из примера Вы всю информацию из МТ5 получаете, а квик лишь для открытия ордеров через Trans2Quick dll, верно?

Или же как то из квика еще информацию подтягивать будите пробовать ? На сколько я помню для получения данных из квика лучше через луа работать, но там нужно будет стыковку с терминалом опять наращивать...

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

Приветствую местных завсегдатых. Можно попробовать через шаблоны программирования обойти (http://cpp-reference.ru/patterns/behavioral-patterns/observer/)
Меня тоже тема связки нескольких рынков интересует, по Вашей стыковке спросить хотел. Как я понял из примера Вы всю информацию из МТ5 получаете, а квик лишь для открытия ордеров через Trans2Quick dll, верно?

Или же как то из квика еще информацию подтягивать будите пробовать ? На сколько я помню для получения данных из квика лучше через луа работать, но там нужно будет стыковку с терминалом опять наращивать...

Я уже писал, что все написал DDE - Моя программа - trans2quik.dll

Но эта связка не достаточно быстро работает (на глаз видно по стакану как квик отстает от МТ5).

Хотел получать маркет-дата через МТ5, а ордера отсылать через trans2quik.dll,

но забыл про депо, его можно брать только из квик.

Дальше "городить огород" - неохота.

 

Появилось "окошко" в строительстве и решил продолжить заниматься экспортом данных из МТ5 реал-тайм.

Реализовал экспорт через postMessageW, работает достаточно быстро, но иногда "залипают" данные.

Код советника

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

Код приложения (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.

Сначала я подумал, что это погрешность деления, чтобы получить DOUBLE, но ведь в МТ5 число умнажается на 10 в степени n,

а в приложении полученное число делится на 10 в степени n.

Не должно быть погрешности.

Может быть что-то не так делаю?

(скомпилированное приложение во вложении) 

Добавлено

Неужели из-за этого?


Файлы:
Mess_test.zip  997 kb
 

Все работает



Преимущества

1. Экспорт работает очень быстро и не загружает ни терминал, ни систему

2. Минимум кода.

3. Не требуется самописной DLL

Недостатки

1. Передавать можно только LONG, ULONG, DOUBLE (с ограничением по значению числа) и до 127 бит текста ANSI (только английский)

Добавлено

Осталось в Квик через LUA посылать PostMessage с депозитом.

Никто не пробовал PostMessage из Квик (LUA)?

Это нужно для ЕБС счетов.

 
prostotrader:

Все работает

А поподробней можно, как этим пользоваться, что делать?

 
Aleksey Vyazmikin:

А поподробней можно, как этим пользоваться, что делать?

Все эти "приблуды" нужны для торговли через Квик на ЕБС счетах ( или для реал-тайм анализа данных вне МТ5).

Вывод данных в свое приложение из тормознутого КВИКа по DDE ну очень медленный,

поэтому данные берем из МТ5, а торговые приказы отправляем в Квик, через их API (trans2quik.dll).

Механизм такой

МТ5 --> Свое приложение <-->  trans2quik.dll <--> Квик

Вот пример торговли в Квик фьючерсов против акций


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

Все эти "приблуды" нужны для торговли через Квик на ЕБС счетах ( или для реал-тайм анализа данных вне МТ5).

Вывод данных в свое приложение из тормознутого КВИКа по DDE ну очень медленный,

поэтому данные берем из МТ5, а торговые приказы отправляем в Квик, через их API (trans2quik.dll).

Механизм такой

МТ5 --> Свое приложение <-->  trans2quik.dll <--> Квик

Вот пример торговли в Квик фьючерсов против акций


Для этой конкретной задачи не проще ли поставить второй терминал MT5 на фондовый рынок и перекидывать инфу между двумя терминалами через PIPE канал?

Собираюсь в этом году заняться фондовым рынком именно по такой схеме.

 
Dmi3:

Для этой конкретной задачи не проще ли поставить второй терминал MT5 на фондовый рынок и перекидывать инфу между двумя терминалами через PIPE канал?

Собираюсь в этом году заняться фондовым рынком именно по такой схеме.

Вы предлагаете еще больший "геморрой", ЕБС счет тем и хорош, что денежка не разделена по секциям.

То что Вы видели на видео - работает, но очень медленно!

Квик --> DDE --> Моё проложение <-->  trans2quik.dl <--> Квик

Я заменил  Квик --> DDE --> на МТ5 --> PostMessage -->

Стало гораздо быстрее.

При этом, 2 строчки кода и никакой нагрузки на терминал и систему.

Передача сообщений

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

Прием сообщений

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;
Причина обращения: