*

[MT4からMT4へ]コピートレードシステムを作る,使い方,ダウンロード

ツールの特徴

MT4で自動売買ソフトを稼働させるトレーダーには、ときとしてトレードを別のMT4にコピーしたい場合があります。

例えば、デモ口座でしか稼働しないトライアル版のEAや、口座番号に制限がかかっているEA、FX業者に制約があるEAなどです。

今回は同一コンピューター上でのコピートレードシステムを作ります。

ネットを経由させないコピーツールとしてのメリットは、トレードの反映のスピードが早いこと、外部サーバーの構築、管理をする手間がないことが挙げられます。

逆にデメリットとしては、
”コピー元のMT4とコピー先のMT4が同一PC上になければならない”
ということです。

この使用場面はいろいろと限られてくると思いますが、基本的には個人利用を想定しています。

 

実装概要

さて、実際の仕様の話ですが、現在のMT4であればDLLや外部ソフトを使わずに、EA単体で稼働させることが可能です。(もちろんプログラマの腕ありきですが・・・)

これを実現させるコアとなるのが、ファイル関数のCOMMON機能です。

ファイル関数は、EA上のデータをMT4外のファイルに記録することができます。

MT4のターミナル上にデータを保存するグローバル変数はそれぞれのMT4上に記録されますが、
ファイル関数はCOMMON指定することで、より上位のフォルダにデータを保存することが可能です。

それにより、異なるFX業者のMT4同士でデータのやりとりが可能になります。

データ格納のアクセス範囲としては、
ファイル関数(COMMON)>ファイル関数(通常)>グローバル変数(外域変数)>PUBLIC変数>ローカル変数
といった感じです。

右に行くほどデータにアクセスする権限が厳しくなり、外側から参照・書き込みできなくなります。

逆に、左になればなるほど、長期の間データを保存できます。
頻繁に出し入れするデータはなるべく短期型の格納方式を使ってメモリの消費を減らします。

MQLを長年いじったことがある方でもファイル関数を触る機会というのは、そう多くはないと思います。

用途としては、
・コピートレード
・アービトラージ
・外部ソフトを使った分析(人工知能とか)
に限られてくるので、

一般的な自動売買ソフトを開発しているだけではお目にかかることはないでしょう。

 

全体のタスク

全体的にやるべきタスクは下記になります。
■コピー元(配信側)
・オーダーをファイル関数でファイルに記録する

■コピー先(受信側)
・ファイル関数でトレードデータを引っ張ってくる
・引っ張て来たデータを現在のポジション情報と照らし合わせる
・照らし合わせた内容に従ってエントリーor決済する

 

MT4の注意すべき仕様

コピーツールを作る前に、MT4の仕様上の話をしなくてはなりません。

複数のMT4業者を利用したことがある方はご存じかと思いますが、業者によって通貨ペアの名称が若干違います。

ある業者では、USDJPY、ある業者では、USDJPY-m
またある業者は、USDJPY- …

と通貨ペアの後(サフィックス)に変な記号を勝手につけられることがあります。

これをちゃんと処理しないとバグに繋がります。

 

トレードデータを送信する際にはこれらの邪魔な記号を消して、6文字に統一すると処理が楽になります。

これは、文字列関数を使えば一発です。(PHPほど便利ではありませんが)

 

StringSubstrは指定文字列の指定番号以降の文字列を抽出することができるので、適当にExなどの変数を文字列型で宣言して、横に置いておきましょう。

データをやり取りする際には、このExを外して統一し、
オーダーを出す際には再び必要になります。(あとでくっつけます)

ストップレベルによるバグの回避

また業者によって変わってくるものとして、ストップレベルがあります。

ストップレベルとは、予約注文を出す際に最も近くに出せるレートの幅のことです。

業者としては予約注文(リミットオーダー、ストップオーダー)は、現在レートからある程度離れたところに置いてほしいわけですが、その最小許容幅がストップレベルです。

が、しかし、今回はレートの厳密性よりも、スピードを重視したコピートレードシステムを開発したいと思いますので、すべて成行注文でオーダーします。(トレードをコピーする側のMT4の話)

もちろん、コピー元のトレードは成行以外で自由にやっていただいてOKです。

また、スリッページもあまり狭くすると、リクオートが多発してエントリーしなくなるので、なるべくデフォルトは広めにしましょう。

為替以外のシンボル(ゴールド、インデックス、米、石油など)は、FX業者によって名前が全然違ったり、そもそもチャートがないこともあるので、今回は為替だけを考えます。

 

コピー元のプログラムを作る

まずは、コピー元のプログラムを作ります。トレードを受信する側よりもかなり簡単です。

コピー先に送る情報として最低限必要なのは、通貨ペア、売り買いの方向、オーダーを識別するためのチケットナンバーです。

この三つがあれば、とりあえずコピーは可能です。
ファイル関数は文字列型でしか格納できないので、これらを一つの情報にまとめます。

チケット番号:通貨ペア(6文字):売買@

で一つのオーダーの情報にします。
情報を区切る記号(:@)はなんでもOKです。何ならJSON形式チックの方が分かりやすい方もいるかもしれません。

オーダーが複数になった場合には、
チケット番号:通貨ペア(6文字):売買@チケット番号:通貨ペア(6文字):売買@…
という風にどんどん連結していきます。

 

あとはこの関数が吐き出すトレード情報の文字列をファイル関数でファイルに書き込みます。
ファイル名はなんでもOKです。

ここではCoypingTradingData.txtとしています。

ただし、ファイル名に変な記号(カンマなど)を入れると、OSが変な拡張子として認識したりするので、特殊記号はいれないでください。

 

ファイル関数の使い方

ファイル関数は通常の変数などと違って、
”○○という名前のファイルを(書き込み専用or読み込み専用)開きます”と宣言します。 FileOpen
次に、
”さっき指定したファイルに書き込みますor読み込みます” FileWrite, FileRead
最後に、
”今開いているファイルを閉じます” FileClose
という手順を踏まなければなりません。

 

ファイル関数はMT4ターミナルの外部フォルダにアクセスするので、PCの状態によってはアクセスに失敗することがあります。(メモリがいっぱいとか、ビジー状態とか)そのため、成功するまで最大30回繰り返す仕様にしています。

また、コピー元がファイルに書き込みをするタイミングと受信側ファイルを読み込むタイミングが重なると、Windowsの仕様上例外処理が必要になります。(対象のファイルに対して読み込みと書き込みを同時に行うことはできない。)

【追記】ここの処理は後の記事でwhile文からfor文に書き換えています。あとスリープも入れています。

一応MQLリファレンスにはFILE_SHARE_WRITE, FILE_SHARE_READという指定もあるのですが、なぜか上手く書き込みができなかったので、通常版で記述しています。

ここで宣言していない変数は、あとでコードをまとめたときに別の場所で宣言しているので、コピペする際には全体のコードから取得してください。

ここで一番重要なのはファイル関数を使う際にFILE_COMMONを指定することです。これを入れることでフォルダアクセスが一つ上層になり、ほかのMT4からもアクセス可能な領域にデータが保存されます。

この保存場所は「C:\Users\AppData\Roaming\MetaQuotes\Terminal\Common\Files」です。

もしこのディレクトリの書き込み権限がない場合はエラーになりますので、書き込み権限を与えておいてください。(デフォルトでは通常書き込みOKになっているはずです。)

 

コピー先:受信側のコードを書く

コピー先(受信側)のコードに入ります。

コピー先でまずやらなくてはならないことは、ファイル関数でファイルからトレード情報を引っ張ってくることです。

【追記】while文をfor文に直しています。->OnTimer使えばいいんじゃね?

FILE_READを使えば、ファイルの情報を取得することができます。ここらへんはヘルプでもフォーラムでも載っているので、詳しくはそちらを見てください。

この関数が吐き出す情報は、
チケット番号:通貨ペア(6文字):売買方向@…
となっているので、

この情報を扱いやすいように分割しなければなりません。

FileDataという変数にとりあえずこの文字列を格納し、
文字列関数を使ってそれぞれ分割した文字列を変数に入れます。

 

MQL4はMQL5と違って構造体は使えないので、OrderData_ticketのような変数名で代用しています。
【追記】バージョンアップでMQL4でも構造体が使えるようになりました。

for文の100というのは「配信元が100以上のポジションを同時に保有しないという前提の数字」です。
文字列の検索が終わり次第、breakするので、実際に100回計算することはないと思います。

 

StringReplaceとその使い方

StringReplace関数は、特定の文字列の検索文字列を別の文字列に置き換えます。

例えば、
string Moji = “あいうえお”;
StringRelace(Moji,”あ”,”か”);
とすれば、

Moji == “かいうえお”

となるように、一部だけを置換することができます。

ここら辺はコードを読んで理解するよりも自分で考えた方が早いと思います。
要するに、
1124310:USDJPY:0@1123311:EURUSD:0@1123412:GBPUSD:0@1123413:AUDJPY:0@1123414:CADJPY:0@1123415:USDJPY:1@…
のような形でデータが並んでいるので、それぞれデータごとに変数に格納できればOKです。

これでざっくり、コピーするべきトレードの情報が取得できたので、次は「そのトレード情報を現在のトレード状態と照らし合わせる」箇所に入ります。

 

ポジションを照らし合わせる

取得したコピー元のトレード情報を、現在のトレード状態と照らし合わせる作業をします。

最も容易に想定されるバグとして、何度も同じポジションを取ったり決済したりを繰り返す、というものがあります。

これを解消するには、コピー先のオーダーの履歴に、すでにそのオーダーを取得したことがあるかどうかを調べる作業が必要です。

まだオーダーをコーディングしていませんが、受信側がオーダーをコピーしてポジションを取得する際に、そのオーダーのコメントに親のオーダーのチケット番号を入れます。

受信側が持っているオーダーのコメント と 配信側が持っているオーダーのチケット番号が一致していれば、
それはコピートレードで対応されたオーダーということになります。

(もっと良い関数名があればなぁ….)

【追記】後の記事では、コメントがFX業者によって勝手に編集される可能性を考慮して、
受信側のオーダーのコメントに配信側のチケット番号を入れるのではなく、
受信側のオーダーのマジックナンバーに配信側のチケット番号を入れています。

MQL4ではOrderSelectの際にMODE_HISOTRYを選択すると、決済済み、削除済みのオーダーを参照できます。

ただし、参照できる決済済み削除済みのオーダーは、MT4で表示されている履歴に依存するので、表示されている履歴が短い場合は、その分しか参照できません。

逆に全履歴がターミナル上で表示されている場合には、全履歴を取得することができます。
(今後のアップデートで変わるかもしれませんね。)

今回のコピートレードでは、コピーしたオーダーのコメントに、コピー元のチケット番号を入れる仕様にしました。

これによって、そのオーダーを過去にコピーしたことがあるのかどうかがわかります。

ちなみにMT5のネッティングアカウントの場合、オーダーコメントは比較的変わってしまうので、この手法は使えません。

 

オーダーの反映の状態は二つ

また、履歴上のオーダーの検索と同時に、コピーするべきトレードが現在コピーされているかどうかを検索する必要があります。

A・今、コピーするべきオーダーを持っているか調べる
B・過去にコピーするべきオーダーを持っていたか調べる

つまりこの2パターンです。

何を想定しているかというと、せっかくコピーしたトレードを裁量で決済されてしまったパターンです。

この場合、
もう一度ポジションを保有するか、それとも、トレーダーを信用してポジションを見送るか、の選択になるのですが、

せっかくトレーダーが何かの意図をもって決済したものを、間髪入れずに再ポジションしたら、クレームになりそうな気がします。

(もちろん誤って決済してしまった、という可能性もあると思います。)

しかし、過去のトレードも参照しておけばバグの可能性も減らせることができるので、今回は
「コピーしたポジションをトレーダーが裁量で決済した場合、再エントリーしない」仕様にします。

先ほどと同じように、今度は”現在もっているポジション”とコピー元のトレード情報を照らし合わせます。(照らし合わせる関数を作ります)

 

ちょっとややこしいかもしれませんが、やっていることは、
A・今、コピーするべきオーダーを持っているか調べる
B・過去にコピーするべきオーダーを持っていたか調べる
ことが必要で、そのための独自関数を作っただけです。

 

これまでで

「”過去に”コピー元のトレードを持っていたか調べる関数」と「”現在”コピー元のトレードを持っているか調べる関数」を作りました。

次はまず、それぞれのオーダー情報に対して、2つの関数を適応した際の組み合わせ4パターンを考えます。

オーダーの状態とパターンを調べる

[]パターン1
履歴にコピー元のトレードを持っていて、今は持っていない
→一度コピーはしたが裁量で決済された
→何もしない

[]パターン2
履歴にコピー元のトレードを持っていて、今も持っている
→ありえないパターン。(バグってる)
→何もしない

[]パターン3
履歴にコピー元のトレードがなく、今もない
→直ちにエントリー

[]パターン4
履歴にコピー元のトレーがないが、今現在持っている
→現在配信元がポジションを持っている
→何もしない

こうしてみると、実際にエントリー処理するべきなのはパターン3だけです。

決済処理は、
・受信側であるポジションを持っている
&&ファイル関数のデータにそのポジションに対応するオーダーがない
場合に決済します。

 

OrderSendはOnTicke(Start)内にべた書きでもいいですが、一応関数化して使いましょう。
ファイル関数から取得したトレード情報は文字列型なので、オーダー関数を使うには必要に応じて型を変換する必要があることに注意してください。

また、ファイル関数の通貨ペアは6文字ですが、実際にこれからエントリーしようとする通貨ペアはFX業者によって6文字ではないかもしれません。(ex. USDJPY^, USDJPY-m)

通貨ペアの文字列は完璧に一致していないと、オーダーがはじかれるため、あらかじめ保存したExを使い、文字列を連結しています。

 

決済する必要がある場合の決済処理

決済処理をします。
決済は「ファイル関数から取得した文字列に既定のトレード情報がなくなったら」決済とします。

勘の良い方はお気づきだと思いますが、これ、比較的危ういです。

というのもファイル関数がファイルの取得に失敗した場合、返り値が””になって、全決済してしまう可能性があるからです。(実際にはないです。)

これを回避するにはファイル関数の参照エラーをきっちり分けてやればOKです。

つまり、

パターン1:ファイル関数が正常に作動し、トレード情報がまだある状態
パターン2:ファイル関数が正常に作動し、トレード情報が消えた状態(決済)
パターン3:ファイル関数が失敗した場合(エラー)

パターン2とパターン3をちゃんと区別して書けば、万事OKです。

 

for文の中でOrderCloseを使うべきではない

話が少しそれるのですが、多くのEA開発代行業者が決済の際にfor文とOrdersTotal()を併用しています。
しかし、これってちょっと危うくないですか。

OrdersTotal()は現在保持しているオーダーの総数です。しかし、そのfor文の中でオーダーを決済してしまえば、OrdersTotalの数が変わります。

すると、for文が本来回るはずだった回数が減っていき、ポジションの番号の順番も変わる可能性があります。

おそらくこの記述でうまくいっているということはRefreshRate()するかOnTickから一度抜け出すまではOrdersTotalに入っている値が変わらないということを利用しているのでしょう。

しかしそれをわざわざするなら、決済するべきオーダーのチケット番号を一度保管して、for文を抜けた後に決済処理した方が安全です。

(と言いつつ、forとOrdersTotal使うんですけどね)

 

オーダーコメントはFX業者に勝手に書き換えられる

話を戻します。

注意するべきは、業者によってオーダーコメントに変な文字列が追加されるケースがあることです。

例えばオーダーコメントを”at12345678″としたつもりでも、
業者側が勝手に”at12345678tp”のようないらない文字列を付け足すことがあります。
(タイミングはまちまちです。)

そのため、
if(オーダーコメント==調べるチケット番号)
としてしまうと、正常に処理されない可能性があります。

ここはStringFindを使って、オーダーコメントの中に指定のチケット番号が”含まれているかどうか”
を使いましょう。

if(StringFind(オーダーコメント,調べるチケット番号,0) > 0 )
です。

検索文字列が見つかった場合、その文字列の位置を返すので、0以上の場合は合致ということになります。

もし最後まで合致しなければコピー元がポジションを決済したということになり、オーダーを決済します。

【追記】FX業者によっては決済後のオーダーコメントを”tp”だけにしたりする場合があるので、オーダーコメントではなくマジックナンバーに親のチケット番号を入れる仕様に変更しました。

これでコピーツールの全体が終わりました。次回は全体のコードとそれぞれのケースについて考察します。

 

コピートレードツールの仕様と使い方

現在のこれまでの仕様は下記のとおりです。
・DLL、外部ソフトは必要なし

・WEBサーバーを経由しないコピーツール
(同一コンピューター上に複数のコピー元とコピー先のMT4がなければならない)

・コピー元、コピー先に同じEAを一つずつセット
(パラメータでコピー元なのか、コピー先なのか指定)
↑普通だったらコピー元とコピー先のEAを分けるところなんでしょうけど、管理・編集がめんどいってことで合体させました。

・コピーは、レートよりもスピード重視(成行注文)

・コピーしたポジションを裁量決済した場合は、そのポジションはもうコピーされない

・コピー先のロットはパラメータで指定

・コピーするかどうかのタイミングはレート更新ベース
(レート更新が遅い時間帯・通貨ペアにEAをセットするとコピーが遅くなる)

・シンボル名が6文字でないGold,Silver,Oil,DAU,SP500,Coffeeなどはコピーできない
.

左が配信元(コピー元)、右が受信先(コピー先)
受信側のFX業者のレート更新が遅いので、反映に多少ラグが生じています。
.
ただし、改良の余地として、
・予約注文もコピーする
・SL,TPもコピーする
・配信元のロット比率も反映できるようにする
・コピーしようとしたタイミングで配信元が約定してから○○分以上経っているポジションはコピーしない
などの追加機能を付けても良いと思います。

 

バグ取りと改良

前回までに書いたコードでは、ごくまれに受信側が勝手にオーダーを決済してしまうというバグがありました。

これはファイルにアクセスする際に書き込みと読み込みがまったく同じタイミングで行われることで、読み込み結果が空白となり、それをEAが”ポジションなし”と判断していただめです。

OSの基幹部分の仕様については専門ではないので、この処理は比較的迷いました。

解決策1:書き込み、読み込みするファイルを複数に分けて、読み込み結果が同じ時だけ処理する

コーディングがめんどい、泥沼になるような気がする…

解決策2:書き込み、読み込みのタイミングをずらすために、ローカルタイムの秒数の剰余で実行をずらすとか

コピー処理が早いことが唯一のメリットなのに、それが失われると作る意味がない…

しかし、
とりあえず「ポジションがない状態」と「読み込みに失敗した状態」を区別して、
ファイルにアクセスできない場合にはSleepを入れてちょっと待つ仕様にしたところ、問題は解決しました。(観測時点では…)



(これは以前while文で書いていた、ファイルのトレードデータを読み込む関数です)

 

より高速にコピーさせる

また、やっぱりコピーの反映が遅いのが気になります。EAをセットしている通貨ペアチャートだけが低速で、他のチャートが頻繁に動いているとき、コピーの反映が遅いというのはやっぱり良くないと思います。

他のパターンとしても、コピーする通貨ペアが頻繁に動いていて、セットしている通貨ペアが鈍い可能性も考えられます。

そこで、OnTickの中に再帰的なループを入れました。
While文で延々とループするとメモリを圧迫したり、フリーズしたりする可能性があるのですが、妥協案として、
100回ループしてOnTickで再読み込みという手を取りました。



下記はその結果です。

前よりも反映速度が格段に上がっています。(ごく稀に遅くなる可能性は内包していますけどね。)

 

ダウンロード

下記はこのEAのダウンロードリンクです。
ダウンロード

二つのMT4にそれぞれこのEAをセットします。パラメータで受信か配信か切り替えます。

使い方

■パラメータ
IsSender: 配信元のMT4にセットする場合trueにします。
IsReceiver: 受信(コピー先)のMT4にセットする場合trueにします。
SendersAccountNumber: 受信(コピー先)のMT4にセットする場合、親のアカウント番号を入力します。
LotForReceiver: 受信(コピー先)のMT4にセットする場合、コピーするトレードのロットを入力します。
Slippage: 受信(コピー先)のMT4にセットする場合のトレードのスリッページです。

予約注文には対応していません。

※このEAを使って発生した損失などは一切責任を負いません。

 

リバーストレードできるようにする

つづいてはリバーストレードができるように改良します。
端的に言うと、コピー元と逆向きのポジションをコピーできるようにするということです。

と言っても、エントリー直前のエントリーの向きをパラメータによって場合分けすればいいだけなので、
てきとうにReverseModeという名前のパラメータを作って、



のようにすればOKです。(ニュアンスだけわかってもらえればOKです)

ちょっとわかりにくいかもしれませんが、左はFXPROのデモ口座で右はXMのデモ口座です。左でトレードを行うと右で逆向きのトレードをすぐさま入れています。

このソフトはこちらでプレゼントしていますので、欲しい方はこちらからどうぞ。

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。
 

この記事にコメントを残す

  1. かず より:

    スキャルピングでも早くコピートレードできるソフトを探してます。宜しくお願いしますm(__)m

  2. のり より:

    ダウンロードして使わせてもらいます。
    親のアカウント番号とは口座番号でしょうか?
    メールの場所がわからずこちらに質問しました。

Message

メールアドレスが公開されることはありません。

CAPTCHA


このコメントはWEBに公開されるので、問い合わせ等はメールなどでお願いします。

関連記事

[MT5からMT5へ]コピートレードシステム(EA) 使い方、無料ダウンロード

今回はMT5からMT5にトレードをコピーするツールの紹介です。 まずは様子をご覧ください。

記事を読む

[MT4からMT5へコピー]コピートレードツール(EA) 使い方、無料ダウンロード

今回はMT4からMT5にトレードをコピーするツールの紹介です。 まずは様子をご覧くださ

記事を読む

MQL&PHP サーバーを経由するコピートレードシステムを作るやり方

この記事ではWEBサーバーを経由するMT5のコピートレードシステムの作り方について解説します。MT5

記事を読む

汎用型MT4MT5間 コピートレードシステムEA 使い方 無料ダウンロード

これまで、MT4->MT4, MT4->MT5, MT5->MT4, MT5>

記事を読む

[MT5からMT4に]コピートレードツールEA 使い方、無料ダウンロード

まず、完成形をお見せします。 左がMT5で、右がMT4です。 ナビゲータの口座のとこ

記事を読む

 
  • (↑広告です。このサイトの管理者の運営ではありません)

     


  • 横瀬兼元(ペンネーム)です。

    プロフィール
    商材を買わせようとする偽者がいるらしいのでご注意ください。
    ツイッター始めました(イマサラー)
    https://twitter.com/FxantennaC
    (埋め込みするとページ表示が極端に遅くなるので、リンクでご容赦を)

Translate »
ページトップへ