Если ордер исполнился частично, то его не будет в Истории до тех пор, пока он не исполнится полностью (но здесь делать FILLED-проверку делать бессмыленно), либо будет отменен (но здесь и STATE станет Cancelled, т.е. опять же FILLED-проверка не актуальна).
Согласен. Я это обдумывал. Нужно контролировать эту ситуацию. Я даже написал уже себе заготовку для этого. Но, по скольку не нужно было ещё это и не как проверить пока что забил т.к. и без этого полно дел.
Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:
if (transaction.type == TRADE_TRANSACTION_DEAL_ADD) {
Print("transaction.order = ", transaction.order);
Print("historyType = ", EnumToString(selectedHistoryOrderType(transaction.order)));
HistoryOrderSelect(transaction.order);
if (selectedHistoryOrderState(transaction.order) == ORDER_STATE_FILLED)
if (request.type == ORDER_TYPE_BUY) {
if (!putOrder(ORDER_TYPE_SELL, g_price1, g_price2))
return;
} elseif (request.type == ORDER_TYPE_SELL) {
if (!putOrder(ORDER_TYPE_BUY_STOP, g_price1, g_price2))
return;
}
}
Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:
Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:
Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:
Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?
Ловим транзакцию TRADE_TRANSACTION_DEAL_ADD, если сделка по текущему символу и magic равен Original_EA_Magic (если задать его в ноль, то будут отлавливаться только сделки произошедшие от ручной установки отложенных ордеров или от ручной отсылки торговых приказов по-рынку), если тип сделки DEAL_ENTRY_IN (вход в рынок) то открываемся в противоположную сторону.
//+------------------------------------------------------------------+//| TradeTransaction function |//+------------------------------------------------------------------+voidOnTradeTransaction(constMqlTradeTransaction &trans,
constMqlTradeRequest &request,
constMqlTradeResult &result)
{
//---//--- get transaction type as enumeration value ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in historyif(type==TRADE_TRANSACTION_DEAL_ADD)
{
long deal_ticket =0;
long deal_order =0;
long deal_time =0;
long deal_time_msc =0;
long deal_type =-1;
long deal_entry =-1;
long deal_magic =0;
long deal_reason =-1;
long deal_position_id =0;
double deal_volume =0.0;
double deal_price =0.0;
double deal_commission =0.0;
double deal_swap =0.0;
double deal_profit =0.0;
string deal_symbol ="";
string deal_comment ="";
string deal_external_id ="";
if(HistoryDealSelect(trans.deal))
{
deal_ticket =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
deal_order =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
deal_time =HistoryDealGetInteger(trans.deal,DEAL_TIME);
deal_time_msc =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
deal_type =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
deal_entry =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
deal_magic =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
deal_reason =HistoryDealGetInteger(trans.deal,DEAL_REASON);
deal_position_id =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);
deal_volume =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
deal_price =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
deal_commission =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
deal_swap =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
deal_profit =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);
deal_symbol =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
deal_comment =HistoryDealGetString(trans.deal,DEAL_COMMENT);
deal_external_id =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
}
elsereturn;
if(deal_symbol==m_symbol.Name() && deal_magic==Original_EA_Magic)
if(deal_entry==DEAL_ENTRY_IN)
if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
{
if(deal_type==DEAL_TYPE_BUY) // buy
{
double sl=(InpStopLoss==0)?0.0:m_symbol.Bid()+ExtStopLoss;
double tp=(InpTakeProfit==0)?0.0:m_symbol.Bid()-ExtTakeProfit;
OpenSell(sl,tp);
}
if(deal_type==DEAL_TYPE_SELL) // sell
{
double sl=(InpStopLoss==0)?0.0:m_symbol.Ask()-ExtStopLoss;
double tp=(InpTakeProfit==0)?0.0:m_symbol.Ask()+ExtTakeProfit;
OpenBuy(sl,tp);
}
}
}
}
Ловим транзакцию TRADE_TRANSACTION_DEAL_ADD, если сделка по текущему символу и magic равен Original_EA_Magic (если задать его в ноль, то будут отлавливаться только сделки произошедшие от ручной установки отложенных ордеров или от ручной отсылки торговых приказов по-рынку), если тип сделки DEAL_ENTRY_IN (вход в рынок) то открываемся в противоположную сторону.
Здесь есть стрёмный момент, на первый взгляд:
//+------------------------------------------------------------------+//| TradeTransaction function |//+------------------------------------------------------------------+voidOnTradeTransaction(constMqlTradeTransaction &trans,
constMqlTradeRequest &request,
constMqlTradeResult &result)
{
//---//--- get transaction type as enumeration value ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in historyif(type==TRADE_TRANSACTION_DEAL_ADD)
{
long deal_ticket =0;
long deal_order =0;
long deal_time =0;
long deal_time_msc =0;
long deal_type =-1;
long deal_entry =-1;
long deal_magic =0;
long deal_reason =-1;
long deal_position_id =0;
double deal_volume =0.0;
double deal_price =0.0;
double deal_commission =0.0;
double deal_swap =0.0;
double deal_profit =0.0;
string deal_symbol ="";
string deal_comment ="";
string deal_external_id ="";
if(HistoryDealSelect(trans.deal))
{
deal_ticket =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
deal_order =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
deal_time =HistoryDealGetInteger(trans.deal,DEAL_TIME);
deal_time_msc =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
deal_type =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
deal_entry =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
deal_magic =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
deal_reason =HistoryDealGetInteger(trans.deal,DEAL_REASON);
deal_position_id =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);
deal_volume =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
deal_price =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
deal_commission =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
deal_swap =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
deal_profit =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);
deal_symbol =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
deal_comment =HistoryDealGetString(trans.deal,DEAL_COMMENT);
deal_external_id =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
}
elsereturn;
if(deal_symbol==m_symbol.Name() && deal_magic==Original_EA_Magic)
if(deal_entry==DEAL_ENTRY_IN)
if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
{
if(deal_type==DEAL_TYPE_BUY) // buy
{
double sl=(InpStopLoss==0)?0.0:m_symbol.Bid()+ExtStopLoss;
double tp=(InpTakeProfit==0)?0.0:m_symbol.Bid()-ExtTakeProfit;
OpenSell(sl,tp);
}
if(deal_type==DEAL_TYPE_SELL) // sell
{
double sl=(InpStopLoss==0)?0.0:m_symbol.Ask()-ExtStopLoss;
double tp=(InpTakeProfit==0)?0.0:m_symbol.Ask()+ExtTakeProfit;
OpenBuy(sl,tp);
}
}
}
}
Блок, где происходит инициализация дефолтными значениями свойств сделки.. Зачем? Нам же нужно получить значения совершённой транзакции.. Они придут какие и есть, на самом деле. К чему нам их обнуление. Ведь значения этих свойств зависят от сервера.. т.е. как он их отработает и вернёт терминалу.
Блок, где происходит инициализация дефолтными значениями свойств сделки.. Зачем? Нам же нужно получить значения совершённой транзакции.. Они придут какие и есть, на самом деле. К чему нам их обнуление. Ведь значения этих свойств зависят от сервера.. т.е. как он их отработает и вернёт терминалу.
Это привычка: всегда всё инициализировать. И только потом уже работать. Те кто работает надеясь на авось и не инициализируют - потом часто попадают на трудно вылавливаемые ошибки.
Для примера: Структура торговой транзакции - обратите внимание, что каждый вид транзакции заполняет только НЕКОТОРЫЕ поля, в остальных может быть что угодно.
Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:
Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:
Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?
Это привычка: всегда всё инициализировать. И только потом уже работать. Те кто работает надеясь на авось и не инициализируют - потом часто попадают на трудно вылавливаемые ошибки.
Для примера: Структура торговой транзакции - обратите внимание, что каждый вид транзакции заполняет только НЕКОТОРЫЕ поля, в остальных может быть что угодно.
Да. Но это нужно проверять на реале. Потому что никаких данных нет в справке. Там вообще как-то всё убого. Многие вещи сам проверяю. Просто, если понятие ордера и позиции у меня уже пару лет как сложилось, то со сделками только вот пару дней назад как столкнулся. Потому что раньше не нужно было.
Я обычно тоже всё инициализирую, но это локальные вещи, а когда приходят данные из вне, здесь вопрос.. Нужно на реале будет прогнать и поглядеть. Я сторонник минимализма. Если столкнулся с чем-то, тогда включаю в код. А так можно было бы весь спектр ошибок обрабатывать, например. Но это заколебёшся проверять всё. Я об этом тоже думал. Пришёл к выводу, что нужно самые очевидные моменты анализировать. На данный момент, всё и так чётко, кроме кк вот этот аспект со сделками ещё разрулить. Уже работает, но хочу всё это хозяйство запаковать в библиотеку и разгруппировать. Потому что такие пачки кода повторяющиеся это не есть желаемый вариант. Да и у меня в прошлом варианте, всё было правильно, кроме как я выбирал не сделку, а ордер:
if (transaction.type == TRADE_TRANSACTION_DEAL_ADD) {
if (request.action == TRADE_ACTION_DEAL)
if (!HistoryDealSelect(transaction.deal)) // Здесь был выбор ордера из истории
return;
if (selectedDealDirection(transaction.deal) == DEAL_ENTRY_IN) {
if (selectedDealType(transaction.deal) == DEAL_TYPE_BUY) {
if (!putOrder(ORDER_TYPE_SELL, g_price1, g_price2)) {
return;
}
} elseif (selectedDealType(transaction.deal) == DEAL_TYPE_SELL) {
if (!putOrder(ORDER_TYPE_BUY_STOP, g_price2, g_price1)) {
return;
}
}
}
}
Только вот всё-равно, здесь ещё 1 косяк есть очевидный. В наших обоих вариантах есть недочёт. Если ордер не открылся, то он пропариться и больше не откроется. Здесь придётся флаг заводить, на вскидку. А так всё остальное верно.
prostotrader, да я и не спорю даже. У меня такое иногда бывает. Всегда продумываю всё наперёд. Это не просто. Привычка к оптимизации кода.
А Вашу инфу ещё нужно переварить для начала. Но вижу, что enum'ы можно было взять дефолтные, по идее. А так логика в общем ясно. Хотя, параметр get_data не особо я ещё понял для чего.
prostotrader, да я и не спорю даже. У меня такое иногда бывает. Всегда продумываю всё наперёд. Это не просто. Привычка к оптимизации кода.
А Вашу инфу ещё нужно переварить для начала. Но вижу, что enum'ы можно было взять дефолтные, по идее. А так логика в общем ясно. Хотя, параметр get_data не особо я ещё понял для чего.
get_data == true - даёт возможность получить абсолютно всю информацию об ордере.
Если get_data == false, то только состояние ордера и его наличие.
Добавлено
В том - то и дело, что дефолтные enum'ы не дают полной картины состояния ордера, в тот момент, когда приходит сообщение в OnTradeTransaction()
Посмотрите, как получаются ORDER_NONE_PARTIAL_CANCELED и ORDER_NONE_PARTIAL, предварительно прочитав комментарий к enum'у
Для авторизации и пользования сайтом MQL5.com необходимо разрешить использование файлов Сookie.
Пожалуйста, включите в вашем браузере данную настройку, иначе вы не сможете авторизоваться.
Вы вошли в аккаунт. Двухфакторная аутентификация отключена. Настройте её заново и отсканируйте новый QR-код или продолжите с отключённой двухфакторной аутентификацией.
Если ордер исполнился частично, то его не будет в Истории до тех пор, пока он не исполнится полностью (но здесь делать FILLED-проверку делать бессмыленно), либо будет отменен (но здесь и STATE станет Cancelled, т.е. опять же FILLED-проверка не актуальна).
Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:
Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:
Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?
Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:
Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:
Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?
Пример: EES Hedger.
Ловим транзакцию TRADE_TRANSACTION_DEAL_ADD, если сделка по текущему символу и magic равен Original_EA_Magic (если задать его в ноль, то будут отлавливаться только сделки произошедшие от ручной установки отложенных ордеров или от ручной отсылки торговых приказов по-рынку), если тип сделки DEAL_ENTRY_IN (вход в рынок) то открываемся в противоположную сторону.
Пример: EES Hedger.
Ловим транзакцию TRADE_TRANSACTION_DEAL_ADD, если сделка по текущему символу и magic равен Original_EA_Magic (если задать его в ноль, то будут отлавливаться только сделки произошедшие от ручной установки отложенных ордеров или от ручной отсылки торговых приказов по-рынку), если тип сделки DEAL_ENTRY_IN (вход в рынок) то открываемся в противоположную сторону.
Здесь есть стрёмный момент, на первый взгляд:
Блок, где происходит инициализация дефолтными значениями свойств сделки.. Зачем? Нам же нужно получить значения совершённой транзакции.. Они придут какие и есть, на самом деле. К чему нам их обнуление. Ведь значения этих свойств зависят от сервера.. т.е. как он их отработает и вернёт терминалу.
Здесь есть стрёмный момент, на первый взгляд:
Блок, где происходит инициализация дефолтными значениями свойств сделки.. Зачем? Нам же нужно получить значения совершённой транзакции.. Они придут какие и есть, на самом деле. К чему нам их обнуление. Ведь значения этих свойств зависят от сервера.. т.е. как он их отработает и вернёт терминалу.
Это привычка: всегда всё инициализировать. И только потом уже работать. Те кто работает надеясь на авось и не инициализируют - потом часто попадают на трудно вылавливаемые ошибки.
Для примера: Структура торговой транзакции - обратите внимание, что каждый вид транзакции заполняет только НЕКОТОРЫЕ поля, в остальных может быть что угодно.
Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:
Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:
Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?
Здесь есть код на эту тему.
Это привычка: всегда всё инициализировать. И только потом уже работать. Те кто работает надеясь на авось и не инициализируют - потом часто попадают на трудно вылавливаемые ошибки.
Для примера: Структура торговой транзакции - обратите внимание, что каждый вид транзакции заполняет только НЕКОТОРЫЕ поля, в остальных может быть что угодно.
Да. Но это нужно проверять на реале. Потому что никаких данных нет в справке. Там вообще как-то всё убого. Многие вещи сам проверяю. Просто, если понятие ордера и позиции у меня уже пару лет как сложилось, то со сделками только вот пару дней назад как столкнулся. Потому что раньше не нужно было.
Я обычно тоже всё инициализирую, но это локальные вещи, а когда приходят данные из вне, здесь вопрос.. Нужно на реале будет прогнать и поглядеть. Я сторонник минимализма. Если столкнулся с чем-то, тогда включаю в код. А так можно было бы весь спектр ошибок обрабатывать, например. Но это заколебёшся проверять всё. Я об этом тоже думал. Пришёл к выводу, что нужно самые очевидные моменты анализировать. На данный момент, всё и так чётко, кроме кк вот этот аспект со сделками ещё разрулить. Уже работает, но хочу всё это хозяйство запаковать в библиотеку и разгруппировать. Потому что такие пачки кода повторяющиеся это не есть желаемый вариант. Да и у меня в прошлом варианте, всё было правильно, кроме как я выбирал не сделку, а ордер:
Только вот всё-равно, здесь ещё 1 косяк есть очевидный. В наших обоих вариантах есть недочёт. Если ордер не открылся, то он пропариться и больше не откроется. Здесь придётся флаг заводить, на вскидку. А так всё остальное верно.
Viktar Dzemikhau
Вы всё очень усложняете.
Всё очень просто
1. Ордер
Если Вы отправили ордер, то
а) Ордер исполнился полностью
б) Ордер исполнился частично
в) Ордер отклонен
г) Ордер поставлен в очередь
2. Позиция
а) Есть позиция
б) Нет позиции
Коль скоро ордер первичен в торговле, то после оправки ордера
необходимо знать, что с ним произошло (OnTradeTransaction()) в помощь
Если ордер исполнялся, то PositionSelect(symbol) даст всю необходимую инфориацию о позиции.
Вот функция, которая даст всю необходимую инфу об ордере.
prostotrader, да я и не спорю даже. У меня такое иногда бывает. Всегда продумываю всё наперёд. Это не просто. Привычка к оптимизации кода.
А Вашу инфу ещё нужно переварить для начала. Но вижу, что enum'ы можно было взять дефолтные, по идее. А так логика в общем ясно. Хотя, параметр get_data не особо я ещё понял для чего.prostotrader, да я и не спорю даже. У меня такое иногда бывает. Всегда продумываю всё наперёд. Это не просто. Привычка к оптимизации кода.
А Вашу инфу ещё нужно переварить для начала. Но вижу, что enum'ы можно было взять дефолтные, по идее. А так логика в общем ясно. Хотя, параметр get_data не особо я ещё понял для чего.get_data == true - даёт возможность получить абсолютно всю информацию об ордере.
Если get_data == false, то только состояние ордера и его наличие.
Добавлено
В том - то и дело, что дефолтные enum'ы не дают полной картины состояния ордера, в тот момент, когда приходит сообщение в OnTradeTransaction()
Посмотрите, как получаются ORDER_NONE_PARTIAL_CANCELED и ORDER_NONE_PARTIAL, предварительно прочитав комментарий к enum'у
Не так всё просто, как кажется на первый взгляд.