English Русский 中文 Español Deutsch Português
preview
初心者からプロまでMQL5をマスターする(第2回):基本的なデータ型と変数の使用

初心者からプロまでMQL5をマスターする(第2回):基本的なデータ型と変数の使用

MetaTrader 5 | 10 6月 2024, 11:16
221 0
Oleh Fedorov
Oleh Fedorov

はじめに

前回の記事では、MQL5プログラマーが使用する主なプログラムについて見てきました(そしてMetaEditor IDEが初心者のニーズに適しているという結論に達した)。さらに、関数の概念をざっと見て、システムログにメッセージを表示する簡単なスクリプトを作成しました。これらのメッセージは、端末ウィンドウの一番下にある[エキスパート]タブで見ることができます。

関数とはアクションの記述であることを思い出してください。

使用したのは、あらかじめ定義されたOnStart関数とPrint関数だけです。OnStartに関しては、中身を詰め込みました。Printは私たちが必要とする情報を表示するもので、既成のフォームで使用され、私たちはそれにパラメータを渡すだけでした。プログラマーは、特定のタスクを解決するために必要な独自のカスタム関数を作成することができます。

各関数は、と呼ばれる、非常に初歩的なステップアクションで構成されています。このようなアクションは非常に単純で、2つの数値を比較したり、コードの一部を何度か繰り返したり、2つのテキストをくっつけたり、別の関数を呼び出したりします。数は多くありません。この記事では、そのいくつかの文について考えてみます。

一連の文はアルゴリズムを形成します。

アルゴリズムは、実行者(この場合はコンピュータ)に対して、特定の、よりグローバルなタスクの解決につながる特定のアクションを実行するよう、明確で理解しやすい指示で構成されます。アルゴリズムには膨大な種類があります。同じ問題でもさまざまな解き方があるからです。

特に取引に関してはです。取引の入力、取引の終了、対応するログの出力、およびその他のアクションは、さまざまな方法で実装することができます。あなた(あるいはあなたの顧客)がこの特定のケースで何を望んでいるのか、コンピュータに明確に説明する必要があります。

より複雑なアルゴリズムは、より単純なアルゴリズムから構成され、それぞれのアルゴリズムは、ある関数によって実装され、あるアクションを実行します。これらのアクションはデータに適用されます。このデータは、1秒間に数回届くAskとBidの価格や取引量です。その他のデータの例としては、直線や曲線を描ける画面上の点などがあります。また、取引が実行されたときに再生されるサウンドにすることもできます。データはテキストで、例えばある期間の相場のリストなどです。いろいろな例が考えられます。アイデアが明確であることを願っています。

さて、このデータはどこかに保存されなければなりません。

今日は、データがどのようにRAMに保存されるかについてお話しします。データは変数または定数としてメモリに保存できます。

その違いは明らかです。

  • 変数変化できます。つまり、プログラムはそのようなデータを書き換える権利を持っています。
  • 定数はプログラムの存続期間中一定(変更されない)のままであり、プログラマーがその値を上書きしようとすると、コンパイルエラーが返されます。

それ以外は、両者の意味は全く同じです。これは、プロセッサ命令ではなく、データを格納するRAMの特定の領域です。通常、これらのメモリ領域が何に使用されるかを理解するために、意味のある名前をつけます。

コンパイラはこれらの名前を削除しますが、ソースコード(テキストファイル)にアクセスできれば、その名前から変数の目的を常に理解することができます。もちろん、それらが正しく記述されていることが条件です。

定数には名前がない場合もあります。プログラマーは、処理すべき内容(例えば、Print関数に渡した文字列)を書くだけです。このような名前のない定数リテラルと呼ばれます。

この記事では、基本的なデータ型、変数や定数の記述方法、プログラマーがアルゴリズムを作成するために使用できる基本的な文について詳しく見ていきます。これによって、「Hello, World」だけでなく、もっと便利なプログラムを作ることができるようになります。


記事にあるすべての式をテストするための基本コード

前回の記事では、簡単なプログラムを作成しました。端末下部のパネルにある[エキスパート]タブにデータを表示するスクリプトです。こちらです。

//+------------------------------------------------------------------+
//|                                                   HelloWorld.mq5 |
//|                                       Oleg Fedorov (aka certain) |
//|                                   mailto:coder.fedorov@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Oleg Fedorov (aka certain)"
#property link      "mailto:coder.fedorov@gmail.com"
#property version   "1.00"
//#property script_show_inputs

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
  Print("Hello, MQL5 world!");
  }

//+------------------------------------------------------------------+

例1:最もシンプルなスクリプトの全文

今日はこのコードを使用して作業します。中括弧の中に例題の行を挿入することでコードを修正します(例題の説明で他の挿入場所が明示されている場合を除く)。


リテラル

データを出力する方法を見てみましょう。

文字列から始めます。

文字列リテラルは二重引用符(")で囲まれます。しかし、すべての記号をそのまま表示できるわけではありません。これらの中には、その言語で特別な意味を持つもの(引用符)もあれば、改行文字のようにまったく表示されないものもあります。

このような文字には特別な慣例があり、バックスラッシュを使用して記述します。

Print(
    "Symbol <\"> can't be placed"
    " without (\\).\n  And we can carrying over the string now."
  );

例2:バックスラッシュを使用して特殊文字を出力する

例2では、出力文字列を表す引用符が緑色で強調表示され、特殊文字は黄色で強調表示されています。\nは改行を表します。

文字列リテラルの出力例

図1:文字列リテラルの出力例

以下の特徴にもご注目ください。MQL5では、非常に長い文字列を(各部分を引用符で囲むことによって)任意の場所で分割することができます。これらの行を統合するために、他のアクションを追加する必要はありません。もしコンパイラが(例のように)2つの連続した文字列リテラルを見つけた場合、自動的にその文字列を1つの大きな文字列に結合し、その中に特殊文字がないかどうかを検索します。

特殊文字の完全な表と、文字定数のより詳細な説明は、公式ヘルプにあります。

次によく使用されるのは数値です。

整数には共通の形式があります。

Print(5);

例3:整数出力

小数の出力も非常に簡単です。整数部と小数部の区切り記号は小数点です。

Print(5.5);

例4:10進数出力

非常に大きな数値や非常に小さな数値には、浮動小数点記法(指数形式と呼ばれることもある)を使用することができます。

Print(5.5e3);
Print(5.5e-3);

例5:浮動小数点リテラルの使用

これらすべての数字形式を使ったスクリプトの結果を図2に示します。

Print関数を使用して数字を出力する

図2:Print関数で数値を出力した結果

最後の2行で、関数が渡されたデータをどのように変換したかにご注目ください。これは、データが数字として認識され、適切に処理されたことを示唆しています。

プログラマーは16進数を扱わなければならないことがあります。初心者がこのタイプを必要とすることはほとんどありませんが、16進数は例えば色を表現するのに便利な場合もあります。16進数は、数字(0~9)または文字(a~f)で構成されます。

プログラムにこれが16進数リテラルであることを理解させるには、数値の先頭に「0x」を追加します(ゼロと文字x)。

大文字と小文字は区別されません。

Print(0xAF35);

例6:16進数の使用

16進数出力

図3:16進数の出力結果

スクリプトの結果を図3に示します。この数値は(通常の整数に)変換されたもので、コンピュータは必要なものを正確に理解したことになります。

MQL5のプログラマーは日付を使用することが非常に多くなります。

日時を完全に表記するには、大文字のDで始め、アポストロフィ< ' >を付け、必要に応じてドットやスラッシュを使用して希望の日付を書き、スペースで時間を示し、分と秒をコロンで区切り、さらにアポストロフィを付けます。

  Print(D'24/12/23');
  Print(D'24.12');
  Print(D'24.12.2023 7:55:34');

例7:日時の使用

2行目の場合、日付が完全でないというコンパイラの警告が出ることにご注意ください。ただし、ファイルはコンパイルされ、3行とも正しく動作します。

不完全なリテラル警告

図4:不完全な日付リテラルに関すル渓谷(MetaEditor)

スクリプトの結果(日付の出力)

図5日付出力スクリプトの結果(端末)

なお、1行目をコンパイルする際にはその日の開始時刻を、2行目をコンパイルする際にはコンパイル時刻を代入しています。形式が適切に変換されたので、プログラムはそれを正しく理解したと結論づけることができます。

任意のリテラルに対して、指定されたデータ型に許容されるあらゆるアクションを実行できます。

例えば、数値を比較したり、算術演算をおこなったり、パラメータとして関数に渡すことができます。

文字列は足す(結合する)ことはできますが、引くことはできません。

次の例を見てみましょう。

Print( "This will be calculated: "+4+9 );
Print( "This will be calculated: "+(4+9) );

例8:式を書くときに括弧を使用する

文字列式での数値の使用に関するコンパイラの警告

図6:文字列式での数値の使用に関するコンパイラの警告

計算結果

図7:この関数は計算結果を出力する

括弧がない場合は、数字は単にテキストに「接続」されています。括弧を使用すると、すべてが正しく計算されました。これはかなりとらえどころのないエラーで、だからこそコンパイラはすぐに警告してくれるのです。数値を明示的に文字列に変換するための特別な関数がありますが、今は、括弧は重要だということだけは覚えておいてください。


defineプリプロセッサ指令を使った定数の定義

自分のコードで混乱したくないなら、またプログラムで使用するデータの目的を理解したいなら、すべての定数に意味のある名前を設定するよう常に心がけるべきです。この目的のために、#defineプリプロセッサ指令が一般的に使用されます。
#define name value

例9:define指令

プリプロセッサ言語は「言語の中の言語」のようなもので、この言語はコンパイルが始まる前の動作を記述するものです。

原則として、プリプロセッサはあるコード断片を他のコード断片に置き換えることを目的とします。例えば、最初のパスで#defineディレクティブを指定すると、コンパイラはコード全体を通してnamevalueに置き換え、その後に初めて構文チェックを開始します。

例えば、こう書くことができます。

  #define MY_SUPER_CONSTANT 354
  Print(MY_SUPER_CONSTANT);

例10:define指令

プログラムは名前ではなく値を出力する

図8:プログラムは定数名ではなく、定数の値を出力する

実行されると、プログラムには名前ではなく数字354が表示されます。

数字を表すリテラルにはセミコロンが付かないことにご注意ください。

プリプロセッサディレクティブを使用して定数を宣言する場合、セミコロンは必要ありません。

もしセミコロンを追加していたら、プリプロセッサはこの記号を数字とともにプリント括弧の中に挿入し、コンパイルエラーのメッセージが表示されたでしょう。

つまり、定数には名前を付けでは値ではなく名前を使用するということを覚えておいてください。

ちなみに、同じ定数がプログラム内の異なる場所で何度も使用される場合や、複数の定数が同じ値を持つ場合に、名前は非常に便利です。定数の値が変更された場合、複数の場所を検索して変更するよりも、通常はドキュメントの最初か、あるいは別のファイルなど、1つの場所で変更する方がはるかに簡単です。


変数の説明

覚えておいてほしいのは、作業の過程でメモリ上のデータが変更されることが予想される場合は、変数を使用するということです。

変数の記述も非常に簡単です。具体的に保存したいものを書き出すだけだす。

type variable_name;

例11:変数宣言テンプレート

このエントリは、コンパイラがデータ用に一定量のメモリを割り当てなければならないことを意味します。型とサイズについては後で詳しく説明します。

このデータは名前variable_nameでアクセスできるようになりました。


識別子の規則

変数識別子と呼ばれることが多い)は、作成する名前と同様に、次の条件を満たすべきです

  • 情報量が多い(sssよりもchartNumberの方が良い)
  • ラテンアルファベット、数字、アンダースコア(_)で構成される 

また、次の条件も満たす必要があります。

  • 数字で始まらない
  • 予約語と一致しない
  • 63文字以下

大文字と小文字は区別されます。例えば、myVariableとMyVariableは異なる名前です(もちろん、同じファイル内でこれらを両方使用しないことを強くお勧めします)。

プログラムテキストのどこかで大文字と小文字を間違えた場合、コンパイラは"Undeclared variable"エラーメッセージを生成します。これは簡単に修正できますが、すべての規則に従って両方の変数を記述しているのに、大文字か小文字かだけが異なる、似たような名前を使用すると、混乱しやすくなります。

それ以外は特に制限はありません。必要であれば、組み込み関数にちなんだ変数名をつけることもできますが、これもお勧めしません。


代入演算子

変数にデータを書き込むには、代入操作を使います。これは宣言時に行われることもあります。この場合は初期化とみなされます。

// Initialization (at creation)
int counter = 0;
// Normal assignment
counter = 10;

例12:簡単な代入

intという単語は、変数が整数型のデータしか格納できないことを示しています。

この例の記号「=」は代入演算子を意味します。この場合、counterというセルに整数が書き込まれます。

代入前にこのセルにあったデータはすべて失われます。

この変数内のデータは、プログラム中の任意の場所で名前を介して使用することができます。例えば、任意の関数のパラメータとして渡したり、式の中で使用したりすることができます(例は記事の後半で紹介します)。


代入操作:特定の機能

前節で説明したように、課題は非常にシンプルです。しかし、もしこの操作を式で使用するのであれば、より効果的に使用ために以下の注意事項が役立つでしょう。

  • 代入操作は最も優先度が低いので、右から左に実行されます。つまり、右側に式があり、左側にデータが書き込まれる変数があります。まず、この表現です。
a = b + c;

例13:代入の優先度は最も低い

上の式は、まずbとcを加算し、その結果を変数aに書き込みます。

  • 前述したように、変数の値を式の中で使用し、その結果を同じ変数に書き込むことができます。
a = a — c;

    例14:変数の前の値を式の中で使用することができる

    • MQL5では、(上の例のように)同じ変数が右と左に1度ずつ現れる式は、式の符号を演算の左側に移動させることで簡略化できます。
    a -= c;

    例15:代入の省略形

    このような短い使用法は、乗算、除算、シフトなど、あらゆる二項演算子(和や積のように2つの値を使用する)に有効です。ただし、この式の変数は簡単に分離できるはずです。

    例えば、a = a*(1+1/a)という式の場合、このトリックは展開しないと使用できませんが、a = a*(b+c)の場合は簡単で、a *= b+cとなります。

    • 整数を1増やしたり減らしたりする必要がある場合、代入を使用する必要はまったくありません。代わりにインクリメント演算とデクリメント演算を使用することができます。
    a++; // Increment. Increase a by 1
    b--; // Decrement. Decreases b by 1
    

    例16:インクリメントとデクリメント

    これらの演算は単項演算であり、演算に必要な変数は1つだけです。このような操作には、接頭辞と接尾辞という2つの表記法があります。

    接頭辞形式で使用すると、アクションが最初に実行され、その結果が式の中で使用されます。

    postfix形式で使用される場合、変数の古い値が最初に使用され、次に変数が1ずつ変化します。

    int a = 1;
    Print (++a); // 2, and a == 2
    Print (a++); // 2, but a == 3
    

      例17:インクリメントの接頭辞形と接尾辞形(デクリメントもまったく同じように使用される)

      • 「カスケード」を使えば、複数の代入演算子を連続して使用することができます。右から左への一連の動作は維持されます。
      int a=1, c=3;
      a = c = a+c; // first a+c (4), then c = 4, then a = c (i.e. a = 4)
      

      例18:「カスケード」代入


      基本データ型

      データ型は比較的多いです。

      中には単純(あるいは基本的)なものもあります。これらは文字列、数値、日付、色などの型です。その他は複雑であり、そのような型はMQL5のプログラム開発者によって作成されます。原則として、「複雑な」データ型は単純なデータ型を組み合わせたものであり、複数の変数を1つのブロックにまとめて利便性を高めたものです。

      この記事では、基本的な型のみを取り上げます。複雑なものについては後続の記事で説明します。

      整数型

      整数は、コンピュータが「考える」ための主要な手段です。

      コンピュータ上での整数演算はシンプルで高速です。しかし、操作の結果が特定の値の範囲を超えると、データの損失につながる可能性があります。

      2つ目の重要なポイント:整数には「符号あり」と「符号なし」があります。

      数値が「符号なし」の場合は、0から最大までの数値を使用できます。例えば、1バイトを占有する数値は、0から28-1=255まで増やすことができます。これは合計で256の値になります。

      このような変数に数値「256」や「-1」を書き込もうとすると、オーバーフローが発生します。この場合、結果は同じ範囲[0..255]に収まりますが、残りのデータは失われますこれが有効な場合もあるが、大半の場合、このような変換には他の方法を使った方が良いです。例えば、この記事で後述するように、剰余演算子を使用することができます。すべてのデータを損失することなく受け入れてくれるタイプの変数を使用するのがよいです。

      0から始まる(実際には自然数を表す)型の名前の前には、u(符号なし)という文字が付きます。

      「符号付き」数値は、同じ範囲の数値を半分に割って使用します。前半は負の数を、後半は正の数を格納します。したがって、[-128..127]の範囲では、同じ1バイト数字が正しいことになります。

      表1:整数データ型

      名前
      サイズ(バイト単位)
       最小値
      最大値
      char
      1(8ビット)
      -128
      127
      uchar
      1(8ビット)
      0
      255
      short
      2(16ビット)
      -32 768
      32 767
      ushort
      2(16ビット)
      0
      65 535
      int
      4(32ビット)
      -2 147 483 648
      2 147 483 647
      uint
      4(32ビット)
      0
      4 294 967 295
      long
      8(64ビット)
      -9 223 372 036 854 775 808
      9 223 372 036 854 775 807
      ulong
      8(64ビット)
       0  18 446 744 073 709 551 615

      実際には、最もよく使用される型はint型(この単語は素早く書けるし、この型のデータはかなり大きいため)とlong型(このサイズは大半のタスクに十分で、コンパイラはバイトコードを最適化して最新のコンピュータで最高のパフォーマンスを発揮できる)です。

      しかし、他の型も役に立ちます。

      ブール

      この型はboolキーワードで指定され、1バイトのメモリを占め、truefalseの2つの値しか取ることができません。

      どうしても必要であれば、どんな数字でも論理データとして使用することができます。例えば、数値が0に等しい場合はfalseであり、それ以外の場合はtrueです。しかし、このような目的で数字を使用する場合は、細心の注意を払う必要があります。

      実数(浮動小数点数)

      表2:Realデータ型

      名前
       サイズ(バイト単位) 正の最小値  最大値  
      float
      4(32ビット)
      1.175494351e-38
      3.402823466e+38
      double
      8(64ビット)
      2.2250738585072014e-308
      1.7976931348623158e+308

      現代はdouble型が主に使用されています。他の人のコードでfloat型を見かけてから久しいです。古いバージョンとの互換性のために使用されているのでしょう。ただ、非常に大規模なデータセットでは、メモリ容量を節約するのに有効です。

      実数は、価格、通貨の量、その他の有用な概念を表すことができます。

      整数よりもはるかに大きな値の範囲をカバーします。

      しかし、コンピュータがこのような型で作業するのはあまり便利ではありません。まず、実数を使った演算は整数を使った演算よりも若干遅いです。第二に、形式の特殊性により、計算結果はほとんどの場合、下1桁に誤差が生じるため、ある操作では1.0の代わりに1.00000001、別の操作では0.99999999が得られます。

      したがって、2つの実数を比較する必要がある場合は、通常、その差をとり、誤差よりも確実に大きい小さな値と比較する必要があります。その方が信頼できます。

      日時

      この型はdatetimeという単語で示され、メモリ内で8バイトを占有します。

      この型の各変数には、1970年1月1日から必要な日付までの経過数が格納されます。つまり、普通の整数です。

      最終可能日は3000年12月31日です。私たちが生きている間はこれで十分なので、「2000年問題」(覚えておいでしょうか)を恐れる必要はありません。

      特別な定義済み定数があります。

      • __DATE__:コンパイル日
      • __DATETIME__:コンパイル日時
      • __DATETIME__- __DATE__という式を使用することができます。これは、コンパイル時間のみを記述し、日付は記述しません。

      リテラルを書くときは、すべてを省略してD''(Dと2つのアポストロフィ)と書くことができます。この表記は__DATETIME__と同じですが、コードの可読性が悪化します。


      MQL5での色は、別の型colorによって決定されます。色を表現する場合、リテラルを使用することができます。

        color myColor1=C'100,200,30';
        color myColor2=C'0xFF,0x00,0x5A';
      

      例19:10進数または16進数を使用して色を表現する

      Webカラー用に定義された定数を使用することもできます。色定数名はclrで始まります(例:青はclrBlue)。定数の完全なリストは、MetaEditorでclrとタイプするか、公式ドキュメントを参照することで見ることができます。

      例12では、各色の説明が3つの断片から構成されていることがわかります。このような断片はそれぞれ、画面上のドットの赤、緑、青のの強さを表します(赤、緑、青=RGB)。それらが合わさることで、さまざまな色が生まれます。

      赤と緑を混ぜることで、黄色、茶色、オレンジのすべての色合いが得られます。

      赤と青はバイオレットピンクの色調を生み出します。

      緑と青は、ターコイズ、シアンなどの異なるバリエーションを生み出します。

      3つの色合いを等しい割合で混ぜ合わせると、グレーの色合いの範囲(すべての成分が「オフ」、つまり強度が0の黒から、すべての成分の強度が最大の255(0xFF)の白まで)ができます。

      比率が不均等、つまり各成分の強度が他と異なる場合、モニター上の他のすべての色合いが得られます。通常、緑は全体の色を明るくし、青は暗くします。もちろん一般的には、明るい成分ほど明るくなります(全体の色も明るくなる)。

      これらのルールはすべて表3に示されており、私は単にエディターで利用可能な色でセルに色をつけただけです。

      実際には、ほとんどの場合、各色の数値を知る必要はなく、特別なパレットから色を選択するか、あらかじめ定義された定数を渡すだけです。とにかく、すべてのものの仕組みを理解することは有益だと思います。

      colorデータはメモリ上で4バイトを占めますが、使用されるのはそのうちの3バイトだけです。これは歴史的に起こってきたことであり、この色記述モデルで動作できるすべてのプログラムにとって一般的な合意事項です。

      表3:カラー例

      0, 0, 0 156, 15, 15 106, 0, 86 0, 49, 110 0, 110, 41 56, 37, 9 56, 37, 9
      51, 51, 51 191, 3, 3 133, 2, 108 0, 67, 138 0, 137, 44 243, 195, 0 87, 64, 30
      102, 102, 102 226, 8, 0 160, 39, 134 0, 87, 174 55, 164, 44 255, 221, 0 117, 81, 26
      153, 153, 153 232, 87, 82 177, 79, 154 44, 114, 199 119, 183, 83 255, 235, 85 143, 107, 50
      204, 204, 204 240, 134, 130 193, 115, 176 97, 147, 207 177, 210, 143 255, 242, 153 179, 146, 93
      255, 255, 255 249, 204, 202 232, 183, 215 164, 192, 228 216, 232, 194 255, 246, 200 222, 188, 133

      必要であれば、色を普通の整数と同じように扱うことができます。

      例えば、このようにです。

        color a = C'255,0,0';
        color b = C'0,255,0';
        color d = a+b;
        Print(a," ",b," ",d);
      

      例20:算術式で色を使用する

      これは次のような結果をもたらします。

      算術式に色を使った結果

      図9:算術式に色を使った結果

      列挙体

      最後の基本型は列挙型です。

      問題の特殊性に応じて、変数が特定の値だけを取るべき場合があります。例えば、トレンドには下降、上昇、横ばいがあります。また、買い注文タイプには、Buy(成行価格で買う)、Buy Stop(価格がブレイクアウトのための一定レベルに達するまで保留)、Buy Limit(反発を期待して保留)のみが存在します。曜日はいつも同じです。原則は明確だと思います。

      そのような場合は、列挙を使用します。

      列挙の記述は3つのステップからなります。

      1. 最初のステップでは、リストそのものを作成し、何らかの名前をつけます。結果として得られる名前は、変数や関数の型名となります。この名前と定義済みの型との唯一の違いは、私たちが自分で考えたということです。
      2. 2番目のステップでは、このタイプの変数を作成します。
      3. そして最後に、3番目のステップでこの変数を使用することができます。
      例15は列挙の記述と使用法を示しています。説明のために、Upward、Downward、Asideの3つの値しか使用できない方向記述(DIRECTION)を取り上げてみました。

      //--- First step: creating a new list (new data type)
        enum ENUM_DIRECTION
         {
          Upward,
          Downward,
          Aside
         };
      
      //--- Second step: description (and, if necessary, initialization) of a variable of this type
        ENUM_DIRECTION next=Upward;
      
      //--- Third step: using the variable
        Print(next);
      

      例21:列挙の説明と使用法

      通常、列挙リストはファイルの最初、プリプロセッサディレクティブの直後に作成されます。この場合、アプリケーションのすべての関数でグローバルに利用できます。

      ある関数の中にローカルに記述することもできます。そうすると、この列挙は他の関数からは見えなくなります。ほとんどの場合、これはあまり意味をなしませんが、あり得ます。

      列挙要素名は、カンマで区切られた中括弧で指定します。

      型記述(列挙を含む)の閉じ中括弧のには、セミコロンが必要です。他のブロックではそうではないかもしれません。

      言語内で定義済みの列挙型は、大文字で書かれた名前を持っており、これらの名前は接頭辞ENUM_で始まります。列挙の名前は(制限の範囲内で)好きなように付けることができますが、同じ基準を守ることは良い習慣です。

      列挙の内部表現は符号付き整数で、メモリ内で4バイトを占有します。

      例21のコードを実行しようとすると、数字0が表示されます。つまり、MQL5に列挙要素の数値選択をさせると、ゼロから始まるということです。

      ただし、他の数値を指定することも可能で、その場合は明示的に設定する必要があります。

      //--- First step: creating a new list (new data type)
        enum DIRECTION
         {
          Upward = 1,
          Downward = -1,
          Aside = 0
         };
      

      例22:列挙値を明示的に設定する

      すべての値を指定する必要はありません。

      いくつかの値が指定され、いくつかの値が指定されていない場合、MQL5は要素の順序と最後に最も大きい数値に基づいて数値自体を選択します。つまり、例15でUpward = 1とし、他の初期化をすべて取り除けば、Downwardは2となり、Asideは3となります。ご自分で確認してください。


      式と簡単な演算子

      データを扱うときは、それを比較したり、数学的な演算を実行したりできることが重要です。異なるデータ型には異なるを使用することができます。

      比較演算子

      これらの演算子はすべてのデータ型に対して意味があります。

      比較結果論理的です。

      以下の比較演算子があります。

      • より大きい(>) 
      • 未満(<) 
      • 以上(>=
      • 以下( <=
      • 等しい(==
      • 等しくない(!=)

      これらの操作の優先度はすべて同じです。

      文字列を比較するとき、コンピュータはエンコーディングの文字の配列に従います。例えば、大文字のAは小文字のaの前に来るので、より小さくなります。よって

      "An apple" < "a pal" //true

      例23:文字列の比較 - 大文字は小文字より小さい

      同じ記号が何個か並んでいる場合、最初の不等号が比較対象として選択されます。

      "An apple" > "A pal" //true

      例24:最初の文字は同じ

      例24の表現は、エンコーディングのスペースがアルファベット文字の前にあり、最初の文字が同じなので正しいです。

      一方の行がすでに終わっていて、もう一方の行が続いている場合、始まりが同じであれば、終わった行の方が少ないとみなされます。次は例です。

      "An apple" < "An apple was found" //true

      例25:異なる行の長さ

      算術演算

      結果は、式で使用されているデータ型によって決まります。

      数値に対して算術演算をおこなうことができます。

      • 符号を(-3)の前に置く(「単項」マイナスとも呼ばれる)
      • 乗算(*)、除算(/)(整数の場合は切り捨て)、除算の余り(%)(整数のみ、5%2 == 1);
      • 加算(+)、減算(-)
      • インクリメント(++)、デクリメント(--)

      リストは優先度の高い順に記載されています。

      しかし、普通の式でインクリメントやデクリメントを他の算術演算子と一緒にしない方がよいです。結果が定義されない状況が発生する可能性があるためです。

      操作(+)は文字列に対しても定義されますが、ここでは結合(2つの短い文字列から1つの長い文字列を作成)を意味します。

      ビット演算

      結果整数です。

      整数の場合、次のようなビット演算もあります。

      • ビット単位否定(~)
      • 右シフト(>>)
      • 左シフト(<<)
      • ビット単位論理積(&)
      • ビット単位論理和(|)
      • 排他的論理和(^)

      もしこれら必要なら、あなたはもう間違いなく初心者ではありません。必要な情報は言語ドキュメントで見つけることができます。

      リストは優先度の高い順に記載されています。

      論理演算子

      結果は論理的です。

      • 論理否定(!)
      • 論理積:論理AND(&&)
      • 論理和:論理OR(||)

      リストは優先度の高い順に記載されています。

      他の操作もありますが、それは他の記事で説明します。また、他の記事では、上記のすべての演算子の使用例についてより詳しく説明します。とりあえず、自分が理解しているものを使用するか、言語のドキュメントを確認してください。特別難しいことはないはずです。


      型キャスティング

      算術式に複数のデータ型が含まれることがあります。例えば、Print関数を使えば常に文字列を数字と一緒に表示することができます。この記事では色も示しました。

      結果はどんな型になるのでしょうか。ここで、2つの選択肢から選ぶことができます。私たち自身が最終的な結果を決定するか、コンパイラを信頼するかです。

      もちろん、コンパイラは賢く、それを理解できますが、いつもというわけではありません。

      そこで、重要なデータを失わないように、コンパイル中に警告を受けないように、そして結果に自信を持てるように、コンパイラが何をするのか、そして「手動」で何ができるのかを見てみましょう。

      コンパイラは何をするのでしょう。

      まず、式が同じ型のデータを使用する場合、結果も同じ型になります。これは最も簡単なケースです。

      異なる型が関係する場合、コンパイラは結果を最も正確なものに展開しようとします。例えば、4バイトの整数(int)と日付(datetime)を足そうとすると、(範囲がより広いので)日付が返されます。

      整数リテラルはint型であり、浮動小数点リテラルは、小文字のfで終わらない限り、通常double型です。

      5 + 3.4f + 4.25 // The result is double, since 5 is first converted to float, and then 4.25 sets double precision

      例26:リテラル使用時の型キャスト

      ヘルプドキュメントには、型キャスティングの優先度スキームが記載されています。

      型キャストの優先度

      図10:型キャスティングの優先度

      符号付き型と符号なし型の相互変換はデータロスにつながる可能性があり、float型への変換は精度のロスにつながる可能性があることに注意すべきです。

      したがって、コンパイラがデータをどのように変換するかわからない場合は、何を何に変換するかを手動で指定することも考えられます。

      結果(または特定の値)を特定の型に変換する必要がある場合は、そうできます。

      • 結果を特定の型の変数に書き込みます。この方法は基本的に自動キャスティングの変形であるため、使用には注意が必要です。
      • 特殊なデータ変換関数を使用します。
      • 型キャスティングの短縮形を使用します。
      (int)a+b // converts a to an integer. b remains unchanged
      double (c+d) // absolutely similar to the previous one. In this case, the result of the summation is converted
      
      // and so on - you can use any suitable type
      
      

      例27:型キャスティングの短縮形

      括弧は最も優先度が高いので、操作の順序を変更できることをお忘れなく。よくわからない場合は、括弧を使用してください。


      結論

      基本的なデータ型、変数、式に関する理論の大部分をカバーしました。この記事と次の記事の内容を理解すれば、初心レベルから抜け出し、より高いレベルに進むことができるでしょう。変数(今回のテーマ)と関数(次回のテーマ)の仕組みを理解すれば、自信を持ってOOP(オブジェクト指向プログラミング)のような複雑なトピックに進むことができます。

      OOPは複雑な素材と考えられています。技術的な問題よりも、イデオロギー的な問題の方が大きいです。

      理解できなかった点がある方は、この記事を(1回以上)ゆっくり読み直し、コードに書かれていることをすべて確認しながら、1つずつ概念を確認していくことをお勧めします。

      すべてを理解し、次の記事の準備ができるまで待ちたくないという人には、使用する銘柄や残高に関する役立つ情報を表示するスクリプトをご自分で書くことで、待ち時間を明るくすることをお勧めします。これらの情報の多くは、AccountInfo関数ファミリーとSymbolInfo関数ファミリーから得ることができます。

      MetaEditorを使用してこれらのファミリーの各関数のフルネームを見つけ、ヘルプでその説明を調べてみてください。これらの説明とこの記事で取り上げた資料があれば、このスクリプトを作成するのにそれほど多くの労力は必要ないでしょう。

      追記このようなスクリプトの例は標準ライブラリにあります。もし自分でスクリプトを書きたくなければ、既成のスクリプトを分析してみましょう。もし自分で書けたら、標準ライブラリのものと比べてみてください。

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

      ニューラルネットワークが簡単に(第70回):閉形式方策改善演算子(CFPI) ニューラルネットワークが簡単に(第70回):閉形式方策改善演算子(CFPI)
      この記事では、閉形式の方策改善演算子を使用して、オフラインモードでエージェントの行動を最適化するアルゴリズムを紹介します。
      ニューラルネットワークが簡単に(第69回):密度に基づく行動方策の支持制約(SPOT) ニューラルネットワークが簡単に(第69回):密度に基づく行動方策の支持制約(SPOT)
      オフライン学習では、固定されたデータセットを使用するため、環境の多様性をカバーする範囲が制限されます。学習過程において、私たちのエージェントはこのデータセットを超える行動を生成することができます。環境からのフィードバックがなければ、そのような行動の評価が正しいとどうやって確信できるのでしょうか。訓練データセット内のエージェントの方策を維持することは、訓練の信頼性を確保するために重要な要素となります。これが、この記事でお話しする内容です。
      ニューラルネットワークが簡単に(第71回):目標条件付き予測符号化(GCPC) ニューラルネットワークが簡単に(第71回):目標条件付き予測符号化(GCPC)
      前回の記事では、Decision Transformer法と、そこから派生したいくつかのアルゴリズムについて説明しました。さまざまな目標設定手法で実験しました。実験では、さまざまな方法で目標を設定しましたが、それ以前に通過した軌跡に関するモデルの研究は、常に私たちの関心の外にありました。この記事では、このギャップを埋める手法を紹介したいと思います。
      Candlestick Trend Constraintモデルの構築(第2回):ネイティブ指標の結合 Candlestick Trend Constraintモデルの構築(第2回):ネイティブ指標の結合
      この記事では、トレンドから外れたシグナルを選別するために、MetaTrader 5指標を活用することに焦点を当てます。前回に引き続き、MQL5コードを使用してアイデアを最終的なプログラムに伝える方法を探っていきます。