English Русский 中文 Español Deutsch Português
初めてのGrail

初めてのGrail

MetaTrader 4テスター | 16 2月 2016, 11:43
1 371 0
Сергей Ковалев
Сергей Ковалев

"... アートはプログラムされることはありません。詩の二つ意味は
混ぜられることはありません。才能は、
正条植えによっては成長されません。
.. 彼らは生まれるのです。それらは、国家の富である
ラジウム預金のようなもので、
スィグルダやべテスダの9月のようです。"
(Andrey Voznesenskiy)


Holy Grail はChristが一般的に最後の夕食で酔っ払った際に使用したカップで、十字架から血をとる際にJosephによって使用されたものであると考えられています。その聖餐杯を栄養を提供する石で、1週間以内に死ぬことを防ぐものとして表現します。こちらでさらに詳しく知ることができます。また、インターネット検索エンジンを使用してください。

その単語 "grail"は今では現代のプログラムに皮肉的に使用されています。すべての場合に当てはまる「普遍的な」プログラムを作成することは不可能であるという意味で使用されています。MQL4はにおけるプログラミングに関して、この単語は実際のトレーディングにおいて効果的なエキスパートを作成することは不可能という意味を指します。

実際、Forexは、経済・産業の関係、人格、政治などの複雑な現象の集合体の繁栄です。さらに、簡単に公式化することはできません。熟練したトレーダーは、もしトレンドを示す3から5以上のサインがあれば、マーケットに入ることを勧めます。

同時にその規則はかなり高い成功確立のマーケット予測における基礎を完全に提供することはできません。著名な銀行や金融機関の一流のアナリストによってなされる矛盾のある予測は、これを保証しています。全てのアナリストは例外なくすでに起こっている出来事に対しては上手に解釈しますが、ほとんどは自信のある予測を行うことはできません。

それらに焦点を当ててみましょう;彼らはできることをやっているだけで、多くは長いトレーディング経験や知識を持っています。しかし、それを適切に述べるとすれば、彼らのほとんどが失敗しています。彼らはビッグに見え、多かれ少なかれ人気を博し、時折かなりの遺産を残します(Trading for a Living: Psychology, Trading Tactics, Money ManagementというタイトルのAlexander Elderの本にてよく記載されています。)、しかし、事実は依然、 熟練したアナリストがしばしば間違えるということです。

したがって、これらの状況を考慮し、Forexでのトレーディングに最初のステップを踏もうとする初心者プログラマをどうすれば良いのでしょうか?初心者が歩む「聖杯」探求への道を辿ってみましょう。


1. "聖杯"は何で構成されるのか

形式的なロジックにおいて、権威を主張することは証拠とはみなされません。これを知ると、初心者は大方このように推測します:「聖杯の作成は不可能であると証明できるのか?証明できない?もしできないのであれば、それは可能だ!". 初心者は、そのようなものを作成することができるかは未だ証明されていないということを考慮に入れません。そして、その他の「金鉱探し」の経験を学んだり、検討しようとせず、熱意に基づく「できる!」という自分の考えに突き動かされ、プログラミングを始めます。

1.1. 公式の戦略

多くの場合、初心者プログラマは、短期間でかなり利益を生むトレーディング戦略を作成するという作業を自己に課しません。Forexでの大きい利益を生むという夢に奮起され、トレーディング基準が利益を生むエキスパートにおいて必要であると気付きません。

良い基準を見つけるために初心者はMetaTrader 4クライアントターミナルを開き、M!のタイムフレームのEURUSDチャートを見てください。通過レートが波のように変化していることに気づくでしょう。プログラマはこれらの波にて利益を生むことにします。しかし、その波をつかむには、例えば波は上昇をやめ、下降することを知る必要があります。

もしそのシンプルなレートの動きを基準として選べば、黒と白のろうそくが高頻度で入れ替わり、その小さな変化の幅はほぼスプレッド値なので、なんの結果も導きません。さらに、スロープ状態ではなく波の頂点時にマーケットに参入する方が利益を生みます。そして、その波は不幸にも異なる高さです。熟慮し、プログラマは以下の基準に決定しました:
  • もしレートが特定のポイント、例えば、10から15に上昇し、上昇をやめ、およそ3ポイントほど下降(図1 移動 B-C)した場合、(図1移動 A-B)マーケットが下降の動きの時に参加される必要があると想定する。この時、マーケットの降下移動は予測されます(図1のC-D)Buyのクロージングに使用される同様の基準
  • もしレートが特定のポイント、例えば、10から15に下降し、下降をやめ、およそ3ポイントほど上昇(図1 移動 C-D)した場合、(図1移動 D-E)マーケットがその上方の動き(Buy) の時に参加される必要があると想定する。この時、そのマーケットの上昇の動きは予測されます(図1 E-F)Sellのクロージングにおいて使用される同様の基準



図1. エキスパートGraal_1 (Grail 1).におけるトレーディング基準

時折予想もしない驚きの経験を与えることがあります:3ほどだけで初心者プログラマが「聖杯」を作成することができました。
extern int TP=100; extern int SL=100; extern int lim=1; extern int prodvig=3;
extern double  Prots= 10;
int   total, bb=0,ss=0; double max,min,lmax,lmin,Lot; 
int start(){
total=OrdersTotal(); if (total==0){bb=0;ss=0;}
if (max<Bid) max=Bid;if (min>Ask) min=Ask;
if (((max-Bid)>=lim*Point)&&(Bid>lmax )) { for (int i=total;i>=0;i--) { 
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY)
{OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE); bb=0;}} Strateg(1); } 
if (((Ask-min)>=lim*Point)&&(lmin>Ask )) { for (i=total;i>=0;i--) {
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL)
{OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);ss=0;}}  Strateg(2);}return;}
void Strateg (int vv)                                    
{if (vv==1 && ss==0)                                   
{OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red); ss=1;}
if (vv==2 && bb==0)                                   
{OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);bb=1;}
lmax=Ask+prodvig*Point; lmin=Bid-prodvig*Point;   return;  }
double Lots(){ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);
double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   
if (Lot==0 ) Lot=Min_Lot; return(Lot);  }


作成することができました。寛大になりましょうーこれはスタイルがまだ形成されていない初心者プログラマの最初の経験です。そして、本当に素晴らしい結果を残したので、このエキスパートを褒め称えましょう。

そのコードをより読みやすくし、何が何か理解できるようにします。少し編集した後、このエキスパートはこのようになります:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_1.mq4 (Grail 1).
// Used as an example in the article My First "Grail".
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int     TP = 100;                                 // TakeProfit orders
extern int     SL = 100;                                 // StopLoss orders
extern int     lim=   1;                                 // Distance of the rate return
extern int     prodvig=3;                                // Distance of the rate progress
extern double  Prots= 10;                                 // Percentage of the liquid assets
//--------------------------------------------------------------------------------------------
int
   total,                                                // Count of lots
   bb=0,                                                 // 1 = the Buy order is available
   ss=0;                                                 // 1 = the Sell order is available 
//--------------------------------------------------------------------------------------------
double 
   max,                                                  // Maximum price at the peak (abs.)
   min,                                                  // Minimum price in the trough(abs.)
   lmax,                                                 // Limiting price after the exceeding
                                                         // of which we consider selling(abs.)
   lmin,                                                 // The same for buying
   Lot;                                                  // Count of lots
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
   {   
//============================================================================================
   total=OrdersTotal();                                  // Count of lots
   if (total==0)                                         // If there are no orders, ..
      {
      bb=0;                                              // .. no Buys
      ss=0;                                              // .. no Sells
      }
   if (max<Bid) max=Bid;                                 // Calculate the max. price at the peak 
   if (min>Ask) min=Ask;                                 // Calculate the min. price in the trough
//------------------------------------------------------------- The price turns down ----
   if (((max-Bid)>=lim*Point)&&(Bid>lmax ))              // Turn at a high level
      {
      for (int i=total;i>=0;i--)                         // On all orders
         {                                               
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY)
            {
            OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE);// Close Buy
            bb=0;                                        // No Buys anymore
            }
         }   
      Strateg(1);                                        // Opening function
      }             
//------------------------------------------------------------ The price turns up ----
   if (((Ask-min)>=lim*Point)&&(lmin>Ask ))              // Turn at the deep bottom
      {
      for (i=total;i>=0;i--)                             // On all orders
         {
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL)
            {         
            OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);// Close Sell   
            ss=0;                                        // No Sells anymore
            }
         }
      Strateg(2);                                        // Opening function
      }
//============================================================================================
   return;

   } 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Strateg (int vv)                                    // Opening function
   {
//============================================================================================
   if (vv==1 && ss==0)                                   // Sell situation and no Sells
      {
      OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red);// Откр
      ss=1;                                              // Now, there is a Sell
      }
//--------------------------------------------------------------------------------------------
   if (vv==2 && bb==0)                                   // Buy situation and no Buys
      {
      OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);// Откр
      bb=1;                                              // Now, there is a Buy
      }      
//--------------------------------------------------------------------------------------------
   lmax=Ask+prodvig*Point;                               // Redefine the new limiting ..
   lmin=Bid-prodvig*Point;                               // .. levels for open and close 
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()                                            // Calculation of lots
   {
//============================================================================================
   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amoung of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum permissible cost of lots
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min.lots
//============================================================================================
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*


一般的にそのエキスパートの内容はかなり理解しやすいです。

その上部では、start()関数前に変数が収集されています。start()関数にて、スロープの頂点にて現在のレートの位置がまず計算され、その状況がトレーディング基準を満たすか分析されます。もしその基準が満たされれば、すでに処理されている注文がクローズされます。二つの以上の関数がエキスパートが使用されています - 新規注文をオープンするためのStarteg()とロットの量を決定するLots()です。変数 ssとbbがオープンされた注文を予約するために使用されます。

ストラテジーテスターは、MetaTrader 4クライアントターミナルにておいてかなり重要なツールです。プログラマは、インプットを最適化するために注意深くエキスパートをテストしました。最良の結果の一つが以下になります:




図2. 古典的な"聖杯". その結果は、 MetaQuotes Software Corpのトレーディング条件下にて、2005年3月から2006年1月のM1 EURUSDの履歴データにおけるGraal_1.mq4 (Grail 1)というエキスパートのテスト時に取得されたものです。デモサーバー

プログラマが喜んでいる姿を容易に想像できます:彼自身で作品を完成させることができました!こちらが彼らの初めての「聖杯」です!くそのプログラマはシンプルな結論を下しました: "自分だけが作成した!"

公式の戦略が必ずしも「聖杯」の作成につながりませんが、この例ではそうなりました。プログラマにこのような結果をもたらしたものについて詳しく見てみましょう。

1.2. 上級の投資

プログラマは、中途半端なところでは止めず、注文の値を最大化することになりました。現金の資産(Prots=70という値)の70%までに値しますが、このアプローチは結果として効果的ではないことがわかりました。


図3. 攻撃的な投資は、不当な損失につながりうる


我々のヒーローは、そのような結果に驚きました。そしてこのように考えました:「そのエキスパートが利益を生むなら、より多くを投資すれば、より多くを得ることができる!」しかし、テスターの結果は必ずしもそうではないと示しました。

そのような結果を引き起こしたものが何か調べてみましょう。

1.2.1. 幾何学的進歩

注文値の計算技術について見てみましょう。上記のコードによれば、その注文の値は流動資産の額に応じて増加します:

 Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum allowed lot value
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min.lots


このアルゴリズムは、幾何学的進歩を示しています。Prots (パーセント)変数は、現在の流動資産の額に応じて注文の額を規定させます。注文の額を計算するこの方法は特定のディーラーの際の証拠金請求を考慮していないので、あまり正しくはありません。同時に、上記のコードは主な問題である比例した投資という問題を解決します。したがって、後続する注文の額は取得された結果に比例して依存します:その額は個々の利益のあるトレードの後に大きくなり、損失を生んだトレードの後に減少します。上記のGraal_1.mq4 (Grail 1)の注文の値は、流動資産の10%です。

その拡大は、"聖杯"の必要な性質ではありません。その他の普通のエキスパートは、この技術を用いて作成できます。しかし、幾何学的進歩はより注意深く聖杯を調査するために除外する必要があり、最小注文値にて取得されたテスト結果のみに焦点を当てます。この場合、容易に取得したポイント量を評価することができます。

以下のコードに応じてProts変数の値を0に設定します。

   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min. lots

定数値の注文値にてエキスパートをテストします。

この場合、テスト結果は以下のようになります。

図4. 定数 ロット値でのExpert Graal_1.mq4 (Grail 1) のテスト結果

累進的な注文の値の除外は、バランスカーブの変化の本当の本質を視覚化します-大波、深い欠点などです。

1.2.2. 攻撃的な再投資

利益を生むエキスパートは、利益と損失の間の利点を探しています。利益を生むトレードのみ を実行する技術は現在ありません。トレードで損失を上げることは、茶道するトレーディングストラテジー全てにおいて普通です。問題は利益を生む処理とそうでないものの比率が何かという点です。

例えば、利益と損失が3:1であれば、かなり良いと考えられます。これは、100の連続したオープン・クローズされた注文は利益を出す75のトレードと損失を出す25のトレードからなるということです。同時に、損失を出す注文がどのように利益を出す注文の中に潜んでいるか予測することはできません。この配分は、ランダムな性質を持ちます。

A.利益と損失の理想的な配分は、すべてのトレーディング利益を通して均一な配分になるでしょう。

P P P L P P P L P P P L P P P L P P P L P P P L P P P L ...

しかしながら、その配分が常に理想的であるという保証はありません。反対に、連続した損失が遅かれ早かれ起こることはありえます。


В.
以下は実際のトレーディングで起こりうるの利益と損失の非均一の 配分状況の例です。

P P P P P P P P P P P P P P P LLLL P P P L P P P L ...


5つの連続した損失が上記で示され、そのような損失を出すトレードはより長くなる可能性もあります。この場合、その比率は3:1で維持されるということに注意してください。

したがって、この 規則的なランダム性はどういう結果になるのでしょうか?この質問に対する答えは、トレーダーが選択した戦略の質に依存します。攻撃的な再投資: i利益を得るたびに大半のデポジットを一度に投資します。

攻撃的な再投資の場合、そのトレーディング口座履歴は、予測できないほどに発展します。まれな"lラッキー"はトラブルを逃れます。しかし、多くの場合、残念な結果が差し迫ります。エキスパートGraal_1.mq4 (Grail 1) がいかに動作するかの起こりうるシナリオを表現するために、すべての条件が等しい二つの投資を分析してみましょう(同じ履歴期間、同様の入力)
  • 1. 注文のあ愛は、 流動資産の10%(Prots=10)です。そのような状況下で、テストはよい仕事をし、バランスを少しずつ長期的に増加させました。図2.で結果をご覧ください。You can also notice in the Fig.2 that the expert has been working for a very long time (about 10 000 orders)
  • 2. 注文の額は 流動資産の70% です (Prots=70;)テスト結果は図3に示されています。連続して損失を出した2、3の注文は、エキスパートが400トレードを実行する前にデポジットが空になる結果となりました。

テスト結果についてレポートに注意を払ってみてください:Graal_1.mq4 (Grail 1) エキスパートにおける連続した損失の最大の数は10のみです。その他の損失は、テスト期間全体で発生しますが、それぞれの損失の数は10を超えません。これらの損失は、(1)のトレーディングの全体の結果を大きく影響しませんが、(2)では壊滅的です

したがって、そのまちがった投資での損失は、完全な失敗につながります。適切な資産管理のために開発された効果的なシステムがあります - Money Management. このシステムによれば、一つの注文の値は、バランス全体の15%を超えず、投資の額は、その50%を超えないようにします。このシステムは、プログラマが読んだことのあるいくつかの便利なルールを提供しています。

彼らはこのような結論を導きます:攻撃的な再投資を用いるトレーディングは、自己欺瞞であり、破産につながります。すべてのトレーダーは、個別に制限を置く位置を決めます。その結果はそれに応じて取得されます。

したがって、「聖杯」をいじり、すべてがうまく動作することを確認し、プログラマは実際のアカウントを開き、「金を稼ぎ」始めます。複数の注文がオープン・クローズされた後、バランスが成長せず、安定して降下していることがわかりました。さらに、取引所のスタッフがそのプログラマのエキスパートをその日の終わりに停止させます。

そして、プログラマはかなりイライラしだします。ディラーからのそのような不当に対する理由を聞こうとしますが、いかなる説明にも同意しません。困惑します:どのような"技術制限”があるのか?”遅延”と関係があるのか?!実際のトレーディングの最初の経験の結果として、プログラマはこれは「悪い取引所」だという結論に至り、ただ
いたずらされたのだと考えます。そして、その業者との契約を破棄します。


しかし、諦めず、そのプロセスの詳細を見てみることにし、MQL4にてより熟練したトレーダーにコンタクトを取り、そのコードを見せました。コードをみせますが、いかなる場合においてもそのエキスパートは利益を出さないということに同意します。プログラマは、フォーラムにて議論がなされた後、以下について理解しました。


1.3. エラー

Meta Editorは、継続的にエラーが起こらないことを確認します。
図5. コンパイル中のエラー無し

にもかかわらずエラーがありました。

1.3.1. 公式戦略からの脱線


かなり知識豊富な戦略がエキスパート作成の根底にあるにもかかわらず、凡用変数の最適化やコーディング中に変更されました。したがって、初期の考えは、縮小された「聖杯」に示されています。実際、その考えは、14-20ポイントの波にて稼ぐことでしたが、このパラメーターは現在の「聖杯」版にて3という悲惨な値を取得します。山と谷を誰がここでわかるでしょうか...

黒と白に明確な境界線はありません。すべての中間的な状態は、白と黒の係数によって係数によって特徴づけられます。しかし、普通、ある色は白よりも黒く、また逆もそうであると判別できます。この場合、その初期の「純粋な白」は「黒」にされ、スウィープほどに黒くなり、すべての力を失いました。これを取得された「聖杯」の理由であると考えられます。
1.3.2. まちがったプログラミング

注文が変数ssとbbにてどのように考察されるのか注意しましょう。これは注文を考察する間違った方法です。その注文はすでに形成された時にオープンされていると考えられます。しかし、前もってその注文がオープンされるかはわかりません。サーバーが返答するまで待ち、ターミナルにてその注文の可能性を分析します。実際のトレーディングにおいて、ストラテジテスター内も含めて特定の修正は多くの場合動作しますが(Considering Orders in a Large Programという記事をご覧ください )、このコードは再度書き直される必要があります。

1.4. ハードウェアの制限


エキスパートは、タイムフレームにてテストされ、M1にてそれが意図されています。M1タイムフレームにてエキスパートのトレーディングのモデル化を行う際、とくに価格に敏感なエキスパートにおいてとても注意深くなります。

もしより大きいタイムフレームにてバーの履歴を正確にしたいのであれば、より小さいタイムフレームのバー履歴を使用できます。しかし、M1において、ティック履歴が保存されず、またMetaTrader4クライアントターミナルにて使用されていないので、より小さいタイムフレームはありません。 (Strategy Tester: Modes of Modeling during Testingをご覧ください)

テストモデルと実際のトレーディング戦略の大きな違いは、テストモードは遅延や再価格設定をしない(ディーラーが別の価格を渡した時)という店です。

異なる取引所は、異なるデータフィードで作動します。より高頻度でレートを変えると、ディーラーがトレーダーに別の価格で注文を実行することを提案するようになります。一方で、よりトラッフィクが滑らかに見えると、再価格設定は起こりにくくなりますが、頻繁にトレードするエキスパートにとってスペースが少なくなります。

プログラマは、別の取引所で1分間の履歴のGraal_1 (Grail 1)をテストし、自身の目で結果がトラッフィクの種類によって大きく変わることを確認しました。


図6. FX Integralbankのデモサーバーのトレーディング条件での2006年4月4日から7月26日までのEURUSDのM1の履歴でのGraal_1.mq4 (Grail 1)テスト結果

深い欠点の存在や不安定な利益開発は、エキスパートが損失の瀬戸際でバランスをとることを示します。

結果として、その再価格設定額は、1か2ポイントで異なります (早いマーケットではもっと大きく異なります). もしその超過した支払いが10-15などで、より大きければ、この状況は、本質的にエキスパートの成功に影響を与えません。しかし、エキスパートは小さい支払いを持ち、もしそれが2以下であれば、その価格の本質や確定され再価格設定に依存するので、一般的な成功を当てにしません。

特定のディーラーが現在のティックにて再価格設定をするか否かは、ディーラーのみが答えられる質問です。実際のマーケットに取り組み始めると、再価格設定は標準であり、自然な現象であると想定する必要があり、実際のアカウントで動作するトレーディング技術はこれを考慮する必要があります。



1.5. 経済的な要素

  • 少額の注文

トレーダーの注目が、トレーディングアカウントや戦略、エキスパートに向けられているという状況は最も直面する状況です。しかし、トレーダーの関心に加えて、ディラーの経済的関心ごとがあります。

「普通の」トレーディングでは双方が勝ちます:よく考えられた戦略を使用するトレーダーや、トレーダーにより実行されるトレード処理の利益を得るディーラーの二人です。この場合、双方はお互いに関連し、助け合おうとします。

しかし、一方の行動が他方の利益に反対するという状況も起こります。例えば、もしディーラーがそのスプレッドをあげ、自動トレーディングを停止させたり、注文をオープンしなければ、これはトレーダーの利益に対します。

同時に、トレーダーの行動がディーラーの経済的な利益に反することがあります。そのような行動の一つは、少額での高頻度なトレード処理です。

ディーラーの技術は、かなり単純です。ディーラーは、買い注文や売り注文を収集し、それらの価格差を処理するため銀行や金融機関と連携します。簡単な例を調査してみましょう。ディーラーが100人のトレーダーに対してサービスをし、その内60人がEURUSDを1ロットで購入し、40人が同じ通貨ペアを1ロットで売りに出します。この場合、そのディーラーは銀行から20ロット購入しなければなりません。その際、その価格の方向がいかなる場合でも同じです。どのような場合でも、そのディーラーは80ロットにおいて全スプレッドと20ロットの部分的なスプレッドを取得します(いくつかはサービスのために銀行に提供されます。)

この場合、40人のトレーダーにおける利益/損失のソースは、その他の40人のトレーダーの損失/利益です。残りの20人のトレーダーの利益/損失のソースは、銀行で、より正確に言うと、銀行により提供されている法的個人や輸出入処理のための売買通貨です。これは、いかに金融市場が相互関連しているかということを示しています。

しかし、どのようにディーラーが銀行や金融機関と連携しているかより詳細に示すものがあります。問題は、ディーラーは、もしトレーダーが少額の金額で購買する場合、銀行と各購買処理時に連携はしないということです。ディーラと銀行でのトレード処理は、MT4ターミナルでのトレーダーのクリックよりも少ない頻度で実行されます。通常、ディーラと銀行感での関係における最小の額は、US$ 50000を超えず、レバレッジ1:100の注文価格は0.5ロットになります。そのため、もしトレーダーが常に少額で行う際、ディーラーと取引を行うということになります。この場合、トレーダーの利益のソースは、ディーラーのお金です。

ディーラーは、金融マーケットの参加者と同様です。ディーラーは、トレーダーの動きを監視し分析しなければなりません。もちろん、ディーラーは不規則に繰り返される投資にはもしトレーダーの損失や特定の機関での結果につながる場合、目を背けることができます。しかし、どのディーラーももしディーラーの損失につながるのであれば、それが続くことを取り止めます。この場合、そのディーラーはどうに反応する必要があります。さもなければ、金融マーケットの経済領域にてディーラーは何も獲得できません。

金融マーケットの現代のルーティンは、ディーラーの気まぐれや、悪意ではありません。ディーラーと銀行の関係は契約されているのです。そして、ディーラーは公平な手段によって利益を得ようとしています(ディーラ側の不正はこの記事は議論されません。)ディーラーは、銀行と毎秒トレードすることを嬉しく思いますが、そのような可能性はありません。

あるトレーダーに実行された少額トレードの条件下で、ディーラはなんらかの手段を講じる必要があります。通知が送られるか、トレーダ0にあまりそれは良くないと告げられます。ディーラーはこのトレーダーの自動トレーディングを停止させるか、再価格設定の額を上げることもできます。

  • 多額の注文

実際のトレーディんとテストやデモアカウントでのトレーディングを区別するもう一つの制限があります。ロット価格の最大値です。銀行やブックマーカーのオフィル、金融機関であろうとも、どの取引所も多額の資金でトレードすることはできません。

もし注文が、US$10 000から20 000ほどであれば、取引所はUS$1 000 000.を購買します(100ほどのレバッレッジがありることに注意してください。)これは、本当に多額ですが、ディーラーはそのような多額の量をどう処理するかを学び、成功しています。

いくつかの困難は、もし注文価格がUS$50 000や、US$100 000に達した場合、中小金融機関において発生します。この場合、1000万、500万USドルの額は、銀行間マーケットで目立ちます。この額は、一回での動作において購買する上でそこまで簡単ではありません。

もしその注文がUS$ 300 000から500 000を超えると問題が発生します。この場合、取引所は、トレーダーを個別に対応します。5000万ドルは、どの金融機関にとっても多額のお金です。

この場合、取引所の手数料は問題外で、トレーダーがこの手数料を理解し受け入れていることをベースにトレーディングが実行されます。(マーケットの強い動きの中で、実際、ディーラーがかなりの費用で注文をオープンする上でどのような自由があるでしょうか?)

このため、何百万単位でのエキスパートのトレーディングのスカルピングは実際の生活とは全く関係ありません。

この推論は、プログラマが初期の10000ドルを稼げ、苦手な金融機関を見つけることを推奨します。プログラマは、「すべてが管理下にある」と考えます。

ディーラーは、教育水準を満たした普通の人々で、彼らなりにビジネスを進めていることを忘れてはいけません。ディーラにとって利益のない同じ技術は、アナリストが効果的になり、熟練しておらず必要なソフトウェアを持たないディーラーによって発見されない場所で発見されます。しかし、多くの場合、ディーラーは以前の「聖杯者」であり、トレーディングに熟練し、金融市場でトレーディングの旨味を味わっていますので、幾何学的累進が何か知り、攻撃的再投資や少額多額の注文も知っています。一般的にすべてのトレーダーは、ディーラーの資格はトレーダーのものよりも高く、ディーラーのポジションはよく推察されているという肯定から始める必要があります。

ご自身で判断してください:20000以上の注文を行うエキスパートはどのような結果になるでしょうか?



図7. Graal_1 (Grail 1)エキスパートのテストレポート


プログラマの脳は、これらすべてのティックやバー、ポイント、金融機関の間で考察を重ねます。詳細に進むべきか、「唯一の質問」に進むべきかを決定します。そして、「テスト結果は実際のトレーディングとは合致しない」という理解に満足します。また、適した技術は、未決注文に基づいて構築されるのだと判断します。さらに、「うまくいかなかったのでしょう!」と結論付けます。

2. 二つ目の"聖杯"

2.1 ストラテジー

エキスパートを未決注文に基づいて構築するという考えは、EURGBPとEURCHFのクロス率を学び思いつきました。



図8. 価格の逸脱を持つクロス率の歴史

ヨーロッパセッションがすでに終わり、アジアセッションが始まらないほどに、いくつかのシンボルチャートは標準の価格から全く異なる予想されない価格にてバーを含んでいます。制限型の未決注文を配置することで十分で、かなりの確率でそれらはオープンされます。未決注文がメインの価格帯の変化に適して反応するため、正中線にドラッグされ、MA(移動平均)戦から特定の距離で維持される必要があります。プログラマは、エキスパートをアイディアを実現するために記述します。

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_2.mq4 (Grail 2).
// Used as an example in the article My First "Grail".
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int TakeProfit=5;                            // TakeProfit orders
extern int StopLoss= 29;                            // StopLoss orders
extern int Distan   = 2;                            // Distance from the МА line
extern int Cls      = 2;                            // Close at ** points of profit
extern int period_MA=16;                            // MA period 
//extern int Time_1   = 0;                          // Starting time 
//extern int Time_2   = 0;                          // Finishing time
extern int Prots    = 0;                            // Percentage of free assets
 
//--------------------------------------------------------------------------------------------
int
   Nom_bl,                                          // BuyLimit order number
   Nom_sl,                                          // SellLimit
   total,                                           // Count of lots
   bl = 0,                                          // 1 = BuyLimit order availability
   sl = 0,                                          // 1 = SellLimit order availability
   b  = 0,                                          // 1 = Buy order availability
   s  = 0;                                          // 1 = Sell order availability
//--------------------------------------------------------------------------------------------
double 
   OP,                                              // OpenPrice (absolute points)
   SL,                                              // StopLoss orders (relative points)
   TP,                                              // TakeProfit orders (relative points)
   dist,                                            // Distance from МА (relative points)
   Level,                                           // Min.allowed distance of a pending order
   OP_bl,                                           // OpenPrice BuyLimit (absolute points)
   OP_sl,                                           // OpenPrice SellLimit(absolute points)
   cls,                                             // Close at ** profit (absolute points)
   MA,                                              // MA value (rate)
   spred,                                           // Spread (absolute points)
   Lot;                                             // Count of lots
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()
   {   
   Level=MarketInfo(Symbol(),MODE_STOPLEVEL);       // Check what the server shows us
   Level=(Level+1)*Point;                           // ?:)
   SL=StopLoss*Point;                               // StopLoss orders (relative points)
   TP=TakeProfit*Point;                             // TakeProfit orders (relative points)
   dist=Distan*Point;                               // Distance from the MA line(relative points)
   cls=Cls*Point;                                   // Close at ** profit (absolute points)
   spred=Ask-Bid;                                   // Spread (absolute points)
   return;
   } 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
   {   
//============================================================================================
   total=OrdersTotal();                             // Count of lots
   bl=0;                                            // Zeroize at the start of the pass
   sl=0;                                            // Zeroize at the start of the pass
   b=0;                                             // Zeroize at the start of the pass
   s=0;                                             // Zeroize at the start of the pass
//--------------------------------------------------------------------------------------------
   for (int i=total; i>=0; i--)                     // For all orders
      {                                             
      if (OrderSelect(i,SELECT_BY_POS)==true &&     // Select an order
         OrderSymbol()==Symbol())
         {
      
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_BUY)                   // Buy order
            {
            b =1;                                   // The order found
            Close_B(OrderTicket(),OrderLots());     // Close the order (the function decides
                                                    // whether it is necessary)
            }
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_SELL)                   // Sell order
            {
            s =1;                                   // The order found
            Close_S(OrderTicket(),OrderLots());     // Close the order (if necessary)
            }
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_BUYLIMIT)              // BuyLimit order
            {
            OP_bl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice BuyLimit(absolute points)
            Nom_bl=OrderTicket();
            bl=1;                                   // The order found
            }
//--------------------------------------------------------------------------------------------
         if (OrderType()==OP_SELLLIMIT)             // SellLimit order
            {
            OP_sl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice SellLimit(absolute points)
            Nom_sl=OrderTicket();
            sl=1;                                   // The order found
            }
//--------------------------------------------------------------------------------------------
         }
      }   
//--------------------------------------------------------------------------------------------
   MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// The MA current value
   Modify_order();                                  // Activate modification
   Open_order() ;                                   // Activate opening
//============================================================================================
   return;
   } 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_B(int Nomber, double lots)               // Close Buy orders
   {
//============================================================================================
   if (NormalizeDouble(Bid-OrderOpenPrice(),Digits)>=cls)// If the preset profit is reached
      {
      OrderClose( Nomber, lots, Bid, 1, Yellow);    // Close
      b = 0;                                        // No Buy order anymore
      }
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_S(int Nomber, double lots)               // Close Sell orders
   {
//============================================================================================
   if (NormalizeDouble(OrderOpenPrice()-Ask,Digits)>=cls)// If the preset order is reached
      {
      OrderClose( Nomber, lots, Ask, 1, Yellow);    // Close
      s = 0;                                        // No Sell order anymore
      }
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Modify_order()                                 // Modification of orders
   {
//============================================================================================
   if (bl==1)                                       // If there is BuyLimit
      {
      OP=MA-dist;                                   // it must be located here
      if (MathAbs(OP_bl-OP)>0.5*Point)              // if it is not located here
         {
         OrderModify(Nom_bl,OP,OP-SL,OP+TP,0,DeepSkyBlue);// The order modification 
         }
      }
//--------------------------------------------------------------------------------------------
   if (sl==1)                                       // If there is SeelLimit
      {
      OP=MA+spred+dist;                             // It must be located here
      if (MathAbs(OP_sl-OP)>0.5*Point)              // If it is not located here
         {
         OrderModify( Nom_sl, OP, OP+SL, OP-TP, 0, Pink);// The order modification 
         }
      }
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Open_order()                                   // An opening function
   {
//   int Tek_Time=TimeHour(CurTime());              // To test by the time
//   if (Tek_Time>Time_2 && Tek_Time>
//============================================================================================
   if (b==0 && bl==0)                               // No Buy orders, open bl
      {
      OP=MA-dist;                                   // bl order open rate      
      if(OP>Ask-Level) OP=Ask-Level;                // OP precision according to the tolerance
      OP=NormalizeDouble(OP,Digits);                // Normalizing (MA gives the 5th digit) 
      OrderSend(Symbol(),OP_BUYLIMIT, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Open
      bl=1;                                         // Now there is a Buy order b1
      }      
//--------------------------------------------------------------------------------------------
   if (s==0 && sl==0)                               // No Sell orders, open sl
      {
      OP=MA+spred+dist;                             // sl order open rate    
      if(OP<Bid+Level) OP=Bid+Level;                // OP precision according to the tolerance
      OP=NormalizeDouble(OP,Digits);                // Normalizing (MA gives the 5th digit) 
      OrderSend(Symbol(),OP_SELLLIMIT,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// Open
      sl=1;                                         // Now there is a Sell order sl
      }
///============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()                                       // Calculation of lots
   {
//============================================================================================
   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum lot values
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const.min.lots
//============================================================================================
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*

StopLoss, TakeProfit, Distan (その注文がメインストリームに沿って維持する距離), Cls (注文にて取得されるポイントの最小値、その注文はポイントの値がこの値に達すればクローズされる必要がある), period_MA (MA期間; MAは、最近の履歴のレートの中間線)、Prots (自由資産のパーセント、注文価格)が調整可能な変数として選択されました。これらは、かなりその考えを実現する上で十分です。
  • 特別なstart()関数にて、その注文は分析され(その注文の分析メソッドはこちらで記載されています)、それらの扱い方に関する判断は同時になされます。もしそのターミナルにてオープンの注文があれば、一致する関数Close_*()はクローズの必要性が分析された地点で呼ばれ、その注文はクローズされます。
  • start()関数の終了時に、Modify_order()とOpen_order()関数はそれぞれの修正と、制限型の未決注文のためオープンされました。その他の注文はオープンされていません。
  • Modify_order()関数にて、その注文の位置は計算され、もし適切な位置になければ、そこに移動されます。
  • Open_order()関数にて、未決注文の位置する適切な場所も判断されます。この際に、サーバ制限が考慮され、もし注文がなければ、それが配置されます。
プログラムを記述する際に、プログラムの記述は完成されず、止められる必要があるということに気づきました。EURCHFでのエキスパートテストは、以下のようになりました(類似した結果がEURGBPにて取得できますが、この例を学んでいきます)


図9. MIG Investments会社 のトレーディング条件下のM1 EURUSDチャート 2005年3月から2006年7月までの履歴のGraal_2.mq4 (Grail 2)におけるテスト結果


2.2. 幾何学的累進

このエキスパートでは、以前のものと同様、累進的投資技術が使用されています。一定の注文価格において、バランスグラフは以下のようになります:


Рис. 10.
一定の注文価格での
MIG Investments Companyトレーディング条件下 2005年3月から2006年7月までの履歴におけるМ1 EURUSD チャートのGraal_2.mq4 (Grail 2)

元来、プログラマは夜のみお金を稼ぎたかったのですが、1日中うまくエキスパートが稼働するので驚きました。この美しさを見て、再び判断しました: "自分だけだ" そして、"もう一度お金稼ごうか?"と考え始めますしかし、何も起こらないのです。今回、プログラマは「spikes」を知る必要があります。

2.3. エラー

上記の例には、たくさんの欠陥やまちがったプログラミング手段があります。Modify_order()には、未決注文においての最少の距離は考慮されておらず、そのオープン注文はまちがってまとめられており、TakeProfitはClsの利益に奮闘するため個別に修正されず、エキスパートの分析部分は全体のコードにおいて消されています。

まちがった、さらに不注意なプログラミングはしばしば、識別できないエラーに繋がり、時折、もしそのコードがその他のエキスパートに統合されれば、エラーが複製されます。

2.4. 技術制限 (Spikes)

技術的・組織的にしろ、すべての制限は最終的に経済的な損失に変わります。誰の費用でこれらの損失がカバーされるかという疑問が生まれます。

モニターにてトレーダーによって見られている標準のろうそく足チャートは、特定の領域でのマーケット開発の平均した結果です。異なるディーラーでの短期間の履歴におけるレートの所作が分析されます。この際、すべてのチャートは類似はしていますが、お互いに異なります。いくつかのディーラーのチャートは、長い多方向的なろうそくをたくさん含み、その他のディーラーのチャートは「安穏無事」な様子を示しています。

ティックチャートはまた売り上げのオブジェクトです。超過し、不自然な価格ティックをフィルタリングするプログラムの動作結果です。そして、それらが ("不自然な" ティック) 現れます。これは、いくつかの個人的な理由のため、銀行の人がマーケット価格とはかなり異なる価格でいくらかを購買すると発生します。その処理プログラムは、この情報を取得し、もしそのような取引が一度だけ発生すれば、最終的なチャートには考慮しません。プログラムは、どの価格が「標準」で、何が違うのかを理解しがたいことがあります。この理由のため、(プログラムのアルゴリズムに応じて)異なる長さのろうそくはチャートにて現れます。これらはspikesです。異なる種類として表示されますが、金融市場での本当の状況を示しません

これらの「pin」や「spikes」を捉え、価格が最も利益を生む際の注文を捉えるエキスパートを作るのはそこまで難しくはありません。しかし、ディーラーと銀行間で結論づけられた契約下で、銀行はディーラーへのそのような取引費用を払わないことをしっかり理解する必要があります。これは、トレーダーの利益のソースは、再びディーラーのポケットになるということです。そして、そのディーラーはこれをもちろん望んでおらず、ディーラは標準のマーケット価格でトレード処理を行うためにトレーダーと戦います。

ディーラーのための機会を提供する手段として、ディーラーとトレーダー間の契約には、普通強い価格の動きの際に注文の保証や再価格設定の可能性や、未決注文やその他の事項を含んだディーラーの権利に関する条項が記載されています。ディーラーは、注文がスパイクにてオープンされれば、すでにオープンされた注文をキャンセルすることができます。

これが実際に起こったことです。その聖杯は再び訂正されました。今回、プログラマは受信者を無視せず、注文が強制的にクローズされた理由を説明するたびに注意深くディーラーに耳を傾けました。しかし、ディーラーはエキスパートを停止させた時、プログラマは耐え切れず、契約を破棄しました。

そして、繰り返される失敗は、1分間のタイムフレームが原因であると考えます。フォーラムの投稿を読み、その他のトレーダーとコミュニケーションをとり、プログラマはそれらの多くは同じシンボルでより大きいタイムフレームに励みます。"これで意味が通るはずだ"と考えます。だんだん、プログラマは、"Mozart and me"の結論に至り、M1チャート上ではなく、3番目のプログラムの会はを始めます。

3. 3番目の"聖杯"

3.1公式の戦略

EURUSD H1チャートを注意深く学び、分析のため異なるインジケーターを使用し、プログラマはとても魅力的な規則性を発見しました:もし短期間のMAがより大きい期間のMAに合致すると、マーケットはより短い期間のMAが動く方向に動きます。

図11. 異なる期間のMAの交差に基づく戦略のグラフィカル表現

プログラマは、この相互関係はすべてのタイムフレームで見られることに気づきますが、大きいもののみを扱い始めました。それは、抽出された知識をMQL4に変換するためにのみ残っており、エキスパートにどの方向、どの条件下で注文をオープンするかを知らせます。そして、エキスパートが準備できれば、そのパラメーターを最適化する必要があり、最も効果的なMAの長さをソートし、StopLossとTakeProfitを適切に配置します。

今回は、以下のエキスパートが生まれました:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_3.mq4 (Grail 3).
// Used as an example in the article My First "Grail".
// Sergey Kovalyov, Dnepropetrovsk (Ukraine),sk@mail.dnepr.net,ICQ 64015987, http://autograf.dp.ua/
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int    MA1 = 11;                                  // Period of the first MA
extern int    MA2 = 23;                                  // Period of the second MA
extern double TP =  50;                                  // TakeProfit orders
extern double SL =  15;                                  // StopLoss orders
extern double Prots= 0;                                  // Percentage of free assets
//--------------------------------------------------------------------------------------------
int
   ret,                                                  // Direction of intersection
   total;                                                // Count of open orders
//--------------------------------------------------------------------------------------------
double 
   Lot,                                                  // Count of lots
   Pred,                                                 // Preceding value of the 1st MA(red)
   Tek,                                                  // Current value of the 1st MA (red)
   Golub;                                                // Current value of the 2nd MA (blue)
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
//============================================================================================
   SL = SL*Point;                                        // StopLoss in points
   TP = TP*Point;                                        // TakeProfit in points
   return;
//============================================================================================
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()  
   {
//============================================================================================
   total=OrdersTotal();                                  // Total amount of orders
   if (total==2)return;                                  // Both orders are already open
//--------------------------------------------------------------------------------------------
   Tek  =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 1st MA
   Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Preceding value of the 2nd MA
   Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 2nd MA
//--------------------------------------------------------------------------------------------
   if (Peresechenie()==1) Open_Buy();                    // Movement bottom-up = open Buy
   if (Peresechenie()==2) Open_Sell();                   // Movement top-down  = open Sell
//============================================================================================
   return;
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie()                                       // Function determining intersection
   {
//============================================================================================
   if ((Pred<=Golub && Tek> Golub) ||
       (Pred< Golub && Tek>=Golub)  ) ret=1;             // Intersection bottom-up       
//--------------------------------------------------------------------------------------------
   if ((Pred>=Golub && Tek< Golub) ||
       (Pred> Golub && Tek<=Golub)  ) ret=2;             // Intersection top-down
//============================================================================================
   return(ret);                                          // Return the intersection direction
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Buy()                                           // Function opening Buy
   {
//============================================================================================
   if (total==1)                                         // If there is only one order...
      {                                                  // ... it means another can be opened
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==0)return;                         // If it is Buy, do not open
      }
   OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// open
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Sell()                                          // Function opening Sell
   {
//============================================================================================
   if (total==1)                                         // If there is only one order...
      {                                                  // ... it means another can be opened
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==1)return;                         // If it is Sell, do not open
      }
   OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Open
//============================================================================================
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()                                            // Calculation of lots
   {
//============================================================================================
   Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Calculate the amount of lots  
   double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT);   // Minimum lot values
   if (Lot == 0 ) Lot = Min_Lot;                         // For testing on const. min. lots
//============================================================================================
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*

このエキスパートは、以前のものと同様、かなりシンプルです。

変数を記述するブロックから始まります。start()関数では、注文の最大量は、より大きい、短い期間におけるMA値と同様、定義されています。MAが合致すると、一致する関数は呼ばれ、注文をオープンします:Open_*()MAが合致すると、Peresechenie()が使用され、ロットの値を計算します - Lots()関数

プログラマは、エキスパートをもう一度見直し、何も欠陥が見つからず、テストを開始します。変数の最適化をすると、結果はすばらしいものでした。

図12. 2005年3月から2005年7月の履歴のGraal_3.mq4 (Grail 3)におけるテスト結果
MetaQuotes Software Corp.条件下でH1 EURUSD チャートを使用しています。

5ヶ月で300万でした!すばらしい!しかし、このバランスグラフでは、以前の経験での苦い経験と似ている何かがあります。そして、プログラマは少し遅めることにしました。

3.2. 進歩

同じエキスパートが一定の注文値でテストされ、かなり受け入れられるバランスグラフを示しました。



図13.H1 EURUSD チャートの2005年3月から2005年7月の履歴のGraal_3.mq4 (Grail 3) ,
MetaQuotes Software Corp条件下でH1 EURUSD チャートを使用しています。一定のロット価格のデモサーバーで行っています。

5ヶ月間で6000ポイントでした-ナイフで切ることができます一月で1000ポイントです。しかし、実際のトレーディングでそのエキスパートを設定することを疑いました。結局、二度も失敗しているのですから...

それから、プログラマは注文のオープン・クローズの印付けのあるタイムフレームをより注意深く見ることにすると、驚くことにエキスパートは、MAの交差点で注文をオープンするだけでなあく、その他のポイントでも行っていました。

図14. 初期の戦略で予想されていなかった状況でGraal_3.mq4 (Grail 3) エキスパートによる注文のオープン

3.3. エラー

"これはおかしい!MetaEditorに何かまちがった部分があるはずだ!”と最初はそう考えました。しかし、コードを学んでいくと、プログラマはエラーを再び見つけました。それらについて学んでいきましょう。

3.3.1初期の戦略からの逸脱 - アルゴリズムのエラー

以下のシンプルな関数をみてください:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie()                                       // Function that detects the intersection
   {
//=================================================================================================
   if ((Pred<=Golub && Tek> Golub) ||
       (Pred< Golub && Tek>=Golub)  ) ret=1;             // Bottom-up intersection       
//-------------------------------------------------------------------------------------------------
   if ((Pred>=Golub && Tek< Golub) ||
       (Pred> Golub && Tek<=Golub)  ) ret=2;             // Top-down intersection
//=================================================================================================
   return(ret);                                          // Return the intersection direction
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

かなり明確に見えますが、何が見つけられるでしょうか?しかし、エラーがここでもあります。グローバル変数retが使用された時、その値は最後に計算されたもの、1か2に等しく保存されるのです。このため、現在の状況に関係なく、Peresechenie()関数は、最後に計算された値を返します。そのため、start()関数にて開くため、注文されます:

   if (Peresechenie()==1) Open_Buy();                    // Bottom-up movement = open Buy
   if (Peresechenie()==2) Open_Sell();                   // Top-down movement  = open Sell

Peresechenie() 関数の初期にてret変数を0にする上で十分です。アルゴリズムのエラーにとらわれ、それを訂正し、一つのバーのみでオープンするよう同じ時間のフラグメントを記述しました。エキスパートはこのようになります:

//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Graal_31.mq4 (Grail 31)
// Used as an example in the article My First "Grail"
// Sergey Kovalyov, Dnepropetrovsk, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/.
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
extern int    MA1 = 11;                                  // Period of the 1st MA
extern int    MA2 = 23;                                  // Period of the 2nd MA
extern double TP =  50;                                  // TakeProfit orders
extern double SL =  15;                                  // StopLoss orders
extern double Prots= 0;                                  // Percentage of free assets
//--------------------------------------------------------------------------------------------
int
   New_Bar,                                              // 0/1 The fact of new bar forming
   Time_0,                                               // The new bar beginning time
   ret,                                                  // Intersection direction
   total;                                                // Count of open orders
//--------------------------------------------------------------------------------------------
double 
   Lot,                                                  // Count of lots
   Pred,                                                 // Previous value of the 1st MA (red)
   Tek,                                                  // Current value of the 1st MA (red)
   Golub;                                                // Current value of the 2nd MA (blue)
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
//============================================================================================
   SL = SL*Point;                                        // SL in points
   TP = TP*Point;                                        // ТР in points
   return;
//============================================================================================
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()  
   {
//============================================================================================
   total=OrdersTotal();                                  // Total count of orders
   if (total==2)return;                                  // Both orders already opened
 
//----------------------------------------------------------------------------- New bar ------
   New_Bar=0;                                            // First zeroize
   if (Time_0 != Time[0])                                // If the bar beginning time changed
      {
      New_Bar= 1;                                        // Here we have a new bar
      Time_0 = Time[0];                                  // Remember the new bar beginning time
      } 
      
//--------------------------------------------------------------------------------------------
   Tek  =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 1st MA
   Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Previous value of the 2nd MA
   Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Current value of the 2nd MA
   
//--------------------------------------------------------------------------------------------
   if (Peresechenie()==1 && New_Bar==1) Open_Buy();      // Bottom-up movement = open Buy
   if (Peresechenie()==2 && New_Bar==1) Open_Sell();     // Top-down movement  = open Sell
//============================================================================================
   return;
   }  
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Peresechenie()
   {
   ret=0;                                                // That's the heart of the matter!:)
//============================================================================================
   if ((Pred<=Golub && Tek> Golub) ||
       (Pred< Golub && Tek>=Golub)  ) ret=1;             // Bottom-up intersection       
//--------------------------------------------------------------------------------------------
   if ((Pred>=Golub && Tek< Golub) ||
       (Pred> Golub && Tek<=Golub)  ) ret=2;             // Top-down intersection
//============================================================================================
   return(ret);                                          // Return the intersection direction
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Buy()  
   {
   if (total==1)
      {
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==0)return;                         // If it is buy, don't open
      }
   OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// Open
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Open_Sell() 
   {
   if (total==1)
      {
      OrderSelect(0, SELECT_BY_POS);                     // Select the order
      if (OrderType()==1)return;                         // If it is sell, don't open
      }
   OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Open
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots()
   {
   Lot = NormalizeDouble( AccountEquity()*Prots/100/1000, 1);// Calculate the amount of lots  
   if (Lot<0.1)Lot = 0.1;                                // For testing on const. min. lots
   return(Lot);
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
/*

一定のロット価格でのエキスパートのテストは、制限された成功と一致します:

図. 15. H1 EURUSDチャートの2005年3月から2005年7月までの履歴のGraal_31.mq4 (Grail 31)におけるテスト結果
MetaQuotes Software Corpのトレーディング条件下での一定のロット価格のデモサーバを使用しています。


プログラマはかなりがっかりしました。たくさんの作業が無駄になりました。プログラマは、「聖杯」の探求に時間を費やしました。数ヶ月後、Graal_3.mq4 (Grail 3)エキスパートに戻ることにしました。"エラーがあったが、良い結果だった。おそらく、これは当然のことだ。良い結果のみが維持されるならエキスパートは注文をオープンするだろう。そして、テストを再び開始しました。

プログラマが驚いたことは、コードに変化もなく、エキスパートがデポジットを失い始めたことです。

図16. H1 EURUSDチャートでの2005年3月から2006年7月までのGraal_3.mq4 (Grail 3) テスト結果
MetaQuotes Software Corpのトレーディング条件下での一定のロット値
のデモサーバーを使用しています。

3.4. 結果のすり合わせ

自分自身をダチョウのように感じました。履歴セグメントのエキスパートのために最適なパラメーターを調節することに困難はありませんでした。同じエキスパートは常に異なる履歴期間で異なる結果を出します。

質問は、可能であれば、そのような最適な入力を見つける方法の質問となります。価格の小さい市場変動はエキスパートの動作や効果に影響を与えません。一般的に、マーケットにていかなる変化にも耐えうる戦略に焦点を当てる必要があり、パラメータの最適化はベストな結果を取得するためにいくらか助ける必要があります。

エキスパートGraal_3.mq4 (Grail 3)の最適な設定のための検索は、何にも繋がりませんでした。外部変数の異なる値のエキスパートのテストは、損失を示すか、異なる履歴期間のための異なる設定に繋がります。このため、最適な設定を見つけることに失敗しました。なので、この戦略はすべての場合のための普遍的な設定を持つと結論づけました。

プログラマは、Graal_31.mq4 (Grail 31)エキスパートに戻り、望んだ結果の取得に悶えます。しかし、最適な設定は以下のようになります:




Fig. 17. 2005年3月から2006年7月までの履歴のGraal_31.mq4 (Grail 31)におけるテスト結果、 EURUSD Chartの
MetaQuotes Software Corpのトレーディング条件下、デモサーバー一定のロット価格

にて実行。


プログラマが見たものは、全く「聖杯」に類似していませんでした。チャートの真ん中で水面低下したため、そのエキスパートを実際のアカウントのために使用することができません。しかし、かなりすごいものではありませんが、以前よい結果を残すエキスパートです。

これは励みになるものです。

4. まとめ


幻滅は、その錯覚が陽気で、幸せなものなら、常につらいものです。しかし、人生は遅かれ早かれその場所に導きます。世界の配慮がそのプログラマから元気を奪いました:そのプログラマは、二つの取引所と関係を破棄し、稼いだお金をかなり失いました。プログラミングやForexでのトレーディングなど貴重な経験を得て、"Mozartだけ..."という結論をみちびだそうとしますが、そのような早急な結論を取り止めます。

代わりに、そのプログラマは空白の紙を取り、教訓をもとに結論を公式化しました。

  • 実際のトレーディングでの累進的投資は標準である。しかし、注文は高すぎる価格ではない。
  • 初期の戦略に固執しなければならない
    もし調節可能なパラメーターにおける重要な変化は、結果における変化につながれば、初期の戦略はレベルアップかダウンされます。新しい戦略はより効果的な可能性があります。この場合、しばらく中止される必要があり、そのような予想されない成功の理由がよく学ばれた後、呼び出される必要があります。しかし、最もな制限の中でパラメーターの変化を許容する最大の範囲でユーザビリティを調査するため初期のアイディアに戻る必要があります。
  • アルゴリズムエラーを詳しく監視してください。
    アルゴリズムエラーの存在は、かなり不自然な現象です。そのようなエラーを発見するためにはかなりの経験が必要です。同時に、それらはエキスパートの動作の最終結果にて見つけられる必要があります。オープンやマークから外れたオープンの提供は、アルゴリズムエラーの証拠になります。
  • ストラテジーテスターのエキスパートテスト結果を適切に解釈してください
    実際のアカウントでのエキスパートの動作やストラテジーのモデリングはお互いに異なります。その違いは、モデリングは実際のトレーディングで発生する再価格設定や、注文の実行の拒否を考慮しないという点です。これは、高い見返りが期待されるエキスパートには問題ではありませんが、低い見返りのものにとって、その結果は、テスト中に大きく異なってきます。多くの場合、エキスパートは低い見返りをもち、テスト時にはかなりの利益を出し、実際のトレーディングでは、損失という結果で終わります。
  • 攻撃的投資を控える
    いかなるトレーディング戦略は、損失処理を考慮しなければなりません。もしその注文価格が無限に高い場合、少しの損失も修復不可能な損益ミスに繋がり、デポジットすべてを失うことにもなります。監視されていない攻撃的な再投資の許可は、現実逃避であり、保証された破産を意味します。
  • 変動にて利益を得ようとしない
    スパイクは、標準で自然なマーケットのレートを反映しません。もしトレーダーがそのようなスパイクで稼ぐなら、利益のソースはディーラのお金になります。この事実は、ディーラーにより発見されます:取引処理のキャンセルや、エキスパートの停止、アカウントのブロックに繋がります。
  • 異なる履歴期間でのクロスチェックテスト
    すべてのエキスパートは、異なるタイムフレームにて異なる結果を示します。それぞれの履歴インターバルにおいて、最適な設定が見つけられ、結果は最も良いものになります。テストに注意深くなり、現実逃避をせず、取得した結果をできるだけたくさんの履歴インターバルにてクロスチェックしてください。

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

添付されたファイル |
Grail_1.mq4 (5.99 KB)
Grail_2.mq4 (11.58 KB)
Grail_3.mq4 (6.38 KB)
Grail_31.mq4 (5.9 KB)
自分の DLL をデバッグするためのクラッシュログの利用方法 自分の DLL をデバッグするためのクラッシュログの利用方法
ユーザーから受け取った全クラッシュログ中25~30% はカスタム dll からインポートされた関数が実行されるときにおこるエラーが原因のようです。
いくつかのインジケーターにおけるマルチNullバー再計算 いくつかのインジケーターにおけるマルチNullバー再計算
この記事は、Nullバーが変化した際に MetaTrader 4クライアントターミナルのインジケーター値の再計算に関する問題に焦点を当てています。複数の再計算前に保存されたプログラムコードを保存させるいくつかの追加プログラムをインジケーターに追加する方法について述べています。
MetaTrader 4 クライアントターミナルの秘密 MetaTrader 4 クライアントターミナルの秘密
楽になる21の方法:MetaTrader 4 クライアントターミナルの機潜在的機能フルスクリーン、ホットキー、高速検索バー、ウィンドウ最小化、お気に入り、トラフィック削減、ニュース無効化、シンボル設定、銘柄リスト、検証用テンプレートと個別チャート、プロフィール、クロスヘア、電子ルーラー、バー単位のチャートページめくり、チャート内アカウント履歴、未決注文タイプ、ストップロスおよびテイクプロフィットの修正、削除の取り消し、チャート表示。
トレーダーツール、上級者向けのテクニカル分析のためのMQL4 トレーダーツール、上級者向けのテクニカル分析のためのMQL4
まず、トレーディングは確率の計算です。進展のエンジンとなる無為に関することわざは、それらのインジケーターやトレーディングシステムが開発された理由を明らかにします。トレーディングの多くの新人は「すでにできあがった」トレーディング理論を学習します。しかし、より多くの発見されていない市場の秘密があり、価格の動きの分析に使用されているツールは基本的に明らかにされていないテクニカルインジケーターや統計パッケージとして存在しています。マーケットの動向の理論への貢献において、Bill Williamsに感謝します。おそらくその漕ぎ手に頼るのは早すぎますが。