目的
C#とMetaTraderでデータのやり取りをして、トレードパネルを作る。
前提条件
(おさらい)データのやり取りに関する実現方法について
データのやり取りに関する実現方法については,主に3種類あると考えられます。
- 共有メモリを使用する方法
- ソケット通信による方法
- ファイルによる方法
恐らく3番目が一番実装しやすいのではないでしょうか。
ただし,3番目の場合,ファイルアクセスのルールを決めないといけないため,少しコードの工夫が必要です。
共有メモリを使ってトレードパネルを実装していきたいと思います!!!
画面構成
あとはどんだけ作りこむかだけなので、実装次第でなんとでもなります。
GitHubに置いてあるのを一番下のリンクに貼りますが、MQL4ファイルがどっからか持ってきたやつのままで、このままだとC#と全然つながりません。(だれもpull requestとかissue上げてくれなかったのはこのせい?と勝手に思っている!!!)
C#
前提条件の記事にあるように
//共有メモリにアクセスするためのメンバ
MemoryMappedFile share_mem;
MemoryMappedFile shareMemOrder;
//MT4->C#/C#->MT4の区別をつけるためのタグ
String pullTAG = "mtexe";
String pushTAG = "exemt";
が大事だと思ってます。
このほかThreadingTimerを使って、200msec毎にMT4から新しいメッセージが来ていないかチェックしています。
Windowがロードされたタイミングで、MT4が起動しているか確認します。
一応、MT4側からは、自分の口座情報的(通貨ペアなど)なものを共有メモリに既に書き込んで置いてあるイメージです。
C#側からこの口座情報的なものを最初に読みます。
private void Window_Loaded(object sender, RoutedEventArgs e)
{
orderFlag = false;
mt4Status.Text = "未連携";
Trace.WriteLine("mtexe:" + getMemorryString(pullTAG) + ":");
Trace.WriteLine(getMemorryString(pullTAG+".array"));
String getSymbol = getMemorryString("mtexe").Trim().Replace("\0", "");
share_mem = MemoryMappedFile.CreateNew(pushTAG+".symbol", 256, MemoryMappedFileAccess.ReadWriteExecute);
shareMemOrder
= MemoryMappedFile.CreateOrOpen(pushTAG+".order", 256, MemoryMappedFileAccess.ReadWriteExecute);
//シンボルがあればMT4との連携ができているものとし、
//定期実行用のThreadingTimerを動かす。
if (getSymbol != null && getSymbol.Length > 0)
{
timerDelegate = new TimerCallback(requestMTStatus);
timer = new Timer(timerDelegate, null, 0, 200);
statusBorder.Background = Brushes.LightGreen;
mt4Status.Text = "連携済み";
}
if (getMemorryString(pullTAG+ ".array") != null && getMemorryString(pullTAG +".array").Length > 0)
{
int selectedItem = 0;
int i = 0;
String[] sep = { "," };
String[] f = getMemorryString(pullTAG+".array").Split(sep, StringSplitOptions.RemoveEmptyEntries);
Trace.WriteLine("\r\nMT4通貨:" + getSymbol);
foreach (String str in f)
{
if (str.IndexOf(getSymbol) > -1)
{
selectedItem = i;
}
else
{
i++;
}
comboBox.Items.Add(str);
}
//Trace.WriteLine("MT4側の選択されている通貨は?" + selectedItem);
comboBox.SelectedItem = selectedItem;
comboBox.Text = getSymbol;
}
}
次に定期実行されるrequestMTStatusですが、requestMTStatus内では、MT4側から流れてくるであろうBidとAskの価格を表示させるようにします。
スプレッドもついでに表示させます。
private void requestMTStatus(object state)
{
this.Dispatcher.Invoke(() =>
{
try
{
//
String orderEnable = getMemorryString(pullTAG + ".order");
orderEnable = orderEnable.Replace("\0", "");
if (orderEnable.Length > 0)
{
if (orderFlag)
{
Trace.WriteLine("o:" + orderEnable);
MemoryMappedViewAccessor accessor = shareMemOrder.CreateViewAccessor();
// sellは1
// Write data to shared memory
string orderStr = "";
char[] data = orderStr.ToCharArray();
accessor.Write(0, data.Length);
accessor.WriteArray<char>(0, data, 0, data.Length);
// Dispose accessor
accessor.Dispose();
orderFlag = !orderFlag;
}
}
String val = getMemorryString(pullTAG+".value");
//Trace.WriteLine(val);
textBlock.Text = val;
String[] sep = { "," };
String[] sep2 = { "." };
String[] str = val.Split(sep, StringSplitOptions.RemoveEmptyEntries);
//Trace.WriteLine(str[0]+","+str[1]);
String[] bid = str[0].Split(sep2, StringSplitOptions.RemoveEmptyEntries);
String[] ask = str[1].Split(sep2, StringSplitOptions.RemoveEmptyEntries);
int digits = int.Parse(str[2].Replace("\0", ""));
digits = digits - 3 < 0 ? 0 : digits - 3;
int index = str[0].IndexOf(".");
selltextBlock.Text = "";
Underline underline = new Underline();
Run run = new Run();
run.Text = "SELL\n";
run.Foreground = Brushes.White;
run.FontSize = 16;
underline.Inlines.Add(run);
underline.Foreground = Brushes.White;
this.selltextBlock.Inlines.Add(underline);
selltextBlock.TextAlignment = TextAlignment.Right;
this.selltextBlock.Inlines.Add(bid[0] + "." + bid[1].Substring(0, digits));
run = new Run();
run.Text = bid[1].Substring(digits, 2);
run.FontSize = 24;
this.selltextBlock.Inlines.Add(run);
//int qr = digits - 2;
this.selltextBlock.Inlines.Add(bid[1].Substring(digits + 2, 1));
sellBtn.Content = selltextBlock;
//buyの処理
buytextBlock.Text = "";
Underline underline2 = new Underline();
Run run2 = new Run();
run2.Text = "BUY\n";
run2.Foreground = Brushes.White;
run2.FontSize = 16;
underline2.Inlines.Add(run2);
underline2.Foreground = Brushes.White;
this.buytextBlock.Inlines.Add(underline2);
buytextBlock.TextAlignment = TextAlignment.Left;
this.buytextBlock.Inlines.Add(ask[0] + "." + ask[1].Substring(0, digits));
run2 = new Run();
run2.Text = ask[1].Substring(digits, 2);
run2.FontSize = 24;
this.buytextBlock.Inlines.Add(run2);
this.buytextBlock.Inlines.Add(ask[1].Substring(digits + 2, 1));
buyBtn.Content = buytextBlock;
spreadTbk.Text = "";
Run run3 = new Run();
run3.Text = "Spread\n" + str[3];
run3.FontSize = 18;
this.spreadTbk.Inlines.Add(run3);
this.spreadTbk.TextAlignment = TextAlignment.Center;
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
});
}
あとは、BUYボタン押したときやSELLボタン押したときの処理をMT4側に流してあげれば良いです。
MQL側
ソースコード探してます。
///ソース見つかったら更新します!!!
完成品
GitHubにトレードパネルがあるので、みんなで改良していきましょう!
REFERENCEs
さいごに
投資は自己責任!
カレンダー参加者募集してます!
Have a good MQL Life!!!