コンテンツにスキップ

【移植#42】口座種別をDLLなしで判定 — 標準APIと表示プライバシーを検証する

EURUSDのH1チャート上で数値関数32ケース、口座情報の安定読取、ログイン番号の非表示が合格したMT5画面

この記事の3行まとめ

  • MQL4時代のウィンドウタイトル解析を使わず、MQL5のAccountInfoInteger()で口座種別を判定します
  • 数値関数の自作版は32ケースで標準関数と照合し、「書ける」と「同じ仕様」を分けて確認します
  • 口座番号は取得できても画面・ログ・診断バッファへ出さず、存在確認だけを公開します

今回の原典は「標準関数を書き直せるか」

投稿日順で次に当たる2010年1月31日の記事は、前日の「演算子を使わずに計算する」話を、MQL4の標準関数へ広げた続編です。

元記事「昨日の続き。。。」を読む

原典はまず、MathAbsMathCeilMathFloorMathMaxMathMinMathModMathPowMathRoundなどを別の形で書けないか、と問いかけます。

後半ではさらに踏み込み、WindowsのウィンドウタイトルをDLLで読み、文字列からデモ口座かどうかと口座番号を推測するサンプルを紹介していました。当時の「標準関数の裏側を考える」という知的パズルとしては面白い題材です。

ただし、現在のMQL5へそのまま移す理由はありません。口座情報には公式APIがあり、ウィンドウの表示形式に依存する必要がないからです。今回は次の二つに分けて検証します。

  1. 数値関数は小さな自作版を書き、標準関数と結果を照合する
  2. 口座情報は再発明せず、MQL5の標準APIで安全に読む

数値関数は短く書けても、境界で意味が変わる

絶対値は、原典と同じ発想で簡単に書けます。

MQL
double MyMathAbs(const double value)
{
   return value < 0.0 ? -value : value;
}

最大値と最小値も、二つの値を比較するだけです。ところが、切り上げ・切り捨て・剰余・べき乗・丸めまで進むと、対象にする型や入力範囲を決めなければ「標準関数と同じ」とは言えません。

たとえば、浮動小数点数をlongへ変換した結果を利用する自作MathCeilでは、正数と負数で補正する方向が変わります。

MQL
double MyMathCeil(const double value)
{
   const long truncated = (long)value;
   if(value > 0.0 && value != (double)truncated)
      return (double)(truncated + 1);
   return (double)truncated;
}

2.8なら切り捨てた2へ1を加えます。一方、-2.8を整数化した結果は-2なので、そのまま上側の整数になります。

MQL5公式リファレンスのMath Functionsには、各関数の役割が定義されています。自作版はこの一覧を置き換えるものではなく、限定した入力で仕組みを確かめる教材です。


剰余は符号、べき乗は指数の範囲を決める

自作した剰余は、商を0方向へ整数化してから元の値との差を取ります。

\[ \text{remainder} = x - \operatorname{trunc}(x/y) \times y \]

MQL5公式のMathModでは、余りの符号は割られる側と同じになり、絶対値は除数より小さくなると説明されています。そこで、正負を組み合わせた4ケースを照合しました。

べき乗は整数指数だけに限定し、指数の各ビットを見ながら二乗を繰り返す方法で実装しています。

MQL
while(remaining > 0)
{
   if((remaining & 1) != 0)
      result *= factor;
   factor *= factor;
   remaining >>= 1;
}

この自作版は2^102^-3(-2)^35^0MathPow()と比較します。小数指数や非常に大きな指数まで標準関数と同じにする実装ではありません。

丸めについても、MathRound()が最も近い整数を返す仕様に合わせ、正数はfloor(x + 0.5)、負数はceil(x - 0.5)として3ケースを照合しました。


口座種別はAccountInfoIntegerで直接読む

原典のサンプルは、Windows APIで親ウィンドウを探し、タイトル文字列から口座情報を切り出していました。この方法には、少なくとも次の依存があります。

  • Windowsのウィンドウ構造
  • ターミナルのタイトル形式
  • 文字列中の区切り位置
  • DLL呼び出しの許可
  • 32bit・64bitや文字コードの違い

MQL5では、AccountInfoIntegerACCOUNT_TRADE_MODEを渡すと口座種別を取得できます。

MQL
const ENUM_ACCOUNT_TRADE_MODE trade_mode =
   (ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);

const bool is_demo =
   trade_mode == ACCOUNT_TRADE_MODE_DEMO;
const bool is_contest =
   trade_mode == ACCOUNT_TRADE_MODE_CONTEST;
const bool is_real =
   trade_mode == ACCOUNT_TRADE_MODE_REAL;

Account Propertiesで定義されている種別は、デモ、コンテスト、リアルの三つです。文字列の一部が偶然一致したかではなく、列挙値そのものを比較できます。

配布インジケーターは三つのフラグのうち一つだけが真になることも確認します。実機ではデモ口座だったため、demo=1contest=0real=0となりました。


取得できる情報と、表示してよい情報は別

ACCOUNT_LOGINを指定すると、口座番号もlongとして取得できます。しかし、取得できるからといって記事画像やログへ出す必要はありません。

今回の配布版は、内部で次の二点だけを検証します。

  • 値が0より大きく、ログイン情報が存在する
  • 5回連続で読み、口座種別とログイン値が変わらない

公開する表示は常にMASKEDです。診断バッファにも口座番号そのものは入れず、「値が存在したか」を1または0で返します。

MQL
string SafeLoginText()
{
   return "MASKED";
}

さらに、公開用文字列に数字が一つも含まれないことをコード側で検査しました。末尾数桁を見せる方式もありますが、この記事の目的には不要なので、全部を隠しています。


DLLを使えることと、使う必要があることは違う

MQL5の#importは、EX5やDLLの関数を呼び出す正式な仕組みです。DLLがすべて悪いわけではありません。

ただし、公式リファレンスにも、DLL側の関数はコンパイラが渡した引数の妥当性を検証できないため、宣言を正確に合わせる必要があると記載されています。また、ストラテジーテスターのUsing DLLsでは、DLLを必要とする第三者製プログラムを使う際のリスクへ注意を促しています。

今回の専用MT5はDLL許可を無効にした状態でした。それでも口座種別判定、口座情報の安定読取、数値関数の検証、画面表示はすべて成功しています。

判断基準は単純です。

  • MQL5の標準APIで取れる情報は標準APIを使う
  • DLLは標準APIで表現できない必要性があるときだけ検討する
  • DLLを使う場合は、権限、配布元、引数型、失敗時の動作を確認する

32ケースと13本の診断バッファを照合する

数値関数は、正数だけでなく負数、ゼロ、同値、負の除数、負の指数を含む32ケースで標準関数と比較しました。

自作関数 ケース数 主な入力
MyMathAbs 3 -12.507.25
MyMathCeil 5 -2.8-2.002.22.8
MyMathFloor 5 -2.8-2.002.22.8
MyMathMax 4 正数、負数、ゼロ、同値
MyMathMin 4 正数、負数、ゼロ、同値
TryMyMathMod 4 被除数と除数の正負
TryMyMathPowInteger 4 正負の底、正負・ゼロの指数
MyMathRound 3 1.41.5-1.5

診断用の13バッファは次の内容です。

  1. 全体合格フラグ
  2. 口座種別の列挙値
  3. デモ口座フラグ
  4. コンテスト口座フラグ
  5. リアル口座フラグ
  6. ログイン情報の存在フラグ
  7. 数値関数の合格数
  8. 数値関数の総数
  9. 口座情報の安定読取合格数
  10. 公開文字列のプライバシー合格フラグ
  11. ターミナルのDLL許可状態
  12. ターミナルのビルド番号
  13. パネル用オブジェクト数

検証EAは13本をCopyBuffer()で1件ずつ読み、現在のACCOUNT_TRADE_MODE、ログイン情報の存在、DLL許可状態、ビルド番号と独立に照合しました。口座番号そのものは検証ログへ出していません。

検証項目 結果
配布インジケーターのコンパイル 0エラー・0警告
検証EAのコンパイル 0エラー・0警告
MetaTrader 5 build 5836
実機の口座種別 デモ
口座種別フラグ 1つだけ有効
口座情報の連続読取 5 / 5一致
数値関数 32 / 32一致
ログイン情報 存在のみ確認
公開文字列 口座番号の数字なし
DLL許可 無効
DLLへの依存 なし
診断バッファ 13本一致
パネルオブジェクト 11個一致
実画面キャプチャー 成功
売買注文 なし
外部ファイルの作成・更新 なし

ダウンロードと使い方

42_Native_Account_API_Audit_v1_00.mq5 をダウンロード

MT5のIndicatorsへ保存してコンパイルし、任意のチャートへ適用してください。

パネルには口座種別、三つの種別フラグ、口座情報の安定読取、数値関数32ケース、公開文字列のプライバシー検査、DLL許可状態を表示します。口座番号、名義、サーバー名、残高は表示しません。


使えないこと・注意点

  • 自作した数値関数は学習用です。標準関数の完全な代替ではありません。
  • 自作MathPowは整数指数だけを対象にしています。
  • 自作MathModは商をlongへ安全に変換できる小さな入力で検証しています。
  • NaN、無限大、longの範囲外となる入力は検証対象外です。
  • ACCOUNT_TRADE_MODEは口座の種別であり、売買可能かどうかを示す値ではありません。
  • DLL許可状態が有効でも、そのDLLが安全であることを意味しません。
  • 口座番号、名義、サーバー名などを公開ログへ出さないでください。
  • 売買ロジックはなく、取引成績を評価するものではありません。

ロジック評価の結論

標準関数を自分で書き直す作業は、型変換、丸め、符号、入力範囲を考える良い練習になります。短いMathAbsから始めても、剰余やべき乗へ進むと仕様を決める必要があることが見えてきます。

一方、口座種別や口座番号のような環境情報は、標準APIがあるなら再発明しない方が堅実です。ウィンドウタイトルを解析する方法は、表示形式とOSの都合をアプリの契約だと思い込むことになるからです。

今回の移植で残したい考え方は、「書き直せるか試す好奇心」と「本番では最も狭く安定したAPIを選ぶ判断」を分けることです。そして、取得できる情報より、公開してよい情報の方を少なく保つ。それが現在のMQL5では、いちばん実用的な続きになりました。


前後の記事

前: 【移植#41】「+」なしで整数を足す — ビット演算を境界値まで検証する

— SPONSORED —