Generell benötigen wir von den Entwicklern eine Art synchrones RefreshPositions(), das zuverlässig den Stand der Positionen + Aufträge vom Server zurückliefert
Dann sendet derjenige, der es braucht, die Aufträge asynchron, und derjenige, der es nicht braucht, wartet im Hauptteil des Programms auf die Antwort des Servers.
Das ist es ja, das war es. Wenn das Skript zu Ende ist, bleiben ein oder zwei Positionen hängen (je nachdem, wie viele Drucke in den Code eingefügt wurden).
Code:
Ergebnis:
Um das Bild zu vervollständigen, fügen Sie den Handelsereignis-Listener aus dem Artikel https://www.mql5.com/ru/articles/2513 in das nebenstehende Diagramm ein
Um die Reihenfolge der Ereignisse zu sehen
//+------------------------------------------------------------------+//| 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 output- Request ID, die vom Terminal beim Absenden der Bestellung gesetzt wird
printf("Перед открытием. PositionsTotal: %d, OrdersTotal: %d", PositionsTotal(), OrdersTotal());
Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.MqlTradeResult result;
Trade.Result(result);
PRINT(result.request_id);
...
Wie viele Aufträge werden wirklich dorthin geschickt?
Многие трейдеры на Московской бирже хотели бы автоматизировать свои торговые алгоритмы, но не знают с чего начать. Язык MQL5 предлагает не только огромный набор торговых функций, но и готовые классы, которые максимально облегчают первые шаги в алготрейдинге.
Imho garantiert OnTradeTransaction() auch nichts, die Abfolge der Ereignisse ist nicht garantiert, ebenso wenig wie die Zustellung der Informationen an das Terminal selbst - ich meine den Fall mit nicht den zuverlässigsten Internet-Providern
es gibt keinen Mechanismus zur Steuerung von OnTradeTransaction(), oder ich habe alle Ereignisse in strikter Reihenfolge erhalten oder nicht
PZY: Ich wünschte, ein nicht allzu beschäftigter MQ-Programmierer könnte 2 Stunden Zeit finden, um eine Funktion zu schreiben, die eine Textbeschreibung des Fehlercodes zurückgibt. Das wäre großartig, und es gäbe weniger Schreibarbeit in MQL5 und keinen Bedarf in MT4 - lassen Sie sie es manuell tun
In der Codobase gefunden und die neuesten Codes hinzugefügt
//+------------------------------------------------------------------+//| Возврат стрингового результата торговой операции по его коду |//+------------------------------------------------------------------+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);
}
Also verlangten die Leute Zugang zur Blackbox - und sie bekamen ihn. Jetzt müssen Sie die Synchronisierung selbst vornehmen. Gefragt? Das taten sie. Haben sie? Das taten sie. Ist es gut? Sie sagten, es würde gut sein. Sobald sie gegeben war, wurde sie schlecht.
1. ich habe nicht darum gebeten.
2. Niemand hat gesagt, dass der Preis die Datenintegrität sein würde, die viel wichtiger ist.
Können Sie statt nackter Demagogie wie "es ist unsere Schuld" eine Lösung ohne Krücken anbieten?
In kodobase gefunden und die neuesten Codes hinzugefügt
Ich habe den gleichen Code in einer halben Stunde mit der ME-Hilfe erstellt - ich habe die Fehlercodes geöffnet, die Maus markiert, Strg+C gedrückt, eine leere Excel-Seite erstellt, Strg+V gedrückt und Spalten mit Groß- und Kleinschreibung und Anführungszeichen hinzugefügt
dann Strg+C+Strg+V in ME
Okay, offenbar ist "Härte ertragen" nicht nur ein Artikel aus dem Militärhandbuch, sondern eher unsere Mentalität
2. Niemand hat gesagt, dass der Preis die Datenintegrität sein würde, die viel wichtiger ist.
Können Sie anstelle der "Selbst schuld"-Demagogie eine Lösung ohne Krücken vorschlagen?
Das werde ich wahrscheinlich tun. Aber viel später. Aufgrund subjektiver Umstände. Leider. In der Zwischenzeit können Sie sich als Demagoge betrachten. Nicht verboten.
Ich habe den gleichen Code in einer halben Stunde mit der ME-Hilfe erstellt - ich habe die Fehlercodes geöffnet, die Maus markiert, Strg+C gedrückt, eine leere Excel-Seite erstellt, Strg+V gedrückt und Spalten mit Groß- und Kleinschreibung und Anführungszeichen hinzugefügt.
dann Strg+C+Strg+V in ME
Okay, offenbar ist "Härte ertragen" nicht nur ein Artikel aus dem Militärhandbuch, sondern eher unsere Mentalität
Auf Russisch? Auf Spanisch? Englisch? Welcher ist es?
Es scheint folgendermaßen zu funktionieren:
aber es ist sehr langsam und keine besonders gute Lösung.
Es scheint folgendermaßen zu funktionieren:
aber es ist sehr langsam und keine besonders gute Lösung.
Sie haben fast diese Möglichkeit geschaffen.
Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien
The Great and Horrible MT4 Forever (oder wie man die Migration strategisch plant)
fxsaber, 2021.05.09 00:36
Sie können diese Bedingung verwenden:
Generell benötigen wir von den Entwicklern eine Art synchrones RefreshPositions(), das zuverlässig den Stand der Positionen + Aufträge vom Server zurückliefert
Dann sendet derjenige, der es braucht, die Aufträge asynchron, und derjenige, der es nicht braucht, wartet im Hauptteil des Programms auf die Antwort des Servers.
Das ist es ja, das war es. Wenn das Skript zu Ende ist, bleiben ein oder zwei Positionen hängen (je nachdem, wie viele Drucke in den Code eingefügt wurden).
Code:
Ergebnis:
Um das Bild zu vervollständigen, fügen Sie den Handelsereignis-Listener aus dem Artikel https://www.mql5.com/ru/articles/2513 in das nebenstehende Diagramm ein
Um die Reihenfolge der Ereignisse zu sehen
+ addrequest_id output - Request ID, die vom Terminal beim Absenden der Bestellung gesetzt wird
Wie viele Aufträge werden wirklich dorthin geschickt?
Imho garantiert OnTradeTransaction() auch nichts, die Abfolge der Ereignisse ist nicht garantiert, ebenso wenig wie die Zustellung der Informationen an das Terminal selbst - ich meine den Fall mit nicht den zuverlässigsten Internet-Providern
es gibt keinen Mechanismus zur Steuerung von OnTradeTransaction(), oder ich habe alle Ereignisse in strikter Reihenfolge erhalten oder nicht
PZY: Ich wünschte, ein nicht allzu beschäftigter MQ-Programmierer könnte 2 Stunden Zeit finden, um eine Funktion zu schreiben, die eine Textbeschreibung des Fehlercodes zurückgibt. Das wäre großartig, und es gäbe weniger Schreibarbeit in MQL5 und keinen Bedarf in MT4 - lassen Sie sie es manuell tun
;)
In der Codobase gefunden und die neuesten Codes hinzugefügt
Also verlangten die Leute Zugang zur Blackbox - und sie bekamen ihn.
Jetzt müssen Sie die Synchronisierung selbst vornehmen. Gefragt? Das taten sie. Haben sie? Das taten sie. Ist es gut? Sie sagten, es würde gut sein. Sobald sie gegeben war, wurde sie schlecht.
1. ich habe nicht darum gebeten.
2. Niemand hat gesagt, dass der Preis die Datenintegrität sein würde, die viel wichtiger ist.
Können Sie statt nackter Demagogie wie "es ist unsere Schuld" eine Lösung ohne Krücken anbieten?
In kodobase gefunden und die neuesten Codes hinzugefügt
Ich habe den gleichen Code in einer halben Stunde mit der ME-Hilfe erstellt - ich habe die Fehlercodes geöffnet, die Maus markiert, Strg+C gedrückt, eine leere Excel-Seite erstellt, Strg+V gedrückt und Spalten mit Groß- und Kleinschreibung und Anführungszeichen hinzugefügt
dann Strg+C+Strg+V in ME
Okay, offenbar ist "Härte ertragen" nicht nur ein Artikel aus dem Militärhandbuch, sondern eher unsere Mentalität
1. ich habe nicht darum gebeten.
2. Niemand hat gesagt, dass der Preis die Datenintegrität sein würde, die viel wichtiger ist.
Können Sie anstelle der "Selbst schuld"-Demagogie eine Lösung ohne Krücken vorschlagen?
Ich habe den gleichen Code in einer halben Stunde mit der ME-Hilfe erstellt - ich habe die Fehlercodes geöffnet, die Maus markiert, Strg+C gedrückt, eine leere Excel-Seite erstellt, Strg+V gedrückt und Spalten mit Groß- und Kleinschreibung und Anführungszeichen hinzugefügt.
dann Strg+C+Strg+V in ME
Okay, offenbar ist "Härte ertragen" nicht nur ein Artikel aus dem Militärhandbuch, sondern eher unsere Mentalität