Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 70

 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Wie erkennt man einen Kartenersatz?

fxsaber, 2018.02.08 12:39

void OnTick()
{  
  const long Chart = ChartID();
  string PrevSymbol = _Symbol;
  ENUM_TIMEFRAMES PrevTF = _Period;
    
  while (!IsStopped())
  {
    if ((PrevSymbol != ChartSymbol(Chart)) || (PrevTF != ChartPeriod(Chart))) // ноль указывать НЕЛЬЗЯ!
    {      
      PrevSymbol = ChartSymbol(Chart);
      PrevTF = ChartPeriod(Chart);
      
      Alert(PrevSymbol + " " + EnumToString(PrevTF));      
    }
    
    Sleep(0);
  }
}

ChartID-Eingabeparameter Null in einigen Funktionen führt nicht zur Neuberechnung der Werte. Wenn Sie die aktuellen Daten des aktuellen Diagramms wünschen, müssen Sie die vollständige ID verwenden.

 

Forum zum Thema Handel, automatisierte Handelssysteme und Strategietests

POSITIONS_TICKET != POSITIONS_IDENTIFIKATOR

fxsaber, 2018.02.12 20:14

Schlussfolgerungen

Wenn wir davon ausgehen, dass dies ein normales MT5-Verhalten ist und keine Besonderheit des Broker-Hacks, dann

  • ORDER_STATE_PARTIAL kommt in historischen Aufträgen nicht vor.
  • Ausgeführte Aufträge haben immer den Status ORDER_STATE_FILLED.
  • Wenn ein Auftrag teilweise ausgeführt wird, wird ein entsprechender neuer Marktauftrag vom Handelsserver angelegt (ORDER_REASON_CLIENT - auch wenn der ursprüngliche Auftrag automatisch erteilt wurde (EXPERT)).
  • Der alte Live-Auftrag (das Ticket wird nicht geändert) bleibt mit einem reduzierten Volumen (ORDER_VOLUME_CURRENT) anhängig.
  • Der alte Live-Auftrag hat in diesem Fall den Status ORDER_STATE_PARTIAL. Eigentlich ist dieses Kennzeichen das Ergebnis des Vergleichs von ORDER_VOLUME_CURRENT und ORDER_VOLUME_INITIAL.
  • Alle offenen Positionen erhalten eine ID == OrderTicket. Dabei ist OrderTicket das vom Handelsserver generierte Ticket.
  • Ein Geschäft hat immer genau einen historischen Auftrag, und sein Status ist ORDER_STATE_FILLED.
  • Jeder ausgeführte historische Auftrag hat genau einen Abschluss.
  • Das ORDER_VOLUME_INITIAL eines ausgeführten Auftrags ist gleich dem Volumen, für das er ausgeführt wurde. D.h. selbst der ursprüngliche Auftrag, der storniert wurde, hat ein ORDER_VOLUME_INITITAL, das dem Volumen des von ihm ausgelösten Handels entspricht.
  • Der Zeitpunkt des ursprünglichen Auftrags (der teilweise ausgeführt wurde) ändert sich nicht und ist nicht gleich dem Zeitpunkt seines Abschlusses.
  • Die Historientabelle ist nach Auftragszeit (ORDER_TIME_SETUP), nicht aber nach Geschäftszeit sortiert. Wenn wir also HistorySelect from DEAL_TIME ausführen, können wir die entsprechende Bestellung nicht in die History-Tabelle übernehmen.
  • HistorySelectByPosition liefert immer die erforderliche Menge an Geschäften/Aufträgen.
  • Sie können die Slippage für jeden Handel berechnen.

Schwachstellen

  • Es fehlen die Angaben ORDER_REASON_PARTIAL, DEAL_REASON_PARTIAL und POSITION_REASON_PARTIAL. Diese Flags müssen in den jeweiligen Auflistungen unmittelbar nach REASON_EXPERT gesetzt werden.
  • Entsprechende Marktaufträge können bei der teilweisen Ausführung von Limit-Aufträgen naturgemäß einen negativen Slippage aufweisen. Dies scheint nur ein Fehler in der Auftragsart zu sein, und es gibt wirklich keinen Marktauftrag - er wird nur innerhalb von MT5 erstellt und geht nicht nach außen.

ZZY Vollständig bestätigte Hypothese.

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

POSITIONS_TICKET != POSITIONS_IDENTIFIKATOR

Pavel Kolchin, 2018.02.12 13:31

(nicht sicher, schwer zu überprüfen, ähnlich wie bei der teilweisen Schließung von Positionen)

Das Ganze funktioniert folgendermaßen:

1) Pending Order teilweise ausgelöst - Position mit Position_ID = Order_Ticket1 wird eröffnet

2) der verbleibende Auftrag wird in einen neuen Auftrag Order_Ticket2 umgewandelt und wartet auf seine Ausführung; der neue Auftrag_Ticket2 != Order_Ticket1, da es nicht 2 Aufträge mit dem gleichen Order_Ticket in der Historie geben kann

3) der verbleibende Auftrag wurde ausgeführt - eine Position mit Position_ID = Order_Ticket2 wird eröffnet

es gibt zwei Aufträge in der Geschichte, zwei Positionen im Terminal, alles entspricht

 

Forum zum Thema Handel, automatische Handelssysteme und Testen von Handelsstrategien

Diskussion über "LifeHack für Trader: ForEach auf Defines mischen (#define)"

fxsaber, 2018.02.14 10:54

Leistungsmessung

#define  BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

double GetAsk()
{
  static MqlTick tick = {0};
  
  return(SymbolInfoTick(Symbol(),tick) ? tick.ask : 0);
}

#define  AMOUNT 1 e6

void OnStart()
{
  double Sum = 0;
  
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += GetAsk())
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += SymbolInfoDouble(_Symbol, SYMBOL_ASK))
  
  Print(Sum);
}


Ergebnis

Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 78952
Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 162606

Ich lag völlig falsch! SymbolInfoDouble ist doppelt so langsam wie SymbolInfoTick.

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Diskussion über "LifeHack für Trader: ForEach auf Defines mischen (#define)"

fxsaber, 2018.02.14 11:58

Inkompetent. Ergebnis im Tester.

2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 87424
2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 83410

Wenn Leistung erforderlich ist (Optimierer), ist es besser , SymbolInfoDouble zu verwenden. In der realen Welt macht das keinen Unterschied.


ZZY Function Geschwindigkeitsmessung sollte in einer Umgebung gemessen werden, in der Leistung wichtig ist - Tester.

 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Wanzen, Wanzen, Fragen

fxsaber, 2018.02.12 23:10

Eröffnung einer BUY-Position von Hand auf zwei Trading-Demo-Servern


RoboForex-MetaTrader 5

2018.02.13 00:02:08.424 '8520459': market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': accepted market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': deal #90389019 buy 1.00 GBPUSD at 1.38387 done (based on order #107426544)
2018.02.13 00:02:10.101 '8520459': order #107426544 buy 1.00 / 1.00 GBPUSD at 1.38387 done in 1683.949 ms


FXOpen-MT5

2018.02.13 00:00:25.780 '18000903': market buy 1.00 GBPUSD
2018.02.13 00:00:25.912 '18000903': accepted market buy 1.00 GBPUSD
2018.02.13 00:00:25.922 '18000903': market buy 1.00 GBPUSD placed for execution
2018.02.13 00:00:25.942 '18000903': order #896454 buy 1.00 / 1.00 GBPUSD at market done in 154.252 ms
2018.02.13 00:00:25.942 '18000903': deal #80559 buy 1.00 GBPUSD at 1.38387 done (based on order #896454)

Die gleichfarbigen Linien bedeuten das Gleiche. Es ist jedoch klar ersichtlich, dass sie in unterschiedlicher Reihenfolge angeordnet sind. Im Robo kommt die Nachricht über die Auftragsausführung, nachdem der Handel ausgeführt wurde. Im Offenen kommt es VOR! Aus diesem Grund liefert OrderSend zwar Glück, aber noch keine Transaktion. D.h. wir erhalten unsynchronisierte OrderSend mit der Historie

Code für FXOpen-MT5

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  MqlTradeRequest Request = {0};
  
  Request.action = TRADE_ACTION_DEAL;
  Request.symbol = _Symbol;
  Request.volume = 1;
  Request.type_filling = ORDER_FILLING_IOC;
  
  MqlTradeResult Result;
  
  PRINT(OrderSend(Request, Result));
  PRINT(Result.deal);
}


Ergebnis

OrderSend(Request,Result) = true
Result.deal = 0


Für diese Situation gibt es folgende Erklärung

Forum zum Thema Handel, automatisierte Handelssysteme und Strategietests

Wanzen, Wanzen, Fragen

Rashid Umarov, 2018.02.15 06:25

Wenn ein Auftrag an ein externes Handelssystem gesendet wird, wartet der MetaTrader 5 Handelsserver nicht auf eine Antwort von diesem und gibt das Ergebnis der Anfrage sofort als "Auftrag erteilt" zurück. Aus diesem Grund wird OrderSend immer deal=0 zurückgeben, da es noch keine Informationen über den ausgeführten Handel gibt. Fangen Sie es in OnTrade oder OnTradeTransaction ab.

Ein Beispiel für einen Handels-Ereignis-Listener finden Sie im Artikel Where to start when creating a trading robot for MOEX - TradeTransactionListener.mq5

OrderSend - sendet einen Auftrag zur Ausführung eines Marktgeschäfts.Der Auftrag wird erteilt- wir müssen Result.order lesen. Aber niemand wartet auf das Geschäft oder die Geschäfte - es kann viele davon geben und die Gesamtdauer ihrer Ausführung ist nicht festgelegt.

Dies hängt von der spezifischen Implementierung der Ausgabe auf der Seite des Brokers ab. Im allgemeinen Fall ist sie nicht definiert.

Ich empfehle Ihnen daher, das Demokonto auf FXOpen-MT5 als Test für Ihren Code zu verwenden, da es sich von anderen Demos abhebt.


Zum Beispiel schlage ich vor, zu versuchen, ein Skript in MQL5 mit solchen Handelslogik (MQL4-Stil nur für schnelle Sinn Anzeige) zu schreiben

void OnStart()
{
  OrderCloseBy(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0), OrderSend(_Symbol, OP_SELL, 1, Bid, 0, 0, 0));
}

Das ist gar nicht so einfach. Ich empfehle auch den erwähnten Demoserver, um an der Teilausführung zu arbeiten.

 
fxsaber:
Ich habe einen Beitrag gelöscht, der eine Erklärung für einen der häufigsten Fehler auf MT5 enthielt.
Sie ist nicht unter den gelöschten. Das ist merkwürdig. Können Sie es noch einmal posten?
 
fxsaber:

Der Posten war groß. Ich habe nicht erwartet, dass ich gelöscht werde. Ich würde gerne den Grund für die Entfernung erfahren. Denn es ist masochistisch, wieder gelöscht zu werden.

Ich sage Ihnen, es ist nicht unter den gelöschten. Vielleicht gab es eine Störung?
 

Forum zum Thema Handel, automatische Handelssysteme und Testen von Handelsstrategien

Organisieren einer Auftragsschleife

fxsaber, 2018.02.16 09:40

Im MT5 funktionieren die Dinge überhaupt nicht gut. Beispiel für das Problem

// Пример неправильного считывания торгового окружения на каждом тике
// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.

#include <Trade/Trade.mqh>

// Возвращает количество позиций по символу
int GetAmountPositions( const string Symb )
{
  int Res = 0;
  
  // Этот MQL5-код с ошибкой
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if (PositionGetSymbol(i) == Symb)
      Res++;

/*
  // В MT4 такой код выполняется без ошибки
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
      Res++;
*/      
  return(Res);
}

// Пример OnTick
void ExampleOnTick()
{
  static CTrade Trade;
  
  // Если нет позиции, открываем
  if (!GetAmountPositions(_Symbol))
    Trade.Buy(1);    
}

// Эмуляция прихода двух Tick-событий
void OnStart()
{
  ExampleOnTick(); 
  
  Sleep(10); // Между двумя тиками ~10 мс.
  
  ExampleOnTick();
}

Was glauben Sie, was passiert, wenn Sie dieses Skript auf ein Symbol ohne Positionen anwenden?

Die richtige Antwort lautet, dass eine oder zwei Stellen geschaffen werden.

Der Grund dafür ist, dass dies geschieht. Nach dem ersten OrderSend erscheint ein Marktauftrag, und wenn ein neuer Tick vor dem Zeitpunkt seiner Ausführung kommt, gibt es noch keine Position und der zweite OrderSend wird ausgeführt.

Aus diesem Grundfunktioniert ein scheinbar normales MT5-Musternicht richtig, und als Folge davon funktionieren die meisten MT5 Expert Advisors in Codobase nicht mehr. Gleichzeitig wird das nahezu identische MT4-Template weiterhin problemlos funktionieren.

Die scheinbar gute Idee von PositionsTotal wird etwas überschattet von der Notwendigkeit, in MT5 auch OrdersTotal für Marktaufträge zu analysieren.

Seien Sie vorsichtig!

 
fxsaber:

Aus diesem Grund wird ein scheinbar normales MT5-Musternicht richtig funktionieren, und infolgedessen werden die meisten MT5-EAs in der kodobase.

Als Beweis für diese Aussage können wir fast jeden Expert Advisor in der MT5 kodobase nehmen. Lassen Sie uns nicht irgendetwas auswählen, sondern nehmen Sie den neuesten Expert Advisor, den es derzeit gibt. Es ist gut, dass es von einem Autor geschrieben wurde, der viel Erfahrung mit MT5-Publishing in QB hat.

Der Quellcode enthält die folgenden Strings (meine Kommentare sind hervorgehoben)

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//....
   int total=0; // для расчета количества открытых советником позиций
//....
//--- main cycle
   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            total++; // расчет количества открытых позиций
//....
   if(total==0) // Если нет открытых советником позиций
     {
      if(!RefreshRates())
        {
         PrevBars=iTime(1);
         return;
        }
      //--- open BUY 
      if(MACD_MAIN_2>MACD_SIGNAL_2 && MACD_MAIN_4<MACD_SIGNAL_4) // Сигнал на покупку
        {
         double sl=(InpStopLoss!=0)?m_symbol.Ask()-ExtStopLoss:0.0;
         double tp=(InpTakeProfit!=0)?m_symbol.Ask()+ExtTakeProfit:0.0;
         OpenBuy(sl,tp); // Отправка маркет-ордера на покупку
         return;
        }
      //--- open SELL
      if(MACD_MAIN_2<MACD_SIGNAL_2 && MACD_MAIN_4>MACD_SIGNAL_4) // Сигнал на продажу
        {
         double sl=(InpStopLoss!=0)?m_symbol.Bid()+ExtStopLoss:0.0;
         double tp=(InpTakeProfit!=0)?m_symbol.Bid()-ExtTakeProfit:0.0;
         OpenSell(sl,tp); // Отправка маркет-ордера на продажу
        }
     }
   return;
  }

Wir haben eine identische Situation wie die oben beschriebene.

Forum für Handel, automatisierte Handelssysteme und Strategietests

Eigenheiten der Sprache mql5, Tipps und Tricks

fxsaber, 2018.02.16 19:52

Nach dem ersten OrderSend erscheint ein Marktauftrag, und wenn ein neuer Tick vor seiner Ausführung kommt, gibt es noch keine Position und ein zweiter OrderSend wird ausgeführt.

Die scheinbar gute Idee von PositionsTotal wird etwas überschattet von der Notwendigkeit, in MT5 auch OrdersTotal für Marktaufträge zu analysieren.

Das bedeutet, dass der Expert Advisor im allgemeinen Fall statt einer Position zwei, drei usw. öffnet. Je nachdem, wie oft Ticks empfangen werden und wie lange Marktaufträge ausgeführt werden.


Da fast alle MT5 EAs in der kodobase mit der gleichen Logik wie das MT5 Template geschrieben sind, haben sie auch den gleichen Fehler, der darin enthalten ist. Dies gilt leider für fast alle MT5 EAs in KB.

MACD EA
MACD EA
  • Stimmen: 4
  • 2018.02.15
  • Vladimir Karputov
  • www.mql5.com
При поступлении сигнала противоположная позиция закрывается. Также советник может закрывать половину позиции (параметр Profit for closing half of the position), может переводить позицию в безубыток (параметр Breakeven). Размер открываемой позиции может задавать вручную (параметр Lots) или в процентах риска от свободной маржи (параметр Risk in...
 

Bei einem Netting können gleichzeitig eine offene Position und mehrere Marktaufträge in beiden Richtungen für dasselbe Symbol vorliegen. Zum Beispiel eine KAUFEN-Position und ein KAUFEN-Auftrag. Es stimmt, ich habe es nicht geschafft, ein solches Demokonto zu finden, weil es überall eine Regel mit Asynchronität gab

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Wanzen, Wanzen, Fragen

fxsaber, 2018.02.14 08:58

Die gesamte OnTradeTransaction-Ereignissequenz erfolgt nach Abschluss des OrderSend.

EA

void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest&, const MqlTradeResult& )
{ 
  static bool FirstRun = true;  
  static ulong StartTime;
  
  if (FirstRun)
  {
    StartTime = GetMicrosecondCount();
    
    FirstRun = false;
  }

  Print(EnumToString(Trans.type));
  Print((GetMicrosecondCount() - StartTime) / 1000);    
}

Manuelles Senden eines Handelsauftrags.

Protokoll

2018.02.14 09:41:46.671 '8854170': instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': accepted instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': deal #192088422 sell 1.00 EURUSD at 1.23673 done (based on order #208541700)
2018.02.14 09:41:46.853 '8854170': order #208541700 sell 1.00 / 1.00 EURUSD at 1.23673 done in 190.608 ms


Expert Advisor Ergebnis

2018.02.14 09:41:46.853 TRADE_TRANSACTION_ORDER_ADD
2018.02.14 09:41:46.853 0
2018.02.14 09:41:46.853 TRADE_TRANSACTION_DEAL_ADD
2018.02.14 09:41:46.853 1
2018.02.14 09:41:46.853 TRADE_TRANSACTION_ORDER_DELETE
2018.02.14 09:41:46.853 1
2018.02.14 09:41:46.853 TRADE_TRANSACTION_HISTORY_ADD
2018.02.14 09:41:46.853 2
2018.02.14 09:41:46.853 TRADE_TRANSACTION_REQUEST
2018.02.14 09:41:46.853 2


Anhand der Zeitspalte und der numerischen Daten des EA können wir sehr gut erkennen, dass die Dauer der Ausführung eines Handelsauftrags keinen Einfluss auf die Abfolge der OnTradeTransaction-Ereignisse hat. Die ganze Asynchronität geht zum Teufel! Sie haben es geschafft, es so sehr zu vermasseln. Baujahr 1755.

Wenn z. B. OrderSendAsync Market Order im Terminal platziert wird, erscheint die Market Order nicht einmal für einen Moment. Vielleicht haben sich die Entwickler dazu entschlossen, um die Dinge ein wenig zu beschleunigen.

 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Diskussion zum Artikel "Visualisierung der Handelsstrategieoptimierung in MetaTrader 5"

fxsaber, 2018.02.22 08:39

Im Rahmenmodus werden OnInit, OnDeinit, OnTick, OnTrade, OnTradeTransaction und OnTimer ignoriert. Nur OnChartEvent funktioniert.

Wegen der OnChartEvent-Ausnahme ist natürlich eine obligatorische Überprüfung des Frame-Mode-Flags erforderlich.