トップ  >  自作してみる >  プログラミング未経験者向け  >  F3.ログ出力について
スポンサーリンク
検索

↑の検索エンジンが表示されない人は、
↓の古い検索エンジンを使用して下さい。
カスタム検索
MQL4リファレンスツリー
F3.ログ出力について



ソースコードを書いてプログラムが一通り出来上がった後は設計通りに動作するか必ずチェックする必要があります
(実際のIT企業では外注プログラマーが動作チェックもテストもせずに納品するという信じられない事が日常茶飯事ですが・・・)。
メタエディターのデバッグツールを使う方法もありますが、起動が遅かったりしてイライラします。
チェックしたい部分の情報だけをログ出力して確認した方が早い事が多いです
(しばらくデバッグツールを使っていませんでしたが、つい先日使ってみたら処理が軽くて起動も早くなっていました)。


Print関数でログ出力

MQLで最も簡単なログ出力方法はPrint関数を使う事です。


Print関数の使用例:
    Print( "ログ出力テスト" );


結果:
print例

ログはターミナルのエキスパートタグをクリックすると確認する事が出来ます。



関数の呼び出し方法

上の例では当たり前のようにPrint関数を使用したので、関数の呼び出し方法について説明します。
まず、Print関数というのはMQL4で用意されているログ出力を行う関数です。

関数というのは基本的に呼び出して使用します。
その関数の呼び出す為には、呼び出したい関数名の後に括弧()で括る必要があります。
今回はPrintという関数を呼び出すので、Printの後に()をつけます。
print例


Print関数は引数の値を渡す必要がある為、引数に文字列の値を設定します。
引数というは関数に渡す値で、関数のInput情報みたいなものです。
引数を渡す必要があるか否かはリファレンスで関数を調べる必要があります。
Print関数のリファレンスを見ると、一つ以上の引数を渡す必要がある事が分かります
(Print関数の引数は複雑なので理解出来ないかもしれないので、今はリファレンスは斜め読み程度で引数が必要かどうかだけチェックして下さい。)。
print例

今回は"ログ出力テスト"という文字列を引数に渡しています。
文字列はダブルクォーテーション(")で括る必要があります。
プログラムのソースコードでは基本的に日本語は使えません、日本語が使えるのはコメント文字列型の値だけです。

処理の最後には処理の終わりを示すセミコロン(;)をつけます。
print例




処理というのは最初の 1.プログラミングについてで説明したフローチャートの処理です。
print例




チャートの安値をログ出力する

チャート上の現在の安値のログ出力をします。
例:
    Print( Low[0] );
結果:
    108.505


まずLowという配列について説明します。
これはMT4で事前に定義されている動的配列の変数です。
前回、動的配列は動的配列領域を確保しないと説明しましたが、
MT4で事前に定義されている動的配列についてはMT4が自動で動的配列領域を確保して、値も自動で設定します。
これら定義済み変数は基本的に読み取り専用で、ユーザーが勝手に値を設定する事は出来ません。


次にLow配列の要素についてですが、
これは時系列配列の要素と同様で、インデックス値が0の場合は最新のデータで、インデックス値が大きくなる程古いデータになります。

print例

例:
    Print( Low[0] );
    Print( Low[1] );
    Print( Low[2] );
結果:
    108.505
    108.411
    108.357


チャートの日付時間をログ出力する

チャート上の現在の日付時間のログ出力をします。
例:
    Print( Time[0] );
結果:
    2019.11.20 08:00:00


Timeという配列は、Lowと同様にMT4で事前に定義されている動的配列の変数です。
なお#property strictを使用していない場合は、日時時間では無く1970年からのカウント秒数が表示されます。




文字列を結合してログ出力する

単純に変数の値だけをログ出力しても、何の値か分からないです。
今はサンプルで一つだけしかログ出力していないので分かりますが、
これが色んな箇所から色んなログが出力されていたら理解不能になります。

まずは文字列変数を宣言します。
例:
    string temp_str;


この文字列変数に、チャートインデックスと時間と安値をセットします。

例:
    string temp_str;
    temp_str = "インデックス=0" + ",時間=" + (string)Time[0] + ",安値=" + (string)Low[0];
    Print( temp_str );
結果:
    インデックス=0,時間=2019.11.20 08:00:00,安値=108.505


これで何をログ出力しているのか理解し易くなりました。


型変換(キャスト)

上記の例で妙なコードが現れました。
    (string)Time[0]


Time[0]の前に(string)が付けられています。
これは型変換(キャスト)と呼ばれます。

プログラミング経験の無い人には意味不明な行為にしか見えません。
前の例で、string型のtemp_strにTime[0]を値を代入しようとしています、
Timeというのはdatetime型の変数なので、それをstring型のtemp_str変数に代入する事は出来ません。

前回紹介した変数宣言についてに記載してある通り、int型とdouble型はデータの扱い方が異なり互換性がありません。
同様にdatetime型とstring型もデータの扱い方が異なり互換性が無いので、そのまま計算させる事が出来ません。

日本のお店で買物する時に、日本円が足りなかったからといって、日本円と中国人民元で支払っても普通は拒否されますよね?
いくらあなたが「今1元≒15円だから、日本円相当に換算すると支払金額は足りている!ふざけるな!店長を呼べ!ムカついたからタダにしろ!お詫びとして煙草を1カートンよこせ!土下座しろ!」と言っても、 お店の人は「日本円で支払って下さい。恐喝するなら警察呼びますよ?録音していますからそれ以上フザけた発言をしたら告訴しますよ?告訴出来るわけ無いと高を括ってませんか?警察を呼んで告訴に必要な個人情報を教えてもらえば少額訴訟でお手軽に慰謝料請求出来るんですよ? そんな事も知らないからこんな暴君ぶりを発揮しているんですよね?ちなみに告訴とは別に、さっきの暴君ぶりの様子はYouTubeへアップロードしますねw」 としか言いませんよね?
それと一緒です。
中にはそういう暴君ぶりを発揮させるサイコパスは実在しますが、そういうサイコパスは全人口の4%(私の実体験から基づく個人的な統計データでは15%だと思いますが)と言われています。。

string型の変数に値を代入出来るのはstring型だけのデータなので、
他の型の値はstring型に型変換しなければなりません。

初心者の人は、この変数のデータ型について理解していない人が多く、
型違いによる計算で予期せぬ不具合を発生させる事が多いです(型指定を必要としないプログラミング言語しか知らない人も要注意)。
ここは重要な内容なので「なんか良く分からないし、大した事じゃないだろうからいいや~」程度で読み流してしまうと、不具合だらけでまともに動作しないプログラムを納品してくる外注プログラマーと同じになってしまいます。



フォーマットに従ったログ出力(printf関数)

文字列を結合してログ出力する方法では、出力する内容が多くなってくるとダブルクォーテーション(")の使用が多くなり、ダブルクォーテーションの閉じ漏れ等が発生してエラーを出し易くなります。
またソースコードも見難くなります。

PrintFormat関数をフォーマットに従った文字列を出力する事で、ソースコードが見易くなります。
PrintFormat関数はprintfと書いて使用する事も出来ます。
c言語慣れしている人はprintfを使う人が多いと思います。

例:
    printf( "インデックス=%d, 時間=%s, 安値=%f" , 0 , (string)Time[0] , Low[0] );
結果:
    インデックス=0, 時間=2019.11.20 08:00:00, 安値=108.5050000


printf関数の説明の為に、Low[0]はわざとstringキャストをしませんでした。

文字列を結合してログ出力する方法と違って、 ダブルクォーテーション(")で括った文字列が一つしか無いので、ソースコードがスマートになったと思います。

printf関数のリファレンスを見ても、書いてある内容が多過ぎて初心者の人は理解し難いと思いますので、簡単に説明します。

まずは1つ目の引数について
printf例

ここにフォーマットに従った文字列を書きます、この文字列がログ出力されます。

printf例

文字列の中に%dとか見慣れないものがありますが、ここには変数等の値が表示されます。

%dはint型の整数。
%sはstring型の文字列。
%fはdouble型の実数。

が表示されます。
基本的にこの3つをよく使用します。

printf例

2つ目以降の引数には、↑で説明した%d等に表示する値を指定します。

printf例

この値は順番に適用されます。
渡す値の型と渡す先の型が一致しない場合は表示される値がおかしくなります。
引数の数が一致しない場合はコンパイルエラーになります。
Low[0]はstringキャストしていないのでdouble型です、
なのでLow[0]の渡す先の型は%fになっています。



変換関数を用いた型変換

キャストと呼ばれる型変換は、強制型変換とも呼ばれます。
自動的に変換先の型に合わせて型変換してくれます。
しかし、自動で行われてしまうが為に意図しない値になってしまう場合があります。
その場合は、変換関数を用いて任意の値になるように型変換する必要があります。

上のprintfの例ではドル円の4時間足の現在安値を表示させているので、価格の表示は小数点第3位までで十分です。
フォーマット指定で小数点第3位までの実数表示にする事は可能ですが、
ドル円とクロス円以外の通貨ペアでは小数点第5位まで使われているので、小数点第3位固定で表示するのは都合が悪いです。

なので安値の値を変換関数のDoubleToString関数を使って、現在の通貨ペアの価格精度に合わせた桁数の文字列に変換させます。
現在の通貨ペアの価格精度の桁数はDigitsで取得出来ます。

例:
    printf( "インデックス=%d, 時間=%s, 安値=%s" , 0 , (string)Time[0] , DoubleToString(Low[0] , Digits) );
結果:
    インデックス=0, 時間=2019.11.20 08:00:00, 安値=108.505


結果を見ると、安値の価格がドル円の価格精度に合わせられているのが分かります。
ちなみにDoubleToString関数によってdouble型からstring型に変換されているので、
フォーマット指定は%fから%sに変える必要があります。

forループを使った繰り返し

printfを用いてスマートなログ出力が出来る事が分かったので、直近3本のチャートの安値をログ出力してみましょう。
一度書いたコードをコピー&ペーストして、インデックスの値を変更しても出来ますが、そんな手間隙かかる機械的な作業は行いません。
コンピュータはこういう機械的な繰り返し処理が得意なので、forループを使って処理を繰り返しましょう。
ループ処理にはforループ以外にもありますが、基本的にはforループが主に使用されます。


例:
    for ( int icount = 0 ; icount < 3 ; icount++ )
    {
        printf( "インデックス=%d, 時間=%s, 安値=%s" 
                 , icount , (string)Time[icount] , DoubleToString(Low[icount] , Digits) );
    }
結果:
    インデックス=0, 時間=2019.11.20 08:00:00, 安値=108.505
    インデックス=1, 時間=2019.11.20 04:00:00, 安値=108.411
    インデックス=2, 時間=2019.11.20 00:00:00, 安値=108.357


print例

forループだけ書き方が特殊なので注意して下さい。
for文の括弧の中には3つの式を書く必要があります。

for例

◆1つ目の式はループ処理の最初に一度だけ行われます。
ここではループカウンターの初期値設定を行います。


◆2つ目の式はループ処理の終了条件を判定します。
これはループ処理を行う前に毎回判定されます。
もし、一番最初にここの判定結果がfalseだった場合、一度も処理されずにforループが終了します。


◆3つ目の式はループ処理の最後に毎回行われます。
icount++はインクリメントと呼ばれる算術演算子で、icount = icount + 1と同じ意味を持ちます。


for例

1つ目の初期値設定の式の終わりと、
2つ目の終了条件判定の式の終わりに必ずセミコロン(;)をつける必要があります。
以前、処理の終わりにセミコロンを必ず付けるルールと説明しましたが、forループの3つ目の式の後にはセミコロンは付けません
forループの書き方だけ特殊なので注意して下さい。


for例

forループ文の後に中括弧{}で囲んだ部分が繰り返し処理されます。

for例

フローチャートで描くとこんな感じになります。

forループ文の処理部分をフローチャートで表現すると
for例

こんな感じになります。
forループ文の3つの式がどのタイミングで処理されて、ループ処理を抜けるタイミングがヴィジュアルで理解できると思います。

もし理解出来ない場合、ソースコードを色々と変更してみて、動作の変化を自身の目で見てみて下さい。
自身でソースコードを触ってみて変化を確認するのが一番理解できます。


スポンサーリンク


Copyright ©2015 MT4でEA自作しちゃお~ All Rights Reserved.


Top

inserted by FC2 system