【移植#49】DLL共有メモリをやめて共通ファイルへ — 2つのMT5価格を鮮度付きで比較する¶

この記事の3行まとめ
- 共有メモリDLLを使わず、同じPC上のMT5同士でBidとAsk、更新時刻を受け渡します
- 一時ファイルからの置換、送信元・銘柄・価格・未来時刻・鮮度の検査で書きかけや取り違えを拒否します
- 実機では正常データ15バッファに加え、期限切れ・未来時刻・送信元違い・銘柄違いの拒否を独立検証しました
今回の原典は「共有メモリで他業者の価格を読む」¶
投稿日順で次に当たる2010年2月7日の記事は、あるMT4で受け取ったGBPJPY価格を、別業者のMT4から参照する実験でした。
元記事「MT4他業者の価格を表示させる。/共有メモリの活用。」を読む
原典では、書込側と読取側がMemMap.dllを読み込み、同じタグ名で文字列を受け渡していました。ファイルを毎回読み書きする代わりに、Windowsの共有メモリを「メモリ上のファイル」のように使う発想です。
ただし、記事自身も用途には慎重でした。
- 業者間裁定が成立するかは分からない
- 複数価格からシステム異常を検出できるかも分からない
- まずは再利用できる道具として試した
今回も、この距離感を引き継ぎます。
作るのは、2つの価格を観測して差を表示する道具です。価格差が見えたことを、約定可能な利益や売買シグナルとは扱いません。
MT5標準の共通フォルダーへ置き換える¶
MQL5のFileOpen()へFILE_COMMONを指定すると、同じPC上のMT5端末が共通で使うファイル領域を読み書きできます。
FileOpen(
file_name,
FILE_READ | FILE_CSV | FILE_ANSI |
FILE_COMMON | FILE_SHARE_READ | FILE_SHARE_WRITE,
';',
CP_UTF8
);
通常のMQL5\Filesは端末ごとに分かれています。一方、FILE_COMMONはそのPC上の端末で共有されるため、ジャンクションや任意パスへのWindows API呼出しを用意しなくても、端末間連携を試せます。
今回の配布インジケーターは、次の2モードを持ちます。
| モード | 役割 |
|---|---|
PUBLISH | 現在のチャート銘柄のBid・Ask・時刻を共通ファイルへ書く |
COMPARE | 共通ファイルを読み、現在のチャート価格との差を表示する |
書込側と比較側へ同じインジケーターを入れ、モードだけを変えます。
DLLインポート、注文、ポジション変更、任意の絶対パスへの書込みはありません。
1つのチャンネルには1つの書込側だけを置く¶
初期チャンネル名は次のとおりです。
書込側は、この名前に対応する1個のCSVを更新します。比較側は同じチャンネル名を指定して読みます。
チャンネル名と送信元別名には、半角英数字、_、-だけを使えます。区切り文字やパス記号を入力できないようにし、意図しない別フォルダーや別形式を指さないようにしました。
1つのチャンネルへ複数の書込側を置くと、最後に置換した価格だけが残ります。複数の価格元を比べる場合は、価格元ごとにチャンネル名を分けてください。
書きかけのCSVを読ませない¶
書込側が最終ファイルを直接開いている途中に比較側が読むと、項目の一部しかない状態を拾う可能性があります。
そこで、書込側は次の順に更新します。
- 送信元別名を含む一時ファイルへ全項目を書く
FileFlush()して閉じるFileMove()で最終ファイルへ置換する
比較側に見せる名前へ移すのは、書込みが終わってからです。
これはOSや端末が落ちないことを保証する仕組みではありません。途中状態を見せにくくする更新手順です。移動に失敗した場合は成功扱いにせず、画面へREPLACE FAILEDを表示します。
11項目をひとかたまりで渡す¶
共通ファイルの1行には、次の項目をセミコロン区切りで保存します。
| # | 項目 | 役割 |
|---|---|---|
| 1 | マジック文字列 | このインジケーターの形式か確認 |
| 2 | 形式バージョン | 将来の項目変更を区別 |
| 3 | 送信元別名 | 想定した端末か確認 |
| 4 | 実際の銘柄名 | 画面表示と監査用 |
| 5 | 正規化した銘柄キー | 接頭辞・接尾辞が異なるFX銘柄を照合 |
| 6 | 小数桁 | 送信元価格の表示精度 |
| 7 | 送信元の1 point | 送信元スプレッドの単位 |
| 8 | Bid | 送信元の売値 |
| 9 | Ask | 送信元の買値 |
| 10 | Tick時刻(ミリ秒) | 価格自体の更新時刻 |
| 11 | 公開時刻(GMT秒) | ファイルの鮮度判定 |
SymbolInfoTick()でBid、Ask、Tick時刻を1回にまとめて取得します。BidとAskを別々のタイミングで読む構成にはしていません。
期限切れと未来時刻を拒否する¶
ファイルが読めても、新しい価格とは限りません。
端末が異常終了すると、最後のファイルが残る場合があります。古い価格を現在値として扱わないよう、比較側は公開時刻と現在のGMT時刻を照合します。
初期設定の有効期限は5秒です。
| 状態 | 判定 |
|---|---|
| 現在より2秒を超えて未来 | FUTURE TIMESTAMP |
| 現在より5秒を超えて古い | STALE |
| 範囲内 | 次の検査へ進む |
2秒の未来許容は、同じPC上でもイベント処理の境界で1秒程度ずれる可能性を考えたものです。20秒先のような値は受理しません。
書込側を正常に外したときは、初期設定で自分のチャンネルを削除します。ただし、端末やPCの強制終了では削除処理が走らないことがあります。その場合も鮮度検査が防波堤になります。
送信元と銘柄が違えば価格を表示しない¶
チャンネル名が合っているだけでは、取り違えを防ぎきれません。
比較側は、次の一致も確認します。
- ファイル内の送信元別名が
InpExpectedPeerAliasと一致する - ファイル内の銘柄キーが現在のチャート銘柄と一致する
- ファイル内の銘柄名を正規化し直しても同じキーになる
主要FX通貨では、EURUSDの前後にブローカー固有の文字が付いていても、通貨ペア部分を探してEURUSDへそろえます。これにより、たとえばEURUSDとEURUSD.aのような違いを吸収できます。
一方、送信元別名は暗号学的な認証ではありません。共通ファイル領域を読み書きできる別プログラムからの改変を防ぐ仕組みではなく、設定ミスによる取り違えを検出するための印です。
口座番号、口座名、サーバー名、認証情報はファイルへ書きません。
価格差は比較側のpoint単位で表示する¶
中央価格は、BidとAskの平均です。
画面のMID DIFFは、次の式で表示します。
正なら送信元の中央価格が高く、負なら低い状態です。
5桁表示のFX通貨で+25.0 local pointsなら、価格差は2.5 pipsに相当します。
ただし、これは表示時点の気配値差です。次の要素は含みません。
- 実際に約定できる数量
- 約定遅延とスリッページ
- 手数料とスワップ
- 入出金や資金移動の制約
- 注文拒否、最小距離、取引時間
- 同時に両側を約定できる保証
この数値だけから業者間裁定の収益性は判断できません。
15バッファと4つの拒否ケースを独立検証した¶
画面が見えるだけでなく、配布インジケーターは15本の診断バッファを公開します。
- データが全検査に合格したか
- 実行モード
- 更新回数
- 公開からの経過秒数
- 送信元Bid
- 送信元Ask
- 比較側Bid
- 比較側Ask
- 中央価格差
- 送信元スプレッド
- 比較側スプレッド
- 状態コード
- 表示オブジェクト数
- 送信元Tick時刻
- 比較側Tick時刻
専用の検証EAは、配布インジケーターが読むものと同じ11項目形式を独立に書き、ファイルを読み戻してから各バッファと照合しました。
さらに正常データを表示する前に、次の4ケースを順番に投入しました。
| 異常データ | 期待する状態 | 結果 |
|---|---|---|
| 公開から20秒経過 | STALE | 拒否 |
| 公開時刻が20秒先 | FUTURE TIMESTAMP | 拒否 |
| 送信元別名が不一致 | SOURCE MISMATCH | 拒否 |
| 銘柄キーが不一致 | SYMBOL MISMATCH | 拒否 |
最後に正常データへ戻し、価格、経過秒数、価格差、スプレッド、Tick時刻、状態コード、12個の表示部品を照合してから画面を保存しています。
実行条件¶
| 項目 | 値 |
|---|---|
| MT5 Build | 5836 |
| 通貨・時間足 | EURUSD・H1 |
| モード | COMPARE |
| チャンネル | EURUSD_FEED_A |
| 期待する送信元 | PEER-A |
| 有効期限 | 5秒 |
| 検証用価格差 | 比較側より25 points高い |
検証結果¶
| 確認項目 | 結果 |
|---|---|
| 配布インジケーターのコンパイル | 0エラー・0警告 |
| 独立検証EAのコンパイル | 0エラー・0警告 |
| 正常データの形式・価格・時刻 | 一致 |
| 期限切れ | 拒否 |
| 未来時刻 | 拒否 |
| 送信元違い | 拒否 |
| 銘柄違い | 拒否 |
| 診断バッファ | 15本一致 |
| パネルオブジェクト | 12 |
| 実画面キャプチャー | 成功 |
| 注文・DLL呼出し | なし |
この実機検証は、1台の専用MT5で検証EAが価格ファイルを作り、配布インジケーターが比較側として読む方式です。2つの実ブローカーへ同時接続して、価格差や約定を検証したものではありません。
ダウンロードと使い方¶
49_Common_Quote_Bridge_v1_00.mq5 をダウンロード
同じPC上にある2つのMT5へ、このインジケーターを入れて使います。
書込側¶
- 価格を配信したい銘柄のチャートへ適用します
InpModeをPUBLISHにしますInpChannelへ専用のチャンネル名を設定しますInpSourceAliasへ個人情報を含まない別名を設定します
比較側¶
- 比較したい銘柄のチャートへ適用します
InpModeをCOMPAREにします- 書込側と同じ
InpChannelを設定します InpExpectedPeerAliasへ書込側の別名を設定します
主な入力値は次のとおりです。
| パラメーター | 初期値 | 役割 |
|---|---|---|
InpMode | COMPARE | 書込または比較 |
InpChannel | EURUSD_FEED_A | 価格を分けるチャンネル |
InpSourceAlias | LOCAL-A | 書込側の別名 |
InpExpectedPeerAlias | PEER-A | 比較側が受理する送信元 |
InpMaxAgeSeconds | 5 | 価格ファイルの有効期限 |
InpDeleteOwnFeedOnRemove | true | 書込側を正常に外したとき自分の価格を削除 |
InpShowPanel | true | 比較パネルを表示 |
書込側と比較側でチャンネル名や送信元別名が一致しない場合は、価格差を有効値として表示しません。
使えないこと・注意点¶
- 同じPCの共通ファイル領域を使います。別PC間やインターネット越しの配信機能ではありません。
- 共通ファイルは暗号化・署名されません。秘密情報や口座情報をチャンネル名、別名、ファイルへ入れないでください。
- 1チャンネルにつき書込側は1つにしてください。
- 端末の強制終了後はファイルが残ることがありますが、有効期限を超えた価格は拒否します。
- PC時刻や端末時刻が異常なら、鮮度判定も影響を受けます。
- 主要FX通貨の接頭辞・接尾辞は通貨ペア部分で照合しますが、独自銘柄名やCFDの別名対応を保証しません。
- 価格差はTick到着と1秒タイマーの時点差を含みます。完全な同時刻比較ではありません。
MID DIFFは比較側のpoint単位です。pipsへ読むときは小数桁を確認してください。- スプレッドは送信元と比較側で、それぞれ自分のpoint単位です。
- 表示値は注文可能性、約定価格、利益、異常検出を保証しません。
- このインジケーターは注文、変更、取消、ポジション管理を行いません。
- DLL、Windows API、名前付きパイプ、外部ネットワーク通信は使いません。
ロジック評価の結論¶
原典の共有メモリ実験は、「別々のMT4が持つ価格を、同じプログラムから見られるようにする」という発想を、少ない関数で形にしていました。メモリを使うため、作成元のDLLが外れれば内容も消えるという管理上の分かりやすさもありました。
今回の移植では、速度を最優先して共有メモリDLLを再現する代わりに、MT5標準の共通ファイル領域へ置き換えました。ファイルは残る可能性がありますが、公開時刻と有効期限を持たせることで、残った価格を現在値として扱わないようにしています。
また、「ファイルが読めた」と「比較に使ってよい」を分けました。形式、送信元、銘柄、価格、未来時刻、期限をすべて通ったときだけ、価格差を有効にします。
それでも、見えているのは気配値です。別業者との価格差が25 pointsあっても、その差を同時に約定できるとは限りません。
まず観測する。古い値や別銘柄を混ぜない。観測結果から、いきなり収益性を言い切らない。
共有メモリの実験から今も引き継げるのは、通信方式そのものより、この慎重な道具の作り方だと思います。
前後の記事¶
前: 【移植#48】アイコン改造をやめて端末識別バッジへ — 複数MT5を色と別名で見分ける