
初心者からエキスパートへ:MQL5での共同デバッグ
コアコンテンツ
はじめに
通常、すべての著者は記事の最初から最後まで特定の問題に取り組むことを目指します。本日のタイトルは「デバッグ」ですが、このタイトルを軽視しないでください。ここではプロセスの基本にとどまらず、さらに深く掘り下げます。私は、長年にわたって複数の成功したプロジェクトで実際に採用してきたテクニックを紹介します。ソフトウェアプログラミングのあらゆる分野において、デバッグは欠かせないトピックです。しかし、多くの著者がコードを正しく動作させるために直面した苦労を共有することなく、洗練された最終製品の提示に重点を置いていることに気づきました。
ニューラルネットワークシステム、人工知能、その他関連するソフトウェア分野のいずれにおいても、デバッグは不可欠です。最も価値のあるスキルは、問題が発生した際にそれを解決する能力であり、このスキルは将来同様の課題に直面した際に不可欠な要素となると私は信じています。したがって、問題解決を通じて強力なスキルセットが構築され、徐々に専門家としての成長へとつながっていくのです。
共同デバッグ
この記事を書こうと決心したとき、私はあるプロジェクトに取り組んでいました。そのプロジェクトではコードをコンパイルしようとした際、いくつものエラーが発生していました。中にはデバッガーが50行にも及ぶエラーを表示し、それらすべてに対処しなければならないこともありました。試行錯誤を重ねる中で、バグに対処するためのルーチンを開発しました。このルーチンを使えば、わずか数分、場合によっては数秒で問題を解決し、プログラムをスムーズに実行させることが可能となったのです。
私の目標は、デバッグプロセスを加速させるテクニックについて知っていただくことにあります。私の経験から得た最も貴重な教訓の1つは、デバッグプロジェクトに積極的に取り組むことで、MQL5を迅速かつ効果的に習得できるということです。以前、バグのあるプログラムを保存しておいたので、それを一緒に確認しながら改良してみましょう。
根強い課題の1つとして、多くの人が無料で入手可能な長いMQL5の書籍を読み通すのに苦労するという現実があります。しかし、それによってこれらの書籍の価値が損なわれるわけではありません。これらの書籍には、MQL5プログラミングの基本から高度な概念に至るまで重要な知識が含まれています。最良の結果を得るには、進行中の作業に関連する特定のトピックについてこれらの書籍を参照しつつ、アクティブなプロジェクトに参加することが賢明です。このようなプロジェクトを完了することで、自然と豊富な知識を吸収できます。
通常、バグレポートは以下の表のように4列に編成されます。
列(名前) | 説明 |
---|---|
詳細 | この列には、コード内で発生したエラーまたは警告の簡単な説明が表示されます。構文エラー、宣言されていない変数、型の不一致、その他のコーディングミスなど、問題の性質を説明できます。説明を理解することで、プログラマーは問題を迅速に特定できます。 |
ファイル | ここでは、エラーが発生したファイル名が示されます(例:D1 PriceMarker.mq5)。プロジェクト内に複数のファイルがある場合、どのファイルに問題が含まれているかを知ることは、効果的なデバッグと修正をおこなう上で非常に重要です。 |
行 | 指定されたファイル内でエラーが見つかった正確な行番号を指定します。この特定により、プログラマーは注意が必要なコードの特定の部分にすばやく移動でき、問題を見つけるのに必要な時間を短縮できます。 |
列 | エラーが検出された行の特定の列番号を示します。前の列ほど頻繁に参照されるわけではありませんが、複雑なステートメントで発生したエラーや、行に多数の要素(複数の関数呼び出しやパラメータなど)が含まれている場合にエラーを識別するのに特に役立ちます。 |
これらは通常、以下に示すように、左から右に配置されます。また、この説明でデバッグするプログラムの完全なエラーレポートも含まれています。このレポートには、20個のエラーと4個の警告が含まれています(スニペットの下部を参照)。これは、テーブルレイアウトのすぐ下にあります。レポートの特徴は簡単に識別できます。最後まで読んでいただければ、以下のコードスニペットに示されているエラーを解決する方法について説明します。
詳細 | ファイル | 行 | 列 |
'D1 PriceMarker.mq5' 1 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 70 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 70 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 71 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 71 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 72 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 72 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 73 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 73 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 74 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 74 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 75 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 75 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 76 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 76 5 'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 77 5 built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 77 5 'ObjectCreate' - wrong parameters count D1 PriceMarker.mq5 15 9 built-in: bool ObjectCreate(long,const string,ENUM_OBJECT,int,datetime,double,...) D1 PriceMarker.mq5 15 9 'ObjectCreate' - wrong parameters count D1 PriceMarker.mq5 27 9 built-in: bool ObjectCreate(long,const string,ENUM_OBJECT,int,datetime,double,...) D1 PriceMarker.mq5 27 9 'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5 37 5 ',' - unexpected token D1 PriceMarker.mq5 37 28 'labelName' - some operator expected D1 PriceMarker.mq5 37 19 '+' - illegal operation use D1 PriceMarker.mq5 37 36 ',' - unexpected token D1 PriceMarker.mq5 37 69 result of expression not used D1 PriceMarker.mq5 37 43 ',' - unexpected token D1 PriceMarker.mq5 37 73 expression has no effect D1 PriceMarker.mq5 37 71 ',' - unexpected token D1 PriceMarker.mq5 37 82 expression has no effect D1 PriceMarker.mq5 37 76 ')' - unexpected token D1 PriceMarker.mq5 37 87 expression has no effect D1 PriceMarker.mq5 37 84 'OBJPROP_Y' - undeclared identifier D1 PriceMarker.mq5 41 36 'ObjectSetInteger' - no one of the overloads can be applied to the function call D1 PriceMarker.mq5 41 5 could be one of 2 function(s) D1 PriceMarker.mq5 41 5 built-in: bool ObjectSetInteger(long,const string,ENUM_OBJECT_PROPERTY_INTEGER,long) D1 PriceMarker.mq5 41 5 built-in: bool ObjectSetInteger(long,const string,ENUM_OBJECT_PROPERTY_INTEGER,int,long) D1 PriceMarker.mq5 41 5 20 errors, 4 warnings 21 5
このトピックについて議論する際に理解すべき一般的な用語をいくつか紹介します。
- 構文:MetaTrader 5プラットフォームがプログラム(取引アルゴリズム、指標、スクリプトなど)を正しく理解して実行できるようにするために、プログラムをどのように記述する必要があるかを規定する特定のルールセットを指します。
- エラー:コードの間違いや問題により、コードが正しく実行されないことを指します。エラーは、構文エラー、ランタイムエラー、論理エラー、型エラー、コンパイルエラーなど、いくつかの種類に分類できます。
デバッグとは何か?
皆さんのほとんどはこの活気に満ちた用語をよくご存知だと思いますが、初心者にとってはその概念を詳細に把握することが不可欠です。ここで、デバッグのプロセスをよりよく理解できるように、バグを定義します。
- バグ
コンピュータプログラムやシステムにおいて、予期せぬ動作や不正確な動作を引き起こすエラーや欠陥のことです。
- デバッグ
プログラムが意図したとおりに動作し、さまざまな条件下で正しい出力が得られるようにすることを目的として、コンピュータプログラムやシステムのエラーやバグを特定、分離、修正するプロセスです。
MQL5プログラミングの文脈におけるデバッグ
ここでは、MQL5に特有のデバッグの側面をいくつか紹介します。
1. MQL5でよくあるバグの種類
- 構文エラー:スクリプトのコンパイルを妨げるMQL5コード構造の間違い
この例では、Print()関数の閉じ括弧が欠落している単純な構文エラーを表示しています。その結果、スクリプトはコンパイルに失敗します。コード構造を慎重にチェックする必要があることがわかります。
void OnStart() { Print("Hello, World!" // Missing closing parenthesis }
- 論理エラー:コードはコンパイルされて実行されるが、誤った取引シグナルが生成されたり、予期しない動作をしたりする問題
ここには、条件が誤って買い注文をトリガーする論理エラーがあります。プログラマーは、市場の状況に依存するより複雑なロジックを活用することを意図していましたが、現在の実装では不要な取引が発生します。
void OnTick() { double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); double targetPrice = currentPrice + 100; // Intended to use a different logic // Mistakenly placing a buy when conditions aren't right if (currentPrice < targetPrice) // Logic Error { OrderSend(_Symbol, OP_BUY, 0.1, currentPrice, 3, 0, 0, "Buy order", 0, 0, clrGreen); } }
- ランタイムエラー:範囲外の配列にアクセスしようとしたり、取引注文を適切に処理しなかったりするなど、実行中に発生するエラー
この例では、有効なインデックスが5つしかない配列の6番目の要素にアクセスしようとしています。これは実行時エラーとなり、配列を扱う際の境界チェックの重要性を示しています。
void OnStart() { double prices[5]; // Attempt to access out-of-range index (e.g., index 5) double value = prices[5]; // Runtime error: Array out of range }
2.MQL5のデバッグツール
- MetaEditor:MQL5の統合開発環境(IDE)で、構文の強調表示、コード補完、および構文エラーを迅速に特定するのに役立つエラー表示を提供します。
以下のコードでは、result変数の計算にブレークポイントを設定できます。MetaEditorでデバッグする場合、この時点で変数を検査し、期待通りに設定されていることを確認することで、プログラムの流れを分析するための行ごとの実行が容易になります。
void OnStart() { double startValue = 10.0; // Set a breakpoint here to inspect value double result = startValue * 2; Print("Result: ", result); // Check the value of result }
- Print()文:Print()関数を使って、変数の値や実行フローのログをEAログに出力します。これは問題を追跡する簡単な方法です。
このコード例では、Print()関数を使って現在の買値と売値を記録しています。このアプローチは、実行中の変数値をトレースするのに有益であり、期待値と実際の値を比較することで論理エラーを診断するのに役立ちます。
void OnTick() { double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Logging prices for debugging Print("Bid: ", bidPrice, ", Ask: ", askPrice); }
- コードのコメントアウト:問題のある領域を特定するために、コードの一部を一時的に無効にします。
この例では、代替ロジックに焦点を当てるため、コード1行をコメントアウトしています。このテクニックは、バグを切り分けたり、完全に除去せずにコードの異なる部分をテストしたりするのに便利です。
void OnTick() { // double result = SomeFunction(); // Temporarily disabling this line // Run alternate logic while debugging Print("Running alternative logic."); }3. MetaEditorでデバッガを使う
MetaEditorには次の機能を備えた組み込みデバッガーが含まれています。4. テストと最適化
- ブレークポイント:コードにブレークポイントを設定することで、特定の行で実行を一時停止し、変数の値を調べることができます。
- ステップスルー:コードを1行ずつたどりながら、変数がどのように変化し、ロジックの流れがどのようになっているかを観察することができます。
- ウォッチ:コードの実行中、特定の変数の値を監視します。
5. エラー処理
- ストラテジーテスター:MQL5は、履歴データを使用して取引戦略のバックテストを実行できるストラテジーテスターを備えています。取引をシミュレートし、パフォーマンスを分析することで、隠れたバグを明らかにすることができます。
- 最適化:取引アルゴリズムのパフォーマンスを向上させるためにパラメータを最適化することができ、ロジックや実行の潜在的なバグを浮き彫りにすることもできます。
- 取引操作に関連する関数の戻り値のチェックなど、MQL5固有のエラーコードを処理します。一般的な関数には、注文実行関数(OrderSend、OrderCloseなど)があり、適切なエラー処理によって、クラッシュや望ましくない結果を防ぐことができます。
MQL5におけるデバッグのベストプラクティス
1. コードのモジュール性:関数に分割してモジュール化されたコードを記述します。これにより、個々のコンポーネントのテストとデバッグが容易になります。2. コードの文書化:コードにコメントを付けて各部分の動作を説明します。これは、時間が経過してからコードを再確認するときに非常に役立ちます。3. 定期的なテスト:全体の作業が完了するまで待たず、開発中に頻繁にコードをテストします。これにより、バグを早期に発見し、修正することができます。MQL5におけるデバッグの実装
少し前に、友人と私は前日足(D1)ローソク足のラベル付き価格ラインを描画し、高値、安値、始値、終値などの重要な価格レベルをマークするスクリプトの下書きを作成しました。このバージョンは、この記事のために保存しておいたものです。
通常、エキスパートアドバイザー(EA)を作成する際には、MetaEditorが正しい言語構文に基づいて詳細を入力していれば、テンプレートやパラメータの提案を提供してくれるため、開発者を支援しエラーの可能性を減らしてくれます。しかし、一方でフォーラムなどから得たコードにはエラーが点在している場合があります。以下に、バグのあるスクリプトプログラムのコードスニペットを示します。
//+------------------------------------------------------------------+ //| D1 PriceMarker.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/ja/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Clemence Benjamin" #property link "https://www.mql5.com/ja/users/billionaire2024/seller" #property version "1.00" #property strict // Function to create a price line with a label void CreatePriceLine(string name, double price, color clr, string label) { // Create a horizontal line if(!ObjectCreate(name, OBJ_HLINE, 0, 0, price)) { Print("Failed to create line: ", GetLastError()); return; } // Set line properties ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); // Create a label for the price string labelName = name + "_label"; if(!ObjectCreate(labelName, OBJ_LABEL, 0, 0, 0)) { Print("Failed to create label: ", GetLastError()); return; } // Set label properties ObjectSetInteger(0, labelName, OBJPROP_XSIZE, 70); ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr); ObjectSetText(labelName, label + ": " + DoubleToString(price, 2), 10, "Arial", clr); // Position the label double yPos = price; // Positioning along the price axis ObjectSetInteger(0, labelName, OBJPROP_Y, yPos); ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 5); } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { // Get the previous D1 candle's open, high, low, and close prices datetime prevCandleTime = iTime(NULL, PERIOD_D1, 1); double openPrice = iOpen(NULL, PERIOD_D1, 1); double highPrice = iHigh(NULL, PERIOD_D1, 1); double lowPrice = iLow(NULL, PERIOD_D1, 1); double closePrice = iClose(NULL, PERIOD_D1, 1); // Draw labeled price lines for open, high, low, and close prices CreatePriceLine("PrevCandle_Open", openPrice, clrBlue, "Open"); CreatePriceLine("PrevCandle_High", highPrice, clrRed, "High"); CreatePriceLine("PrevCandle_Low", lowPrice, clrGreen, "Low"); CreatePriceLine("PrevCandle_Close", closePrice, clrOrange, "Close"); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Remove the drawn price lines and labels upon indicator deinitialization ObjectDelete("PrevCandle_Open"); ObjectDelete("PrevCandle_High"); ObjectDelete("PrevCandle_Low"); ObjectDelete("PrevCandle_Close"); ObjectDelete("PrevCandle_Open_label"); ObjectDelete("PrevCandle_High_label"); ObjectDelete("PrevCandle_Low_label"); ObjectDelete("PrevCandle_Close_label"); } //+------------------------------------------------------------------+
(i)バグの検出
バグのあるプログラムをコンパイルしようとする場合、MetaEditorの内蔵デバッガはかなり使い勝手がいいことがわかりました。ほとんどのバグは、MetaEditorの[コンパイル]または[リアルタイムプロファイリング]ボタンをクリックしたときに検出されます。ただし、プログラムのコンパイルを妨げないパフォーマンスエラーもあります。これらは、プログラムを実行しようとしたときにプラットフォームまたはテスターでのみ識別できます。
開発者は、プログラム全体をゼロから書いてからデバッグすることも、既存のプログラムを単にデバッグすることもできます。下の画像では、MetaEditorに内蔵されているコンパイラとデバッガを利用して、エラーのサマリーを取得しています(画像のツールボックスウィンドウの下部を参照)。エラー行をダブルクリックすると、カーソルが該当するエラー行に移動し、ハイライト表示されます。[コンパイル]ボタンを押すまで、コード内のエラーに気付くことはほとんどありませんでした。その時点で、デバッガーは発生した問題を報告します。
MetaEditorでのエラーの特定
プログラムのコンパイルは成功するが、期待した結果が得られないこともあります。このような場合、MetaTrader 5プラットフォームのツールボックスウィンドウで利用可能なエキスパートログと操作ログ出力を確認して、潜在的なエラーを特定するのが賢明です。これらのログは、実行中に何が問題になっているかについての貴重な洞察を提供し、トラブルシューティングや問題の効率的な解決に役立ちます。
(ii)3つのデバッグ技術
エラーはしばしばタイプミスや用語の誤用から生じることがあり、デバッガーは通常、説明や解決に向けた部分的なヒントを提供します。これらのメッセージを理解することができれば、コードを再検討し、必要な修正を加えることはたいていの場合簡単です。しかし、診断が難しい複雑な状況で、参考書やコミュニティの専門家によるより深い知識が必要な場合もあります。
私の経験では、複雑な問題をデバッグするときには、いくつかの戦略を使うのが一般的です。これらの手順を3つの主要なアプローチに分類していますが、このリストは網羅的なものではなく、この議論の目的に特化したものです。それぞれの手順を詳しく説明します。
1. ドキュメンテーションの再検討
構文や関数の使用方法を明確にし、エラーメッセージを適切に解釈することで、MQL5プログラムのデバッグは大幅に効率化されます。詳細な説明や具体的な例を参照することで、誤った実装を特定し、組み込み関数への理解を深める助けとなります。さらに、ドキュメントには一般的なエラー、ベストプラクティス、代替ソリューションに関する情報が含まれている場合が多く、これにより開発者は問題を効果的にトラブルシューティングし、コードを最適化してパフォーマンスを向上させることができます。このプロジェクトでは、下の画像を見て、ドキュメントに簡単にアクセスする方法をご覧ください。
ドキュメントの再検討
エラー報告
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5 70 5
解決のヒント
built-in: bool ObjectDelete(long,const string) D1 PriceMarker.mq5 70 5
現在の状況
ObjectDelete("PrevCandle_Open");
解決のヒントから、ObjectDelete関数は2つのパラメータを要求していることがわかります。この食い違いが問題の所在を示し、それに応じて対処することができます。ドキュメントによると、MQL5のObjectDelete関数は2つのパラメータを必要とします。
- name:削除するオブジェクトの名前を文字列で指定します。
- Chart_id:オブジェクトを削除すべきチャートのIDを整数で指定します。省略された場合、関数は現在のチャートをデフォルトとします。
この問題を解決するには、ObjectDeleteを呼び出すときに両方のパラメータを確実に渡す必要があります。そうすることで、関数の呼び出しを期待される構文に合わせ、エラーをなくすことができます。
解決:
ObjectDelete(0, "PrevCandle_Open");
次に、メインコードを見てみると、ObjectDelete関数のインスタンスがいくつかあることに気づきます。調査から集めた情報を使えば、そのすべてに必要な調整を施すことができます。各インスタンスに必要な両方のパラメータを確実に提供することで、これらのエラーを効果的に解決することができます。
以下の画像で、エラーの総数をいかにして10も減らすことに成功したかをご覧ください。これは、私たちのスクリプトのデバッグに大きな進展があったことを示しており、適切なドキュメントに基づく徹底的な調査と修正の重要性を示しています。
ObjectDelete関数のエラー解決
完成です。エラーが発生したら、解決策を試行するたびに[コンパイル]ボタンを押すのがよい習慣です。これにより、エラーがまだ続いているかどうかを確認し、残っている問題を特定することができます。
さて、次のエラーに移りましょう。
エラー報告
'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5 29 5 'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5 29 5 ',' - unexpected token D1 PriceMarker.mq5 29 28 'labelName' - some operator expected D1 PriceMarker.mq5 29 19 '+' - illegal operation use D1 PriceMarker.mq5 29 36 ',' - unexpected token D1 PriceMarker.mq5 29 69 result of expression not used D1 PriceMarker.mq5 29 43 ',' - unexpected token D1 PriceMarker.mq5 29 73 expression has no effect D1 PriceMarker.mq5 29 71 ',' - unexpected token D1 PriceMarker.mq5 29 82 expression has no effect D1 PriceMarker.mq5 29 76 ')' - unexpected token D1 PriceMarker.mq5 29 87 expression has no effect D1 PriceMarker.mq5 29 84
今回、複数のレポートを集めたのは、確認すると同じ行でエラーが発生しているからです。これは多くの場合、コードの特定の部分で対処すべき共通の問題を示しています。根本的な問題を特定し、必要な修正を判断するために、問題のラインを詳しく見てみよう。
解決のヒント
このシナリオでは、宣言されていない識別子、期待される演算子、式が有効でない、予期しないトークンのようなエラーが発生します。
現在の状況
ObjectSetText(labelName, label + ": " + DoubleToString(price, 2), 10, "Arial", clr);
ドキュメントを確認しましたが、ObjectSetTextへの言及は見つかりませんでした。しかし、ObjectSet...と入力し始めると、いくつかの候補が表示され、ObjectSetStringが最良の選択肢でした。この関数は正しいものであることが判明し、期待通りに機能しました。
私たちの取り組みは下記に反映されています。
ObjectSetTextがドキュメントにない
ObjectSetString
ドキュメントに従うObjectSetString関数のパラメータは以下の通りです。
bool ObjectSetString( long chart_id, // chart identifier string name, // object name ENUM_OBJECT_PROPERTY_STRING prop_id, // property int prop_modifier, // modifier string prop_value // value );
解決
最初のエラーに対してと同じように、必要な調整をおこなうことで、ほぼすべての問題を解決することができました。あとは数行を修正するのみです。残されたエラーを完全に解消するために、最終調整に集中しましょう。
ObjectSetString(0, labelName, OBJPROP_TEXT, label + ": " + DoubleToString(price, 2));
バグがいくつか残っています。
残り2つのエラー
最後に、残りのエラーを修正します。
ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, price); // Position label at the price level
OBJPROP_Yではなく、OBJPROP_YDISTANCEのはずでした。
ドキュメントを参考にデバッグを成功させる
最終的にクリーンアップされたコードは次のとおりです。
//+------------------------------------------------------------------+ //| D1 PriceMarker.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/ja/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Clemence Benjamin" #property link "https://www.mql5.com/ja/users/billionaire2024/seller" #property version "1.00" #property strict // Function to create a price line with a label void CreatePriceLine(string name, double price, color clr, string label) { // Create a horizontal line if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price)) { Print("Failed to create line: ", GetLastError()); return; } // Set line properties ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); // Create a label for the price string labelName = name + "_label"; if(!ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0)) { Print("Failed to create label: ", GetLastError()); return; } // Set label properties ObjectSetInteger(0, labelName, OBJPROP_XSIZE, 70); ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr); ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, price); // Position label at the price level ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 5); // Set the text of the label ObjectSetString(0, labelName, OBJPROP_TEXT, label + ": " + DoubleToString(price, 2)); } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { // Get the previous D1 candle's open, high, low, and close prices datetime prevCandleTime = iTime(NULL, PERIOD_D1, 1); double openPrice = iOpen(NULL, PERIOD_D1, 1); double highPrice = iHigh(NULL, PERIOD_D1, 1); double lowPrice = iLow(NULL, PERIOD_D1, 1); double closePrice = iClose(NULL, PERIOD_D1, 1); // Draw labeled price lines for open, high, low, and close prices CreatePriceLine("PrevCandle_Open", openPrice, clrBlue, "Open"); CreatePriceLine("PrevCandle_High", highPrice, clrRed, "High"); CreatePriceLine("PrevCandle_Low", lowPrice, clrGreen, "Low"); CreatePriceLine("PrevCandle_Close", closePrice, clrOrange, "Close"); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Remove the drawn price lines and labels upon indicator deinitialization ObjectDelete(0, "PrevCandle_Open"); ObjectDelete(0, "PrevCandle_High"); ObjectDelete(0, "PrevCandle_Low"); ObjectDelete(0, "PrevCandle_Close"); ObjectDelete(0, "PrevCandle_Open_label"); ObjectDelete(0, "PrevCandle_High_label"); ObjectDelete(0, "PrevCandle_Low_label"); ObjectDelete(0, "PrevCandle_Close_label"); } //+------------------------------------------------------------------+
D1 PriceMarkerは、前日足(D1)の高値、安値、始値、終値に対応する水平線を描画することで、取引チャートにおけるテクニカル分析を支援するよう設計されたMQL5スクリプトです。このスクリプトは初期化時にこれら4つの価格ポイントを取得し、ヘルパー関数を使用して、各価格に対応する水平線を描画します。それぞれの線は異なる色で示されます(始値は青、高値は赤、安値は緑、終値はオレンジ)。さらに、各価格線には、その価格を示すラベル付きのテキストが付属しています。スクリプトがチャートから削除される際には、描画された線とラベルがすべて自動的に削除され、トレーダーの作業スペースが整理されます。
2.AIによるデバッグ
誰もがAIモデルをどのように活用できるかに興味を持っていることは理解しています。このトピックについては簡単に触れたうえで、後ほど詳細に議論する予定です。幸いにも、これらのAIモデルの多くは、構文を人間よりも迅速かつ正確に理解する能力を持っています。ただし、予期しない結果が生じる場合もあるため、特に複雑なケースでは、人間による慎重な監視が必要となることを忘れてはなりません。AIは適切に利用すれば非常に優れたツールとなります。私自身、多くのコーディング課題をAIの提案を活用して解決してきました。
基本的に、AIプロンプトを作成する際は、まずデバッグ対象のプログラムを提供することから始めます。その後、MetaEditorのレポートからエラー行をコピーし、それらをプロンプトに貼り付けることで、AIがデバッグプロセスを支援できるようにします。この方法は多くの場合成功につながりますが、場合によってはさらに複雑な問題を引き起こすこともあります。そのため、AIの提案に盲目的に従うのではなく、批判的に考え、必要に応じてさらに一歩踏み込むことが重要です。適切に使用すれば、AIは他のデバッグツールとともに効果的に活用でき、その結果はこれらのツールが生成するはずの結果と一致することが期待されます。
AIプロンプトにエラーをコピーする
3. フォーラム訪問
上記と同様に、フォーラムのメンバーもデバッグに関する貴重な洞察を提供するためには情報が必要です。コーディングの課題について議論に参加することは、他の専門家から学び、知見を深めるための素晴らしい方法です。プログラムを提出することで、他のメンバーから賢明な提案や具体的な解決策を得る機会が得られます。このような共同アプローチは、単に問題を解決するだけでなく、フォーラムに参加するすべての人々の知識とスキルを向上させるのに役立ちます。
MetaTrader 5上のプログラム
D1 PriceMarkerスクリプト
結論
MQL5プログラミングにおけるチームワークは、D1 PriceMarkerスクリプトの作成過程を通じて示されているように、堅牢な取引アルゴリズムの開発を強化する上で不可欠な実践であることが明らかになりました。デバッグプロセスはエラーレポートと包括的なMQL5リファレンスドキュメントに大きく依存しており、開発中に直面した問題を体系的に特定し、効果的に対処することを可能にしました。
このアプローチにより、特定のエラーを迅速かつ正確に解決できるだけでなく、プログラミング環境全体に対する理解を深めることができました。また、将来的にデバッグを支援するために人工知能(AI)を活用する可能性についても触れました。AIが提供する洞察や推奨事項は、デバッグプロセスを効率化し、開発者にとって有益なサポートとなるでしょう。
さらに、コミュニティの支援、特にMQL5フォーラムを通じたサポートの重要性も強調されます。他の経験豊富な開発者からのアドバイスを受けたり、知識を共有したりすることで、開発の質をさらに向上させることができます。このような共同作業とリソース主導のアプローチを採用することで、デバッグ作業の有効性を飛躍的に高め、最終的にはアルゴリズム取引の競争の激しい環境で信頼性が高く革新的な取引ソリューションの開発につながるのです。皆さん、取引をお楽しみください。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15325





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