English Русский Español Deutsch 日本語 Português
preview
如何利用 MQL5 创建简单的多币种智能交易系统(第 3 部分):添加交易品种、前缀和/或后缀、以及交易时段

如何利用 MQL5 创建简单的多币种智能交易系统(第 3 部分):添加交易品种、前缀和/或后缀、以及交易时段

MetaTrader 5交易 | 10 六月 2024, 10:57
440 0
Roberto Jacobs
Roberto Jacobs

概述

若干交易员同事发送电子邮件或评论了如何基于经纪商提供的名称里带有前缀和/或后缀的品种使用此多币种 EA,以及

如何在该多币种 EA 上实现交易时区或交易时段。

因此,在这种境况下,我将解释并在上一篇文章中实现的 EA 中创建一个函数 FXSAR_MTF_MCEA,为其添加自动检测经纪商提供的带有前缀和/或后缀的品种、以及交易时区的功能。


计划和功能

1. 交易货币对。

该多币种智能交易系统计划在如下品种或货币对上进行交易: 

对于外汇:

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 对

加上 2 种贵金属对:XAUUSD(黄金)和 XAGUSD(白银)

总共是 30 对。


上一篇文章中,我说过,这个多币种智能交易系统不适用于经纪商提供的含有前缀或后缀的品种或货币对。

在仅适用于单一货币对的 EA 中(一个 EA 只对一个货币对起作用),经纪商的品种名称含有前缀和/或后缀也不会出现任何问题。

但是在我创建的多币种 EA 中,这成了一个问题,因为我们首先注册了 30 对,这些交易的货币对是许多经纪商常用的标准品种名称。相比必须在在智能系统属性输入栏中逐个输入货币对名称,这样做是最快捷和最简单的,且存在出现拼写错误的可能性。

实际上,喜欢我们创建 EA 原则的交易者或编码人员,可以手工编辑列出所有 30 对,且不会导致任何问题。

但是我们所有人,包括我,实际上都希望创建一个函数来自动处理具有前缀和/或后缀的品种名称,如此这般,若在 MetaTrader5 上经纪商使用特殊品种名称,EA 也能顺利处理一切。

检测含有前缀和后缀品种名称的函数,其弱点在于仅适用于 MT5 中外汇货币对和贵金属等品种名称,而不适用于自定义品种和指数。

在这个版本中,因为我们加了一个交易时段(交易时区),我们还要加上 10 个选项对进行交易,这些选项对可能与交易时段的时间相对应。

将被交易的 10 个选项对之一是“交易者愿望对”,其中将要交易的对必须由交易者在智能系统属性输入栏里手工输入。

注意:永远记住,输入的对名称必须已经在 30 对列表之中。



2. 交易时段(时区)。

众所周知,Metatrader 平台有两个版本:MT4 和 MT5,分别由 MetaQuotes 软件公司创建于 2005 年(Metatrader4)和 2010 年(Metatrader5)。该公司源自俄罗斯,是金融软件市场的领导者。

每个交易商的 MetaTrader5 时间偏移设置是不同的,这取决于交易商的时区,即 GMT/UTC 时间。您还可以在 Metatrader5 平台的左上角看到交易服务器的经纪商时间偏移设置。但通常,经纪商的交易时间服务器是指纽约交易市场(NYEM)的收盘时间,因为当 MetaTrader5 显示 00:00 时,NYEM 正在收盘。

外汇市场每周 5 天、每天 24 小时开市。市场首先于新西兰当地时间周一上午 8:00 或格林威治标准时间/世界标准时间 20:00 开盘,随后于当地时间周一上午 9:00(格林威治标准时间/世界标准时间周日 21:00)在悉尼开始主要市场交易时段之一。(标准时间偏移量)

若要获取交易时区,我们必须首先据交易服务器的当前时间知道最后的时间。然后,我们还必须知道与 GMT/UTC 时间相比,交易者服务器的时差(以小时为单位)。在夏令时期间将时间提前 1 小时对交易服务器的时间没有影响,因为 Metatrader5 的交易服务器时间也会提前 1 小时。

世界范围有 5 个外汇时区交易者使用最广泛:

  • 新西兰开盘时间为 20:00,收盘时间为格林威治标准时间/世界标准时间上午 05:00,即当地时间上午 8:00 至下午 5:00。
  • 悉尼的开盘时间为格林威治标准时间/世界标准时间上午 7:00,即当地时间上午 9:00 至下午 5:00。
  • 东京的开盘时间为 00:00,收盘时间为格林威治标准时间上午 9:00,即当地时间上午 8:00 至下午 6:00。
  • 伦敦上午 9:00 开盘,格林威治标准时间/UTC 时间 19:00 收盘,即当地时间上午 9:00 至晚上 7:00。
  • 纽约在格林威治标准时间/世界标准时间 13:00 开盘,22:000 收盘,即当地时间上午 9:00 至晚上 7:00。


    在 MQL5 程序中实现计划

    1. 程序头文件和属性输入。

    包含 MQL5 头文件

    //+------------------------------------------------------------------+
    //|                             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;
    //---


    时区使用的枚举

    //--
    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
     };
    //--


    选择时间钟点的枚举

    //--
    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
      };
    //--


    选择时间分钟的枚举

    //--
    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
      };
    //--


    选择 10 个要交易选项对的枚举

    //--
    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
     };   
    //--


    枚举 YN 是智能系统属性输入中的选项(Yes)或(No)

    //--
    enum YN
      {
       No,
       Yes
      };
    //--


    资金管理手数的枚举

    //--
    enum mmt
      {
       FixedLot,   // Fixed Lot Size
       DynamLot    // Dynamic Lot Size
      };
    //--


    智能系统属性输入

    //---
    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)
    //---


    在智能系统输入属性组 “Trade on Specific Time(在特定时段交易)” 中,交易者将在此处选择:

    在特定时区进行交易(是)或(否)。

    如果是,选择列举选项:

    • Trading on Custom Session(在自定义时段交易)
    • Trading on New Zealand Session(在新西兰时段交易)
    • Trading on Australia Sydney Session(在澳大利亚悉尼时段交易)
    • Trading on Asia Tokyo Session(在亚洲东京时段交易)
    • Trading on Europe London Session(在欧洲伦敦时段交易)
    • Trading on America New York Session(在美国纽约时段交易)

    在自定义时段进行交易

    在该时段,交易者必须设置交易开盘时间(钟点和分钟),以及交易收盘时间(钟点和分钟)。故此,EA 只会在开盘时间至收盘时间的指定时间范围内运作。

    在新西兰时段交易到美国纽约时段交易中,从交易开始到交易结束的时间由 EA 计算。


    2. 工作 EA 的类。

    为该多币种智能交易系统声明所需的全部变量、对象和函数,我们将创建一个类来为智能交易系统指定工作流中的构造和配置。

    特别是,函数中所用的检测品种名称前缀和/或后缀、以及时区计算的变量,我们都在 MCEA 类中进行计算。

    //+------------------------------------------------------------------+
    //| 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
    //---------//


    在多币种智能交易系统工作流程中,从 OnInit() 调用的首要函数是 FXSAR_MTF_MCEA_sptz_Config()。

    在 FXSAR_MTF_MCEA_sptz_Config() 函数中,配置了所有要用到的品种,所有用到的指标句柄,以及包含头文件里一些交易系统工作流程所需的重要函数。

    //+------------------------------------------------------------------+
    //| 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()
    //---------//


    为了配置要交易的货币对,我们将调用 HandlingSymbolArrays() 函数。

    调用 HandlingSymbolArrays() 函数,我们将处理所有将要交易的货币对。

    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()
    //---------// 


    在 HandlingSymbolArrays() 函数中,我们将调用 SetSymbolNamePS() 函数。

    调用 SetSymbolNamePS() 函数,我们就能够检测和处理含有前缀和/或后缀的品种名称。

    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. 智能系统跳价函数

    在智能系统跳价函数(OnTick() 函数)中,我们将调用多币种智能系统中的主要函数之一,即 ExpertActionTrade() 函数。

    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick(void)
      {
    //---
        mc.ExpertActionTrade();
        //--
        return;
    //---
      } //-end OnTick()
    //---------//


    该函数内 EA 按顺序操作处理。

    ExpertActionTrade() 函数将运作所有活动,并管理自动交易,从开单开始,然后是平单、尾随停止、或止盈、及其它附加活动。

    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()
    //---------//


    特别是对于交易时区,在 ExpertActionTrade() 函数中,加入了调用 Trade Session() 布尔函数。

    如果 Trade_session() 为真,则 EA 工作流程将继续进行,直到完成;但如果为假,则 EA 将仅执行“Close Trade and Save profit due to weak signal (Yes) — 因疲软信号而平仓交易并保存利润(是)” 和 “Trailing Stop (Yes) — 尾随停止(是)” 的任务。

    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()
    //---------//

    时间计算的一些支持函数:

    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. 如何得到开仓或平仓的交易信号?

    上一篇文章中,我基于 5 个时间帧获取多时间帧信号

    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()
    //---------//
    


    但在本文中,我更改了多时间帧信号的基数为 4 时间帧,开始从 M5、M30、H1、最后是 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()
    //---------//


    因此,为了获得多时间帧 PSAR 信号,我们将调用函数 GetPSARSignalMTF() 来获取抛物线 SAR 指标在所请求时间帧上的位置,

    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()
    //---------//


    然后调用相应的指标句柄,从所请求时间帧中获取 iSAR 指标的缓冲区值。

    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()
    //---------//


    从 GetOpenPosition() 调用 GetPSARSignalMTF 函数来获取开仓的交易信号。

    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()
    //---------//


    GetPSARSignalMTF() 函数将调用一个函数 PARSARMTF(),该函数根据请求计算相应时间帧的 iSAR 信号。

    正如您所见,在 PARSARMTF() 函数中,我们调用了 2 个函数:

    1. int xx= PairsIdxArray(symbol)

    PairsIdxArray() 函数获取所请求品种的名称。

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

    TFIndexArray() 函数获取所请求时间帧的数组序列。

    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. ChartEvent 函数

    为了支持多币种智能交易系统的有效性和效率,有必要在管理订单和更改图表或交易品种时创建几个手工按钮。由于此版本用到 10 个选项对进行交易,因此 OnChartEvent 函数略有更改。

    //+------------------------------------------------------------------+
    //| 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()
    //---------//


    为了一键更改图表品种,当单击其中一个品种名称时,OnChartEvent() 将调用函数 ChangeChartSymbol()。

    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()
    //---------//


    由于我们正在为即将交易的货币对添加交易时段、或交易时区、以及选项,因此我们需要在图表上显示的交易信息中提供其它信息。

    为了将信息追加到图表上显示的交易信息,我们对 TradeInfo() 函数进行了修改。

    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()  
    //---------//


    我们添加了一个函数来根据交易时区条件解释时间

    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()
    //---------//


    TradeInfo() 的显示如下图所示。

    waiting_time


    注意: 对于其它函数和算法,它与上一篇文章中的多币种智能交易系统相同。


    如您所见,名为 FXSAR_MTF_MCEA 的智能交易系统有按钮 “M”、“C” 和 “R”

    如果单击 “M” 或 “C” 按钮,将显示手工单击按钮面板,如下所示

    MCR_Combine

    如果点击 ”M“ 按钮,将显示手工点击按钮面板,然后交易者可以管理订单:

    1. Set SL/TP All Orders — 为所有订单设置止损/止盈
    2. Close All Orders — 所有订单平仓
    3. Close All Profits — 所有盈利单平仓

    如果单击 ”C“ 按钮,将显示一个包含 30 个品种名称或货币对的面板按钮,交易者可以单击其中一个货币对名称或品种名称。如果单击其中一个货币对或品种名称,则图表品种将立即替换为所单击品种名称。

    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()
    //---------//

    如果单击 ”R“ 按钮,则多币种智能交易系统 FXSAR_MTF_MCEA 将从图表中删除


    策略测试器

    我做了回溯测试,尝试若干个将会交易的时区和货币对。

    策略测试器中的结果如下图所示。

    在下面的回溯测试中,时区设置选择位于美国纽约

    策略测试器 FXSAR_MTF_MCEA_sptz_01


    在下面的回溯测试中,时区设置选择位于亚洲/东京

    策略测试器 FXSAR_MTF_MCEA_sptz_02


    在下面的回溯测试中,时区设置选择在交易者自定义时区

    策略测试器 FXSAR_MTF_MCEA_sptz_03


    结束语

    1. 在多币种 EA 中,经纪商的品种名称含有前缀和/或后缀的问题,可以通过 MQL5 轻松解决并顺利运行,而无需创建自定义品种。
    2. 通过添加交易时段或交易时区,并添加 10 个想要交易的选项对,交易者希望仅在特定时间或时段,针对特定货币对进行交易来获得更好的策略。
    3. 这个多币种 EA 只是一个学习和开拓思路的示例,所以如果您有改进的想法,我邀请您根据自己的意愿修改这个 EA 代码。

    希望本文和 MQL5 多币种智能交易系统程序能对交易者学习和开拓思路有所帮助。感谢您的阅读。


    本文由MetaQuotes Ltd译自英文
    原文地址: https://www.mql5.com/en/articles/13705

    附加的文件 |
    群体优化算法:带电系统搜索(CSS)算法 群体优化算法:带电系统搜索(CSS)算法
    在本文中,我们将探讨另一种受无生命自然启发的优化算法--带电系统搜索(Charged System Search,CSS)算法。本文旨在介绍一种基于物理和力学原理的新的优化算法。
    神经网络变得简单(第 62 部分):在层次化模型中运用决策转换器 神经网络变得简单(第 62 部分):在层次化模型中运用决策转换器
    在最近的文章中,我们已看到了运用决策转换器方法的若干选项。该方法不仅可以分析当前状态,还可以分析先前状态的轨迹,以及在其中执行的动作。在本文中,我们将专注于在层次化模型中运用该方法。
    神经网络变得简单(第 63 部分):决策转换器无监督预训练(PDT) 神经网络变得简单(第 63 部分):决策转换器无监督预训练(PDT)
    我们将继续讨论决策转换器方法系列。从上一篇文章中,我们已经注意到,训练这些方法架构下的转换器是一项相当复杂的任务,需要一个大型标记数据集进行训练。在本文中,我们将观看到一种使用未标记轨迹进行初步模型训练的算法。
    Scikit-Learn 库中的分类模型及其导出到 ONNX Scikit-Learn 库中的分类模型及其导出到 ONNX
    在本文中,我们将探讨使用 Scikit-Learn 库中所有可用的分类模型来解决 Fisher 鸢尾花数据集的分类任务。我们将尝试把这些模型转换为 ONNX 格式,并在 MQL5 程序中使用生成的模型。此外,我们将在完整的鸢尾花数据集上比较原始模型与其 ONNX 版本的准确性。