English Русский 中文 Español Deutsch Português
大きなプログラムでの注文に関する考察

大きなプログラムでの注文に関する考察

MetaTrader 4 | 27 4月 2016, 08:35
1 551 0
Сергей Ковалев
Сергей Ковалев


取引戦略が、例えば一つの買い注文と一つの売り注文など少数の注文を前提にしている場合、このような取引戦略を実装しているエキスパートアドバイザは注文を検証することなく、独自のイデオロギーに基づいて取引決定を行い、ターミナル上に一方向の注文が一つ以上存在することはできません。

このようなアプローチは、基本的に許容できるものでありますが、これは小さなプログラムにのみ適していて、普遍性を求めることはできません。一つの通貨シンボルにつき、二つまたはそれ以上の同一の注文がある場合、このようなエキスパートアドバイザは、どのように振る舞うべきなのでしょうか?取引戦略はこういった状況を想定しておらず、またそういう状況は起こりえないと反論することもできます。それは正しいですが、この概念の欠陥と限界を示すものでもあります。

トレーダーが指値注文を含む、複数の注文を扱うのに十分な経験を得た瞬間から、指値注文は成立する場合があるので、持っている注文を精査する必要が出てきます。また、周知のように、ターミナルではエキスパートアドバイザが動作しているということを忘れて、トレーダーはいつでも『手動で』注文を出すこともできます。同様に、一つのアカウントで複数のトレーダーが同時に取引をすることもあり得ます。そして、より一般的な場合では、取引戦略自体が多数の注文の使用を想定することが可能です。

大きなプログラムではどのように注文の考察をすべきか考えてみましょう。


1. 環境の特性と一般論

私たちのプログラムが動作する環境の特性について簡単に記述してみましょう。

1. まず、私達はどんな注文がいくつあるのかを知りたいものです。(つまり、プログラムによってデータが必要とされると想定します)そして、ただ単に3つの売り注文と4つの買い注文があるというだけでは、十分ではありません。多くの場合、知的取引システムは、注文の特性(ストップロスやテイクプロフィットの位置)や、指値注文の場合には注文自体の特性(OpenPrice)を制御するアルゴリズムを含んでいます。また、私達は各注文がいくらで、どれくらいの有効期間で、どんなプログラムで作成されているかを知る必要があります。

2. ティックタイムリーに検証されるなら、どんな情報も意味を持ちます。どんなエキスパートアドバイザも、常にターミナルに入ってくる相場価格で動作します。注文の状態は任意の価格変化で変わることがあり、つまり各ティックで『再検証』する必要があることは明らかです。

3. エキスパートアドバイザが設定されているウィンドウで通貨シンボルを一般的特徴に移すことができます。

これらの簡単な事実で、私達は注文計算を含むプログラム構築の一般的原則を明確にすることができます。

第二に、注文計算の課題の他に、取引システムは、例えば注文の数を分析しつつ、取引決定を行うなど他の課題もこなさなければいけません。状況が分かっている場合にのみ、状況分析は行うことができます。これはつまり、注文計算を行うプログラムのコードが、他のコードよりも前に実行されなければならないということです。計算コードは別個の関数として作成するのがベストです。ターミナルに反映される注文を参照するのが主なので、その関数はTerminal()と名付けましょう。

第二に、Terminal()関数によって蓄積されたデータは、他の機能に利用可能でなければなりません。したがって、注文についての有益な情報を持つ変数はグローバルレベル(GlobalVariableグローバル変数と混同しないように)で宣言しなければなりません。

第三に、私達は一連の情報を扱うので、計算は注文配列をベースに計算をするのが理に適ってします。


2. プログラムの構造

前述の話から、注文計算を含むプログラムの一般的構造を設計することができます。

// My_expert.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
#include ...
#include <Peremen.mq4>          // 変数のエキスパートアドバイザの詳細
#include <Terminal.mq4>         // Terminal関数の接続
#include <Sobytiya.mq4>         //Sobytiya関数の接続
#include ...
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
// 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()  
   {
   ...                                       // init()関数のコード
   return;
   } 
//=================================================================
int start() 
   {
   Terminal();                   // この関数は一連の関数の中で
                                 // 一番初めにきます
   ...                           // start()関数のその次のコード
   Sobytiya();                   // イベント処理の関数
   ...                           // start()関数のその次のコード
   return;                                                                 
   }
//=================================================================
int deinit() 
   {   
   ...                                    // deinit()関数のコード
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

変数を記述するPeremen.mq4ファイルは、注文に関する情報を持つ配列の記述を含まなければなりません。

//  Peremen.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//=================================================================
int
...
//=================================================================
double
...
Mas_Ord_Tek[31][8], Mas_Ord_Old[31][8], 
// 現在と以前の注文の配列
// 第一のインデックス=この配列内の注文の順序番号
// [][0]は定義されていません
// [][1] 発注した注文のレート(レートの絶対値)
// [][2] StopLoss注文(レートの絶対値)
// [][3] TakeProfit注文(レートの絶対値)
// [][4] 注文番号        
// [][5] 注文のロット数(レート絶対値)
// [][6] 注文タイプ 1=B、2=S、3=BL、4=SL、5=BS、6=SS
// [][7] 注文のマジックナンバー
...
//=================================================================
string 
...
//=================================================================
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

小さなプログラムのグローバル変数を定義する時、これらは通常一番初めに来る関数の前に書かれます。中規模や大規模のプログラムでは、全てのグローバル変数を一つのファイルに集め、それを#includeの指示を使用しエキスパートアドバイザに添付することに意味はあります。コードの操作性の観点から見ると、方法の違いは意味がありませんが、使用の利便性の観点で見るとファイルの添付は望ましいです。この例では、Peremen.mq4ファイルは、まさにこの方法でエキスパートアドバイザに添付されています。


3. 配列

Peremen.mq4ファイルには、グローバル変数として二つの配列が定義されています。

Mas_Ord_Tek[31][8] - 現在の注文の配列

Mas_Ord_Old[31][8] - 以前の注文の配列

どうして我々には一つではなく、二つの配列が必要になったのでしょうか?それは、イベントの観測を可能にする為です。どんなものがイベントと言えるのかは、もう少し後でお話しするとして、今はイベント自体はその元の(初めの)状態と、現在の(最新の)の状態との比較をベースにして識別されるということが言えます。状態について何かしらの情報がない場合、イベントの識別は不可能です。このような場合は、ティックの前と後の状態についての情報を持つ注文の配列がこの役割を担います。

どうして二次元配列を使うのか?なぜなら、我々は複数の注文を同時に計算し、それらの一つ一つからいくつかの特性に関する情報を保存するからです。最初の指標は、配列内の注文番号で、二つ目の指標は指定したカテゴリーの注文特性です。この例では、最初の指標はターミナル内に注文が30以下であれば利用可能です。あなたは自分の好みで、ターミナルで同時に存在する計算を考えながら、この数字を50や100といったように変えることができます。勿論、これはあなたの取引システムがこのような注文数を扱う場合にのみ、行う意味があります。通常は1~2注文、稀な場合で4注文です。30というのは、私の見解では多すぎると思います。

なぜ配列の指標の括弧内に31や8があり、30や7ではないのか?これは、MQL4の配列がゼロで指標のカウントを開始する点にあります。通常の要素の為のセルのゼロ化は、いつも正しいわけではありません。私が思うには、配列の順序番号に注文の順序番号を対応させるのが理に適っていると思います。例えば、3番目の注文は指標の3の列にあるべきです。実際には、番号順は一番最初の列が指標0の為4つ目の列になります。

配列の内部を可視化し表を見てみましょう。全部で異なる性質のBuy、Sell、BuyStopの3つの注文があると仮定します。


注文に関する情報は、番号のついた配列の[1][1]から[7][30]までのセルに配置されています。また、[0][0]の指標を持つセルには、配列内にある注文総数を配置します。この場合は3です。今後の計算で、この数字は現在の状態の分析を行うループ編成の為に必要になります。

このように、私達は7つの特性をマークした30の注文についての情報を保存することができます。

この場合、あなたの取引戦略が複数の金融銘柄での同時取引を前提としている場合、複数の配列を開き、金融銘柄に応じて配置することができます。この方法は十分許容できるものではありますが、便利ではありません。この計算の構成時、注文についての情報を持つ配列名の保存の為にもう一つの配列を追加する必要があります。

より便利な解決方法としては、全ての注文を計算する大きな配列(一つの以前のものと一つの新しいもの)を一つ使用することです。この選択は、今後のコード内のこの配列を処理する時に、通貨シンボルの注文配列名を探す必要がなく、配列のインデックスの一つで正式な数値変数のループ内で検索を整理するだけで十分です。

全ての注文についての情報を持つ配列は、このように構成されます。


各通貨シンボルごとの注文に関する情報は、上記の例のように、一つの指標面に保存されます。この場合、このような面が複数あるということが違う点です(図では3、黄色、ピンク色、水色のもの)。これらの総数は、我々が作業を行うことを想定する通貨ペアの数にもう一つゼロを追加したものと等しくなります。この指標面(灰色)では、[0][0][0]の指標を持つセルには、注文総数の値が保存されます。

例えば、25の通貨シンボルの配列サイズは、最初の指標は26と等しくなります。この場合、配列が書かれるPeremen.mq4ファイルはこのようになります。

//  Peremen.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//============================================================================
int
...
//============================================================================
double
...
Mas_Ord_Tek[26][31][8], Mas_Ord_Old[26][31][8], // 現在と以前の注文の配列
                                 // 第一の指標=通貨シンボルの順序番号
                                 // 第二の指標=注文の順序番号・・
                                 // .. 通貨シンボルの面
                                 // [][][0]定義されていません
                                 // [][][1]発注した注文のレート(レートの絶対値)
                                 // [][][2] StopLoss注文(レートの絶対値)
                                 // [][][3] TakeProfit注文(レートの絶対値)
                                 // [][][4]注文番号        
                                 // [][][5] 注文のロット数(レート絶対値)
                                 // [][][6]注文タイプ 1=B、2=S、3=BL、4=SL、5=BS、6=SS
                                 // [][][7]注文のマジックナンバー
//=================================================================
string 
      Instrument[26];          // 通貨シンボル名の配列
...
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//
//
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Predopred()
   {
//===============================================予定 =
   Instrument[1] = "EURUSD";
   Instrument[2] = "GBPUSD";
   ...
   Instrument[25]= "AUDCAD";
//==================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

このファイルの始めのブロックの下の部分には、Instrument[26]配列が開かれています。

大きなプログラムでは、通常、多くの変数、プログラム実行中に変化しない値があります。この場合、これらにはInstrument[]配列の要素が関わっています。プログラミングを快適にするために、このような変数を一つの関数に集めることは意味があり、同様に#includeを使ってプログラムに添付する別個のファイルとしてこれを作成することができます。

この例では、Peremen.mq4ファイルに含まれているPredopred()関数のInstrument[]配列要素の事前定義を見ることができます。この関数は実行するために一度だけ起動させるだけで十分なので、これをinit():の特別な関数でプログラムに含める意味があります。

int init()  
   {
   Predopred();            // いくつかの変数の事前定義
   return;
   }

したがって、この場合には、Instrument[]配列の指標値に含まれているいくつかの整数は通貨シンボルに応じてつけられています。


4. 注文計算関数

通貨シンボルごとの注文計算の為のTerminal()関数が何からできているかを見てみましょう。この関数もTerminal.mq4の同じ名前を持つ別個のファイルとして編成され、#includeの指示を使ってエキスパートアドバイザに取り付けられます。

// Terminal.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Terminal()
   {
//============================================== 事前定義 ==
   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);
// 以前の履歴を保存します
   int Kol=0;                         // 注文カウンターのゼロ化
   ArrayInitialize(Mas_Ord_Tek,0);    // 配列のゼロ化
//===============================================注文の分析 ==
   for (int i=0; i<OrdersTotal(); i++)// ターミナルの全ての注文について
     {
      if((OrderSelect(i, SELECT_BY_POS)==true) && 
          (OrderSymbol()==Symbol()))
                                //次の、そして私たちの通貨ペアがある場合。
       {                                                                     
        Kol++;                  // 注文総数を計算します
//-------------------------- 新しい注文配列の形成 --
        Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(),
                                              Digits); 
// 注文の始まりレート
        Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss(),
                                              Digits); 
// SLレート 
        Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(),
                                              Digits); 
// ТРレート 
        Mas_Ord_Tek[Kol][4] = OrderTicket();     // 注文番号
        Mas_Ord_Tek[Kol][5] = OrderLots();       // ロット数
        Mas_Ord_Tek[Kol][6] = OrderType();       // 注文タイプ
        Mas_Ord_Tek[Kol][7] = OrderMagicNumber();// マジックナンバー 
//------------------------------------------------------------------
       }
     }
   Mas_Ord_Tek[0][0] = Kol; // ゼロのセルに保存します
//==================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

まず最初に、システムがTerminal()関数の制御を引き渡した瞬間から、注文の以前の状態を保存する必要があります。これはMas_Ord_Tek[][]配列に含まれていますが、以前のティックの注文の状態を羽根井している為、現時点では現実的ではありません。始めの時点では現在の状態はわかりません。

行では

   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);
// 以前の履歴を保存します

既知の最新の注文の状態はMas_Ord_Old[][]配列へ渡されます。

関数では、新しい注文数と現在の注文数を反映するKolローカル変数が使われます。MQL4は指標化されたインデックスを使用することができない為、この変数を使用する必要性が出ました。コードから分かるように、これは指標値として使用されます。この変数をゼロ化し、現在の状態の全配列と現在の状態に目を向けてみましょう。

この為に、ターミナルにループを作成し、全ての有している注文に注目して、その特徴を明らかにしましょう。

   for (int i=0; i<OrdersTotal(); i++)
// ターミナルの全ての注文について

OrdersTotal()は注文数を明らかにし、ターミナル内の注文番号の計算は0から始まることに注意してください。したがって、ループラインでは記号『<』が使われ、ループの内部変数の変更は0から始まります(i=0)。

次のコードでは、エキスパートアドバイザが取り付けられている通貨シンボルに属した注文が、強調されています。注文の様々な特性を判別する関数を使って、取得した情報はMas_Ord_Tek[][]配列の対応する要素に格納されます。

//------------------------- 新しい注文配列の形成 --
       Mas_Ord_Tek[Kol][1] = NormalizeDouble(OrderOpenPrice(),
                                             Digits); 
// 注文の開始レート
       Mas_Ord_Tek[Kol][2] = NormalizeDouble(OrderStopLoss(),
                                             Digits); 
// SLレート
       Mas_Ord_Tek[Kol][3] = NormalizeDouble(OrderTakeProfit(),
                                             Digits); 
// ТРレート
       Mas_Ord_Tek[Kol][4] = OrderTicket(); // 注文番号
       Mas_Ord_Tek[Kol][5] = OrderLots();   // ロット数
       Mas_Ord_Tek[Kol][6] = OrderType();   // 注文タイプ
       Mas_Ord_Tek[Kol][7] = OrderMagicNumber();// マジックナンバー 
//-----------------------------------------------------------------

充填されるカウンターはループの終わりに自分の値を配列のゼロ要素へ引き渡します。

   Mas_Ord_Tek[0][0] = Kol;    // ゼロのセルに保存します

腹痛の通貨シンボルでの同時取引の場合、Tеrminal()関数はこのようにすることができます。

// Terminal.mq4
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Terminal()
   {
//============================================== 事前定義 =
   ArrayCopy(Mas_Ord_Old, Mas_Ord_Tek);
// 以前の履歴を保存します
   ArrayInitialize(Mas_Ord_Tek,0); 
// 現在の注文の配列のゼロ化
//=============================================== 注文の分析 =
   for (int i=0; i<OrdersTotal(); i++)// ターミナルの全ての注文について
      {
      if(OrderSelect(i, SELECT_BY_POS)==true)
// もしまだ活きている注文がある場合
         {
//-------------------- 通貨シンボルのインデックスの定義 -
         string Symb=OrderSymbol();
//現在の注文の通貨を明らかにしましょう
         for (int ind=1; ind<=25; ind++)
// 通貨シンボルでの検索
            {
            if (Symb==Instrument[ind])
// インデックスが定義され、検索が終了しました
               break;                                   
// indによりループから出ます
            }
//---------------------- 注文の新しい配列の形成 ----
         Mas_Ord_Tek[0][0][0]++;
// 注文総数を計算します
         Mas_Ord_Tek[ind][0][0]++;
// 通貨ペアでの注文数を計算します
         int k=Mas_Ord_Tek[ind][0][0]; // 正式な変数
         
         Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                                  Digits); 
// 発注した注文のレート
         Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(),
                                                  Digits); 
// SLレート
         Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(),
                                                  Digits); 
// ТРレート
         Mas_Ord_Tek[ind][k][4] = OrderTicket(); // 注文番号
         Mas_Ord_Tek[ind][k][5] = OrderLots();   // ロットの数
         Mas_Ord_Tek[ind][k][6] = OrderType();   // 注文タイプ
         Mas_Ord_Tek[ind][k][7] = OrderMagicNumber();
// マジックナンバー 
         
//-----------------------------------------------------------------
         }
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

一つの通貨ペアの為にあるアルゴリズムと、複数の通貨シンボルの為の注文計算のアルゴリズムの違いは、通貨シンボルのインデックスの定義の為の小さなブロックです。

//----------------- 通貨シンボルのインデックスの定義 ----
         string Symb=OrderSymbol();
//現在の注文の通貨を明らかにしましょう
         for (int ind=1; ind<=25; ind++)
// 通貨シンボルでの検索
            {
            if (Symb==Instrument[ind])
// インデックスが定義され、検索が終了しました
               break;                 // indによりループから出ます
            }

次のTerminal()関数の次の行では、発見した通貨シンボルのインデックス値は、indが通貨シンボルに応じた注文についての情報を持つ配列面のインデックスを明確にします。

提示されたTerminal()関数の実装例では、いくつかの変数の演算時に正規化が使用されます。

Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),Digits); 
// 発注した注文のレート
Mas_Ord_Tek[ind][k][2] = NormalizeDouble(OrderStopLoss(),Digits); 
// SLレート
Mas_Ord_Tek[ind][k][3] = NormalizeDouble(OrderTakeProfit(),Digits); 
// ТРレート

これらの演算の必要性は、将来の計算に比較演算子で正規化された変数値を使用する為にあります。この時、有効桁数はDigitsの事前定義変数をベースに定義されます。

いくつかの取引システムは、注文の他の特性や特徴を考慮に入れることができます。上記の例では、大きいプログラムでの注文計算構築の一般的原理が反映されています。例えば、ここでは決済した注文や削除した注文の計算は検証されておらず、注文のいくつかの特性は考慮に入れていません(指値注文の有効期限など)。あなたにこのようなものが必要になる場合には、あなたは簡単に追加の情報を格納する為に配列の構成を変更することができます。例えば、指値注文の有効期限についての情報を保存する為に、最後のインデックスの項目の数を増やすことができます。

5. イベントの処理

さて、新しいティックは発生し、Tеrminal()関数が動作しました。制御は、Terminal()関数の後にあるオペレーターに移されます。先だって、start()特別関数のどの部分にイベント処理の特定のカスタム関数がなければならないかを言うことはできません。これは、取引システムの基礎となる考え方によって異なります。単純なケースでは、少なくともいくつかのイベントの処理はすぐに行うことができます。

イベント処理の例に移る前に、特殊なイベントが存在し、その場合には直感的に予想されるイベントの秩序は保たれないということに触れておく必要があります。

第一に、取引日の最後に強制的に全ての注文を決済し、次の日の始めに同じような注文を出すが、レートは現在のものとは数十ポイント違うものになるというディーラー(例えば、独自の会計処理をもつ銀行など)がいくつか存在します。ポイントのこれらの一部で、注文にスワップがつきます。スワップ自体はターミナルではいつもゼロと表示されています。経済の観点からはディーラーは何も違反はしていません。この状況において、私達に重要なことは、再び出される注文には、以前のものと何ら関係のない新しい番号が割り当てられることです。

第二に、別個に取られた注文の部分的決済は二つの段階で行われます(全てのディーラーで)。第一段階では注文は完全に決済され、二つ目の段階で価格を小さくした新しい注文が出されますが、その注文には新しい番号が振られます。この時、最初の注文番号は新しい注文のコメント欄に記載されます。

第三に、同様の特例は、これらの注文が異なる価格を持っている場合に、他方の計算で一つの注文が決済された場合に起こります。実際には、この場合には、注文のうちの一つの部分的決済が繰り返されます。

注文の識別の唯一の方法は、変更されない、また繰り返されないパラメータを分析することです。MQL4の提供するこれらの方法の中からは、唯一MagicNumberというパラメータを見つけることができました。しかし、この場合でもプログラマーは、状況の完全な制御の作成を計算にいれることはできません。問題は、MagicNumberはプログラミングによって変更できないということです。一方で明らかな利点もあり、このパラメータは偶々であったとしても注文がある間は変化しないと確信することができます。しかし一方で、プログラムで利用することができる調整可能なパラメータを持つことが望ましいです。現時点では、このような可能性はない為、もし何らかの注文(一つもしくは複数)が他のプログラムもしくは『手動で』、私たちの取引システム以外で出されている場合、このような注文に『私達のものか』そうでないかを示すマークを付けることはできません。

発注時に独自の機能の代替を務めることができるものがいくつかあります。しかし、このような基準は正確で汎用性のあるものとみなすことはできないかもしれません。というのは、同時に(同じ瞬間に)複数の注文が出されるという理論的可能性が常に存在するからです。例えば、二つの指値注文が異なる通貨シンボルにあり、激しい価格変動時に同時に発注されることがあります。

Sobytiya.mq4ファイルに含まれている、Sobytiya()関数の実装例を見てみましょう。簡単なイベント、注文の削除と決済を見てみましょう。

この目的の為に注文番号がいつも必要になるとは限らないと分かっているので、MagicNumberを分析しましょう。

// Sobytiya.mq4   
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Sobytiya()
   {
//==================================== 欠落している注文の検索 ====
   for (int oo=1;oo<=Mas_Ord_Old[0][0];oo++)     
// 以前の配列から注文番号を取ります
      {   
      int Sovpadenie=0;                          
// 始めに一致条件のマークをゼロ化します
      for (int i=1;i<=Mas_Ord_Tek[0][0];i++)     
// この注文を現在の配列で探しましょう 
         {
         if (Mas_Ord_Tek[i][7]==Mas_Ord_Old[oo][7]) 
// もし注文のMagicNumberが一致した場合、まだ生きていることを覚え
// 内部ループから出ます
            {
            Sovpadenie=1;                           
            break;                                
            }
         }      
      if (Sovpadenie==1) continue;  // 次の古い配列に移ります
      Alert("注文の決済",Mas_Ord_Old[oo][4]); 
// 画面にメッセージで知らせます
      PlaySound( "Close_order.wav" );               
// そして音楽で
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

お分かりのように、自分の管理下にイベントを書く基準を持っていると、イベントの観測はとても楽になります。ティックの後にくる注文を持つティックまでの注文を連続して比較するだけで十分です。これはイベントが起こったということを確認する事実となります。

次の例では他のイベントの検索―注文タイプの変更を見ていきましょう。ここでは同じ原理を利用していますが、他の基準に適用されます。状況の観測には、注文番号とそのタイプの分析を適用することが可能です。

// Sobytiya_2.mq4   
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int Sobytiya_2()
   {
//============================== タイプが変わった注文の検索 ====
   for(int oo=1;oo<=Mas_Ord_Old[0][0]; oo++)               
// 以前の配列を通ります
      {
      for (int i=1;i<=Mas_Ord_Tek[0][0];i++)              
// 現在の配列で注文を検索します 
         {
         if (Mas_Ord_Tek[i][4] == Mas_Ord_Old[oo][4] &&    
// もし以前の配列にこのような注文があったが、違うタイプである場合
             Mas_Ord_Tek[i][6] != Mas_Ord_Old[oo][6])      
            {                                                  // 指値は明らかになりました
            Alert("形質転換された注文",Mas_Ord_Tek[i][4]);
// 画面にメッセージで知らせます
            PlaySound("Transform.wav" );                       
// そして音楽で
            }
         }
      }
//=================================================================
   return();
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

プログラマによってエキスパートアドバイザに設置されたアイディアによって、イベントはプログラムの異なる場所で観測することができます。必要に応じて、全ての興味のあるイベントを一つのファイルに形成することができます。この時、各基準の為に別個に何度も配列の検索を実行しなくても良いように、コードを少し変更する必要があります。その後の分析の為に、部分的に決済された注文のコメントから、初期番号を抽出するアルゴリズムを作成することも簡単です。これには、OrderComment()関数を使うだけで十分です。

上記の注文の計算に関わる特徴に加えて、他にも注意深く観察することで私たちの現実への理解を深め、余分な作業やつまらないエラーから私達を守るのに役立つものがあります。取引日の最後に注文を決済するディーラーに戻りましょう。

スワップの値は、通常ポイントで割り切れず、その結果注文の始値のレートの重要な数字の数は1つ増えます。この特徴の計算する為には、精度の正規化を行い、Digitsよりも1つ多くする必要があります。

   Mas_Ord_Tek[ind][k][1] = NormalizeDouble(OrderOpenPrice(),
                                            Digits+1); 
// 発注した注文のレート

また、この状況では、注文の始値はその位置を大きく変える可能性があることに注目する必要があります。もしこの時、トレーダーが注文の始値の計算を使い取引決定を行ういくつかの取引システムを使用している場合、このようなシステムは、一日の終わりに水の泡になるでしょう。注意深く検証し、注文の始値のレートは何の意味も持たないと結論付けることができます!重要な要素は状況の発展傾向であり、もしこれが私達に反する場合、注文は決済するべきです。

取引決定に影響を与える基準の議論は、この記事では範疇を超えています。それにはあらゆる戦略にとって基本の要素となる、プログラムがそれに基づいて動作する正しい基準の選び方について言及する必要があります。

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

グラフィカルインタフェース III: シンプルなボタンと多機能ボタン(チャプター 1) グラフィカルインタフェース III: シンプルなボタンと多機能ボタン(チャプター 1)
ボタンについて考えましょう。ここでは、簡単なボタン、拡張機能を持ったボタン(アイコンボタンとスプリットボタン)、また相互接続されたボタン(ボタングループとラジオボタン)を作成するためのいくつかのクラスの例を説明していきます。そのうえ、それらの能力を拡大するためのコントロールのために既存クラスにいくつかの追加を導入します。
グラフィカルインタフェース  II:メインメニュー要素(チャプターー4) グラフィカルインタフェース II:メインメニュー要素(チャプターー4)
これは、グラフィカルインターフェイスに関するシリーズの第二部の最終章です。ここでは、メインメニューの作成を検討します。このコントロールの開発とユーザの行動に正確な反応するライブラリクラスのハンドラ設定が実証されます。また、メインメニューの項目にコンテキストメニューを取り付ける方法についても説明します。そのに加えて、現在非アクティブな要素のブロックも言及されます。
グラフィカルインタフェースIII:シンプルボタンと多機能ボタンのグループ(チャプター 2) グラフィカルインタフェースIII:シンプルボタンと多機能ボタンのグループ(チャプター 2)
シリーズの最初の章は、シンプルボタンと多機能ボタンについてでした。2番目の記事は、アプリケーション内でユーザーがセット(グループ)のうちオプションのいずれかを選択することができる際の要素の作成を可能にする相互接続されたボタンのグループに専念します。
グラフィカルインタフェース  II:ライブラリのイベントハンドラの設定(チャプター3) グラフィカルインタフェース II:ライブラリのイベントハンドラの設定(チャプター3)
以前の記事には、メインメニューの構成部分を作成するためのクラスの実装が含まれています。ここで、主要な基本クラスと作成されたコントロールのクラスでイベントハンドラを細かく見ることにします。また、マウスカーソルの位置に応じたチャートの状態の管理にも特別な注意が払われます。