Added MtEvent into MtApiService. Added event LastTimeBar into MtApi (MT4)

This commit is contained in:
DW
2016-08-30 16:01:23 +03:00
parent e24502f303
commit edc7311104
18 changed files with 238 additions and 180 deletions
+1
View File
@@ -60,6 +60,7 @@
<Compile Include="MtApiProxy.cs" /> <Compile Include="MtApiProxy.cs" />
<Compile Include="MtClient.cs" /> <Compile Include="MtClient.cs" />
<Compile Include="MtCommandTask.cs" /> <Compile Include="MtCommandTask.cs" />
<Compile Include="MtEvent.cs" />
<Compile Include="MtMqlBookInfo.cs" /> <Compile Include="MtMqlBookInfo.cs" />
<Compile Include="MtMqlRates.cs" /> <Compile Include="MtMqlRates.cs" />
<Compile Include="MtMqlTick.cs" /> <Compile Include="MtMqlTick.cs" />
+10 -12
View File
@@ -224,20 +224,14 @@ namespace MTApiService
{ {
Debug.WriteLine("[INFO] MtClient::OnQuoteAdded"); Debug.WriteLine("[INFO] MtClient::OnQuoteAdded");
if (QuoteAdded != null) QuoteAdded?.Invoke(quote);
{
QuoteAdded(quote);
}
} }
public void OnQuoteRemoved(MtQuote quote) public void OnQuoteRemoved(MtQuote quote)
{ {
Debug.WriteLine("[INFO] MtClient::OnQuoteRemoved"); Debug.WriteLine("[INFO] MtClient::OnQuoteRemoved");
if (QuoteRemoved != null) QuoteRemoved?.Invoke(quote);
{
QuoteRemoved(quote);
}
} }
public void OnServerStopped() public void OnServerStopped()
@@ -246,10 +240,13 @@ namespace MTApiService
Close(); Close();
if (ServerDisconnected != null) ServerDisconnected?.Invoke(this, EventArgs.Empty);
{ }
ServerDisconnected(this, EventArgs.Empty);
}
public void OnMtEvent(MtEvent mtEvent)
{
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
} }
#endregion #endregion
@@ -301,6 +298,7 @@ namespace MTApiService
public event MtQuoteHandler QuoteUpdated; public event MtQuoteHandler QuoteUpdated;
public event EventHandler ServerDisconnected; public event EventHandler ServerDisconnected;
public event EventHandler ServerFailed; public event EventHandler ServerFailed;
public event EventHandler<MtEventArgs> MtEventReceived;
#endregion #endregion
#region Fields #region Fields
+36
View File
@@ -0,0 +1,36 @@
using System;
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtEvent
{
[DataMember]
public int EventType { get; private set; }
[DataMember]
public string Payload { get; private set; }
public MtEvent(int eventType, string payload)
{
EventType = eventType;
Payload = payload;
}
public override string ToString()
{
return "MtEvent = " + EventType + ", Payload = " + Payload;
}
}
public class MtEventArgs: EventArgs
{
public MtEventArgs(MtEvent e)
{
Event = e;
}
public MtEvent Event { get; private set; }
}
}
+15 -15
View File
@@ -66,6 +66,7 @@ namespace MTApiService
} }
} }
} }
#endregion #endregion
#region Public Methods #region Public Methods
@@ -114,6 +115,11 @@ namespace MTApiService
return null; return null;
} }
public void SendEvent(MtEvent mtEvent)
{
FireOnMtEvent(mtEvent);
}
#endregion #endregion
#region IMtCommandExecutor #region IMtCommandExecutor
@@ -134,29 +140,22 @@ namespace MTApiService
private void FireOnQuoteChanged(MtQuote quote) private void FireOnQuoteChanged(MtQuote quote)
{ {
var handler = QuoteChanged; QuoteChanged?.Invoke(this, quote);
if (handler != null)
{
handler(this, quote);
}
} }
private void FireOnDeinited() private void FireOnDeinited()
{ {
var handler = Deinited; Deinited?.Invoke(this, EventArgs.Empty);
if (handler != null)
{
handler(this, EventArgs.Empty);
}
} }
private void FireOnCommandExecuted() private void FireOnCommandExecuted()
{ {
var handler = CommandExecuted; CommandExecuted?.Invoke(this, EventArgs.Empty);
if (handler != null) }
{
handler(this, EventArgs.Empty); private void FireOnMtEvent(MtEvent mtEvent)
} {
OnMtEvent?.Invoke(this, new MtEventArgs(mtEvent));
} }
#endregion #endregion
@@ -164,6 +163,7 @@ namespace MTApiService
public event EventHandler Deinited; public event EventHandler Deinited;
public event MtQuoteHandler QuoteChanged; public event MtQuoteHandler QuoteChanged;
public event EventHandler CommandExecuted; public event EventHandler CommandExecuted;
public event EventHandler<MtEventArgs> OnMtEvent;
#endregion #endregion
#region Private Fields #region Private Fields
+7 -5
View File
@@ -107,6 +107,7 @@ namespace MTApiService
{ {
expert.Deinited += expert_Deinited; expert.Deinited += expert_Deinited;
expert.QuoteChanged += expert_QuoteChanged; expert.QuoteChanged += expert_QuoteChanged;
expert.OnMtEvent += Expert_OnMtEvent;
lock (_experts) lock (_experts)
{ {
@@ -308,13 +309,14 @@ namespace MTApiService
_service.QuoteUpdate(quote); _service.QuoteUpdate(quote);
} }
private void Expert_OnMtEvent(object sender, MtEventArgs e)
{
_service.OnMtEvent(e.Event);
}
private void FireOnStopped() private void FireOnStopped()
{ {
var handler = Stopped; Stopped?.Invoke(this, EventArgs.Empty);
if (handler != null)
{
handler(this, EventArgs.Empty);
}
} }
#endregion #endregion
+18
View File
@@ -101,6 +101,24 @@ namespace MTApiService
Debug.WriteLine("MtApiServerInstance::SendQuote: finish."); Debug.WriteLine("MtApiServerInstance::SendQuote: finish.");
} }
public void SendEvent(int expertHandle, int eventType, string payload)
{
Debug.WriteLine("MtApiServerInstance::SendEvent called. eventType = {0}, payload = {1}", eventType, payload);
MtExpert expert = null;
lock (mExpertsDictionary)
{
expert = mExpertsDictionary[expertHandle];
}
if (expert != null)
{
expert.SendEvent(new MtEvent(eventType, payload));
}
Debug.WriteLine("MtApiServerInstance::SendEvent: finished");
}
public void SendResponse(int expertHandle, MtResponse response) public void SendResponse(int expertHandle, MtResponse response)
{ {
Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response); Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response);
+38 -132
View File
@@ -35,6 +35,9 @@ namespace MTApiService
[OperationContract(IsOneWay = true)] [OperationContract(IsOneWay = true)]
void OnQuoteRemoved(MtQuote quote); void OnQuoteRemoved(MtQuote quote);
[OperationContract(IsOneWay = true)]
void OnMtEvent(MtEvent ntEvent);
} }
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
@@ -123,171 +126,74 @@ namespace MTApiService
#region Public Methods #region Public Methods
public void OnStopServer() public void OnStopServer()
{ {
try ExecuteCallbackAction(a => a.OnServerStopped());
{
mClientsLocker.AcquireReaderLock(2000);
try
{
foreach (var callback in mClientCallbacks)
{
try
{
callback.OnServerStopped();
}
catch (Exception)
{
}
}
}
finally
{
mClientsLocker.ReleaseReaderLock();
}
}
catch (ApplicationException)
{
}
} }
public void QuoteUpdate(MtQuote quote) public void QuoteUpdate(MtQuote quote)
{ {
try ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
{
mClientsLocker.AcquireReaderLock(200);
List<IMtApiCallback> crashedClientsCallback = null;
try
{
foreach (var callback in mClientCallbacks)
{
try
{
callback.OnQuoteUpdate(quote);
}
catch (Exception)
{
if (crashedClientsCallback == null)
crashedClientsCallback = new List<IMtApiCallback>();
crashedClientsCallback.Add(callback);
}
}
}
finally
{
mClientsLocker.ReleaseReaderLock();
}
removeCrashedClientCallbacks(crashedClientsCallback);
}
catch (ApplicationException)
{
}
} }
public void OnQuoteAdded(MtQuote quote) public void OnQuoteAdded(MtQuote quote)
{ {
try ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
{
mClientsLocker.AcquireReaderLock(2000);
List<IMtApiCallback> crashedClientsCallback = null;
try
{
foreach (var callback in mClientCallbacks)
{
try
{
callback.OnQuoteAdded(quote);
}
catch (Exception)
{
if (crashedClientsCallback == null)
crashedClientsCallback = new List<IMtApiCallback>();
crashedClientsCallback.Add(callback);
}
}
}
finally
{
mClientsLocker.ReleaseReaderLock();
}
removeCrashedClientCallbacks(crashedClientsCallback);
}
catch (ApplicationException)
{
}
} }
public void OnQuoteRemoved(MtQuote quote) public void OnQuoteRemoved(MtQuote quote)
{ {
try ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
{ }
mClientsLocker.AcquireReaderLock(2000);
List<IMtApiCallback> crashedClientsCallback = null; public void OnMtEvent(MtEvent mtEvent)
{
try ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
{
foreach (var callback in mClientCallbacks)
{
try
{
callback.OnQuoteRemoved(quote);
}
catch (Exception)
{
if (crashedClientsCallback == null)
crashedClientsCallback = new List<IMtApiCallback>();
crashedClientsCallback.Add(callback);
}
}
}
finally
{
mClientsLocker.ReleaseReaderLock();
}
removeCrashedClientCallbacks(crashedClientsCallback);
}
catch (ApplicationException)
{
}
} }
#endregion #endregion
#region Private Methods #region Private Methods
private void removeCrashedClientCallbacks(List<IMtApiCallback> crashedClientCallbacks) private void ExecuteCallbackAction(Action<IMtApiCallback> action)
{ {
if (crashedClientCallbacks != null) try
{ {
mClientsLocker.AcquireReaderLock(2000);
List<IMtApiCallback> crashedClientCallbacks = null;
try try
{ {
mClientsLocker.AcquireWriterLock(200); foreach (var callback in mClientCallbacks)
{
try
{
action(callback);
}
catch (Exception)
{
if (crashedClientCallbacks == null)
crashedClientCallbacks = new List<IMtApiCallback>();
try crashedClientCallbacks.Add(callback);
}
}
if (crashedClientCallbacks != null)
{ {
foreach (var crashedCallback in crashedClientCallbacks) foreach (var crashedCallback in crashedClientCallbacks)
{ {
mClientCallbacks.Remove(crashedCallback); mClientCallbacks.Remove(crashedCallback);
} }
} }
finally
{
mClientsLocker.ReleaseWriterLock();
}
} }
catch (ApplicationException) finally
{ {
mClientsLocker.ReleaseReaderLock();
} }
} }
catch (ApplicationException)
{
//TODO: add logging
}
} }
#endregion #endregion
+16
View File
@@ -71,6 +71,22 @@ int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double a
return 1; return 1;
} }
int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateTimeBar(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendIntResponse(int expertHandle, int response) int _stdcall sendIntResponse(int expertHandle, int response)
{ {
try try
+1
View File
@@ -3,6 +3,7 @@ LIBRARY MTConnector
EXPORTS initExpert EXPORTS initExpert
deinitExpert deinitExpert
updateQuote updateQuote
sendEvent
sendIntResponse sendIntResponse
sendBooleanResponse sendBooleanResponse
sendDoubleResponse sendDoubleResponse
+2 -8
View File
@@ -1,14 +1,8 @@
using System; namespace MtApi
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi
{ {
static class ExtensionMethods static class ExtensionMethods
{ {
public static MtQuote Parse(this MTApiService.MtQuote quote) public static MtQuote Convert(this MTApiService.MtQuote quote)
{ {
return (quote != null) ? new MtQuote(quote.Instrument, quote.Bid, quote.Ask) : null; return (quote != null) ? new MtQuote(quote.Instrument, quote.Bid, quote.Ask) : null;
} }
+3
View File
@@ -66,10 +66,12 @@
<Compile Include="MtConnectionState.cs" /> <Compile Include="MtConnectionState.cs" />
<Compile Include="MtCommandType.cs" /> <Compile Include="MtCommandType.cs" />
<Compile Include="MtErrorCode.cs" /> <Compile Include="MtErrorCode.cs" />
<Compile Include="MtEventTypes.cs" />
<Compile Include="MtExecutionException.cs" /> <Compile Include="MtExecutionException.cs" />
<Compile Include="MtOrder.cs" /> <Compile Include="MtOrder.cs" />
<Compile Include="MtQuote.cs" /> <Compile Include="MtQuote.cs" />
<Compile Include="MtQuoteEventArgs.cs" /> <Compile Include="MtQuoteEventArgs.cs" />
<Compile Include="MtTimeBar.cs" />
<Compile Include="MtTypes.cs" /> <Compile Include="MtTypes.cs" />
<Compile Include="PriceConstantsType.cs" /> <Compile Include="PriceConstantsType.cs" />
<Compile Include="MarketInfoModeType.cs" /> <Compile Include="MarketInfoModeType.cs" />
@@ -95,6 +97,7 @@
<Compile Include="Responses\OrderSendResponse.cs" /> <Compile Include="Responses\OrderSendResponse.cs" />
<Compile Include="Responses\ResponseBase.cs" /> <Compile Include="Responses\ResponseBase.cs" />
<Compile Include="SeriesIdentifier.cs" /> <Compile Include="SeriesIdentifier.cs" />
<Compile Include="TimeBarArgs.cs" />
<Compile Include="TradeOperation.cs" /> <Compile Include="TradeOperation.cs" />
<Compile Include="MtApiTimeConverter.cs" /> <Compile Include="MtApiTimeConverter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
+31 -8
View File
@@ -29,11 +29,12 @@ namespace MtApi
public MtApiClient() public MtApiClient()
{ {
_client.QuoteAdded +=new MtClient.MtQuoteHandler(mClient_QuoteAdded); _client.QuoteAdded += mClient_QuoteAdded;
_client.QuoteRemoved += new MtClient.MtQuoteHandler(mClient_QuoteRemoved); _client.QuoteRemoved += mClient_QuoteRemoved;
_client.QuoteUpdated += new MtClient.MtQuoteHandler(mClient_QuoteUpdated); _client.QuoteUpdated += mClient_QuoteUpdated;
_client.ServerDisconnected += new EventHandler(mClient_ServerDisconnected); _client.ServerDisconnected += mClient_ServerDisconnected;
_client.ServerFailed += new EventHandler(mClient_ServerFailed); _client.ServerFailed += mClient_ServerFailed;
_client.MtEventReceived += _client_MtEventReceived;
} }
#endregion #endregion
@@ -81,7 +82,7 @@ namespace MtApi
public IEnumerable<MtQuote> GetQuotes() public IEnumerable<MtQuote> GetQuotes()
{ {
var quotes = _client.GetQuotes(); var quotes = _client.GetQuotes();
return quotes != null ? (from q in quotes select q.Parse()) : null; return quotes != null ? (from q in quotes select q.Convert()) : null;
} }
#endregion #endregion
@@ -1597,14 +1598,35 @@ namespace MtApi
private void mClient_QuoteRemoved(MTApiService.MtQuote quote) private void mClient_QuoteRemoved(MTApiService.MtQuote quote)
{ {
var handler = QuoteRemoved; var handler = QuoteRemoved;
handler?.BeginInvoke(this, new MtQuoteEventArgs(quote.Parse()), (a) => handler.EndInvoke(a), null); handler?.BeginInvoke(this, new MtQuoteEventArgs(quote.Convert()), (a) => handler.EndInvoke(a), null);
} }
private void mClient_QuoteAdded(MTApiService.MtQuote quote) private void mClient_QuoteAdded(MTApiService.MtQuote quote)
{ {
var handler = QuoteAdded; var handler = QuoteAdded;
handler?.BeginInvoke(this, new MtQuoteEventArgs(quote.Parse()), (a) => handler.EndInvoke(a), null); handler?.BeginInvoke(this, new MtQuoteEventArgs(quote.Convert()), (a) => handler.EndInvoke(a), null);
} }
private void _client_MtEventReceived(object sender, MtEventArgs e)
{
MtEventTypes eventType = (MtEventTypes) e.Event.EventType;
switch(eventType)
{
case MtEventTypes.LastTimeBar:
{
FireOnLastTimeBar(JsonConvert.DeserializeObject<MtTimeBar>(e.Event.Payload));
}
break;
}
}
private void FireOnLastTimeBar(MtTimeBar timeBar)
{
var handler = OnLastTimeBar;
handler?.BeginInvoke(this, new TimeBarArgs(timeBar), (a) => handler.EndInvoke(a), null);
}
#endregion #endregion
#region Events #region Events
@@ -1612,6 +1634,7 @@ namespace MtApi
public event EventHandler<MtQuoteEventArgs> QuoteAdded; public event EventHandler<MtQuoteEventArgs> QuoteAdded;
public event EventHandler<MtQuoteEventArgs> QuoteRemoved; public event EventHandler<MtQuoteEventArgs> QuoteRemoved;
public event EventHandler<MtConnectionEventArgs> ConnectionStateChanged; public event EventHandler<MtConnectionEventArgs> ConnectionStateChanged;
public event EventHandler<TimeBarArgs> OnLastTimeBar;
#endregion #endregion
#region Private Fields #region Private Fields
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi
{
public enum MtEventTypes
{
LastTimeBar = 1
}
}
+26
View File
@@ -0,0 +1,26 @@
using System;
namespace MtApi
{
public class MtTimeBar
{
public string Symbol { get; set; }
public int MtOpenTime { get; set; }
public int MtCloseTime { get; set; }
public double Open { get; set; }
public double Close { get; set; }
public double High { get; set; }
public double Low { get; set; }
public DateTime OpenTime
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtOpenTime); }
}
public DateTime CloseTime
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtCloseTime); }
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi
{
public class TimeBarArgs: EventArgs
{
public TimeBarArgs(MtTimeBar timeBar)
{
TimeBar = timeBar;
}
public MtTimeBar TimeBar { get; private set; }
}
}
+9
View File
@@ -23,6 +23,7 @@ namespace TestApiClientUI
_apiClient.QuoteAdded += apiClient_QuoteAdded; _apiClient.QuoteAdded += apiClient_QuoteAdded;
_apiClient.QuoteRemoved += apiClient_QuoteRemoved; _apiClient.QuoteRemoved += apiClient_QuoteRemoved;
_apiClient.ConnectionStateChanged += apiClient_ConnectionStateChanged; _apiClient.ConnectionStateChanged += apiClient_ConnectionStateChanged;
_apiClient.OnLastTimeBar += _apiClient_OnLastTimeBar;
initOrderCommandsGroup(); initOrderCommandsGroup();
@@ -95,6 +96,14 @@ namespace TestApiClientUI
RunOnUiThread(() => AddNewQuote(e.Quote)); RunOnUiThread(() => AddNewQuote(e.Quote));
} }
private void _apiClient_OnLastTimeBar(object sender, TimeBarArgs e)
{
string msg = string.Format("TimeBar: Symbol = {0}, OpenTime = {1}, CloseTime = {2}, Open = {3}, Close = {4}, High = {5}, Low = {6}",
e.TimeBar.Symbol, e.TimeBar.OpenTime, e.TimeBar.CloseTime, e.TimeBar.Open, e.TimeBar.Close, e.TimeBar.High, e.TimeBar.Low);
Console.WriteLine(msg);
AddToLog(msg);
}
private volatile bool IsUiQuoteUpdateReady = true; private volatile bool IsUiQuoteUpdateReady = true;
private void apiClient_QuoteUpdated(object sender, string symbol, double bid, double ask) private void apiClient_QuoteUpdated(object sender, string symbol, double bid, double ask)
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.