Skip to content

Commit 6dbeca8

Browse files
authored
First Commit
1 parent d647404 commit 6dbeca8

File tree

8 files changed

+957
-0
lines changed

8 files changed

+957
-0
lines changed

Form1.Designer.cs

Lines changed: 422 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Form1.cs

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
using MTsocketAPI.MT5;
2+
using ScottPlot;
3+
using ScottPlot.Plottable;
4+
5+
namespace MTsocketAPI_Chart
6+
{
7+
public partial class Form1 : Form
8+
{
9+
MTsocketAPI.MT5.Terminal mt5;
10+
FinancePlot? fnplot;
11+
CancellationTokenSource cts = new CancellationTokenSource();
12+
Thread? updateThread;
13+
14+
public Form1()
15+
{
16+
InitializeComponent();
17+
}
18+
19+
//private async void BeginWork()
20+
//{
21+
// while (true)
22+
// {
23+
// List<Position> result = await DoWork();
24+
25+
// dataGridView1.Rows.Clear();
26+
// foreach (var item in result)
27+
// dataGridView1.Rows.Add(item.SYMBOL, item.TICKET, item.OPEN_TIME, item.TYPE, item.VOLUME, item.PRICE_OPEN, item.SL, item.TP, item.SWAP, item.PROFIT);
28+
// dataGridView1.AutoResizeColumns();
29+
// }
30+
//}
31+
32+
//private async Task<List<Position>> DoWork()
33+
//{
34+
// List<Position> lst = new List<Position>();
35+
// await Task.Run(() =>
36+
// {
37+
// if (mt5 != null)
38+
// {
39+
// System.Threading.Thread.Sleep(1000);
40+
// lst = mt5.GetOpenedOrders();
41+
// }
42+
// });
43+
// return lst;
44+
45+
//}
46+
private void Form1_Load(object sender, EventArgs e)
47+
{
48+
try
49+
{
50+
//Configure datagridview
51+
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
52+
53+
//Configure formsPlot
54+
formsPlot1.Plot.Grid(false);
55+
formsPlot1.Plot.XAxis.DateTimeFormat(true);
56+
formsPlot1.Plot.RightAxis.Ticks(true);
57+
formsPlot1.Plot.RightAxis.TickLabelFormat("F5", false);
58+
formsPlot1.Plot.LeftAxis.Ticks(false);
59+
}
60+
catch (Exception ex)
61+
{
62+
MessageBox.Show("Error: " + ex.Message);
63+
}
64+
}
65+
66+
DateTime RoundDown(DateTime dt, TimeSpan d)
67+
{
68+
var delta = dt.Ticks % d.Ticks;
69+
return new DateTime(dt.Ticks - delta, dt.Kind);
70+
}
71+
72+
private void Mt5_OnPrice(object? sender, Quote e)
73+
{
74+
lock (this)
75+
{
76+
try
77+
{
78+
if (fnplot != null)
79+
{
80+
if (Convert.ToDateTime(e.TIME) >= fnplot.Last().DateTime.Add(fnplot.Last().TimeSpan))
81+
{
82+
//New Candle
83+
ScottPlot.OHLC candle = new OHLC(open: e.BID, high: e.BID, low: e.BID, close: e.BID, RoundDown(Convert.ToDateTime(e.TIME), fnplot.Last().TimeSpan), fnplot.Last().TimeSpan);
84+
fnplot.Add(candle);
85+
}
86+
else
87+
{
88+
//Update existing candle
89+
fnplot.Last().Close = e.BID;
90+
if (e.BID > fnplot.Last().High) { fnplot.Last().High = e.BID; }
91+
if (e.BID < fnplot.Last().Low) { fnplot.Last().Low = e.BID; }
92+
}
93+
94+
this.formsPlot1.Invoke((EventHandler)delegate
95+
{
96+
formsPlot1.Refresh();
97+
});
98+
}
99+
}
100+
catch (Exception)
101+
{
102+
103+
}
104+
}
105+
}
106+
107+
Terminal pos;
108+
void UpdateOrderList()
109+
{
110+
//Fill datagridview with opened orders from Metatrader
111+
try
112+
{
113+
if (pos == null)
114+
{
115+
pos = new Terminal();
116+
pos.Connect();
117+
}
118+
List<Position> lst = pos.GetOpenedOrders();
119+
if (lst.Count > 0)
120+
{
121+
this.dataGridView1.Invoke((EventHandler)delegate
122+
{
123+
dataGridView1.Rows.Clear();
124+
foreach (var item in lst)
125+
dataGridView1.Rows.Add(item.SYMBOL, item.TICKET, item.OPEN_TIME, item.TYPE, item.VOLUME, item.PRICE_OPEN, item.SL, item.TP, item.SWAP, item.PROFIT);
126+
dataGridView1.AutoResizeColumns();
127+
});
128+
}
129+
}
130+
catch (Exception)
131+
{
132+
133+
}
134+
}
135+
void UpdateOrderListLoop(CancellationTokenSource cancelTS)
136+
{
137+
do
138+
{
139+
System.Threading.Thread.Sleep(1000);
140+
if (cancelTS.IsCancellationRequested) return;
141+
UpdateOrderList();
142+
} while (true);
143+
}
144+
145+
TimeSpan TimeSpanFromTF(TimeFrame tf)
146+
{
147+
switch (tf)
148+
{
149+
case TimeFrame.PERIOD_M1: return TimeSpan.FromMinutes(1);
150+
case TimeFrame.PERIOD_M2: return TimeSpan.FromMinutes(2);
151+
case TimeFrame.PERIOD_M3: return TimeSpan.FromMinutes(3);
152+
case TimeFrame.PERIOD_M4: return TimeSpan.FromMinutes(4);
153+
case TimeFrame.PERIOD_M5: return TimeSpan.FromMinutes(5);
154+
case TimeFrame.PERIOD_M6: return TimeSpan.FromMinutes(6);
155+
case TimeFrame.PERIOD_M10: return TimeSpan.FromMinutes(10);
156+
case TimeFrame.PERIOD_M15: return TimeSpan.FromMinutes(15);
157+
case TimeFrame.PERIOD_M20: return TimeSpan.FromMinutes(20);
158+
case TimeFrame.PERIOD_M30: return TimeSpan.FromMinutes(30);
159+
case TimeFrame.PERIOD_H1: return TimeSpan.FromHours(1);
160+
case TimeFrame.PERIOD_H2: return TimeSpan.FromHours(2);
161+
case TimeFrame.PERIOD_H3: return TimeSpan.FromHours(3);
162+
case TimeFrame.PERIOD_H4: return TimeSpan.FromHours(4);
163+
case TimeFrame.PERIOD_H6: return TimeSpan.FromHours(6);
164+
case TimeFrame.PERIOD_H8: return TimeSpan.FromHours(8);
165+
case TimeFrame.PERIOD_H12: return TimeSpan.FromHours(12);
166+
case TimeFrame.PERIOD_D1: return TimeSpan.FromDays(1);
167+
case TimeFrame.PERIOD_W1: return TimeSpan.FromDays(7);
168+
case TimeFrame.PERIOD_MN1: return TimeSpan.FromDays(30);
169+
default: return TimeSpan.FromSeconds(0);
170+
}
171+
}
172+
173+
private void cmbSymbols_SelectedIndexChanged(object sender, EventArgs e)
174+
{
175+
UpdateChart();
176+
}
177+
178+
void UpdateChart()
179+
{
180+
try
181+
{
182+
formsPlot1.Plot.Clear();
183+
184+
List<ScottPlot.OHLC> prices = new List<ScottPlot.OHLC>();
185+
186+
TimeFrame tf = (TimeFrame)Enum.Parse(typeof(TimeFrame), cmbTimeframe.Text);
187+
188+
var rates = mt5.PriceHistory(cmbSymbols.Text, tf, DateTime.Now.AddHours(-12).AddMinutes(-TimeSpanFromTF(tf).TotalMinutes * 30), DateTime.Now.AddDays(1));
189+
190+
foreach (var item in rates)
191+
{
192+
ScottPlot.OHLC candle = new OHLC(open: item.OPEN, high: item.HIGH, low: item.LOW, close: item.CLOSE, Convert.ToDateTime(item.TIME), TimeSpanFromTF(tf));
193+
prices.Add(candle);
194+
}
195+
196+
prices.Reverse();
197+
198+
fnplot = formsPlot1.Plot.AddCandlesticks(prices.ToArray());
199+
fnplot.YAxisIndex = formsPlot1.Plot.RightAxis.AxisIndex;
200+
201+
mt5.TrackPrices(new List<string>() { cmbSymbols.Text });
202+
203+
formsPlot1.Plot.AxisAuto();
204+
formsPlot1.Refresh();
205+
}
206+
catch (Exception ex)
207+
{
208+
MessageBox.Show(ex.Message);
209+
}
210+
211+
}
212+
213+
private void btnBuy_Click(object sender, EventArgs e)
214+
{
215+
try
216+
{
217+
TradeResult res = mt5.SendOrder(cmbSymbols.Text, (double)nVolume.Value, OrderType.ORDER_TYPE_BUY);
218+
if (res != null) UpdateOrderList();
219+
220+
}
221+
catch (Exception ex)
222+
{
223+
MessageBox.Show(ex.Message);
224+
}
225+
226+
}
227+
228+
private void btnSell_Click(object sender, EventArgs e)
229+
{
230+
try
231+
{
232+
TradeResult res = mt5.SendOrder(cmbSymbols.Text, (double)nVolume.Value, OrderType.ORDER_TYPE_SELL);
233+
if (res != null) UpdateOrderList();
234+
}
235+
catch (Exception ex)
236+
{
237+
MessageBox.Show(ex.Message);
238+
}
239+
240+
}
241+
242+
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
243+
{
244+
//If we click the datagridview close button then we close the position
245+
if (e.ColumnIndex == 10)
246+
{
247+
try
248+
{
249+
TradeResult res = mt5.OrderClose(Convert.ToInt64(dataGridView1.Rows[e.RowIndex].Cells[1].Value));
250+
if (res != null) if (res.TYPE == "FULLY_CLOSED") dataGridView1.Rows.RemoveAt(e.RowIndex);
251+
}
252+
catch (Exception ex)
253+
{
254+
MessageBox.Show(ex.Message);
255+
}
256+
257+
}
258+
}
259+
260+
private void cmbTimeframe_SelectedIndexChanged(object sender, EventArgs e)
261+
{
262+
if (cmbSymbols.Text.Length > 0) UpdateChart();
263+
}
264+
265+
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
266+
{
267+
if (cts != null) cts.Cancel();
268+
}
269+
270+
private void btnConnect_Click(object sender, EventArgs e)
271+
{
272+
try
273+
{
274+
mt5 = new Terminal();
275+
mt5.OnPrice += Mt5_OnPrice;
276+
mt5.Connect();
277+
}
278+
catch (Exception ex)
279+
{
280+
MessageBox.Show("Please check that MTsocketAPI is running. \nError: " + ex.Message);
281+
Application.Exit();
282+
return;
283+
}
284+
285+
//Fill TimeFrame list
286+
cmbTimeframe.DataSource = Enum.GetNames(typeof(TimeFrame));
287+
// cmbTimeframe.SelectedIndex = 4;
288+
289+
//Fill list with tradeable symbols
290+
cmbSymbols.DataSource = mt5.GetSymbolList().Where(x => x.TRADE_MODE != 0).Select(x => x.NAME).ToList();
291+
292+
btnConnect.Text = "Connected";
293+
btnBuy.Enabled = true;
294+
btnSell.Enabled = true;
295+
btnConnect.Enabled = false;
296+
297+
//Loop to retrieve opened positions from Metatrader
298+
updateThread = new Thread(() => UpdateOrderListLoop(cts));
299+
updateThread.IsBackground = true;
300+
updateThread.Start();
301+
}
302+
}
303+
}

0 commit comments

Comments
 (0)