Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Логирование вообще-то кудаздо более широкое определение чем поиск ошибок 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 в кухню ОС? тогда как вариант не через сокет, а через маппинг, но нужен внешний модуль, читающий память, тогда конечно система не будет вообще от этого зависеть