Как вы ищете ошибки в программе? - страница 5

 
давно пишу советников. Пользуюсь в основном Print ом. А что такое логирование ?
 

Логирование вообще-то кудаздо более широкое определение чем поиск ошибок print'ом

enum ENUM_LOG_LEVELS {
  LOG_LEVEL_NONE, // disabled
  LOG_LEVEL_ERR,  // errors only
  LOG_LEVEL_INFO, // errors + EA comments
  LOG_LEVEL_ALL   // debugging
};

...

if(Log_Level > LOG_LEVEL_ERR)
  PrintFormat(
    "Позиция над уровнем закрыта с прибылью %.2f. Общая прибыль: %.2f. Закрыть всё",
    OrderProfit(),
    d_Profit
  );

 
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
 

 
Я ищу ошибки распечатывая значения переменных с помощью Comment. Иногда я вывожу их на экран с помощью метки OBJ_LABEL.
 
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.

profiler on the historical data

Thanks.

It works only in Visual mode ?

Это - отличные новости, только что проверил. Спасибо.

Это работает только в Визуальном способе?
 
George Merts:

Логирование - это примерно тоже самое, что 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 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво

 
Konstantin:

круто )) есть два вопроса:
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-режим только на некотором участке кода.

 
Konstantin:

по п.3 вопрос возникает, т.к. при тестировании на истории, считывание и запись в файл очень тормозит тесты, поэтому все записи делаю в журнал, а вот при тестировании на реальной торговле для отлова багов и т.д. уже пишу в отдельный файл логов, но у меня не так все конечно выглядит красиво

Можно писать логи в отдельный процесс (через сокет), который и будет их сливать в файлы. Тормозить не будет.

 
Mesaoria:

Можно писать логи в отдельный процесс (через сокет), который и будет их сливать в файлы. Тормозить не будет.

т.е. выносить из кухни МТ5 в кухню ОС? тогда как вариант не через сокет, а через маппинг, но нужен внешний модуль, читающий память, тогда конечно система не будет вообще от этого зависеть
 
Konstantin:
т.е. выносить из кухни МТ5 в кухню ОС? тогда как вариант не через сокет, а через маппинг, но нужен внешний модуль, читающий память, тогда конечно система не будет вообще от этого зависеть
Ну или так. Просто синхронная запись в файл на диске - относительно "дорогая" операция
Причина обращения: