Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 4): Triangulärer gleitender Durchschnitt — Indikatorensignale
Einführung
Die Definition eines Expert Advisor für mehrere Währungen ( Multi-Currency) in diesem Artikel ist ein Expert Advisor oder Handelsroboter, der mehr als nur ein Symbolpaar von dessen Symbolchart handeln kann (Aufträge öffnen, schließen und verwalten oder zum Beispiel Trailing Stop Loss und Trailing Profit). wobei in diesem Artikel der Expert Advisor 30 Paare handeln wird.
Dieses Mal werden wir nur einen Indikator verwenden, nämlich den Triangulären gleitenden Durchschnitt im Multi-Zeitrahmen- oder Einzelzeitrahmen-Modus.Der Trianguläre gleitende Durchschnitt ist ein nutzerdefinierter Indikator für MT5 vom Autor Mladen Rakic, und ich habe die Erlaubnis vom Autor erhalten, seinen Indikator als Signal für den Multi-Currency Expert Advisor „TriangularMA_MTF_MCEA“ zu verwenden.
Gruss und Dank an den Autor Mladen Rakic.
Ziel ist es daher, die wesentlichen Bedürfnisse von Händlern zu erfüllen, die sich effiziente und effektive Handelsroboter wünschen. Indem wir uns auf die Stärken, Fähigkeiten und Möglichkeiten des äußerst zuverlässigen MQL5 verlassen, können wir einen einfachen Expertenberater für mehrere Währungen erstellen, der die Indikatorsignale aus diesem Artikel verwendet: den Triangulären gleitenden Durchschnitt.
Anmerkung: Die Entwicklung des Multi-Currency Expert Advisors TriangularMA_MTF_MCEA erfolgte auf Anregung und Wunsch von Händlern.
Pläne und Eigenschaften
1. Handel mit Währungspaaren.
Dieser Multi-Currency Expert Advisor ist für den Handel mit einem der folgenden Symbole oder Paare vorgesehen:
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.
Im vorigen Artikel haben wir für Paare von Maklern mit speziellen Namen für die Paare mit Präfixen und/oder Suffixen eine automatische Funktion verwendet, um die Paarnamen mit Präfixen und/oder Suffixen zu erkennen.
Aber in diesem Artikel machen wir es uns einfach, indem wir spezielle Eingabeeigenschaften für das Präfix und das Suffix des Paar-Namens hinzufügen.
Dann behandeln wir mit einer einfachen Funktion die Präfix- und/oder Suffix-Paar-Namen in Kombination mit den 30 registrierten Paar-Namen, sodass, wenn ein EA auf MetaTrader5 von einem Broker mit speziellen Symbol-Namen wie diesem verwendet wird, alles reibungslos läuft.
Der Schwachpunkt der Funktion zur Erkennung von Symbolnamen mit Präfixen und Suffixen ist, dass diese Funktion nur bei Forex- und Metallsymbolpaaren oder -namen im MT5 funktioniert, nicht aber bei speziellen Symbolen und Indizes.
Eine weitere Schwäche dieser Methode besteht darin, dass sich der Händler bei der Eingabe des Präfixes und/oder Suffixes des Paares vertippen kann (Groß- und Kleinschreibung muss beachtet werden).
Wie im vorherigen Artikel haben wir auch in diesem Expert Advisor 10 Optionen für die Paare hinzugefügt, die zu diesem Zeitpunkt gehandelt werden sollen.
Eines der 10 Optionspaare, die gehandelt werden, ist „Trader Wishes Pairs“ (des Händlers Wunschpaare), wobei die Paare, die gehandelt werden sollen, vom Händler manuell über die Experteneingabeeigenschaft eingegeben werden müssen. Sie müssen aber immer daran denken, dass der Name des eingegebenen Paares bereits in der Liste der 30 Paare enthalten sein muss.
Immer noch das gleiche wie der vorherige Artikel, in dieser Version des Expert Advisor haben wir auch eine Option für Trading Session (Time Zone bzw. Zeitzone), sodass die Paare, die gehandelt werden, die die Zeit für den Handel Sitzung entsprechen kann.
2. Signalindikator
In der Beschreibung des Indikators „Triangulärer gleitender Durchschnitt“ stellt der Autor fest:
„Verwendung:
Sie können den Farbwechsel als Signal nutzen...“
Standardmäßig sind die Farben des Indikators „Triangulärer gleitender Durchschnitt“:
- 0-DarkGray = Unbekanntes Signal
- 1-DeepPink = Verkaufssignal
- 2-MediumSeaGreen = Kaufsignal.
In dieser Version des Expert Advisors haben wir 2 Optionen für die Verwendung von Zeitrahmen bei der Berechnung des Signals des Indikators Triangulärer gleitender Durchschnitt geschaffen.
1. Signalberechnung auf der Grundlage von multi-timeframe.
In einem Multi-Timeframe-Berechnungssystem muss der Händler aus einer Enumerationsliste die gewünschten Zeitrahmenserie auswählen.
Die ausgewählten Zeitreihen reichen von M5 bis D1 (11 Zeitrahmen).
Händler können zum Beispiel eine Zeitrahmenserie mit dem Beginn bei M15 und dem Ende bei H4.
Der Expert Advisor berechnet also das Signal des Triangulären gleitenden Durchschnittsindikators ab dem Zeitrahmen M15 bis H4.
Die Berechnung des Triangulären gleitenden Durchschnitts auf Multi-Timeframes sind:
- Kaufsignal, wenn der Indikator auf allen ausgewählten Zeitrahmen MediumSeaGreen gefärbt ist, und
- Verkaufssignal, wenn der Indikator auf allen ausgewählten Zeitrahmen DeepPink gefärbt ist.
2. Signalberechnung auf der Grundlage eines einzigen Zeitfensters.
Beim System zur Berechnung der Signale im Single-Timeframe muss der Händler einen von 11 Zeitrahmen auswählen, angefangen beim M5-Zeitrahmen bis hin zum D1-Zeitrahmen.
Der Expert Advisor berechnet also das Signal des Triangulären gleitenden Durchschnitts für den ausgewählten Zeitrahmen.
Die Berechnung des Signals des Triangulären gleitenden Durchschnitts auf einem einzigen Zeitrahmen ist indessen:
- Kaufsignal, wenn die vorherigen 2 Balken DeepPink sind und der vorherige 1 Balken MediumSeaGreen und der aktuelle Balken MediumSeaGreen ist.
- Verkaufssignal, wenn die vorherigen 2 Balken MediumSeaGreen sind, der vorherige 1 Balken DeepPink ist und der aktuelle Balken DeepPink ist.
Eine Illustration des Triangulären gleitenden Durchschnitts für ein KAUF- oder VERKAUFssignal ist in Abbildung 1 und Abbildung 2 zu sehen.
3. Handel und Auftragsverwaltung.
Das Handelsmanagement dieses Mehr-Währungs-EAs verfügt über mehrere Optionen:
1. Stop-Loss-Aufträge
- Optionen: Use Order Stop Loss (Yes) or (No) (Stop-Loss-Auftrag verwenden, Ja oder Nein)
Wenn die Option (No) für Use Stop-Loss für Aufträge verwenden ausgewählt ist, werden alle Aufträge ohne Stop-Loss eröffnet.
Wenn die Option Use Order Stop Loss (Yes) (Stop-Loss für Aufträge verwenden (Ja)):
Dann gibt es die weiteren Optionen: Use Automatic Calculation Stop Loss (Yes) or (No) (Autom. Berechnung des Stop Loss verwenden, Ja oder Nein)
Wenn die Option Automatische Berechnung Stop Loss (Ja), dann 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) (Order Stop Loss verwenden (Nein)):
Dann prüft der Experte für jeden geöffneten Auftrag, ob die Signalbedingung noch aufrecht ist, sollte ein bereits profitabler Auftrag
geschlossen werden, um den Gewinn zu sichern, oder hat sich das Signal abgeschwächt.
Die Gewinn- oder Signalbedingung hat sich umgekehrt und der Auftrag muss als Verlust geschlossen werden.
Anmerkung:
Speziell für Close Trade (Handel schließen) und Save Profit (Gewinn sichern) aufgrund eines schwachen Signals wird eine Option angeboten, ob diese aktiviert werden kann oder nicht.
Wenn sie nicht aktiviert ist (Nein), wird der Auftrag trotz des schwächeren Signals aufrechterhalten oder nicht geschlossen, um den Gewinn zu sichern.
2. Take-Profit-Aufträge
- Optionen: Use Order Take Profit (Yes) or (No) (Take-Profit verwenden, Ja oder Nein)
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 Order Take Profit (Yes):
Dann gibt es die weiteren Optionen: Use Automatic Calculation Order Take Profit (Yes) oder (No) (Take-Profit automatisch berechnen, Ja oder Nein).
Bei der Option Automatic Calculation Order Take Profit (Yes), dann wird die Berechnung der Take Profit Order automatisch vom Experten durchgeführt.
Wenn die Option Automatic Calculation Order Take Profit (No), gewählt wurde, muss der Händler den Order-Take-Profit-Wert in Pips eingeben.
3. Trailing Stop und Trailing Take-Profit
- Optionen: Use Trailing SL/TP (Yes) or (No) (Nachlaufende SL/TP verwenden, Ja oder Nein)
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):
Dann gibt es die weiteren Optionen: Use Automatic Trailing (Yes) oder (No) (Automatisches Nachziehen verwenden, Ja oder Nein).
Bei Verwendung von der Option Use Automatic Trailing (Yes) (Automatisches Trailing verwenden (Ja)) wird der Trailing-Stop vom Experten ausgeführt, indem er
den Triangulären gleitenden Durchschnittspuffer 0 (Indikatordaten) des Zeitrahmens, der automatisch vom Expert Advisor ausgewählt wird, und gleichzeitig
durch Erzielung eines Trailing Profits auf der Grundlage des variablen Werts TPmin (kleinster Wert des Trailing Profits).
Bei der Option Use Automatic Trailing (No) wird der Trailing-Stop vom Experten anhand des Wertes in der Eingabeeigenschaft ausgeführt.
Anmerkung: Der Experte führt einen Trailing-Take-Profit gleichzeitig mit einem Trailing-Stop aus.
Die Funktion „Trailing Stop Price“:
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 TriMAID[]; //-- ArrayResize(TriMAID,br,br); ArraySetAsSeries(TriMAID,true); CopyBuffer(hTriMAt[x],0,0,br,TriMAID); // Copy buffer 0 from the hTriMAt indicator handle //-- RefreshTick(xsymb); if(ptype==POSITION_TYPE_BUY && (mc_symbol.Bid()>mc_symbol.NormalizePrice(TriMAID[0]+TSval*pip))) pval=TriMAID[0]; if(ptype==POSITION_TYPE_SELL && (mc_symbol.Ask()<mc_symbol.NormalizePrice(TriMAID[0]-TSval*pip))) pval=TriMAID[0]; break; } } //-- return(pval); //--- } //-end TSPrice() //---------//
Modifikation SL/TP-Funktion:
bool MCEA::ModifySLTP(const string symbx,int TS_type) { //--- ResetLastError(); MqlTradeRequest req={}; MqlTradeResult res={}; MqlTradeCheckResult check={}; //-- int TRSP=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*pip); double modbuysl=vtrsb; double modbuytp=mc_symbol.NormalizePrice(price+TPmin*pip); bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop)); //-- if(modbuy && netp>0.05) { 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*pip); double modselsl=vtrss; double modseltp=mc_symbol.NormalizePrice(price-TPmin*pip); bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); //-- if(modsel && netp>0.05) { modist=mc_trade.PositionModify(symbol,modselsl,modseltp); } } } } //-- return(modist); //--- } //-end ModifySLTP() //---------//
4. Manuelle Auftragsverwaltung.
Um die Effizienz in diesem Mehr-Währungs-EA zu unterstützen, werden mehrere manuelle Klick-Buttons hinzugefügt.
1. Set SL / TP All Orders (Setzen von SL / TP bei allen Aufträgen)
Wenn der Händler-Eingabeparameter Use Order Stop Loss (No) und/oder Use Order Take Profit (No) einstellt
aber der Händler beabsichtigt, Stop-Loss oder Take-Profit für alle Aufträge anzuwenden, dann kann er mit einem einzigen Klick auf die Schaltfläche
„Set SL / TP All Orders“ (SL/TP für alle Aufträge setzen) alle Aufträge ändern und ein Stop-Loss und/oder Take-Profits setzen.
2. Close All Orders (Alle Aufträge schließen)
Wenn ein Händler alle Aufträge schließen möchte, dann kann er mit einem einzigen Klick auf die Schaltfläche „Close All Orders“ alle offenen Aufträge schließen.3. Close All Orders Profit (Alle Aufträge im Gewinn schließen)
Wenn ein Händler alle bereits profitabelen Aufträge schließen will, genügt ein einziger Klick auf die Schaltfläche
"Close All Orders Profit", um sie alle zu schließen.
5. Management-Befehle und Chartsymbole.
Für Mehr-Währungs-EAs, die 30 Paare von nur einem Chartsymbol handeln, ist es sehr effektiv und effizient, wenn eine Panel für alle Symbole vorhanden ist, sodass Händler Charts oder Symbole mit nur einem Klick wechseln können.
Umsetzung der Planung im Programm MQL5
1. Programm-Header 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 Optionspaaren, die gehandelt werden sollen:
//-- 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 }; //--
Enumeration YN wird für die Optionen (Ja) oder (Nein) in der Experteneingabeeigenschaft verwendet:
//-- enum YN { No, Yes }; //--
Die Enumeration zur Bestimmung der Losgröße:
//-- enum mmt { FixedLot, // Fixed Lot Size DynamLot // Dynamic Lot Size }; //--
Die Enumeration zur Auswahl des Zeitrahmens, ob ein Multi-Zeitrahmen oder ein Einzel-Zeitrahmen verwendet wird:
//-- enum TFMTF { TFM5, // PERIOD_M5 TFM15, // PERIOD_M15 TFM30, // PERIOD_M30 TFH1, // PERIOD_H1 TFH2, // PERIOD_H2 TFH3, // PERIOD_H3 TFH4, // PERIOD_H4 TFH6, // PERIOD_H6 TFH8, // PERIOD_H8 TFH12, // PERIOD_H12 TFD1 // PERIOD_D1 }; //--
Die Enumeration zur Verwendung von Multi-Timeframe oder Single-Timeframe:
//-- enum SMTF { MTF, // Use Multi-Timeframe STF // Use Single-Timeframe }; //--
Eingabeeigenschaften des Experten:
//--- input group "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter input SMTF tfinuse = MTF; // Select Calculation in Multi or Single Timeframe input TFMTF singletf = TFH1; // Select Single Calculation TimeFrame, default PERIOD_H1 input TFMTF tfstart = TFM15; // Select Multi Timeframe calculation start input TFMTF tfclose = TFH4; // Select Multi Timeframe calculation end input int Trmaperiod = 14; // Input Triangular MA Indicator period, default 14 input ENUM_APPLIED_PRICE Trprice = PRICE_CLOSE; // Select Triangular MA Applied Price, default Price Close //--- input group "=== Select Pairs to Trade ==="; // Selected Pairs to trading 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 string sym_prefix = ""; // Input the symbol prefix in case sensitive (if any) input string sym_suffix = ""; // Input the symbol suffix in case sensitive (if any) //-- 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; // 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 = 10; // If Not Use Automatic TP - Input TP value in Pips input YN TrailingSLTP = Yes; // Use Trailing SL/TP (Yes) or (No) input YN autotrl = Yes; // Use Automatic Trailing (Yes) or (No) input double TSval = 5; // If Not Use Automatic Trailing Input Trailing value in Pips input double TSmin = 5; // Minimum Pips to start Trailing Stop input double TPmin = 25; // 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 = 2023111; // Expert ID (Magic Number) //---
In der Experten-Eingabeeigenschaftsgruppe „Global Strategy EA Parameter“ müssen die Händler wählen, ob sie die Signalberechnung für mehrere oder nur einem Zeitrahmen verwenden möchten.
Wenn der Händler einen Single-Timeframe (STF) wählt, muss er den zu verwendenden Zeitrahmen festlegen.
In der Experten-Eingabeeigenschaft müssen Sie „Select Single Calculation timeframe“ auswählen, Standardwert ist PERIOD_H1.
Entscheidet sich der Händler für Multi-Timeframe (MTF), so muss er die zu verwendenden Zeitrahmenreihen festlegen.
In der Experten-Eingabeeigenschaft werden Sie angewiesen, den Beginn der Multi Timeframe-Berechnung und das Ende der Multi Timeframe-Berechnung auszuwählen.
In den Zeilen 478 bis 518 der Funktion TriangularMA_MTF_MCEA_Config() wird erläutert, wie Multi- und Single-Timeframe zu behandeln sind.
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(singletf==x) TFt=TFs[x]; // TF for single-timeframe if(tfstart==x) arstr=x; // multi-timeframe start calculation timeframe if(tfclose==x) arend=x; // multi-timeframe end calculation timeframe } //-- if(arstr>=arend) { Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe"); Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart."); ExpertRemove(); } //-- switch(tfinuse) { case MTF: { TFArrays=arend-arstr+1; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=arstr+1; tftrlst=(int)TFArrays/2; TFts=TFs[tftrlst+arstr-1]; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } case STF: { TFArrays=arTFs; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=TFIndexArray(TFt)-2 <=0 ? 1 : TFIndexArray(TFt)-2; TFts=TFt; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } }
Die Variable ENUM_TIMEFRAMES TFs[] muss mit der Enumerationsoption enum TFMTF verknüpft sein:
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}; //-- enum TFMTF { TFM5, // PERIOD_M5 TFM15, // PERIOD_M15 TFM30, // PERIOD_M30 TFH1, // PERIOD_H1 TFH2, // PERIOD_H2 TFH3, // PERIOD_H3 TFH4, // PERIOD_H4 TFH6, // PERIOD_H6 TFH8, // PERIOD_H8 TFH12, // PERIOD_H12 TFD1 // PERIOD_D1 }; //--
Dann muss der Händler die Periode des Triangulären MA-Indikators bestimmen, standardmäßig Periode 14.
Darüber hinaus müssen Händler auch den angewandten Triangulären MA-Preis angeben, standardmäßig PRICE_CLOSE.
In der Eigenschaftsgruppe „Select Pairs to Trade“ (Zu handelnde Paare auswählen) müssen die Händler das zu handelnde Paar aus den 10 zur Verfügung stehenden Optionen auswählen; standardmäßig ist All Forex 30 Pairs festgelegt.
Um das zu handelnde Paar zu konfigurieren, rufen wir die Funktion HandlingSymbolArrays() auf.
Mit der Funktion HandlingSymbolArrays() 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); aretc=ArraySize(EURs); 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<aretc; 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 30 Pairs { ArrayResize(DIRI,sall,sall); arrsymbx=sall; ArraySymbolResize(); ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY); pairs="Multi Currency 30 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,aretc,aretc); 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 der Funktion SetSymbolNamePS() können wir Symbolnamen behandeln, die Präfixe und/oder Suffixe haben.
void MCEA::SetSymbolNamePS(void) { //--- symbfix=false; int ptriml; int ptrimr; string insymbol=Symbol(); int sym_Lenpre=StringLen(prefix); int sym_Lensuf=StringLen(suffix); if(sym_Lenpre>0) { ptriml=StringTrimLeft(suffix); ptriml=StringTrimRight(suffix); } if(sym_Lensuf>0) { ptrimr=StringTrimLeft(suffix); ptrimr=StringTrimRight(suffix); } string sym_pre=prefix; string sym_suf=suffix; //-- pre=sym_pre; suf=sym_suf; inpre=StringLen(pre); insuf=StringLen(suf); posCur1=inpre; posCur2=posCur1+3; //-- return; //--- } //-end SetSymbolNamePS() //---------//
Anmerkung:
Der Experte wird die Paare überprüfen.
Wenn der Händler einen Fehler bei der Eingabe des Paar-Namens oder des Paar-Präfix-Namens und/oder des Paar-Suffix-Namens macht (Tippfehler) oder
wenn die Paarvalidierung fehlschlägt, gibt der Experte eine Warnung aus und der Expertenberater wird vom Chart entfernt.
In der Experten-Eingabeeigenschaftsgruppe Trade on Specific Time (Handel zu einer bestimmten Zeit) kann der Händler wählen, ob er in einer bestimmten Zeitzone handeln möchte (Ja) oder (Nein).
und Wenn Ja, wählen Sie die Enumerationsoptionen:
- Handel während einer nutzerdefinierten Sitzung (Custom Session)
- Handel während der neuseeländischen Sitzung
- Handel während der Australien Sydney Session
- Handel während der Asien Tokyo Session
- Handel während der Europa London Session
- Handel während der Amerika New York Session
Der EA wird also nur während der angegebenen Zeit von Anfang bis Ende Aktivitäten durchführen.
Beim Handel an der New Zealand Session bis zum Handel an der US New York Session wird die Zeit vom Handelsbeginn bis zum Handelsschluss vom EA berechnet.
Um alle Variablen, Objekte und Funktionen zu deklarieren, die in diesem Mehr-Währungs-EA benötigt werden, werden wir eine Klasse erstellen, um den Aufbau und die Konfiguration im Expert Advisor Workflow zu spezifizieren.
Insbesondere die Variablen, die in der Funktion für die Handhabung von Präfix-Symbolnamen und/oder Suffix-Symbolnamen sowie für die Zeitzonenberechnung verwendet werden, haben wir in der MCEA-Klasse erstellt.
//+------------------------------------------------------------------+ //| 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 slv, tpv, pip, xpip; 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 TriaMASMTF(const string symbol,ENUM_TIMEFRAMES mtf); int GetTriaMASignalMTF(string symbol); int TriaMASignalSTF(const string symbol); int LotDig(const string symbol); //-- 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: //--- //-- TriangularMA_MTF_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; string indiname; //-- int hTriMAt[]; int hTriMAs[]; int hTriMAm[]; int hTriMAb[][11]; int ALO, dgts, arrsar, arrsymbx; int sall, arusd, aretc, arspc, arper; ulong slip; //-- double profitb[], profits[]; //-- int Buy, Sell; int ccur, psec, xtto, TFArrays, 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, TFts, TFT05, TFCWS; ENUM_TIMEFRAMES TFTri[]; //-- bool PanelExtra; //------------ MCEA(void); ~MCEA(void); //------------ //-- virtual void TriangularMA_MTF_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 CloseBuyPositions(const string symbol); void CloseSellPositions(const string symbol); 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); //-- int PairsIdxArray(const string symbol); int ValidatePairs(const string symbol); int TFIndexArray(ENUM_TIMEFRAMES TF); int GetOpenPosition(const string symbol); int GetSignalMidTF(const string symbol); int GetCloseInWeakSignal(const string symbol,int exis); //-- string getUninitReasonText(int reasonCode); //-- //------------ //--- }; //-end class MCEA //---------//
Die allererste und wichtigste Funktion im Arbeitsprozess des Multi-Currency Expert Advisors, die von OnInit() aufgerufen wird, ist TriangularMA_MTF_MCEA_Config().
In der Funktion TriangularMA_MTF_MCEA_Config() werden alle zu verwendenden Symbole, alle verwendeten Handle-Indikatoren und einige wichtige Funktionen des Include-Dateikopfes für den Expert Advisor Workflow konfiguriert.
void MCEA::TriangularMA_MTF_MCEA_Config(void) { //--- //-- HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded //-- int arstr=0, arend=0; TFT05=PERIOD_M5; 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(singletf==x) TFt=TFs[x]; // TF for single-timeframe if(tfstart==x) arstr=x; // multi-timeframe start calculation timeframe if(tfclose==x) arend=x; // multi-timeframe end calculation timeframe } //-- if(arstr>=arend) { Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe"); Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart."); ExpertRemove(); } //-- switch(tfinuse) { case MTF: { TFArrays=arend-arstr+1; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=arstr+1; tftrlst=(int)TFArrays/2; TFts=TFs[tftrlst+arstr-1]; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } case STF: { TFArrays=arTFs; ArrayResize(TFTri,TFArrays,TFArrays); ArrayCopy(TFTri,TFs,0,0,WHOLE_ARRAY); tfcinws=TFIndexArray(TFt)-2 <=0 ? 1 : TFIndexArray(TFt)-2; TFts=TFt; // TF for Trailing Stop TFCWS=TFs[tfcinws]; // TF for Close Order in weak signal break; } } //-- //-- Triangular MA Indicators handle for all symbol for(int x=0; x<arrsymbx; x++) { hTriMAs[x]=iCustom(DIRI[x],TFT05,indiname,Trmaperiod,Trprice); hTriMAm[x]=iCustom(DIRI[x],TFCWS,indiname,Trmaperiod,Trprice); hTriMAt[x]=iCustom(DIRI[x],TFts,indiname,Trmaperiod,Trprice); //-- for(int i=0; i<TFArrays; i++) { if(tfinuse==MTF) // MTF indicator handle { hTriMAb[x][i]=iCustom(DIRI[x],TFTri[i],indiname,Trmaperiod,Trprice); } if(tfinuse==STF) { if(TFs[i]==TFt) // Single-TF indicator handle { hTriMAb[x][i]=iCustom(DIRI[x],TFs[i],indiname,Trmaperiod,Trprice); break; } } } } //-- ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders(); //-- LotPS=(double)ALO; //-- mc_trade.SetExpertMagicNumber(magicEA); mc_trade.SetDeviationInPoints(slip); mc_trade.SetMarginMode(); Set_Time_Zone(); //-- return; //--- } //-end TriangularMA_MTF_MCEA_Config() //---------//
2. Die OnTick-Funktion des Experten
Innerhalb der Funktion OnTick() des EAs werden wir eine der Hauptfunktionen in einem Mehr-Währungs-EA aufrufen, nämlich die Funktion ExpertActionTrade().
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(void) { //--- mc.ExpertActionTrade(); //-- return; //--- } //-end OnTick() //---------//
Der Ablauf des EA-Arbeitsprozesses innerhalb dieser Funktion.
Die Funktion ExpertActionTrade() führt alle Aktivitäten durch und verwaltet den automatischen Handel, angefangen bei Positionen eröffnen und schließen (Open Orders, Close Orders), Trailing-Stop oder Trading-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++) { //-- if(mc.DIRI[x]==Symbol()) symbol=Symbol(); else symbol=mc.DIRI[x]; //-- 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]>0.02 && 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]>0.02 && 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) { if(autotrl==Yes) mc.ModifySLTP(symbol,1); //-- If Use Automatic Trailing (Yes) if(autotrl==No) mc.ModifySLTP(symbol,0); //-- Use Automatic Trailing (No) } } //-- mc.CheckClose(symbol); } //-- mc.psec=mc.ccur; } //-- return; //--- } //-end ExpertActionTrade() //---------//
Speziell für den Zeitzonenhandel wurde in der Funktion ExpertActionTrade() ein Aufruf der booleschen Funktion Trade_session() hinzugefügt.
Wenn Trade_session() true ist, dann wird der EA-Arbeitsprozess fortgesetzt, bis er beendet ist, aber wenn er false ist, dann führt der EA nur die Aufgaben „Close Trade and Save profit due to weak signal (Yes)“ and „Trailing Stop (Yes)“. (Positionen schließen und Gewinn sichern aufgrund eines schwachen Signals (Ja) und Trailing-Stop (Ja)) aus.
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() //---------//
3. Wie kann ich Handelssignale für offene Positionen erhalten?
Um ein Signal 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 trimOp=GetTriaMASignalMTF(symbol); int getmid=GetSignalMidTF(symbol); if(trimOp==rise && getmid==rise) ret=rise; if(trimOp==down && getmid==down) ret=down; //-- return(ret); //--- } //-end GetOpenPosition() //---------//
Die Funktion GetOpenPosition() ruft 2 Funktionen auf, die Signalberechnungen durchführen:
1. GetSignalMidTF(const string symbol); //-- Funktion zum Abrufen von Signalen auf dem mittleren Zeitrahmen und Preisbewegungspositionen:
int MCEA::GetSignalMidTF(const string symbol) // Signal Indicator Position Close in profit { //--- int ret=0; int rise=1, down=-1; //-- int br=2; //-- double TriMACI[]; //-- ArrayResize(TriMACI,br,br); ArraySetAsSeries(TriMACI,true); int xx=PairsIdxArray(symbol); CopyBuffer(hTriMAm[xx],1,0,br,TriMACI); //#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2 //-- int dirmove=DirectionMove(symbol,TFCWS); //-- if(TriMACI[0]==2.0 && dirmove==rise) ret=rise; if(TriMACI[0]==1.0 && dirmove==down) ret=down; //-- return(ret); //--- } //-end GetSignalMidTF() //---------//
2. GetTriaMASignalMTF(const string symbol); //-- Funktion zur Berechnung der Formel des Triangulären gleitenden Durchschnitts.
Die Funktion GetTriaMASignalMTF() ruft eine Funktion TriaMASMTF() auf, die das Signal des Triangulären gleitenden Durchschnitts entsprechend dem gewünschten Zeitrahmen berechnet:
int MCEA::GetTriaMASignalMTF(string symbol) { //--- int mv=0; int rise=1, down=-1; int tfloop=tfinuse==MTF ? TFArrays : 1; //-- int trimup=0, trimdw=0; //-- for(int x=0; x<tfloop; x++) { if(TriaMASMTF(symbol,TFTri[x])>0) trimup++; if(TriaMASMTF(symbol,TFTri[x])<0) trimdw++; } //-- if(trimup==tfloop) mv=rise; if(trimdw==tfloop) mv=down; //-- return(mv); //--- } //- end GetTriaMASignalMTF() //---------//
int MCEA::TriaMASMTF(const string symbol,const ENUM_TIMEFRAMES mtf) // formula Triangular MA on the requested Timeframe { //--- int ret=0; int rise=1, down=-1; int br=3; ENUM_TIMEFRAMES TFUse=tfinuse==MTF ? mtf : TFt; //-- double TriMACI[]; ArrayResize(TriMACI,br,br); ArraySetAsSeries(TriMACI,true); int xx=PairsIdxArray(symbol); int tx=TFIndexArray(TFUse); CopyBuffer(hTriMAb[xx][tx],1,0,br,TriMACI); //#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2 //Print("Symbol = "+symbol+" TF = "+EnumToString(mtf)+" TriMACI[0] = "+string(TriMACI[0])); //-- switch(tfinuse) { case MTF: { if(TriMACI[0]==2.0) ret=rise; if(TriMACI[0]==1.0) ret=down; //-- break; } case STF: { if(TriMACI[2]==1.0 && TriMACI[1]==2.0 && TriMACI[0]==2.0) ret=rise; if(TriMACI[2]==2.0 && TriMACI[1]==1.0 && TriMACI[0]==1.0) ret=down; //-- break; } } //-- return(ret); //--- } //-end TriaMASMTF() //---------//
Wie Sie sehen können, werden innerhalb der Funktion TriaMASMTF() 2 Funktionen verwendet und aufgerufen:
- 1. int xx= PairsIdxArray(symbol)
- 2. int tx=TFIndexArray(mtf).
Die Funktion PairsIdxArray() wird verwendet, um den Namen des angeforderten Symbols zu erhalten, und die Funktion TFIndexArray() wird verwendet, um die Zeitrahmen-Array-Sequenz des angeforderten Zeitrahmens zu erhalten.
Dann wird das entsprechende Indikator-Handle aufgerufen, um den Pufferwert des Triangulären gleitenden Durchschnittssignals aus diesem Zeitrahmen zu erhalten.
Wie der Autor des Indikators „Triangulärer gleitender Durchschnitt“ sagt:
„Verwendung:
Sie können den Farbwechsel als Signal nutzen...“
Wie soll das Signal des Triangulären gleitenden Durchschnitts beurteilte werden?
In der Eigenschaft des Indikators Triangulärer gleitender Durchschnitt:
#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2
SetIndexBuffer(1,valc,INDICATOR_COLOR_INDEX);
valc[i] = (i>0) ?(val[i]>val[i-1]) ? 2 :(val[i]<val[i-1]) ? 1 : valc[i-1]: 0;
Das wissen wir also:
- 0-DarkGray = Unbekanntes Signal
- 1-DeepPink = Verkaufssignal
- 2-MediumSeaGreen = Kaufsignal.
Wir können also den Wert des Puffers 1 des Indikators „Triangulärer gleitender Durchschnitt“ als Signal verwenden, indem wir die Funktion CopyBuffer wie in der Funktion TriaMASMTF() verwenden.
double TriMACI[]; ArrayResize(TriMACI,br,br); ArraySetAsSeries(TriMACI,true); int xx=PairsIdxArray(symbol); int tx=TFIndexArray(TFUse); CopyBuffer(hTriMAb[xx][tx],1,0,br,TriMACI); //#property indicator_color1 clrDarkGray,clrDeepPink,clrMediumSeaGreen // 0 1 2
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, mehrere manuelle Schaltflächen für die Verwaltung von Aufträgen einzurichten
und dem Wechseln zwischen den Charts oder den Symbolen.
//+------------------------------------------------------------------+ //| 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() //---------//
Um die Chartsymbole mit einem Klick zu ändern, wird der Befehl OnChartEvent() ChangeChartSymbol() aufgerufen, wenn einer der Symbolnamen angeklickt wird:
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() //---------//
Da wir einen Expertenhandelsmodus mit mehreren Zeitrahmen oder einem einzigen Zeitrahmen und einer Handelssitzung oder einer Handelszeitzone und Optionen für die zu handelnden Paare hinzufügen, benötigen wir zusätzliche Informationen in den angezeigten Handelsinformationen auf dem Chart.
Um Informationen zu den angezeigten Handelsinformationen im Chart hinzuzufügen, haben wir Änderungen an der Funktion TradeInfo() vorgenommen:
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 tradetf=tfinuse==MTF ? EnumToString(Period()) : EnumToString(TFts); string eamode=tfinuse==MTF ? "Multi-Timeframe" : "Single-Timeframe"; 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 : "+ tradetf+ "\n :: Trade Mode : "+ eamode+ "\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() //---------//
Wir haben auch eine Funktion zur Beschreibung der Zeit gemäß den Bedingungen der Handelszeitzone als Teil der Funktion TradeInfo() hinzugefügt:
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() //---------//
Die Schnittstelle des Multi-Currency Expert Advisor TriangularMA_MTF_MCEA sieht wie in der folgenden Abbildung dargestellt aus:
Unter dem Namen des Expert Advisors TriangularMA_MTF_MCEA finden Sie die Schaltflächen „M“, „C“ und „R“:
Wenn die Schaltfläche M angeklickt wird, wird ein manuelles Schaltflächenfeld angezeigt (siehe unten):
Dann kann der Händler die Aufträge, wie im Abschnitt Manuelle Auftragsverwaltung beschrieben, verwalten.
- 1. Set SL/TP All Orders (SL/TP für alle Aufträge einstellen)
- 2. Close All Orders (Alle Aufträge schließen)
- 3. Close All Profits (Alle Positionen im Gewinn schließen)
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.
Wird einer der Namen des Paars oder der Symbole angeklickt, wird das Chartsymbol sofort durch das Symbol ersetzt, dessen Name angeklickt wurde.
Wenn die Schaltfläche R angeklickt wird, wird der Multi-Currency Expert Advisor TriangularMA_MTF_MCEA aus dem Chart entfernt,
sodass die Händler die Experten nicht manuell ablösen müssen.
Strategietester
Wie bekannt, unterstützt das MetaTrader5-Terminal Strategy Tester und ermöglicht es uns, Strategien zu testen, auf mehreren Symbolen zu handeln oder den automatischen Handel für alle verfügbaren Symbole und auf allen verfügbaren Zeitrahmen zu testen.
Bei dieser Gelegenheit werden wir also einen TriangularMA_MTF_MCEA als Multi-Timeframe und Single-Timeframe in Multi-Currency Expert Advisor auf der MetaTrader5 Strategy Tester Plattform testen.
1. Test TriangularMA_MTF_MCEA mit Multi-Timeframe-Modus.
2. Test TriangularMA_MTF_MCEA mit Single-Timeframe-Modus.
Schlussfolgerung
Die Schlussfolgerung bei der Erstellung eines Multi-Currency Expert Advisors sowohl im Multi-Timeframe-Modus als auch im Single-Timeframe-Modus mit MQL5 lautet wie folgt:
- Es stellt sich heraus, dass die Erstellung eines Mehr-Währungs-EA in MQL5 sehr einfach ist und sich nicht wesentlich von einem Single-Currency Expert Advisor unterscheidet. Aber gerade bei Mehr-Währungs-EAs mit Multi-Timeframes ist es ein wenig komplizierter als einer für einen einzelnen Zeitrahmen.
- Die Erstellung eines Mehr-Währungs-EAs erhöht die Effizienz und Effektivität von Händlern, da sie nicht viele Chart-Symbole für den Handel öffnen müssen.
- Durch die Anwendung der richtigen Handelsstrategie erhöht sich die Gewinnwahrscheinlichkeit im Vergleich zur Verwendung eines Single-Currency Expert Advisors. Denn die Verluste, die bei einem Paar auftreten, werden durch Gewinne bei anderen Paaren ausgeglichen.
- Dieser TriangularMA_MTF_MCEA Multi-Currency Expert Advisor ist nur ein Beispiel, um zu lernen und Ideen zu entwickeln.
- Die Testergebnisse des Strategietesters sind immer noch nicht gut. Wenn also eine bessere Strategie mit genaueren Signalberechnungen implementiert wird und einige bessere Zeitrahmen hinzugefügt werden, glaube ich, dass die Ergebnisse besser sein werden als die aktuelle Strategie.
- Aus den Testergebnissen auf dem Strategy Tester des TriangularMA_MTF_MCEA geht hervor, dass die Ergebnisse von Single-Timeframe immer noch besser sind als Multi-Timeframe.
Anmerkung:
Wenn Sie eine Idee für die Erstellung eines einfachen Mehr-Währungs-EA auf der Grundlage der eingebauten MQL5-Standardindikatoren haben, schlagen Sie sie bitte in den Kommentaren vor.
Wir hoffen, dass dieser Artikel und das MQL5 Mehr-Währungs-EA-Programm für Händler beim Lernen und Entwickeln von Ideen nützlich sein werden. Danke fürs Lesen.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/13770
- 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.
Indem Sie den Artikel lesen, daraus lernen und den Beispielcode am Ende herunterladen.
Indem ich den Artikel lese, von ihm lerne und den Beispielcode am Ende herunterlade.
Bitte sagen Sie mir, wo ich den Beispielcode herunterladen kann.
Wie von Moderator Fernando Carreiro erklärt, schauen Sie ganz unten im Artikel auf die Bezeichnung Attached files und klicken Sie auf den Dateinamen.
Können Sie mir bitte sagen, wo ich den Beispielcode herunterladen kann?