Dmitiry Ananiev: давно пишу советников. Пользуюсь в основном Print ом. А что такое логирование ?
Логирование - это примерно тоже самое, что Print - но только в специальный файл.
Также я использую термин "Трассировка". У меня куча макросов типа TRACE_DOUBLE4(strName,dValue) - в данном случае выводится в лог-файл фраза и значение double c 4-значной точностью. При этом, в файле определений этого макроса - с помощью дефайнов можно его сделать пустым (для RELEASE варианта), можно выводить сообщения в лог, можно в Print, можно в Comment, можно в МessageBox. При этом не только выводится этот текст, но и момент, название объекта, и номер строки.
Вот, например, лог файл для простого советника, совершившего одну сделку:
2017.05.01 00:00:00 Log file has opened. Log file path: Trace_12345_EURUSD.log 2017.05.01 00:00:00 int OnInit(), line 52: Советник запущен (произведен вход в функцию OnInit() 2017.05.01 00:00:00 void _TellTraceMode(), line 26: Запуск эксперта DoubleExt_EA. Дата билда: 2017.05.16 2017.05.01 00:00:00 void _TellTraceMode(), line 34: Включены режимы _RELEASE и _FORCEASSERT (Трассирующие макросы и ассерты работают) 2017.05.01 00:00:00 void _TellTraceMode(), line 38: Включены режимы _RELEASE и _FORCETRACE (Трассирующие макросы работают.) 2017.05.01 00:00:00 void _TellTraceMode(), line 46: Режим _TESTERONLY выключен. 2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnSymbol(ECurrencySymbol), line 237: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnSymbol(), по умолчанию разрешаем работу на данном символе 2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnTimeframe(ENUM_TIMEFRAMES), line 231: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnTimeframe(), по умолчанию разрешаем работу на данном таймфрейме 2017.05.01 00:00:00 int CDataProviderT::GetConstSpread(ECurrencySymbol), line 349: Для МТ4 спред в таймсериях не предусмотрен, устанавливаем фиксированный спред, пт: 15 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08876 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08856 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 166: Успешно создан запрос на вход в лонг ! 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 168: Объем: 0.0100 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 169: TP: 1.09512 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 170: SL: 1.08856 2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 17: Очередь торговых реквестов не пуста ! Реквестов :1 2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 21: Количество реквестов: 1 2017.05.01 02:00:00 EEAWorkRetcode CChngPosComponentRequestT::ProceedRequestInto(CTradeProcessorI*,datetime), line 79: Внимание ! Запрос отправляется на исполнение ! 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Создан и инициализирован 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 4294967295 2017.05.01 02:00:00 void CExpert::_BeforeRequestDelete(CChngPosComponentRequestI*), line 45: Внимание ! Удаляется реквест ! 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Успешно обработан на сервере 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 0 2017.05.01 02:22:30 void CExpert::MyOnDeinit(const int), line 196: Деинициализация эксперта ! Причина: График закрыт 2017.05.01 02:22:30 Log file has closed. Log file path: Trace_12345_EURUSD.log
Renat Fatkhullin: For information: in the next build we will release a profiler on the historical data, which will make it possible to optimize the programs much more easily.
Plus, we fix the brakes on access to history, especially on measuring instruments. It will be easy to write global character scanners without brakes.
That's great news, just tested it.
Thanks.
It works only in Visual mode ?
Это - отличные новости, только что проверил. Спасибо.
Логирование - это примерно тоже самое, что Print - но только в специальный файл.
Также я использую термин "Трассировка". У меня куча макросов типа TRACE_DOUBLE4(strName,dValue) - в данном случае выводится в лог-файл фраза и значение double c 4-значной точностью. При этом, в файле определений этого макроса - с помощью дефайнов можно его сделать пустым (для RELEASE варианта), можно выводить сообщения в лог, можно в Print, можно в Comment, можно в МessageBox. При этом не только выводится этот текст, но и момент, название объекта, и номер строки.
Вот, например, лог файл для простого советника, совершившего одну сделку:
2017.05.01 00:00:00 Log file has opened. Log file path: Trace_12345_EURUSD.log 2017.05.01 00:00:00 int OnInit(), line 52: Советник запущен (произведен вход в функцию OnInit() 2017.05.01 00:00:00 void _TellTraceMode(), line 26: Запуск эксперта DoubleExt_EA. Дата билда: 2017.05.16 2017.05.01 00:00:00 void _TellTraceMode(), line 34: Включены режимы _RELEASE и _FORCEASSERT (Трассирующие макросы и ассерты работают) 2017.05.01 00:00:00 void _TellTraceMode(), line 38: Включены режимы _RELEASE и _FORCETRACE (Трассирующие макросы работают.) 2017.05.01 00:00:00 void _TellTraceMode(), line 46: Режим _TESTERONLY выключен. 2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnSymbol(ECurrencySymbol), line 237: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnSymbol(), по умолчанию разрешаем работу на данном символе 2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnTimeframe(ENUM_TIMEFRAMES), line 231: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnTimeframe(), по умолчанию разрешаем работу на данном таймфрейме 2017.05.01 00:00:00 int CDataProviderT::GetConstSpread(ECurrencySymbol), line 349: Для МТ4 спред в таймсериях не предусмотрен, устанавливаем фиксированный спред, пт: 15 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446 2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446 2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08876 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08856 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446 2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 166: Успешно создан запрос на вход в лонг ! 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 168: Объем: 0.0100 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 169: TP: 1.09512 2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 170: SL: 1.08856 2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 17: Очередь торговых реквестов не пуста ! Реквестов :1 2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 21: Количество реквестов: 1 2017.05.01 02:00:00 EEAWorkRetcode CChngPosComponentRequestT::ProceedRequestInto(CTradeProcessorI*,datetime), line 79: Внимание ! Запрос отправляется на исполнение ! 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Создан и инициализирован 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 4294967295 2017.05.01 02:00:00 void CExpert::_BeforeRequestDelete(CChngPosComponentRequestI*), line 45: Внимание ! Удаляется реквест ! 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий: 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Успешно обработан на сервере 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00 2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 0 2017.05.01 02:22:30 void CExpert::MyOnDeinit(const int), line 196: Деинициализация эксперта ! Причина: График закрыт 2017.05.01 02:22:30 Log file has closed. Log file path: Trace_12345_EURUSD.log
круто )) есть два вопроса: 1. как определяете строку для вывода 2. что такое реквест 3. это лог в момент тестирования в реале или тестирование на истории?
по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво
круто )) есть два вопроса: 1. как определяете строку для вывода 2. что такое реквест 3. это лог в момент тестирования в реале или тестирование на истории?
по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво
1. Базовый трассировочный макрос для DEBUG-варианта ракрывается следующим образом:
/* TRACEMODE: 0 - без трассирующих сообщений 1 - трассирующие сообщения через Print 2 - трассирующие сообщения в файл 3 - трассирующие сообщения через Print и в файл */
switch(TRACEMODE) { case 0: return;
case 1: Print(strRes); return;
case 2: CLogFile::GlobalLogString(strRes,_CreateLogFilename(ulMagic,strSymbol)); return;
case 3: Print(strRes); CLogFile::GlobalLogString(strRes,_CreateLogFilename(ulMagic,strSymbol)); return;
case 4: Print(strRes); CLogFile::GlobalLogString(strRes,_CreateLogFilename(ulMagic,strSymbol)); return;
default: break; } };
2. У меня советник построен следующим образом - сперва части эксперта (их может быть много, по разным символам, и в пределах одного символа - генератор входов, анализатор объема позиции, определитель TP-SL) анализируют ситуацию, и принимают решения, что необходимо сделать. Потом - эти решения исполняются торговым процессором.
Соответственно, при анализе ситуации - создается список запросов на торговые действия - объекты-наследники виртуального интерфейса:
class CChngPosComponentRequestI: public CMyObject { public: void CChngPosComponentRequestI() { SetMyObjectType(MOT_CHNG_POSCOPMPONENT_REQUEST_I); }; virtual void ~CChngPosComponentRequestI() {};
// Функция отправляет реквест на сервер, через указанный трейд процессор интерфейс virtual EEAWorkRetcode ProceedRequestInto(CTradeProcessorI* ptpProcessor,datetime dtCurMoment) = 0; };
Проще говоря, реквест - это просто требование на торговое действие, поддерживающий данный интерфейс. Оно также платформонезависимо, части эксперта просто вызывают функции создания тех или иных реквестов, они складываются в очередь, а после анализа - реквесты отправляются в торговый процессор, для чего есть соответствующая виртуальная функция. Опять же, эксперт не имеет прямого доступа к реквестам, только к их интерфейсу, и чтобы послать реквест в торговый процессор, он вызывает функцию ProceedRequestInto(), передавая ей указатель на интерфейс процессора. Реквест, в свою очередь - тоже не имеет прямого доступа к торговому процессору, но получив указатель на интерфейс - вызывает соответствующие функции, некобходимые именно для реквеста данного типа.
В результате - все блоки изолированы друг от друга, никто ни про кого ничего не знает, общение происходит только на уровне чисто виртуальных интерфейсов, которые были написаны при проектировании системы, и меняются лишь в крайнем случае (и это весьма неприятная ситуация).
3. Данный лог - лог тестера. Действительно, запись в лог - очень сильно тормозит работу. Более того, я стараюсь как можно чаще использовать макросы ASSERT, проверяя, по возможности, все, что проверяется (например, если у меня есть отсортированный массив - порядок сортировки проверяется в каждой функции, которая его использует), это еще сильнее тормозит работу.
Именно поэтому у меня есть свои DEBUG и RELEASE версии, независимые от типа компиляции. Включающиеся макросами FORCEASSERT и FORCETRACE. Плюс трассировка и ассерты могут включаться и выключаться в DEBUG-режим только на некотором участке кода.
по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво
Можно писать логи в отдельный процесс (через сокет), который и будет их сливать в файлы. Тормозить не будет.
Можно писать логи в отдельный процесс (через сокет), который и будет их сливать в файлы. Тормозить не будет.
т.е. выносить из кухни МТ5 в кухню ОС? тогда как вариант не через сокет, а через маппинг, но нужен внешний модуль, читающий память, тогда конечно система не будет вообще от этого зависеть
Konstantin: т.е. выносить из кухни МТ5 в кухню ОС? тогда как вариант не через сокет, а через маппинг, но нужен внешний модуль, читающий память, тогда конечно система не будет вообще от этого зависеть
Ну или так. Просто синхронная запись в файл на диске - относительно "дорогая" операция
Логирование вообще-то кудаздо более широкое определение чем поиск ошибок print'ом
давно пишу советников. Пользуюсь в основном Print ом. А что такое логирование ?
Логирование - это примерно тоже самое, что Print - но только в специальный файл.
Также я использую термин "Трассировка". У меня куча макросов типа TRACE_DOUBLE4(strName,dValue) - в данном случае выводится в лог-файл фраза и значение double c 4-значной точностью. При этом, в файле определений этого макроса - с помощью дефайнов можно его сделать пустым (для RELEASE варианта), можно выводить сообщения в лог, можно в Print, можно в Comment, можно в МessageBox. При этом не только выводится этот текст, но и момент, название объекта, и номер строки.
Вот, например, лог файл для простого советника, совершившего одну сделку:
2017.05.01 00:00:00 Log file has opened. Log file path: Trace_12345_EURUSD.log
2017.05.01 00:00:00 int OnInit(), line 52: Советник запущен (произведен вход в функцию OnInit()
2017.05.01 00:00:00 void _TellTraceMode(), line 26: Запуск эксперта DoubleExt_EA. Дата билда: 2017.05.16
2017.05.01 00:00:00 void _TellTraceMode(), line 34: Включены режимы _RELEASE и _FORCEASSERT (Трассирующие макросы и ассерты работают)
2017.05.01 00:00:00 void _TellTraceMode(), line 38: Включены режимы _RELEASE и _FORCETRACE (Трассирующие макросы работают.)
2017.05.01 00:00:00 void _TellTraceMode(), line 46: Режим _TESTERONLY выключен.
2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnSymbol(ECurrencySymbol), line 237: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnSymbol(), по умолчанию разрешаем работу на данном символе
2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnTimeframe(ENUM_TIMEFRAMES), line 231: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnTimeframe(), по умолчанию разрешаем работу на данном таймфрейме
2017.05.01 00:00:00 int CDataProviderT::GetConstSpread(ECurrencySymbol), line 349: Для МТ4 спред в таймсериях не предусмотрен, устанавливаем фиксированный спред, пт: 15
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08876
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08856
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 166: Успешно создан запрос на вход в лонг !
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 168: Объем: 0.0100
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 169: TP: 1.09512
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 170: SL: 1.08856
2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 17: Очередь торговых реквестов не пуста ! Реквестов :1
2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 21: Количество реквестов: 1
2017.05.01 02:00:00 EEAWorkRetcode CChngPosComponentRequestT::ProceedRequestInto(CTradeProcessorI*,datetime), line 79: Внимание ! Запрос отправляется на исполнение !
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Создан и инициализирован
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 4294967295
2017.05.01 02:00:00 void CExpert::_BeforeRequestDelete(CChngPosComponentRequestI*), line 45: Внимание ! Удаляется реквест !
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Успешно обработан на сервере
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 0
2017.05.01 02:22:30 void CExpert::MyOnDeinit(const int), line 196: Деинициализация эксперта ! Причина: График закрыт
2017.05.01 02:22:30 Log file has closed. Log file path: Trace_12345_EURUSD.log
For information: in the next build we will release a profiler on the historical data, which will make it possible to optimize the programs much more easily.
That's great news, just tested it.
Thanks.
It works only in Visual mode ?
Логирование - это примерно тоже самое, что Print - но только в специальный файл.
Также я использую термин "Трассировка". У меня куча макросов типа TRACE_DOUBLE4(strName,dValue) - в данном случае выводится в лог-файл фраза и значение double c 4-значной точностью. При этом, в файле определений этого макроса - с помощью дефайнов можно его сделать пустым (для RELEASE варианта), можно выводить сообщения в лог, можно в Print, можно в Comment, можно в МessageBox. При этом не только выводится этот текст, но и момент, название объекта, и номер строки.
Вот, например, лог файл для простого советника, совершившего одну сделку:
2017.05.01 00:00:00 Log file has opened. Log file path: Trace_12345_EURUSD.log
2017.05.01 00:00:00 int OnInit(), line 52: Советник запущен (произведен вход в функцию OnInit()
2017.05.01 00:00:00 void _TellTraceMode(), line 26: Запуск эксперта DoubleExt_EA. Дата билда: 2017.05.16
2017.05.01 00:00:00 void _TellTraceMode(), line 34: Включены режимы _RELEASE и _FORCEASSERT (Трассирующие макросы и ассерты работают)
2017.05.01 00:00:00 void _TellTraceMode(), line 38: Включены режимы _RELEASE и _FORCETRACE (Трассирующие макросы работают.)
2017.05.01 00:00:00 void _TellTraceMode(), line 46: Режим _TESTERONLY выключен.
2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnSymbol(ECurrencySymbol), line 237: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnSymbol(), по умолчанию разрешаем работу на данном символе
2017.05.01 00:00:00 bool CEAPartsFactoryT::CanWorkOnTimeframe(ENUM_TIMEFRAMES), line 231: Не перегружена функция CMyAdvisorPartsFactoryT::CanWorkOnTimeframe(), по умолчанию разрешаем работу на данном таймфрейме
2017.05.01 00:00:00 int CDataProviderT::GetConstSpread(ECurrencySymbol), line 349: Для МТ4 спред в таймсериях не предусмотрен, устанавливаем фиксированный спред, пт: 15
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446
2017.05.01 00:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08620
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08600
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446
2017.05.01 01:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 98: Long SL Low: 1.08876
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 99: Long SL : 1.08856
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 101: Short SL High: 1.09446
2017.05.01 02:00:00 bool CDoubleExt_EG::_GetEAState(SDblExtState&), line 102: Short SL : 1.09466
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 166: Успешно создан запрос на вход в лонг !
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 168: Объем: 0.0100
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 169: TP: 1.09512
2017.05.01 02:00:00 bool CCPRqEAPartT::_SendEnterTradeRequest(CCPRList*,ENUM_POSITION_TYPE,double,double,string,datetime), line 170: SL: 1.08856
2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 17: Очередь торговых реквестов не пуста ! Реквестов :1
2017.05.01 02:00:00 EEAWorkRetcode CExpert::_ProceedTradeRequests(datetime), line 21: Количество реквестов: 1
2017.05.01 02:00:00 EEAWorkRetcode CChngPosComponentRequestT::ProceedRequestInto(CTradeProcessorI*,datetime), line 79: Внимание ! Запрос отправляется на исполнение !
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Создан и инициализирован
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 4294967295
2017.05.01 02:00:00 void CExpert::_BeforeRequestDelete(CChngPosComponentRequestI*), line 45: Внимание ! Удаляется реквест !
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 97: Трассировка реквеста:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 98: ID создателя реквеста: 7006
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 99: Тип реквеста: Создание новой компоненты позиции
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 100: Символ реквеста: EURUSD
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 101: Тикет торговой компоненты: -1
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 102: Комментарий:
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 103: Состояние реквеста: Успешно обработан на сервере
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 104: Момент создания реквеста: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 105: Момент экспирации реквеста: 2100.01.01 00:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 106: Момент отсылки на сервер: 2017.05.01 02:00:00
2017.05.01 02:00:00 void CChngPosComponentRequestT::TraceRequest(), line 107: Код возврата сервера: 0
2017.05.01 02:22:30 void CExpert::MyOnDeinit(const int), line 196: Деинициализация эксперта ! Причина: График закрыт
2017.05.01 02:22:30 Log file has closed. Log file path: Trace_12345_EURUSD.log
круто )) есть два вопроса:
1. как определяете строку для вывода
2. что такое реквест
3. это лог в момент тестирования в реале или тестирование на истории?
по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво
круто )) есть два вопроса:
1. как определяете строку для вывода
2. что такое реквест
3. это лог в момент тестирования в реале или тестирование на истории?
по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво
1. Базовый трассировочный макрос для DEBUG-варианта ракрывается следующим образом:
#define TRACE2(strValue1,strValue2) PerformTrace2(strValue1,strValue2,__FUNCSIG__,__LINE__,_GetMagic(),_Symbol);
А функция PerformTrace2() - объединяет две строки, и вызвает функцию PerformTrace(), которая и производит трассировку, в зависимости от режимов. :
void PerformTrace(string strValue,string strFunc,string strLine,ulong ulMagic,string strSymbol)
{
if(FUNCTIONSIG4TRACE !="" && strFunc != FUNCTIONSIG4TRACE)
return;
if(bGTracePermition != true)
return;
uint uiCurTickCounter = GetTickCount();
if(bGDenyOftenTrace == true && uiCurTickCounter - uiGTraceTickCounter < TRACEMINTIME)
return;
uiGTraceTickCounter = uiCurTickCounter;
string strRes;
if(TRACEFUNCTIONSIG == 1)
#ifdef __MQL5__
StringConcatenate(strRes,strFunc,", line ",strLine,": ",strValue);
#else
strRes = StringConcatenate(strFunc,", line ",strLine,": ",strValue);
#endif
else
strRes = strValue;
if(TRACEREPEAT == 0)
{
if(strGLastMessage == strValue)
{
++uiGNumOfPassedMessages;
return;
};
if(uiGNumOfPassedMessages > 0)
{
strRes = "(ВНИМАНИЕ !!! Пропущено одинаковых предыдущих сообщений: " + IntegerToString(uiGNumOfPassedMessages) + "); " + strRes ;
uiGNumOfPassedMessages = 0;
};
strGLastMessage = strValue;
};
/*
TRACEMODE:
0 - без трассирующих сообщений
1 - трассирующие сообщения через Print
2 - трассирующие сообщения в файл
3 - трассирующие сообщения через Print и в файл
*/
switch(TRACEMODE)
{
case 0:
return;
case 1:
Print(strRes);
return;
case 2:
CLogFile::GlobalLogString(strRes,_CreateLogFilename(ulMagic,strSymbol));
return;
case 3:
Print(strRes);
CLogFile::GlobalLogString(strRes,_CreateLogFilename(ulMagic,strSymbol));
return;
case 4:
Print(strRes);
CLogFile::GlobalLogString(strRes,_CreateLogFilename(ulMagic,strSymbol));
return;
default:
break;
}
};
2. У меня советник построен следующим образом - сперва части эксперта (их может быть много, по разным символам, и в пределах одного символа - генератор входов, анализатор объема позиции, определитель TP-SL) анализируют ситуацию, и принимают решения, что необходимо сделать. Потом - эти решения исполняются торговым процессором.
Соответственно, при анализе ситуации - создается список запросов на торговые действия - объекты-наследники виртуального интерфейса:
class CChngPosComponentRequestI: public CMyObject
{
public:
void CChngPosComponentRequestI() { SetMyObjectType(MOT_CHNG_POSCOPMPONENT_REQUEST_I); };
virtual void ~CChngPosComponentRequestI() {};
virtual CEAPartI* GetCreator() = 0;
virtual EChngPosRequestType GetRequestType() = 0;
virtual ECurrencySymbol GetSymbol() = 0;
virtual long GetComponentTicket() = 0;
virtual string GetCommentary() = 0;
virtual EChngPosRequestState GetState() = 0;
virtual datetime GetCreatedMoment() = 0;
virtual datetime GetExpiresMoment() = 0;
virtual datetime GetSendToServerMoment() = 0;
virtual uint GetServerRetCode() = 0;
// Функция отправляет реквест на сервер, через указанный трейд процессор интерфейс
virtual EEAWorkRetcode ProceedRequestInto(CTradeProcessorI* ptpProcessor,datetime dtCurMoment) = 0;
};
Проще говоря, реквест - это просто требование на торговое действие, поддерживающий данный интерфейс. Оно также платформонезависимо, части эксперта просто вызывают функции создания тех или иных реквестов, они складываются в очередь, а после анализа - реквесты отправляются в торговый процессор, для чего есть соответствующая виртуальная функция. Опять же, эксперт не имеет прямого доступа к реквестам, только к их интерфейсу, и чтобы послать реквест в торговый процессор, он вызывает функцию ProceedRequestInto(), передавая ей указатель на интерфейс процессора. Реквест, в свою очередь - тоже не имеет прямого доступа к торговому процессору, но получив указатель на интерфейс - вызывает соответствующие функции, некобходимые именно для реквеста данного типа.
В результате - все блоки изолированы друг от друга, никто ни про кого ничего не знает, общение происходит только на уровне чисто виртуальных интерфейсов, которые были написаны при проектировании системы, и меняются лишь в крайнем случае (и это весьма неприятная ситуация).
3. Данный лог - лог тестера. Действительно, запись в лог - очень сильно тормозит работу. Более того, я стараюсь как можно чаще использовать макросы ASSERT, проверяя, по возможности, все, что проверяется (например, если у меня есть отсортированный массив - порядок сортировки проверяется в каждой функции, которая его использует), это еще сильнее тормозит работу.
Именно поэтому у меня есть свои DEBUG и RELEASE версии, независимые от типа компиляции. Включающиеся макросами FORCEASSERT и FORCETRACE. Плюс трассировка и ассерты могут включаться и выключаться в DEBUG-режим только на некотором участке кода.
по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво
Можно писать логи в отдельный процесс (через сокет), который и будет их сливать в файлы. Тормозить не будет.
Можно писать логи в отдельный процесс (через сокет), который и будет их сливать в файлы. Тормозить не будет.
т.е. выносить из кухни МТ5 в кухню ОС? тогда как вариант не через сокет, а через маппинг, но нужен внешний модуль, читающий память, тогда конечно система не будет вообще от этого зависеть