
Wie man einen einfachen Multi-Currency Expert Advisor mit MQL5 erstellt (Teil 3): Hinzufügen von Symbolpräfixen und/oder -suffixen und der Handelszeiten
Einführung
Mehrere Handelskollegen schickten E-Mails oder kommentierten, wie man diesen Multi-Currency EA bei Brokern mit Symbolnamen, die Präfixe und/oder Suffixe haben, verwenden kann, und auch
wie man Handelszeitzonen oder die Zeiten der Handelssitzungen in diesem Multi-Currency EA implementiert.
Daher werde ich bei dieser Gelegenheit eine Funktion erklären und erstellen, die in dem EA FXSAR_MTF_MCEA des vorherigen Artikels implementiert wurde, indem ich eine automatische Erkennungsfunktion für Brokersymbole mit Präfixen und/oder Suffixen und Trading Time Zones hinzufüge.
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.
Im vorherigen Artikel habe ich gesagt, dass dieser Multi-Currency Expert Advisor nicht mit Brokern funktioniert, deren Symbol- oder Paarnamen Präfixe oder Suffixe haben.
Bei Expert Advisors (EAs), die nur mit einzelnen Währungen arbeiten (ein Paar, ein EA), gibt es keine Probleme mit Brokern, deren Symbolnamen Präfixe und/oder Suffixe enthalten.
In dem von mir erstellten Multiwährungs-EA wurde dies jedoch zu einem Problem, da wir zunächst 30 Paare registrierten, die mit den von vielen Brokern verwendeten Standardsymbolen gehandelt werden sollten. Diese Methode ist die schnellste und einfachste, wenn man die Namen der Paare nicht einzeln in die Experteneingabeeigenschaften eingeben muss.
Tatsächlich können Händler oder Programmierer, die EA-Prinzipien wie die von uns erstellten verwenden, alle 30 aufgelisteten Paare manuell bearbeiten und es wird keine Probleme verursachen.
Aber alle von uns, mich eingeschlossen, würden es eigentlich bevorzugen, wenn eine Funktion geschaffen würde, die automatisch mit Symbolnamen umgeht, die Präfixe und/oder Suffixe haben, sodass, wenn ein EA auf MetaTrader5 von einem Broker mit speziellen Symbolnamen 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 Paaren oder Symbolnamen für Forex und Metall im MT5 funktioniert, aber nicht bei nutzerdefinierten Symbolen und Indizes.
Da wir in dieser Version eine Handelssitzung (Handelszeitzone) hinzufügen, fügen wir auch 10 zu handelnde Optionspaare hinzu, die der Zeit der Handelssitzung entsprechen können.
Eines der 10 Optionspaare, die gehandelt werden, ist „Trader Wishes Pairs“, wobei die Paare, die gehandelt werden sollen, vom Händler manuell über die Experteneingabeeigenschaft eingegeben werden müssen.
Hinweis: Denken Sie immer daran, dass der Name des eingegebenen Paares bereits in der Liste der 30 Paare enthalten sein muss.
2. Handelssitzung (Zeitzone).
Wie wir wissen, hat die Metatrader-Plattform zwei Versionen: MT4 und MT5, die von der MetaQuotes Software Corporation 2005 (Metatrader4) und 2010 (Metatrader5) entwickelt wurden. Dieses Unternehmen ist russischen Ursprungs und führend auf dem Markt für Finanzsoftware.
Die Einstellung der MetaTrader5-Zeitverschiebung ist für jeden Broker unterschiedlich, abhängig von der Zeitzone des Brokers, die sich auf die GMT/UTC-Zeit bezieht. Sie können auch die Zeitverschiebung des Brokers für den Handelsserver oben links auf der Metatrader5-Plattform sehen. Aber im Allgemeinen bezieht sich die Handelszeit des Brokers auf den Börsenschluss der New Yorker Börse (NYEM), denn wenn der MetaTrader5 00:00 anzeigt, ist die NYEM geschlossen.
Der Devisenmarkt ist 24 Stunden am Tag, 5 Tage die Woche, weltweit geöffnet. Der Markt wird am Montag in Neuseeland um 8:00 Uhr Ortszeit oder 20:00 Uhr GMT/UTC eröffnet, gefolgt vom Beginn einer der wichtigsten Marktsitzungen in Sydney um 9:00 Uhr Montag Ortszeit, was 21:00 Uhr GMT/UTC am Sonntag entspricht. (Standardzeitverschiebung)
Um die Zeitzone für den Handel zu ermitteln, müssen wir zunächst die späteste Zeit der aktuellen Zeit des Handelsservers kennen. Dann müssen wir auch den Zeitunterschied (in Stunden) zwischen der Zeit des Händlerservers und der GMT/UTC-Zeit kennen. Die Zeitumstellung um 1 Stunde während der Sommerzeit hat keine Auswirkung auf die Zeit des Handelsservers, da die Zeit des Handelsservers von Metatrader5 ebenfalls um 1 Stunde vorgestellt wird.
Es gibt 5 Forex-Zeitzonen, die von Händlern in der Welt am häufigsten genutzt werden:
- Neuseeland öffnet um 20:00 Uhr und schließt um 05:00 Uhr GMT/UTC, d. h. zwischen 8:00 Uhr und 17:00 Uhr Ortszeit.
- Sydney öffnet um 21:00 Uhr und schließt um 7:00 Uhr GMT/UTC, also um 9:00 Uhr und 17:00 Uhr Ortszeit.
- Tokio öffnet um 00:00 Uhr und schließt um 9:00 Uhr GMT/UTC, also zwischen 8:00 Uhr und 18:00 Uhr Ortszeit.
- London öffnet um 9:00 Uhr morgens und schließt um 19:00 Uhr GMT/UTC, was 9:00 Uhr morgens und 19:00 Uhr abends Ortszeit entspricht.
- New York öffnet um 13:00 Uhr und schließt um 22:00 Uhr GMT/UTC, also zwischen 9:00 und 19:00 Uhr Ortszeit.
Umsetzung der Planung im Programm MQL5
1. Eingabe des Programmkopf und der Eigenschaften.
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; //---
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 }; //--
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 }; //--
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 }; //--
Enumeration zur Auswahl von 10 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 }; //--
Die Enumeration YN wird für die Optionen (Ja) oder (Nein) in den Experteneingabeeigenschaften verwendet.
//-- enum YN { No, Yes }; //--
Die Enumeration zur Bestimmung der Losgröße
//-- enum mmt { FixedLot, // Fixed Lot Size DynamLot // Dynamic Lot Size }; //--
Eigenschaften der Eingabe des Experten:
//--- input group "=== Select Pairs to Trade ==="; // Selected Pairs to trading input PairsTrade usepairs = All30; // Select Pairs to Use input string traderwishes = "eg. eurusd,usdchf,gbpusd,gbpchf"; // 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; // 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 = 2023102; // Expert ID (Magic Number) //---
In der Experten-Eingabeeigenschaftsgruppe Trade on Specific Time (Handel zu einem bestimmten Zeitpunkt) wählt der Händler aus:
um in einer bestimmten Zeitzone zu handeln (Ja) oder (Nein).
Wenn Ja, wählen Sie die Enumerationsoptionen aus:
- 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
Handel während der Custom Session:
In dieser Sitzung müssen die Händler die Zeit oder Stunden und Minuten für den Handelsbeginn und die Stunden und Minuten für den Handelsschluss festlegen. Der EA wird also nur während der angegebenen Zeit von der Startzeit bis zur Endzeit 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.
2. Klasse für funktionierenden Expert Advisor.
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 zur Erkennung von Präfix-Symbolnamen und/oder Suffix-Symbolnamen verwendet werden, sowie die Zeitzonenberechnungen haben wir in der MCEA-Klasse vorgenommen.
//+------------------------------------------------------------------+ //| 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; string pre,suf; //--- Variables are used in Trading Time Zone int ishour, onhour; 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 differ; 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); int GetPSARSignalMTF(string symbol); int PARSAR05(const string symbol); int PARSARMTF(const string symbol,ENUM_TIMEFRAMES mtf); 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: //--- //-- FXSAR_MTF_MCEA_sptz 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 hPar05[]; int hPSAR[][5]; int ALO, dgts, arrsar, arrsymbx; int sall, arusd, aretc, arspc, arper; ulong slip; //-- double SARstep, SARmaxi; 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, TFT05, TFSAR[]; //-- bool PanelExtra; //------------ MCEA(void); ~MCEA(void); //------------ //-- virtual void FXSAR_MTF_MCEA_sptz_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 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 FXSAR_MTF_MCEA_sptz_Config().
In der Funktion FXSAR_MTF_MCEA_sptz_Config() werden alle zu verwendenden Symbole, alle verwendeten Handle-Indikatoren und einige wichtige Funktionen des Include-Dateikopfes für den Expert Advisor Workflow konfiguriert.
//+------------------------------------------------------------------+ //| Expert Configuration | //+------------------------------------------------------------------+ void MCEA::FXSAR_MTF_MCEA_sptz_Config(void) { //--- //-- HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded //-- TFT05=PERIOD_M5; ENUM_TIMEFRAMES TFA[]={PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1}; TFArrays=ArraySize(TFA); ArrayResize(TFSAR,TFArrays,TFArrays); ArrayCopy(TFSAR,TFA,0,0,WHOLE_ARRAY); //-- TFt=TFSAR[2]; //-- //-- iSAR Indicators handle for all symbol for(int x=0; x<arrsymbx; x++) { hPar05[x]=iSAR(DIRI[x],TFT05,SARstep,SARmaxi); //-- for(int i=0; i<TFArrays; i++) { hPSAR[x][i]=iSAR(DIRI[x],TFSAR[i],SARstep,SARmaxi); } } //-- ALO=(int)mc_account.LimitOrders()>arrsymbx ? arrsymbx : (int)mc_account.LimitOrders(); //-- LotPS=(double)ALO; //-- mc_trade.SetExpertMagicNumber(magicEA); mc_trade.SetDeviationInPoints(slip); mc_trade.SetMarginMode(); Set_Time_Zone(); //-- return; //--- } //-end FXSAR_MTF_MCEA_sptz_Config() //---------//
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);} //-- 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, die Präfixe und/oder Suffixe haben, erkennen und behandeln.
void MCEA::SetSymbolNamePS(void) { //--- int sym_Lenpre=0; int sym_Lensuf=0; string sym_pre=""; string sym_suf=""; 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() //---------//
3. Experten-Tick-Funktion.
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 ExpertActionTrade()-Funktion 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 Handel mit Zeitzonen 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() //---------//
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() //---------//
Einige unterstützende Funktionen für Zeitberechnungen sind:
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() //---------// 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() //---------// string MCEA::timehr(int hr,int mn) { //--- string scon=""; string men=mn==0 ? "00" : string(mn); int shr=hr==24 ? 0 : hr; if(shr<10) scon="0"+string(shr)+":"+men; else scon=string(shr)+":"+men; //-- return(scon); //--- } //-end timehr() //---------// string MCEA::ReqDate(int d,int h,int m) { //--- MqlDateTime mdt; datetime t=TimeCurrent(mdt); x_year=mdt.year; x_mon=mdt.mon; x_day=d; x_hour=h; x_min=m; x_sec=mdt.sec; //-- string mdr=string(x_year)+"."+string(x_mon)+"."+string(x_day)+" "+timehr(x_hour,x_min); return(mdr); //--- } //-end ReqDate() //---------// int MCEA::ThisTime(const int reqmode) { //--- MqlDateTime tm; TimeCurrent(tm); int valtm=0; //-- switch(reqmode) { case 0: valtm=tm.year; break; // Return Year case 1: valtm=tm.mon; break; // Return Month case 2: valtm=tm.day; break; // Return Day case 3: valtm=tm.hour; break; // Return Hour case 4: valtm=tm.min; break; // Return Minutes case 5: valtm=tm.sec; break; // Return Seconds case 6: valtm=tm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) case 7: valtm=tm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero) } //-- return(valtm); //--- } //-end ThisTime() //---------// int MCEA::ReqTime(datetime reqtime, const int reqmode) { MqlDateTime tm; TimeToStruct(reqtime,tm); int valtm=0; //-- switch(reqmode) { case 0: valtm=tm.year; break; // Return Year case 1: valtm=tm.mon; break; // Return Month case 2: valtm=tm.day; break; // Return Day case 3: valtm=tm.hour; break; // Return Hour case 4: valtm=tm.min; break; // Return Minutes case 5: valtm=tm.sec; break; // Return Seconds case 6: valtm=tm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) case 7: valtm=tm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero) } //-- return(valtm); //--- } //-end ReqTime() //---------//
4. Wie erhalten wir die Handelssignale für das Öffnen oder Schließen von Positionen?
Im vorherigen Artikel habe ich Multi-Zeitrahmen-Signale auf der Grundlage von 5 Zeitrahmen
void MCEA::FXSAR_MTF_MCEA_Config(void) { //--- ENUM_TIMEFRAMES TFA[]={PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1}; TFArrays=ArraySize(TFA); ArrayResize(TFSAR,TFArrays,TFArrays); ArrayCopy(TFSAR,TFA,0,0,WHOLE_ARRAY); //-- return; //--- } //-end FXSAR_MTF_MCEA_Config() //---------//
Aber in diesem Artikel, änderte ich die Multi-Zeitrahmen-Signal Basis 4 Zeitrahmen, beginnend mit M5, M30, H1 und schließlich H4.
void MCEA::FXSAR_MTF_MCEA_sptz_Config(void) { //--- //-- ENUM_TIMEFRAMES TFA[]={PERIOD_M5,PERIOD_M30,PERIOD_H1,PERIOD_H4}; TFArrays=ArraySize(TFA); ArrayResize(TFSAR,TFArrays,TFArrays); // TFArrays now the value of array size is 4 ArrayCopy(TFSAR,TFA,0,0,WHOLE_ARRAY); //-- return; //--- } //-end FXSAR_MTF_MCEA_sptz_Config() //---------//
Um also ein Multi-Zeitrahmen-PSAR-Signal zu erhalten, rufen wir die Funktion GetPSARSignalMTF() auf, um die Position des ParabolicSAR-Indikators im gewünschten Zeitrahmen zu erhalten,
int MCEA::GetPSARSignalMTF(string symbol) { //--- int mv=0; int rise=1, down=-1; //-- int sarup=0, sardw=0; //-- for(int x=0; x<TFArrays; x++) // The TFArrays variable has a value of 54which is taken from the number of time frames from TF_M5, M30, H1 and H4. { if(PARSARMTF(symbol,TFSAR[x])>0) sarup++; if(PARSARMTF(symbol,TFSAR[x])<0) sardw++; } //-- if(sarup==TFArrays) mv=rise; if(sardw==TFArrays) mv=down; //-- return(mv); //--- } //- end GetPSARSignalMTF() //---------//
Dann wird das entsprechende Indikator-Handle aufgerufen, um den Pufferwert des iSAR-Indikators für den angeforderten Zeitrahmen zu erhalten.
int MCEA::PARSARMTF(const string symbol,ENUM_TIMEFRAMES mtf) // formula Parabolic SAR in set timeframe { //--- int ret=0; int rise=1, down=-1; //-- int br=2; //-- double PSAR[]; ArrayResize(PSAR,br,br); ArraySetAsSeries(PSAR,true); int xx=PairsIdxArray(symbol); int tx=TFIndexArray(mtf); CopyBuffer(hPSAR[xx][tx],0,0,br,PSAR); //-- double OPN0=iOpen(symbol,TFSAR[tx],0); double HIG0=iHigh(symbol,TFSAR[tx],0); double LOW0=iLow(symbol,TFSAR[tx],0); double CLS0=iClose(symbol,TFSAR[tx],0); //-- if(PSAR[0]<LOW0 && CLS0>OPN0) ret=rise; if(PSAR[0]>HIG0 && CLS0<OPN0) ret=down; //-- return(ret); //--- } //-end PARSARMTF() //---------//
Die Funktion GetPSARSignalMTF wird von GetOpenPosition() aufgerufen, um ein Handelssignal für eine offene Position zu erhalten.
int MCEA::GetOpenPosition(const string symbol) // Signal Open Position { //--- int ret=0; int rise=1, down=-1; //-- int dirmov=DirectionMove(symbol); int parsOp=GetPSARSignalMTF(symbol); //-- if(parsOp==rise && dirmov==rise) ret=rise; if(parsOp==down && dirmov==down) ret=down; //-- return(ret); //--- } //-end GetOpenPosition() //---------//
Die Funktion GetPSARSignalMTF() ruft eine Funktion PARSARMTF() auf, die das iSAR-Signal entsprechend dem gewünschten Zeitrahmen berechnet.
Wie Sie sehen können, werden innerhalb der Funktion PARSARMTF() 2 Funktionen verwendet und aufgerufen:
1. int xx= PairsIdxArray(symbol)
Die Funktion PairsIdxArray() wird verwendet, um den Namen des gewünschten Symbols zu erhalten.
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() //---------//
2. int tx=TFIndexArray(mtf).
Die Funktion TFIndexArray() wird verwendet, um die Zeitrahmen-Array-Sequenz des angeforderten Zeitrahmens zu erhalten.
int MCEA::TFIndexArray(ENUM_TIMEFRAMES TF) { //--- int res=-1; //-- for(int x=0; x<TFArrays; x++) { if(TF==TFSAR[x]) { res=x; break; } } //-- return(res); //--- } //-end TFIndexArray() //---------//
5. Die Funktion ChartEvent
Um die Effektivität und Effizienz bei der Verwendung von Mehr-Währungs-EAs zu unterstützen, wird es als notwendig erachtet, manuelle Schaltflächen für die Verwaltung von Aufträgen und das Ändern von Charts oder Symbolen einzurichten. Da diese Version 10 Optionen für den Handel mit Paaren verwendet, wurde die Funktion OnChartEvent leicht geändert.
//+------------------------------------------------------------------+ //| 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 eine Handelssitzung oder eine Handelszeitzone und Optionen für die Paare, die gehandelt werden, hinzufügen, benötigen wir zusätzliche Informationen in den angezeigten Handelsinformationen im 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 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() //---------//
Wir fügen eine Funktion hinzu, die die Zeit entsprechend den Bedingungen der Handelszeitzone erklärt
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 Anzeige von TradeInfo() sieht dann wie in der folgenden Abbildung aus.
Anmerkungen: Für andere Funktionen und Algorithmen gilt dasselbe wie für den Multi-Currency Expert Advisor im vorherigen Artikel.
Unter dem Namen des Expert Advisors FXSAR_MTF_MCEA finden Sie die Schaltflächen „M“, „C“ und „R“.
Wenn die Schaltfläche „M“ oder „C“ angeklickt wird, wird ein manuelles Schaltflächenfeld angezeigt (siehe unten).
Wenn die Schaltfläche M angeklickt wird, wird ein manuelles Schaltfeld angezeigt, über das der Händler Aufträge verwalten kann:
- Set SL/TP All Orders (SL/TP für alle Aufträge einstellen)
- Close All Orders (Alle Aufträge schließen)
- 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.
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-15)*22),true,"Change to "+mc.AS30[i]); //-- ChartRedraw(0); //-- return; //--- } //-end CreateSymbolPanel() //---------//
Wenn die Schaltfläche R angeklickt wird, wird der Multi-Currency Expert Advisor FXSAR_MTF_MCEA aus dem Chart entfernt.
Strategietester
Ich habe einen Backtest durchgeführt, indem ich verschiedene Zeitzonen und Paare ausprobiert habe, die gehandelt werden sollten.
Die Ergebnisse im Strategy Tester sind in der nachstehenden Abbildung zu sehen.
Im folgenden Backtest ist die Zeitzone auf US New York eingestellt
Im folgenden Backtest ist die Zeitzone auf Asien/Tokio eingestellt
Im folgenden Backtest ist die Zeitzoneneinstellung auf „Trader Custom time zone“ (nutzerdefinierte Handelssitzung) eingestellt
Schlussfolgerung
- Das Problem, dass Symbolnamen von Brokern Präfix- und/oder Suffix-Namen in Mehrwährungs-EAs haben, kann leicht gelöst werden und läuft reibungslos mit MQL5, ohne dass nutzerdefinierte Symbole erstellt werden müssen.
- Durch das Hinzufügen einer Handelssitzung oder einer Handelszeitzone und von 10 Optionspaaren, die gehandelt werden können, hofft man, dass die Händler eine bessere Strategie entwickeln, indem sie nur mit bestimmten Paaren und zu bestimmten Zeiten oder Sitzungen handeln.
- Dieser Multi-Währungs-EA ist nur ein Beispiel zum Lernen und Entwickeln von Ideen. Wenn Sie also Ideen zur Verbesserung haben, lade ich Sie ein, diesen EA-Code nach Ihren Wünschen zu ändern.
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/13705





- 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.