Обсуждение статьи "Библиотека для простого и быстрого создания программ для MetaTrader (Часть X): Совместимость с MQL4 - События открытия позиции и активации отложенных ордеров" - страница 3
Артём, скажи пожалуйста какую роль играет выделенный участок кода
Как может выполняться этот код, если таймер не включен?
Но если этот участок кода удалить, то сообщения о событии не печатаются. А с ним всё работает.
И хотелось-бы вместе с сообщением о событии была возможность получить тикет, цены и возможно какие-то ещё свойства позиций и ордеров.
Мне кажется, что ты поменял комментарий. В OnTimer() советника проверяется работа не в тестере:
/************************Expert tick function************************/voidOnTick()
{
//--- Инициализация последнего торгового событияstatic ENUM_TRADE_EVENT last_event=WRONG_VALUE;
//--- Если работа в тестереif(MQLInfoInteger(MQL_TESTER))
{
engine.OnTimer();
}//--- Если последнее торговое событие изменилосьif(engine.LastTradeEvent()!=last_event)
{
last_event=engine.LastTradeEvent();
Comment("last_event: ",EnumToString(last_event));
Print(__FUNCTION__, " last_event: ",EnumToString(last_event));
//engine.ResetLastTradeEvent();//Print("last_event: ",EnumToString(last_event));
}
}
/***************************Timer function***************************/voidOnTimer()
{
//--- Инициализация последнего торгового событияstatic ENUM_TRADE_EVENT last_event=WRONG_VALUE;
//--- Если работа не в тестереif(!MQLInfoInteger(MQL_TESTER))
{
engine.OnTimer();
}
}
/*******************************************************************/
И сравни два обработчика: в OnTick() таймер библиотеки запускается только в тестере, а в OnTimer() таймер библиотеки запускается только не в тестере - ведь в MQL4 таймер в тестере не работает, и работаем по тикам в тестере.
Просто копировал в одном месте, а вставлял в разные и не обратил внимания. Но потом поставил отрицание в виде ! а не важное не трогал.
Но вопрос остался без ответа: Если в OnInit() таймер не запускается, то какой смысл вообще в обработчике OnTimer() и почему код в нём выполняется как минимум один раз.
В принципе я получил сообщения в журнал. Осталось получить свойства позиций. Тип, тикет, цены и время открытия, закрытия, модификации.
И хотелось-бы вместе с сообщением о событии была возможность получить тикет, цены и возможно какие-то ещё свойства позиций и ордеров.
Не в тестере ты можешь получить тикет ордера последнего события в OnChartEvent() - параметр lparam. В dparam хранится цена. В sparam - символ.
Чтобы получать данные в тестере, нужно на данный момент использовать код события, который получаешь при помощи engine.LastTradeEvent() - ведь всё зависит от события - если это модификация, то нужно получать список модификаций, а если это изменение количества ордеров, то нужно получать списки этих новых ордеров.
Нужно добавить в CEngine возврат нужных значений в программу. Я же ещё не дошёл до отправки в программу сведений - пока идёт описание подготовки необходимых данных. В последующих статьях дойдём до класса, дающего простой доступ ко всем нужным данным. А сейчас - если нужно прям срочно, то надо добавить в CEngine возврат списка из класса-коллекции событий - в самом классе есть получение этого списка, вот они - все списки в публичной секции CEventCollection:
public:
//--- Выбирает события из коллекции со временем в диапазоне от begin_time до end_time
CArrayObj *GetListByTime(const datetime begin_time=0,const datetime end_time=0);
//--- Возвращает полный список-коллекцию событий "как есть"
CArrayObj *GetList(void) { return &this.m_list_events; }
//--- Возвращает список по выбранному (1) целочисленному, (2) вещественному и (3) строковому свойству, удовлетворяющему сравниваемому критерию
CArrayObj *GetList(ENUM_EVENT_PROP_INTEGER property,longvalue,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByEventProperty(this.GetList(),property,value,mode); }
CArrayObj *GetList(ENUM_EVENT_PROP_DOUBLE property,doublevalue,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByEventProperty(this.GetList(),property,value,mode); }
CArrayObj *GetList(ENUM_EVENT_PROP_STRING property,stringvalue,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByEventProperty(this.GetList(),property,value,mode); }
Все события хранятся в списке m_list_events, а эти методы возвращают либо полный список, либо отфильтрованный по заданному критерию.
Для получения последнего события достаточно создать в CEngine возврат этого списка в программу, а в программе уже брать из списка нужное событие.
Всё это скоро будет автоматизировано - пока до этого не дошла очерёдность.
Если тебе нужно всё же сделать костыль, то его обсуждение - в личку. Здесь не стоит - это не относится к библиотеке, так как она на стадии разработки, и далее будет сделана нормальная и правильная работа по получению всех и любых требуемых событий в программе.
Просто копировал в одном месте, а вставлял в разные и не обратил внимания. Но потом поставил отрицание в виде ! а не важное не трогал.
Но вопрос остался без ответа: Если в OnInit() таймер не запускается, то какой смысл вообще в обработчике OnTimer() и почему код в нём выполняется как минимум один раз.
В принципе я получил сообщения в журнал. Осталось получить свойства позиций. Тип, тикет, цены и время открытия, закрытия, модификации.
Поясни что имеешь в виду? Ты говоришь о создании таймера? Он создаётся в конструкторе CEngine:
//+------------------------------------------------------------------+//| CEngine конструктор |//+------------------------------------------------------------------+
CEngine::CEngine() : m_first_start(true),m_last_trade_event(TRADE_EVENT_NO_EVENT)
{
this.m_list_counters.Sort();
this.m_list_counters.Clear();
this.CreateCounter(COLLECTION_COUNTER_ID,COLLECTION_COUNTER_STEP,COLLECTION_PAUSE);
this.m_is_hedge=#ifdef __MQL4__ true#else bool(::AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) #endif;
this.m_is_tester=::MQLInfoInteger(MQL_TESTER);
::ResetLastError();
#ifdef __MQL5__if(!::EventSetMillisecondTimer(TIMER_FREQUENCY))
::Print(DFUN,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError());
//---__MQL4__#else
if(!this.IsTester() && !::EventSetMillisecondTimer(TIMER_FREQUENCY))
::Print(DFUN,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError());
#endif }
//+------------------------------------------------------------------+
Не в тестере ты можешь получить тикет ордера последнего события в OnChartEvent() - параметр lparam. В dparam хранится цена. В sparam - символ.
Это я уже нашёл, спасибо. А получив тикет можно получить всё что надо. За исключением с какой цены была модификация. Или делать действительно костыль чтобы знать цену до модификации. В принципе не очень пока надо.
Это я уже нашёл, спасибо. А получив тикет можно получить всё что надо. За исключением с какой цены была модификация. Или делать действительно костыль чтобы знать цену до модификации. В принципе не очень пока надо.
Я тебе уже дал код - там есть всё, и цена до модификации тоже.
И вдруг при очередном издевательстве был модифицирована одна позиция, одна открыта и закрыта. Но вот откуда появилась запись об удалении давно удалённого ордера?
Артём, скажи пожалуйста какую роль играет выделенный участок кода
Как может выполняться этот код, если таймер не включен?
Но если этот участок кода удалить, то сообщения о событии не печатаются. А с ним всё работает.
И хотелось-бы вместе с сообщением о событии была возможность получить тикет, цены и возможно какие-то ещё свойства позиций и ордеров.
Мне кажется, что ты поменял комментарий. В OnTimer() советника проверяется работа не в тестере:
И сравни два обработчика: в OnTick() таймер библиотеки запускается только в тестере, а в OnTimer() таймер библиотеки запускается только не в тестере - ведь в MQL4 таймер в тестере не работает, и работаем по тикам в тестере.
Сейчас пример сделаю.
Мне кажется, что ты поменял комментарий.
Комментарий сам поменялся, я не трогал.)))
Просто копировал в одном месте, а вставлял в разные и не обратил внимания. Но потом поставил отрицание в виде ! а не важное не трогал.
Но вопрос остался без ответа: Если в OnInit() таймер не запускается, то какой смысл вообще в обработчике OnTimer() и почему код в нём выполняется как минимум один раз.
В принципе я получил сообщения в журнал. Осталось получить свойства позиций. Тип, тикет, цены и время открытия, закрытия, модификации.
И хотелось-бы вместе с сообщением о событии была возможность получить тикет, цены и возможно какие-то ещё свойства позиций и ордеров.
Не в тестере ты можешь получить тикет ордера последнего события в OnChartEvent() - параметр lparam. В dparam хранится цена. В sparam - символ.
Чтобы получать данные в тестере, нужно на данный момент использовать код события, который получаешь при помощи engine.LastTradeEvent() - ведь всё зависит от события - если это модификация, то нужно получать список модификаций, а если это изменение количества ордеров, то нужно получать списки этих новых ордеров.
Нужно добавить в CEngine возврат нужных значений в программу. Я же ещё не дошёл до отправки в программу сведений - пока идёт описание подготовки необходимых данных. В последующих статьях дойдём до класса, дающего простой доступ ко всем нужным данным. А сейчас - если нужно прям срочно, то надо добавить в CEngine возврат списка из класса-коллекции событий - в самом классе есть получение этого списка, вот они - все списки в публичной секции CEventCollection:
Все события хранятся в списке m_list_events, а эти методы возвращают либо полный список, либо отфильтрованный по заданному критерию.
Для получения последнего события достаточно создать в CEngine возврат этого списка в программу, а в программе уже брать из списка нужное событие.
Всё это скоро будет автоматизировано - пока до этого не дошла очерёдность.
Если тебе нужно всё же сделать костыль, то его обсуждение - в личку. Здесь не стоит - это не относится к библиотеке, так как она на стадии разработки, и далее будет сделана нормальная и правильная работа по получению всех и любых требуемых событий в программе.
Комментарий сам поменялся, я не трогал.)))
Просто копировал в одном месте, а вставлял в разные и не обратил внимания. Но потом поставил отрицание в виде ! а не важное не трогал.
Но вопрос остался без ответа: Если в OnInit() таймер не запускается, то какой смысл вообще в обработчике OnTimer() и почему код в нём выполняется как минимум один раз.
В принципе я получил сообщения в журнал. Осталось получить свойства позиций. Тип, тикет, цены и время открытия, закрытия, модификации.
Поясни что имеешь в виду? Ты говоришь о создании таймера? Он создаётся в конструкторе CEngine:
Не в тестере ты можешь получить тикет ордера последнего события в OnChartEvent() - параметр lparam. В dparam хранится цена. В sparam - символ.
Это я уже нашёл, спасибо. А получив тикет можно получить всё что надо. За исключением с какой цены была модификация. Или делать действительно костыль чтобы знать цену до модификации. В принципе не очень пока надо.
В принципе я получил сообщения в журнал. Осталось получить свойства позиций. Тип, тикет, цены и время открытия, закрытия, модификации.
Впрочем, для быстрого решения, добавь в публичную секцию CEngine возврат списка событий:
В советнике добавь этот код:
И последнее событие распечатается в журнале
Поясни что имеешь в виду? Ты говоришь о создании таймера? Он создаётся в конструкторе CEngine:
Ну, так для этого-же надо было всю библиотеку проштудировать. )))
Это я уже нашёл, спасибо. А получив тикет можно получить всё что надо. За исключением с какой цены была модификация. Или делать действительно костыль чтобы знать цену до модификации. В принципе не очень пока надо.
Я тебе уже дал код - там есть всё, и цена до модификации тоже.
Ну, так для этого-же надо было всю библиотеку проштудировать. )))
Нет. Просто прочитать статьи
И вот такая непонятка случилась:
Пока я гонял этот код на демке был установлен и удалён лимитный ордер
И вдруг при очередном издевательстве был модифицирована одна позиция, одна открыта и закрыта. Но вот откуда появилась запись об удалении давно удалённого ордера?