Что нового

Вывод данных из MQL для задачи условий последующей работы скрипта

CrazyDoc

Новичок
Сообщения
75
Репутация
2
Есть биржевой терминал MetaTrader и язык написания скриптов в нем MQL. Ищу возможности вывода результатов работы скрипта в MT и использования их для формирования условий последующей работы скрипта AutoIT. Пожалуйста подскажите какие есть варианты обмена данными между приложениями(хоть в общем, не обязательно для этой пары)?
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Нормальные приложения изначально рассчитаны под интеграцию. Тот же самый терминал альфабанка AlfaTrade, интегрируется хоть с экселем. Почитай документацию своего терминала, если там нет открытого API, сомнительный какой-то терминал получается, с отсутствием какого-либо нормального функционала.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Смотря что вы собираетесь передавать. Можно и через файл работать.
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2
Belfigor сказал(а):
Почитай документацию своего терминала, если там нет открытого API, сомнительный какой-то терминал получается, с отсутствием какого-либо нормального функционала.
действительно API не предусмотрена.


Добавлено:
Сообщение автоматически объединено:

edyapd сказал(а):
Смотря что вы собираетесь передавать. Можно и через файл работать.
через файл подойдет наверное. пожалуйста подскажите где почитать о реализации этого метода?
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Сама то твоя программа хоть какой-то вариант экспорта информации предусматривает?
Думаю выше, про файл, имелось ввиду что из программы сохраняешь файлик и далее его парсишь.
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2
Belfigor сказал(а):
Сама то твоя программа хоть какой-то вариант экспорта информации предусматривает?
да. разобрался с выводом строковой информации в .txt, .csv. не могу представить как исходя из этих строк организовать работу скрипта AutoIT. т.е. насколько я понял - не знаю как "парсить". буду искать.

также есть возможность вывода массива в .txt, .csv. но в этом я еще плохо разобрался - записывает непонятную билеберду.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Ты строк 5-10 покажи, поидее все парсится с помощью StringRegExp. Эта функция позволит тебе растолкать данные из твоего текста, в массив AutoIt.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Со стороны MQL нечто подобное. Соответственно подготовив данные.
Код:
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_WRITE|FILE_TXT, " ; ");
   if(file_handle!=INVALID_HANDLE)
     {
      PrintFormat("Файл %s открыт для записи",InpFileName);
      PrintFormat("Путь к файлу: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
      //--- запишем время сигналов и их значения в файл
      for(int i=0;i<sign_size;i++)
         FileWrite(file_handle,time_buff[i],sign_buff[i]);
      //--- закрываем файл
      FileClose(file_handle);
      PrintFormat("Данные записаны, файл %s закрыт",InpFileName);
     }
   else
      PrintFormat("Не удалось открыть файл %s, Код ошибки = %d",InpFileName,GetLastError());
Со стороны AutoIT
Код:
$hFile = FileOpen($FileMame)
$Data = FileRead($hFile)
FileClose($hFile)
$Array = StringSplit($Data, " ; ", 1)
Можно удалить файл после прочтения, чтобы не заморачиваться с проверкой на то, был он ранее обработан или нет.
Структуру файла вам надо будет самому разработать, что передаёте, сколько параметров. Тоже самое и в обратную сторону.
Все приведённые примеры это только приблизительное направление.
Вообще MQL работает быстрей AutoIT. Для ещё большего ускорения можно использовать подключаемые dll написаные на С++
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Прям приведенный тобою пример высосан из программы?
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2
Belfigor сказал(а):
Прям приведенный тобою пример высосан из программы?
Да, примерно так работает скрипт на MQL в моем случае он следующий:
Код:
for(int i=0;i<OrdersTotal();i++)//---повторяем пока не дойдем до последнего открытого ордера на данный момент
   {
   int handle=FileOpen("1.csv",FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE);//--- откроем файл куда записываем построчно ордера с параметрами
   if(handle!=INVALID_HANDLE)//---если файл открылся удачно то:
      {
      int seek=FileSeek(handle,0,SEEK_END);//--- запишем строку с данными в конец файла
      if(seek!=false)//---если установить курсор записи удалось на конец файла то:
         {
         int or=OrderSelect(i,SELECT_BY_POS, MODE_TRADES);//---выбираем ордер из списка по номеру равному номеру цикла(1-я строка)
         if (or!=false)//---если орде удалось выбрать то:
            {
            int write=FileWrite(handle,OrderTicket(),OrderSymbol(),OrderType(),OrderStopLoss(),OrderTakeProfit());//---записываем в файл уникальный номер ордера, символ торговли, тип ордера, стоплосс, тэйкпрофит
            if(write!=0)//---если данные записались то:
               FileClose(handle);//--- закрываем файл
            else
               {
               ResetLastError();
               Alert("write",GetLastError());//---выводим ошибку записи если данные не записаны
               }
             }
         else
            {
            ResetLastError();
            Alert("Ошибка выбора ордера",GetLastError());//---выводим ошибку выбора ордера, если ордер не выбран
            }   
         }
      else
         Alert("seek",GetLastError());//---выводим ошибку установки курсора записи, если не удалось установить в конец файла
      }
   else
      Alert("Failed to open the file, error ",GetLastError());//---выводим ошибку открытия файла, если не удалось открыть файл
   }
В итоге работы скрипта формируется файл csv(таблица экселя???).
Ticket272114349 EURUSD 0 1.08183 1.08193
Ticket272115115 EURUSD 0 1.08173 1.08193
Теперь бы понять: возможен ли поиск строки с тикетом не совпадающим ни с одним из другого файла(№2) со списком тикетов, если да то как затем задать условия работы скрипта исходя их четырех остальных столбцов и после завершения обработки строки внести номер тикета обработанной строки во второй файл?
StringRegExp,StringSplit смотрел, но пока не разобрался - вечером буду читать внимательнее.
Совет удалить после прочтения - с каждым повтором скрипта файл будет обновляться, выводя 40-50 строк. Но только 5-7 из них будут с новыми тикетами, т.е. требующие действий от скрипта AutoIT.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
С помощью регэкспа можно распарсить такие данные в массив автоит. С регэкспами можно поэксперементировать тут: https://regex101.com/ . На форуме так же в разделе регэкспов есть неплохой мануал. Ну а найти уникальные тикеты можно просто построчно сравнивая каждый тикет файла 1, со всеми тикетами файла 2 в цикле.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
CrazyDoc сказал(а):
В итоге работы скрипта формируется файл csv(таблица экселя???).
Ticket272114349 EURUSD 0 1.08183 1.08193
Ticket272115115 EURUSD 0 1.08173 1.08193
Теперь бы понять: возможен ли поиск строки с тикетом не совпадающим ни с одним из другого файла(№2) со списком тикетов, если да то как затем задать условия работы скрипта исходя их четырех остальных столбцов и после завершения обработки строки внести номер тикета обработанной строки во второй файл?
Номера тикетов по определению должны быть разные. Не совсем понятно как у вас формируется второй файл, что там могут быть одиноковые номера с первым.
Для того, чтобы вам было легче парсить, я вам привёл пример кода сохранения в файл с разделителями. Тогда можно создать массив массивов и сравнивать первый элемент каждого массива, с первыми элементами других массивов.
Можно работать и с тем что у вас есть. Просто прочитать весь файл №1 и создать массив строк. Потом вытаскивать с каждого элемента массива номер тикета с помощью команды
Код:
$Number_ticket = _StringBetween("Здесь строка в которой ищем", "Ticket", "   ")  ; В третьем параметре знак "табуляция", так как он является разделителем в вашем файле
И уже этот номер искать в последующих строках с помощью команды
Код:
If StringInStr("Здесь строка в которой ищем", $Number_ticket, 0, 1, 7, 10)  ; Для ускорения поиска можно искать сразу с позиции номера и искать не более чем количество цифр в номере + 1 на будущее

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

CrazyDoc

Новичок
Сообщения
75
Репутация
2
сделал так:
со стороны MQL
Код:
int start()
{
WriteData(1);
return(0);
}
void WriteData(const int n)
{
for(int i=0;i<OrdersTotal();i++)
   {
   int handle=FileOpen("1.txt",FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_TXT,";");
   if(handle!=INVALID_HANDLE)
     {

      int seek=FileSeek(handle,0,SEEK_END);
      if(seek!=false)
         {
         int or=OrderSelect(i,SELECT_BY_POS, MODE_TRADES);
         if (or!=false)
            {
            int write=FileWrite(handle,OrderTicket(),OrderSymbol(),OrderType(),OrderStopLoss(),OrderTakeProfit(),"");
            if(write!=0)
               {   

               FileClose(handle);
               ResetLastError();
               
               }
            else
               {
               ResetLastError();
               Alert("Ошибка записи № ",GetLastError());
               }
             }
         else
            {
            ResetLastError();
            Alert("Ошибка выбора ордера № ",GetLastError());
            }   
         }
      else
         Alert("Ошибка установки курсора записи № ",GetLastError());
      }
   else
      Alert("Ошибка открытия файла № ",GetLastError());
   }
}
запись данных в ТХТ с разделителем ";", в конце каждой строки пробел ради разделителя(тут видимо надо было обратиться к массиву массивов? - не смог пока найти ничего похожего на эту тему).

со стороны AutoIT
Код:
$hFile = FileOpen("C:\Documents and Settings\%username%\Application Data\MetaTrader 4\MQL4\Files\2.txt")
$Data = FileRead($hFile)
FileClose($hFile)
$Array2 = StringSplit($Data,";",1)

$hFile = FileOpen("C:\Documents and Settings\%username%\Application Data\MetaTrader 4\MQL4\Files\1.txt")
$Data = FileRead($hFile)
FileClose($hFile)
$Array1 = StringSplit($Data,";",1)

for $i=1 to $Array1[0]-5 step +5
	for $j=1 to $Array2[0]-1 step +1
		if Number($Array1[$i])=Number($Array2[$j]) Then
			MsgBox(0,"ticket","Тикет совпал")
			ExitLoop
		Else
			if $j=$Array2[0]-1 Then
				MsgBox(0,"ticket","Тикета нет, записываем")
				$hFile=FileOpen("C:\Documents and Settings\belev\Application Data\MetaTrader 4\MQL4\Files\2.txt",1)
				FileWrite($hFile,$Array1[$i]&";")
				FileClose($hFile)
			EndIf
		EndIf
	Next
Next

Создал файл 2.txt с записью "000000000;".Cоздал два ордера для теста. MQL успешно вывел ордера в файл 1.txt. Получилось:

272395894;EURUSD;1;1.0755;1.073;
272395942;EURUSD;0;1.07265;1.07468;
Запустил скрипт AutoIT. Cкрипт дважды успешно сказал в первый раз - "Тикета нет, записываем"(и изменил файл 2.txt до
000000000;

272395894;
272395942;
), во второй - "Тикет совпал".

Теперь буду думать как задать дальнейшую работу скрипта из оставшихся условий
EURUSD;1;1.0755;1.073;
EURUSD;0;1.07265;1.07468;

StringRegExp - пока до конца не разобрался как этим пользоваться. Мб им проще будет сделать все это? И если кто-нибудь видит шаги которые можно заменить на более простые действия, буду рад видеть предложения.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Запроси помощь в разделе Регулярных выражений. Один регэксп распарсит весь твой файл по массиву, память если мне не изменяет им без проблем можно заполнить двумерный массив. Могу перенести тему туда.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
У меня как-то так получилось
Код:
Dim $Array1[1], $Array2[1]

$hFile = FileOpen("1.txt", 0)
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf
$i = 0
While 1
    $Array1[$i] = FileReadLine($hFile)
    If @error = -1 Then ExitLoop
	$i += 1
	ReDim $Array1[$i+1]
WEnd

FileClose($hFile)

$hFile = FileOpen("2.txt", 0)
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf
$i = 0
While 1
    $Array2[$i] = FileReadLine($hFile)
    If @error = -1 Then ExitLoop
	$i += 1
	ReDim $Array2[$i+1]
WEnd

FileClose($hFile)

$hFile = FileOpen("2.txt", 1)
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf

For $i = 0 To UBound($Array1)-2
	$t = False
	$aTemp = StringSplit($Array1[$i], ";", 2)
	For $j = 0 To UBound($Array2)-2
		If StringInStr($Array2[$j], $aTemp[0], 0, 1, 1, 10) Then
;~ 			ConsoleWrite("Найдено " & $aTemp[0] & " в " & $Array2[$j] &@LF)
			$t = True
			ExitLoop
		EndIf
	Next
	If Not $t Then
;~ 		ConsoleWrite("Не найдено " & $aTemp[0] & " Записываем " & $Array1[$i] & " в файл" & @LF)
		FileWriteLine($hFile, $Array1[$i])
	EndIf
Next

FileClose($hFile)
Я сомневаюсь, что с помощью StringRegExp это будет сделано быстрее.

OffTopic:
Лет семь назад пытался писать советника для Forex. Как-то не очень успешно.
Блин и снова эта тема. Опять вот три дня уже сижу изучаю графики :smile: и вспоминаю MQL
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Belfigor сказал(а):
Один регэксп распарсит весь твой файл по массиву, память если мне не изменяет им без проблем можно заполнить двумерный массив.

Там немножко не так... Регэксп может распарсить не в двумерный массив, а в массив массивов. Механизм обращения к элементам несколько отличается от двумерного массива.
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2
Более-менее в рамках поставленной задачи разобрался. Спасибо всем кто помогал.
В конечном варианте приняты следующие решения:
для MQL
Код:
int start()
{
int handle=FileOpen("1.txt",FILE_SHARE_READ|FILE_WRITE|FILE_TXT);
int seek=FileSeek(handle,0,SEEK_END);
int write=FileWrite(handle,TimeToStr(TimeCurrent()));
FileClose(handle);
WriteData(1);
return(0);
}
void WriteData(const int n)
{
for(int i=0;i<OrdersTotal();i++)
   {
   int handle=FileOpen("1.txt",FILE_READ|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_TXT,";");
   if(handle!=INVALID_HANDLE)
     {
      int seek=FileSeek(handle,0,SEEK_END);
      if(seek!=false)
         {
         int or=OrderSelect(i,SELECT_BY_POS, MODE_TRADES);
         if (or!=false)
            {
            int write=FileWrite(handle,OrderTicket(),OrderSymbol(),OrderType(),OrderStopLoss(),OrderTakeProfit(),"");
            if(write!=0)
               {   
               FileClose(handle);
               ResetLastError();
               }
            else
               {
               ResetLastError();
               Alert("Ошибка записи № ",GetLastError());
               }
             }
         else
            {
            ResetLastError();
            Alert("Ошибка выбора ордера № ",GetLastError());
            }   
         }
      else
         Alert("Ошибка установки курсора записи № ",GetLastError());
      }
   else
      Alert("Ошибка открытия файла № ",GetLastError());
   }
}
для AutoIT:
Код:
While 1
Dim $Array1[1], $Array2[1]

$hFile = FileOpen("C:\Users\DJ Sich\AppData\Roaming\MetaQuotes\Terminal\F8B0CF1E1FEED3B00D2D7E193237B799\MQL4\Files\1.txt", 0)
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf
$i = 0
While 1
    $Array1[$i] = FileReadLine($hFile)
    If @error = -1 Then ExitLoop
    $i += 1
    ReDim $Array1[$i+1]
WEnd

FileClose($hFile)

$hFile = FileOpen("C:\Users\DJ Sich\AppData\Roaming\MetaQuotes\Terminal\F8B0CF1E1FEED3B00D2D7E193237B799\MQL4\Files\2.txt", 0)
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf
$i = 0
While 1
    $Array2[$i] = FileReadLine($hFile)
    If @error = -1 Then ExitLoop
    $i += 1
    ReDim $Array2[$i+1]
WEnd

FileClose($hFile)

$hFile = FileOpen("C:\Users\DJ Sich\AppData\Roaming\MetaQuotes\Terminal\F8B0CF1E1FEED3B00D2D7E193237B799\MQL4\Files\2.txt", 1)
If $hFile = -1 Then
    MsgBox(4096, "Ошибка", "Невозможно открыть файл.")
    Exit
EndIf

For $i = 1 To UBound($Array1)-2
    $t = False
    $aTemp = StringSplit($Array1[$i], ";", 2)
    For $j = 0 To UBound($Array2)-2
        If StringInStr($Array2[$j], $aTemp[0], 0, 1, 1, 10) Then
;~          ConsoleWrite("Найдено " & $aTemp[0] & " в " & $Array2[$j] &@LF)
            $t = True
            ExitLoop
        EndIf
    Next
    If Not $t Then
;~      ConsoleWrite("Не найдено " & $aTemp[0] & " Записываем " & $Array1[$i] & " в файл" & @LF)
        FileWriteLine($hFile, $aTemp[0])
    EndIf
Next

FileClose($hFile)
WEnd
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
[info border=#0000ff float=left]На форуме принято помечать тему решенной после получения ответа на свой вопрос!
Вверху или внизу темы нажмите на ссылку такого вида:
package_old.gif
Тема не решена
[/info]







Предупреждение За нарушение общих правил (пункт В.4):
Не лепите несколько вопросов разной тематики в один пост. По типу "Ребят, а ещё такой вопрос...". Каждый вопрос в свою тему.


С уважением, ваш Модератор.
 
Автор
C

CrazyDoc

Новичок
Сообщения
75
Репутация
2


Добавлено:
Сообщение автоматически объединено:

Belfigor сказал(а):
[warn]За нарушение общих правил (пункт В.4):
Не лепите несколько вопросов разной тематики в один пост. По типу "Ребят, а ещё такой вопрос...". Каждый вопрос в свою тему.


С уважением, ваш Модератор.[/warn]







Исправил.
Посмотрел тему "Уроки по работе с Регулярными Выражениями (RegExp)". Очень полезная вещь=) Но в данном случае
вполне хватает StringSplit, т.к. точно известно что ожидается в полученных строках.
 
Верх