
もうひとつ別の MQL5 OOP クラス
はじめに
実際い動作する完全なオブジェクト指向 EA (以降 OO EA )を構築することは私見ですが数多くの技能:理論的合理性、多様な発想、分析力と演繹的推理力、イ構想力など、を集結する必要のある難しいがやりがいのあるタスクです。われわれがやり遂げるべき自動トレーディングシステムがチェスのゲームであるとするならトレーディングのアイデアはチェスの戦略です。また戦法によってチェスの線略を実行することはテクニカルインディケータ、チャート図、基礎的な知識、コンセプト原理を利用してロボットをプログラムすることと言えるでしょう。
図1 ラファエロ・サンティによるアテネ学派の詳細この絵画にプロトンとアリストテレスが深い議論をかわしているのが見て取れます。
プラトンはここでは概念的世界を、アリストテレスは経験主義的世界の省庁として描かれています。
この課題のむずかしさは解っています。OO EA はプログラムするのに極端に難しいものではありませんが、アプリケーション開発の経験があまりない人にとって難しいのは事実です。その他原理と同じで、これ自体は経験の欠如そのものによりよります。私が必ず理解が得られると思う特定の例を用いてこのテーマをみなさんにお伝えしようとしているのはそのためです。まだ OOP コンセプトに取り組めるか不安でもがっかりしないでください。最初の EAを作成したら物事はずっと簡単だとお気づきになるはずです、ということにしておきましょう。現時点では一から何かを構築する必要はありません。ここで説明することを理解することだけです。
トレーディングシステムを発想し実装する全手順は複数の人がこれを行う場合、多くの意味で簡素化が可能です。この事実がコミュニケーションの問題をもたらすとしても。投資戦略を考える人にはプログラミングのコンセプトを扱う必要はなく、彼らの対話者すなわちプログラマーに対処するのです。そして最初はMQL5 開発者は顧客のトレーディング戦略の重要側面を理解しないかもしれません。
これは スクラム、テスト駆動開発(TDD)、 エクストリームプログラミング(XP)などソフトウェア開発方法論の創造につながるソフトウェア工学における古典的問題です。言語の落とし穴に気づくことはきわめて重要です。ところで参考までにウィキペディアは「ソフトウェア工学におけるソフトウェア開発方法論またはシステム開発方法論は構築、設計、情報システム開発手順の管理に利用される枠組みである」と述べています。
われわれは迅速に 着想し成功するトレードの考えを実装することができると考えていきます。また顧客によって考えられるトレーディングシステムがすでにうまく定義され、だれからも理解されている反復的開発過程の終盤にあると仮定することもできます。お好きなように考えてください。ところでここから本テキストではMQL5 プログラム記事で入手可能な教育的記事をいくつか参照していき、必要に応じてこの練習を首尾よく行うためにみなさんがすばやく確認したりある考え方を思い出したりできるようにしていきます。準備はいいですか?
1. 新しいパラダイムを取り入れる第一ステップ
1.1. Forex EA をプログラムするのになぜ OOP が適しているのでしょうか?
みなさんはこの時点でなぜこのようなことをする必要があるのだろう、と疑問を感じれおられるかもしれません。まずみなさんにお伝えしたいのは、OOPは強制されているわけではないということです。とりあえず自動売買システムをプログラムする知識を一歩深めるために OOP を選択することを強くお薦めします。
アプリケーションを開発する従来の方法、いわゆる手順的プログラミングはには以下のような短所があります。
- 課題のモデル化を難しくする。この古いパラダイム下では主な課題の解決は関数モジュール、すなわち関数とプロシージャ、で解決されるよりシンプルな下位問題に分割されます。
- それではコードの再利用が難しくなります。それは回りまわってコストを上げ、また信頼性、柔軟性、管理を妨げます。
コードの再利用は新しいオブジェクト指向スタイルでは簡単です。これはたいへん重要なことです!数多くの専門家はコードの再利用はソフトウェア開発のほとんどの問題に対する現実的解決法であると考えています。
ここで 抽象的データタイプ(ADT)いついて述べます。OOP によりADTの作成が可能です。ADT はあらゆるプログラム言語に存在する従来的なデータタイプのコンセプトです。その主な使用方法はアプリケーションのデータドメインを快適に定義することです。Include\Arrays\Array.mqh、 Include\Arrays\List.mqh、 Include\Arrays\Tree.mqh が MQL5 の抽象的データタイプの例です。
端的に言うと、オブジェクト指向プログラムパラダイムはコード再利用、信頼性、柔軟性、管理のしやすさといったメリットを得るためアプリケーションをコンセプトレベルで作成することを要求します。
1.2. みなさんはコンセプト論者ですか?UML が救いの手をさしのべます。
UMLについて聞いたことはありますか?UML は "Unified Modeling Language"の略語です。それはオブジェクト指向システムをデザインするグラフィカル言語です。われわれ人間はまず分析文でシステムを考え、それからプログラム言語でそれをコード化しています。開発者にとって上から下に行くことは異常なことではありません。それでもなお、分析家としての経験から私はいくつかの理由によりときどきこれは可能ではないと思います。その理由とはアプリケーションはひじょうに短い間時間で作成されなければならない。UMLの知識を迅速に採用できる人がチームにいない。たぶんチームの中には UMLのいくつかの部分を知らない人がいる、などです。
私見ですがUML は使いやすいと漢字、プロジェクト環境が許すなら利用することのできるすぐれた分析ツールです。UMLに関して詳しく調べたいとお思いならHow to Develop an Expert Advisor using UML Tools の一読をお薦めします。この記事は圧倒されるかもしれませんが、プロのソフトウェアエンジニアがどのように分析しているか全体像を得るのに役立ちます。UMLを完全に理解するにはまるまる数週間必要でしょう。現時点では UML とは何かを理解するだけでじゅうぶんです。私の経験では、この分析ツールは現実世界に存在する状況によりかならずしもすべてのソフトウェアプロジェクトで使用するわけではありません。
図2 UML ロゴ
1.3. はじめまして!最初の OO クラス
みなさんがオブジェクト指向プログラミングにまったくの初心者だとしたら、まず MQL5 参考資料で入手可能な OO に関する公式ドキュメンテーションを読み、それから基礎知識を得るために Writing an Expert Advisor Using the MQL5 Object-Oriented Programming Approach に目を通すことをお薦めします。何件か別の資料を読んでかならず補足してください。ここからはみなさんがすでに OOPについていくらか知識があり、以下に示すように MQL5 にあるクラス Person の従来的な例を簡単に理解するものとして話を進めていきます。
//+------------------------------------------------------------------+ //| CPerson Class | //+------------------------------------------------------------------+ class CPerson { protected: string m_first_name; string m_surname; datetime m_birth; public: //--- Constructor and destructor methods CPerson(void); ~CPerson(void); //--- Getter methods string GetFirstName(void); string GetSurname(void); datetime GetBirth(void); //--- Setter methods void SetFirstName(string first_name); void SetSurname(string surname); void SetBirth(datetime birth); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CPerson::CPerson(void) { Alert("Hello world! I am run when an object of type CPerson is created!"); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CPerson::~CPerson(void) { Alert("Goodbye world! I am run when the object is destroyed!"); } //+------------------------------------------------------------------+ //| GetFirstName | //+------------------------------------------------------------------+ string CPerson::GetFirstName(void) { return m_first_name; } //+------------------------------------------------------------------+ //| GetSurname | //+------------------------------------------------------------------+ string CPerson::GetSurname(void) { return m_surname; } //+------------------------------------------------------------------+ //| GetBirth | //+------------------------------------------------------------------+ datetime CPerson::GetBirth(void) { return m_birth; } //+------------------------------------------------------------------+ //| SetFirstName | //+------------------------------------------------------------------+ void CPerson::SetFirstName(string first_name) { m_first_name=first_name; } //+------------------------------------------------------------------+ //| SetSurname | //+------------------------------------------------------------------+ void CPerson::SetSurname(string surname) { m_surname=surname; } //+------------------------------------------------------------------+ //| SetBirth | //+------------------------------------------------------------------+ void CPerson::SetBirth(datetime birth) { m_birth=birth; } //+------------------------------------------------------------------+
以下はクオリティーコードを書かなければと思っている純粋主義の開発者のためのものです。MQL5 プログラム記事にある例や コードベースで入手できる数多くのそのたソフトウェア例とはやや異なり、 上記クラスは MQL5 の構想をコード化するためにMetaQuotes Software Corp.によって採用されるプログラム規約を使用します。みなさんには MetaQuotes がするのとまったく同じようにコードを書くことをお薦めします。ところで、About conventions in OOP MQL5 programs というタイトルのスレッドがこのテーマを取り上げています。
簡単に言えばPerson.mqh を書くのに採用されている重要な規約がいくつかあります。
- クラス名 CPerson は大文字 C で始まります。
- メソッド名は キャメル記法で大文字で始まります。たとえば GetFirstName、SetSurnameなどです。
- 保護されたプロパティ名は接頭辞 m_が付いています。たとえば、m_first_name、m_surname、 m_birthです。
- 予約語これ はクラス自体の中ではクラスメンバーを述べるために使用されることはありません。
MQL5 のフレームワークファイル、たとえばInclude\Arrays\Array.mqh、Include\Arrays\List.mqh、Include\Trade\Trade.mqhに目を通し、元の MQL5 コードがどのように書かれているか確認してください。
2. 最初のオブジェクト指向 EA をプログラムしましょう。
2.1. トレーディングシステムの考え方
われわれのトレーディングの考え方はシンプルです。『乱調子でのショートトレンドは無作為に近い』というものです。それだけです!これはいくつかの状況で複数の専門家によって観察されています。この仮説が正しければ、われわれの Forex ロボっておは必要に応じて動作するはずです。チャート上のある無作為な点を取ると、次の動きはあきらかに上下どちらでもありえ、われわれにはわかりません。問題は確立された SL レベルと TP レベルの差が十分小さい場合には、その差が絶対的に有意でなく、そのため数学的期待値に達していることです。このシステムは数学的期待を動作させるためだけのものです。本稿でOnce you get the EAコードを取得しバックテストを行ったら、みなさんはそれがひじょうにシンプルな資金管理ポリシーを要求することがわかるでしょう。
2.2. ロボットの OOP スケルトン
本節ではOOP が必要とする抽象的論理に基づく戦略を作成します。というわけで EA を生き物のように考えていってはいかがでしょうか?このバージョンではわれわれの Forex マシンは3つのメインパートで構成することができます。脳、なにか進化を呼ぶもの、そしてチャートです。
脳は処理に必要なデータを持つロボットの一部で、なにか読み取り専用メモリ(ROM)のようなものです。チャートはロボットが処理を行うグラフをエミュレートする情報部分です。最後にいわゆる進化は既定の時間におけるロボットの状態、処理パフォーマンスの履歴などといったような一時的情報を持つデータ部分です。これは生体の器官によって人間を設計するフランケンシュタインのようなものです。というのもアプリケーションを健康セクターについて開発する必要があるからです。各器官はこのコンテクストで全体のその他部分と関連する独自の意味概念となっています。
まずカスタム的なものを格納するためのフォルダ MQL5\Include\Mine を作成します。これはみなさんのコードを整理するための単なる考え方に過ぎません。ご自身の開発でこれを行えることを知るのはよいことですが、もちろん強制ではありません。作成する列挙型を格納するためのファイル MQL5\Include\Mine\Enums.mqh を作成します。
//+------------------------------------------------------------------+ //| Status enumeration | //+------------------------------------------------------------------+ enum ENUM_STATUS_EA { BUY, SELL, DO_NOTHING }; //+------------------------------------------------------------------+ //| Lifetime enumeration | //+------------------------------------------------------------------+ enum ENUM_LIFE_EA { HOUR, DAY, WEEK, MONTH, YEAR }; //+------------------------------------------------------------------+
次に EA の受精卵を作成し、ExpertSimpleRandom.mq5と名づけます。そのため以下のコードによってフォルダ MQL5\Experts\SimpleRandomを作成し、ファイル ExpertSimpleRandom.mq5 の中に作成します。
//+------------------------------------------------------------------+ //| ExpertSimpleRandom.mq5 | //| Copyright © 2013, Jordi Bassagañas | //+------------------------------------------------------------------+ #property copyright "Copyright © 2013, laplacianlab" #property link "https://www.mql5.com/ja/articles" #property version "1.00" #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\PositionInfo.mqh> #include <Indicators\Indicators.mqh> #include <Mine\Enums.mqh> #include <..\Experts\SimpleRandom\CSimpleRandom.mqh> input int StopLoss; input int TakeProfit; input double LotSize; input ENUM_LIFE_EA TimeLife; MqlTick tick; CSimpleRandom *SR=new CSimpleRandom(StopLoss,TakeProfit,LotSize,TimeLife); //+------------------------------------------------------------------+ //| Initialization function | //+------------------------------------------------------------------+ int OnInit(void) { SR.Init(); return(0); } //+------------------------------------------------------------------+ //| Deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { SR.Deinit(); delete(SR); } //+------------------------------------------------------------------+ //| OnTick event function | //+------------------------------------------------------------------+ void OnTick() { SymbolInfoTick(_Symbol,tick); SR.Go(tick.ask,tick.bid); } //+------------------------------------------------------------------+
これは数ある可能性の中の一方法に過ぎません。これはすべて基本的に MQL5 で OOP がどのように動作するかを説明しています。ご覧のように CSimpleRandom.mqhと名づけられた, Expert Advisorの主要クラスは MQL5\Experts\SimpleRandom\CSimpleRandom.mqhに保存してください。
//+------------------------------------------------------------------+ //| ExpertSimpleRandom.mq5 | //| Copyright © 2013, Jordi Bassagañas | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> #include <Mine\Enums.mqh> #include <..\Experts\SimpleRandom\CBrain.mqh> #include <..\Experts\SimpleRandom\CEvolution.mqh> #include <..\Experts\SimpleRandom\CGraphic.mqh> //+------------------------------------------------------------------+ //| CSimpleRandom Class | //+------------------------------------------------------------------+ class CSimpleRandom { protected: CBrain *m_brain; CEvolution *m_evolution; CGraphic *m_graphic; CTrade *m_trade; CPositionInfo *m_positionInfo; public: //--- Constructor and destructor methods CSimpleRandom(int stop_loss,int take_profit,double lot_size,ENUM_LIFE_EA time_life); ~CSimpleRandom(void); //--- Getter methods CBrain *GetBrain(void); CEvolution *GetEvolution(void); CGraphic *GetGraphic(void); CTrade *GetTrade(void); CPositionInfo *GetPositionInfo(void); //--- Specific methods of CSimpleRandom bool Init(); void Deinit(void); bool Go(double ask,double bid); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSimpleRandom::CSimpleRandom(int stop_loss,int take_profit,double lot_size,ENUM_LIFE_EA time_life) { int lifeInSeconds; switch(time_life) { case HOUR: lifeInSeconds=3600; break; case DAY: lifeInSeconds=86400; break; case WEEK: lifeInSeconds=604800; break; case MONTH: lifeInSeconds=2592000; break; // One year default: lifeInSeconds=31536000; break; } m_brain=new CBrain(TimeLocal(),TimeLocal()+lifeInSeconds,lot_size,stop_loss,take_profit); m_evolution=new CEvolution(DO_NOTHING); m_graphic=new CGraphic(_Symbol); m_trade=new CTrade(); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSimpleRandom::~CSimpleRandom(void) { delete(m_brain); delete(m_evolution); delete(m_graphic); delete(m_trade); } //+------------------------------------------------------------------+ //| GetBrain | //+------------------------------------------------------------------+ CBrain *CSimpleRandom::GetBrain(void) { return m_brain; } //+------------------------------------------------------------------+ //| GetBrain | //+------------------------------------------------------------------+ CEvolution *CSimpleRandom::GetEvolution(void) { return m_evolution; } //+------------------------------------------------------------------+ //| GetGraphic | //+------------------------------------------------------------------+ CGraphic *CSimpleRandom::GetGraphic(void) { return m_graphic; } //+------------------------------------------------------------------+ //| GetTrade | //+------------------------------------------------------------------+ CTrade *CSimpleRandom::GetTrade(void) { return m_trade; } //+------------------------------------------------------------------+ //| GetPositionInfo | //+------------------------------------------------------------------+ CPositionInfo *CSimpleRandom::GetPositionInfo(void) { return m_positionInfo; } //+------------------------------------------------------------------+ //| CSimpleRandom initialization | //+------------------------------------------------------------------+ bool CSimpleRandom::Init(void) { // Initialization logic here... return true; } //+------------------------------------------------------------------+ //| CSimpleRandom deinitialization | //+------------------------------------------------------------------+ void CSimpleRandom::Deinit(void) { // Deinitialization logic here... delete(m_brain); delete(m_evolution); delete(m_graphic); delete(m_trade); } //+------------------------------------------------------------------+ //| CSimpleRandom Go | //+------------------------------------------------------------------+ bool CSimpleRandom::Go(double ask,double bid) { double tp; double sl; int coin=m_brain.GetRandomNumber(0,1); // Is there any open position? if(!m_positionInfo.Select(_Symbol)) { // If not, we open one if(coin==0) { GetEvolution().SetStatus(BUY); } else { GetEvolution().SetStatus(SELL); } } // If so, let it work the mathematical expectation. else GetEvolution().SetStatus(DO_NOTHING); switch(GetEvolution().GetStatus()) { case BUY: tp = ask + m_brain.GetTakeProfit() * _Point; sl = bid - m_brain.GetStopLoss() * _Point; GetTrade().PositionOpen(_Symbol,ORDER_TYPE_BUY,m_brain.GetSize(),ask,sl,tp); break; case SELL: sl = ask + m_brain.GetStopLoss() * _Point; tp = bid - m_brain.GetTakeProfit() * _Point; GetTrade().PositionOpen(_Symbol,ORDER_TYPE_SELL,m_brain.GetSize(),bid,sl,tp); break; case DO_NOTHING: // Nothing... break; } // If there is some error we return false, for now we always return true return(true); } //+------------------------------------------------------------------+
2.3. 複雑なタイプのオブジェクトへのCSimpleRandom のバインディング
カスタムオブジェクトCBrain、CEvolution 、CGraphic タイプが CSimpleRandomにリンクされる方法に留意します。
まず対応する保護されたプロパティを定義します。
protected:
CBrain *m_brain;
CEvolution *m_evolution;
CGraphic *m_graphic;
そしてその直後にこれらオブジェクトをコンストラクタ内にインスタンス化します。
m_brain=new CBrain(TimeLocal(), TimeLocal() + lifeInSeconds, lot_size, stop_loss, take_profit); m_evolution=new CEvolution(DO_NOTHING); m_graphic=new CGraphic(_Symbol);
今やっていることは複雑なタイプのオブジェクトを動的に作成することです。公式ドキュメントが Object Pointersで説明しているとおりです。このスキームにより CSimpleRandomから直接CBrain、CEvolution、CGraphicの機能にアクセスすることができるのです。たとえば ExpertSimpleRandom.mq5内の以下のコードに対して実行することができます。
//+------------------------------------------------------------------+ //| OnTick event function | //+------------------------------------------------------------------+ void OnTick() { // ... int randNumber=SR.GetBrain().GetRandomNumber(4, 8); // ... }
ここで私はコードCBrain、CEvolution、CGraphic を書いてこの節の終わりとします。SimpleRandomのバックテストに必ずしも必要でないため、コード化されない部分もいくつかあることに注意してください。これらクラスの未コード部分はみなさんの練習用に残しておkます。ご自身の要望に応じて自由に作成してください。たとえばm_death はその背後にある考えはロボットが処理を終える日付の始まりを知るためですが、実際使用されません。
//+------------------------------------------------------------------+ //| ExpertSimpleRandom | //| Copyright © 2013, Jordi Bassagaсas | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| CBrain Class | //+------------------------------------------------------------------+ class CBrain { protected: ENUM_TIMEFRAMES m_period; // period must always be initialized to PERIOD_M1 to fit the system's idea datetime m_birth; // The datetime in which the robot is initialized for the first time datetime m_death; // The datetime in which the robot will die double m_size; // The size of the positions int m_stopLoss; // Stop loss int m_takeProfit; // Take profit public: //--- Constructor and destructor methods CBrain(datetime birth,datetime death,double size,int stopLoss,int takeProfit); ~CBrain(void); //--- Getter methods datetime GetBirth(void); datetime GetDeath(void); double GetSize(void); int GetStopLoss(void); int GetTakeProfit(void); //--- Setter methods void SetBirth(datetime birth); void SetDeath(datetime death); void SetSize(double size); void SetStopLoss(int stopLoss); void SetTakeProfit(int takeProfit); //--- Brain specific logic int GetRandomNumber(int a,int b); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CBrain::CBrain(datetime birth,datetime death,double size,int stopLoss,int takeProfit) { MathSrand(GetTickCount()); m_period=PERIOD_M1; m_birth=birth; m_death=death; m_size=size; m_stopLoss=stopLoss; m_takeProfit=takeProfit; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CBrain::~CBrain(void) { } //+------------------------------------------------------------------+ //| GetBirth | //+------------------------------------------------------------------+ datetime CBrain::GetBirth(void) { return m_birth; } //+------------------------------------------------------------------+ //| GetDeath | //+------------------------------------------------------------------+ datetime CBrain::GetDeath(void) { return m_death; } //+------------------------------------------------------------------+ //| GetSize | //+------------------------------------------------------------------+ double CBrain::GetSize(void) { return m_size; } //+------------------------------------------------------------------+ //| GetStopLoss | //+------------------------------------------------------------------+ int CBrain::GetStopLoss(void) { return m_stopLoss; } //+------------------------------------------------------------------+ //| GetTakeProfit | //+------------------------------------------------------------------+ int CBrain::GetTakeProfit(void) { return m_takeProfit; } //+------------------------------------------------------------------+ //| SetBirth | //+------------------------------------------------------------------+ void CBrain::SetBirth(datetime birth) { m_birth=birth; } //+------------------------------------------------------------------+ //| SetDeath | //+------------------------------------------------------------------+ void CBrain::SetDeath(datetime death) { m_death=death; } //+------------------------------------------------------------------+ //| SetSize | //+------------------------------------------------------------------+ void CBrain::SetSize(double size) { m_size=size; } //+------------------------------------------------------------------+ //| SetStopLoss | //+------------------------------------------------------------------+ void CBrain::SetStopLoss(int stopLoss) { m_stopLoss=stopLoss; } //+------------------------------------------------------------------+ //| SetTakeProfit | //+------------------------------------------------------------------+ void CBrain::SetTakeProfit(int takeProfit) { m_takeProfit=takeProfit; } //+------------------------------------------------------------------+ //| GetRandomNumber | //+------------------------------------------------------------------+ int CBrain::GetRandomNumber(int a,int b) { return(a+(MathRand()%(b-a+1))); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| ExpertSimpleRandom | //| Copyright © 2013, Jordi Bassagaсas | //+------------------------------------------------------------------+ #include <Indicators\Indicators.mqh> #include <Mine\Enums.mqh> //+------------------------------------------------------------------+ //| CEvolution Class | //+------------------------------------------------------------------+ class CEvolution { protected: ENUM_STATUS_EA m_status; // The current EA's status CArrayObj* m_operations; // History of the operations performed by the EA public: //--- Constructor and destructor methods CEvolution(ENUM_STATUS_EA status); ~CEvolution(void); //--- Getter methods ENUM_STATUS_EA GetStatus(void); CArrayObj *GetOperations(void); //--- Setter methods void SetStatus(ENUM_STATUS_EA status); void SetOperation(CObject *operation); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CEvolution::CEvolution(ENUM_STATUS_EA status) { m_status=status; m_operations=new CArrayObj; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CEvolution::~CEvolution(void) { delete(m_operations); } //+------------------------------------------------------------------+ //| GetStatus | //+------------------------------------------------------------------+ ENUM_STATUS_EA CEvolution::GetStatus(void) { return m_status; } //+------------------------------------------------------------------+ //| GetOperations | //+------------------------------------------------------------------+ CArrayObj *CEvolution::GetOperations(void) { return m_operations; } //+------------------------------------------------------------------+ //| SetStatus | //+------------------------------------------------------------------+ void CEvolution::SetStatus(ENUM_STATUS_EA status) { m_status=status; } //+------------------------------------------------------------------+ //| SetOperation | //+------------------------------------------------------------------+ void CEvolution::SetOperation(CObject *operation) { m_operations.Add(operation); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| ExpertSimpleRandom.mq5 | //| Copyright © 2013, Jordi Bassagaсas | //+------------------------------------------------------------------+ #include <Trade\SymbolInfo.mqh> #include <Arrays\ArrayObj.mqh> //+------------------------------------------------------------------+ //| CGrapic Class | //+------------------------------------------------------------------+ class CGraphic { protected: ENUM_TIMEFRAMES m_period; // Graphic's timeframe string m_pair; // Graphic's pair CSymbolInfo* m_symbol; // CSymbolInfo object CArrayObj* m_bars; // Array of bars public: //--- Constructor and destructor methods CGraphic(string pair); ~CGraphic(void); //--- Getter methods string GetPair(void); CSymbolInfo *GetSymbol(void); CArrayObj *GetBars(void); //--- Setter methods void SetPair(string pair); void SetSymbol(CSymbolInfo *symbol); void SetBar(CObject *bar); }; //+------------------------------------------------------------------+ //| Constuctor | //+------------------------------------------------------------------+ CGraphic::CGraphic(string pair) { m_period=PERIOD_M1; m_pair=pair; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CGraphic::~CGraphic(void) { } //+------------------------------------------------------------------+ //| GetPair | //+------------------------------------------------------------------+ string CGraphic::GetPair(void) { return m_pair; } //+------------------------------------------------------------------+ //| GetSymbol | //+------------------------------------------------------------------+ CSymbolInfo *CGraphic::GetSymbol(void) { return m_symbol; } //+------------------------------------------------------------------+ //| GetBars | //+------------------------------------------------------------------+ CArrayObj *CGraphic::GetBars(void) { return m_bars; } //+------------------------------------------------------------------+ //| SetPair | //+------------------------------------------------------------------+ void CGraphic::SetPair(string pair) { m_pair=pair; } //+------------------------------------------------------------------+ //| SetSymbol | //+------------------------------------------------------------------+ void CGraphic::SetSymbol(CSymbolInfo *symbol) { m_symbol=symbol; } //+------------------------------------------------------------------+ //| SetBar | //+------------------------------------------------------------------+ void CGraphic::SetBar(CObject *bar) { m_bars.Add(bar); } //+------------------------------------------------------------------+
3. ExpertSimpleRandom.mq5のバックテスト
この無作為トレーディングシステムは予想どおり特定のSLレベルとTPレベルに対してのみ有効であることが示されました。もちろんこれら勝者OSL/TP 間隔は全てのシンボルについて同じではありません。これは各シンボルが既定時刻にそれ自体の性質を表すため、または別の言い方をすればすべての通過ペアはその他と関連して異なる動きをするためです。そのため実環境でExpertSimpleRandom.mq5 を実行する前にまずバックテストにおけるこれらレベルを特定してくだい。
ここで本稿で紹介された考えが勝者であるように思うデータサンプルをいくつか共有します。これはMetaTrader 5 「ストラテジーテスタ」で何度も ExpertSimpleRandom.mq5 を実行したあと推論できるものです。
EURUSD、2012年12月に対する勝者インプット
- ストップロス:400
- テイクプロフィット: 600
- LotSize: 0.01
- TimeLife: MONTH
実行番号 1:
実行番号 2:
実行番号3:
おわりに
自動トレーディングシステムにオブジェクト指向プログラミングを採用することを学習しました。そのためまずメカニカルトレーディング戦略を決定する必要がありました。われわれのトレーディングの考え方はシンプルです。『乱調子でのショートトレンドは無作為に近い』というものです。これはいくつかの状況で複数の専門家によって観察されています。
そして EA を現実世界の語で生き物のように考えました。このビジョンのおかげでわれわれの Forex マシンが3つのメインパートで構成されるようにみなしました。脳、進化と呼ぶなにか、そしてチャートです。
最後にバックテストを実行するのに必要な理論を持つシステムのエキスパートアドバイザーをプログラムし、2012年1月でロボットを何度も実行し、ほとんどの場合システムが勝者であることを確認しました。このシステムの背後にある考えは真であると証明されましたが、その有効性はあまり高いものではありません。それはそのシンプルさによるものです。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/703





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索