Sorting deal history
В процессе торговли любой опытный трейдер не ограничивается одной стратегией, всегда используя хотя бы две-три из своего арсенала. Если сюда еще добавить то обстоятельство, что кроме различных стратегий используется множество инструментов, то в результате история счета превращается в кашу различных закрытых позиций и отмененных отложенных ордеров. В этой каше порой бывает очень трудно разобраться, не говоря уже об анализе деятельности каждой стратегии или одной из стратегий в пределах одного инструмента.
Выход, как всегда, существует. Ведь ничто не мешает разобрать историю счета по различным инструментам. А если торговля велась при помощи экспертов, которые для идентификации ордеров снабжают их магическим числом (MagicNumber), то можно и вовсе выделить сделки, совершенные отдельно взятой стратегией.
Обработка полученной таким образом информации наиболее удобна в Excel. Поэтому необходимо позаботиться о выводе данных в файл, формат которого совместим с Excel-форматом.
В итоге нашей задачей является поиск в доступной истории счета сделок по определенному инструменту с определенным MagicNumber. Для этого скрипту понадобится всего три входных параметра: наименование инструмента (SymbolNamee), магическое число (MagicNumber) и имя файла (FileName), в который необходимо произвести запись.
Еще стоит учесть потребность пользователя в собрании истории по различным инструментам, но с определенным MagicNumber. Это решается разрешением ввода пустого значения в параметре SymbolName. И наоборот, если пользователю потребуется найти все ордера и позиции по одному инструменту, но с различными магическими числами, то нужно принять какое-то значение, которое будет означать «любое магическое число». Так как чаще всего MagicNumber устанавливают положительным, то в качестве такого значения можно взять -1.
Дополнительным сервисом скрипта будет подсчет прибыли или убытка по сделке в пунктах. Также можно просуммировать показатели по каждой сделке и вывести общее итоговое значение.
Связующая функция скрипта start в результате принимает вид:
int start()
{
// — 1 — ================== Открытие файла ============================
if (!OpenFile()) return(0);
// — 1 — ================== Окончание блока ============================
// — 2 — ================== Поиск нужного ордера в истории сделок ========
CurrencyInAll = 0;
PipsInAll = 0;
for (int i = 0; i < OrdersHistoryTotal(); i++)
if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
if (OrderType() >= 0 && OrderType() < 6)
if (OrderSymbol() == SymbolName || SymbolName == «»)
if (OrderMagicNumber() == MagicNumber || MagicNumber == -1)
if (!WriteInFile())
return(0);
// — 2 — ================== Окончание блока =============================
// — 3 — ====== Закрытие файла и вывод сообщения об окончании работы =====
if (!CloseFile()) return(0);
Alert(«Скрипт успешно завершил работу!»);
// — 3 — ================== Окончание блока =============================
return(0);
}
Первый блок при помощи вызова функции OpenFile, которая будет рассмотрена ниже, пытается открыть указанный пользователем файл для записи. Если при этом была допущена хотя бы одна ошибка, то скрипт прекращает работу.
Второй блок последовательно считывает историю сделок. Сначала инициализируются переменные CurrencyInAll и PipsInAll, в которых по окончанию поиска будет находиться общая итоговая прибыль в валюте депозита и пунктах соответственно. Цикл поиска ордеров является стандартным для подобных процедур. Наличие проверки типа ордера связано с присутствием в истории счета записей о пополнении счета и выводе средств. Именно таким образом эти записи и отсеиваются. Если же найденный ордер удовлетворяет всем требованиям, то информация о нем записывается в файл при помощи функции WriteInFile. Эта операция также происходит с проведением необходимых проверок и в случае ошибки выполнение of the script прерывается.
Третий блок закрывает открытый вначале выполнения программы файл и при успешном закрытии выводит сообщение об успешном окончании работы скрипта.
Функция OpenFile также очень лаконична:
bool OpenFile()
{
// — 1 — ================== Попытка открытия файла =====================
FileHandle = FileOpen(FileName, FILE_CSV|FILE_WRITE);
if (FileHandle < 1)
{
Alert(«Не удалось открыть файл «, FileName, » для записи!»);
return(False);
}
// — 1 — ================== Окончание блока =============================
// — 2 — ================== Запись заголовка файла ======================
if (FileWrite(FileHandle, «Тикет», «Дата/время открытия», «Тип позиции», «Объем»,
«Символ», «Цена открытия», «S/L», «T/P», «Дата/время закрытия»,
«Цена закрытия», «Своп», «Прибыль, валюта», «Прибыль, пункты») < 0)
{
Alert(«Ошибка записи заголовка в файл!»);
return(False);
}
// — 2 — ================== Окончание блока ============================
return(True);
}
После открытия файла вызывается функция записи данных по каждой сделке WriteInFile:
bool WriteInFile()
{
// — 1 — ===== Получение информации по инструменту ордера ==============
int Dig = MarketInfo(OrderSymbol(), MODE_DIGITS); // Количество значащих цифр
double Points = MarketInfo(OrderSymbol(), MODE_POINT); // Размер пункта
if (GetLastError() == 4106 || Points == 0) // Инструмент не найден
if (FileWrite(FileHandle, OrderTicket(), TimeToStr(OrderOpenTime()),
NumToStr(OrderType()), DoubleToStr(OrderLots(), 2), OrderSymbol(),
«нет инф.», «нет инф.», «нет инф.», TimeToStr(OrderCloseTime()),
«нет инф.», DoubleToExcel(OrderSwap(), 2),
DoubleToExcel(OrderProfit(), 2), «нет инф.») < 0)
{
Alert(«Ошибка записи в файл!»);
return(False);
}
// — 1 — ================== Окончание блока =============================
// — 2 — ================== Вычисление прибыли в пунктах ===============
if (OrderType() == OP_BUY)
int ProfitPoints = MathRound((OrderClosePrice() — OrderOpenPrice())/Points);
else
if (OrderType() == OP_SELL)
ProfitPoints = MathRound((OrderOpenPrice() — OrderClosePrice())/Points);
else
ProfitPoints = 0;
PipsInAll += ProfitPoints;
CurrencyInAll += OrderSwap() + OrderProfit();
// — 2 — ================== Окончание блока ============================
// — 3 — ================== Запись строки в файл ========================
if (FileWrite(FileHandle, OrderTicket(), TimeToStr(OrderOpenTime()),
NumToStr(OrderType()), DoubleToExcel(OrderLots(), 2), OrderSymbol(),
DoubleToExcel(OrderOpenPrice(), Dig), DoubleToExcel(OrderStopLoss(), Dig),
DoubleToExcel(OrderTakeProfit(), Dig), TimeToStr(OrderCloseTime()),
DoubleToExcel(OrderClosePrice(), Dig), DoubleToExcel(OrderSwap(), 2),
DoubleToExcel(OrderProfit(), 2), ProfitPoints) < 0)
{
Alert(«Ошибка записи в файл!»);
return(False);
}
// — 3 — ================== Окончание блока ============================
}
Первый блок производит попытку получения информации по инструменту найденного ордера. Вполне может быть такое, что в терминале отсутствует подобный инструмент в «Обзоре рынка». Но к ошибке работы of the script это не приведет. Просто станет невозможным правильное округление значений цены и прибыли в пунктах. Поэтому в соответствующие колонки файла будет записано «нет. инф.» — нет информации.
Второй блок использует данные по инструменту, полученные в первом блоке для расчета значения прибыли в пунктах. Здесь же подсчитывается общая прибыль в валюте депозита и пунктах.
Третий блок просто записывает необходимую информацию в файл по соответствующим колонкам таблицы. Здесь стоит отметить способ записи вещественных чисел. Дело в том, что в Excel зачастую в качестве разделителя целой и дробной части используется запятая, в то время как в MQL4 – точка. Поэтому при помощи функции DoubleToExcel производится замена точки на запятую. Если у вас в Excel разделителем целой и дробной части числа выступает точка, то просто замените вызов DoubleToExcel на DoubleToStr.
И, наконец, последняя функция CloseFile:
bool CloseFile()
{
if (FileWrite(FileHandle, «») < 0 || // Пропуск одной строки после данных по сделкам
FileWrite(FileHandle, «Всего», «», «», «», «», «», «», «», «», «», «»,
DoubleToExcel(CurrencyInAll, 2), DoubleToStr(PipsInAll, 0)) < 0) // «Всего»
{
Alert(«Ошибка записи в файл!»);
return(False);
}
FileClose(FileHandle); // Закрытие файла
}
В этой функции все также должно быть очевидно. Перед закрытием файла в него дописываются значения общей прибыли в валюте депозита и пунктах. Если и эта операция проходит успешно, то файл закрывается.
Перед использованием скрипта в закладке «История счета» необходимо настроить доступ к интересующему периоду истории сделок или всей истории сделок. Только после этого можно запускать скрипт, причем неважно, к графику какой валюты он прикреплен.
В параметре SymbolName нужно указать имя инструмента, по которому производить поиск. Если указать пустую строку (пробелы тоже нужно удалить), то в результатах будут отображены все найденные сделки, если при этом значение MagicNumber установить -1. Любое другое значение MagicNumber ограничит количество найденных сделок.
Файл, имя которого нужно указать в параметре FileName, после успешного выполнения скрипта нужно искать в папке терминала experts\files.
The full source code of the script can be found here.