【MQL5】MathTan関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク

MathTan関数の働き・役割

MathTan関数は、指定された角度の正接(タンジェント)を求めるために使用されます。この関数は、ラジアン単位で表された角度を入力として受け取り、その角度の正接値を計算します。

正接(タンジェント)とは

正接(タンジェント)は、三角比の一つで、直角三角形におけるある角度と辺の長さの関係を表します。三角形の一つの角度(θ)に対して、正接は次のように定義されます。

tan(θ) = 対辺 / 隣辺

ここで、「対辺」は角度θに向かい合う辺、「隣辺」は角度θに隣接する辺です。

例えば、45度の場合では対辺と隣辺の長さが同じになります。したがって、tan(45°)は 1 です。45度よりも小さい角度では、対辺が隣辺よりも短くなるため、tan(θ)も1未満の値をとります。

一方、角度が45度を超えてさらに大きくなると、対辺が隣辺よりも長くなり、tan(θ)も1より大きくなっていきます。この傾向は90度に近づくほど急激になり、90度の直前で無限大に発散します。

MathTan関数の引数について

double  MathTan(
  double  rad      // ラジアン単位の引数
  );

MathTan関数には1つの引数があります。

rad

  • 種類: double型
  • 説明:ラジアン単位(角度を円周率πを基準として表す方法)で表した角度を指定します。この引数は、角度を度ではなくラジアンで指定する必要があるため、注意が必要です。

ラジアンは次の算出式を使って変換できます。

ラジアン = 度 × (π / 180)

例えば、45度の場合、この算出式を使ってラジアンに変換すると、45 × (π / 180) = π / 4 になります。このように、度をラジアンに変換することでMathTan関数に適した形式で角度を指定できます。

MathTan関数の戻り値について

MathTan関数は、指定された角度の正接タンジェント)を計算し、その値をdouble型で返します。この戻り値は、指定したラジアン単位の角度に対する正接の数値です。

ただし、注意すべき点として、引数の値が263以上または-263以下の場合、計算結果に重大な損失が生じる可能性があります。これは、大きな角度での正接計算が精度を失いやすく、不特定の数値が戻される可能性があるためです。

MathTan関数を使ったサンプルコード

#define GRAPH_WIDTH 750  // グラフの幅を指定(ピクセル)
#define GRAPH_HEIGHT 350 // グラフの高さを指定(ピクセル)

#include <Graphics\Graphic.mqh> // グラフィック描画のためのライブラリをインクルード

CGraphic ExtGraph; // グラフィック描画用のオブジェクトを作成

//+------------------------------------------------------------------+
//| スクリプトの開始関数                                             |
//+------------------------------------------------------------------+
void OnStart()
{
    // 0から2πまでを101分割し、ラジアンでの角度をステップごとに増加させるベクトルdeltaを生成
    vector delta = vector::Full(101, 2 * M_PI / 100);
    delta[0] = -263; // ベクトルの最初の要素を-263に設定

    //--- deltaのステップで-263から2πまでの値を累積和でXに取得
    vector X = delta.CumSum();

    //--- Xの各角度に対する正接値をYに計算
    vector Y = MathTan(X);

    //--- 計算されたベクトルの内容を配列に変換(Swapメソッドでベクトル内容を配列に移動)
    double x_array[], y_array[];
    X.Swap(x_array); // Xの値を配列x_arrayに転送
    Y.Swap(y_array); // Yの値を配列y_arrayに転送

    //--- 計算された正接値のグラフを描画
    CurvePlot(x_array, y_array, clrDodgerBlue);

    //--- ESCキーまたはPgDnキーが押されるまでグラフ表示を維持
    while (!IsStopped())
    {
        if (StopKeyPressed())
            break; // キーが押された場合はループを抜ける
        Sleep(16); // 一定時間待機してCPU負荷を軽減
    }

    //--- クリーンアップ:グラフィックオブジェクトを削除して終了
    ExtGraph.Destroy();
}

//+------------------------------------------------------------------+
//| ESCキーが押されたらtrueを返す                                      |
//| PgDnキーが押されてグラフを保存したらtrueを返す                    |
//| その他の場合はfalseを返す                                          |
//+------------------------------------------------------------------+
bool StopKeyPressed()
{
    //--- ESCキーが押されたか確認し、押された場合はtrueを返す
    if (TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE) != 0)
        return (true);

    //--- PgDnキーが押され、グラフのスクリーンショットが正常に保存された場合はtrueを返す
    if (TerminalInfoInteger(TERMINAL_KEYSTATE_PAGEDOWN) != 0 &&
        MakeAndSaveScreenshot(MQLInfoString(MQL_PROGRAM_NAME) + "_Screenshot"))
        return (true);

    //--- その他の場合はfalseを返す
    return (false);
}

//+------------------------------------------------------------------+
//| グラフオブジェクトを作成し、正接曲線を描画する                     |
//+------------------------------------------------------------------+
void CurvePlot(double &x_array[], double &y_array[], const color colour)
{
    // グラフ描画オブジェクトを作成
    ExtGraph.Create(ChartID(), "Graphic", 0, 0, 0, GRAPH_WIDTH, GRAPH_HEIGHT);
    // x_arrayとy_arrayに基づいてグラフの曲線を追加
    ExtGraph.CurveAdd(x_array, y_array, ColorToARGB(colour), CURVE_LINES);
    ExtGraph.IndentUp(30); // グラフの上マージンを設定
    ExtGraph.CurvePlotAll(); // 全てのグラフをプロット

    //--- ユーザーに操作を案内するテキストをグラフ上に追加
    string text1 = "Press ESC to delete the graph and stop the script, or";
    string text2 = "Press PgDn to create a screen, delete the graph and stop the script";
    ExtGraph.TextAdd(54, 9, text1, ColorToARGB(clrBlack));
    ExtGraph.TextAdd(54, 21, text2, ColorToARGB(clrBlack));
    ExtGraph.Update(); // 画面を更新してテキストを反映
}

//+------------------------------------------------------------------+
//| スクリーンショットを撮り、画像ファイルに保存する                   |
//+------------------------------------------------------------------+
bool MakeAndSaveScreenshot(const string file_name)
{
    string file_names[]; // 保存ファイル名を格納する配列
    ResetLastError(); // エラー情報をリセット
    int selected = FileSelectDialog("Save Picture", NULL, "All files (*.*)|*.*", FSD_WRITE_FILE, file_names, file_name + ".png");

    // ファイル選択に失敗した場合のエラーチェック
    if (selected < 1)
    {
        if (selected < 0)
            PrintFormat("%s: FileSelectDialog() function returned error %d", __FUNCTION__, GetLastError());
        return false; // エラーが発生した場合はfalseを返す
    }

    bool res = false;
    // 一時的にチャートの表示をオフにしてスクリーンショットを撮る
    if (ChartSetInteger(0, CHART_SHOW, false))
        res = ChartScreenShot(0, file_names[0], GRAPH_WIDTH, GRAPH_HEIGHT);
    ChartSetInteger(0, CHART_SHOW, true); // チャートの表示を再設定

    return (res); // スクリーンショットが成功した場合はtrueを返す
}

このコードは、指定範囲の角度に対する正接タンジェント)値を計算し、それらをグラフとして描画します。画面には、ESCキーを押すとグラフが削除されスクリプトが停止する指示と、PgDnキーを押すとスクリーンショットが保存されてグラフが削除される指示が表示されます。

実行後、ESCまたはPgDnキーを押すと、グラフを閉じてスクリプトが終了します。

サンプルコード解説1: グローバル領域での定義

#define GRAPH_WIDTH 750    // グラフの幅を設定
#define GRAPH_HEIGHT 350   // グラフの高さを設定

#include <Graphics\Graphic.mqh> // グラフィック描画用のライブラリをインクルード

CGraphic ExtGraph; // CGraphicクラスのインスタンスを作成

定義の詳細

グラフの幅と高さの定義

グラフの幅を750ピクセル(デジタル画像を構成する最小の単位)に、グラフの高さを350ピクセルに設定しています。defineディレクティブを使用して定数を定義することで、コード内でこれらの値を使用する際に簡単に参照できるようになります。

グラフィックライブラリのインクルード

includeディレクティブを使用して、グラフィック関連の機能を提供するライブラリファイル「Graphic.mqh」をインクルードしています。このライブラリには、グラフの描画や曲線の追加など、グラフィック操作に必要な関数クラスが定義されています。

グラフィックオブジェクトの作成

CGraphicクラスインスタンスであるExtGraphオブジェクトを作成しています。このオブジェクトは、グラフの描画や操作に使用されます。クラスはオブジェクト指向プログラミングの基本要素であり、特定の機能を持つオブジェクト(変数配列など)を作成するためのテンプレートです。

サンプルコード解説2: OnStart関数の中1

//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数                                      |
//+------------------------------------------------------------------+
void OnStart()
 {
  // vectorクラスを使用してdeltaベクトルを作成し、2πを100等分した101個の値を生成
  vector delta=vector::Full(101, 2 * M_PI / 100);
  delta[0] = 0; // ベクトルの初めの要素を0に設定
  
  //--- deltaステップで -1 から 2πまでの101個の値を取得する
  vector X = delta.CumSum(); // ベクトルXにdeltaの累積和を格納
  
  //--- Xベクトルの各値の正接(タンジェント)値を計算してYベクトルに格納
  vector Y = MathTan(X);

この部分のコードでは、スクリプトが実行される際の処理として、正接計算をおこなう手順を記述しています。

最初に、deltaというベクトル(複数の値を一つのデータとしてまとめて扱うデータ構造)を作成しています。vectorクラスのFullメソッドを用いて、deltaに101個の要素を持たせ、各要素に2π/1000の値を格納しています。

※「vector::」という表記は、vectorクラスメソッド定数を参照するための構文です。この構文により、vector型の様々なメソッド(例えばFullやCumSumなど)を呼び出すことが可能です。

このdeltaベクトルの初期化によって、-1から2πにわたる範囲で値を生成する準備をしています。

次に、deltaベクトルの最初の要素を0に設定して範囲を調整しています。

次に、deltaの累積和を計算してXというベクトルに格納しています。CumSumメソッドを用いることで、deltaの各要素が累積的に加算された結果がXに保存されます。

最後に、MathTan関数を用いてXベクトルの各値に対する正接を計算し、結果をYベクトルに格納しています。このYベクトルには、Xの各要素に対応した正接の値が格納されることになり、これらのデータが次のグラフ描画部分で使用されます。

サンプルコード解説3:OnStart関数部分その2

  //--- 計算された値をベクトルから配列に転送する
  double x_array[], y_array[]; // 配列を宣言
  X.Swap(x_array);             // Xベクトルをx_array配列にスワップ
  Y.Swap(y_array);             // Yベクトルをy_array配列にスワップ
 
  //--- 計算されたベクトル値のグラフを描画する
  CurvePlot(x_array, y_array, clrDodgerBlue); // 曲線を描画

この部分のコードでは、余弦計算の結果を使ってグラフ描画の準備を行っています。

まず、空の配列x_arrayとy_arrayを宣言しています。これらの配列は、それぞれXベクトルとYベクトルのデータを受け取るためのもので、後にグラフ描画で使用されます。次に、Xベクトルの内容をx_array配列に、Yベクトルの内容をy_array配列に転送するために、Swapメソッドを使用しています。Swapメソッドベクトルの内容を配列に効率的にコピーするメソッドです。

これにより、XとYの計算結果が配列形式に変換され、グラフ描画に適した形に整えられます。そして、CurvePlot関数を呼び出して、計算したデータをもとにグラフを描画しています。CurvePlot関数には、x_arrayとy_array、そしてグラフの線の色clrDodgerBlueが渡され、指定されたデータと色でグラフが描画されます

サンプルコード解説4:OnStart関数部分その3

//--- EscapeキーまたはPgDnキーを押してグラフを削除し、終了するまで待機
  while (!IsStopped())
    {
    if (StopKeyPressed()) // 停止ボタンが押されているかを確認
        break;
    Sleep(16); // 16ミリ秒待機してから次のループへ
    }
 
  //--- グラフィックのクリーンアップ
  ExtGraph.Destroy(); // ExtGraphオブジェクトを削除してメモリを解放
 }

この部分のコードは、グラフを表示させたまま、ESCキーまたはPgDnキーが押されるのを待機する処理です。

まず、while文でループを開始し、スクリプトが停止されていない間、つまりIsStopped関数がfalseを返す間はループが続きます。ループの中でStopKeyPressed関数が呼ばれ、ESCキーまたはPgDnキーが押されたかを確認します。もし、いずれかのキーが押されている場合、break文によってループを抜け、待機処理を終了します。これにより、ユーザーが任意のタイミングでグラフの表示を終了できるようになっています。

ループ内でSleep関数が16ミリ秒の待機を挟むことで、CPU負荷を軽減しながらキーの入力を定期的に確認します。待機処理が終了すると、グラフのクリーンアップに移ります。ExtGraphインスタンスに対してDestroyメソッドを呼び出し、グラフを破棄して使用していたメモリを解放します。これにより、スクリプトの終了時にリソースが適切に解放されます。

サンプルコード解説5:StopKeyPressed関数(オリジナル関数)部分

//+------------------------------------------------------------------+
//| ESCが押されたら「true」を返す                                     |
//| PgDnが押されたら、スクリーンショットを撮り「true」を返す           |
//| その他の場合は「false」を返す                                     |
//+------------------------------------------------------------------+
bool StopKeyPressed()
 {
  //--- ESCキーが押されたら「true」を返す
  if (TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE) != 0)
    return (true);
  
  //--- PgDnキーが押されてスクリーンショットが正常に保存されたら「true」を返す
  if (TerminalInfoInteger(TERMINAL_KEYSTATE_PAGEDOWN) != 0 && 
      MakeAndSaveScreenshot(MQLInfoString(MQL_PROGRAM_NAME) + "_Screenshot"))
    return (true);
  
  //--- その他の場合は「false」を返す
  return (false);
 }

StopKeyPressed関数は、ESCキーやPgDnキーが押されたかどうかを検出し、特定の動作を行うためのカスタム関数です。この関数は、グラフ表示の終了条件を管理する重要な役割を持っています。

まず、TerminalInfoInteger関数を使用してESCキーの状態を確認しています。引数として、TERMINAL_KEYSTATE_ESCAPEという識別子を指定しています。この識別子は、ESCキーの押下状態を取得するために使用され、キーが押されている場合には非ゼロの値が返されます。もし非ゼロが返された場合、関数はtrueを返し、スクリプト内でグラフの表示を終了させることができます。

次に、PgDnキーが押されているかどうかを確認しています。この場合もTerminalInfoInteger関数を使用しており、引数としてTERMINAL_KEYSTATE_PAGEDOWNという識別子を指定しています。この識別子は、PgDnキーの押下状態を取得するために使用され、押されていれば非ゼロが返されます。PgDnキーが押されているときには、さらにMakeAndSaveScreenshot関数を呼び出してスクリーンショットをファイルに保存します。

MakeAndSaveScreenshot関数には、スクリーンショットのファイル名を指定するための文字列引数として渡されています。この文字列は、MQLInfoString関数を使用して生成されています。MQLInfoString関数引数には、MQL_PROGRAM_NAMEという識別子が指定されており、これによって現在のスクリプト名が取得されます。スクリーンショットのファイル名には、このスクリプト名に「_Screenshot」という文字列を追加し、ファイルが保存されます。

スクリーンショットの保存に成功した場合にはtrueが返され、PgDnキーによる終了動作とスクリーンショットの保存が同時に行われます。いずれのキーも押されていない場合にはfalseが返され、スクリプトは実行を続行します。この構造により、ESCまたはPgDnが押されるまでグラフを表示し、必要に応じてスクリーンショットを保存してからスクリプトを終了する動作が可能になります。

サンプルコード解説6:CurvePlot関数(オリジナル関数)部分

//+------------------------------------------------------------------+
//| グラフオブジェクトを作成して曲線を描画                            |
//+------------------------------------------------------------------+
void CurvePlot(double &x_array[], double &y_array[], const color colour)
 {
  // グラフオブジェクトを作成(チャートID、名前、座標などを設定)
  ExtGraph.Create(ChartID(), "Graphic", 0, 0, 0, GRAPH_WIDTH, GRAPH_HEIGHT);
  
  // カーブ(曲線)を追加し、色とラインの種類を指定
  ExtGraph.CurveAdd(x_array, y_array, ColorToARGB(colour), CURVE_LINES);
  
  // テキストのインデント位置を少し上に設定
  ExtGraph.IndentUp(30);
  
  // すべての曲線を描画
  ExtGraph.CurvePlotAll();
  
  // ESCキーとPgDnキーに関する操作方法の説明を追加
  string text1 = "Press ESC to delete the graph and stop the script, or";
  string text2 = "Press PgDn to create a screen, delete the graph and stop the script";
  ExtGraph.TextAdd(54, 9, text1, ColorToARGB(clrBlack));
  ExtGraph.TextAdd(54, 21, text2, ColorToARGB(clrBlack));
  
  // グラフの更新
  ExtGraph.Update();
 }

CurvePlot関数は、渡された配列データをもとにグラフを作成し、指定した色で曲線を描画するためのカスタム関数です。この関数には、x軸とy軸のデータ配列、および曲線の色を指定するための引数が含まれています。

最初に、ExtGraphインスタンスのCreateメソッドを使用してグラフを作成しています。Createメソッド引数には、ChartID、グラフの名前(”Graphic”)、座標(0, 0)、および幅と高さ(GRAPH_WIDTHとGRAPH_HEIGHT)が指定されています。ChartID関数は、現在のチャートIDを取得する関数で、これにより生成されたグラフは現在のチャートに描画されます。

次に、ExtGraphインスタンスのCurveAddメソッドを使用して、x軸とy軸の配列データをもとに曲線を追加します。CurveAddメソッド引数には、x_arrayとy_arrayの配列、指定した色をARGB形式に変換するためのColorToARGB関数、そして曲線のスタイル(CURVE_LINES)が渡されています。この処理によって、指定の色とスタイルで曲線が描画されます。

続いて、IndentUpメソッドを使用してグラフの上部に30ピクセル(デジタル画像を構成する最小の単位)の空白を追加しています。これにより、グラフ上に余白が確保され、グラフが画面に適切に配置されるようになります。

その後、CurvePlotAllメソッドを使用して、追加した曲線をグラフに描画しています。

さらに、グラフの操作方法についての説明文を追加しています。text1およびtext2という文字列には、それぞれ「ESCキーでグラフを削除してスクリプトを停止する」「PgDnキーでスクリーンショットを作成してからグラフを削除し、スクリプトを停止する」という内容の説明が含まれています。TextAddメソッドを使って、これらのテキストを画面の指定位置(x=54, y=9 と x=54, y=21)に描画し、説明が表示されるようにしています。

また、色の指定にはColorToARGB関数を使用しています。ColorToARGB関数は、指定された色をARGB(Alpha、Red、Green、Blue)形式に変換し、透過度や色の設定が反映されるようにします。これにより、TextAddメソッドで追加するテキストや曲線が指定の色で正しく表示されます。

最後に、Updateメソッドを呼び出してグラフの描画を更新し、設定したデータやテキストを反映させます。この一連の処理により、x軸とy軸のデータに基づく曲線が描画され、操作の説明が表示されたグラフが完成します。

サンプルコード解説7:MakeAndSaveScreenshot関数(オリジナル関数)部分

//+------------------------------------------------------------------+
//| スクリーンショットを撮り、画像をファイルに保存する                |
//+------------------------------------------------------------------+
bool MakeAndSaveScreenshot(const string file_name)
 {
  string file_names[]; // ファイル名を格納するための配列を初期化
  ResetLastError(); // 最後のエラーをリセット
  
  // ファイル保存用のダイアログを表示し、選択されたファイルを取得
  int selected = FileSelectDialog("Save Picture", NULL, "All files (*.*)|*.*", FSD_WRITE_FILE, file_names, file_name + ".png");
  if (selected < 1)
    {
    // ファイル選択エラーが発生した場合の処理
    if (selected < 0)
        PrintFormat("%s: FileSelectDialog() function returned error %d", __FUNCTION__, GetLastError());
    return false; // エラー時はfalseを返す
    }
 
  bool res = false; // 成功判定の変数
  // 一時的にチャート表示を無効化し、スクリーンショットを撮影
  if (ChartSetInteger(0, CHART_SHOW, false))
    res = ChartScreenShot(0, file_names[0], GRAPH_WIDTH, GRAPH_HEIGHT);
  
  // チャート表示を再度有効に設定
  ChartSetInteger(0, CHART_SHOW, true);
  
  return (res); // スクリーンショットが正常に保存できた場合はtrueを返す
 }

MakeAndSaveScreenshot関数は、スクリーンショットを撮影し、指定したファイル名で保存する機能を持っています。この関数は、ユーザーがPgDnキーを押した際に呼び出され、現在のチャートのスクリーンショットをファイルに保存する手順を実行します。

最初に、file_namesという空の文字列配列を作成しています。これは、ファイル選択ダイアログから選ばれたファイル名を格納するための配列です。また、ResetLastError関数を呼び出してエラー状態をリセットし、後の処理で発生するエラーが過去のエラーと混在しないようにします。

次に、FileSelectDialog関数を使って、ファイルの保存ダイアログを表示します。この関数の最初の引数にはダイアログタイトル(”Save Picture”)、次の引数NULL、そしてファイルの種類として”All files (.)|.“を指定しています。
この”(.)|.“の形式は、ファイルダイアログでのファイルフィルターを設定するための書式です。
左側の(.)はフィルターの表示名で「すべてのファイル」を示し、右側の.はフィルターの実際の条件を指定しています。
これにより、ダイアログにすべてのファイルを表示するようになります。最後の引数には、デフォルトのファイル名として指定されたfile_nameに拡張子”.png”を追加した文字列を渡しています。FileSelectDialog関数が成功すると、選ばれたファイル名がfile_names配列に格納され、選択数が返されます。

ファイルが選択されなかった場合、またはエラーが発生した場合はfalseを返します。選択にエラーが発生した場合、GetLastError関数で取得したエラーコードをPrintFormat関数でエラーメッセージとして出力します。

スクリーンショットの保存処理では、まずChartSetInteger関数でチャート表示を一時的に非表示にします。引数には、チャート識別子として0、プロパティとしてCHART_SHOW、表示を無効にするためのfalseが指定されています。次に、ChartScreenShot関数を呼び出し、file_names配列の最初の要素に指定されたファイル名で、GRAPH_WIDTHとGRAPH_HEIGHTのサイズでスクリーンショットを保存します。最後にChartSetInteger関数でチャートを再表示します。

関数戻り値として、スクリーンショットが正常に保存されたかどうかの成否が返されます。

MathTan関数を使ってEAを作る際のアイディア

MathTan関数を用いてエキスパートアドバイザーEA)を作成する際には、三角関数の特性を活かして市場のサイクルやトレンド分析を行うことが考えられます。例えば、価格の周期的な変動を捉え、適切なエントリーポイントやエグジットポイントを見つけるためにMathTan関数を活用できます。

価格の変動パターンを正接に基づいてモデル化し、特定の値の範囲でポジションを取るEAを構築できます。例えば、価格が上昇の傾向にある場合や下降の傾向にある場合に、MathTan関数で変動のピークと谷を測定してトレードのタイミングを見つける手法が考えられます。

MathTan関数と他の指標を組み合わせることで、フィルタとして利用し、トレンドの強弱や変化のポイントを把握する手法も有効です。こうした分析によって、より信頼性の高いトレード判断を行えるEAの作成が可能です。

タイトルとURLをコピーしました