
人気のトレーディングシステムを基にした Expert Advisors と売買ロボット最適化の錬金術(パート2)
はじめに
トレーディングシステムの最適化はさまざまな文献で幅広く論じられており、インターネットで簡単に見つけられるものをここで詳しく書くのは筋違いであると思われます。ここでは、自動システムの最適化一般の結果を利用するポイントを理解する理論のそこにある基本的なシンプルな考え、および特に最適化の実用性のみ詳しく述べていきます。
比較的シンプルなトレーディングシステムに基づき構築されたをストラテジーテスタにアップロードするのは簡単であることをみなさんはご存じだと思います。最適化を行ったあと、最適化の履歴データに一致するほとんどすべての履歴データに驚くべき検証結果を得ることができるのです。ただ、ここでは当然の疑問が起こります。「結果がすばらしくても、履歴に応じてシステムを調整したとしたら、自動システムの動作の予測と結果はどんな関係があるのか?」
現時点では、この疑問はかなり性急です。この理由の一つは、最初の正常な最適化後、初心者の EA プログラマーは本番の取引で最適化結果を利用するという軽率な考えについて誤った考え方を抱き、その結果は台無しになる可能性があります。初心者の EA プログラマーは自分自身の資金、または既製のを利用する人の資金を失ってしまいます。そんなわけで、私はこのトピックで本稿を始めます。
狂信的でないバックテストまたは検証最適化結果
通常、最初の EA 最適化経験後、人は、取引で最小限のドローダウン、最大限の利益を出す最適化結果使う戦略を構築しようと思います。そのようなパラメータセットのシステムは最適化期間だけでなく、近い将来にも利益を出すと願って。模式的にそれは以下のようなものです。
これは、トレーディング戦略のテスターを最初に知った後、多くの初心者の EA プログラマが使うロジックです。ただし、残念ながら、将来をちょっとのぞくことはできず、このロジックを使ったトレーディングシステムの効率を決めることはできないのです。本番の市場という点では処理結果の通常レコードに対してリアルタイムモードによりデモアカウントで戦略を検証することは、ひじょうに退屈な仕事です。
何年間も結果を待つに十分忍耐があれば、問題はなにもありません。ただし、その後、システムは完全に使い物にならず、時間とインターネット通信の無駄にとてもがっかりすることになるのです。また、そのような方法では多くのトレーディング戦略を検証することはできません。せいぜい1件か、最大でも2件です。最後です。そのようなトレーディング戦略に費やされる多大な労力は、その動作結果を決定的に推定する能力を作成者から奪ってしまいます。
そのような状況では、心理的に真実に向き合い、結果の戦略は時間と労力の無駄でしかなかったと認めることはきわめてむつかしいものです。当然、そのような労力と時間の無駄は、利益を出す Expert Advisor の作成にはつながりにくいものです。
この状況では、唯一の解決策は履歴データを基に将来をモデル化することです。ひじょうに簡単です。必要なことは、時間境界を前のスキームから時間軸に沿って左に移動することだけです。その場合、最適化後に、最適化データよりも現在に近い最近のデー9たで最適化結果を推定する時間が得られます。
上記を含めた多くの場合、そのような方法により、どんな特定の Expert Advisor に対してもパラメータを最適化した最適化結果を利用するその類の戦略の実際の効率を推定することができます。そのような最適化戦略の分析方法の模式的意味は以下の形で表現できます。
この図はひじょうに明確であると思います。たとえば、分析期間として2007年を取り上げます。1番目の最適化には、最適化期間は 2007.01.01~2007.03.31、検証期間は 2007.04.01~2007.05.31 です。検証し結果を記録したあと、最適化期間と検証期間を1か月先に送ります。最適化期間は 2007.02.01~2007.04.30、検証期間は 2007.05.01~2007.06.30 となります。等々。結果、各最適化結果記録のテーブルを取得します。たとえば以下のようなものです。
第1検証パラメータ/実行 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
純利益 | ||||||||||||
総利益 | ||||||||||||
総損失 | ||||||||||||
収益性 | ||||||||||||
絶対ドローダウン | ||||||||||||
相対ドローダウン | ||||||||||||
トータル取引 |
もちろん、最適化実行ごとに表のセルを埋める必要があります。そのような表を分析し、そこにある情報を処理することは大した問題にはならないので、この分析の結論は簡単に出すことができます。有効な履歴データ上のEA 動作のこの種の分析は、EA 最適化結果を正しく推定し、この処理に関する妄想を避けることに役立つと思います。デモアカウントでの検証と比較すると、時間の節約はすばらしいものです!
この調査も時間と労力が要求されるものの、バックテストのテクニックは初心者のEA プログラマにきわめて理解しやすいものです。ご自身の EA バックテスト中、よくない結果を得たとしおても、不安になることはありません。ひじょうに収益性があるように見える損失を生む戦略を本番で使用するよりは、仮想損失の方が断然よいのです。
バックテストに関してお伝えしたいことは以上です。最小ドローダウンの最大利益を選択することが唯一可能なシステム最適化戦略ではないことに留意します。それはバックテスト手順を紹介するためだけに提供されているのです。一般的にバックテスト中ほとんどの時間は最適化に費やされます。一方で。最適化戦略の検証にはほとんど時間がかかりません。よって、同時に複数の線りゃぅを検証し、これから得る結論のためにより大きな統計的材料を取得することは合理的です。ゆえにに、検証結果テーブルはより大きなものとなります。
オシレータトレーディング戦略
オシレータを基に、数多くの異なるトレーディング戦略を構築することが可能です。本稿では、買い過ぎ、売り過ぎ領域でエントランスとエグジットを行うことを基にした最も一般的なシステムについて説明します。
オシレータの大半は、一定の最小値から最大値へ値を変えます。オシレータはそれぞれ独自の値を持ちます。極値からある距離で、UpLevel と DownLevel が設定されます。
そのようなシステムでは、オシレータが非トレンド領域から出て、買い過ぎ領域に入ると、買いシグナルが発生します。
売りシグナルはオシレータが非トレンド領域から出て、売り過ぎ領域に入ると、発生します。
こういったメインのシグナル以外にも、このシステムはオシレータが売り過ぎおよび買い過ぎ領域を出て非トレンド領域に入るとき出現する別のシグナルがあります。いわゆる修正シグナルです。
買いシグナルはオシレータが売り過ぎ領域を出て非トレンド領域に入るとき発生します(下落トレンドの修正)。
売りシグナルはオシレータが買い過ぎ領域を出て非トレンド領域に入るとき発生します(上昇トレンドの修正)。
オシレータトレーディングシステム向け Expert Advisor のコード
よって、市場エンターのアルゴリズムが4つあります。ロングポジション用アルゴリズムのバリアントをよく注意して見ると、それらは完全に同じであり、唯一ブレイクアウトレベルで異なると断定することができます。それはプログラムコードを書く観点からはまったく無関係です。ショートポジションについても状況は同様です。以下はオシレータトレーディングシステム実装の私のバージョンです。
//+==================================================================+ //| Exp_3.mq4 | //| Copyright © 2007, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2007, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up1 = true;//filter of trade calculations direction extern int Timeframe_Up1 = 240; extern double Money_Management_Up1 = 0.1; extern double IndLevel_Up1 = 0.8; // breakout level of the indicator extern int JLength_Up1 = 8; // depth of JJMA smoothing of entering price extern int XLength_Up1 = 8; // depth of JurX smoothing of obtained indicator extern int Phase_Up1 = 100; // parameter changing in the range -100 ... +100, //influences the quality of transient processes of smoothing extern int IPC_Up1 = 0;/* Selecting prices on which the indicator will be calculated (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Up1 = 50; // stoploss extern int TAKEPROFIT_Up1 = 100; // takeprofit extern int TRAILINGSTOP_Up1 = 0; // trailing stop extern bool ClosePos_Up1 = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ ///---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up2 = true;//filter of trade calculations direction extern int Timeframe_Up2 = 240; extern double Money_Management_Up2 = 0.1; extern double IndLevel_Up2 = -0.8; // breakout level of the indicator extern int JLength_Up2 = 8; // depth of JJMA smoothing of entering price extern int XLength_Up2 = 8; // depth of JurX smoothing of obtained indicator extern int Phase_Up2 = 100; // parameter changing in the range -100 ... +100, //influences the quality of transient processes of smoothing extern int IPC_Up2 = 0;/* Selecting prices on which the indicator will be calculated (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Up2 = 50; // stoploss extern int TAKEPROFIT_Up2 = 100; // takeprofit extern int TRAILINGSTOP_Up2 = 0; // trailing stop extern bool ClosePos_Up2 = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn1 = true;//filter of trade calculations direction extern int Timeframe_Dn1 = 240; extern double Money_Management_Dn1 = 0.1; extern double IndLevel_Dn1 = 0.8; // breakout level of the indicator extern int JLength_Dn1 = 8; // depth of JJMA smoothing of entering price extern int XLength_Dn1 = 8; // depth of JurX smoothing of obtained indicator extern int Phase_Dn1 = 100; // parameter changing in the range -100 ... +100, //influences the quality of transient processes of smoothing extern int IPC_Dn1 = 0;/* Selecting prices on which the indicator will be calculated (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Dn1 = 50; // stoploss extern int TAKEPROFIT_Dn1 = 100; // takeprofit extern int TRAILINGSTOP_Dn1 = 0; // trailing stop extern bool ClosePos_Dn1 = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn2 = true;//filter of trade calculations direction extern int Timeframe_Dn2 = 240; extern double Money_Management_Dn2 = 0.1; extern double IndLevel_Dn2 = -0.8; // breakout level of the indicator extern int JLength_Dn2 = 8; // depth of JJMA smoothing of entering price extern int XLength_Dn2 = 8; // depth of JurX smoothing of obtained indicator extern int Phase_Dn2 = 100; // parameter changing in the range -100 ... +100, //influences the quality of transient processes of smoothing extern int IPC_Dn2 = 0;/* Selecting prices on which the indicator will be calculated (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Dn2 = 50; // stoploss extern int TAKEPROFIT_Dn2 = 100; // takeprofit extern int TRAILINGSTOP_Dn2 = 0; // trailing stop extern bool ClosePos_Dn2 = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBar_Up1, MinBar_Dn1; int MinBar_Up2, MinBar_Dn2; //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the correctness of Timeframe variable value if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("Parameter ",Name, " cannot ", "be equal to ", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up1 variable value TimeframeCheck("Timeframe_Up1", Timeframe_Up1); //---- Checking the correctness of Timeframe_Up2 variable value TimeframeCheck("Timeframe_Up2", Timeframe_Up2); //---- Checking the correctness of Timeframe_Dn1 variable value TimeframeCheck("Timeframe_Dn1", Timeframe_Dn1); //---- Checking the correctness of Timeframe_Dn2 variable value TimeframeCheck("Timeframe_Dn2", Timeframe_Dn2); //---- Initialization of variables MinBar_Up1 = 3 + 3 * XLength_Up1 + 30; MinBar_Up2 = 3 + 3 * XLength_Up2 + 30; MinBar_Dn1 = 3 + 3 * XLength_Dn1 + 30; MinBar_Dn2 = 3 + 3 * XLength_Dn2 + 30; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables double Osc1, Osc2; //----+ Declaring static variables //----+ +---------------------------------------------------------------+ static int LastBars_Up1, LastBars_Dn1; static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1; //----+ +---------------------------------------------------------------+ static int LastBars_Up2, LastBars_Dn2; static bool BUY_Sign2, BUY_Stop2, SELL_Sign2, SELL_Stop2; //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS 1 if (Test_Up1) { int IBARS_Up1 = iBars(NULL, Timeframe_Up1); if (IBARS_Up1 >= MinBar_Up1) { if (LastBars_Up1 != IBARS_Up1) { //----+ Initialization of variables BUY_Sign1 = false; BUY_Stop1 = false; LastBars_Up1 = IBARS_Up1; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS Osc1 = iCustom(NULL, Timeframe_Up1, "JCCIX", JLength_Up1, XLength_Up1, Phase_Up1, IPC_Up1, 0, 1); Osc2 = iCustom(NULL, Timeframe_Up1, "JCCIX", JLength_Up1, XLength_Up1, Phase_Up1, IPC_Up1, 0, 2); //----+ DEFINING SIGNALS FOR TRADES if (Osc2 < IndLevel_Up1) if (Osc1 > IndLevel_Up1) BUY_Sign1 = true; if (Osc1 < IndLevel_Up1) BUY_Stop1 = true; } //----+ EXECUTION OF TRADES if (!OpenBuyOrder1(BUY_Sign1, 1, Money_Management_Up1, STOPLOSS_Up1, TAKEPROFIT_Up1)) return(-1); if (ClosePos_Up1) if (!CloseOrder1(BUY_Stop1, 1)) return(-1); if (!Make_TreilingStop(1, TRAILINGSTOP_Up1)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS 2 if (Test_Up2) { int IBARS_Up2 = iBars(NULL, Timeframe_Up2); if (IBARS_Up2 >= MinBar_Up2) { if (LastBars_Up2 != IBARS_Up2) { //----+ Initialization of variables BUY_Sign2 = false; BUY_Stop2 = false; LastBars_Up2 = IBARS_Up2; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS Osc1 = iCustom(NULL, Timeframe_Up2, "JCCIX", JLength_Up2, XLength_Up2, Phase_Up2, IPC_Up2, 0, 1); Osc2 = iCustom(NULL, Timeframe_Up2, "JCCIX", JLength_Up2, XLength_Up2, Phase_Up2, IPC_Up2, 0, 2); //----+ DEFINING SIGNALS FOR TRADES if (Osc2 < IndLevel_Up2) if (Osc1 > IndLevel_Up2) BUY_Sign2 = true; if (Osc1 < IndLevel_Up2) BUY_Stop2 = true; } //----+ EXECUTION OF TRADES if (!OpenBuyOrder1(BUY_Sign2, 2, Money_Management_Up2, STOPLOSS_Up2, TAKEPROFIT_Up2)) return(-1); if (ClosePos_Up2) if (!CloseOrder1(BUY_Stop2, 2)) return(-1); if (!Make_TreilingStop(2, TRAILINGSTOP_Up2)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR SHORT POSITIONS 1 if (Test_Dn1) { int IBARS_Dn1 = iBars(NULL, Timeframe_Dn1); if (IBARS_Dn1 >= MinBar_Dn1) { if (LastBars_Dn1 != IBARS_Dn1) { //----+ Initialization of variables SELL_Sign1 = false; SELL_Stop1 = false; LastBars_Dn1 = IBARS_Dn1; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS Osc1 = iCustom(NULL, Timeframe_Dn1, "JCCIX", JLength_Dn1, XLength_Dn1, Phase_Dn1, IPC_Dn1, 0, 1); Osc2 = iCustom(NULL, Timeframe_Dn1, "JCCIX", JLength_Dn1, XLength_Dn1, Phase_Dn1, IPC_Dn1, 0, 2); //----+ DEFINING SIGNALS FOR TRADES if (Osc2 > IndLevel_Dn1) if (Osc1 < IndLevel_Dn1) SELL_Sign1 = true; if (Osc1 > IndLevel_Dn1) SELL_Stop1 = true; } //----+ EXECUTION OF TRADES if (!OpenSellOrder1(SELL_Sign1, 3, Money_Management_Dn1, STOPLOSS_Dn1, TAKEPROFIT_Dn1)) return(-1); if (ClosePos_Dn1) if (!CloseOrder1(SELL_Stop1, 3)) return(-1); if (!Make_TreilingStop(3, TRAILINGSTOP_Dn1)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR SHORT POSITIONS 2 if (Test_Dn2) { int IBARS_Dn2 = iBars(NULL, Timeframe_Dn2); if (IBARS_Dn2 >= MinBar_Dn2) { if (LastBars_Dn2 != IBARS_Dn2) { //----+ Initialization of variables SELL_Sign2 = false; SELL_Stop2 = false; LastBars_Dn2 = IBARS_Dn2; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS Osc1 = iCustom(NULL, Timeframe_Dn2, "JCCIX", JLength_Dn2, XLength_Dn2, Phase_Dn2, IPC_Dn2, 0, 1); Osc2 = iCustom(NULL, Timeframe_Dn2, "JCCIX", JLength_Dn2, XLength_Dn2, Phase_Dn2, IPC_Dn2, 0, 2); //----+ DEFINING SIGNALS FOR TRADES if (Osc2 > IndLevel_Dn2) if (Osc1 < IndLevel_Dn2) SELL_Sign2 = true; if (Osc1 > IndLevel_Dn2) SELL_Stop2 = true; } //----+ EXECUTION OF TRADES if (!OpenSellOrder1(SELL_Sign2, 4, Money_Management_Dn2, STOPLOSS_Dn2, TAKEPROFIT_Dn2)) return(-1); if (ClosePos_Dn2) if (!CloseOrder1(SELL_Stop2, 4)) return(-1); if (!Make_TreilingStop(4, TRAILINGSTOP_Dn2)) return(-1); } } //----+ +---------------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
このコードは先行記事で提供したコードに比べると2倍長いものです。ところで、オーダー管理関数の呼出しの代わりに完全プログラムであれば、この EA コードがどれほど長いものであるか想像してください。このには新しい入力パラメータが入っていることに注意が必要です。それは、IndLevel_Up1、IndLevel_Up2、IndLevel_Dn1、IndLevel_Dn2 です。IndLevel_Up1 と IndLevel_Up2 はロングポジションの2つのアルゴリズムに対し Uplevel と DownLevel を定義します。一方、IndLevel_Dn1 および IndLevel_Dn2 はショートポジションのアルゴリズムに対し DownLevel と Uplevel を定義します。
この Expert Advisor の最適化中、これらレベルの値は -1.0 to +1.0 で変化することを考慮する必要があります。この EA の JCCIX オシレータを別の任意のオシレータと置き換えたければ、これらレベルの最大値と最小値は異なることに配慮が必要です。ソースインディケータ JCCIX は CCI インディケータの類似体で、そこでは一般的な移動平均によるアルゴリズムの平滑化は JMA と超線形平滑化に置き換わります。この EA ではトレーリングストップが使用されています。その値はTRAILINGSTOP_Up1、TRAILINGSTOP_Up2、 TRAILINGSTOP_Dn1、TRAILINGSTOP_Dn2 のような EA の入力パラメータで決められます。それ以外の語に関しては、この EA は完全に前稿で述べた EA に類似しています。
即時の市場参入を未決注文への変更
上記 EA の類似体では多くの場合、即時の市場エンターを未決注文に変更することで、市場参入をより正確にし、ストップロスへの到達可能性を低く、より大きな利益を得ることが可能となります。ファイル Lite_EXPERT1.mqh の関数セットでそのような置換が簡単になります。
必要なことは、関数 OpenBuyOrder1() および OpenSellOrder1() を OpenBuyLimitOrder1() と OpenSellLimitOrder1() にそれぞれ置き換えることだけです。そのような関数置換の間に、それらの新しい入力変数-LEVEL および Expiration、が初期化されます。たとえば、有効な LEVEL 変数が EA の入力パラメータによって定義されるトレーディング戦略を構築することができます。未決注文の取り消し日は現行バーの次の変更時刻として設定します。
ここで同じコードは繰り返して記しません。上記 EA の変更後コードは本稿に添付があります(Exp_4.mq4)。未決注文の使用例として、 OSMA オシレータを使ったオシレータシステムを記述します。
//For the EA operation the Metatrader\EXPERTS\indicators folder //must contain the 5c_OsMA.mq4 indicator //+==================================================================+ //| Exp_5.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern int Timeframe_Up = 240; extern double Money_Management_Up = 0.1; extern double IndLevel_Up = 0; // breakout level of the indicator extern int FastEMA_Up = 12; // period of quick EMA extern int SlowEMA_Up = 26; // period of slow EMA extern int SignalSMA_Up = 9; // period of signal SMA extern int STOPLOSS_Up = 50; // stoploss extern int TAKEPROFIT_Up = 100; // takeprofit extern int TRAILINGSTOP_Up = 0; // trailing stop extern int PriceLevel_Up =40; // difference between the current price and // the price of pending order triggering extern bool ClosePos_Up = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern int Timeframe_Dn = 240; extern double Money_Management_Dn = 0.1; extern double IndLevel_Dn = 0; // breakout level of the indicator extern int FastEMA_Dn = 12; // period of quick EMA extern int SlowEMA_Dn = 26; // period of slow EMA extern int SignalSMA_Dn = 9; // period of signal SMA extern int STOPLOSS_Dn = 50; // stoploss extern int TAKEPROFIT_Dn = 100; // takeprofit extern int TRAILINGSTOP_Dn = 0; // trailing stop extern int PriceLevel_Dn = 40; // difference between the current price and // the price of pending order triggering extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBar_Up, MinBar_Dn; //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the correctness of Timeframe variable value if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("Parameter ",Name, " cannot ", "be equal to ", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value TimeframeCheck("Timeframe_Up", Timeframe_Up); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("Timeframe_Dn", Timeframe_Dn); //---- Initialization of variables MinBar_Up = 3 + MathMax(FastEMA_Up, SlowEMA_Up) + SignalSMA_Up; MinBar_Dn = 3 + MathMax(FastEMA_Dn, SlowEMA_Dn) + SignalSMA_Dn; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables double Osc1, Osc2; //----+ Declaring static variables //----+ +---------------------------------------------------------------+ static datetime StopTime_Up, StopTime_Dn; static int LastBars_Up, LastBars_Dn; static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1; //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS 1 if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); if (IBARS_Up >= MinBar_Up) { if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign1 = false; BUY_Stop1 = false; LastBars_Up = IBARS_Up; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 60 * Timeframe_Up; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS Osc1 = iCustom(NULL, Timeframe_Up, "5c_OsMA", FastEMA_Up, SlowEMA_Up, SignalSMA_Up, 5, 1); Osc2 = iCustom(NULL, Timeframe_Up, "5c_OsMA", FastEMA_Up, SlowEMA_Up, SignalSMA_Up, 5, 2); //----+ DEFINING SIGNALS FOR TRADES if (Osc2 < IndLevel_Up) if (Osc1 > IndLevel_Up) BUY_Sign1 = true; if (Osc1 < IndLevel_Up) BUY_Stop1 = true; } //----+ EXECUTION OF TRADES if (!OpenBuyLimitOrder1(BUY_Sign1, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up, PriceLevel_Up, StopTime_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop1, 1)) return(-1); if (!Make_TreilingStop(1, TRAILINGSTOP_Up)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR SHORT POSITIONS 1 if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); if (IBARS_Dn >= MinBar_Dn) { if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign1 = false; SELL_Stop1 = false; LastBars_Dn = IBARS_Dn; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 60 * Timeframe_Dn; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS Osc1 = iCustom(NULL, Timeframe_Dn, "5c_OsMA", FastEMA_Dn, SlowEMA_Dn, SignalSMA_Dn, 5, 1); Osc2 = iCustom(NULL, Timeframe_Dn, "5c_OsMA", FastEMA_Dn, SlowEMA_Dn, SignalSMA_Dn, 5, 2); //----+ DEFINING SIGNALS FOR TRADES if (Osc2 > IndLevel_Dn) if (Osc1 < IndLevel_Dn) SELL_Sign1 = true; if (Osc1 > IndLevel_Dn) SELL_Stop1 = true; } //----+ EXECUTION OF TRADES if (!OpenSellLimitOrder1(SELL_Sign1, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn, PriceLevel_Dn, StopTime_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop1, 2)) return(-1); if (!Make_TreilingStop(2, TRAILINGSTOP_Dn)) return(-1); } } //----+ +---------------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
2つのブレイクアウトレベル UpLevel および DownLevel の代わりに、レベルは1つ使われています。EA にあるポジション管理アルゴリズムが2つだけなのは、そのためです。通常、OsMA と連携するトレーディングシステムでは、このレベルはゼロとして選択されますが、私はそれを変更できるように、EA の外部変数として残すことにしました。すなわち、OSMA インディケータが、インディケータが変化する最大値と最小値を持たず、その結果ブレイクアウトレベルの値に制限がないことを考慮する必要があるのです。ですが、申し上げたように、通常それはゼロです。未決注文鳥軽視時刻を定義するには、静的変数StopTime_Up と StopTime_Dn が使用され、バー変更時に 初めてそれらは次回のバー変更の時刻で初期化されます。
おわりに
結論として、オシレータトレーディングシステムは、現在の市場トレンドに対して多くの誤ったシグナルを出すことを付け加えたいと思います。そのような EA は市場がフラットな期間での処理、またはトレンドのみでのポジションオープンに使用するのがより適しています。
バックテストについては、おそらく初心者の EA プログラマーにとって最適化結果を正しく推定するには一番の方法だろうということを再度申し上げます。履歴を調整する際、すばらしい結果を出す EA には何も問題はありません。ただし、市場が最適化された EA パラメータからかけ離れる状況を避けるために、既製のEA をどのように使用するかはもっと理解が困難です。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1517





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