En général, nous avons besoin d'une sorte de RefreshPositions() synchrone de la part des développeurs qui renverra de manière fiable du serveur l'état des positions et des commandes.
Ensuite, celui qui en a besoin envoie des ordres de manière asynchrone, et celui qui n'en a pas besoin attend la réponse du serveur dans le corps du programme.
C'est ça le truc, ça l'a fait. Lorsque le script termine son exécution, une ou deux positions sont laissées en suspens (en fonction du nombre d'impressions insérées dans le code).
Code :
Résultat :
Pour compléter le tableau, ajoutez l'écouteur d'événement de transaction de l'article https://www.mql5.com/ru/article s/2513 au graphique adjacent
Pour voir l'ordre des événements
//+------------------------------------------------------------------+//| TradeTransactionListener.mq5 |//| Copyright 2016, MetaQuotes Software Corp. |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2016, MetaQuotes Software Corp."#property link"https://www.mql5.com"#property version"1.00"//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+intOnInit()
{
//---PrintFormat("LAST PING=%.f ms",
TerminalInfoInteger(TERMINAL_PING_LAST)/1000.);
//---return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
//---
}
//+------------------------------------------------------------------+//| TradeTransaction function |//+------------------------------------------------------------------+voidOnTradeTransaction(constMqlTradeTransaction &trans,
constMqlTradeRequest &request,
constMqlTradeResult &result)
{
//---staticint counter=0; // счетчик вызовов OnTradeTransaction()staticuint lasttime=0; // время последнего вызова OnTradeTransaction()//---uint time=GetTickCount();
//--- если последняя транзакция была больше 1 секунды назадif(time-lasttime>1000)
{
counter=0; // значит, это новая торговая операция и можно сбросить счетчикif(IS_DEBUG_MODE)
Print(" Новая торговая операция");
}
lasttime=time;
counter++;
Print(counter,". ",__FUNCTION__);
//--- результат выполнения торгового запросаulong lastOrderID =trans.order;
ENUM_ORDER_TYPE lastOrderType =trans.order_type;
ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- имя символа, по которому произошла транзакцияstring trans_symbol=trans.symbol;
//--- тип транзакцииENUM_TRADE_TRANSACTION_TYPE trans_type=trans.type;
switch(trans.type)
{
caseTRADE_TRANSACTION_POSITION: // изменение позиции
{
ulong pos_ID=trans.position;
PrintFormat("MqlTradeTransaction: Position #%d %s modified: SL=%.5f TP=%.5f",
pos_ID,trans_symbol,trans.price_sl,trans.price_tp);
}
break;
caseTRADE_TRANSACTION_REQUEST: // отправка торгового запросаPrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
break;
caseTRADE_TRANSACTION_DEAL_ADD: // добавление сделки
{
ulong lastDealID =trans.deal;
ENUM_DEAL_TYPE lastDealType =trans.deal_type;
double lastDealVolume=trans.volume;
//--- идентификатор сделки во внешней системе - тикет, присваиваемый Московской биржейstring Exchange_ticket="";
if(HistoryDealSelect(lastDealID))
Exchange_ticket=HistoryDealGetString(lastDealID,DEAL_EXTERNAL_ID);
if(Exchange_ticket!="")
Exchange_ticket=StringFormat("(MOEX deal=%s)",Exchange_ticket);
PrintFormat("MqlTradeTransaction: %s deal #%d %s %s %.2f lot %s",EnumToString(trans_type),
lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
}
break;
caseTRADE_TRANSACTION_HISTORY_ADD: // добавление ордера в историю
{
//--- идентификатор ордера во внешней системе - тикет, присваиваемый Московской биржейstring Exchange_ticket="";
if(lastOrderState==ORDER_STATE_FILLED)
{
if(HistoryOrderSelect(lastOrderID))
Exchange_ticket=HistoryOrderGetString(lastOrderID,ORDER_EXTERNAL_ID);
if(Exchange_ticket!="")
Exchange_ticket=StringFormat("(MOEX ticket=%s)",Exchange_ticket);
}
PrintFormat("MqlTradeTransaction: %s order #%d %s %s %s %s",EnumToString(trans_type),
lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
}
break;
default: // прочие транзакции
{
//--- идентификатор ордера во внешней системе - тикет, присваиваемый Московской биржейstring Exchange_ticket="";
if(lastOrderState==ORDER_STATE_PLACED)
{
if(OrderSelect(lastOrderID))
Exchange_ticket=OrderGetString(ORDER_EXTERNAL_ID);
if(Exchange_ticket!="")
Exchange_ticket=StringFormat("MOEX ticket=%s",Exchange_ticket);
}
PrintFormat("MqlTradeTransaction: %s order #%d %s %s %s",EnumToString(trans_type),
lastOrderID,EnumToString(lastOrderType),EnumToString(lastOrderState),Exchange_ticket);
}
break;
}
//--- тикет ордера ulong orderID_result=result.order;
string retcode_result=GetRetcodeID(result.retcode);
if(orderID_result!=0)
PrintFormat("MqlTradeResult: order #%d retcode=%s ",orderID_result,retcode_result);
//---
}
//+------------------------------------------------------------------+//| переводит числовые коды ответов в строковые мнемокоды |//+------------------------------------------------------------------+string GetRetcodeID(int retcode)
{
switch(retcode)
{
case10004: return("TRADE_RETCODE_REQUOTE"); break;
case10006: return("TRADE_RETCODE_REJECT"); break;
case10007: return("TRADE_RETCODE_CANCEL"); break;
case10008: return("TRADE_RETCODE_PLACED"); break;
case10009: return("TRADE_RETCODE_DONE"); break;
case10010: return("TRADE_RETCODE_DONE_PARTIAL"); break;
case10011: return("TRADE_RETCODE_ERROR"); break;
case10012: return("TRADE_RETCODE_TIMEOUT"); break;
case10013: return("TRADE_RETCODE_INVALID"); break;
case10014: return("TRADE_RETCODE_INVALID_VOLUME"); break;
case10015: return("TRADE_RETCODE_INVALID_PRICE"); break;
case10016: return("TRADE_RETCODE_INVALID_STOPS"); break;
case10017: return("TRADE_RETCODE_TRADE_DISABLED"); break;
case10018: return("TRADE_RETCODE_MARKET_CLOSED"); break;
case10019: return("TRADE_RETCODE_NO_MONEY"); break;
case10020: return("TRADE_RETCODE_PRICE_CHANGED"); break;
case10021: return("TRADE_RETCODE_PRICE_OFF"); break;
case10022: return("TRADE_RETCODE_INVALID_EXPIRATION"); break;
case10023: return("TRADE_RETCODE_ORDER_CHANGED"); break;
case10024: return("TRADE_RETCODE_TOO_MANY_REQUESTS"); break;
case10025: return("TRADE_RETCODE_NO_CHANGES"); break;
case10026: return("TRADE_RETCODE_SERVER_DISABLES_AT"); break;
case10027: return("TRADE_RETCODE_CLIENT_DISABLES_AT"); break;
case10028: return("TRADE_RETCODE_LOCKED"); break;
case10029: return("TRADE_RETCODE_FROZEN"); break;
case10030: return("TRADE_RETCODE_INVALID_FILL"); break;
case10031: return("TRADE_RETCODE_CONNECTION"); break;
case10032: return("TRADE_RETCODE_ONLY_REAL"); break;
case10033: return("TRADE_RETCODE_LIMIT_ORDERS"); break;
case10034: return("TRADE_RETCODE_LIMIT_VOLUME"); break;
case10035: return("TRADE_RETCODE_INVALID_ORDER"); break;
case10036: return("TRADE_RETCODE_POSITION_CLOSED"); break;
default:
return("TRADE_RETCODE_UNKNOWN="+IntegerToString(retcode));
break;
}
//---
}
//+------------------------------------------------------------------+
+ addrequest_id- ID de la demande à définir par le terminal lors de l' envoi de la commande.
printf("Перед открытием. PositionsTotal: %d, OrdersTotal: %d", PositionsTotal(), OrdersTotal());
Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.MqlTradeResult result;
Trade.Result(result);
PRINT(result.request_id);
...
Многие трейдеры на Московской бирже хотели бы автоматизировать свои торговые алгоритмы, но не знают с чего начать. Язык MQL5 предлагает не только огромный набор торговых функций, но и готовые классы, которые максимально облегчают первые шаги в алготрейдинге.
imho, OnTradeTransaction() ne garantit rien non plus, la séquence des événements n'est pas garantie, de même que la livraison des informations au terminal lui-même - je veux parler du cas des fournisseurs d'accès à Internet qui ne sont pas les plus fiables
il n'y a pas de mécanisme contrôlant OnTradeTransaction(), ou j'ai ou je n'ai pas reçu tous les événements dans une séquence stricte
PZY : J'aimerais qu'un programmeur MQ pas trop occupé trouve 2 heures pour écrire une fonction renvoyant une description textuelle du code d'erreur. Ce serait génial, et il y aurait moins d'écriture dans MQL5 et aucun besoin dans MT4 - laissez-les faire manuellement.
Trouvé dans la codobase et les derniers codes ajoutés
//+------------------------------------------------------------------+//| Возврат стрингового результата торговой операции по его коду |//+------------------------------------------------------------------+string ResultRetcodeDescription(int retcode)
{
string str;
//----switch(retcode)
{
caseTRADE_RETCODE_REQUOTE:
str="TRADE_RETCODE_REQUOTE(Реквота)";
break;
caseTRADE_RETCODE_REJECT:
str="TRADE_RETCODE_REJECT(Запрос отвергнут)";
break;
caseTRADE_RETCODE_CANCEL:
str="TRADE_RETCODE_CANCEL(Запрос отменен трейдером)";
break;
caseTRADE_RETCODE_PLACED:
str="TRADE_RETCODE_PLACED(Ордер размещен)";
break;
caseTRADE_RETCODE_DONE:
str="TRADE_RETCODE_DONE(Заявка выполнена)";
break;
caseTRADE_RETCODE_DONE_PARTIAL:
str="TRADE_RETCODE_DONE_PARTIAL(Заявка выполнена частично)";
break;
caseTRADE_RETCODE_ERROR:
str="TRADE_RETCODE_ERROR(Ошибка обработки запроса)";
break;
caseTRADE_RETCODE_TIMEOUT:
str="TRADE_RETCODE_TIMEOUT(Запрос отменен по истечению времени)";
break;
caseTRADE_RETCODE_INVALID:
str="TRADE_RETCODE_INVALID(Неправильный запрос)";
break;
caseTRADE_RETCODE_INVALID_VOLUME:
str="Неправильный объем в запросе";
break;
caseTRADE_RETCODE_INVALID_PRICE:
str="TRADE_RETCODE_INVALID_VOLUME(Неправильная цена в запросе)";
break;
caseTRADE_RETCODE_INVALID_STOPS:
str="TRADE_RETCODE_INVALID_STOPS(Неправильные стопы в запросе)";
break;
caseTRADE_RETCODE_TRADE_DISABLED:
str="TRADE_RETCODE_TRADE_DISABLED(Торговля запрещена)";
break;
caseTRADE_RETCODE_MARKET_CLOSED:
str="TRADE_RETCODE_MARKET_CLOSED(Рынок закрыт)";
break;
caseTRADE_RETCODE_NO_MONEY:
str="TRADE_RETCODE_NO_MONEY(Нет достаточных денежных средств для выполнения запроса)";
break;
caseTRADE_RETCODE_PRICE_CHANGED:
str="TRADE_RETCODE_PRICE_CHANGED(Цены изменились)";
break;
caseTRADE_RETCODE_PRICE_OFF:
str="TRADE_RETCODE_PRICE_OFF(Отсутствуют котировки для обработки запроса)";
break;
caseTRADE_RETCODE_INVALID_EXPIRATION:
str="TRADE_RETCODE_INVALID_EXPIRATION(Неверная дата истечения ордера в запросе)";
break;
caseTRADE_RETCODE_ORDER_CHANGED:
str="TRADE_RETCODE_ORDER_CHANGED(Состояние ордера изменилось)";
break;
caseTRADE_RETCODE_TOO_MANY_REQUESTS:
str="TRADE_RETCODE_TOO_MANY_REQUESTS(Слишком частые запросы)";
break;
caseTRADE_RETCODE_NO_CHANGES:
str="TRADE_RETCODE_NO_CHANGES(В запросе нет изменений)";
break;
caseTRADE_RETCODE_SERVER_DISABLES_AT:
str="TRADE_RETCODE_SERVER_DISABLES_AT(Автотрейдинг запрещен сервером)";
break;
caseTRADE_RETCODE_CLIENT_DISABLES_AT:
str="TRADE_RETCODE_CLIENT_DISABLES_AT(Автотрейдинг запрещен клиентским терминалом)";
break;
caseTRADE_RETCODE_LOCKED:
str="TRADE_RETCODE_LOCKED(Запрос заблокирован для обработки)";
break;
caseTRADE_RETCODE_FROZEN:
str="TRADE_RETCODE_FROZEN(Ордер или позиция заморожены)";
break;
caseTRADE_RETCODE_INVALID_FILL:
str="TRADE_RETCODE_INVALID_FILL(Указан неподдерживаемый тип исполнения ордера по остатку)";
break;
caseTRADE_RETCODE_CONNECTION:
str="TRADE_RETCODE_CONNECTION(Нет соединения с торговым сервером)";
break;
caseTRADE_RETCODE_ONLY_REAL:
str="TRADE_RETCODE_ONLY_REAL(Операция разрешена только для реальных счетов)";
break;
caseTRADE_RETCODE_LIMIT_ORDERS:
str="TRADE_RETCODE_LIMIT_ORDERS(Достигнут лимит на количество отложенных ордеров)";
break;
caseTRADE_RETCODE_LIMIT_VOLUME:
str="TRADE_RETCODE_LIMIT_VOLUME(Достигнут лимит на объем ордеров и позиций для данного символа)";
break;
caseTRADE_RETCODE_INVALID_ORDER:
str="TRADE_RETCODE_INVALID_ORDER:Неверный или запрещённый тип ордера)";
break;
caseTRADE_RETCODE_POSITION_CLOSED:
str="TRADE_RETCODE_POSITION_CLOSED:Позиция с указанным POSITION_IDENTIFIER уже закрыта)";
break;
caseTRADE_RETCODE_INVALID_CLOSE_VOLUME:
str="TRADE_RETCODE_INVALID_CLOSE_VOLUME(Закрываемый объем превышает текущий объем позиции)";
break;
caseTRADE_RETCODE_CLOSE_ORDER_EXIST:
str="TRADE_RETCODE_CLOSE_ORDER_EXIST(Для указанной позиции уже есть ордер на закрытие)";
break;
caseTRADE_RETCODE_LIMIT_POSITIONS:
str="TRADE_RETCODE_LIMIT_POSITIONS(Количество открытых позиций, которое можно одновременно иметь на счете, может быть ограничено настройками сервера)";
break;
caseTRADE_RETCODE_REJECT_CANCEL:
str="TRADE_RETCODE_REJECT_CANCEL(Запрос на активацию отложенного ордера отклонен, а сам ордер отменен)";
break;
caseTRADE_RETCODE_LONG_ONLY:
str="TRADE_RETCODE_LONG_ONLY(Запрос отклонен, так как на символе установлено правило \"Разрешены только длинные позиции\")";
break;
caseTRADE_RETCODE_SHORT_ONLY:
str="TRADE_RETCODE_SHORT_ONLY(Запрос отклонен, так как на символе установлено правило \"Разрешены только короткие позиции\")";
break;
caseTRADE_RETCODE_CLOSE_ONLY:
str="TRADE_RETCODE_CLOSE_ONLY(Запрос отклонен, так как на символе установлено правило \"Разрешено только закрывать существующие позиции\")";
break;
caseTRADE_RETCODE_FIFO_CLOSE:
str="TRADE_RETCODE_FIFO_CLOSE(Запрос отклонен, так как для торгового счета установлено правило \"Разрешено закрывать существующие позиции только по правилу FIFO\")";
break;
case TRADE_RETCODE_HEDGE_PROHIBITED:
str="TRADE_RETCODE_HEDGE_PROHIBITED(Запрос отклонен, так как для торгового счета установлено правило \"Запрещено открывать встречные позиции по одному символу\")";
break;
//case : str=""; break;//case : str=""; break;//case : str=""; break;//case : str=""; break;default:
str="Неизвестный результат";
}
//----return(str);
}
Les gens ont donc demandé l'accès à la boîte noire - ils l'ont obtenu. Maintenant, vous devez faire la synchronisation vous-même. Demandé ? Ils l'ont fait. L'ont-ils fait ? Ils l'ont fait. C'est bon ? Ils ont dit que ce serait bien. Une fois qu'il a été donné, il est devenu mauvais.
J'ai fait le même code en une demi-heure à partir de l'aide ME - j'ai ouvert les codes d'erreur, j'ai mis la souris en surbrillance, j'ai fait Ctrl+C , j'ai créé une page Excel vide, j'ai fait Ctrl+V et j'ai ajouté des colonnes avec case : et des guillemets inversés.
puis Ctrl+C+Ctrl+V dans ME
ok, apparemment "endurer des difficultés" n'est pas juste un article du manuel militaire, c'est plus comme notre mentalité
2. personne n'a dit que le prix serait l'intégrité des données, ce qui est bien plus important.
Au lieu de la démagogie du "blâmez-vous", pouvez-vous proposer une solution sans béquilles ?
Je vais probablement le proposer. Mais beaucoup plus tard. En raison de circonstances subjectives. Malheureusement. En attendant, considérez-vous comme un démagogue. Pas interdit.
J'ai fait le même code en une demi-heure à partir de l'aide ME - j'ai ouvert les codes d'erreur, j'ai mis la souris en surbrillance, j'ai fait Ctrl+C , j'ai créé une page Excel vide, j'ai fait Ctrl+V et j'ai ajouté des colonnes avec la casse : et des guillemets inversés.
puis Ctrl+C+Ctrl+V dans ME
ok, apparemment "endurer des difficultés" n'est pas juste un article du manuel militaire, c'est plus notre mentalité
Si vous n'avez pas de compte, veuillez vous inscrire
Autorisez l'utilisation de cookies pour vous connecter au site Web MQL5.com.
Veuillez activer les paramètres nécessaires dans votre navigateur, sinon vous ne pourrez pas vous connecter.
Vous êtes connecté. L'authentification à deux facteurs a été désactivée. Configurez-la à nouveau et scannez un nouveau code QR, ou continuez avec l'authentification à deux facteurs désactivée.
il semble que cela fonctionne comme ça :
mais c'est très lent, et ce n'est pas une très bonne solution.
il semble que ça fonctionne comme ça :
mais c'est très lent, et ce n'est pas une très bonne solution.
Vous avez fait presque cette option.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
La Grande et l'Horrible MT4 Forever (ou comment établir une stratégie de migration)
fxsaber, 2021.05.09 00:36
Vous pouvez utiliser cette condition :
En général, nous avons besoin d'une sorte de RefreshPositions() synchrone de la part des développeurs qui renverra de manière fiable du serveur l'état des positions et des commandes.
Ensuite, celui qui en a besoin envoie des ordres de manière asynchrone, et celui qui n'en a pas besoin attend la réponse du serveur dans le corps du programme.
C'est ça le truc, ça l'a fait. Lorsque le script termine son exécution, une ou deux positions sont laissées en suspens (en fonction du nombre d'impressions insérées dans le code).
Code :
Résultat :
Pour compléter le tableau, ajoutez l'écouteur d'événement de transaction de l'article https://www.mql5.com/ru/article s/2513 au graphique adjacent
Pour voir l'ordre des événements
+ addrequest_id - ID de la demande à définir par le terminal lors de l' envoi de la commande.
Combien de commandes y sont réellement envoyées
imho, OnTradeTransaction() ne garantit rien non plus, la séquence des événements n'est pas garantie, de même que la livraison des informations au terminal lui-même - je veux parler du cas des fournisseurs d'accès à Internet qui ne sont pas les plus fiables
il n'y a pas de mécanisme contrôlant OnTradeTransaction(), ou j'ai ou je n'ai pas reçu tous les événements dans une séquence stricte
PZY : J'aimerais qu'un programmeur MQ pas trop occupé trouve 2 heures pour écrire une fonction renvoyant une description textuelle du code d'erreur. Ce serait génial, et il y aurait moins d'écriture dans MQL5 et aucun besoin dans MT4 - laissez-les faire manuellement.
;)
Trouvé dans la codobase et les derniers codes ajoutés
Les gens ont donc demandé l'accès à la boîte noire - ils l'ont obtenu.
Maintenant, vous devez faire la synchronisation vous-même. Demandé ? Ils l'ont fait. L'ont-ils fait ? Ils l'ont fait. C'est bon ? Ils ont dit que ce serait bien. Une fois qu'il a été donné, il est devenu mauvais.
1. Je ne l'ai pas demandé.
2. personne n'a dit que le prix serait l'intégrité des données, ce qui est beaucoup plus important.
au lieu d'une démagogie nue comme "notre faute", pouvez-vous proposer une solution sans béquilles ?
Trouvé dans kodobase et ajouté les derniers codes
J'ai fait le même code en une demi-heure à partir de l'aide ME - j'ai ouvert les codes d'erreur, j'ai mis la souris en surbrillance, j'ai fait Ctrl+C , j'ai créé une page Excel vide, j'ai fait Ctrl+V et j'ai ajouté des colonnes avec case : et des guillemets inversés.
puis Ctrl+C+Ctrl+V dans ME
ok, apparemment "endurer des difficultés" n'est pas juste un article du manuel militaire, c'est plus comme notre mentalité
1. Je ne l'ai pas demandé.
2. personne n'a dit que le prix serait l'intégrité des données, ce qui est bien plus important.
Au lieu de la démagogie du "blâmez-vous", pouvez-vous proposer une solution sans béquilles ?
J'ai fait le même code en une demi-heure à partir de l'aide ME - j'ai ouvert les codes d'erreur, j'ai mis la souris en surbrillance, j'ai fait Ctrl+C , j'ai créé une page Excel vide, j'ai fait Ctrl+V et j'ai ajouté des colonnes avec la casse : et des guillemets inversés.
puis Ctrl+C+Ctrl+V dans ME
ok, apparemment "endurer des difficultés" n'est pas juste un article du manuel militaire, c'est plus notre mentalité