
Die Analyse des Spread von Bid/Ask in MetaTrader 5
Einführung
Wenn Sie keine Limit- oder Stop-Aufträge für den Einstieg und den Ausstieg aus dem Handel verwenden, verwenden Sie Marktaufträge, und diese hängen natürlich von der Größe der Bid-/Ask-Spread (Geld-/Briefspanne) ab, um zu bestimmen, welche Preise Sie erhalten.
Wenn Sie auf die Schaltfläche "Kaufen" klicken, kaufen Sie tatsächlich zum ASK-Kurs, der eine Spanne über dem Geldkurs liegt, den Sie wahrscheinlich für Ihre Kaufentscheidung verwendet haben.
Wenn Sie auf die Schaltfläche Verkaufen klicken, verkaufen Sie zum BID-Kurs, der im Abstand des Spread unter dem Ask-Kurs liegt.
Wenn Sie auf die Schaltfläche "Schließen" klicken, um eine zuvor gekaufte Position zu schließen, verkaufen Sie natürlich zum aktuellen BID-Kurs.
Und umgekehrt gilt: Wenn Sie auf die Schaltfläche "Schließen" drücken, um eine Position zu schließen, die Sie zuvor verkauft ('geshorted') hatten, kaufen Sie tatsächlich zum aktuellen ASK-Preis und schließen oder decken die Position ab.
Nun können wir anhand der Tick-Daten von MetaTrader 5 analysieren, wie hoch die durchschnittliche Bid-Ask-Spread oder Geld-Brief-Spanne in der Vergangenheit tatsächlich war.
Die aktuelle Spanne brauchen Sie nicht zu betrachten, da diese verfügbar ist, wenn Sie sowohl Bid als auch Ask-Kurslinien anzeigen.
Sehen wir uns das Warum und Wie an
Anhand dieser Diagramme können Sie sehen, dass dieser Broker angibt, dass die meisten Spreads 5 Punkte betragen.
Wenn das der Fall ist, dann sollte Sie Kauf und Verkauf mit Öffnen und Schließen einer Position 1 Pip kosten.
Bei einem Handel mit einem Risiko-Rendite-Verhältnis von 1:1, einem Stop-Loss von 10 Pips und einem Take-Profit von 10 Pips würden Sie also 10 % Ihres Risikos/Einsatzes zahlen.
Diese Größe eines Spread ist fair, denn bei einem Buchmacher liegt die Gewinnspanne in der Regel bei 15%, bei Casinos bei etwa 4%.
Die tatsächlichen, durchschnittlichen Spreads (rote Linie) im Vergleich zum dokumentierten Spread des Brokers (schwarze gestrichelte Linie) sind jedoch meist doppelt so groß wie der angegebene Spread, wie das unten stehende Datenfenster bestätigt. Wenn Sie das frühere Beispiel mit demselben SL und TP verwenden, liegen die Kosten für Sie normalerweise bei mindestens 2 Pips oder 20 %.
Wenn Sie ein kleinerer Scalper sind, z. B. mit einem SL von 5 Pips und einem TP von 5 Pips, oder wenn Sie sich entscheiden, auszusteigen, bevor der SL oder TP des vorherigen Beispiels von 10 Pips erreicht wird, z. B. bei einem Verlust von 5 Pips, dann sind die Kosten dieselben 2 Pips, aber da Sie auf Nummer sicher gegangen sind, nachdem der Handel gegen Sie lief, betragen die prozentualen Kosten jetzt 40 % Ihres Einsatzes/Risikos.
Als ich ein Neuling war, habe ich mit 5 Pips S/l und 10 Pips T/P angefangen, um ein Risiko-Ertrags-Verhältnis von 2:1 zu erreichen (wie vermutlich viele neue Händler). Ich war nicht sehr erfolgreich.
Also habe ich den EURUSD M1-Chart mit einem zuverlässigen Zig Zag-Indikator eingehend analysiert. Ich setzte ihn auf 5 Pips als Mindestgröße, was für mich die Art von Retracement bedeutete, mit der ich umgehen konnte.
Die Ergebnisse scheinen darauf hinzudeuten, dass die meisten kleinen Schwankungen bei 7 Pips lagen und die 10-Pips-Legs im Vergleich dazu relativ selten waren. Natürlich habe ich Nachrichten und volatile Märkte berücksichtigt, so dass die Ergebnisse hauptsächlich aus durchschnittlichen Zeiträumen der Handelssitzungen stammten.
Daher begann ich mit einem Stop-Loss von 10 Pips und ließ den Take-Profit offen, so dass ich den Handel genau beobachten und entscheiden konnte, wann ich aussteigen wollte, wenn der Handel bereits einen Verlust oder Gewinn von 7 Pips erreicht hatte. Dies führte zwar zu einer Verbesserung, aber es fehlte mir immer noch ein Gewinn. Erst dann bemerkte ich die hohen Bid/Ask-Spreads, gegen die ich bei diesem Broker handelte, und suchte natürlich nach einem besseren Broker.
Wenn Sie handeln, wenn Nachrichten erscheinen oder der Markt volatil wird, können Sie sehen, dass der tatsächliche durchschnittliche Spread auf etwa 15 Punkte oder das Dreifache der üblichen 5 Punkte ansteigt, so dass Sie 3 Pips oder 60 % Ihres Einsatzes zahlen müssen.
Denken Sie auch nicht an den Handel nach 20:30 Uhr britischer Zeit (21:30 Uhr auf dem Chartserver), er könnte durchaus das 4-, 5-, 6-fache oder sogar noch viel höher sein, vor allem, wenn Sie sich entscheiden, Ihre Handelsposition über das Wochenende zu halten, was, wie Sie unten sehen können, fast das 10-fache des Standard-5-Punkte-Spreads ist, es sei denn, Sie haben extrem große Stop-Loss- und Take-Profit-Levels.
Code-Beispiel für OnInit()
#property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 //--- plots #property indicator_label1 "ActSpread" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 2 #property indicator_label2 "DeclaredSpread" #property indicator_type2 DRAW_LINE #property indicator_color2 clrBlack #property indicator_style2 STYLE_DASH #property indicator_width2 2 //--- indicator parameters input int numRecentBarsBack=100; //#RecentBarsBack M30+~100, M5~200, M1~500 input bool doPrint=true; //true=prints to the toolbox\experts log //--- indicator buffers double ActSpreadBuf[], DeclaredSpreadBuf[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { int numBars=iBars(_Symbol,PERIOD_CURRENT)-2; // Check we have enough data for the request before we begin if(numRecentBarsBack>numBars) { Alert("Can't Do ", numRecentBarsBack, "! Only ", numBars, " Bars are Available", " try 100 or so for 30+ minute charts,", " 200 for 5 minute, or 500 for 1 minute charts.", " Otherwise the indicator may be too slow" ); return(INIT_PARAMETERS_INCORRECT); } double sumPrice=0; double avgPrice=0; // Get the standard 5 point spread for the standard EURUSD currency double stdSpread=0.00005/iClose("EURUSD",PERIOD_M1,1); // 1.2 ~= EURUSD std price //Find out the current average price of the instrument we are using, so we can standardise the spread and _Point int CheckAvgPriceBars=MathMin(numRecentBarsBack, 200); int i=0; for(; i<CheckAvgPriceBars; i++) { sumPrice+=iClose(_Symbol,PERIOD_CURRENT,i); } avgPrice=sumPrice/(i? i: 1.0); //convert the stdSpread to stdPoint by dividing by 5, so we compare apples with apples, not oranges double stdPoint=StringToDouble(DoubleToString(avgPrice*stdSpread/5.0,6)); Print(i, "=bars done, avgPrice=", DoubleToString(avgPrice,6), " std=", DoubleToString(1.2*stdSpread, 6), " stdPoint=", DoubleToString(stdPoint, 6) ); SetIndexBuffer(0,ActSpreadBuf,INDICATOR_DATA); SetIndexBuffer(1,DeclaredSpreadBuf,INDICATOR_DATA); string indName ="BAS("+_Symbol; indName+=" TF="+string(_Period); indName+=" stdPoint="+DoubleToString(stdPoint, 6); indName+=") Last("+string(numRecentBarsBack)+") Bars"; IndicatorSetString(INDICATOR_SHORTNAME, indName); IndicatorSetInteger(INDICATOR_DIGITS,6); IndicatorSetDouble(INDICATOR_MINIMUM, 0.0); IndicatorSetInteger(INDICATOR_LEVELS, 20); //mark out each standard EURUSD 5 point spread, to compare this currencies spread with EURUSD IndicatorSetDouble(INDICATOR_LEVELVALUE,0, 0.000000); IndicatorSetDouble(INDICATOR_LEVELVALUE,1, 5*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,2, 10*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,3, 15*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,4, 20*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,5, 25*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,6, 30*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,7, 35*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,8, 40*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,9, 45*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,10,50*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,11,55*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,12,60*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,13,65*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,14,70*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,15,75*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,16,80*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,17,85*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,18,90*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,19,95*stdPoint); return(INIT_SUCCEEDED); }
Für diesen einfachen 2-Plot-Indikator gibt es nur 2 Parameter, der erste 'numRecentBarsBack' gibt an, wie viele Balken analysiert werden sollen.
Das erste, was wir in OnInit() tun, ist zu überprüfen, ob wir genug Daten haben, um die Anforderung zu erfüllen. Wenn nicht, dann warnen wir den Nutzer und schlagen einige realistische Werte vor, die er verwenden kann, und beenden den Indikator frühzeitig mit einer Fehlermeldung.
Der Rest von OnInit() ist ein ziemlicher Standard, mit Ausnahme der im Unterfenster des Indikators verwendeten Niveaus, die auf Werte gesetzt werden, die einem Vielfachen der üblichen 5-Punkte-Spanne für EURUSD entsprechen.
Dies ist ein ziemlich wichtiger Schritt, denn wir wollen nicht nur den Vergleich zwischen den angegebenen und den tatsächlichen durchschnittlichen Spread-Werten sehen, sondern auch, wie groß der Spread der verschiedenen Währungen im Vergleich zum Standard-EURUSD ist, der normalerweise den niedrigsten verfügbaren Spread aller Währungen hat.
Dies ist eine ziemlich komplizierte Methode, da wir den aktuellen EURUSD-Kurs ermitteln (und durch 1,2 ersetzen müssen, falls er nicht existiert) und 5 EURUSD-Punkte durch diesen Kurs dividieren müssen, um einen Standard-Spread zu ermitteln. Dann iterieren wir durch numRecentBarsBack Preise des aktuellen Forex-Instruments (ich habe es nicht mit Nicht-Forex-Instrumenten getestet), um einen Durchschnittspreis für dieses Instrument zu erhalten.
Wenn wir den Durchschnittspreis des Instruments haben, erstellen wir dann einen gerundeten Standardpunkt, indem wir den Durchschnittspreis des Instruments mit dem zuvor erstellten Standard-Spread multiplizieren und durch 5 teilen, den Standard-EURUSD-Spreadpunkt.
Dieser gerundete Standardpunkt wird dann in jedem Level-Wert verwendet und ist auch in der Kurzbezeichnung des Indikators enthalten, wie im Indikatornamen im untenstehenden "exotischen" USDMXN-Chart zu sehen ist.
In diesem USDMXN Beispiel beträgt der für den Handelstag angegebene Spread etwa 0,0025, was etwa 3 Spread-Levels über Null liegt und somit etwa 15 Punkten in einem EURUSD-Chart entspricht. Beachten Sie auch, dass der tatsächliche, durchschnittliche Spread sogar wild über dieses hohe Niveau für diesen Broker variiert.
Das nachstehende Chart für GBPAUD zeigt, dass der für den Handelstag angegebene Spread bei etwa 0,00019 liegt, was etwa 2,5 Spread-Stufen über dem Nullpunkt liegt und somit etwa 12 Punkten in einem EURUSD-Chart entspricht. Beachten Sie auch, dass in diesem Chart die tatsächlichen durchschnittlichen Spread-Werte ziemlich nahe an den angegebenen Werten für diesen Broker liegen.
Der GBPJPY-Chart unten zeigt, dass der für den Handelstag angegebene Spread bei etwa 0,020 liegt, was etwa 3 Spread-Stufen über dem Nullpunkt liegt und somit etwa 15 Punkten in einem EURUSD-Chart entspricht. Beachten Sie auch, dass in diesem Chart die tatsächlichen durchschnittlichen Spread-Werte ziemlich nah an den angegebenen Werten für diesen Broker liegen.
Der USDJPY-Chart unten zeigt, dass der für den Handelstag angegebene Spread bei etwa 0,0050 liegt, was ungefähr nur eine Spread-Stufe über der Null-Stufe liegt und somit etwa den üblichen 5 Punkten in einem EURUSD-Chart entspricht. Beachten Sie auch, dass in diesem Chart die tatsächlichen durchschnittlichen Spread-Werte wiederum etwa doppelt so hoch sind wie die deklarierten Werte, so dass die gleichen Anmerkungen wie bei den EURUSD-Risiko-/Ertrags-Prozentwerten auch hier gelten.
Hier sind einige weitere Beispiele, Sie können die Beziehungen zwischen den Spreads selbst einschätzen.
Der zweite Parameter ist der boolesche Wert "doPrint", der im Code überprüft wird. Wenn er auf "true" gesetzt wurde, werden die einzelnen Balkenstatistiken in das Expertenprotokoll gedruckt, wie die folgenden Beispiele zeigen. Dies kann den Indikator verlangsamen, wenn der Wert von ' numRecentBarsBack' zu groß ist, daher ist der Standardwert 100.
Wenn Sie den Parameter "doPrint" auf "true" und "numRecentBarsBack" auf einen vernünftigen Wert von etwa 100 für einen 30-Minuten-Chart bzw. 300 für einen 1-Minuten-Chart setzen, können Sie die Protokolleinträge kopieren und sie Ihrem Broker als Nachweis für die wahren Bid/Ask-Spreads schicken.
Code-Beispiel für OnCalculate()
//--- Global variables //--- Set the date formatting for printing to the log const uint dtFormat=uint(TIME_DATE|TIME_MINUTES); //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- Check for no data or Stop flag before we begin if(_StopFlag || rates_total<2) { Alert("Error, StopFlag=", _StopFlag, " #Bars=", rates_total); return(rates_total); } //only do the report at indicator start up or refresh if(prev_calculated>2) { // if we have already nulled the ActSpreadBuf just do the DeclaredSpreadBuf[] and return. if(prev_calculated==rates_total) { int currBar=rates_total-1; DeclaredSpreadBuf[currBar]=spread[currBar]*_Point; return(rates_total); } // else its the start of a new bar so null the ActSpreadBuf else { int currBar=rates_total-1; ActSpreadBuf[currBar]=EMPTY_VALUE; return(rates_total); } } static int start=rates_total-numRecentBarsBack; MqlTick tickBuf[]; double sumSpread=0; double thisSpread=0; int ticks=0; int bid_tick=0; int ask_tick=0; int k=0; ArrayInitialize(ActSpreadBuf, EMPTY_VALUE); ArrayInitialize(DeclaredSpreadBuf, EMPTY_VALUE); for(int i=start; i<rates_total; i++) { sumSpread=0; thisSpread=0; bid_tick=0; ask_tick=0; k=0; ticks=CopyTicksRange(_Symbol, tickBuf, COPY_TICKS_INFO, // Only bid and ask changes are required time[i-1]*1000, // Start time of previous bar time[i ]*1000 // End time of previous bar ); while(k<ticks) { if((tickBuf[k].flags&TICK_FLAG_ASK)==TICK_FLAG_ASK) ask_tick++; if((tickBuf[k].flags&TICK_FLAG_BID)==TICK_FLAG_BID) bid_tick++; sumSpread+=tickBuf[k].ask-tickBuf[k].bid; k++; } // Ensure no divide by zero errors for any missing tick data if(ticks>0) { thisSpread=sumSpread/ticks; ActSpreadBuf[i-1]=thisSpread; } else { thisSpread=0.0; ActSpreadBuf[i-1]=EMPTY_VALUE; } DeclaredSpreadBuf[i-1]=spread[i-1]*_Point; if(doPrint) { Print(TimeToString(time[i-1], dtFormat), " NumTicks="+string(ticks), " b="+string(bid_tick), " a="+string(ask_tick), " AvgSpread=", DoubleToString(thisSpread/_Point, 1), " DeclaredSpread=", string(spread[i-1]) ); } } //don't do stats for incomplete current bar, but can do DeclaredSpread if it has a value DeclaredSpreadBuf[rates_total-1]=(spread[rates_total-1]*_Point); //--- return value of prev_calculated for next call return(rates_total); }
Aus dem obigen Beispiel für OnCalculate() ist vor allem die Verwendung von CopyTicksRange() hervorzuheben, um nur die Tick-Daten zwischen dem Beginn des vorherigen und dem Beginn des aktuellen Indexes von Balken bzw. Kerze zu erhalten. Beachten Sie auch, dass wir das Array von time[] in Millisekunden umwandeln müssen, indem wir es mit 1000 multiplizieren, da datetime-Daten nur auf die Sekunde genau sind und CopyTicksRange() Millisekunden benötigt .
ticks=CopyTicksRange(_Symbol, tickBuf, COPY_TICKS_INFO, // Only bid and ask changes are required time[i-1]*1000, // Start time of previous bar time[i ]*1000 // End time of previous bar );
Beachten Sie auch, dass wir die Bid- und Ask-Ticks akkumulieren, obwohl wir sie nicht in den Diagrammen verwenden. Der Wert der Bid-Ticks sollte mit dem Wert im Array tick_volume[] übereinstimmen, und das tut er auch, wie im Datenfenster angezeigt.
Zusätzlicher Hinweis zum Herunterladen von Ticks...
Wenn Sie eine Währung prüfen möchten, die Sie normalerweise nicht verwenden, müssen Sie diese Währung im Menü Ansicht\Symbole durch Doppelklick auf Symbol anzeigen hinzufügen. Während Sie sich in diesem Fenster befinden, sollten Sie auch zur Registerkarte Ticks gehen und im ersten Datumsmenü Alle Ticks ein Datum wählen, das etwa einen Monat vor dem heutigen Tag liegt; und dann das zweite Datumsmenü auf morgen einstellen, um Ihre lokale Datenbank der Ticks zu füllen.
Schlussfolgerung
Bevor wir mit einer Währung handeln, sollten wir wissen, wie hoch unsere Risikoprozentsätze für die Art des Handels (Scalping, Swing, Position...) sind, die wir besprechen, und die unserer Lieblingswährungen mit anderen vergleichen, die mit einer gemeinsamen Standard-Spread-Größe verfügbar sind.
Nach meinen Studien würde ich Händlern raten, sich an die Hauptwährungen zu halten, die direkt an den USD gekoppelt sind, nämlich USDCAD, USDCHF, USDJPY, EURUSD und GBPUSD, da diese die niedrigsten Gesamtspreads haben.
Wir alle müssen unseren Brokern mitteilen, dass wir jetzt ihre wahren Bid/Ask-Spreads sehen können, auch wenn wir nur auf Kommission handeln, wenn sie ihre Spreads auf ein sehr hohes Niveau anheben. Viel Glück, und denken Sie daran, dass Sie nicht handeln sollten, wenn Sie keinen Broker mit vernünftigen Bid/Ask-Spreads während der Handelszeiten finden können, da Sie NICHT gewinnen können!
Bevor jemand fragt: Dieser Prozess kann nur mit MetaTrader 5 durchgeführt werden, da die Tick-Daten in MetaTrader 4 nicht verfügbar sind.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/9804





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.