Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 6): Zwei RSI-Indikatoren kreuzen ihre Linien
Einführung
Ein Multi-Currency Expert Advisor ist ein Expert Advisor oder Handelsroboter, der handeln kann (z.B. Aufträge eröffnen, schließen und verwalten: Trailing Stop Loss und Trailing Profit) für mehr als 1 Symbolpaar von nur einem Symbolchart aus, wobei in diesem Artikel Expert Advisor für 30 Paare handeln wird.
In diesem Artikel werden wir zwei RSI-Indikatoren, die sich kreuzen, als Signal verwenden, den Fast RSI, der sich mit dem Slow RSI kreuzt.
Wie in den vorangegangenen Artikeln bewiesen wurde, wissen wir alle, dass der Handel mit mehreren Währungen bereits mit der Leistung, den Fähigkeiten und den Möglichkeiten von MQL5 möglich ist, sowohl im Handelsterminal als auch im Strategietester.
Mit dem Ziel der Erfüllung der wichtigen Bedürfnisse der Händler, die eine effiziente und effektive Trading-Roboter wollen, sodass unter Berufung auf die Kraft, Fähigkeiten und Einrichtungen der sehr zuverlässigen MQL5, können wir uns vorstellen, verschiedene Ideen und Strategien eines einfachen Multi-Währung Expert Advisors, der, wie in diesem Artikel beschrieben, die Linien von zwei RSI-Indikatoren kreuzen lässt.
Pläne und Eigenschaften
1. Handel mit Währungspaaren.
Dieser Mehr-Währungs-EA ist für den Handel mit einem der folgenden Symbole oder Paare vorgesehen:
Für Forex:
EURUSD,GBPUSD,AUDUSD,NZDUSD,USDCAD,USDCHF,USDJPY,EURGBP, EURAUD, EURNZD, EURCAD, EURCHF, EURJPY, GBPAUD, GBPNZD, GBPCAD,
GBPCHF,GBPJPY,AUDNZD,AUDCAD,AUDCHF,AUDJPY,NZDCAD,NZDCHF,NZDJPY, CADCHF, CADJPY, CHFJPY = 28 Paare
plus 2 Metallpaare: XAUUSD (Gold) und XAGUSD (Silber).
insgesamt sind es 30 Paare.
Was Symbole oder Paare mit Namenspräfixen und/oder -suffixen betrifft, so verwende ich für den Expert Advisor in diesem Artikel die Funktion zur automatischen Behandlung von Symbolnamen mit Präfixen und/oder Suffixen, sodass bei der Verwendung eines EA auf MetaTrader 5 von einem Broker mit solchen speziellen Symbolnamen alles reibungslos funktioniert.
Die Funktion zur Erkennung von Symbolnamen mit Präfixen und Suffixen funktioniert jedoch nur bei Forex- und Metall-Symbolpaarnamen im MetaTrader 5, nicht aber bei speziellen Symbolen und Indizes.
In Bezug auf den Multi-Currency Expert Advisor in meinem vorherigen Artikel, gibt es einige Händler, die fragen, wie man einen Multi-Currency EA als Einzelwährungs-EA oder als eigenständigen EA verwenden kann.
Eigentlich, in der Expert Advisor in der vorherigen Artikel, gibt es eine Anlage oder Option, um die Expert Advisor als EA durch den Handel nur auf eine einzige Währung oder arbeiten als Stand-alone-EA.
Im Expert Advisor verwenden wir diesmal immer noch 10 verschiedene Paare, die gehandelt werden sollen. Eines der 10 Optionspaare, die gehandelt werden, ist „Trader's Desired Pairs“ (Des Händlers Wunschpaar), wobei die zu handelnden Paare vom Händler manuell in der Eigenschaft Expert Input eingegeben werden müssen. Sie müssen jedoch immer daran denken, dass der Name des Paares, das Sie eingeben, bereits in der Liste der 30 Paare enthalten sein muss.
Diese Option „Trader's Desired Pairs“ (Des Händlers Wunschpaar) kann tatsächlich verwendet werden, sodass Expert Advisors wird nur auf Einzel-Währung Handel oder arbeiten als Stand-alone-EA, durch die Eingabe des Namens von nur einem gewünschten Paar, und dann wird der Experte Berater nur mit diesem einen Paar handeln und arbeiten.
Die Parametereinstellungen für den Experteneingang müssen wie in der folgenden Abbildung gezeigt vorgenommen werden.
Im obigen Beispiel der Eingabeeigenschaft, bei dem der Händler nur den Namen des XAUUSD-Paares eingibt, wird der Expert Advisor unter dieser Bedingung nur mit dem XAUUSD-Paar handeln. Unabhängig davon, wo der Expert Advisor unter den 30 verfügbaren Paaren platziert wird, handelt er nur mit dem Paar XAUUSD.
Abgesehen davon habe ich im Expert Advisor in diesem Artikel eine Option hinzugefügt, um die Bedingungen für das Handelspaar auszuwählen, d.h. ob mit einer einzigen Währung oder mit mehreren Währungen gehandelt werden soll.
Die Experten-Eingabeparameter müssen wie in der folgenden Abbildung dargestellt eingestellt werden.
Bei der Option „SP“ (Single-Pair) handelt der Expert Advisor nur mit dem Paar, auf dessen Chart er platziert ist.
Wenn beispielsweise ein Expert Advisor auf das EURUSD-Paar platziert wird, dann wird der Expert Advisor nur mit dem EURUSD-Paar handeln.
Bei den Expert Advisors in diesem Artikel gibt es also zwei Möglichkeiten, mit Einzelwährungen zu handeln oder als eigenständiger Expertenberater zu arbeiten.
1. Bleiben Sie bei der Option Multi-Pair oder „MP“ und wählen Sie die Option Trader's Desired Pairs, aber geben Sie nur einen Paar-Namen ein, zum Beispiel XAUUSD.
Bei dieser Option handelt der Expert Advisor, unabhängig vom Paar, auf das er eingestellt ist, nur mit dem Paar, das in Trader Wishes Pairs eingegeben wurde.
2. Wählen Sie im Modus Handelspaare auswählen die Option „SP“ oder Einzelpaar.
Wenn ein Expert Advisor auf das EURUSD-Paar platziert wird, handelt der Expert Advisor nur mit dem EURUSD-Paar.
Außerdem werden in der Gruppe Handel zu bestimmten Zeiten Optionen für Händler angeboten, die in der Zeitzone handeln möchten.
Vielleicht möchten viele Händler nach der Zeitzone handeln, sodass die Paare, die gehandelt werden, der Zeit für die Handelssitzung entsprechen können, sodass wir in diesem Expert Advisor noch die Option für die Handelssitzung (Zeitzone) verwenden.
2. Indikatoren.
Der Relative-Stärke-Index (RSI) wurde von J. Welles Wilder entwickelt und 1978 in einem Buch „New Concepts in Technical Trading Systems“ sowie in der Zeitschrift Commodities (heute Modern Trader) in der Juni-Ausgabe 1978 veröffentlicht. Er hat sich zu einem der beliebtesten Oszillator-Indizes entwickelt.
Der Relative-Stärke-Index (RSI) ist ein technischer Indikator, der bei der Analyse der Finanzmärkte verwendet wird. Er soll die aktuelle und historische Stärke oder Schwäche einer Aktie oder eines Marktes auf der Grundlage der Schlusskurse des letzten Handelszeitraums darstellen.
Der technische Indikator Relative Strength Index (RSI) ist ein preisverfolgender Oszillator, der zwischen 0 und 100 liegt. Wilder empfahl für den Relative Strength Index eine Periodenlänge von 14. Seitdem haben RSI mit Periodenlängen von 9 und 25 an Beliebtheit gewonnen.
Der RSI wird in der Regel auf einer 14-Tage-Skala von 0 bis 100 gemessen, wobei die Höchst- und Tiefstwerte bei 70 bzw. 30 liegen. Kürzere oder längere Zeitrahmen werden für abwechselnd kürzere oder längere Prognosen verwendet. Hohe und niedrige Werte - 80 und 20 oder 90 und 10 - treten seltener auf, zeigen aber eine stärkere Dynamik an.
Außerdem wird in der technischen Analyse MetaTrader 5 angegeben, dass das RSI-Signal für die Chartanalyse verwendet wird:
- Hochs und Tiefs
- Chart-Formationen
- Falsche Ausbrüche (Failure Swing, Durchbruch der Unterstützung oder des Widerstands)
- Unterstützungs- und Widerstandsniveaus
- Divergenzen
Es gibt also sehr viele Varianten der RSI-Handelsstrategie.
Auch ein Analyst und Investor in einem Q&A in seinem Artikel bei der Beantwortung der Frage:
„Was ist die beste RSI-Einstellung für das Daytrading?
Leider funktioniert der RSI am besten auf täglichen Balken. Wir haben viele Daten auf der Grundlage von Intraday-Daten getestet, aber sie sind nicht besonders nützlich.“
„Wie handeln Sie mit dem RSI?
Zunächst einmal bevorzugen wir die Verwendung von Tagesbalken. Zweitens ziehen wir es vor, eine kurze Anzahl von Tagen in den Einstellungen zu verwenden, vorzugsweise maximal 5 Tage. Drittens funktioniert der RSI am besten bei Aktien und mittelwertumkehrenden Vermögenswerten mit einer Grenze über Nacht. Im Bereich Forex waren wir nicht erfolgreich.“
Allerdings werde ich in diesem Artikel Signale der Kreuzung von Fast RSI und Slow RSI für den Devisenhandel verwenden.
Ob es erfolgreich sein wird oder nicht, muss noch erprobt und getestet werden.
Eine Illustration des schnellen RSI-Signals, das die langsame RSI-Linie kreuzt, ist in Abbildung 1 und 2 zu sehen.
Abbildung 1
Abbildung 2
3. Handels- & Auftragsmanagement
Es gibt mehrere Möglichkeiten, Ihre Trades mit diesem Multiwährungs-Expertenberater zu verwalten:
3.1. Stop Loss-Aufträge
Optionen: Use Order Stop Loss (Yes) oder (No)
- Wenn die Option (No) für Use Order Stop Loss für Aufträge verwenden ausgewählt ist, werden alle Aufträge ohne Stop Loss eröffnet.
- Bei Verwendung der Option Use Order Stop Loss für Aufträge verwenden (Yes): Dann gibt es die weiteren Optionen: Use Automatic Calculation (automatische Berechnung) des Stop Loss verwenden (Yes) oder (No).
- Bei der Option automatische Berechnung Stop Loss (Yes), wird die Stop Loss-Berechnung automatisch durch den Experten durchgeführt.
- Wenn die Option Automatische Berechnung des Stop Loss (No) gewählt wurde, muss der Händler den Stop Loss-Wert in Pips eingeben.
- Wenn die Option Use Order Stop Loss (No): Dann prüft der Experte für jede eröffnete Order, ob die Signalbedingung noch gut ist und die Order mit Gewinn aufrechterhalten werden kann oder ob sich das Signal abgeschwächt hat und die Order geschlossen werden muss, um den Gewinn zu sichern oder ob sich die Signalbedingung umgekehrt hat und die Order mit Verlust geschlossen werden muss.
- Wenn sie nicht aktiviert ist (No), wird der Auftrag trotz des schwächeren Signals aufrechterhalten oder nicht geschlossen, um den Gewinn zu sichern.
- Wenn aktiviert (Yes), sind die Bedingungen für die Indikatoren Fast RSI und Slow RSI:
Für das Schließen von Kaufpositionen:
Wenn der Fast RSI über dem Slow RSI liegt und der Fast RSI-Wert des aktuellen Balkens kleiner ist als der Fast RSI-Wert des vorherigen Balkens, wird der Kaufauftrag geschlossen.
Für das Schließen von Verkaufspositionen:
Wenn der Fast RSI unter dem Slow RSI liegt und der Fast RSI-Wert des aktuellen Balkens größer ist als der Fast RSI-Wert des vorherigen Balkens, wird der Verkaufsauftrag geschlossen.
Der Code zum Setzen eines Stop Loss-Auftrags lautet wie folgt:
double MCEA::OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice) { //--- slv=0.0; int x=PairsIdxArray(xsymb); Pips(xsymb); RefreshTick(xsymb); //-- switch(type) { case (ORDER_TYPE_BUY): { if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice-38*pip); else if(use_sl==Yes && autosl==No) slv=mc_symbol.NormalizePrice(atprice-SLval*pip); else slv=0.0; //-- break; } case (ORDER_TYPE_SELL): { if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice+38*pip); else if(use_sl==Yes && autosl==No) slv=mc_symbol.NormalizePrice(atprice+SLval*pip); else slv=0.0; } } //--- return(slv); //--- } //-end OrderSLSet() //---------//
Der Code, um den Handel zu schließen und den Gewinn aufgrund eines schwachen Signals zu sichern, lautet wie folgt:
int MCEA::GetCloseInWeakSignal(const string symbol,int exis) // Signal Indicator Position Close in profit { //--- int ret=0; int rise=1, down=-1; int bar=3; //-- double rdif=rsidiff; double RSIFast[], RSISlow[]; //-- ArrayResize(RSIFast,bar,bar); ArrayResize(RSISlow,bar,bar); ArraySetAsSeries(RSIFast,true); ArraySetAsSeries(RSISlow,true); //-- int x=PairsIdxArray(symbol); UpdatePrice(symbol,TFt); //-- CopyBuffer(hRSIFast[x],0,0,bar,RSIFast); CopyBuffer(hRSISlow[x],0,0,bar,RSISlow); //-- if(exis==down && RSIFast[1]<=RSISlow[1] && RSIFast[1]<RSIFast[2] && RSIFast[0]>RSIFast[1]+rdif) ret=rise; if(exis==rise && RSIFast[1]>=RSISlow[1] && RSIFast[1]>RSIFast[2] && RSIFast[0]<RSIFast[1]-rdif) ret=down; //-- return(ret); //--- } //-end GetCloseInWeakSignal() //---------//
2. Take Profit-Aufträge.
Optionen: Use Order Take Profit (Yes) oder (No)
- Wenn die Option Use Order Take Profit (No) ausgewählt ist, werden alle Aufträge ohne ein Take Profit, einem Gewinnziel eröffnet.
- Bei Verwendung der Option Use Order Take Profit (Yes): Dann gibt es die weiteren Optionen: Use Automatic Calculation Order Take Profit (Yes) oder (No).
- Bei der Option der automatischen Berechnung von Take Profit (Yes), dann wird die Berechnung der Take Profit Order automatisch vom Experten durchgeführt.
- Wenn die Option der automatischen Berechnung von Take Profit (No), gewählt wurde, muss der Händler den Order-Take Profit-Wert in Pips eingeben.
Der Code zum Festlegen von Take Profit lautet wie folgt:
double MCEA::OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice) { //--- tpv=0.0; int x=PairsIdxArray(xsymb); Pips(xsymb); RefreshTick(xsymb); //-- switch(type) { case (ORDER_TYPE_BUY): { if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice+50*pip); else if(use_tp==Yes && autotp==No) tpv=mc_symbol.NormalizePrice(atprice+TPval*pip); else tpv=0.0; //-- break; } case (ORDER_TYPE_SELL): { if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice-50*pip); else if(use_tp==Yes && autotp==No) tpv=mc_symbol.NormalizePrice(atprice-TPval*pip); else tpv=0.0; } } //--- return(tpv); //--- } //-end OrderTPSet() //---------//
3. Trailing Stop und Trailing Take Profit.
Optionen: Use Trailing SL/TP (Yes) oder (No)
- Wenn die Option Use Trailing SL/TP (No) gewählt wurde, wird der Experte keinen Trailing Stop Loss und keinen Trailing-Take Profit durchführen.
- Bei der Option Use Trailing SL/TP (Yes): Händler können zwischen 2 Optionen wählen:
1. Trailing durch Preis.
Der Trailing-Stop wird vom Experten anhand der Preisbewegungen und des Wertes in der Eingabeeigenschaft ausgeführt, und gleichzeitig wird der Trailing-Profit auf der Grundlage des variablen Wertes TPmin (minimaler Trailing-Profit-Wert) gemacht.
2. Trailing durch Indikator.
Der Trailing-Stop wird vom Experten mit Hilfe des VIDYA-Indikators ausgeführt, wobei gleichzeitig ein Trailing-Profit auf der Grundlage des variablen Werts TPmin (minimaler Trailing-Profit-Wert) erzielt wird.
Hinweis: Der Experte führt einen Trailing-Take Profit gleichzeitig mit einem Trailing-Stop aus.
Meinen Untersuchungen und Experimenten zufolge ist der VIDYA-Indikator etwas besser und ideal für Trailing-Stops im Vergleich zum Parabolic SAR oder verschiedenen Varianten von Moving Average-Indikatoren.
Im Vergleich zum Parabolic SAR-Indikator ist der VIDYA-Indikator näher an den Kursbewegungen, und im Vergleich zu den AMA-, DEMA- und MA-Indikatoren ist der VIDYA-Indikator noch weiter von den Kursbewegungen entfernt.
Daher habe ich in diesem Artikel beschlossen, den VIDYA-Indikator für die auf dem Indikator basierende Trailing-Stop-Funktion zu verwenden.
Der Code für die Funktion TSPrice, „Trailing Stop Price“ and Indicator:
double MCEA::TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type) { //--- int br=2; double pval=0.0; int x=PairsIdxArray(xsymb); Pips(xsymb); //-- switch(TS_type) { case 0: { RefreshTick(xsymb); if(ptype==POSITION_TYPE_BUY) pval=mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip); if(ptype==POSITION_TYPE_SELL) pval=mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip); break; } case 1: { double VIDyAv[]; ArrayResize(VIDyAv,br,br); ArraySetAsSeries(VIDyAv,true); CopyBuffer(hVIDyAv[x],0,0,br,VIDyAv); RefreshPrice(xsymb,TFt,br); //-- if(ptype==POSITION_TYPE_BUY && (VIDyAv[0]<mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip))) pval=VIDyAv[0]; if(ptype==POSITION_TYPE_SELL && (VIDyAv[0]>mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip))) pval=VIDyAv[0]; break; } } //-- return(pval); //--- } //-end TSPrice() //---------//
Ändern wir den SL/TP-Funktionscode:
bool MCEA::ModifySLTP(const string symbx,int TS_type) { //--- ResetLastError(); MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- int TRSP=(Close_by_Opps==No && TS_type==1) ? 0 : TS_type; bool modist=false; int x=PairsIdxArray(symbx); Pips(symbx); //-- int total=PositionsTotal(); //-- for(int i=total-1; i>=0; i--) { string symbol=PositionGetSymbol(i); if(symbol==symbx && mc_position.Magic()==magicEA) { ENUM_POSITION_TYPE opstype = mc_position.PositionType(); if(opstype==POSITION_TYPE_BUY) { RefreshTick(symbol); double price = mc_position.PriceCurrent(); double vtrsb = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP)); double pos_open = mc_position.PriceOpen(); double pos_stop = mc_position.StopLoss(); double pos_profit = mc_position.Profit(); double pos_swap = mc_position.Swap(); double pos_comm = mc_position.Commission(); double netp=pos_profit+pos_swap+pos_comm; double modstart=mc_symbol.NormalizePrice(pos_open+TSmin*pip); double modminsl=mc_symbol.NormalizePrice(vtrsb+((TSmin-1.0)*pip)); double modbuysl=vtrsb; double modbuytp=mc_symbol.NormalizePrice(price+TPval*pip); bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop)); //-- if(modbuy && netp>minprofit) { modist=mc_trade.PositionModify(symbol,modbuysl,modbuytp); } } if(opstype==POSITION_TYPE_SELL) { RefreshTick(symbol); double price = mc_position.PriceCurrent(); double vtrss = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP)); double pos_open = mc_position.PriceOpen(); double pos_stop = mc_position.StopLoss(); double pos_profit = mc_position.Profit(); double pos_swap = mc_position.Swap(); double pos_comm = mc_position.Commission(); double netp=pos_profit+pos_swap+pos_comm; double modstart=mc_symbol.NormalizePrice(pos_open-TSmin*pip); double modminsl=mc_symbol.NormalizePrice(vtrss-((TSmin+1.0)*pip)); double modselsl=vtrss; double modseltp=mc_symbol.NormalizePrice(price-TPval*pip); bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); //-- if(modsel && netp>minprofit) { modist=mc_trade.PositionModify(symbol,modselsl,modseltp); } } } } //-- return(modist); //--- } //-end ModifySLTP() //---------//
4. Manuelle Auftragsverwaltung.
In diesem Multi-Currency Expert Advisor wurden mehrere manuelle Schaltflächen hinzugefügt, um die Effizienz und Effektivität für Händler bei der Überwachung der Arbeit des Expert Advisors zu erhöhen.
4.1. SL / TP Alle Aufträge einstellen:
Diese Schaltfläche ist nützlich, wenn der Händler die Parameter „Use Order Stop Loss (No)“ und/oder „Use Order Take Profit (No)“ eingegeben hat, dann aber Stop Loss oder Take Profit für alle Aufträge verwenden möchte, dann werden mit einem einzigen Klick auf die Schaltfläche „Set SL/TP All Orders“ alle Orders geändert und ein Stop Loss und/oder Take Profit angewendet.
4.2. Alle Positionen schließen:
Wenn ein Händler alle Positionen schließen möchte, genügt ein einziger Klick auf die Schaltfläche „Alle Aufträge schließen“, um alle offenen Aufträge zu schließen.
4.3. Alle Positionen mit Gewinn schließen:
Wenn ein Händler alle Aufträge schließen möchte, die bereits profitabel sind, genügt ein einziger Klick auf die Schaltfläche „Close All Orders Profit“, um alle offenen Positionen, die bereits profitabel sind, zu schließen.
5. Management-Befehle und Chartsymbole.
Für Multi-Währungs-Expertenberater, die 30 Paare mit nur einem Chart-Symbol handeln, ist es sehr effektiv und effizient, eine Schalttafel für alle Symbole zur Verfügung zu stellen, sodass Händler den Chart-Zeitrahmen oder die Symbole mit nur einem Klick ändern können, um die Genauigkeit des Indikatorsignals zu sehen, wenn der Experte eine Order öffnet oder schließt.
Umsetzung der Planung im Programm MQL5
1. Programmkopf und Eingabeeigenschaften.
Header-Datei MQL5 einbinden:
//+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> #include <Trade\PositionInfo.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\AccountInfo.mqh> //-- CTrade mc_trade; CSymbolInfo mc_symbol; CPositionInfo mc_position; CAccountInfo mc_account; //---
Die Enumeration zur Verwendung der Zeitzone:
//-- enum tm_zone { Cus_Session, // Trading on Custom Session New_Zealand, // Trading on New Zealand Session Australia, // Trading on Autralia Sydney Session Asia_Tokyo, // Trading on Asia Tokyo Session Europe_London, // Trading on Europe London Session US_New_York // Trading on US New York Session }; //--
Die Enumeration zur Auswahl der Zeitstunde:
//-- enum swhour { hr_00=0, // 00:00 hr_01=1, // 01:00 hr_02=2, // 02:00 hr_03=3, // 03:00 hr_04=4, // 04:00 hr_05=5, // 05:00 hr_06=6, // 06:00 hr_07=7, // 07:00 hr_08=8, // 08:00 hr_09=9, // 09:00 hr_10=10, // 10:00 hr_11=11, // 11:00 hr_12=12, // 12:00 hr_13=13, // 13:00 hr_14=14, // 14:00 hr_15=15, // 15:00 hr_16=16, // 16:00 hr_17=17, // 17:00 hr_18=18, // 18:00 hr_19=19, // 19:00 hr_20=20, // 20:00 hr_21=21, // 21:00 hr_22=22, // 22:00 hr_23=23 // 23:00 }; //--
Die Enumeration zur Auswahl von Zeitminuten:
//-- enum inmnt { mn_00=0, // Minute 0 mn_05=5, // Minute 5 mn_10=10, // Minute 10 mn_15=15, // Minute 15 mn_20=20, // Minute 20 mn_25=25, // Minute 25 mn_30=30, // Minute 30 mn_35=35, // Minute 35 mn_40=40, // Minute 40 mn_45=45, // Minute 45 mn_50=50, // Minute 50 mn_55=55 // Minute 55 }; //--
Die Enumeration zur Auswahl von 10 Optionspaaren für den Handel
//-- enum PairsTrade { All30, // All Forex 30 Pairs TrdWi, // Trader Wishes Pairs Usds, // Forex USD Pairs Eurs, // Forex EUR Pairs Gbps, // Forex GBP Pairs Auds, // Forex AUD Pairs Nzds, // Forex NZD Pairs Cads, // Forex CDD Pairs Chfs, // Forex CHF Pairs Jpys // Forex JPY Pairs }; //--
Die Enumeration YN wird für die Optionen (Yes) oder (No) in der Eigenschaft Experteneingabe verwendet.
//-- enum YN { No, Yes }; //--
Die Enumeration zur Verwendung von Money Management Lot Size
//-- enum mmt { FixedLot, // Fixed Lot Size DynamLot // Dynamic Lot Size }; //--
Die Enumeration zur Auswahl des Zeitrahmens, der für die Berechnung der Signalindikatoren verwendet werden soll
//-- enum TFUSE { TFM5, // 00_PERIOD_M5 TFM15, // 01_PERIOD_M15 TFM30, // 02_PERIOD_M30 TFH1, // 03_PERIOD_H1 TFH2, // 04_PERIOD_H2 TFH3, // 05_PERIOD_H3 TFH4, // 06_PERIOD_H4 TFH6, // 07_PERIOD_H6 TFH8, // 08_PERIOD_H8 TFH12, // 09_PERIOD_H12 TFD1 // 10_PERIOD_D1 }; //--
Bei der TFUSE-Enumeration beschränke ich die Verwendung der Zeitrahmenberechnungen für die Experten nur von TF-M5 bis TF-D1.
Die Enumeration zur Auswahl des Typs, der für die Berechnung des Trailing-Stops verwendet werden soll
//-- enum TrType { byprice, // Trailing Stop by Price byindi // Trailing Stop by Indicator }; //--
Die Enumeration zur Auswahl der Handelsart, mit der der Experte handelt, Einzelwährung oder Mehrfachwährung.
//-- enum MS { SP, // Single Pair MP // Multi Pairs }; //--
Eingabeeigenschaften des Experten:
//--- input group "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter input TFUSE tfinuse = TFH4; // Select Expert TimeFrame, default PERIOD_H4 input int rsifast = 10; // Input Period for Fast RSI input ENUM_APPLIED_PRICE frsiapp = PRICE_WEIGHTED; // Select Fast RSI Applied Price input int rsislow = 30; // Input Period for Slow RSI input ENUM_APPLIED_PRICE srsiapp = PRICE_WEIGHTED; // Select Slow RSI Applied Price input double rsidiff = 4.56; // Input Differentiation between RSIs //--- input group "=== Select Pairs to Trade ==="; // Selected Pairs to trading input MS trademode = MP; // Select Trading Pairs Mode (Multi or Single) input PairsTrade usepairs = All30; // Select Pairs to Use input string traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma //-- input group "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter input mmt mmlot = DynamLot; // Money Management Type input double Risk = 10.0; // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%) input double Lots = 0.01; // Input Manual Lot Size FixedLot //--Trade on Specific Time input group "=== Trade on Specific Time ==="; // Trade on Specific Time input YN trd_time_zone = Yes; // Select If You Like to Trade on Specific Time Zone input tm_zone session = Cus_Session; // Select Trading Time Zone input swhour stsescuh = hr_00; // Time Hour to Start Trading Custom Session (0-23) input inmnt stsescum = mn_15; // Time Minute to Start Trading Custom Session (0-55) input swhour clsescuh = hr_23; // Time Hour to Stop Trading Custom Session (0-23) input inmnt clsescum = mn_55; // Time Minute to Stop Trading Custom Session (0-55) //--Day Trading On/Off input group "=== Day Trading On/Off ==="; // Day Trading On/Off input YN ttd0 = No; // Select Trading on Sunday (Yes) or (No) input YN ttd1 = Yes; // Select Trading on Monday (Yes) or (No) input YN ttd2 = Yes; // Select Trading on Tuesday (Yes) or (No) input YN ttd3 = Yes; // Select Trading on Wednesday (Yes) or (No) input YN ttd4 = Yes; // Select Trading on Thursday (Yes) or (No) input YN ttd5 = Yes; // Select Trading on Friday (Yes) or (No) input YN ttd6 = No; // Select Trading on Saturday (Yes) or (No) //--Trade & Order management Parameter input group "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter input YN use_sl = No; // Use Order Stop Loss (Yes) or (No) input YN autosl = Yes; // Use Automatic Calculation Stop Loss (Yes) or (No) input double SLval = 30.0; // If Not Use Automatic SL - Input SL value in Pips input YN use_tp = Yes; // Use Order Take Profit (Yes) or (No) input YN autotp = Yes; // Use Automatic Calculation Take Profit (Yes) or (No) input double TPval = 60.0; // If Not Use Automatic TP - Input TP value in Pips input YN TrailingSLTP = Yes; // Use Trailing SL/TP (Yes) or (No) input TrType trlby = byindi; // Select Trailing Stop Type input double TSval = 10.0; // If Use Trailing Stop by Price Input value in Pips input double TSmin = 5.0; // Minimum Pips to start Trailing Stop input double TPmin = 25.0; // Input Trailing Profit Value in Pips input YN Close_by_Opps = Yes; // Close Trade By Opposite Signal (Yes) or (No) input YN SaveOnRev = Yes; // Close Trade and Save profit due to weak signal (Yes) or (No) //--Others Expert Advisor Parameter input group "=== Others Expert Advisor Parameter ==="; // Others EA Parameter input YN alerts = Yes; // Display Alerts / Messages (Yes) or (No) input YN UseEmailAlert = No; // Email Alert (Yes) or (No) input YN UseSendnotify = No; // Send Notification (Yes) or (No) input YN trade_info_display = Yes; // Select Display Trading Info on Chart (Yes) or (No) input ulong magicEA = 20240111; // Expert ID (Magic Number) //--- //---------//
Hinweis: Wenn die Eingabeeigenschaft der Experten-ID (Magic Number) leer gelassen wird, kann der Expert Advisor manuell eröffnete Aufträge verwalten.
In der Eigenschaftsgruppe Globale Strategie-EA-Parameter Experteneingabe werden die Händler aufgefordert, den Zeitrahmen des Experten für die Berechnung der Indikatorsignale auszuwählen und Parameter einzugeben:
- Eingabe der Periodenlänge für RSI Fast und Auswahl von RSI Fast Applied Price
- Eingabe der Periodenlänge für RSI Slow und Auswahl RSI Slow Applied Price
- Eingabewert für die Unterscheidung zwischen RSI
In der Eigenschaftsgruppe „Select Pairs to Trade“ des Expert Advisors müssen Händler das zu handelnde Paar aus den 10 zur Verfügung stehenden Optionen auswählen; standardmäßig ist „All Forex 30 Pairs“ (alle 30 Paare) eingestellt.
Um das zu handelnde Paar zu konfigurieren, rufen wir die Funktion HandlingSymbolArrays() auf. Mit der FunktionHandlingSymbolArrays() werden wir alle Paare behandeln, die gehandelt werden sollen.
void MCEA::HandlingSymbolArrays(void) { //--- string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP", "EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD", "GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF", "NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"}; // 30 pairs string USDs[]={"USDCAD","USDCHF","USDJPY","AUDUSD","EURUSD","GBPUSD","NZDUSD","XAUUSD","XAGUSD"}; // USD pairs string EURs[]={"EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD"}; // EUR pairs string GBPs[]={"GBPAUD","GBPCAD","GBPCHF","EURGBP","GBPJPY","GBPNZD","GBPUSD"}; // GBP pairs string AUDs[]={"AUDCAD","AUDCHF","EURAUD","GBPAUD","AUDJPY","AUDNZD","AUDUSD"}; // AUD pairs string NZDs[]={"AUDNZD","NZDCAD","NZDCHF","EURNZD","GBPNZD","NZDJPY","NZDUSD"}; // NZD pairs string CADs[]={"AUDCAD","CADCHF","EURCAD","GBPCAD","CADJPY","NZDCAD","USDCAD"}; // CAD pairs string CHFs[]={"AUDCHF","CADCHF","EURCHF","GBPCHF","NZDCHF","CHFJPY","USDCHF"}; // CHF pairs string JPYs[]={"AUDJPY","CADJPY","CHFJPY","EURJPY","GBPJPY","NZDJPY","USDJPY"}; // JPY pairs //-- sall=ArraySize(All30); arusd=ArraySize(USDs); areur=ArraySize(EURs); aretc=ArraySize(JPYs); ArrayResize(VSym,sall,sall); ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY); //-- if(usepairs==TrdWi && StringFind(traderwishes,"eg.",0)<0) { string to_split=traderwishes; // A string to split into substrings pairs name string sep=","; // A separator as a character ushort u_sep; // The code of the separator character //--- Get the separator code u_sep=StringGetCharacter(sep,0); //--- Split the string to substrings int p=StringSplit(to_split,u_sep,SPC); if(p>0) { for(int i=0; i<p; i++) StringToUpper(SPC[i]); //-- for(int i=0; i<p; i++) { if(ValidatePairs(SPC[i])<0) ArrayRemove(SPC,i,1); } } arspc=ArraySize(SPC); } //-- SetSymbolNamePS(); // With this function we will detect whether the Symbol Name has a prefix and/or suffix //-- if(inpre>0 || insuf>0) { if(usepairs==TrdWi && arspc>0) { for(int t=0; t<arspc; t++) { SPC[t]=pre+SPC[t]+suf; } } //-- for(int t=0; t<sall; t++) { All30[t]=pre+All30[t]+suf; } for(int t=0; t<arusd; t++) { USDs[t]=pre+USDs[t]+suf; } for(int t=0; t<areur; t++) { EURs[t]=pre+EURs[t]+suf; } for(int t=0; t<aretc; t++) { GBPs[t]=pre+GBPs[t]+suf; } for(int t=0; t<aretc; t++) { AUDs[t]=pre+AUDs[t]+suf; } for(int t=0; t<aretc; t++) { NZDs[t]=pre+NZDs[t]+suf; } for(int t=0; t<aretc; t++) { CADs[t]=pre+CADs[t]+suf; } for(int t=0; t<aretc; t++) { CHFs[t]=pre+CHFs[t]+suf; } for(int t=0; t<aretc; t++) { JPYs[t]=pre+JPYs[t]+suf; } } //-- ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY); ArrayResize(AS30,sall,sall); ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY); for(int x=0; x<sall; x++) {SymbolSelect(AS30[x],true);} if(ValidatePairs(Symbol())>=0) symbfix=true; if(!symbfix) { Alert("Expert Advisors will not trade on pairs "+Symbol()); Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart."); ExpertRemove(); } //-- switch(usepairs) { case 0: // All Forex & Metal 30 Pairs { ArrayResize(DIRI,sall,sall); arrsymbx=sall; ArraySymbolResize(); ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY); pairs="Multi Currency "+string(sall)+" Pairs"; //-- break; } case 1: // Trader wishes pairs { ArrayResize(DIRI,arspc,arspc); arrsymbx=arspc; ArraySymbolResize(); ArrayCopy(DIRI,SPC,0,0,WHOLE_ARRAY); pairs="("+string(arspc)+") Trader Wishes Pairs"; //-- break; } case 2: // USD pairs { ArrayResize(DIRI,arusd,arusd); arrsymbx=arusd; ArraySymbolResize(); ArrayCopy(DIRI,USDs,0,0,WHOLE_ARRAY); pairs="("+string(arusd)+") Multi Currency USD Pairs"; //-- break; } case 3: // EUR pairs { ArrayResize(DIRI,areur,areur); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,EURs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex EUR Pairs"; //-- break; } case 4: // GBP pairs { ArrayResize(DIRI,aretc,aretc); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,GBPs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex GBP Pairs"; //-- break; } case 5: // AUD pairs { ArrayResize(DIRI,aretc,aretc); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,AUDs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex AUD Pairs"; //-- break; } case 6: // NZD pairs { ArrayResize(DIRI,aretc,aretc); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,NZDs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex NZD Pairs"; //-- break; } case 7: // CAD pairs { ArrayResize(DIRI,aretc,aretc); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,CADs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex CAD Pairs"; //-- break; } case 8: // CHF pairs { ArrayResize(DIRI,aretc,aretc); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,CHFs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex CHF Pairs"; //-- break; } case 9: // JPY pairs { ArrayResize(DIRI,aretc,aretc); arrsymbx=aretc; ArraySymbolResize(); ArrayCopy(DIRI,JPYs,0,0,WHOLE_ARRAY); pairs="("+string(aretc)+") Forex JPY Pairs"; //-- break; } } //-- return; //--- } //-end HandlingSymbolArrays() //---------//
Innerhalb der Funktion HandlingSymbolArrays() rufen wir die Funktion SetSymbolNamePS() auf. Mit SetSymbolNamePS() werden wir in der Lage sein, Symbolnamen mit Präfixen und/oder Suffixen zu behandeln.
void MCEA::SetSymbolNamePS(void) { //--- int sym_Lenpre=0; int sym_Lensuf=0; string sym_pre=""; string sym_suf=""; SymbolSelect(Symbol(),true); string insymbol=Symbol(); int inlen=StringLen(insymbol); int toseek=-1; string dep=""; string bel=""; string sym_use =""; int pairx=-1; string xcur[]={"EUR","GBP","AUD","NZD","USD","CAD","CHF"}; // 7 major currency int xcar=ArraySize(xcur); //-- for(int x=0; x<xcar; x++) { toseek=StringFind(insymbol,xcur[x],0); if(toseek>=0) { pairx=x; break; } } if(pairx>=0) { int awl=toseek-3 <0 ? 0 : toseek-3; int sd=StringFind(insymbol,"SD",0); if(toseek==0 && sd<4) { dep=StringSubstr(insymbol,toseek,3); bel=StringSubstr(insymbol,toseek+3,3); sym_use=dep+bel; } else if(toseek>0) { dep=StringSubstr(insymbol,toseek,3); bel=StringSubstr(insymbol,toseek+3,3); sym_use=dep+bel; } else { dep=StringSubstr(insymbol,awl,3); bel=StringSubstr(insymbol,awl+3,3); sym_use=dep+bel; } } //-- string sym_nmx=sym_use; int lensx=StringLen(sym_nmx); //-- if(inlen>lensx && lensx==6) { sym_Lenpre=StringFind(insymbol,sym_nmx,0); sym_Lensuf=inlen-lensx-sym_Lenpre; //-- if(sym_Lenpre>0) { sym_pre=StringSubstr(insymbol,0,sym_Lenpre); for(int i=0; i<xcar; i++) if(StringFind(sym_pre,xcur[i],0)>=0) sym_pre=""; } if(sym_Lensuf>0) { sym_suf=StringSubstr(insymbol,sym_Lenpre+lensx,sym_Lensuf); for(int i=0; i<xcar; i++) if(StringFind(sym_suf,xcur[i],0)>=0) sym_suf=""; } } //-- pre=sym_pre; suf=sym_suf; inpre=StringLen(pre); insuf=StringLen(suf); posCur1=inpre; posCur2=posCur1+3; //-- return; //--- } //-end SetSymbolNamePS() //---------//
Hinweis: Der Experte validiert die Paare. Wenn der Händler bei der Eingabe des Paarnamens einen Fehler macht (Tippfehler) oder wenn die Paarvalidierung fehlschlägt, erhält der Experte eine Warnung und der Expertenberater wird vom Chart entfernt.
In der Experten-Eingabeeigenschaftsgruppe Trade on Specific Time (Handel zu bestimmten Zeiten) kann der Händler wählen, ob er in einer bestimmten Zeitzone handeln möchte (Yes) oder (No).
Wenn die Option „Trade on Specific Time Zone“ (Handel in einer bestimmten Zeitzone) auf „No“ eingestellt ist, handelt der Experte von MT5 00:15 bis 23:59 Uhr.
Wenn Ja, dann wählen Sie die Enumerations-Optionen:
- Trading on Custom Session (Handel während einer nutzerdefinierten Sitzung)
- Trading on New Zealand Session (Handel während der neuseeländischen Sitzung)
- Trading on Australia Sydney Session (Handel während der Australien Sydney Session)
- Trading on Asia Tokyo Session (Handel während der Asien Tokyo Session)
- Trading on Europe London Session (Handel während der Europa London Session)
- Trading on America New York Session (Handel während der Amerika New York Session)
Standardmäßig ist der Handel in bestimmten Zeitzonen auf „Yes“ und auf Handel in nutzerdefinierten Sitzungen eingestellt.
Handel während der Custom Session:
In dieser Sitzung müssen die Händler die Zeit oder die Stunden und Minuten für den Handelsbeginn und die Stunden und Minuten für das Handelsende festlegen. Das bedeutet, dass der EA nur während des angegebenen Zeitraums vom Start bis zum Ende Aktivitäten durchführt.
In der Zwischenzeit wird in der New Zealand Trading Session bis zur New York US Trading Session die Zeit vom Beginn des Handels bis zum Ende des Handels vom EA berechnet.
Klasse für funktionierenden Expert Advisor
Um den Expert Advisor-Workflow zu erstellen und zu konfigurieren, haben wir eine Klasse erstellt, die alle Variablen, Objekte und Funktionen deklariert, die für einen Expert Advisor mit mehreren Währungen erforderlich sind.
//+------------------------------------------------------------------+ //| Class for working Expert Advisor | //+------------------------------------------------------------------+ class MCEA { //--- private: //---- int x_year; // Year int x_mon; // Month int x_day; // Day of the month int x_hour; // Hour in a day int x_min; // Minutes int x_sec; // Seconds //-- int oBm, oSm, ldig; //--- Variables used in prefix and suffix symbols int posCur1, posCur2; int inpre, insuf; bool symbfix; string pre,suf; string prefix,suffix; //--- Variables are used in Trading Time Zone int ishour, onhour; int tftrlst, tfcinws; datetime rem, znop, zncl, zntm; datetime SesCuOp, SesCuCl, Ses01Op, Ses01Cl, Ses02Op, Ses02Cl, Ses03Op, Ses03Cl, Ses04Op, Ses04Cl, Ses05Op, Ses05Cl, SesNoOp, SesNoCl; //-- string tz_ses, tz_opn, tz_cls; //-- string tmopcu, tmclcu, tmop01, tmcl01, tmop02, tmcl02, tmop03, tmcl03, tmop04, tmcl04, tmop05, tmcl05, tmopno, tmclno; //---------------------- //-- double LotPS; double point; double slv, tpv, pip, xpip; double SARstep, SARmaxi; double floatprofit, fixclprofit; //-- string pairs, hariini, daytrade, trade_mode; //-- double OPEN[], HIGH[], LOW[], CLOSE[]; datetime TIME[]; datetime closetime; //-- //------------ //------------ void SetSymbolNamePS(void); void HandlingSymbolArrays(void); void Set_Time_Zone(void); void Time_Zone(void); bool Trade_session(void); string PosTimeZone(void); int ThisTime(const int reqmode); int ReqTime(datetime reqtime,const int reqmode); //-- int DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf); int GetRSIxx(const string symbol); int PARSAR05(const string symbol); int PARSAR15(const string symbol); int LotDig(const string symbol); //-- bool CheckProfit(const string symbol,ENUM_POSITION_TYPE intype); bool CheckLoss(const string symbol,ENUM_POSITION_TYPE intype); //-- double MLots(const string symbx); double NonZeroDiv(double val1,double val2); double OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice); double OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice); double SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice); double SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice); double TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type); //-- string ReqDate(int d,int h,int m); string TF2Str(ENUM_TIMEFRAMES period); string timehr(int hr,int mn); string TradingDay(void); string AccountMode(); string GetCommentForOrder(void) { return(expname); } //------------ public: //--- //-- RSIxRSI_MCEA Config -- string DIRI[], AS30[], VSym[]; string SPC[]; string USD[]; string EUR[]; string GBP[]; string AUD[]; string NZD[]; string CAD[]; string CHF[]; string JPY[]; //-- string expname; //-- int hRSIFast[], hRSISlow[]; int hVIDyAv[]; int hPar05[], hPar15[]; int ALO, dgts, arrsar, arrsymbx; int sall, arusd, areur, aretc, arspc, arper; ulong slip; //-- double profitb[], profits[]; double minprofit; //-- int Buy, Sell; int ccur, psec, xtto, checktml; int OpOr[],xob[],xos[]; //-- int year, // Year mon, // Month day, // Day hour, // Hour min, // Minutes sec, // Seconds dow, // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) doy; // Day number of the year (January 1st is assigned the number value of zero) //-- ENUM_TIMEFRAMES TFt, TFT05, TFT15; //-- bool PanelExtra; //------------ MCEA(void); ~MCEA(void); //------------ //-- virtual void RSIxRSI_MCEA_Config(void); virtual void ExpertActionTrade(void); //-- void ArraySymbolResize(void); void CurrentSymbolSet(const string symbol); void Pips(const string symbol); void TradeInfo(void); void Do_Alerts(const string symbx,string msgText); void CheckOpenPMx(const string symbx); void SetSLTPOrders(void); void CloseAllOrders(void); void CheckClose(const string symbx); void TodayOrders(void); void UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf); void RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars); //-- bool RefreshTick(const string symbx); bool TradingToday(void); bool OpenBuy(const string symbol); bool OpenSell(const string symbol); bool ModifyOrderSLTP(double mStop,double ordtp); bool ModifySLTP(const string symbx,int TS_type); bool CloseAllProfit(void); bool ManualCloseAllProfit(void); bool CheckProfitLoss(const string symbol); bool CloseBuyPositions(const string symbol); bool CloseSellPositions(const string symbol); //-- int PairsIdxArray(const string symbol); int ValidatePairs(const string symbol); int GetOpenPosition(const string symbol); int GetCloseInWeakSignal(const string symbol,int exis); //-- string getUninitReasonText(int reasonCode); //-- //------------ //--- }; //-end class MCEA //---------// MCEA mc; //---------//
Die erste und wichtigste Funktion im Arbeitsablauf des Multi-Currency Expert Advisors wird vom OnInit() aufgerufen: RSIxRSI_MCEA_Config().
Die Funktion RSIxRSI_MCEA_Config() konfiguriert alle zu verwendenden Symbole, alle Timeframes, alle Handle-Indikatoren und einige wichtige Funktionen des Include-Dateikopfes für den Expert Advisor Workflow.
Die Funktion RSIxRSI_MCEA_Config() beschreibt und implementiert die Handhabung von Zeitrahmen und die Erstellung von Indikator-Handles für alle im Expert Advisor Workflow verwendeten Indikatoren.
//+------------------------------------------------------------------+ //| Expert Configuration | //+------------------------------------------------------------------+ void MCEA::RSIxRSI_MCEA_Config(void) { //--- //-- HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded //-- TFT05=PERIOD_M5; TFT15=PERIOD_M15; ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1}; int arTFs=ArraySize(TFs); //-- for(int x=0; x<arTFs; x++) if(tfinuse==x) TFt=TFs[x]; // TF for calculation signal //-- //-- Indicators handle for all symbol for(int x=0; x<arrsymbx; x++) { hRSISlow[x]=iRSI(DIRI[x],TFt,rsislow,srsiapp); //-- Handle for the Slow RSI indicator hRSIFast[x]=iRSI(DIRI[x],TFt,rsifast,frsiapp); //-- Handle for the Fast RSI indicator hVIDyAv[x]=iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED); //-- Handle for the VIDYA indicator for Trailing Stop hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi); //-- Handle for the iSAR indicator for M5 Timeframe hPar15[x]=iSAR(DIRI[x],TFT15,SARstep,SARmaxi); //-- Handle for the iSAR indicator for M15 Timeframe //-- } //-- minprofit=NormalizeDouble(TSmin/100.0,2); //-- ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders(); if(Close_by_Opps==No) { if((int)mc_account.LimitOrders()>=(sall*2)) ALO=sall*2; else ALO=(int)(mc_account.LimitOrders()/2); } //-- LotPS=(double)ALO; //-- mc_trade.SetExpertMagicNumber(magicEA); mc_trade.SetDeviationInPoints(slip); mc_trade.SetMarginMode(); Set_Time_Zone(); //-- return; //--- } //-end RSIxRSI_MCEA_Config() //---------//
2. Die Funktion OnTick() des Experten
Innerhalb der Expert Tick Funktion OnTick() werden wir eine der wichtigsten Funktionen in einem Multi-Currency Expert Advisor aufrufen, nämlich die ExpertActionTrade() Funktion. Der gesamte Prozess der EA-Arbeit für den Handel ist in dieser Funktion enthalten.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(void) { //--- mc.ExpertActionTrade(); //-- return; //--- } //-end OnTick() //---------//
Das bedeutet, dass der ExpertActionTrade()-Befehl alle Aktivitäten durchführt und den automatischen Handel verwaltet, angefangen von Eröffnungs-, Schließaufträgen, Trailing-Stops oder Trailing-Profits und anderen zusätzlichen Aktivitäten.
void MCEA::ExpertActionTrade(void) { //--- //--Check Trading Terminal ResetLastError(); //-- if(!MQLInfoInteger(MQL_TRADE_ALLOWED) && mc.checktml==0) //-- Check whether MT5 Algorithmic trading is Allow or Prohibit { mc.Do_Alerts(Symbol(),"Trading Expert at "+Symbol()+" are NOT Allowed by Setting."); mc.checktml=1; //-- Variable checktml is given a value of 1, so that the alert is only done once. return; } //-- if(!DisplayManualButton("M","C","R")) DisplayManualButton(); //-- Show the expert manual button panel //-- if(trade_info_display==Yes) mc.TradeInfo(); //-- Displayed Trading Info on Chart //--- //-- int mcsec=mc.ThisTime(mc.sec); //-- if(fmod((double)mcsec,5.0)==0) mc.ccur=mcsec; //-- if(mc.ccur!=mc.psec) { string symbol; //-- Here we start with the rotation of the name of all symbol or pairs to be traded for(int x=0; x<mc.arrsymbx && !IsStopped(); x++) { //-- switch(trademode) { case SP: { if(mc.DIRI[x]!=Symbol()) continue; symbol=Symbol(); mc.pairs=mc.pairs+" ("+symbol+")"; break; } case MP: { if(mc.DIRI[x]==Symbol()) symbol=Symbol(); else symbol=mc.DIRI[x]; break; } } //-- mc.CurrentSymbolSet(symbol); //-- if(mc.TradingToday() && mc.Trade_session()) { //-- mc.OpOr[x]=mc.GetOpenPosition(symbol); //-- Get trading signals to open positions //-- //-- and store in the variable OpOr[x] if(mc.OpOr[x]==mc.Buy) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Buy" (value=1) { //-- mc.CheckOpenPMx(symbol); //-- if(Close_by_Opps==Yes && mc.xos[x]>0) mc.CloseSellPositions(symbol); //-- if(mc.xob[x]==0 && mc.xtto<mc.ALO) mc.OpenBuy(symbol); else if(mc.xtto>=mc.ALO) { //-- mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+ "\n the limit = "+string(mc.ALO)+" Orders "); //-- mc.CheckOpenPMx(symbol); //-- if(mc.xos[x]>0 && mc.profits[x]<-1.02 && mc.xob[x]==0) {mc.CloseSellPositions(symbol); mc.OpenBuy(symbol);} else if(SaveOnRev==Yes) mc.CloseAllProfit(); } } if(mc.OpOr[x]==mc.Sell) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Sell" (value=-1) { //-- mc.CheckOpenPMx(symbol); //-- if(Close_by_Opps==Yes && mc.xob[x]>0) mc.CloseBuyPositions(symbol); //-- if(mc.xos[x]==0 && mc.xtto<mc.ALO) mc.OpenSell(symbol); else if(mc.xtto>=mc.ALO) { //-- mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+ "\n the limit = "+string(mc.ALO)+" Orders "); //-- mc.CheckOpenPMx(symbol); //-- if(mc.xob[x]>0 && mc.profitb[x]<-1.02 && mc.xos[x]==0) {mc.CloseBuyPositions(symbol); mc.OpenSell(symbol);} else if(SaveOnRev==Yes) mc.CloseAllProfit(); } } } //-- mc.CheckOpenPMx(symbol); //-- if(mc.xtto>0) { //-- if(SaveOnRev==Yes) //-- Close Trade and Save profit due to weak signal (Yes) { mc.CheckOpenPMx(symbol); if(mc.profitb[x]>mc.minprofit && mc.xob[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Buy)==mc.Sell) { mc.CloseBuyPositions(symbol); mc.Do_Alerts(symbol,"Close BUY order "+symbol+" to save profit due to weak signal."); } if(mc.profits[x]>mc.minprofit && mc.xos[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Sell)==mc.Buy) { mc.CloseSellPositions(symbol); mc.Do_Alerts(symbol,"Close SELL order "+symbol+" to save profit due to weak signal."); } } //-- if(TrailingSLTP==Yes) //-- Use Trailing SL/TP (Yes) { mc.ModifySLTP(symbol,trlby); } } //-- mc.CheckOpenPMx(symbol); if(Close_by_Opps==No && (mc.xob[x]+mc.xos[x]>1)) { mc.CheckProfitLoss(symbol); mc.Do_Alerts(symbol,"Close order due stop in loss."); } //-- mc.CheckClose(symbol); } //-- mc.psec=mc.ccur; } //-- return; //--- } //-end ExpertActionTrade() //---------//
Die Eigenschaftsgruppe Day Trading On/Off ermöglicht es Händlern, an bestimmten Tagen von Sonntag bis Samstag zu handeln. Hier können Händler mit den Optionen (Yes) oder (No) Experten für den Handel an einem bestimmten Tag aktivieren oder deaktivieren.
//--Day Trading On/Off input group "=== Day Trading On/Off ==="; // Day Trading On/Off input YN ttd0 = No; // Select Trading on Sunday (Yes) or (No) input YN ttd1 = Yes; // Select Trading on Monday (Yes) or (No) input YN ttd2 = Yes; // Select Trading on Tuesday (Yes) or (No) input YN ttd3 = Yes; // Select Trading on Wednesday (Yes) or (No) input YN ttd4 = Yes; // Select Trading on Thursday (Yes) or (No) input YN ttd5 = Yes; // Select Trading on Friday (Yes) or (No) input YN ttd6 = No; // Select Trading on Saturday (Yes) or (No)
Die Ausführung für den Day Trading On/Off ist wie folgt:
bool MCEA::TradingToday(void) { //--- bool tradetoday=false; int trdday=ThisTime(dow); hariini="No"; //-- int ttd[]; ArrayResize(ttd,7); ttd[0]=ttd0; ttd[1]=ttd1; ttd[2]=ttd2; ttd[3]=ttd3; ttd[4]=ttd4; ttd[5]=ttd5; ttd[6]=ttd6; //-- if(ttd[trdday]==Yes) {tradetoday=true; hariini="Yes";} //-- return(tradetoday); //--- } //-end TradingToday() //---------//
Anmerkungen: Die Bedingungen für den Tageshandel (Day Trading On/Off) werden in der Handelsinfo im Chart angezeigt.
Sie wird von der Funktion TradingDay() ausgeführt.
string MCEA::TradingDay(void) { //--- int trdday=ThisTime(dow); switch(trdday) { case 0: daytrade="Sunday"; break; case 1: daytrade="Monday"; break; case 2: daytrade="Tuesday"; break; case 3: daytrade="Wednesday"; break; case 4: daytrade="Thursday"; break; case 5: daytrade="Friday"; break; case 6: daytrade="Saturday"; break; } return(daytrade); //--- } //-end TradingDay() //---------//
Händler haben die Möglichkeit, in der Eigenschaftsgruppe „Trade at Specific Time“ des Expert Advisors nach Zeitzonen zu handeln.
Anmerkungen: Wie oben erläutert, wird im Falle des Handels an der New Zealand Session zum Handel an der US New York Session die Zeit vom Beginn des Handels bis zum Ende des Handels vom EA berechnet.
Daher müssen Händler in den Eigenschaften des Experteneintrags nur die Zeit für die Stunde und Minute des Handelsbeginns und die Zeit für die Stunde und Minute des Handelsendes für die nutzerdefinierte Sitzung festlegen.
Die Funktion ExpertActionTrade() wurde um einen Aufruf der booleschen Funktion Trade_session() speziell für den Zeitzonenhandel erweitert.
Wenn Trade_session() true ist, dann wird der EA-Arbeitsprozess fortgesetzt, bis er beendet ist, aber wenn er false ist, dann wird der EA nur die Aufgaben „Close Trade and Save Profit due to Weak Signal if it is (Yes)“ (Schließen der Position und Sichern des Gewinns aufgrund schwachen Signals, wenn es (Yes) ist) und „Trailing Stop if it is (Yes)“ (Trailing Stop, wenn ja (Yes)) ausführen.
bool MCEA::Trade_session(void) { //--- bool trd_ses=false; ishour=ThisTime(hour); if(ishour!=onhour) Set_Time_Zone(); datetime tcurr=TimeCurrent(); // Server Time //-- switch(session) { case Cus_Session: { if(tcurr>=SesCuOp && tcurr<=SesCuCl) trd_ses=true; break; } case New_Zealand: { if(tcurr>=Ses01Op && tcurr<=Ses01Cl) trd_ses=true; break; } case Australia: { if(tcurr>=Ses02Op && tcurr<=Ses02Cl) trd_ses=true; break; } case Asia_Tokyo: { if(tcurr>=Ses03Op && tcurr<=Ses03Cl) trd_ses=true; break; } case Europe_London: { if(tcurr>=Ses04Op && tcurr<=Ses04Cl) trd_ses=true; break; } case US_New_York: { if(tcurr>=Ses05Op && tcurr<=Ses05Cl) trd_ses=true; break; } } //-- if(trd_time_zone==No) { if(tcurr>=SesNoOp && tcurr<=SesNoCl) trd_ses=true; } //-- onhour=ishour; //-- return(trd_ses); //--- } //-end Trade_session() //---------//
Der Arbeitsablauf in Trade at Specific Time sieht folgendermaßen aus: Zuerst ruft die Funktion ExpertActionTrade() die Funktion Trade_session() auf, dann ruft die Funktion Trade_session() die Funktion Set_Time_Zone() auf, und schließlich ruft die Funktion Set_Time_Zone() die Funktion Time_Zone() auf.
void MCEA::Set_Time_Zone(void) { //--- //-- Server Time==TimeCurrent() datetime TTS=TimeTradeServer(); datetime GMT=TimeGMT(); //-- MqlDateTime svrtm,gmttm; TimeToStruct(TTS,svrtm); TimeToStruct(GMT,gmttm); int svrhr=svrtm.hour; // Server time hour int gmthr=gmttm.hour; // GMT time hour int difhr=svrhr-gmthr; // Time difference Server time to GMT time //-- int NZSGMT=12; // New Zealand Session GMT/UTC+12 int AUSGMT=10; // Australia Sydney Session GMT/UTC+10 int TOKGMT=9; // Asia Tokyo Session GMT/UTC+9 int EURGMT=0; // Europe London Session GMT/UTC 0 int USNGMT=-5; // US New York Session GMT/UTC-5 //-- int NZSStm=8; // New Zealand Session time start: 08:00 Local Time int NZSCtm=17; // New Zealand Session time close: 17:00 Local Time int AUSStm=7; // Australia Sydney Session time start: 07:00 Local Time int AUSCtm=17; // Australia Sydney Session time close: 17:00 Local Time int TOKStm=9; // Asia Tokyo Session time start: 09:00 Local Time int TOKCtm=18; // Asia Tokyo Session time close: 18:00 Local Time int EURStm=9; // Europe London Session time start: 09:00 Local Time int EURCtm=19; // Europe London Session time close: 19:00 Local Time int USNStm=8; // US New York Session time start: 08:00 Local Time int USNCtm=17; // US New York Session time close: 17:00 Local Time //-- int nzo = (NZSStm+difhr-NZSGMT)<0 ? 24+(NZSStm+difhr-NZSGMT) : (NZSStm+difhr-NZSGMT); int nzc = (NZSCtm+difhr-NZSGMT)<0 ? 24+(NZSCtm+difhr-NZSGMT) : (NZSCtm+difhr-NZSGMT); //-- int auo = (AUSStm+difhr-AUSGMT)<0 ? 24+(AUSStm+difhr-AUSGMT) : (AUSStm+difhr-AUSGMT); int auc = (AUSCtm+difhr-AUSGMT)<0 ? 24+(AUSCtm+difhr-AUSGMT) : (AUSCtm+difhr-AUSGMT); //-- int tko = (TOKStm+difhr-TOKGMT)<0 ? 24+(TOKStm+difhr-TOKGMT) : (TOKStm+difhr-TOKGMT); int tkc = (TOKCtm+difhr-TOKGMT)<0 ? 24+(TOKCtm+difhr-TOKGMT) : (TOKCtm+difhr-TOKGMT); //-- int euo = (EURStm+difhr-EURGMT)<0 ? 24+(EURStm+difhr-EURGMT) : (EURStm+difhr-EURGMT); int euc = (EURCtm+difhr-EURGMT)<0 ? 24+(EURCtm+difhr-EURGMT) : (EURCtm+difhr-EURGMT); //-- int uso = (USNStm+difhr-USNGMT)<0 ? 24+(USNStm+difhr-USNGMT) : (USNStm+difhr-USNGMT); int usc = (USNCtm+difhr-USNGMT)<0 ? 24+(USNCtm+difhr-USNGMT) : (USNCtm+difhr-USNGMT); if(usc==0||usc==24) usc=23; //-- //---Trading on Custom Session int _days00=ThisTime(day); int _days10=ThisTime(day); if(stsescuh>clsescuh) _days10=ThisTime(day)+1; tmopcu=ReqDate(_days00,stsescuh,stsescum); tmclcu=ReqDate(_days10,clsescuh,clsescum); //-- //--Trading on New Zealand Session GMT/UTC+12 int _days01=ThisTime(hour)<nzc ? ThisTime(day)-1 : ThisTime(day); int _days11=ThisTime(hour)<nzc ? ThisTime(day) : ThisTime(day)+1; tmop01=ReqDate(_days01,nzo,0); // start: 08:00 Local Time == 20:00 GMT/UTC tmcl01=ReqDate(_days11,nzc-1,59); // close: 17:00 Local Time == 05:00 GMT/UTC //-- //--Trading on Australia Sydney Session GMT/UTC+10 int _days02=ThisTime(hour)<auc ? ThisTime(day)-1 : ThisTime(day); int _days12=ThisTime(hour)<auc ? ThisTime(day) : ThisTime(day)+1; tmop02=ReqDate(_days02,auo,0); // start: 07:00 Local Time == 21:00 GMT/UTC tmcl02=ReqDate(_days12,auc-1,59); // close: 17:00 Local Time == 07:00 GMT/UTC //-- //--Trading on Asia Tokyo Session GMT/UTC+9 int _days03=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1; int _days13=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1; tmop03=ReqDate(_days03,tko,0); // start: 09:00 Local Time == 00:00 GMT/UTC tmcl03=ReqDate(_days13,tkc-1,59); // close: 18:00 Local Time == 09:00 GMT/UTC //-- //--Trading on Europe London Session GMT/UTC 00:00 int _days04=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1; int _days14=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1; tmop04=ReqDate(_days04,euo,0); // start: 09:00 Local Time == 09:00 GMT/UTC tmcl04=ReqDate(_days14,euc-1,59); // close: 19:00 Local Time == 19:00 GMT/UTC //-- //--Trading on US New York Session GMT/UTC-5 int _days05=ThisTime(hour)<usc ? ThisTime(day) : ThisTime(day)+1; int _days15=ThisTime(hour)<=usc ? ThisTime(day) : ThisTime(day)+1; tmop05=ReqDate(_days05,uso,0); // start: 08:00 Local Time == 13:00 GMT/UTC tmcl05=ReqDate(_days15,usc,59); // close: 17:00 Local Time == 22:00 GMT/UTC //-- //--Not Use Trading Time Zone if(trd_time_zone==No) { tmopno=ReqDate(ThisTime(day),0,15); tmclno=ReqDate(ThisTime(day),23,59); } //-- Time_Zone(); //-- return; //--- } //-end Set_Time_Zone() //---------//
void MCEA::Time_Zone(void) { //--- //-- tz_ses=""; //-- switch(session) { case Cus_Session: { SesCuOp=StringToTime(tmopcu); SesCuCl=StringToTime(tmclcu); zntm=SesCuOp; znop=SesCuOp; zncl=SesCuCl; tz_ses="Custom_Session"; tz_opn=timehr(stsescuh,stsescum); tz_cls=timehr(clsescuh,clsescum); break; } case New_Zealand: { Ses01Op=StringToTime(tmop01); Ses01Cl=StringToTime(tmcl01); zntm=Ses01Op; znop=Ses01Op; zncl=Ses01Cl; tz_ses="New_Zealand/Oceania"; tz_opn=timehr(ReqTime(Ses01Op,hour),ReqTime(Ses01Op,min)); tz_cls=timehr(ReqTime(Ses01Cl,hour),ReqTime(Ses01Cl,min)); break; } case Australia: { Ses02Op=StringToTime(tmop02); Ses02Cl=StringToTime(tmcl02); zntm=Ses02Op; znop=Ses02Op; zncl=Ses02Cl; tz_ses="Australia Sydney"; tz_opn=timehr(ReqTime(Ses02Op,hour),ReqTime(Ses02Op,min)); tz_cls=timehr(ReqTime(Ses02Cl,hour),ReqTime(Ses02Cl,min)); break; } case Asia_Tokyo: { Ses03Op=StringToTime(tmop03); Ses03Cl=StringToTime(tmcl03); zntm=Ses03Op; znop=Ses03Op; zncl=Ses03Cl; tz_ses="Asia/Tokyo"; tz_opn=timehr(ReqTime(Ses03Op,hour),ReqTime(Ses03Op,min)); tz_cls=timehr(ReqTime(Ses03Cl,hour),ReqTime(Ses03Cl,min)); break; } case Europe_London: { Ses04Op=StringToTime(tmop04); Ses04Cl=StringToTime(tmcl04); zntm=Ses04Op; znop=Ses04Op; zncl=Ses04Cl; tz_ses="Europe/London"; tz_opn=timehr(ReqTime(Ses04Op,hour),ReqTime(Ses04Op,min)); tz_cls=timehr(ReqTime(Ses04Cl,hour),ReqTime(Ses04Cl,min)); break; } case US_New_York: { Ses05Op=StringToTime(tmop05); Ses05Cl=StringToTime(tmcl05); zntm=Ses05Op; znop=Ses05Op; zncl=Ses05Cl; tz_ses="US/New_York"; tz_opn=timehr(ReqTime(Ses05Op,hour),ReqTime(Ses05Op,min)); tz_cls=timehr(ReqTime(Ses05Cl,hour),ReqTime(Ses05Cl,min)); break; } } //-- if(trd_time_zone==No) { SesNoOp=StringToTime(tmopno); SesNoCl=StringToTime(tmclno); zntm=SesNoOp; znop=SesNoOp; zncl=SesNoCl; tz_ses="Not Use Time Zone"; tz_opn=timehr(ReqTime(SesNoOp,hour),ReqTime(SesNoOp,min)); tz_cls=timehr(ReqTime(SesNoCl,hour),ReqTime(SesNoCl,min)); } //-- return; //--- } //-end Time_Zone() //---------//
3. Wie kann ich Handelssignale für offene Positionen erhalten?
Um ein Signal zum Eröffnen einer Position zu erhalten, ruft die Funktion ExpertActionTrade() die Funktion GetOpenPosition() auf.
int MCEA::GetOpenPosition(const string symbol) // Signal Open Position { //--- int ret=0; int rise=1, down=-1; //-- int rsix=GetRSIxx(symbol); int par15=PARSAR15(symbol); //-- if(rsix==rise && par15==rise) ret=rise; if(rsix==down && par15==down) ret=down; //-- return(ret); //--- } //-end GetOpenPosition() //---------//
Und die Funktion GetOpenPosition() wird 2 Funktionen aufrufen:
- GetRSIxx() Funktion, die den Pufferwert von 2 RSI nimmt und den Signalalgorithmus berechnet.
- PARSAR15() Funktion als Filter.
int MCEA::GetRSIxx(const string symbol) // Signal Open Position { //--- int ret=0; int rise=1, down=-1; int bar=3; //-- double rdif=rsidiff; double RSIFast[], RSISlow[]; //-- ArrayResize(RSIFast,bar,bar); ArrayResize(RSISlow,bar,bar); ArraySetAsSeries(RSIFast,true); ArraySetAsSeries(RSISlow,true); //-- int x=PairsIdxArray(symbol); UpdatePrice(symbol,TFt); //-- CopyBuffer(hRSIFast[x],0,0,bar,RSIFast); CopyBuffer(hRSISlow[x],0,0,bar,RSISlow); //-- if(RSIFast[1]<=RSISlow[1] && RSIFast[0]>RSISlow[0]+rdif) ret=rise; if(RSIFast[1]>=RSISlow[1] && RSIFast[0]<RSISlow[0]-rdif) ret=down; //-- return(ret); //--- } //-end GetRSIxx() //---------//
int MCEA::PARSAR15(const string symbol) // formula Parabolic SAR M5 { //--- int ret=0; int rise=1, down=-1; int br=2; //-- double PSAR[]; ArrayResize(PSAR,br,br); ArraySetAsSeries(PSAR,true); int xx=PairsIdxArray(symbol); CopyBuffer(hPar15[xx],0,0,br,PSAR); //-- RefreshPrice(symbol,TFT15,br); double HIG0=iHigh(symbol,TFT15,0); double LOW0=iLow(symbol,TFT15,0); //-- if(PSAR[0]<LOW0) ret=rise; if(PSAR[0]>HIG0) ret=down; //-- return(ret); //--- } //-end PARSAR15() //---------//
Innerhalb der Funktion GetRSIxx() und der Funktion PARSAR15() wird eine Funktion verwendet und aufgerufen, nämlich die FunktionPairsIdxArray().
int xx=PairsIdxArray(symbol);
int MCEA::PairsIdxArray(const string symbol) { //--- int pidx=-1; //-- for(int x=0; x<arrsymbx; x++) { if(DIRI[x]==symbol) { pidx=x; break; } } //-- return(pidx); //--- } //-end PairsIdxArray() //---------//
Die Funktion PairsIdxArray() wird verwendet, um den Namen des gewünschten Symbols und die Handles seiner Indikatoren zu erhalten. Dann wird das entsprechende Indikator-Handle aufgerufen, um den Pufferwert des RSI-Indikators und des PSAR-Indikators für dieses Symbol und diesen Zeitrahmen zu erhalten.
In diesem Expert Advisor werden wir 2 RSI-Indikatoren verwenden.
Sie haben unterschiedliche Eingabeparameter:
Fast RSI:
- symbol = das gewünschte Symbol,
- timeframe = wie im Zeitrahmen des Experten angegeben.
- ma_period = 10, entsprechend der Periodenlänge für Fast RSI
- applied_price = PRICE_WEIGHTED, entsprechend dem Fast RSI Applied Price
Slow RSI:
- symbol = das gewünschte Symbol,
- timeframe = wie im Zeitrahmen des Experten angegeben.
- ma_period = 30,entsprechend der Periodenlänge für Slow RSI
- applied_price = PRICE_WEIGHTED, entsprechend dem Slow RSI Applied Price
//-- Indicators handle for all symbol for(int x=0; x<arrsymbx; x++) { hRSISlow[x]=iRSI(DIRI[x],TFt,rsislow,srsiapp); //-- Handle for the Slow RSI indicator hRSIFast[x]=iRSI(DIRI[x],TFt,rsifast,frsiapp); //-- Handle for the Fast RSI indicator hVIDyAv[x]=iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED); //-- Handle for the VIDYA indicator for Trailing Stop hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi); //-- Handle for the iSAR indicator for M5 Timeframe //-- }
Um also den Pufferwert für jeden RSI-Indikator zu erhalten, kopieren wir jeden Puffer aus dem Indikatoren-Handle.
Kopieren des Fast RSI-Puffers (Puffer 0) vom Fast-RSI-Handle in das Ziel-Array:
CopyBuffer(hRSIFast[x],0,0,bar,RSIFast);
Kopieren des Slow RSI-Puffers (Puffer 0) vom langsamen RSI-Handle in das Ziel-Array:
CopyBuffer(hRSISlow[x],0,0,bar,RSISlow);
Nach Ausführung der beiden Funktionen GetRSIxx() und PARSAR05() liefert die Funktion GetOpenPosition() die Werte:
- Wert 0, Signal unbekannt.
- Der Wert 1 ist das Signal für einen Kaufauftrag;
- Der Wert -1 ist das Signal für einen Verkaufsauftrag.
Wenn die Funktion GetOpenPosition() den Wert 1 zurückgibt, ruft der Expert Advisor die Funktion OpenBuy() auf, um eine Kauforder zu eröffnen.
bool MCEA::OpenBuy(const string symbol) { //--- ResetLastError(); //-- bool buyopen = false; string ldComm = GetCommentForOrder()+"_Buy"; double ldLot = MLots(symbol); ENUM_ORDER_TYPE type_req = ORDER_TYPE_BUY; //-- MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- structure is set to zero ZeroMemory(req); ZeroMemory(res); ZeroMemory(check); //-- CurrentSymbolSet(symbol); double SL=OrderSLSet(symbol,type_req,mc_symbol.Bid()); double TP=OrderTPSet(symbol,type_req,mc_symbol.Ask()); //-- if(RefreshTick(symbol)) buyopen=mc_trade.Buy(ldLot,symbol,mc_symbol.Ask(),SL,TP,ldComm); //-- int error=GetLastError(); if(buyopen||error==0) { string bsopen="Open BUY Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!"; Do_Alerts(symbol,bsopen); } else { mc_trade.CheckResult(check); Do_Alerts(Symbol(),"Open BUY order for "+symbol+" FAILED!!. Return code= "+ (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]"); return(false); } //-- return(buyopen); //-- //--- } //-end OpenBuy //---------//
Wenn die Funktion GetOpenPosition() den Wert -1 zurückgibt, ruft der Expert Advisor die Funktion OpenSell() auf, um eine Verkaufsorder zu eröffnen.
bool MCEA::OpenSell(const string symbol) { //--- ResetLastError(); //-- bool selopen = false; string sdComm = GetCommentForOrder()+"_Sell"; double sdLot = MLots(symbol); ENUM_ORDER_TYPE type_req = ORDER_TYPE_SELL; //-- MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- structure is set to zero ZeroMemory(req); ZeroMemory(res); ZeroMemory(check); //-- CurrentSymbolSet(symbol); double SL=OrderSLSet(symbol,type_req,mc_symbol.Ask()); double TP=OrderTPSet(symbol,type_req,mc_symbol.Bid()); //-- if(RefreshTick(symbol)) selopen=mc_trade.Sell(sdLot,symbol,mc_symbol.Bid(),SL,TP,sdComm); //-- int error=GetLastError(); if(selopen||error==0) { string bsopen="Open SELL Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!"; Do_Alerts(symbol,bsopen); } else { mc_trade.CheckResult(check); Do_Alerts(Symbol(),"Open SELL order for "+symbol+" FAILED!!. Return code= "+ (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]"); return(false); } //-- return(selopen); //-- //--- } //-end OpenSell //---------//
4. Die Funktion ChartEvent
Um die Effektivität und Effizienz bei der Verwendung von Multi-Currency Expert Advisors zu unterstützen, wird es als notwendig erachtet, eine oder mehrere manuelle Schaltflächen für die Verwaltung von Aufträgen und die Änderung von Charts, Zeitrahmen oder Symbolen zu erstellen.
//+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- //--- handling CHARTEVENT_CLICK event ("Clicking the chart") ResetLastError(); //-- ENUM_TIMEFRAMES CCS=mc.TFt; //-- if(id==CHARTEVENT_OBJECT_CLICK) { int lensymbol=StringLen(Symbol()); int lensparam=StringLen(sparam); //-- //--- if "Set SL All Orders" button is click if(sparam=="Set SL/TP All Orders") { mc.SetSLTPOrders(); Alert("-- "+mc.expname+" -- ",Symbol()," -- Set SL/TP All Orders"); //--- unpress the button ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_STATE,false); ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_ZORDER,0); CreateManualPanel(); } //--- if "Close All Order" button is click if(sparam=="Close All Order") { mc.CloseAllOrders(); Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Orders"); //--- unpress the button ObjectSetInteger(0,"Close All Order",OBJPROP_STATE,false); ObjectSetInteger(0,"Close All Order",OBJPROP_ZORDER,0); CreateManualPanel(); } //--- if "Close All Profit" button is click if(sparam=="Close All Profit") { mc.ManualCloseAllProfit(); Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Profit"); //--- unpress the button ObjectSetInteger(0,"Close All Profit",OBJPROP_STATE,false); ObjectSetInteger(0,"Close All Profit",OBJPROP_ZORDER,0); CreateManualPanel(); } //--- if "X" button is click if(sparam=="X") { ObjectsDeleteAll(0,0,OBJ_BUTTON); ObjectsDeleteAll(0,0,OBJ_LABEL); ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL); //--- unpress the button ObjectSetInteger(0,"X",OBJPROP_STATE,false); ObjectSetInteger(0,"X",OBJPROP_ZORDER,0); //-- DeleteButtonX(); mc.PanelExtra=false; DisplayManualButton(); } //--- if "M" button is click if(sparam=="M") { //--- unpress the button ObjectSetInteger(0,"M",OBJPROP_STATE,false); ObjectSetInteger(0,"M",OBJPROP_ZORDER,0); mc.PanelExtra=true; CreateManualPanel(); } //--- if "C" button is click if(sparam=="C") { //--- unpress the button ObjectSetInteger(0,"C",OBJPROP_STATE,false); ObjectSetInteger(0,"C",OBJPROP_ZORDER,0); mc.PanelExtra=true; CreateSymbolPanel(); } //--- if "R" button is click if(sparam=="R") { Alert("-- "+mc.expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart."); ExpertRemove(); //--- unpress the button ObjectSetInteger(0,"R",OBJPROP_STATE,false); ObjectSetInteger(0,"R",OBJPROP_ZORDER,0); if(!ChartSetSymbolPeriod(0,Symbol(),Period())) ChartSetSymbolPeriod(0,Symbol(),Period()); DeletePanelButton(); ChartRedraw(0); } //--- if Symbol button is click if(lensparam==lensymbol) { int sx=mc.ValidatePairs(sparam); ChangeChartSymbol(mc.AS30[sx],CCS); mc.PanelExtra=false; } //-- } //-- return; //--- } //-end OnChartEvent() //---------//
In der Gruppe Other Expert Advisor Parameters der Eingabeeigenschaften kann der Händler auswählen, ob Handelsinformationen auf dem Chart angezeigt werden sollen (Yes) oder (No).
Wenn diese Option ausgewählt ist (Yes), werden die Handelsinformationen auf dem Chart angezeigt, auf dem der Expert Advisor durch Aufruf der Funktion TradeInfo() läuft.
Wir haben auch eine Funktion hinzugefügt, um die Zeit gemäß den Bedingungen der Handelszeitzone als Teil der Funktion TradeInfo() zu beschreiben.
string MCEA::PosTimeZone(void) { //--- string tzpos=""; //-- if(ReqTime(zntm,day)>ThisTime(day)) { tzpos=tz_opn+ " Next day to " +tz_cls + " Next day"; } else if(TimeCurrent()<znop) { if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)==ReqTime(zncl,day)) tzpos=tz_opn+" to " +tz_cls+ " Today"; //else if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day)) tzpos=tz_opn+ " Today to " +tz_cls+ " Next day"; } else if(TimeCurrent()>=znop && TimeCurrent()<zncl) { if(ThisTime(day)<ReqTime(zncl,day)) tzpos=tz_opn+ " Today to " +tz_cls+ " Next day"; else if(ThisTime(day)==ReqTime(zncl,day)) tzpos=tz_opn+" to " +tz_cls+ " Today"; } else if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day)) { tzpos=tz_opn+" Today to " +tz_cls+ " Next day"; } //-- return(tzpos); //---- } //-end PosTimeZone() //---------//
void MCEA::TradeInfo(void) // function: write comments on the chart { //---- Pips(Symbol()); double spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)/xpip; rem=zntm-TimeCurrent(); string postime=PosTimeZone(); string eawait=" - Waiting for active time..!"; //-- string comm=""; TodayOrders(); //-- comm="\n :: Server Date Time : "+string(ThisTime(year))+"."+string(ThisTime(mon))+"."+string(ThisTime(day))+ " "+TimeToString(TimeCurrent(),TIME_SECONDS)+ "\n ------------------------------------------------------------"+ "\n :: Broker : "+ TerminalInfoString(TERMINAL_COMPANY)+ "\n :: Expert Name : "+ expname+ "\n :: Acc. Name : "+ mc_account.Name()+ "\n :: Acc. Number : "+ (string)mc_account.Login()+ "\n :: Acc. TradeMode : "+ AccountMode()+ "\n :: Acc. Leverage : 1 : "+ (string)mc_account.Leverage()+ "\n :: Acc. Equity : "+ DoubleToString(mc_account.Equity(),2)+ "\n :: Margin Mode : "+ (string)mc_account.MarginModeDescription()+ "\n :: Magic Number : "+ string(magicEA)+ "\n :: Trade on TF : "+ EnumToString(TFt)+ "\n :: Today Trading : "+ TradingDay()+" : "+hariini+ "\n :: Trading Session : "+ tz_ses+ "\n :: Trading Time : "+ postime; if(TimeCurrent()<zntm) { comm=comm+ "\n :: Time Remaining : "+(string)ReqTime(rem,hour)+":"+(string)ReqTime(rem,min)+":"+(string)ReqTime(rem,sec) + eawait; } comm=comm+ "\n ------------------------------------------------------------"+ "\n :: Trading Pairs : "+pairs+ "\n :: BUY Market : "+string(oBm)+ "\n :: SELL Market : "+string(oSm)+ "\n :: Total Order : "+string(oBm+oSm)+ "\n :: Order Profit : "+DoubleToString(floatprofit,2)+ "\n :: Fixed Profit : "+DoubleToString(fixclprofit,2)+ "\n :: Float Money : "+DoubleToString(floatprofit,2)+ "\n :: Nett Profit : "+DoubleToString(floatprofit+fixclprofit,2); //-- Comment(comm); ChartRedraw(0); return; //---- } //-end TradeInfo() //---------//
Die Schnittstelle des Multi-Currency Expert Advisors RSIxRSI_MCEA ist in der folgenden Abbildung dargestellt.
Wie Sie sehen können, befinden sich unter dem Namen des Expert Advisors RSIxRSI_MCEA die Schaltflächen „M“, „C“ und „R“.
Wenn Sie auf die Schaltfläche „M“ klicken, wird ein Feld mit Schaltflächen zum manuellen Klicken angezeigt (siehe unten).
Der Händler kann Aufträge manuell verwalten, wenn die Schaltfläche für manuelle Klicks angezeigt wird:
1. Set SL/TP All Orders (SL/TP für alle Aufträge einstellen)
Wie oben erklärt, wenn der Händler die Parameter Use Order Stop Loss (No) und/oder Use Order Take Profit (No) eingibt, dann aber Stop Loss oder Take Profit auf alle Aufträge anwenden möchte, dann wird ein einziger Klick auf die Schaltfläche „Set SL / TP All Orders“ alle Aufträge ändern und Stop Loss und/oder Take Profit anwenden.
void MCEA::SetSLTPOrders(void) { //--- ResetLastError(); MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- double modbuysl=0; double modselsl=0; double modbuytp=0; double modseltp=0; string position_symbol; int totalorder=PositionsTotal(); //-- for(int i=totalorder-1; i>=0; i--) { string symbol=PositionGetSymbol(i); position_symbol=symbol; if(mc_position.Magic()==magicEA) { ENUM_POSITION_TYPE opstype = mc_position.PositionType(); if(opstype==POSITION_TYPE_BUY) { Pips(symbol); RefreshTick(symbol); double price = mc_position.PriceCurrent(); double pos_open = mc_position.PriceOpen(); double pos_stop = mc_position.StopLoss(); double pos_take = mc_position.TakeProfit(); modbuysl=SetOrderSL(symbol,opstype,pos_open); if(price<modbuysl) modbuysl=mc_symbol.NormalizePrice(price-slip*pip); modbuytp=SetOrderTP(symbol,opstype,pos_open); if(price>modbuytp) modbuytp=mc_symbol.NormalizePrice(price+slip*pip); //-- if(pos_stop==0.0 || pos_take==0.0) { if(!mc_trade.PositionModify(position_symbol,modbuysl,modbuytp)) { mc_trade.CheckResult(check); Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+ (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]"); } } } if(opstype==POSITION_TYPE_SELL) { Pips(symbol); RefreshTick(symbol); double price = mc_position.PriceCurrent(); double pos_open = mc_position.PriceOpen(); double pos_stop = mc_position.StopLoss(); double pos_take = mc_position.TakeProfit(); modselsl=SetOrderSL(symbol,opstype,pos_open); if(price>modselsl) modselsl=mc_symbol.NormalizePrice(price+slip*pip); modseltp=SetOrderTP(symbol,opstype,pos_open); if(price<modseltp) modseltp=mc_symbol.NormalizePrice(price-slip*pip); //-- if(pos_stop==0.0 || pos_take==0.0) { if(!mc_trade.PositionModify(position_symbol,modselsl,modseltp)) { mc_trade.CheckResult(check); Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+ (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]"); } } } } } //-- return; //--- } //-end SetSLTPOrders //---------//
2. Close All Orders (Alle Aufträge schließen)
Wenn ein Händler alle Positionen schließen möchte, genügt ein einziger Klick auf die Schaltfläche „Alle Aufträge schließen“, um alle offenen Aufträge zu schließen.
void MCEA::CloseAllOrders(void) //-- function: close all order { //---- ResetLastError(); //-- MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- int total=PositionsTotal(); // number of open positions //--- iterate over all open positions for(int i=total-1; i>=0; i--) { //--- if the MagicNumber matches if(mc_position.Magic()==magicEA) { //-- string position_Symbol = PositionGetSymbol(i); // symbol of the position ulong position_ticket = PositionGetTicket(i); // ticket of the the opposite position ENUM_POSITION_TYPE type = mc_position.PositionType(); RefreshTick(position_Symbol); bool closepos = mc_trade.PositionClose(position_Symbol,slip); //--- output information about the closure PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type)); //--- } } //--- return; //---- } //-end CloseAllOrders() //---------//
3. Close All Profits (Alle Positionen im Gewinn schließen)
Wenn ein Händler alle bereits profitablen Positionen schließen möchte, genügt ein einziger Klick auf die Schaltfläche „Close All Profits“, um alle offenen Positionen, die bereits profitabel sind, zu schließen.
bool MCEA::ManualCloseAllProfit(void) { //---- ResetLastError(); //-- bool orclose=false; //-- MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- int ttlorder=PositionsTotal(); // number of open positions //-- for(int x=0; x<arrsymbx; x++) { string symbol=DIRI[x]; orclose=false; //-- for(int i=ttlorder-1; i>=0; i--) { string position_Symbol = PositionGetSymbol(i); ENUM_POSITION_TYPE type = mc_position.PositionType(); if((position_Symbol==symbol) && (mc_position.Magic()==magicEA)) { double pos_profit = mc_position.Profit(); double pos_swap = mc_position.Swap(); double pos_comm = mc_position.Commission(); double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2); ulong position_ticket = PositionGetTicket(i); //--- if(type==POSITION_TYPE_BUY && cur_profit>0.02) { RefreshTick(position_Symbol); orclose = mc_trade.PositionClose(position_Symbol,slip); //--- output information about the closure PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type)); } if(type==POSITION_TYPE_SELL && cur_profit>0.02) { RefreshTick(position_Symbol); orclose = mc_trade.PositionClose(position_Symbol,slip); //--- output information about the closure PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type)); } } } } //-- return(orclose); //---- } //-end ManualCloseAllProfit() //---------//
Wenn die Schaltfläche C angeklickt wird, wird eine Schaltfläche mit 30 Symbolnamen oder -paaren angezeigt, und die Händler können auf einen der Paar- oder Symbolnamen klicken.
Wenn Sie auf einen der Paar- oder Symbolnamen klicken, wird das Chartsymbol sofort durch das Symbol ersetzt, auf dessen Namen Sie geklickt haben.
void CreateSymbolPanel() { //--- //-- ResetLastError(); DeletePanelButton(); int sydis=83; int tsatu=int(mc.sall/2); //-- CreateButtonTemplate(0,"Template",180,367,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,187,45,true); CreateButtonTemplate(0,"TempCCS",167,25,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBlue,clrWhite,CORNER_RIGHT_UPPER,181,50,true); CreateButtonClick(0,"X",14,14,"Arial Black",10,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,22,48,true,"Close Symbol Panel"); //-- string chsym="Change SYMBOL"; int cspos=int(181/2)+int(StringLen(chsym)/2); CreateButtontLable(0,"CCS","Bodoni MT Black",chsym,11,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,cspos,62,true,"Change Chart Symbol"); //-- for(int i=0; i<tsatu; i++) CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,180,sydis+(i*22),true,"Change to "+mc.AS30[i]); //-- for(int i=tsatu; i<mc.sall; i++) CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,94,sydis+((i-tsatu)*22),true,"Change to "+mc.AS30[i]); //-- ChartRedraw(0); //-- return; //--- } //-end CreateSymbolPanel() //---------//
In diesem Fall wird die Funktion OnChartEvent() die Funktion ChangeChartSymbol() aufrufen, wenn einer der Symbolnamen angeklickt wird.
if(id==CHARTEVENT_OBJECT_CLICK) { int lensymbol=StringLen(Symbol()); int lensparam=StringLen(sparam); //--- if Symbol button is click if(lensparam==lensymbol) { int sx=mc.ValidatePairs(sparam); ChangeChartSymbol(mc.AS30[sx],CCS); mc.PanelExtra=false; } //-- }
void ChangeChartSymbol(string c_symbol,ENUM_TIMEFRAMES cstf) { //--- //--- unpress the button ObjectSetInteger(0,c_symbol,OBJPROP_STATE,false); ObjectSetInteger(0,c_symbol,OBJPROP_ZORDER,0); ObjectsDeleteAll(0,0,OBJ_BUTTON); ObjectsDeleteAll(0,0,OBJ_LABEL); ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL); //-- ChartSetSymbolPeriod(0,c_symbol,cstf); //-- ChartRedraw(0); //-- return; //--- } //-end ChangeChartSymbol() //---------//
Und schließlich wird durch Klicken auf die Schaltfläche R der Multi-Currency Expert Advisor RSIxRSI_MCEA aus dem Chart entfernt, sodass der Händler die Experten nicht manuell entfernen muss.
if(id==CHARTEVENT_OBJECT_CLICK) { //-- //--- if "R" button is click if(sparam=="R") { Alert("-- "+mc.expname+" -- ",Symbol()," -- Expert Advisor will be Remove from the chart."); ExpertRemove(); //--- unpress the button ObjectSetInteger(0,"R",OBJPROP_STATE,false); ObjectSetInteger(0,"R",OBJPROP_ZORDER,0); if(!ChartSetSymbolPeriod(0,Symbol(),Period())) ChartSetSymbolPeriod(0,Symbol(),Period()); DeletePanelButton(); ChartRedraw(0); } //--- }
Strategietester
Der Vorteil des MetaTrader 5 Strategy Testers ist, dass er Strategien unterstützt, die auf mehreren Symbolen handeln oder den automatischen Handel für alle verfügbaren Symbole und auf allen verfügbaren Zeitrahmen testen.
Daher werden wir auf der MetaTrader 5 Strategy Tester Plattform den RSIxRSI_MCEA Multi-Currency Expert Advisor testen.
Im ersten Test haben wir den RSIxRSI_MCEA auf das XAGUSD-Paar und den H4-Zeitrahmen gelegt, mit einer angepassten Zeitspanne von 2023.10.01 bis 2024.01.05
Der Test wurde mit zwei verschiedenen Eingabeeigenschaften durchgeführt, und zwar in der Parametergruppe Global Strategy EA und der Parametergruppe Trade & Order Management.
1. Der RSIxRSI_MCEA für das Paar XAGUSD und den H4-Zeitrahmen
Die Ergebnisse des ersten Tests sind in der folgenden Abbildung dargestellt.
2. Der RSIxRSI_MCEA für das Paar XAGUSD und den H12-Zeitrahmen
Die Ergebnisse des zweiten Tests sind in der nachstehenden Abbildung dargestellt.
Schlussfolgerung
Die Schlussfolgerung bei der Erstellung eines Multi-Currency Expert Advisors mit Signalen von Fast RSI, die Slow RSI kreuzen, oder RSI cross RSI für den Forex-Handel mit MQL5 ist wie folgt:
- Es stellt sich heraus, dass die Erstellung eines Multiwährungs-Expert Advisors in MQL5 sehr einfach ist und sich nicht wesentlich von der Erstellung eines Expert Advisors für eine einzelne Währung unterscheidet.
- Die Erstellung eines Multi-Currency Expert Advisors wird die Effizienz und Effektivität der Händler erhöhen, da sie nicht mehr viele Chart-Symbole für den Handel öffnen müssen.
- Die Anwendung der richtigen Handelsstrategie erhöht die Gewinnwahrscheinlichkeit im Vergleich zur Verwendung eines Expert Advisors für eine einzige Währung. Das liegt daran, dass Verluste in einem Paar durch Gewinne in anderen Paaren ausgeglichen werden.
- Dieser RSIxRSI_MCEA Multi-Currency Expert Advisor ist nur ein Beispiel zum Lernen und zur Ideenfindung. Die Testergebnisse des Strategietesters sind immer noch nicht gut. Daher ist es möglich, durch Experimentieren und Testen mit verschiedenen Zeitrahmen oder Berechnungen verschiedener Indikatorperioden eine bessere Strategie und profitablere Ergebnisse zu erzielen.
- Meiner Meinung nach sollte diese RSI-Cross-RSI-Strategie mit verschiedenen Experimenten weiter erforscht werden, beginnend mit dem Zeitrahmen, dem RSI der schnellen Periode, dem RSI der langsamen Periode und dem Differenzierungswert beider RSIs. Basierend auf den Ergebnissen meiner Experimente auf Strategy Tester, auf Zeitrahmen unter H4 die Ergebnisse sind nicht gut, nur auf Zeitrahmen H4 und darüber, zum Beispiel auf Zeitrahmen H8 und H12, die Ergebnisse sind gut mit wenigen offenen Trades, im Vergleich zu kleinen Zeitrahmen mit vielen offenen Trades, aber in Verlust.
Wir hoffen, dass dieser Artikel und das MQL5 Multi-Currency Expert Advisor Programm für Händler nützlich sein werden, um zu lernen und Ideen zu entwickeln.
Danke fürs Lesen.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/14051
- 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.