English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5 クックブック:カスタムチャートイベント処理

MQL5 クックブック:カスタムチャートイベント処理

MetaTrader 5 | 24 12月 2015, 14:54
712 0
Denis Kirichenko
Denis Kirichenko

はじめに

本稿は記事 MQL5 クックブック:典型的なチャートイベントの処理の論理的続編です。カスタムチャートイベントの処理方法を取り上げています。読者のみなさんはカスタムイベントの作成例と処理例を確認することができます。本稿で述べられる考えはすべてオブジェクト指向ツールによって実装されています。

カスタムイベントのテーマは幅広いため、プログラマーと開発者が各々の作業にクリエイティビティを取り入れることができます。


1. カスタムチャートイベント

このイベントがユーザーによって定義されるのは明らかです。正確に何をまた どのタスクまたはプログラムブロックがイベントの形式をとるのか決めるのはプログラマー次第です。MQL5 開発者は独自のイベントを作成します。それは複雑なアルゴリズムの実装に対して言語の能力を拡げるものです。

カスタムイベントはチャートイベントの2番目に可能なタイプです。最初のタイプは典型的なイベントです。ドキュメンテーションには『典型的チャートイベント』という言葉はありませんが、チャートイベントの最初の10タイプについてはその言葉を使うことを提案します。

開発者はチャートイベントすべてに対して1つの列挙しか提示しません。それはENUM_CHART_EVENTです。

ドキュメンテーションによれば、カスタムイベントの識別子は 65535 あります。カスタムイベントの最初と最後の識別子はの明示的な値CHARTEVENT_CUSTOM および CHARTEVENT_CUSTOM_LASTで設定されます。それはそれぞれ1000 と 66534 に等しくなっています(図1)。

図1 カスタムイベントの最初と最後の識別子

図1 カスタムイベントの最初と最後の識別子

最初と最後の識別子を考察するシンプルな計算により次が得られます:66534-1000+1=65535。

カスタムイベント使用前にまず作成する必要があります。この意味では、開発者は将来のエキスパートのアルゴリズムとして実装されるイベントコンセプトの立案者であり筆者でもあります。カスタムイベントを分類すると役に立つでしょう。この認知方法ではあいまいさ排除ができませんが、確かにその度合いは低くなり、推論のラインを整理します。

ソースとしてのカスタムイベントのそういった基準について考えます。たとえば、開発者 sergeev は売買ロボットのプロトタイプの考えを提示しました。彼はすべてのイベントを3つのグループに分けます(図2)。

図2 カスタムイベントソースのグループ

図2 カスタムイベントソースのグループ

それからこの主な考えによると、カスタムイベントはその所属グループを基に作成されるのです。

まずなにかシンプルなことから始めて見ます。最初に1番目のグループを採ります。それはインディケータイベントを含むものです。このグループに属するイベントは:インディケータの作成と削除、ポジションオープンとクローズのためのシグナル受信、です。2番目のグループには注文とポジションの状態変更のイベントが入ります。われわれの例ではポジションのオープンとクローズはこのグループになります。すべてたいへんシンプルです。そして最後に、公式化にとってもっとも複雑なグループは外部イベントのグループです。

2件のイベントを取り上げます。マニュアルトレードの有効化と無効化です。

図3 カスタムイベントのソース

図3 カスタムイベントのソース

初期パターンは演繹法(標準から特殊へ)で確率されます(図3)。これは対応するクラスのイベントタイプを作成するのにあとで使用しようと思っているまさにそのパターンです(表1)。

表1 カスタムイベント

表1 カスタムイベント

この表はまだ『イベントコンセプト』とは呼べませんが、それがスタートです。そしてもうひとつ別のアプローチがあります。抽象的なトレーディングシステムのモデルが3つのサブシステム-基本モジュール、で構成されているのは周知のことです(図4)。

図4 抽象的なトレーディングシステムモデル

図4 抽象的なトレーディングシステムモデル

『ソース』規準を基にしたカスタムイベントは次で生成されるイベントとして分類されます。

  1. シグナルサブシステム
  2. トレーリングオープンポジションのサブシステム
  3. 資金管理のサブシステム

たとえば後者は許容できるドローダウンレベルに達するイベント、設定値によってトレードボリュームを増やすイベント、損失限界率を大きくするイベントなどといったものを含みます。


2. ChartEvent のハンドラとジェネレータ

以下の数行では特別にチャートイベントのハンドラとジェネレータについて説明します。カスタムチャートイベントのハンドラについては、その原則は一般的なチャートイベントのハンドラに類似しています。

ハンドラである OnChartEvent() 関数はパラメータとして定数を4つ取ります。イベント特定とそれについての追加情報の考えを実装するのに開発者は明らかにこのメカニズムを使用しました。私としては、それはひじょうに堅牢で便利なプログラムメカニズムだと思います。

関数EventChartCustom() はカスタムチャートイベントを生成します。すばらしいことに、カスタムチャートイベントは『自分自身の』チャートと『外部の』チャートに対して作成されることが可能です。私は自分のチャートと外部チャートの意味に関するもっともおもしろい記事は The Implementation of a Multi-currency Mode in MetaTrader 5 だと思います。

個人的には、イベント識別子がハンドラでは int タイプでありながら、ジェネレータでは ushort タイプであるということには調和がないと思います。ハンドラでも ushort データタイプを使用するのが合理的ではないのでしょうか。


3. カスタムイベントのクラス

前に申し上げた通り、イベントコンセプトはエキスパートの開発者次第です。ここで表 1 のイベントを処理していこうと思います。まずカスタムイベントCEventBase のクラスとその派生クラスをソートします(図5)。

図5 イベントクラスの階層

図5 イベントクラスの階層

以下が基本クラスの記述です。

//+------------------------------------------------------------------+
//| Class CEventBase.                                                |
//| Purpose: base class for a custom event                           |
//| Derives from class CObject.                                      |
//+------------------------------------------------------------------+
class CEventBase : public CObject
  {
protected:
   ENUM_EVENT_TYPE   m_type;
   ushort            m_id;
   SEventData        m_data;

public:
   void              CEventBase(void)
     {
      this.m_id=0;
      this.m_type=EVENT_TYPE_NULL;
     };
   void             ~CEventBase(void){};
   //--
   bool              Generate(const ushort _event_id,const SEventData &_data,
                              const bool _is_custom=true);
   ushort            GetId(void) {return this.m_id;};

private:
   virtual bool      Validate(void) {return true;};
  };

イベントタイプは ENUM_EVENT_TYPE 列挙によって設定されます。

//+------------------------------------------------------------------+
//| A custom event type enumeration                                  |
//+------------------------------------------------------------------+
enum ENUM_EVENT_TYPE
  {
   EVENT_TYPE_NULL=0,      // no event
   //---
   EVENT_TYPE_INDICATOR=1, // indicator event
   EVENT_TYPE_ORDER=2,     // order event
   EVENT_TYPE_EXTERNAL=3,  // external event
  };

データメンバーはイベント識別子とデータストラクチャを持ちます。

基本クラス CEventBaseGenerate() メソッドはイベント生成を処理します。GetId() メソッドはイベント ID を返し、仮想メソッド Validate() はイベント識別子の値をチェックします。まず私はイベント処理メソッドをそのクラスにインクルードしましたが、あとでイベントはそれぞれユニークで抽象メソッドはここでは十分ではないと気づきました。私はこのタスクをカスタムイベントを処理するCEventProcessor クラスに委託することにしました。


4. カスタムイベントハンドラクラス

CEventProcessor クラスは提供されるイベントを 8 件生成するものです。以下はこのクラスのデータメンバーです。

//+------------------------------------------------------------------+
//| Class CEventProcessor.                                           |
//| Purpose: base class for an event processor EA                    |
//+------------------------------------------------------------------+
class CEventProcessor
  {
//+----------------------------Data members--------------------------+
protected:
   ulong             m_magic;
   //--- flags
   bool              m_is_init;
   bool              m_is_trade;
   //---
   CEventBase       *m_ptr_event;
   //---
   CTrade            m_trade;
   //---
   CiMA              m_fast_ema;
   CiMA              m_slow_ema;
   //---
   CButton           m_button;
   bool              m_button_state;
//+------------------------------------------------------------------+
  };

属性のリストには初期化とトレードのフラグがあります。最初のものは、正常に起動しなければ EA がトレードすることを許可しません。2番目のものはトレードの許可をチェックします。

CEventBase タイプのオブジェクトに対するポインターもあり、それは多型により異なるタイプのイベントを処理します。CTrade クラスのインスタンスによりトレード処理にアクセスすることができます。

CiMA タイプのオブジェクトはインディケータから受け取られるデータの処理を会付けます。例をシンプルにするために、トレードシグナルを受け取る移動平均を 2つ 採りました。またマニュアルで EA を有効/無効にするための "CButton" クラスのインスタンスもあります。

このクラスのメソッドは『モジュール-プロシージャ-関数-マクロ』の原理で分けられました。

//+------------------------------------------------------------------+
//| Class CEventProcessor.                                           |
//| Purpose: base class for an event processor EA                    |
//+------------------------------------------------------------------+
class CEventProcessor
  {
//+-------------------------------Methods----------------------------+
public:
   //--- constructor/destructor
   void              CEventProcessor(const ulong _magic);
   void             ~CEventProcessor(void);

   //--- Modules
   //--- event generating
   bool              Start(void);
   void              Finish(void);
   void              Main(void);
   //--- event processing
   void              ProcessEvent(const ushort _event_id,const SEventData &_data);

private:
   //--- Procedures
   void              Close(void);
   void              Open(void);

   //--- Functions
   ENUM_ORDER_TYPE   CheckCloseSignal(const ENUM_ORDER_TYPE _close_sig);
   ENUM_ORDER_TYPE   CheckOpenSignal(const ENUM_ORDER_TYPE _open_sig);
   bool              GetIndicatorData(double &_fast_vals[],double &_slow_vals[]);

   //--- Macros
   void              ResetEvent(void);
   bool              ButtonStop(void);
   bool              ButtonResume(void);
  };

モジュールの中にはイベント生成だけを行うものが3つあります。開始をするもの-Start()、終了をするもの-Finish() 、メインのもの-Main() です。4番目のモジュール ProcessEvent() はイベントハンドラでありジェネレータでもあります。


4.1 開始モジュール

このモジュールは OnInit() ハンドラで呼ばれるようにできています。

//+------------------------------------------------------------------+
//| Start module                                                     |
//+------------------------------------------------------------------+
bool CEventProcessor::Start(void)
  {
//--- create an indicator event object
   this.m_ptr_event=new CIndicatorEvent();
   if(CheckPointer(this.m_ptr_event)==POINTER_DYNAMIC)
     {
      SEventData data;
      data.lparam=(long)this.m_magic;
      //--- generate CHARTEVENT_CUSTOM+1 event
      if(this.m_ptr_event.Generate(1,data))
         //--- create a button
         if(this.m_button.Create(0,"Start_stop_btn",0,25,25,150,50))
            if(this.ButtonStop())
              {
               this.m_button_state=false;
               return true;
              }
     }

//---
   return false;
  }

インディケータイベントオブジェクトに対するポインターはこのモジュール内で作成されます。それから『インディケータ作成』イベントが生成されます。ボタンが作成されるのは一番最後です。それは『停止』モードに切り替えられます。それは、ボタンが押されれば、エキスパートが操作を停止するということです。

SEventData ストラクチャもまたこのメソッド定義に入っています。それは単に、パラメータがカスタムイベントのジェネレータに渡されるためのコンテナです。ここではストラクチャの 1 フィールドだけが書き込まれます。それは long タイプのフィールドです。それは EA のマジックナンバーを持ちます。


4.2 終了モジュール

このモジュールは OnDeinit() ハンドラで呼ばれます。

//+------------------------------------------------------------------+
//| Finish  module                                                   |
//+------------------------------------------------------------------+
void CEventProcessor::Finish(void)
  {
//--- reset the event object
   this.ResetEvent();
//--- create an indicator event object
   this.m_ptr_event=new CIndicatorEvent();
   if(CheckPointer(this.m_ptr_event)==POINTER_DYNAMIC)
     {
      SEventData data;
      data.lparam=(long)this.m_magic;
      //--- generate CHARTEVENT_CUSTOM+2 event
      bool is_generated=this.m_ptr_event.Generate(2,data,false);
      //--- process CHARTEVENT_CUSTOM+2 event
      if(is_generated)
         this.ProcessEvent(CHARTEVENT_CUSTOM+2,data);
     }
  }

ここで前のイベントポインターは消去され、『インディケータ削除』イベントが生成されます。OnDeinit() ハンドラ内でカスタムイベントが生成されると、ランタイムエラー4001 (予想されない外部エラー)が発生することを注意申し上げます。そのため、イベント生成と処理は OnChartEvent() を呼び出さずにこのメソッド内で実行されます。

ふたたび EA のマジックナンバーはSEventData ストラクチャにより格納されます。


4.3 メインモジュール

このモジュールは OnTick() ハンドラで呼ばれます。

//+------------------------------------------------------------------+
//| Main  module                                                     |
//+------------------------------------------------------------------+
void CEventProcessor::Main(void)
  {
//--- a new bar object
   static CisNewBar newBar;

//--- if initialized     
   if(this.m_is_init)
      //--- if not paused   
      if(this.m_is_trade)
         //--- if a new bar
         if(newBar.isNewBar())
           {
            //--- close module
            this.Close();
            //--- open module
            this.Open();
           }
  }

プロシージャOpen() および Close() はこのモジュール内で呼ばれます。第1のプロシージャは『開始シグナル受信』イベントを、第2のプロシージャは『終了シグナル受信』イベントを生成します。モジュールの現バージョンは新規バー登場時に完全に機能します。新規バーを検出するクラスは Konstantin Gruzdev 氏によって書かれました。


4.4 イベント処理モジュール

このモジュールは OnChartEvent() ハンドラで呼ばれます。サイズと機能性の面ではこのモジュールは最大です。

//+------------------------------------------------------------------+
//| Process event module                                             |
//+------------------------------------------------------------------+
void CEventProcessor::ProcessEvent(const ushort _event_id,const SEventData &_data)
  {
//--- check event id
   if(_event_id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- button click
      if(StringCompare(_data.sparam,this.m_button.Name())==0)
        {
         //--- button state
         bool button_curr_state=this.m_button.Pressed();
         //--- to stop
         if(button_curr_state && !this.m_button_state)
           {
            if(this.ButtonResume())
              {
               this.m_button_state=true;
               //--- reset the event object
               this.ResetEvent();
               //--- create an external event object
               this.m_ptr_event=new CExternalEvent();
               //---
               if(CheckPointer(this.m_ptr_event)==POINTER_DYNAMIC)
                 {
                  SEventData data;
                  data.lparam=(long)this.m_magic;
                  data.dparam=(double)TimeCurrent();
                  //--- generate CHARTEVENT_CUSTOM+7 event
                  ushort curr_id=7;
                  if(!this.m_ptr_event.Generate(curr_id,data))
                     PrintFormat("Failed to generate an event: %d",curr_id);
                 }
              }
           }
         //--- to resume
         else if(!button_curr_state && this.m_button_state)
           {
            if(this.ButtonStop())
              {
               this.m_button_state=false;
               //--- reset the event object
               this.ResetEvent();
               //--- create an external event object
               this.m_ptr_event=new CExternalEvent();
               //---
               if(CheckPointer(this.m_ptr_event)==POINTER_DYNAMIC)
                 {
                  SEventData data;
                  data.lparam=(long)this.m_magic;
                  data.dparam=(double)TimeCurrent();
                  //--- generate CHARTEVENT_CUSTOM+8 event
                  ushort curr_id=8;
                  if(!this.m_ptr_event.Generate(curr_id,data))
                     PrintFormat("Failed to generate an event: %d",curr_id);
                 }
              }
           }
        }
     }
//--- user event 
   else if(_event_id>CHARTEVENT_CUSTOM)
     {
      long magic=_data.lparam;
      ushort curr_event_id=this.m_ptr_event.GetId();
      //--- check magic
      if(magic==this.m_magic)
         //--- check id
         if(curr_event_id==_event_id)
           {
            //--- process the definite user event 
            switch(_event_id)
              {
               //--- 1) indicator creation
               case CHARTEVENT_CUSTOM+1:
                 {
                  //--- create a fast ema
                  if(this.m_fast_ema.Create(_Symbol,_Period,21,0,MODE_EMA,PRICE_CLOSE))
                     if(this.m_slow_ema.Create(_Symbol,_Period,55,0,MODE_EMA,PRICE_CLOSE))
                        if(this.m_fast_ema.Handle()!=INVALID_HANDLE)
                           if(this.m_slow_ema.Handle()!=INVALID_HANDLE)
                             {
                              this.m_trade.SetExpertMagicNumber(this.m_magic);
                              this.m_trade.SetDeviationInPoints(InpSlippage);
                              //---
                              this.m_is_init=true;
                             }
                  //---
                  break;
                 }
               //--- 2) indicator deletion
               case CHARTEVENT_CUSTOM+2:
                 {
                  //---release indicators
                  bool is_slow_released=IndicatorRelease(this.m_fast_ema.Handle());
                  bool is_fast_released=IndicatorRelease(this.m_slow_ema.Handle());
                  if(!(is_slow_released && is_fast_released))
                    {
                     //--- to log?
                     if(InpIsLogging)
                        Print("Failed to release the indicators!");
                    }
                  //--- reset the event object
                  this.ResetEvent();
                  //---
                  break;
                 }
               //--- 3) check open signal
               case CHARTEVENT_CUSTOM+3:
                 {
                  MqlTick last_tick;
                  if(SymbolInfoTick(_Symbol,last_tick))
                    {
                     //--- signal type
                     ENUM_ORDER_TYPE open_ord_type=(ENUM_ORDER_TYPE)_data.dparam;
                     //---
                     double open_pr,sl_pr,tp_pr,coeff;
                     open_pr=sl_pr=tp_pr=coeff=0.;
                     //---
                     if(open_ord_type==ORDER_TYPE_BUY)
                       {
                        open_pr=last_tick.ask;
                        coeff=1.;
                       }
                     else if(open_ord_type==ORDER_TYPE_SELL)
                       {
                        open_pr=last_tick.bid;
                        coeff=-1.;
                       }
                     sl_pr=open_pr-coeff*InpStopLoss*_Point;
                     tp_pr=open_pr+coeff*InpStopLoss*_Point;

                     //--- to normalize prices
                     open_pr=NormalizeDouble(open_pr,_Digits);
                     sl_pr=NormalizeDouble(sl_pr,_Digits);
                     tp_pr=NormalizeDouble(tp_pr,_Digits);
                     //--- open the position
                     if(!this.m_trade.PositionOpen(_Symbol,open_ord_type,InpTradeLot,open_pr,
                        sl_pr,tp_pr))
                       {
                        //--- to log?
                        if(InpIsLogging)
                           Print("Failed to open the position: "+_Symbol);
                       }
                     else
                       {
                        //--- pause
                        Sleep(InpTradePause);
                        //--- reset the event object
                        this.ResetEvent();
                        //--- create an order event object
                        this.m_ptr_event=new COrderEvent();
                        if(CheckPointer(this.m_ptr_event)==POINTER_DYNAMIC)
                          {
                           SEventData data;
                           data.lparam=(long)this.m_magic;
                           data.dparam=(double)this.m_trade.ResultDeal();
                           //--- generate CHARTEVENT_CUSTOM+5 event
                           ushort curr_id=5;
                           if(!this.m_ptr_event.Generate(curr_id,data))
                              PrintFormat("Failed to generate an event: %d",curr_id);
                          }
                       }
                    }
                  //---
                  break;
                 }
               //--- 4) check close signal
               case CHARTEVENT_CUSTOM+4:
                 {
                  if(!this.m_trade.PositionClose(_Symbol))
                    {
                     //--- to log?
                     if(InpIsLogging)
                        Print("Failed to close the position: "+_Symbol);
                    }
                  else
                    {
                     //--- pause
                     Sleep(InpTradePause);
                     //--- reset the event object
                     this.ResetEvent();
                     //--- create an order event object
                     this.m_ptr_event=new COrderEvent();
                     if(CheckPointer(this.m_ptr_event)==POINTER_DYNAMIC)
                       {
                        SEventData data;
                        data.lparam=(long)this.m_magic;
                        data.dparam=(double)this.m_trade.ResultDeal();
                        //--- generate CHARTEVENT_CUSTOM+6 event
                        ushort curr_id=6;
                        if(!this.m_ptr_event.Generate(curr_id,data))
                           PrintFormat("Failed to generate an event: %d",curr_id);
                       }
                    }
                  //---
                  break;
                 }
               //--- 5) position opening
               case CHARTEVENT_CUSTOM+5:
                 {
                  ulong ticket=(ulong)_data.dparam;
                  ulong deal=(ulong)_data.dparam;
                  //---
                  datetime now=TimeCurrent();
                  //--- check the deals & orders history
                  if(HistorySelect(now-PeriodSeconds(PERIOD_H1),now))
                     if(HistoryDealSelect(deal))
                       {
                        double deal_vol=HistoryDealGetDouble(deal,DEAL_VOLUME);
                        ENUM_DEAL_ENTRY deal_entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal,DEAL_ENTRY);
                        //---
                        if(deal_entry==DEAL_ENTRY_IN)
                          {
                           //--- to log?
                           if(InpIsLogging)
                             {
                              Print("\nNew position for: "+_Symbol);
                              PrintFormat("Volume: %0.2f",deal_vol);
                             }
                          }
                       }
                  //---
                  break;
                 }
               //--- 6) position closing
               case CHARTEVENT_CUSTOM+6:
                 {
                  ulong ticket=(ulong)_data.dparam;
                  ulong deal=(ulong)_data.dparam;
                  //---
                  datetime now=TimeCurrent();
                  //--- check the deals & orders history
                  if(HistorySelect(now-PeriodSeconds(PERIOD_H1),now))
                     if(HistoryDealSelect(deal))
                       {
                        double deal_vol=HistoryDealGetDouble(deal,DEAL_VOLUME);
                        ENUM_DEAL_ENTRY deal_entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal,DEAL_ENTRY);
                        //---
                        if(deal_entry==DEAL_ENTRY_OUT)
                          {
                           //--- to log?
                           if(InpIsLogging)
                             {
                              Print("\nClosed position for: "+_Symbol);
                              PrintFormat("Volume: %0.2f",deal_vol);
                             }
                          }
                       }
                  //---
                  break;
                 }
               //--- 7) stop trading
               case CHARTEVENT_CUSTOM+7:
                 {
                  datetime stop_time=(datetime)_data.dparam;
                  //---
                  this.m_is_trade=false;                  
                  //--- to log?                  
                  if(InpIsLogging)
                     PrintFormat("Expert trading is stopped at: %s",
                                 TimeToString(stop_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
                  //---
                  break;
                 }
               //--- 8) resume trading 
               case CHARTEVENT_CUSTOM+8:
                 {
                  datetime resume_time=(datetime)_data.dparam;
                  this.m_is_trade=true;                  
                  //--- to log?                  
                  if(InpIsLogging)                     
                     PrintFormat("Expert trading is resumed at: %s",
                                 TimeToString(resume_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
                  //---
                  break;
                 }
              }
           }
     }
  }

それは二部構成になっています。最初の部分は『ボタン』オブジェクトをクリックすることに関連する処理イベントです。このクリックは外部カスタムイベントを生成します。それはハンドラによって後に処理されるものです。

次の部分は先生されたカスタムイベントを処理するために作成されています。それにはブロックが2つあり、そこで関連するイベントが処理された後、新しいイベントが生成されます。『開始シグナル受信』イベントは最初のブロックで処理されます。正常に処理されると新しい注文イベント『ポジションのオープン』が生成されます。『終了シグナル受信』イベントは2番目のブロックで処理されます。シグナルが処理されると、『ポジションのクローズ』イベントが発生します。

エキスパートCustomEventProcessor.mq5CEventProcessor クラス使用の好例です。EA はイベント作成とそれに対して適切に応答するために作成されています。OPP パラダイムを使用し、ソースコードを数行に最小化することができました。EA のソースコードは本稿に添付しております。

私の考えでは、毎回カスタムイベントのメカニズムを参照する必要はないと思っています。異なる形式を持ちうる戦略の面では、小規模な無意味でつまらないものが数多くあります。


おわりに

本稿では、MQL5 環境でカスタムイベントを処理する原理を説明しようとしました。本稿で取り上げられている考えが初心者だけでなくさまざまな経験を持つプログラマーの方にとっても興味を引くものとなることを願っております。

私は MQL5 言語が開発されてよかったと思っています。おそらく近い将来、クラスのテンプレートができ、関数に対するポインターもできることでしょう。そうなれば抽象的なオブジェクトのメソッドを指す本格的なデリゲートを書くこととなるのです。

アーカイブのソースファイルはプロジェクトフォルダに入れることが可能です。私の場合それはMQL5\Projects\ChartUserEventフォルダです。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1163

添付されたファイル |
MetaTrader 4 と MetaTrader 5 の仮想ホスティングが通常の VPS より優れている理由 MetaTrader 4 と MetaTrader 5 の仮想ホスティングが通常の VPS より優れている理由
MetaTrader 4 と MetaTrader 5 用に仮想ホスティングクラウドネットワークが開発され、それはネイティブソリューションのメリットをすべて備えています。無料の24時間ディスカウントの恩恵を受けてください。いますぐ仮想サーバーを試してください。
MQL5 クックブック:トレードトランザクションイベントの処理 MQL5 クックブック:トレードトランザクションイベントの処理
本稿ではイベント駆動型プログラミングの観点から MQL5 言語の機能を考察します。この方法の最大のメリットはプログラムがトレード処理の段階的な実装に関する情報を入手することができることです。また「トレードトランザクション」イベントハンドラによって現在進行中のトレード処理に関する情報を受信し処理する例を取り上げます。私見ですが、この方法はあるターミナルから別のターミナルへディールをコピーするのにも利用可能です。
MQL5 クックブック:BookEvent の処理 MQL5 クックブック:BookEvent の処理
本稿では BookEvent-マーケットデプスイベントの深さとその処理原則について考察します。「マーケットデプス」を処理するMQL プログラムが例となります。それはオブジェクト指向のアプローチで書かれています。処理結果はパネルとして、またマーケットデプスのレベルとして画面に表示されます。
第三世代ニューラルネットワーク:深層ネットワーク 第三世代ニューラルネットワーク:深層ネットワーク
本稿ではマシン学習の新しい視点方向-深層学習、より正確には深いニューラルネットワークについてお話します。第二世代のニューラルネットワークについて、その連携のアーキテクチャと主なタイプ、メソッド、学習ルール、主な欠点とそれに続き第三世代の開発とその主要タイプ、特殊性、トレーニング方法について簡単に再検討しています。実データについて集積されたオートエンコーダのウェイトによって開始される深いニューラルネットワークの構築とトレーニングにおける実践的実験を行います。入力データを選択するところから行列偏差までの全段階について詳細にお話します。本稿最終部分は MQL4/R を基にした内蔵インディケータを持つ Expert Advisor での深いニューラルネットワークのソフトウェア実装です。