English Русский 中文 Español Deutsch Português
preview
MQL5オブジェクト指向プログラミング(OOP)について

MQL5オブジェクト指向プログラミング(OOP)について

MetaTrader 5トレーディング | 8 8月 2023, 10:08
368 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

はじめに

この記事では、スムーズかつ簡単なコーディングにつながり、開発者またはプログラマーとして繰り返しを避ける(Do Not Keep Yourself)という「DRY」の概念を適用するのに役立つ、プログラミングにおける最も重要なトピックの1つを共有します。また、作成されたソフトウェアのセキュリティの向上などのその他の機能についても説明します。オブジェクト指向プログラミング(OOP)について、そしてMQL5(MetaQuotes言語)でこの概念をどのように使い、どのようにコーディングできるのかについて、まずOOPの基本を理解し、次にいくつかのアプリケーションを見ながらMQL5での使い方を理解します。

以下の3つのポイントを通して、この興味深く重要なトピックを取り上げます。

この記事の主な目的は、一般的なオブジェクト指向プログラミング(OOP)の基本を理解し、それがソフトウェア作成にどのように役立つかを理解することです。そこから、この驚くべきアプローチをMQL5に適用することで、より効果的でセキュアなソフトウェアを作成するのに役立つ可能性をMQL5でどのように適用できるかを学びます。

このOOPアプローチについて詳しく学ぶことは誰にとっても非常に有用です。このアプローチは一般的に、特にC++、Java、Pythonなどの他のプログラミング言語にも適用できるため、非常に重要で有益なリソースがあります。MQL5言語では、記事のトピックだけでなく、MQL5言語のすべてのトピックにおいて非常に重要なリソースがあります。MQL5ドキュメントです。MQL5 OOPドキュメントのリンクからOOPのトピックを確認することができます。

免責条項:すべての情報は「現状有姿」で提供され、情報提供のみを目的としており、取引目的やアドバイスを目的としたものではありません。いかなる結果も保証するものではありません。読者がこれらの資料を自分の取引口座で使用する場合、自己責任でおこなってください。


OOPとは

このトピックでは、一般的なOOPの基礎を学ぶので、OOPの定義からこの興味深いトピックを始めましょう。OOPはオブジェクト指向プログラミングの略で、コンピュータープログラミングのパラダイムです。これは、作業やコードを重複させることなく、再利用可能なソフトウェアをスムーズに作成および開発するのに役立ち、DRY(Do notrepeat Yourself)の概念を適用するのに役立ちます。

これから説明するように、OOPは世界の本質に近づくのに役立ちます。なぜなら、私たちの周りのすべてのものはオブジェクトによって作成され、それぞれがその性質と動作を持っているからです。これがソフトウェア内のデータでできることなのです。OOPについてさらに詳しく知りたい場合は、オブジェクトとクラスを扱うことになることを知っておく必要があります。オブジェクトとはクラスのインスタンスを意味し、クラスはオブジェクトのテンプレートです。クラスであるテンプレートの内部で、このオブジェクトの振る舞いを詳細に定義します。

OOPの基本概念

OOPをソフトウェアに適用する場合、以下の原則が適用されます。

  1. カプセル化
  2. 抽象化
  3. 継承
  4. 多態性(ポリモーフィズム)

oop

1. カプセル化

カプセル化とは、1つのクラス内で関数とデータのリンクを可能にする手法です。クラス内のデータと関数は、クラス内でのみアクセス可能なprivateにすることも、クラス外からアクセス可能なpublicにすることもできます。カプセル化の概念は、クラス実装の複雑さを隠すのに役立ちます。開発者がデータを完全に制御できるようになり、競合することなく他の値に依存するすべての値を追跡するのに役立ちます。

つまり、カプセル化はシステムを稼働させ続け、起こりうる多くのエラーを回避するのに役立つということです。さらに、開発者に高いレベルのコントロールを与え、ソフトウェアのコード全体に影響を与えたり変更したりすることなく、テストやクラスデータをよりスムーズかつ簡単に処理するにも役立ちます。前述のように、エラーを解決し、コーディングが複雑になるのを防ぐのにも役立ちます。

次の図は、カプセル化の概念を表しています。

カプセル化

2. 抽象化

抽象化とは、不必要な詳細を隠し、本質的な詳細のみを提示する手法です。これはカプセル化の概念よりも広いですが、すべてのクラスの実装プロセスについてすべてを知らなくても、実装を完了させるために何をする必要があるかだけを知っていれば、データを保護し、関数を実装するという同じ目的を達成するのに役立ちます。

そのためには、インターフェイスとインプリメンテーションという2つの重要なメソッドを含める必要があります。インターフェイスは、クラスが相互に作用し、対処するためのメソッドです。インプリメンテーションは、コードの詳細やクラスのロジックの詳細をすべて持つメソッドです。つまり、抽象化はソフトウェアの安全性を高め、コーディングプロセスを繰り返したり、ゼロから再コード化したりすることなく、よくできたアプリケーションをベースにしてより多くのアプリケーションを開発しコード化するのに役立ちます。

3. 継承

その名前から、継承の概念は、古いクラスから新しいクラスを派生し、新しいクラスが古いクラスの機能を継承することを意味します。この場合、古いクラスは親クラスまたはスーパークラスと呼ばれ、新しく派生したクラスは子クラスと呼ばれます。この概念は、DRY(Do not Repeat Yourself)の概念を適用するのに役立ちますが、再利用性の主要な考え方を提供します。

相続

4. ポリモーフィズム

この概念の名前から単語を2つに分けると、Polyは多数または複数を意味し、Morphismは形態を意味します。つまり、ポリモーフィズム(Polymorphism)の概念は、実体が多数または複数の形態で動作できるようにすることです。例えば、変数aと変数bの合計を求めることができるSumメソッドと、変数a、変数b、変数cの合計を求めることができる別のメソッドのように、異なる動作をすることができます。

簡単に言えば、ポリモーフィズムとは、1つのインターフェイスに多数の、あるいは複数のメソッドを持つことを意味します。

これまでに述べたことは、OOPとは、独自の動作や特性を持つオブジェクトを通してソフトウェアの設計を組織化することに重点を置いたコンピュータプログラミングモデルであり、これは大規模で複雑なソフトウェア、特にソフトウェアの更新や操作が多い場合に役立つ手法である、としてまとめることができます。

OOPの属性と特徴

  • OOPアプローチを適用したソフトウェアには、クラスと関数が含まれる
  • カプセル化と抽象化の原則を適用することで、データが隠蔽されるため、高度なセキュリティを実現できる
  • コードを小さなブロックに分割できるため、複雑なプロジェクトに容易に取り組むことができ、プロジェクトの複雑さを軽減できる
  • 更新や開発プロセスが簡潔化する
  • 継承原則の適用によるコードの再利用性
  • 競合することなく、同じクラスのインスタンスを多数作成する能力

OOPアプローチを適用できるプログラミング言語は数多くあり、最も普及しているのは、C++、C#、Python、Java、JavaScript、PHPなどです。これらのOOPアプローチを適用できる言語にはMQL5言語が含まれます。次のトピックではこれについて学びます。


MQL5のOOP

このトピックでは、MQL5でのOOPとその使い方について学びます。OOPの基本として述べましたが、オブジェクトの設計図としてクラスを作成します。クラス自体はコレクションのようで、変数と特定の一連のタスクを実行するメソッド(関数と同じですがクラス内ではメソッドと呼ばれます)が含まれています。ここで、クラス内の変数やメソッド(関数)はクラスメンバーとも呼ばれることにも触れておきたいと思います。ここで言うべきことは、MQL5でOOPの概念を適用できるようになったことは、品質やセキュリティに加えて、これまで述べてきたような労力や作業を大幅に削減できるということであり、良い取り組みであり、評価すべきことだということです。

MQL5でOOP概念を適用する必要がある場合、以下をどのように使用できるかを理解する必要があります。

  • クラス
  • アクセス修飾子
  • コンストラクタとデストラクタ
  • 派生(子)クラス
  • 仮想関数
  • オブジェクト

クラス

オブジェクトの設計図となるクラスを作成する場合、MQL5では、クラスを関数と同じようにグローバルスコープで宣言する必要があります。クラスを作成するには、classキーワードの後に希望の一意なキーワードを続けます。次に、中括弧の対の間にクラスのメンバーである変数とメソッドを配置し、2番目の中括弧の後にセミコロンを配置してクラス宣言を終了します。ところで、クラスはプログラム内でもインクルードファイル内でも宣言できます。

以下はクラス宣言の例です。

class Cobject
{
   int var1;       // variable1
   double var2;    // variable1
   void method1(); // Method or function1
};

先ほどの例でわかるように、このクラスには3つのメンバーがあり、それらは2つの変数と1つのメソッドまたは関数です。

アクセス修飾子

アクセス修飾子によって、クラス外で使用できる変数や関数を決定することができます。public、private、protectedの3つのアクセスキーワードがあります。

  • Public:クラスの外部で使用できるメンバーを表します。
  • Private:クラスの外部では使用できないが、クラス内部の関数によってのみ使用可能なメンバーを表します。クラスの子クラスは、privateメンバーを継承しません。
  • Protected:子クラスに継承されるが、本来はprivateなメンバーを表します。

必要があれば、次の例をご覧ください。

class Cobject
{
   private:
   int var1;       // variable1
   protected:
   double var2;    // variable1
   public:
   void method1(); // Method or function1
};

先ほどの例でわかるように、クラスには3つのメンバーがあります。2つの変数があり、1つはprivate、もう1つはprotectedで、3つ目のメンバーはpublicです。

コンストラクタとデストラクタ

クラス内の変数を初期化する必要がある場合は、コンストラクタを使用します。もしそうしなければ、コンパイラがデフォルトで作成するが、このデフォルトのコンストラクタは表示されません。また、アクセシビリティに応じて公開されなければならない。一方、デストラクタは、クラスオブジェクトが破壊されるときに自動的に呼び出される関数です。デストラクタ名は、クラス名にチルダ(~)をつけたものです。デストラクタがあってもなくても、文字列、動的配列、オブジェクトは初期化を必要とするので、いずれにせよ初期化は解除されます。

以下はコンストラクタの例です。

class CPrices
  {
private:
   double               open;         // Open price
   double               high;         // High price
   double               low;          // Low price
   double               close;        // Close price
public:
   //--- Default constructor
                     CPrices(void);
   //--- Parametric constructor
                     CPrices(double o,double h,double l, double c);
  };

派生(子)クラス

前に学んだように、継承の概念はOOPの最も貴重で便利な機能の1つです。スーパー クラス(親クラス)から子クラスを作成でき、この子クラスはprivateメンバーを除く親クラスのすべてのメンバーを継承するためです。その後、その子クラスに新しい変数や関数を追加することができます。

必要でしたら次の例をご覧ください。価格の親クラスがあれば、次のように日次価格の子クラスを作ることができます。

class CDailyPrices : public CPrices
{
public:
   double               open;          // Open price
   double               high;          // High price
   double               low;           // Low price
   double               close;         // Close price
};

見てわかるように、親クラス名はCPricesで、CDailyPricesは子クラス(派生クラス)です。さて、CPricesのpublicメンバーもprotectedメンバーもすべてCDailyPricesクラスの一部であり、publicのままです。

仮想機能

子クラスでメソッドや関数の動作方法を更新したい場合は、親クラスで(仮想)関数を使用してから、子クラスで関数を定義できます。例えば、クラスに基づいて2つの異なるバージョンの関数があるとします。親クラスでは、virtualキーワードを使って関数を定義します。

class CVar
  {
public:
   virtual 
void varCal();
  };

次に、子クラスの同じ関数を更新します。

class CVar1 : public CVar
{
public:
 int varCal(int x, int y);
}; 

オブジェクト

オブジェクトは、変数を作成するときと同じように一意な識別子です。オブジェクト識別子の前には型としてクラス名を使用します。プロジェクトに必要なクラスに属するオブジェクトを多数作成できます。必要なのは、すべてに一意の識別子を使用することだけです。オブジェクトを宣言した後、ドットである(.)を使うことで、任意のpublicメンバーにアクセスすることができます。

取引数の整数変数num_tradesを持つクラスを作成する場合、それを明確に理解するために例を見てみましょう。

class CSystrades
{
public:
int num_trades;
};

次に、system1というこのクラスに属するオブジェクトを作成する必要があります。

CSystrades system1;

このオブジェクトを3の値で定義すると、次のようになります。

system1.num_trades=3;

さて、このトピックでOOPに関する最も重要なアイデアを学ぶことで、MQL5でどのようにOOPアプローチを適用できるかがわかりました。

OOPアプリケーション

この興味深い部分では、ソフトウェアにOOPアプローチを適用した簡単なアプリケーションをいくつか紹介し、OOPの使い方とその有用性を説明していきます。

価格クラスアプリケーション

この単純なアプリケーションでは複数の時間枠の価格を確認します。この例では3つの時間枠(日足、週足、月足)を提示します。すべての価格(始値、高値、安値、終値)を1つの場所(例:[エクスパート]タブ)で確認できる必要があります。その後、より高度なソフトウェアを実装するために、この単純な例をさらに発展させることができます。

まず、次のステップでクラスを宣言する必要があります。

  • 価格を表すクラスをグローバルスコープで宣言し、classキーワードを使ってすべての共通メンバーをpublicとして含める
  • publicキーワードを使う
  • 5つの変数(時間枠、始値、高値、安値、終値)を作成する
  • すべての価格データを印刷するvoid関数を作成する
class CPrices
  {
public:
   string            timeFrame;
   double            open;
   double            high;
   double            low;
   double            close;
   void              pricesPrint()
     {
      Print(timeFrame," Prices = Open: ",open," - ","High: ",high,"-","Low: ",low,"-","Close: ",close);
     }
  };

日次、週次、月次価格のオブジェクトをクラスから作成します。

CPrices CDailyPrices;
CPrices CWeeklyPrices;
CPrices CMonthlyPrices;

OnInit関数の中で、3つの時間枠について以下のように定義します。

  • stringの時間枠の定義
  • iOpen関数を使った始値の定義
  • iHigh関数を使った高値の定義
  • iLow関数を使った安値の定義
  • iClose関数を使った終値の定義
  • print関数(メソッド)の呼び出し
int OnInit()
  {
//--- Daily time frame
   CDailyPrices.timeFrame="Daily";
   CDailyPrices.open=(iOpen(Symbol(),PERIOD_D1,1));
   CDailyPrices.high=(iHigh(Symbol(),PERIOD_D1,1));
   CDailyPrices.low=(iLow(Symbol(),PERIOD_D1,1));
   CDailyPrices.close=(iClose(Symbol(),PERIOD_D1,1));
   CDailyPrices.pricesPrint();

//--- Weekly time frame
   CWeeklyPrices.timeFrame="Weekly";
   CWeeklyPrices.open=(iOpen(Symbol(),PERIOD_W1,1));
   CWeeklyPrices.high=(iHigh(Symbol(),PERIOD_W1,1));
   CWeeklyPrices.low=(iLow(Symbol(),PERIOD_W1,1));
   CWeeklyPrices.close=(iClose(Symbol(),PERIOD_W1,1));
   CWeeklyPrices.pricesPrint();

//--- Monthly time frame
   CMonthlyPrices.timeFrame="Monthly";
   CMonthlyPrices.open=(iOpen(Symbol(),PERIOD_MN1,1));
   CMonthlyPrices.high=(iHigh(Symbol(),PERIOD_MN1,1));
   CMonthlyPrices.low=(iLow(Symbol(),PERIOD_MN1,1));
   CMonthlyPrices.close=(iClose(Symbol(),PERIOD_MN1,1));
   CMonthlyPrices.pricesPrint();
   return(INIT_SUCCEEDED);
  }

このEAを実行した後で、ツールボックスの[エキスパート]タブで、出力された価格を以下のように確認できます。

価格出力

前の画像でわかるように、3行が出力されています。

  • 最初の行は、日次データの始値、高値、安値、終値を表示している
  • 2行目は週次データに属する同じ価格を表示している
  • 3行目は月次データに属する同じ価格を表示している

indicatorClassアプリケーション

OOPアプローチを使って、4種類の移動平均(単純平均、指数平均、平滑平均、線形加重平均)の値を出力できるソフトウェアを作成します。このタイプのソフトウェアを作成する簡単な手順は次のとおりです。

classキーワードを使用してCiMA指標クラスを宣言し、このクラスのpublicメンバーを作成します。これらは、移動平均のタイプを定義するMAType、移動平均の配列を定義するMAArray、移動平均のハンドルを定義するMAHandle、すべての移動平均の値を定義するMAValueの4つの共通変数です。voidメソッド(関数)valuePrintを作成します。関数本体で、すべての移動平均タイプの値を表示するようにします。

class CiMA
  {
public:
   string            MAType;
   double            MAArray[];
   int               MAHandle;
   double            MAValue;
   void              valuePrint()
     {
      Print(MAType," Current Value: ",MAValue);
     };
  };

各移動平均の以下のオブジェクトをクラスから作成します。

  • 平均の名前
  • 平均のハンドル
  • 平均の配列
//--- SMA
CiMA CSma;
CiMA CSmaHandle;
CiMA CSmaArray;

//--- EMA
CiMA CEma;
CiMA CEmaHandle;
CiMA CEmaArray;

//--- SMMA
CiMA CSmma;
CiMA CSmmaHandle;
CiMA CSmmaArray;

//--- LWMA
CiMA CLwma;
CiMA CLwmaHandle;
CiMA CLwmaArray;

OnInit関数の内部で、移動平均のタイプごとに以下のステップを実行します。

  • 平均値の名前を定義する
  • 平均値のハンドルを定義する
  • ArraySetAsSeries関数を使用して配列にAS_SERIESフラグを設定する
  • CopyBuffer関数を使用して、平均の指標バッファデータを取得する
  • 平均値を定義し、NormalizeDouble関数を使って正規化する
  • Printメソッド(関数)を呼び出す
int OnInit()
  {
   //--- SMA
   CSma.MAType="Simple MA";
   CSmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_SMA,PRICE_CLOSE);
   ArraySetAsSeries(CSmaArray.MAArray,true);
   CopyBuffer(CSmaHandle.MAHandle,0,0,3,CSmaArray.MAArray);
   CSma.MAValue=NormalizeDouble(CSmaArray.MAArray[1],_Digits);
   CSma.valuePrint();

   //--- EMA
   CEma.MAType="Exponential MA";
   CEmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_EMA,PRICE_CLOSE);
   ArraySetAsSeries(CEmaArray.MAArray,true);
   CopyBuffer(CEmaHandle.MAHandle,0,0,3,CEmaArray.MAArray);
   CEma.MAValue=NormalizeDouble(CEmaArray.MAArray[1],_Digits);
   CEma.valuePrint();

   //--- SMMA
   CSmma.MAType="Smoothed MA";
   CSmmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_SMMA,PRICE_CLOSE);
   ArraySetAsSeries(CSmmaArray.MAArray,true);
   CopyBuffer(CSmmaHandle.MAHandle,0,0,3,CSmmaArray.MAArray);
   CSmma.MAValue=NormalizeDouble(CSmmaArray.MAArray[1],_Digits);
   CSmma.valuePrint();

   //--- LWMA
   CLwma.MAType="Linear-weighted MA";
   CLwmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_LWMA,PRICE_CLOSE);
   ArraySetAsSeries(CLwmaArray.MAArray,true);
   CopyBuffer(CLwmaHandle.MAHandle,0,0,3,CLwmaArray.MAArray);
   CLwma.MAValue=NormalizeDouble(CLwmaArray.MAArray[1],_Digits);
   CLwma.valuePrint();
   return(INIT_SUCCEEDED);
  }

このコードをコンパイルして実行すると、移動平均の種類ごとに4行が見つかります。それぞれの行は以下のように平均の値を表示します。

指標出力

前に述べたように、これらのアプリケーションを開発してより複雑で高度なタスクを実装できますが、ここでの目的は、オブジェクト指向プログラミング(OOP)の基本と、このアプローチをMQL5に適用する方法を学び理解することです。 この便利なアプローチを適用すると得られる機能が多くのあるためです。


結論

この記事では、プログラミング全般において非常に重要なトピックとアプローチの基本を学びました。安全でセキュリティの高いソフトウェアを作成するのにどのように役立つか、コードを小さなコードブロックに分割してコーディングプロセスを簡略化することでソフトウェア作成の複雑さを軽減する方法を学ぶことで、このアプローチがソフトウェアを設計する際にいかに非常に役立つかを学びました。 これにより、動作が異なる場合でも競合することなく同じクラスから多数のインスタンスを作成することが容易になり、ソフトウェアを更新する際の柔軟性と安全性が向上します。

また、MQL5でこの重要なアプローチをどのように適用すれば、これらの素晴らしい機能をすべて手に入れることができるかを学び、MQL5でOOPアプローチを適用して作成できる、MetaTrader 5で使用される簡単なアプリケーションをいくつか学びました。

この記事が皆さんに役に立ち、MQL5プログラミングにおける非常に重要かつ重要なトピックを学ぶのに役立てば幸いです。コーディングする際に、OOPアプローチを適用すればどれほど多くのアイデアが簡単になるかについて、より多くの洞察を得ることができるからです。

この記事を気に入り、最も人気のあるテクニカル指標に基づいてMetaTrader 5で使用するMQL5で取引システムを作成する方法や、カスタムテクニカル指標を作成してEAで使用する方法についてもっと学びたい方は、私のプロフィールに掲載されている出版物を通じて、これらのトピックに関する私の他の記事をお読みになってください。

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/12813

添付されたファイル |
indicatorClass.mq5 (2.09 KB)
priceClass.mq5 (1.7 KB)
MetaTrader 5用のMQTTクライアントの開発:TDDアプローチ MetaTrader 5用のMQTTクライアントの開発:TDDアプローチ
この記事では、MQL5のネイティブMQTTクライアント開発における最初の試みについて報告します。MQTTは、クライアントサーバーのパブリッシュ/サブスクライブメッセージングトランスポートプロトコルです。MQTTは軽量、オープン、シンプルで、簡単に実装できるように設計されています。これらの特性により、さまざまな状況での使用に最適です。
シンプルな平均回帰取引戦略 シンプルな平均回帰取引戦略
平均回帰とは、トレーダーが価格が何らかの形の均衡に戻ることを期待する逆張り取引の一種で、通常は平均値または別の中心的傾向の統計によって測定されます。
Goertzelアルゴリズムによるサイクル分析 Goertzelアルゴリズムによるサイクル分析
この記事では、MQL5でGoertzel(ゲルツェル)アルゴリズムを実装するコードユーティリティを紹介し、このテクニックを価格相場の分析に利用し、可能な戦略を開発するための2つの方法を探ります。
MQL5におけるARIMAモデルによる予測 MQL5におけるARIMAモデルによる予測
この記事では、ARIMAモデルを構築するためのCArimaクラスの開発を継続し、予測を可能にする直感的な手法を追加します。