English Русский Español Deutsch 日本語 Português
preview
如何利用 MQL5 创建简单的多币种智能交易系统(第 2 部分):指标信号:多时间帧抛物线 SAR 指标

如何利用 MQL5 创建简单的多币种智能交易系统(第 2 部分):指标信号:多时间帧抛物线 SAR 指标

MetaTrader 5示例 | 20 五月 2024, 11:11
421 0
Roberto Jacobs
Roberto Jacobs

概述

本文中多币种智能交易系统的定义是一款智能交易系统或交易机器人,它可以从一个品种图表中交易 1 个以上的品种对(开单、平单、及管理订单,例如:尾随止损和止盈),在本文中,智能交易系统将交易 30 个对。这次我们只用 1 个指标,即抛物线 SAR 或 iSAR,将其应用在 PERIOD_M15 到 PERIOD_D1 的多个时间帧。

我们都知道,在交易终端和策略测试器上进行多币种交易,都可以借助 MQL5 提供的强大能力和设施。

因此,我们的目标是满足那些想要高效和有效的交易机器人的交易者的基本需求,故此,依靠高度可靠的 MQL5 提供的能力和设施,我们可以创建一款简单的多币种智能交易系统,在本文中使用指标信号:多时间帧抛物线 SAR 或 iSAR 指标。



计划和功能

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 对。

注意:所有这些交易品种或货币对都是经纪商常用的交易品种或货币对。因此,该多币种智能交易系统不适用于经纪商提供的名称含有前缀或后缀的品种或货币对。


2. 信号指标。

多币种智能交易系统将用 1 个指标信号,但有 5 个时间帧,始自 PERIOD_M15、PERIOD_M30、PERIOD_H1、PERIOD_H4 和 PERIOD_D1。

在该智能交易系统中,它不使用固定的时间帧来计算指标信号,故无需检测信号计算时间帧。

这意味着 FXSAR_MTF_MCEA 智能交易系统可在从 PERIOD_M1 到 PERIOD_MN1 的任何时间帧内使用,并且 FXSAR_MTF_MCEA 仍将基于 iSAR PERIOD_M15、PERIOD_M30、PERIOD_H1、PERIOD_H4 和 PERIOD_D1 计算信号。

这五个抛物线 SAR 时间帧将检测开单的信号。

同时,在订单处于盈利条件下,若 iSAR 指标 PERIOD_M15 的信号疲软时平单。

若要尾随止损和止盈,则用 iSAR 指标的 PERIOD_H1。


iSAR 信号条件策略公式:

上行 =(PRICE_LOW[0] 大于 iSAR 线),或 PRICE_LOW[0] > iSAR[0]

下行 =(PRICE-HIGH[0] 小于 iSAR 线),或 PRICE-HIGH[0] < iSAR[0]

从哪里获得买入信号或卖出信号:

五个 iSAR 指标时间帧,必须总计 5 x 上行是为买入,5 x 下行是为卖出。

iSAR 指标买入和卖出的描绘,参见图例 1

iSAR_Signal 买入和卖出


3. 交易和订单管理

该多币种智能交易系统的交易管理有多种选项:

1. 止损单。   

  • 选项:使用订单止损(是)或(否)           

如果选中“使用订单止损(否)”选项,则所有订单在开单时都不带止损。            

如果选项“使用订单止损(是)”:再次给出选项:使用自动计算止损(是)或(否)            

如果选项是“自动计算止损(是)”,则将由智能系统自动执行止损计算。

如果选项是“自动计算止损(否)”,则交易者必须以点数为单位输入止损值。

如果选项是“使用订单止损(否)”:则智能系统将检查每笔开单,信号条件是否仍然良好,且订单            

或许维持盈利,或者信号疲软,需要平单以确保            

盈利,或信号条件方向已逆转,持仓亏损也必须平仓。


2. 止盈单。

  • 选项:使用订单止盈(是)或(否)

如果选中“使用订单止盈”(否)选项,则所有订单在开单时都不带止盈。

如果选项是“使用订单止盈“(是):再次给出选项:使用自动计算订单止盈(是)或(否)

如果选项是“自动计算订单止盈”(是),则将由智能系统自动执行止盈计算。

如果选项是“自动计算订单止盈“(否),则交易者必须以点数输入订单止盈值。


3. 尾随止损和尾随止盈
  • 选项:使用尾随止损/止盈(是)或(否)
如果”使用尾随止损/止盈“选项为(否),则智能系统不会执行尾随止损和尾随止盈。如果选项”使用尾随止损/止盈“(是):再次给出选项:使用自动尾随(是)或(否)如果选项”使用自动尾随“(是),则尾随止损将由智能系统依据抛物线 SAR 的 PERIOD_H1 值执行,同时基于变量值 TPmin(尾随止盈值)进行尾随止盈。如果选项是”使用自动尾随“(否),则智能系统将采用输入属性中的值执行尾随止损。
注意:智能系统将同时执行尾随止盈和尾随止损。


4. 手动订单管理。

为了提高该多币种智能交易系统的效率,将添加若干个手动单击按钮

1. 为所有订单设置止损/止盈

当交易者在输入参数设置”使用订单止损“(否)和/或”使用订单止盈“(否)时

但随后交易者打算针对所有订单使用止损或止盈,然后只需单击“设置止损/止盈所有订单”按钮,所有订单将被修改,止损和/或止盈将被应用。


2. 所有订单平仓

如果交易者想要所有订单平仓,那么只需单击 “所有订单平仓” 按钮,所有持仓将被平仓。


3. 所有盈利订单平仓

如果交易者想把所有盈利订单平仓,那么只需单击“所有盈利订单平仓”按钮即可 

把所有盈利持仓都平仓。


5. 管理订单和品种图表。

对于仅从单一品种图表交易 30 对的多币种智能系统,如果为所有品种提供按钮面板,这将非常有效和高效,如此交易者只需单击一下即可更改图表或品种。



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


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

enum YN
 {
   No,
   Yes
 };


资金管理手数的枚举

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


智能系统输入属性

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


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

//+------------------------------------------------------------------+
//| 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;
    int              posCur1,
                     posCur2;        
    //--
    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;
     
    //------------
    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 Config --
    string           DIRI[],
                     AS30[];
    string           expname;
    int              hPar05[];   // Handle for the iSAR indicator for M5 Timeframe
    int              hPSAR[][5]; // Handle Indicator, where each Symbol has 5 arrays for Timeframe starting from TF_M15 to TF_D1
    int              ALO,
                     dgts,
                     arrsar,
                     arrsymbx;
    int              sall,
                     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_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              TFIndexArray(ENUM_TIMEFRAMES TF);
    int              GetOpenPosition(const string symbol);
    int              GetCloseInWeakSignal(const string symbol,int exis);
    int              ThisTime(const int reqmode);
    //--
    string           getUninitReasonText(int reasonCode);
    //------------
//---
  }; //-end class MCEA


在多币种智能交易系统工作过程中,自 OnInit() 调用的第一个也是最重要的函数是 FXSAR_MTF_MCEA_Config()。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//---
   mc.FXSAR_MTF_MCEA_Config();
   //--
   return(INIT_SUCCEEDED);
//---
  } //-end OnInit()


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

//+------------------------------------------------------------------+
//| Expert Configuration                                             |
//+------------------------------------------------------------------+
void MCEA::FXSAR_MTF_MCEA_Config(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
    //--
    sall=ArraySize(All30);
    ArrayResize(AS30,sall,sall);
    ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY);
    //--
    arrsymbx=sall;
    ArraySymbolResize();
    ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
    for(int x=0; x<arrsymbx; x++) {SymbolSelect(DIRI[x],true);}
    pairs="Multi Currency 30 Pairs";
    //--
    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);  //-- Handle for the iSAR indicator for M5 Timeframe
        //--
        for(int i=0; i<TFArrays; i++)
          {
            hPSAR[x][i]=iSAR(DIRI[x],TFSAR[i],SARstep,SARmaxi); // Handle for iSAR Indicator array sequence of the requested timeframe
          }
      }
    //--
    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();
    //--
    return;
//---
  } //-end FXSAR_MTF_MCEA_Config()


2. 智能系统跳价函数

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

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


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


3. 如何获得开仓或平仓的交易信号?

若要获取指标信号,我们必须调用函数 GetOpenPosition(symbol) 来获取开仓的交易信号

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

GetOpenPosition() 函数将调用 2 个信号函数,并存储在变量 OpOr[] 当中。

1. DirectionMove(symbol);         //--函数检查价格在智能系统周期内是否在烛条柱上移动。
2. GetPSARSignalMTF(symbol);   //-- 函数在请求的时间帧内计算抛物线 iSAR 公式。
int MCEA::GetPSARSignalMTF(string symbol) // iSAR MTF signal calculation
  {
//---
    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 5 which is taken from the number of time frames from TF_M1 to TF_H1.
      {
        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()


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

正如您所看到的,在 PARSARMTF() 函数中,我们使用并调用了 2 个函数:

1. int xx= PairsIdxArray(symbol)

2. int tx=TFIndexArray(mtf).

PairsIdxArray() 函数获取所请求品种的名称,TFIndexArray() 函数获取所请求时间帧的数组序列。

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

int MCEA::PARSARMTF(const string symbol,ENUM_TIMEFRAMES mtf) // formula Parabolic iSAR on the requested 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()


int MCEA::PairsIdxArray(const string symbol)
  {
//---
    int pidx=0;
    //--
    for(int x=0; x<arrsymbx; x++)
      {
        if(DIRI[x]==symbol)
          {
            pidx=x;
            break;
          }
      } 
    //--
    return(pidx);
//---
  } //-end PairsIdxArray()

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


4. ChartEvent 函数


为了支持多币种智能交易系统的有效性和效率,有必要创建几个手动按钮,便于管理订单和更改图表或品种。
//+------------------------------------------------------------------+
//| 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.PairsIdxArray(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;
   //--
   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     ------------------------------------------------------------"+ 
      "\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()  


多币种智能交易系统 FXSAR_MTF_MCEA 界面如下图所示。

FXSAR_MTF_MCEA_look


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

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

MCR_Combine

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

1. 为所有订单设置止损/止盈

2. 所有订单平仓

3. 所有盈利单平仓

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

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



策略测试器

众所周知,MetaTrader 5 终端策略测试器支持并允许我们测试策略、交易多个品种、或测试所有可用品种及所有可用时间帧的自动交易。

因此,在这种情况下,我们将在 MetaTrader 5 策略测试器平台上测试多时间帧和多币种智能交易系统 FXSAR_MTF_MCEA。




结束语

利用 MQL5 创建多币种和多时间帧智能交易系统的结论如下:

  1. 事实摆明,在 MQL5 中创建多币种智能交易系统非常简单,与单币种智能交易系统没有太大区别。但对于具有多时间帧的多币种智能交易系统有点特别,它比单一时间帧要复杂一些。
  2. 创建多币种智能交易系统将提高交易者的效率和有效性,因为交易者无需打开更多品种图表即可进行交易。
  3. 通过应用正确的交易策略,并计算更佳指标信号,比之单货币智能交易系统,其获利可能性会提升。因为一个品种(货币对)产生的亏损会被其它品种(货币对)的盈利所补偿。
  4. 这个 FXSAR_MTF_MCEA 多币种智能交易系统只是一个学习和开发思路的例子。 
  5. 在策略测试器当中的测试结果仍然不佳。因此,如果拥有更准确信号计算的更好策略,并添加一些更好的时间帧,我相信结果将比当前策略更好。


注意:

如果您有基于内置 MQL5 标准指标信号创建简单多币种智能交易系统的思路,请在评论中提出。

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

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

附加的文件 |
FXSAR_MTF_MCEA.mq5 (80.52 KB)
机器学习中的量化(第1部分):使用 CatBoost 的理论、示例代码和实现分析 机器学习中的量化(第1部分):使用 CatBoost 的理论、示例代码和实现分析
本文探讨了量化在树模型构建中的理论应用,并展示了使用 CatBoost 实现的量化方法。不使用复杂的数学方程。
开发回放系统 — 市场模拟(第 28 部分):智能交易系统项目 — C_Mouse 类 (II) 开发回放系统 — 市场模拟(第 28 部分):智能交易系统项目 — C_Mouse 类 (II)
当人们开始创建第一个拥有计算能力的系统时,一切都需要工程师的参与,他们必须非常熟知该项目。我们谈论的是计算机技术的曙光,那个时代甚至没有用于编程的终端。随着它的发展,越来越多的人对能够创造一些东西感兴趣,涌现出新的思路和编程方式,取代了旧式风格的改变连接器位置。这就是第一个终端出现的时刻。
神经网络变得简单(第 58 部分):决策转换器(DT) 神经网络变得简单(第 58 部分):决策转换器(DT)
我们继续探索强化学习方法。在本文中,我将专注于一种略有不同的算法,其参考智能体政策构造一连串动作的范式。
开发回放系统(第32部分):订单系统(一) 开发回放系统(第32部分):订单系统(一)
在我们迄今为止开发的所有东西中,正如你可能会注意到并最终同意的那样,这个系统是最复杂的。现在我们需要做一些非常简单的事情:让我们的系统模拟交易服务器的操作。准确实现交易服务器操作方式似乎是一件轻而易举的事情。至少说起来是这样。但我们需要这样做,以便对回放/模拟系统的用户来说,一切都是无缝和透明的。