Jump to content
Programmer

Общие вопросы по языку MQL

Recommended Posts

AntFX
В 19.09.2018 в 04:33, torgf сказал:

Спасибо, нашла ☺️.

Можно, как нибудь, узнать первоначальный размер лота позиции закрытой по частям. Например лот 0.3 закрыт по рынку дважды 0.1 и 0.1, остаток закрылся по стоп лосс. Как узнать что был лот 0.3?

Сначала нужно узнать номер позиции, для этого нужно получить свойство сделки HistoryDealGetInteger(DEAL_POSITION_ID) или свойство ордера HistoryOrderGetInteger(ORDER_POSITION_ID)

Затем нужно выбрать историю этой позиции в ордерах и сделках HistorySelectByPosition(POSITION_ID), используя полученный номер

Теперь можно выбирать сделки со свойством IN (то есть вход в рынок) и анализировать их объемы и последовательность. Ведь все может быть не так просто, как - сначала открыли 0.3, а потом закрывали по 0.1. А может быть, открывали 7 раз по 0.1, потом закрыли 3 раза по 0.2, потом открыли 2 раза по 0.3 и т.д. и все в пределах одной и той же позиции... В МТ5 "частичное открытие и закрытие" это более "простое" и естественное понятие, чем в МТ4 с его жесткой привязкой к ордерам.

Edited by AntFX

1

Share this post


Link to post
Share on other sites
torgf

AntFX  Спасибо☺️

Есть скрипт который при запуске вызывает настройки всех индикаторов и кликает "ОК".

Чтобы не запускать скрипт каждый раз, решила вставить код в OnInit() одного из индикаторов, но работает только вызов списка индикаторов.

В OnCalculate() тоже самое.

как заставить работать код из индикатора?


#include <WinUser32.mqh>

#import "user32.dll"
int GetAncestor(int hWnd, int gaFlags);
int GetLastActivePopup(int hWnd);
int GetDlgItem(int hDlg, int nIDDlgItem);
#import

#define PAUSE 100

#define VK_HOME 0x24
#define VK_DOWN 0x28

#define GA_ROOT 2

#define TVM_GETCOUNT 0x1105

//+------------------------------------------------------------------+
//| Вызывает окно "Список индикаторов" и возвращает его дескриптор   |
//+------------------------------------------------------------------+
int GetListDialog(int hOwnedWnd)
{
int hDlgWnd;
//---- вызываем окно "Список индикаторов"
PostMessageA(hOwnedWnd,WM_COMMAND,35419,0);
Sleep(PAUSE);
//---- определяем дескриптор окна
hDlgWnd = GetLastActivePopup(hOwnedWnd);
//----
return(hDlgWnd);
}

//+------------------------------------------------------------------+
//| Вызывает окно свойств индикатора и возвращает его дескриптор     |
//+------------------------------------------------------------------+
int GetPropertyDialog(int hOwnedWnd, int hListDlg)
{
int hDlgWnd;
//---- вызываем окно свойств выбранного индикатора
PostMessageA(hListDlg,WM_COMMAND,0x48B,GetDlgItem(hListDlg,0x48B));
Sleep(PAUSE);
//---- определяем дескриптор окна
hDlgWnd = GetLastActivePopup(hOwnedWnd);
//----
return(hDlgWnd);
}

//+------------------------------------------------------------------+
//| Основная функция скрипта	                                     |
//+------------------------------------------------------------------+
void start()
{
int hParentWnd, hListDlg, hTreeView, hPropDlg;
int nTreeCount;
//---- получаем дескриптор основного окна терминала
hParentWnd = GetAncestor(WindowHandle(Symbol(),Period()),GA_ROOT);

if(hParentWnd!=0)
{
//---- вызываем окно "Список индикаторов"
hListDlg = GetListDialog(hParentWnd);
//---- находим список индикаторов
hTreeView = GetDlgItem(hListDlg,0x48C); //
//---- определяем общую длину списка
nTreeCount = SendMessageA(hTreeView,TVM_GETCOUNT,0,0);
//---- устанавливаем курсор на верхней строчке списка
PostMessageA(hTreeView,WM_KEYDOWN,VK_HOME,0);
//---- в цикле перебираем весь список
for(int i=1; i<nTreeCount; i++)
{
//---- смещаем курсор на следующую позицию списка
PostMessageA(hTreeView,WM_KEYDOWN,VK_DOWN,0);
//---- проверяем активность кнопки "Свойства"
if(IsWindowEnabled(GetDlgItem(hListDlg,0x48B))==0) continue;
//---- вызываем окно свойств выделенного индикатора
hPropDlg = GetPropertyDialog(hParentWnd,hListDlg);
//---- нажимаем кнопку "ОК"
PostMessageA(hPropDlg,WM_COMMAND,0x001,GetDlgItem(hPropDlg,0x001));
}
//---- закрываем окно "Список индикаторов"
PostMessageA(hListDlg,WM_COMMAND,0x001,GetDlgItem(hListDlg,0x001));
}
}

 

Edited by torgf

Share this post


Link to post
Share on other sites
AntFX
27 минут назад, torgf сказал:

Есть скрипт который при запуске вызывает настройки всех индикаторов и кликает "ОК".

А может лучше не использовать методы "через одно место", а сделать обмен данными через глобальные переменные, или события OnChartEvent? :)

 

Кстати, если нужно только добиться перерисовки индикаторов, то это должно быть возможно сделать с помощью простого вызова ChartRedraw();

Edited by AntFX

1

Share this post


Link to post
Share on other sites
torgf
36 минут назад, AntFX сказал:

:)

В данном случае нужно именно "через это место" :)ChartRedraw(); не справляется.

А что, из индикатора не все действия возможны по winapi?

Edited by torgf

Share this post


Link to post
Share on other sites
AntFX
5 минут назад, torgf сказал:

А что, из индикатора не все действия возможны по winapi?

Все возможно по винапи, но лично мне не нравится желание делать вещи через это место :) Разве что когда дело касается загрузки инфы из интернета, хотя сейчас и для этого уже вроде встроенная в mql функция появилась...


1

Share this post


Link to post
Share on other sites
AntFX

К тому же у меня этот код вообще не работает (не только в индикаторах...), и написан он явно для очень старой версии МТ4 (до 2014), т.к. функция start уже 4 года называется в mql иначе... Таким образом, чтобы этот код "исправить", нужно самому разбираться во внутреннем строении окон метатрейдер, править их дескрипторы и т.п. Может кто-то и поможет, но я лично не полезу туда ради непонятной цели )


1

Share this post


Link to post
Share on other sites
torgf
56 минут назад, AntFX сказал:

но лично мне не нравится желание делать вещи через это место :) 

Всё правильно делать, мне тоже нравится. Но это необходимость, средствами mql не достигается цель😐

18 минут назад, AntFX сказал:

К тому же у меня этот код вообще не работает

Из папки Скрипты, выполняет необходимые действия, несмотря на год выпуска, и большой пробег :)

Может быть, у вас, вызов dll запрещен.

Edited by torgf

Share this post


Link to post
Share on other sites
AntFX
1 час назад, torgf сказал:

Всё правильно делать, мне тоже нравится. Но это необходимость, средствами mql не достигается цель😐

Из папки Скрипты, выполняет необходимые действия, несмотря на год выпуска, и большой пробег :)

Может быть, у вас, вызов dll запрещен.

Может он и работает, я судил по тому, что не выполняет заново OnInit индикаторов из списка. 

Судя по всему, именно это Ваша цель - вызвать OnInit индикаторов заново. И вывод, что скрипт "не работает из индикаторов" Вы, возможно, сделали тоже поэтому.

Однако, я сейчас проверил, это далеко не всегда достигается открытием свойств индикатора и нажатием на ОК, как это делает скрипт.

Поэтому, возможно, что код "работает" и у меня, и у Вас при вызове из индикаторов тоже работает, только он делает не то, что Вам нужно, и поэтому Вы думаете, будто он "не работает".

Раньше, до 2014, вызов свойств индикатора и нажатие ОК возможно, всегда приводило к вызову init/deinit, а сейчас не так.

Поскольку мы все равно здесь не будем "лечить" этот скрипт, дальше пояснять нет смысла :)


1

Share this post


Link to post
Share on other sites
torgf
34 минуты назад, AntFX сказал:

 

Ваша позиция мне понятна.

34 минуты назад, AntFX сказал:

и поэтому Вы думаете, будто он "не работает".

Однако, когда запускаю скрипт, видно - возникают, на мгновение, окна настроек индикаторов и данные обновляются. Из индикатора, код выполняет только вызов окна "Список индикаторов" дальше код не выполняется. Поэтому и предположила что из индикатора невозможно полноценно эмулировать действия. 

Edited by torgf

Share this post


Link to post
Share on other sites
AntFX
29 минут назад, torgf сказал:

Ваша позиция мне понятна.

Однако, когда запускаю скрипт, видно - возникают, на мгновение, окна настроек индикаторов и данные обновляются. Из индикатора, код выполняет только вызов окна "Список индикаторов" дальше код не выполняется. Поэтому и предположила что из индикатора невозможно полноценно эмулировать действия. 

Забавно - добавил в индикатор, запустил не подумав - и наглухо повесил терминал, да ещё так, что с трудом восстановил (пришлось откомпилированный файл индикатора удалять перед запуском терминала)

Так что все работает из индикаторов отлично, даже более чем. Ну а поскольку за попытку помочь я уже был наказан) а также потому, что Вы так и не обозначили подробно свою цель при использовании этого инструмента, далее разбирайтесь сами...

 

Кстати, интересно - у Вас также вызов из индикатора вешал терминал, но Вы об этом промолчали? :)

Edited by AntFX

1

Share this post


Link to post
Share on other sites
AntFX

Кто-нибудь в курсе, как заставить перегруженные логические операции, типа operator==, правильно работать с указателями? То есть как сделать, чтобы следующий код

class A{
   public:
      bool operator==(A *a){  Print("a==a?"); return(false); }
};

void OnStart(){
   A *a;
   A *b;
   Print(a==b); }

Выполнял не сравнение указателей, а переопределенное действие? Со всеми логическими операциями так... Да, кстати с оператором =, похоже, та же проблема

 

П.С. Вот так можно вызвать перегруженную операцию: bool eq(A &op1, A &op2){   return(op1==op2); }

Но тогда теряется смысл перегрузки - сделать код изящнее за счет использования операций вместо вызова функций.

Edited by AntFX

1

Share this post


Link to post
Share on other sites
kazakov.v
2 часа назад, AntFX сказал:

заставить перегруженные логические операции, типа operator==, правильно работать с указателями?

 

Указатель - это просто цифирь, по сути базовый (элементарный) тип данных.

Для базовых типов перегружать операторы нельзя, да и бессмысленно. Я так думаю)

 


Никому верить нельзя.

Мне - можно.

 

Share this post


Link to post
Share on other sites
AntFX
34 минуты назад, kazakov.v сказал:

Указатель - это просто цифирь, по сути базовый (элементарный) тип данных.

Для базовых типов перегружать операторы нельзя, да и бессмысленно. Я так думаю)

Ага, только чтобы хотя бы распечатать этот "цифирь", приходится плясать с бубном, а что-то кроме объекта присвоить - почти невозможно )) То есть когда им хочется, он себя не ведет как цифирь, если только оочень-очень настойчиво не попросить.

Тем не менее, mql его трактует как что-то вроде bool при свободной записи, т.е. если он=NULL, то Print(a) возвращает 0, а иначе 1. Причем, независимо от его валидности, что делает такое поведение бесполезным чуть более, чем полностью. Но зато перегрузка логических операций с ним не работает.

Все остальные операции (типа < или <<, то есть побитовые и арифметические) перегружаются на "ура".

Edited by AntFX

1

Share this post


Link to post
Share on other sites
AntFX

Кстати, переменная типа объект (не указатель) - это точно такой же цифирь. Но с ним перегрузка уже и логических операций работает как надо


1

Share this post


Link to post
Share on other sites
AntFX

Вот ещё пара интересных фактов про "цифирь"

class A{
   public:
      bool operator==(A &a){  Print("a==a!"); return(false); }
      bool operator==(int b){  Print("a==B!"); return(false); }
};


void OnStart(){
   A *a;
   A *b;
   A c;
   int base_type;
   Print(a==b); // Перегруженная операция НЕ работает
   Print(a==c); // Отлично работает перегруженная операция!
   Print(c==a); // Отлично работает перегруженная операция!
   Print(a==base_type); // Отлично работает перегруженная операция!
//   Print(base_type==a); Но тем не менее - illegal operation use! )) Вот такой вот "базовый тип"...
}

 


1

Share this post


Link to post
Share on other sites
torgf
5 часов назад, AntFX сказал:

Кстати, интересно - у Вас также вызов из индикатора вешал терминал, но Вы об этом промолчали? :)

Зачем вы так. Не виснет терминал и даже нагрузки на процессор нет. Возникает окно "Список индикаторов" и торчит, пока не кликну "Закрыть".

Его я уже и в OnTimer определяла, не идёт дальше списка индикаторов.

5 часов назад, AntFX сказал:

так и не обозначили подробно свою цель при использовании этого инструмента

История очень длинная, не хотела отнимать время. Коротко - есть 3 индикатора которые не меняют показаний в реальном времени, открытого кода нет. Строятся графические объекты, читать буферы нет смысла. Запускала на графике индикатор с ChartRedraw  нет эффекта. После запуска вышеуказанного скрипта данные индикаторов обновляются. Есть замысел по графике этих индикаторов проверить некое предположение возможного предвидения будущего направления движения цены. В целом банальщина, жажда наживы, грааль и т.д. хотя исследовательский кодинг- интерес присутствует :)

Edited by torgf

Share this post


Link to post
Share on other sites
AntFX
1 час назад, torgf сказал:

ачем вы так. Не виснет терминал и даже нагрузки на процессор нет. Возникает окно "Список индикаторов" и торчит, пока не кликну "Закрыть".

Его я уже и в OnTimer определяла, не идёт дальше списка индикаторов.

В общем, получается так, что после присоединения к графику индикатора, в котором сидит этот код, он сам оказывается в списке индикаторов, запускается код в OnCalculate, открывает его свойства, закрывает, он перегружается и снова запускает OnCalculate, запускается код, открывает его свойства и так далее в бесконечном цикле, который можно остановить только через диспетчер задач. А потом Вы открываете "испортившийся" метатрейдер и видите тоже самое, потому что он успевает запомнить, что этот индикатор был установлен на график и пытается открыть его там же...

Так что забудьте об этой затее, Вам просто повезло, что Вы не сломали себе метатрейдер. Попробуйте это сделать через советник, что ли :) 

 

Что касается ChartRedraw - если он не работает, попробуйте поиграть с ChartApplyTemplate, один шаблон с нужными индикаторами, другой без, последовательно их меняя. И попробуйте вызывать WindowRedraw вместо ChartRedraw. Любой найденный "нормальный" способ будет лучше, чем это потенциально убивающее терминал древнее художество.

Edited by AntFX
  • Thanks 1

1

Share this post


Link to post
Share on other sites
torgf
13 часов назад, AntFX сказал:

он сам оказывается в списке индикаторов, запускается код в OnCalculate,

Спасибо, понятно объяснили.

Все усилия тщетны. Обновляются данные только вызовом окна настроек. Решила попробовать вызвать этот злосчастный скрипт из индикатора, не вызывается. Подскажите, что не так.

#property strict
#property indicator_chart_window

#define MT4_MESSAGE "MetaTrader4_Internal_Message"
#include <WinUser32.mqh>;
#import "user32.dll"
int RegisterWindowMessageA(uchar &lParam[]);
int SendMessageA(int hWnd,int Msg,int wParam,char &lParam[]);
#import

#define TA_SCRIPT_NAME "dostal"//"<dostal>"
//////
datetime OlderTime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   char buf[];

   int hwnd=WindowHandle(Symbol(),Period());

   int i;//counted_bars=IndicatorCounted();
   if(rates_total<4) return(0);
   int limit=rates_total-prev_calculated-1;
//
   for(i=limit; i>=10; i--)
     {

      //if(TimeCurrent()>=OlderTime+120)
      if(TimeLocal()>=OlderTime+120)
        {

         StringToCharArray(TA_SCRIPT_NAME,buf);
         int MT4InternalMsg=RegisterWindowMessageA(buf);
         SendMessageA(hwnd,MT4InternalMsg,14,buf);
         //OlderTime=TimeCurrent();
         OlderTime=TimeLocal();
        }
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

 

Share this post


Link to post
Share on other sites
ИМН

Доброго здравия г-дам специалистам по MQL4/5. Есть вопрос: советник на открытии каждой свечи (ТФ М15) выполняет некоторые операции, затем записывает/перезаписывает некоторые глобальные переменные ТЕРМИНАЛА. После чего при помощи GlobalVariablesFlush() фиксирует их на диске. Таким образом, например, в 23:50 я увижу, что глобальные переменные терминала обновлялись последний раз около 23:45 (время терминала и сервака часто не совпадает). Однако по непонятной мне причине терминал проигнорировал последнее выполнение этой рутины в пятницу в 23:45, последнее сохранение глобалок в списке указано в 23:30. Причём советник совершенно точно входил в блок операторов записи глобалок, то есть проблема не в советнике. В чём может быть дело?


Лёгкие деньги бывают только там же, где и бесплатный сыр.

Share this post


Link to post
Share on other sites
AntFX
2 часа назад, ИМН сказал:

советник совершенно точно входил в блок операторов записи глобалок, то есть проблема не в советнике

Если входил, но не выполнил то, что нужно, значит проблема именно в советнике. Больше на эту тему сказать нечего - здесь не Ванги собрались


1

Share this post


Link to post
Share on other sites
DVargo
В 28.09.2018 в 00:44, torgf сказал:

как заставить работать код из индикатора?

 

Методом тыка, эта строчка лишняя.

//---- проверяем активность кнопки "Свойства"
if(IsWindowEnabled(GetDlgItem(hListDlg,0x48B))==0) continue;

при любом раскладе определяется как "0".

А откуда индюк взяли?

Интересует эта часть

//---- вызываем окно "Список индикаторов"
PostMessageA(hOwnedWnd,WM_COMMAND,35419,0);

какие еще окна можно получить вместо 35419?

Интересуют именно окна.

Как их получать из spy не разобрался.

 

Я не думаю, что вызывать окна из индикатора правильно. лучше наверное все же из скрипта.

До кнопок можно добраться также эмуляцией клавиш таб и ввод.

добавить строки с нужными клавишами, по аналогу.

//---- устанавливаем курсор на верхней строчке списка
PostMessageA(hTreeView,WM_KEYDOWN,VK_HOME,0);
  • Upvote 1

Share this post


Link to post
Share on other sites
ИМН
7 часов назад, AntFX сказал:

Если входил, но не выполнил то, что нужно, значит проблема именно в советнике. Больше на эту тему сказать нечего - здесь не Ванги собрались

Антон, не советник не выполнил то, что нужно, а терминал не выполнил то, что ему велел сделать советник. Блок перезаписи глобалок ничем не обусловлен, просто тупо делается перезапись каждый раз на открытии каждой свечи. До 23:45 пятницы все перезаписи с момента запуска советника на неделе работали чётко. Я не к вангам обращаюсь, а к тем, кто, возможно, сталкивался с чем-то подобным.

Угар, Вы велели писать здесь, выполняю. Ничего не подскажете?


Лёгкие деньги бывают только там же, где и бесплатный сыр.

Share this post


Link to post
Share on other sites
AntFX
10 часов назад, ИМН сказал:

Антон, не советник не выполнил то, что нужно, а терминал не выполнил то, что ему велел сделать советник.

Это заявление является слишком самонадеянным с Вашей стороны. С вероятностью 90% именно Ваш советник накосячил, а терминал тут непричем. Именно поэтому

10 часов назад, ИМН сказал:

Я не к вангам обращаюсь

Если Вы "не к вангам обращаетесь", в первую очередь нужно выложить тут сам советник. А если нет желания - то и не обращаться.

 

 


1

Share this post


Link to post
Share on other sites
torgf
В 29.09.2018 в 16:31, DVargo сказал:

Я не думаю, что вызывать окна из индикатора правильно. лучше наверное все же из скрипта.

Совершенно верно, скрипт выполняет все действия, несмотря на "лишнюю" строку. AntFX объяснил, почему код из скрипта не будет корректно выполнять действия из индикатора. Поэтому и пытаюсь программно  из индикатора прикрепить скрипт "dostal" к графику, попытка в предыдущем сообщении. Но действие, прикрепление скрипта к графику, не выполняется.

Edited by torgf

Share this post


Link to post
Share on other sites
DVargo

Скрипт из индикатора запускается

Скрытый текст

//+------------------------------------------------------------------+
//|                                              Test run Script.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#define MT4_MESSAGE "MetaTrader4_Internal_Message"
#define TA_SCRIPT_NAME "Test MessegeBox"

#import "user32.dll"
  int RegisterWindowMessageA(uchar &lParam[]);
  int SendMessageA(int hWnd, int Msg, int wParam, char &lParam[]);
#import

int k=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   k=k+1;
   if (k==10)
      {
      Main();
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void Main()
  {
//---
    char buf[];
    StringToCharArray(MT4_MESSAGE, buf);
    int MT4InternalMsg = RegisterWindowMessageA(buf);
    StringToCharArray(TA_SCRIPT_NAME, buf);
  
    int hwnd=WindowHandle(Symbol(),Period());
    if (hwnd < 0)
    {
      Alert("Заданное окно для запуска скрипта не найдено.");
      return;
    }
  
    SendMessageA(hwnd, MT4InternalMsg, 16, buf);     
  }
//+------------------------------------------------------------------+

 

Скрытый текст

//+------------------------------------------------------------------+
//|                                              Test MessegeBox.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   MessageBox("Run Script ");
  }
//+------------------------------------------------------------------+

 

 

Можно также сделать эмуляцию нажатия клавиш, а на скрипт сделать горячие кнопки.

Edited by DVargo
  • Thanks 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×