Files
mtapi/TestClients/MtApi5TestClient/ViewModel.cs
T

1038 lines
38 KiB
C#
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using MtApi5;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Threading.Tasks;
namespace MtApi5TestClient
{
public class ViewModel : INotifyPropertyChanged
{
#region Commands
public DelegateCommand ConnectCommand { get; private set; }
public DelegateCommand DisconnectCommand { get; private set; }
public DelegateCommand OrderSendCommand { get; private set; }
public DelegateCommand HistoryOrderGetIntegerCommand { get; private set; }
public DelegateCommand HistoryDealGetDoubleCommand { get; private set; }
public DelegateCommand HistoryDealGetIntegerCommand { get; private set; }
public DelegateCommand HistoryDealGetStringCommand { get; private set; }
public DelegateCommand HistoryDealMethodsCommand { get; private set; }
public DelegateCommand AccountInfoDoubleCommand { get; private set; }
public DelegateCommand AccountInfoIntegerCommand { get; private set; }
public DelegateCommand AccountInfoStringCommand { get; private set; }
public DelegateCommand CopyRatesCommand { get; private set; }
public DelegateCommand CopyTimesCommand { get; private set; }
public DelegateCommand CopyOpenCommand { get; private set; }
public DelegateCommand CopyHighCommand { get; private set; }
public DelegateCommand CopyLowCommand { get; private set; }
public DelegateCommand CopyCloseCommand { get; private set; }
public DelegateCommand CopyTickVolumeCommand { get; private set; }
public DelegateCommand CopyRealVolumeCommand { get; private set; }
public DelegateCommand CopySpreadCommand { get; private set; }
public DelegateCommand CopyTicksCommand { get; private set; }
public DelegateCommand SymbolsTotalCommand { get; private set; }
public DelegateCommand SymbolNameCommand { get; private set; }
public DelegateCommand SymbolSelectCommand { get; private set; }
public DelegateCommand SymbolIsSynchronizedCommand { get; private set; }
public DelegateCommand SymbolInfoDoubleCommand { get; private set; }
public DelegateCommand SymbolInfoIntegerCommand { get; private set; }
public DelegateCommand SymbolInfoStringCommand { get; private set; }
public DelegateCommand SymbolInfoTickCommand { get; private set; }
public DelegateCommand SymbolInfoSessionQuoteCommand { get; private set; }
public DelegateCommand SymbolInfoSessionTradeCommand { get; private set; }
public DelegateCommand MarketBookAddCommand { get; private set; }
public DelegateCommand MarketBookReleaseCommand { get; private set; }
public DelegateCommand MarketBookGetCommand { get; private set; }
public DelegateCommand PositionOpenCommand { get; private set; }
public DelegateCommand PrintCommand { get; private set; }
public DelegateCommand iCustomCommand { get; private set; }
#endregion
#region Properties
private Mt5ConnectionState _connectionState;
public Mt5ConnectionState ConnectionState
{
get { return _connectionState; }
set
{
_connectionState = value;
OnPropertyChanged("ConnectionState");
}
}
private string _connectionMessage;
public string ConnectionMessage
{
get { return _connectionMessage; }
set
{
_connectionMessage = value;
OnPropertyChanged("ConnectionMessage");
}
}
private string _host;
public string Host
{
get { return _host; }
set
{
_host = value;
OnPropertyChanged("Host");
}
}
private int _port;
public int Port
{
get { return _port; }
set
{
_port = value;
OnPropertyChanged("Port");
}
}
public ObservableCollection<QuoteViewModel> Quotes { get; } = new ObservableCollection<QuoteViewModel>();
private QuoteViewModel _selectedQuote;
public QuoteViewModel SelectedQuote
{
get { return _selectedQuote; }
set
{
_selectedQuote = value;
OnPropertyChanged("SelectedQuote");
OnSelectedQuoteChanged();
}
}
public ObservableCollection<string> History { get; } = new ObservableCollection<string>();
public ObservableCollection<MqlTradeRequestViewModel> TradeRequests { get; } = new ObservableCollection<MqlTradeRequestViewModel>();
private MqlTradeRequestViewModel _tradeRequest;
public MqlTradeRequestViewModel TradeRequest
{
get { return _tradeRequest; }
set
{
_tradeRequest = value;
OnPropertyChanged("TradeRequest");
}
}
public ENUM_ACCOUNT_INFO_DOUBLE AccountInfoDoublePropertyId { get; set; }
public ENUM_ACCOUNT_INFO_INTEGER AccountInfoIntegerPropertyId { get; set; }
public ENUM_ACCOUNT_INFO_STRING AccountInfoStringPropertyId { get; set; }
public TimeSeriesValueViewModel TimeSeriesValues { get; set; }
public ObservableCollection<string> TimeSeriesResults { get; } = new ObservableCollection<string>();
private string _messageText = "Print some text in MetaTrader expert console";
public string MessageText
{
get { return _messageText; }
set
{
_messageText = value;
OnPropertyChanged("MessageText");
}
}
#endregion
#region Public Methods
public ViewModel()
{
// Init MtApi client
_mtApiClient = new MtApi5Client();
_mtApiClient.ConnectionStateChanged += mMtApiClient_ConnectionStateChanged;
_mtApiClient.QuoteAdded += mMtApiClient_QuoteAdded;
_mtApiClient.QuoteRemoved += mMtApiClient_QuoteRemoved;
_mtApiClient.QuoteUpdated += mMtApiClient_QuoteUpdated;
_quotesMap = new Dictionary<string, QuoteViewModel>();
ConnectionState = _mtApiClient.ConnectionState;
ConnectionMessage = "Disconnected";
Port = 8228; //default local port
InitCommands();
var request = new MqlTradeRequest { Action = ENUM_TRADE_REQUEST_ACTIONS.TRADE_ACTION_DEAL
, Type = ENUM_ORDER_TYPE.ORDER_TYPE_BUY
, Volume = 0.1
, Comment = "Test Trade Request"
};
TradeRequest = new MqlTradeRequestViewModel(request);
TimeSeriesValues = new TimeSeriesValueViewModel { Count = 100 };
}
public void Close()
{
_mtApiClient.BeginDisconnect();
}
#endregion
#region Private Methods
private void InitCommands()
{
ConnectCommand = new DelegateCommand(ExecuteConnect, CanExecuteConnect);
DisconnectCommand = new DelegateCommand(ExecuteDisconnect, CanExecuteDisconnect);
OrderSendCommand = new DelegateCommand(ExecuteOrderSend);
HistoryOrderGetIntegerCommand = new DelegateCommand(ExecuteHistoryOrderGetInteger);
HistoryDealGetDoubleCommand = new DelegateCommand(ExecuteHistoryDealGetDouble);
HistoryDealGetIntegerCommand = new DelegateCommand(ExecuteHistoryDealGetInteger);
HistoryDealGetStringCommand = new DelegateCommand(ExecuteHistoryDealGetString);
HistoryDealMethodsCommand = new DelegateCommand(ExecuteHistoryDealMethods);
AccountInfoDoubleCommand = new DelegateCommand(ExecuteAccountInfoDouble);
AccountInfoIntegerCommand = new DelegateCommand(ExecuteAccountInfoInteger);
AccountInfoStringCommand = new DelegateCommand(ExecuteAccountInfoString);
CopyRatesCommand = new DelegateCommand(ExecuteCopyRates);
CopyTimesCommand = new DelegateCommand(ExecuteCopyTime);
CopyOpenCommand = new DelegateCommand(ExecuteCopyOpen);
CopyHighCommand = new DelegateCommand(ExecuteCopyHigh);
CopyLowCommand = new DelegateCommand(ExecuteCopyLow);
CopyCloseCommand = new DelegateCommand(ExecuteCopyClose);
CopyTickVolumeCommand = new DelegateCommand(ExecuteCopyTickVolume);
CopyRealVolumeCommand = new DelegateCommand(ExecuteCopyRealVolume);
CopySpreadCommand = new DelegateCommand(ExecuteCopySpread);
CopyTicksCommand = new DelegateCommand(ExecuteCopyTicks);
SymbolsTotalCommand = new DelegateCommand(ExecuteSymbolsTotal);
SymbolNameCommand = new DelegateCommand(ExecuteSymbolName);
SymbolSelectCommand = new DelegateCommand(ExecuteSymbolSelect);
SymbolIsSynchronizedCommand = new DelegateCommand(ExecuteSymbolIsSynchronized);
SymbolInfoDoubleCommand = new DelegateCommand(ExecuteSymbolInfoDouble);
SymbolInfoIntegerCommand = new DelegateCommand(ExecuteSymbolInfoInteger);
SymbolInfoStringCommand = new DelegateCommand(ExecuteSymbolInfoString);
SymbolInfoTickCommand = new DelegateCommand(ExecuteSymbolInfoTick);
SymbolInfoSessionQuoteCommand = new DelegateCommand(ExecuteSymbolInfoSessionQuote);
SymbolInfoSessionTradeCommand = new DelegateCommand(ExecuteSymbolInfoSessionTrade);
MarketBookAddCommand = new DelegateCommand(ExecuteMarketBookAdd);
MarketBookReleaseCommand = new DelegateCommand(ExecuteMarketBookRelease);
MarketBookGetCommand = new DelegateCommand(ExecuteMarketBookGet);
PositionOpenCommand = new DelegateCommand(ExecutePositionOpen);
PrintCommand = new DelegateCommand(ExecutePrint);
iCustomCommand = new DelegateCommand(ExecuteICustom);
}
private bool CanExecuteConnect(object o)
{
return ConnectionState == Mt5ConnectionState.Disconnected || ConnectionState == Mt5ConnectionState.Failed;
}
private void ExecuteConnect(object o)
{
if (string.IsNullOrEmpty(Host))
{
_mtApiClient.BeginConnect(Port);
}
else
{
_mtApiClient.BeginConnect(Host, Port);
}
}
private bool CanExecuteDisconnect(object o)
{
return ConnectionState == Mt5ConnectionState.Connected;
}
private void ExecuteDisconnect(object o)
{
_mtApiClient.BeginDisconnect();
}
private async void ExecuteOrderSend(object o)
{
var request = TradeRequest.GetMqlTradeRequest();
MqlTradeResult result = null;
var retVal = await Execute(() =>
{
var ok = _mtApiClient.OrderSend(request, out result);
return ok;
});
var message = retVal ? $"OrderSend excute successed. {MqlTradeResultToString(result)}" : $"OrderSend execute failed. {MqlTradeResultToString(result)}";
AddLog(message);
}
private async void ExecuteHistoryOrderGetInteger(object o)
{
const ulong ticket = 12345;
const ENUM_ORDER_PROPERTY_INTEGER propertyId = ENUM_ORDER_PROPERTY_INTEGER.ORDER_POSITION_ID;
var retVal = await Execute(() => _mtApiClient.HistoryOrderGetInteger(ticket, propertyId));
AddLog($"HistoryOrderGetInteger: {retVal}");
}
private async void ExecuteHistoryDealGetDouble(object o)
{
const ulong ticket = 12345;
const ENUM_DEAL_PROPERTY_DOUBLE propertyId = ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PROFIT;
var retVal = await Execute(() => _mtApiClient.HistoryDealGetDouble(ticket, propertyId));
AddLog($"HistoryDealGetDouble: {retVal}");
}
private async void ExecuteHistoryDealGetInteger(object o)
{
const ulong ticket = 12345;
const ENUM_DEAL_PROPERTY_INTEGER propertyId = ENUM_DEAL_PROPERTY_INTEGER.DEAL_TICKET;
var retVal = await Execute(() => _mtApiClient.HistoryDealGetInteger(ticket, propertyId));
AddLog($"HistoryDealGetInteger: {retVal}");
}
private async void ExecuteHistoryDealGetString(object o)
{
const ulong ticket = 12345;
const ENUM_DEAL_PROPERTY_STRING propertyId = ENUM_DEAL_PROPERTY_STRING.DEAL_SYMBOL;
var retVal = await Execute(() => _mtApiClient.HistoryDealGetString(ticket, propertyId));
AddLog($"HistoryDealGetString: {retVal}");
}
private async void ExecuteHistoryDealMethods(object o)
{
try
{
var posId = await Execute(() => _mtApiClient.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_IDENTIFIER)); // posId = 7247951
var history = await Execute(() => _mtApiClient.HistorySelectByPosition(posId)); // history = true
var historyDealsTotal = await Execute(() => _mtApiClient.HistoryDealsTotal()); // historyDealsCount = 4
var histDealTicket = await Execute(() => _mtApiClient.HistoryDealGetTicket(0)); // histDealTicket = 6632442
var histDealPrice = await Execute(() => _mtApiClient.HistoryDealGetDouble(histDealTicket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PRICE)); // Exception
}
catch (Exception ex)
{
// ex.Messsage = "Service connection failed! Ошибка сериализации параметра http://tempuri.org/:command. Сообщение InnerException было \"Тип \"MtApi5.ENUM_DEAL_PROPERTY_DOUBLE\" с именем контракта данных \"ENUM_DEAL_PROPERTY_DOUBLE:http://schemas.datacontract.org/2004/07/MtApi5\" не ожидается. Попробуйте использовать DataContractResolver, если вы используете DataContractSerializer, или добавьте любые статически неизвестные типы в список известных типов - например, используя атрибут KnownTypeAttribute или путем их добавления в список известных типов, передаваемый в сериализатор.\". Подробнее см. InnerException."
AddLog(ex.Message);
return;
}
AddLog("ExecuteHistoryDealMethods: success.");
}
private async void ExecuteAccountInfoDouble(object o)
{
var result = await Execute(() => _mtApiClient.AccountInfoDouble(AccountInfoDoublePropertyId));
var message = $"AccountInfoDouble: property_id = {AccountInfoDoublePropertyId}; result = {result}";
AddLog(message);
}
private async void ExecuteAccountInfoInteger(object o)
{
var result = await Execute(() => _mtApiClient.AccountInfoInteger(AccountInfoIntegerPropertyId));
var message = $"AccountInfoInteger: property_id = {AccountInfoDoublePropertyId}; result = {result}";
AddLog(message);
}
private async void ExecuteAccountInfoString(object o)
{
var result = await Execute(() => _mtApiClient.AccountInfoString(AccountInfoStringPropertyId));
var message = $"AccountInfoString: property_id = {AccountInfoDoublePropertyId}; result = {result}";
AddLog(message);
}
private async void ExecuteCopyTime(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
DateTime[] array;
var count = _mtApiClient.CopyTime(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyTime: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var time in result)
{
TimeSeriesResults.Add(time.ToString(CultureInfo.CurrentCulture));
}
});
AddLog("CopyTime: success");
}
private async void ExecuteCopyOpen(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
double[] array;
var count = _mtApiClient.CopyOpen(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyOpen: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var open in result)
{
TimeSeriesResults.Add(open.ToString(CultureInfo.CurrentCulture));
}
});
AddLog("CopyOpen: success");
}
private async void ExecuteCopyHigh(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
double[] array;
var count = _mtApiClient.CopyHigh(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyHigh: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var value in result)
{
TimeSeriesResults.Add(value.ToString(CultureInfo.CurrentCulture));
}
});
AddLog("CopyHigh: success");
}
private async void ExecuteCopyLow(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
double[] array;
var count = _mtApiClient.CopyLow(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyLow: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var value in result)
{
TimeSeriesResults.Add(value.ToString(CultureInfo.CurrentCulture));
}
});
AddLog("CopyLow: success");
}
private async void ExecuteCopyClose(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
double[] array;
var count = _mtApiClient.CopyClose(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame,
TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyClose: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var value in result)
{
TimeSeriesResults.Add(value.ToString(CultureInfo.CurrentCulture));
}
});
AddLog("CopyClose: success");
}
private async void ExecuteCopyRates(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
MqlRates[] array;
var count = _mtApiClient.CopyRates(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyRates: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var rates in result)
{
TimeSeriesResults.Add(
$"time={rates.time}; open={rates.open}; high={rates.high}; low={rates.low}; close={rates.close}; tick_volume={rates.tick_volume}; spread={rates.spread}; real_volume={rates.tick_volume}");
}
});
AddLog("CopyRates: success");
}
private async void ExecuteCopyTickVolume(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
long[] array;
var count = _mtApiClient.CopyTickVolume(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame,
TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyTickVolume: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var value in result)
{
TimeSeriesResults.Add(value.ToString());
}
});
AddLog("CopyTickVolume: success");
}
private async void ExecuteCopyRealVolume(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
long[] array;
var count = _mtApiClient.CopyRealVolume(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame,
TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopyRealVolume: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var value in result)
{
TimeSeriesResults.Add(value.ToString());
}
});
AddLog("CopyRealVolume: success");
}
private async void ExecuteCopySpread(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() =>
{
int[] array;
var count = _mtApiClient.CopySpread(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame,
TimeSeriesValues.StartPos, TimeSeriesValues.Count, out array);
return count > 0 ? array : null;
});
if (result == null)
{
AddLog("CopySpread: result is null");
return;
}
RunOnUiThread(() =>
{
foreach (var value in result)
{
TimeSeriesResults.Add(value.ToString());
}
});
AddLog("CopySpread: success");
}
private async void ExecuteCopyTicks(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
TimeSeriesResults.Clear();
var result = await Execute(() => _mtApiClient.CopyTicks(TimeSeriesValues.SymbolValue));
if (result == null)
{
AddLog("CopyTicks: result is null");
return;
}
AddLog("CopyTicks: success.");
RunOnUiThread(() =>
{
foreach (var v in result)
{
var tickStr = $"time = {v.time}, bid = {v.bid}, ask = {v.ask}, last = {v.last}, volume = {v.volume}";
TimeSeriesResults.Add(tickStr);
}
});
}
private async void ExecuteSymbolsTotal(object o)
{
var selectedCount = await Execute(() => _mtApiClient.SymbolsTotal(true));
AddLog($"SymbolsTotal(true) success, result = {selectedCount}");
var commonCount = await Execute(() => _mtApiClient.SymbolsTotal(false));
AddLog($"SymbolsTotal(false) success, result = {commonCount}");
}
private async void ExecuteSymbolName(object o)
{
var selectedSymbol = await Execute(() => _mtApiClient.SymbolName(5, true));
AddLog($"SymbolName(5, true) success, result = {selectedSymbol}");
var commonSymbol = await Execute(() => _mtApiClient.SymbolName(5, false));
AddLog($"SymbolName(5, false) success, result = {commonSymbol}");
}
private async void ExecuteSymbolSelect(object o)
{
var retVal = await Execute(() => _mtApiClient.SymbolSelect("AUDJPY", true));
AddLog("SymbolSelect(AUDJPY, true) success, result = " + retVal);
//var retVal1 = _mtApiClient.SymbolSelect("AUDJPY", false);
//AddLog("SymbolSelect(AUDJPY, false) success, result = " + retVal1);
}
private async void ExecuteSymbolIsSynchronized(object o)
{
var retVal = await Execute(() => _mtApiClient.SymbolIsSynchronized("EURUSD"));
AddLog("SymbolIsSynchronized(EURUSD): result = " + retVal);
}
private async void ExecuteSymbolInfoDouble(object o)
{
var retVal = await Execute(() => _mtApiClient.SymbolInfoDouble("EURUSD", ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID));
AddLog($"SymbolInfoDouble(EURUSD, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID): result = {retVal}");
}
private async void ExecuteSymbolInfoInteger(object o)
{
var retVal = await Execute(() => _mtApiClient.SymbolInfoInteger("EURUSD", ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD));
AddLog($"SymbolInfoInteger(EURUSD, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD): result = {retVal}");
}
private async void ExecuteSymbolInfoString(object o)
{
var retVal = await Execute(() => _mtApiClient.SymbolInfoString("EURUSD", ENUM_SYMBOL_INFO_STRING.SYMBOL_DESCRIPTION));
AddLog($"SymbolInfoString(EURUSD, ENUM_SYMBOL_INFO_STRING.SYMBOL_DESCRIPTION): result = {retVal}");
}
private async void ExecuteSymbolInfoTick(object o)
{
var result = await Execute(() =>
{
MqlTick tick;
var ok = _mtApiClient.SymbolInfoTick("EURUSD", out tick);
return ok ? tick : null;
});
if (result == null) return;
AddLog("SymbolInfoTick(EURUSD) success");
AddLog($"SymbolInfoTick(EURUSD) tick.time = {result.time}");
AddLog($"SymbolInfoTick(EURUSD) tick.bid = {result.bid}");
AddLog($"SymbolInfoTick(EURUSD) tick.ask = {result.ask}");
AddLog($"SymbolInfoTick(EURUSD) tick.last = {result.last}");
AddLog($"SymbolInfoTick(EURUSD) tick.volume = {result.volume}");
}
private async void ExecuteSymbolInfoSessionQuote(object o)
{
var retVal = await Execute(() =>
{
DateTime from;
DateTime to;
var ok = _mtApiClient.SymbolInfoSessionQuote("EURUSD", ENUM_DAY_OF_WEEK.MONDAY, 0, out from, out to);
if (ok)
{
AddLog($"SymbolInfoSessionQuote(EURUSD) from = {from}");
AddLog($"SymbolInfoSessionQuote(EURUSD) to = {to}");
}
return ok;
});
AddLog($"SymbolInfoSessionQuote(EURUSD): result = {retVal}");
}
private async void ExecuteSymbolInfoSessionTrade(object o)
{
var retVal = await Execute(() =>
{
DateTime from;
DateTime to;
var ok = _mtApiClient.SymbolInfoSessionTrade("EURUSD", ENUM_DAY_OF_WEEK.MONDAY, 0, out from, out to);
if (ok)
{
AddLog($"SymbolInfoSessionTrade(EURUSD) from = {from}");
AddLog($"SymbolInfoSessionTrade(EURUSD) to = {to}");
}
return ok;
});
AddLog("SymbolInfoSessionTrade(EURUSD): result = " + retVal);
}
private async void ExecuteMarketBookAdd(object o)
{
var retVal = await Execute(() => _mtApiClient.MarketBookAdd("CHFJPY"));
AddLog($"MarketBookAdd(CHFJPY): result = {retVal}");
}
private async void ExecuteMarketBookRelease(object o)
{
var retVal = await Execute(() => _mtApiClient.MarketBookRelease("CHFJPY"));
AddLog($"MarketBookRelease(CHFJPY): result = {retVal}");
}
private async void ExecuteMarketBookGet(object o)
{
var result = await Execute(() =>
{
MqlBookInfo[] book;
var ok = _mtApiClient.MarketBookGet("EURUSD", out book);
return ok ? book : null;
});
if (result == null)
{
AddLog("MarketBookGet(EURUSD): result is null");
return;
}
AddLog("MarketBookGet(EURUSD): success");
for (var i = 0; i < result.Length; i++)
{
AddLog($"MarketBookGet: book[{i}].price = {result[i].price}");
AddLog($"MarketBookGet: book[{i}].price = {result[i].volume}");
AddLog($"MarketBookGet: book[{i}].price = {result[i].type}");
}
}
private async void ExecutePositionOpen(object obj)
{
const string symbol = "EURUSD";
const ENUM_ORDER_TYPE orderType = ENUM_ORDER_TYPE.ORDER_TYPE_BUY;
const double volume = 0.1;
const double price = 1.18129;
const double sl = 1.1811;
const double tp = 1.1814;
const string comment = "Test PositionOpen";
MqlTradeResult tradeResult = null;
var retVal = await Execute (() => _mtApiClient.PositionOpen(symbol, orderType, volume, price, sl, tp, comment, out tradeResult));
AddLog($"PositionOpen: symbol EURUSD retVal = {retVal}, result = {tradeResult}");
}
private async void ExecutePrint(object obj)
{
var message = MessageText;
var retVal = await Execute(() => _mtApiClient.Print(message));
AddLog($"Print: message print in MetaTrader - {retVal}");
}
private async void ExecuteICustom(object o)
{
const string symbol = "EURUSD";
const ENUM_TIMEFRAMES timeframe = ENUM_TIMEFRAMES.PERIOD_H1;
const string name = @"Examples\Custom Moving Average";
int[] parameters = { 0, 21, (int)ENUM_APPLIED_PRICE.PRICE_CLOSE };
var retVal = await Execute(() => _mtApiClient.iCustom(symbol, timeframe, name, parameters));
AddLog($"Custom Moving Average: result - {retVal}");
}
private static void RunOnUiThread(Action action)
{
Application.Current?.Dispatcher.Invoke(action);
}
private static void RunOnUiThread<T>(Action<T> action, params object[] args)
{
Application.Current?.Dispatcher.Invoke(action, args);
}
private void mMtApiClient_QuoteUpdated(object sender, string symbol, double bid, double ask)
{
if (string.IsNullOrEmpty(symbol) == false)
{
if (_quotesMap.ContainsKey(symbol))
{
var qvm = _quotesMap[symbol];
qvm.Bid = bid;
qvm.Ask = ask;
}
if (string.Equals(symbol, TradeRequest.Symbol))
{
if (TradeRequest.Type == ENUM_ORDER_TYPE.ORDER_TYPE_BUY)
{
TradeRequest.Price = ask;
}
else if (TradeRequest.Type == ENUM_ORDER_TYPE.ORDER_TYPE_SELL)
{
TradeRequest.Price = bid;
}
}
}
}
private void mMtApiClient_QuoteRemoved(object sender, Mt5QuoteEventArgs e)
{
RunOnUiThread<Mt5Quote>(RemoveQuote, e.Quote);
}
private void mMtApiClient_QuoteAdded(object sender, Mt5QuoteEventArgs e)
{
RunOnUiThread<Mt5Quote>(AddQuote, e.Quote);
}
private void mMtApiClient_ConnectionStateChanged(object sender, Mt5ConnectionEventArgs e)
{
ConnectionState = e.Status;
ConnectionMessage = e.ConnectionMessage;
RunOnUiThread(ConnectCommand.RaiseCanExecuteChanged);
RunOnUiThread(DisconnectCommand.RaiseCanExecuteChanged);
switch (e.Status)
{
case Mt5ConnectionState.Connected:
RunOnUiThread(OnConnected);
break;
case Mt5ConnectionState.Disconnected:
RunOnUiThread(OnDisconnected);
break;
}
}
private void AddQuote(Mt5Quote quote)
{
if (quote == null)
return;
QuoteViewModel qvm;
if (_quotesMap.ContainsKey(quote.Instrument) == false)
{
qvm = new QuoteViewModel(quote.Instrument);
_quotesMap[quote.Instrument] = qvm;
Quotes.Add(qvm);
}
else
{
qvm = _quotesMap[quote.Instrument];
}
qvm.FeedCount++;
qvm.Bid = quote.Bid;
qvm.Ask = quote.Ask;
}
private void RemoveQuote(Mt5Quote quote)
{
if (quote == null) return;
if (_quotesMap.ContainsKey(quote.Instrument))
{
var qvm = _quotesMap[quote.Instrument];
qvm.FeedCount--;
if (qvm.FeedCount <= 0)
{
_quotesMap.Remove(quote.Instrument);
Quotes.Remove(qvm);
}
}
}
private void OnConnected()
{
var quotes = _mtApiClient.GetQuotes();
if (quotes != null)
{
foreach (var quote in quotes)
{
AddQuote(quote);
}
}
}
private void OnDisconnected()
{
_quotesMap.Clear();
Quotes.Clear();
}
private static string MqlTradeResultToString(MqlTradeResult result)
{
return result != null ?
"Retcode = " + result.Retcode + ";"
+ " Comment = " + result.Comment + ";"
+ " Order = " + result.Order + ";"
+ " Volume = " + result.Volume + ";"
+ " Price = " + result.Price + ";"
+ " Deal = " + result.Deal + ";"
+ " Request_id = " + result.Request_id + ";"
+ " Bid = " + result.Bid + ";"
+ " Ask = " + result.Ask + ";" : string.Empty;
}
private void OnSelectedQuoteChanged()
{
if (SelectedQuote == null) return;
TradeRequest.Symbol = SelectedQuote.Instrument;
TimeSeriesValues.SymbolValue = SelectedQuote.Instrument;
}
private async Task<TResult> Execute<TResult>(Func<TResult> func)
{
return await Task.Factory.StartNew(() =>
{
var result = default(TResult);
try
{
result = func();
}
catch (Exception ex)
{
AddLog($"Exception: {ex.Message}");
}
return result;
});
}
private void AddLog(string msg)
{
RunOnUiThread(() =>
{
var time = DateTime.Now.ToString("h:mm:ss tt");
History.Add($"[{time}]: {msg}");
});
}
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Private Fields
private readonly MtApi5Client _mtApiClient;
private readonly Dictionary<string, QuoteViewModel> _quotesMap;
#endregion
}
}