Как я могу преобразовать предупреждение Metatrader 4 или сигнал индикатора по электронной почте в советник для открытия сделок?

Я использовал индикатор, чтобы открывать сделки. Индикатор я не разрабатывал, поэтому у меня есть доступ только к файлу .ex4. Как я могу извлечь значения тейк-профита, открытой сделки и стоп-лосса из предупреждений или сигналов по электронной почте для открытия сделок? Пожалуйста, просмотрите образец электронного письма и предупреждающих сигналов ниже.

Как я могу преобразовать предупреждение Metatrader 4 или сигнал индикатора по электронной почте в советник для открытия сделок?

Как я могу преобразовать предупреждение Metatrader 4 или сигнал индикатора по электронной почте в советник для открытия сделок?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
5 579
3

Ответы 3

MT4 не может читать ваши электронные письма. Вам нужно использовать некоторые другие инструменты или более универсальный язык для чтения ваших писем, Java.Mail.API или Pyhton или что-то еще. Прочтите электронное письмо, убедитесь в правильности формата и от ожидаемого отправителя, затем поместите сообщение в файл, доступный для MT4 - либо в собственную папку (C: \ Users \ UserName \ AppData \ Roaming \ MetaQuotes \ Terminal \ 12345678E7E35342DB4776F5AE09D64B \ MQL4 \ Files) или общая папка (C: \ Users \ User1 \ AppData \ Roaming \ MetaQuotes \ Terminal \ Common \ Files). Затем прочтите файл из приложения MT4 с помощью функции FileSearchNext() и пример в документации MQL4. После прочтения файла вам необходимо проанализировать его с помощью String функции и создать запрос OrderSend () (возможно, проверьте ввод и убедитесь, что ваша логика позволяет вашему роботу отправлять сделку, например, вы не достигли максимума разрешенных открытых сделок , время торговли, другая логика).

Спасибо за поломку. Меня интересуют два подхода: совершение сделок по сигналу оповещения индикатора или сигналу электронной почты. Судя по всему, я думаю, что открытие сделки по сигналу индикатора будет намного проще, чем по электронной почте. Если вы можете подтвердить, что это возможно, я бы предпочел отредактировать свой вопрос, чтобы конкретно придерживаться предупреждения о сигнале индикатора. Также я был бы признателен, если бы вы могли также предоставить решение для всплывающего окна с предупреждением, если это возможно.

iGetIt 29.08.2018 13:59

Я считаю, что получить данные предупреждений обратно в MT4 простым способом после их публикации невозможно. Как я уже упоминал, вы можете читать файлы из Терминала \ Common \ Files или из Терминала \ TERMINAL_ID \ MQL4 \ Files, а журналы находятся в Терминале \ TERMINAL_ID \ MQL4 \ Logs. Таким образом, вы не можете читать журналы, чтобы увидеть предупреждение (если оно отправлено, оно также печатается в журналах). Если бы у вас был код, вы могли бы легко решить проблему, отправив ChartEventCustom() после предупреждения, и вы бы упомянули символ, tf и предупреждающее сообщение (или, по крайней мере, направление) в этом событии. Но вы не можете редактировать индикатор без источника.

Daniel Kniaz 29.08.2018 14:26

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

Daniel Kniaz 29.08.2018 14:27

индикатор не имеет буферов. Я думаю, что более сложный маршрут наиболее заметен :). Я не очень хорошо разбираюсь в Java, но буду признателен, если вы предоставите какие-либо ссылки (лучше еще код), которые, по вашему мнению, действительно помогут при чтении электронного письма, как только оно придет.

iGetIt 29.08.2018 14:53

Интересно, что я даже не смог найти надстройку для Outlook или Gmail, которая автоматически сохраняет электронные письма от одного получателя. Все они требуют ручной работы. Думаю, я не могу убежать от кодирования этого. :)

iGetIt 29.08.2018 17:35
stackoverflow.com/questions/21459021/… для javamail. Я бы посоветовал Python, если для вас нет разницы, поскольку py, как мне кажется, намного проще и короче. Для небольших скриптов это кажется идеальным
Daniel Kniaz 29.08.2018 21:31

@DanielKniaz Некоторое время назад я думал о чем-то подобном, но даже не пытался, потому что думал, что это невозможно. Тем не менее, меня очень интересует этот вопрос. У меня есть индикатор и вот как он выглядит в MQL4 \ Logs .log файле 0 02:20:00.874 SuperIndicator USDCAD,M5: Alert: USDCAD, M5: Super Indicator SELL @ 1.29136, TP 1.28836, SL 1.29286. В любом случае, есть ли доступ к этой строке и ее форматирование из файла .log в эксперте, использующем mql?

TenOutOfTen 30.08.2018 19:09
nicholishen показал пример на Python о том, как получить данные из журналов. Вы не можете получить доступ к папке Logs напрямую из советника, вам нужна как минимум DLL или другой движок, который не имеет таких ограничений
Daniel Kniaz 30.08.2018 23:38

Нет необходимости извлекать данные из электронной почты, поскольку индикатор также отправляет данные через функцию Alert. Предупреждения регистрируются в каталоге .\MQL4\Logs в текстовом файле *.log. Вы можете написать какой-нибудь MQL, который использует win32 для чтения журнала, а затем создать свой собственный синтаксический анализатор на MQL.

Другой вариант - написать сценарий сторожевого таймера для сканирования и анализа файла журнала и записи результатов в CSV, где советник может получить к нему доступ. Преимущество этого метода заключается в том, насколько легко его разработать по сравнению с решением MQL, и поскольку он работает для всех символов, он позволяет избежать потенциального состояния гонки, когда несколько советников пытаются одновременно читать журнал записи csv.

Вот пример, написанный на Python.

import csv
import re
import time
from datetime import datetime
from pathlib import Path

MQL_DATA_PATH = Path(
    'C:/Users/user/Desktop/MT-TEST/Vanilla-MT4-v0_0_2/MT4/MQL4'
)
OUTPUT_FILENAME = 'signals.csv'

signal_pattern = re.compile(r'''# regex - verbose mode
    (?P<time>\d\d:\d\d:\d\d).*? # time stamp
    (?P<symbol>[A-Z]{6}\w*),.*? # symbol with ECN suffix
    (?P<type>BUY|SELL).*?       # BUY or SELL command
    (?P<price>\d+\.\d+).*?      # execution price
    (?P<tp>\d+\.\d+).*?         # takeprofit 
    (?P<sl>\d+\.\d+)            # stoploss
''', re.VERBOSE)


def log_to_csv():
    date = datetime.now()
    log_file = MQL_DATA_PATH / 'Logs' / f'{date.strftime("%Y%m%d")}.log'
    with open(log_file) as f:
        log_entries = f.read()
    signals = [s.groupdict() for s in signal_pattern.finditer(log_entries)]
    for signal in signals:
        # correct time to MQL datetime
        signal['time'] = f"{date.strftime('%Y.%m.%d')} {signal['time']}"
    csv_file = MQL_DATA_PATH / 'Files' / OUTPUT_FILENAME
    with open(csv_file, 'w') as f:
        writer = csv.DictWriter(f,
            fieldnames=('time', 'symbol', 'type', 'price', 'tp', 'sl',),
            lineterminator='\n',
        )
        writer.writerows(signals)


def main():
    print(f'Watching MQL log and saving signals to {OUTPUT_FILENAME}')
    print('Press Ctrl+C to exit')
    while True:
        try:
            log_to_csv()
            print(datetime.now().strftime('%Y.%m.%d %H:%M:%S'), end='\r')
            time.sleep(5)
        except KeyboardInterrupt:
            exit()


if __name__ == '__main__':
    main()

Меня это действительно интересует, хотя я не знаю, как писать код на Python. Я только что установил Anaconda для Mac. Как я буду использовать это? Вот так мой индикатор появляется в журнале 0 02:20:00.874 SuperIndicator USDCAD,M5: Alert: USDCAD, M5: Super Indicator SELL @ 1.29136, TP 1.28836, SL 1.29286. Буду очень признателен за вашу помощь.

TenOutOfTen 30.08.2018 19:04

@TenOutOfTen Вам нужно будет сохранить сценарий с расширением *.py, а затем вы запустите его из командной строки. C:\Path\To\Script>python log_parser.py. Я не уверен, будет ли он работать с Mac, так как вы, вероятно, используете виртуальную машину ...

nicholishen 30.08.2018 20:02

@TenOutOfTen Я только что опубликовал собственное решение MQL, которое вы также можете попробовать.

nicholishen 30.08.2018 21:22

Не могли бы вы взглянуть на этот вопрос для меня stackoverflow.com/questions/62479581/…

TenOutOfTen 20.06.2020 00:56

Вот рабочий пример script собственного решения MQL, которое использует kernel32.dll для копирования файла журнала из ./MQL4/Logs в ./MQL4/Files. Абстрактный базовый класс LogSignalParser должен быть подклассом и требует реализации метода virtual bool parse().

Обновлено: @TenOutOfTen хотел бы, чтобы практический пример о том, как анализировать следующий формат строки в файле журнала:

0 02:20:00.874 SuperIndicator USDCAD,M5: Alert: USDCAD, M5: Super Indicator SELL @ 1.29136, TP 1.28836, SL 1.29286

Шаг 1: Сохраните LogParser.mqh в каком-нибудь значимом месте.

//LogParser.mqh

#property strict
#include <stdlib.mqh>
#include <Arrays\ArrayString.mqh>
#include <Arrays\ArrayObj.mqh>
#import "kernel32.dll"
   bool CopyFileW(string lpExistingFileName,
                  string lpNewFileName,
                  bool   bFailIfExists);
#import
//+------------------------------------------------------------------+
//|                                                              
//+------------------------------------------------------------------+
class Signal : public CObject
{
public:
   string            symbol;
   datetime          signal_time;
   int               order_type;
   double            price_entry;
   double            price_sl;
   double            price_tp;
   virtual int Compare(const CObject *node,const int mode=0) const override
   {
      const Signal *other=node;
      if (this.signal_time>other.signal_time)
         return 1;
      if (this.signal_time<other.signal_time)
         return -1;
      return 0;
   }
   string to_string()
   {
      return StringFormat("%s - %s(%s) @ %.5f, SL=%.5f, TP=%.5f",
         signal_time,
         symbol,
         order_type==OP_BUYLIMIT ? "BUY" : "SELL",
         price_entry,
         price_sl,
         price_tp
      );
   }
};
//+------------------------------------------------------------------+
//|Vector-like collection                                                          
//+------------------------------------------------------------------+
class SignalList : public CArrayObj
{
   public: Signal *operator[](int i){return this.At(i);}
};
//+------------------------------------------------------------------+
//|Abstract abse class: the parse method must be implemented in subclass                                                             
//+------------------------------------------------------------------+
class LogSignalParser : public CObject
{
protected:
   CArrayString      m_rows;
   SignalList        m_signals;
   string            m_log_file_name;
   string            m_ind_name;
public:
                     LogSignalParser(string indicator_name);

                     // parse method must be overridden!
   virtual bool      parse() = 0;
   int               Total();
   Signal           *operator[](int i);
protected:
   bool              _copy_log();
   int               _open_log();
   bool              _parse_rows();
};
//+------------------------------------------------------------------+
LogSignalParser::LogSignalParser(string indicator_name)
{
   m_log_file_name = "copy_log.log";
   m_ind_name=indicator_name;
}
//+------------------------------------------------------------------+
bool LogSignalParser::_copy_log(void)
{
   MqlDateTime t;
   TimeLocal(t);
   string data_path = TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL4";
   string logs_path = data_path + "\\Logs\\";
   string dest_file = data_path + "\\Files\\" + m_log_file_name;
   string log_file=logs_path+StringFormat("%d%02d%02d.log",
                                          t.year,t.mon,t.day);
   return CopyFileW(log_file, dest_file, false);
}
//+------------------------------------------------------------------+
bool LogSignalParser::_parse_rows()
{
   if (!this._copy_log())
      return false;
   int h= this._open_log();
   if (h == INVALID_HANDLE)
      return false;
   m_rows.Clear();
   while(!FileIsEnding(h)){
      string row=FileReadString(h);
      if (StringFind(row,"Alert:") >= 0 && StringFind(row,m_ind_name) >= 0)
         m_rows.Add(row);
   }
   m_rows.Sort();
   FileClose(h);
   return true;
}
//+------------------------------------------------------------------+
int LogSignalParser::_open_log(void)
{
   return FileOpen(m_log_file_name,
      FILE_TXT|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE);
}
//+------------------------------------------------------------------+
int LogSignalParser::Total(void)
{
   return m_signals.Total();
}
//+------------------------------------------------------------------+
Signal* LogSignalParser::operator[](int i)
{
   return m_signals.At(i);
}

Шаг 2: создать подкласс класса LogSignalParser и переопределить parse

//SuperIndicatorParser.mqh
#property strict
#include "LogParser.mqh"
//+------------------------------------------------------------------+
class SuperIndicatorParser : public LogSignalParser
{ 
public:
   SuperIndicatorParser():LogSignalParser("SuperIndicator"){}
   virtual bool parse() override;
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
bool SuperIndicatorParser::parse() override
{
   if (!this._parse_rows())
      return false;
   m_signals.Clear();
   MqlDateTime local;
   TimeLocal(local);
   for(int i=m_rows.Total()-1; i>=0; i--)
   {
      string row=m_rows[i];
      MqlDateTime log_time;
      TimeToStruct(StringToTime(StringSubstr(row, 2, 12)), log_time);
      log_time.year = local.year;
      log_time.mon = local.mon;
      log_time.day = local.day;
      datetime time = StructToTime(log_time); 
      row = StringSubstr(row, StringFind(row, m_ind_name) + StringLen(m_ind_name) + 1);
      StringReplace(row, ",", " ");
      string parts[];
      StringSplit(row, ' ', parts);
      int len = ArraySize(parts);
      string debug = "";
      for(int k=0;k<len;k++)
         debug += "|" + parts[k];
      if (len != 17)
         continue;
      Signal *s      = new Signal();
      s.signal_time  = time;
      s.symbol       = parts[0];
      s.order_type   = parts[8] == "BUY" ? OP_BUYLIMIT : OP_SELLLIMIT;
      s.price_entry  = double(parts[10]);
      s.price_tp     = double(parts[13]);
      s.price_sl     = double(parts[16]);
      m_signals.Add(s);
   }
   m_signals.Sort();
   return true;
}

Шаг 3: Использование в программе MQL (пример скрипта)

#property strict
#include "SuperIndicatorParser.mqh"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   SuperIndicatorParser parser;
   if (parser.parse()){
      for(int i=parser.Total()-1; i>=0; i--){
         Signal *s = parser[i];
         int ticket = OrderSend(
            s.symbol, s.order_type, 0.1, 
            s.price_entry, 0, s.price_sl, s.price_tp 
         ); 
         if (ticket < 0){
            Print(_LastError);
         }
      }
   }     
}

Вау, это выглядит невероятно. Я не занимаюсь программированием MQL давно, так что здесь есть много вещей, которые я пытаюсь понять. Хотя я не задавал исходный вопрос, я был бы признателен, если бы вы могли показать, как это применимо к открытию сделки с этим журналом 0 02:20:00.874 SuperIndicator USDCAD,M5: Alert: USDCAD, M5: Super Indicator SELL @ 1.29136, TP 1.28836, SL 1.29286

TenOutOfTen 31.08.2018 11:06

@TenOutOfTen Я обновил сообщение выше, чтобы дать практический пример того, как использовать классы в отношении вашего образца журнала.

nicholishen 31.08.2018 16:10

Еще раз спасибо, например. Буду очень признателен, если вы ответите на этот вопрос от меня stackoverflow.com/questions/53421751/…

TenOutOfTen 22.11.2018 09:32

@nicholishen Я новичок в написании кода mql. Я спросил stackoverflow.com/questions/55930471/…, но не смог далеко продвинуться с решением. Буду признателен, если вы поможете мне, если возможно. Кто-то недавно назначил награду и за мой вопрос.

NotEveryDay 10.05.2019 12:10

Я был бы очень признателен за помощь с заданным мной вопросом по MQL5. Я назначил награду за вопрос с дополнительной информацией. Пожалуйста, посмотрите stackoverflow.com/questions/62528297/…

SuperHueman 25.06.2020 10:11

Другие вопросы по теме