mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-07-28 02:57:56 +00:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e3f206c76 | |||
| 8e5dcbd2ee | |||
| 563a5a895b | |||
| 32f6018858 | |||
| c64417474a | |||
| 6d4b5f4c00 | |||
| 601c95369e | |||
| 0542dd3e71 | |||
| 15068ca99c | |||
| c3617549f8 | |||
| aa91196e31 | |||
| ba7b50e241 | |||
| ddcd6fa2d5 | |||
| ad55740bc7 | |||
| 26a3db9ae1 | |||
| 7d3af82e1f | |||
| 09b72fc64d | |||
| 834b0af430 | |||
| 5dd1e4831d | |||
| 39f11bfc34 | |||
| c6faaf0602 | |||
| c14726bdba | |||
| 05452e3b90 | |||
| 094cdcc448 | |||
| a63e628124 | |||
| 7fec3da7bc | |||
| 1d407b5e16 | |||
| e373f7976c | |||
| 3785ee4ace | |||
| b4b8e7eaf0 | |||
| 22f7915a4a | |||
| 84dfd21f9f | |||
| d4ee2cfada | |||
| 0b3d686f05 | |||
| cacc0ea787 | |||
| d96dc18ea3 | |||
| db4bb44fb3 | |||
| 68d5fa98af | |||
| dc28823ca9 |
Executable
BIN
Binary file not shown.
Executable
+67
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<!-- -->
|
||||
<!-- ILMerge project-specific settings. Almost never need to be set explicitly. -->
|
||||
<!-- for details, see http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx -->
|
||||
<!-- -->
|
||||
<!-- *** set this file to Type=None, CopyToOutput=Never *** -->
|
||||
|
||||
<!-- If True, all copy local dependencies will also be merged from referenced projects whether they are referenced in the current project explicitly or not -->
|
||||
<ILMergeTransitive>true</ILMergeTransitive>
|
||||
|
||||
<!-- Extra ILMerge library paths (semicolon-separated). Dont put your package dependencies here, they will be added automagically -->
|
||||
<ILMergeLibraryPath></ILMergeLibraryPath>
|
||||
|
||||
<!-- The solution NuGet package directory if not standard 'SOLUTION\packages' -->
|
||||
<ILMergePackagesPath></ILMergePackagesPath>
|
||||
|
||||
<!-- The merge order file name if differs from standard 'ILMergeOrder.txt' -->
|
||||
<ILMergeOrderFile></ILMergeOrderFile>
|
||||
|
||||
<!-- The strong key file name if not specified in the project -->
|
||||
<ILMergeKeyFile>MtApiKey.snk</ILMergeKeyFile>
|
||||
|
||||
<!-- The assembly version if differs for the version of the main assembly -->
|
||||
<ILMergeAssemblyVersion></ILMergeAssemblyVersion>
|
||||
|
||||
<!-- added in Version 1.0.4 -->
|
||||
<ILMergeFileAlignment></ILMergeFileAlignment>
|
||||
|
||||
<!-- added in Version 1.0.4, default=none -->
|
||||
<ILMergeAllowDuplicateType></ILMergeAllowDuplicateType>
|
||||
|
||||
<!-- If the <see cref="CopyAttributes"/> is also set, any assembly-level attributes names that have the same type are copied over into the target assembly -->
|
||||
<ILMergeAllowMultipleAssemblyLevelAttributes></ILMergeAllowMultipleAssemblyLevelAttributes>
|
||||
|
||||
<!-- See ILMerge documentation -->
|
||||
<ILMergeAllowZeroPeKind></ILMergeAllowZeroPeKind>
|
||||
|
||||
<!-- The assembly level attributes of each input assembly are copied over into the target assembly -->
|
||||
<ILMergeCopyAttributes></ILMergeCopyAttributes>
|
||||
|
||||
<!-- Creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies, default=true -->
|
||||
<ILMergeDebugInfo></ILMergeDebugInfo>
|
||||
|
||||
<!-- Target assembly will be delay signed -->
|
||||
<ILMergeDelaySign></ILMergeDelaySign>
|
||||
|
||||
<!-- Types in assemblies other than the primary assembly have their visibility modified -->
|
||||
<ILMergeInternalize></ILMergeInternalize>
|
||||
|
||||
<!-- The path name of the file that will be used to identify types that are not to have their visibility modified -->
|
||||
<ILMergeInternalizeExcludeFile></ILMergeInternalizeExcludeFile>
|
||||
|
||||
<!-- XML documentation files are merged to produce an XML documentation file for the target assembly -->
|
||||
<ILMergeXmlDocumentation></ILMergeXmlDocumentation>
|
||||
|
||||
<!-- External assembly references in the manifest of the target assembly will use full public keys (false) or public key tokens (true, default value) -->
|
||||
<ILMergePublicKeyTokens></ILMergePublicKeyTokens>
|
||||
|
||||
<!-- Types with the same name are all merged into a single type in the target assembly -->
|
||||
<ILMergeUnionMerge></ILMergeUnionMerge>
|
||||
|
||||
<!-- The version of the target framework, default 40 (works for 45 too) -->
|
||||
<ILTargetPlatform></ILTargetPlatform>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
# this file contains the partial list of the merged assemblies in the merge order
|
||||
# you can fill it from the obj\CONFIG\PROJECT.ilmerge generated on every build
|
||||
# and finetune merge order to your satisfaction
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public interface IMtApiServer
|
||||
{
|
||||
MtResponse SendCommand(MtCommand command);
|
||||
IEnumerable<MtQuote> GetQuotes();
|
||||
List<MtQuote> GetQuotes();
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using log4net;
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Layout;
|
||||
using log4net.Repository.Hierarchy;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public class LogConfigurator
|
||||
{
|
||||
private const string LogFileNameExtension = "txt";
|
||||
|
||||
public static void Setup(string profileName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(profileName))
|
||||
throw new ArgumentNullException();
|
||||
|
||||
var hierarchy = (Hierarchy) LogManager.GetRepository();
|
||||
|
||||
var patternLayout = new PatternLayout
|
||||
{
|
||||
ConversionPattern = "%date [%thread] %-5level %logger - %message%newline"
|
||||
};
|
||||
patternLayout.ActivateOptions();
|
||||
|
||||
string filename = $"{DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")}-{Process.GetCurrentProcess().Id}.{LogFileNameExtension}";
|
||||
|
||||
var roller = new RollingFileAppender
|
||||
{
|
||||
AppendToFile = false,
|
||||
File = $@"{System.IO.Path.GetTempPath()}{profileName}\Logs\{filename}",
|
||||
Layout = patternLayout,
|
||||
PreserveLogFileNameExtension = true,
|
||||
MaxSizeRollBackups = 5,
|
||||
MaximumFileSize = "1GB",
|
||||
RollingStyle = RollingFileAppender.RollingMode.Size,
|
||||
StaticLogFileName = false
|
||||
};
|
||||
roller.ActivateOptions();
|
||||
hierarchy.Root.AddAppender(roller);
|
||||
|
||||
var memory = new MemoryAppender();
|
||||
memory.ActivateOptions();
|
||||
hierarchy.Root.AddAppender(memory);
|
||||
|
||||
#if (DEBUG)
|
||||
hierarchy.Root.Level = Level.Debug;
|
||||
#else
|
||||
hierarchy.Root.Level = Level.Info;
|
||||
#endif
|
||||
hierarchy.Configured = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props" Condition="Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
@@ -14,6 +15,8 @@
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -35,12 +38,17 @@
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>MtApiKey.pfx</AssemblyOriginatorKeyFile>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.5\lib\net40-full\log4net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
@@ -54,6 +62,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="ICommandManager.cs" />
|
||||
<Compile Include="IMetaTraderHandler.cs" />
|
||||
<Compile Include="LogConfigurator.cs" />
|
||||
<Compile Include="MtCommandEventArgs.cs" />
|
||||
<Compile Include="IDisposableChannel.cs" />
|
||||
<Compile Include="IMtApiServer.cs" />
|
||||
@@ -78,13 +87,28 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="MtApiKey.pfx" />
|
||||
<None Include="ILMerge.props">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="MtApiKey.snk" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="ILMergeOrder.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props'))" />
|
||||
<Error Condition="!Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets" Condition="Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
Binary file not shown.
Executable
BIN
Binary file not shown.
+11
-14
@@ -1,20 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable
|
||||
internal class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable
|
||||
{
|
||||
public MtApiProxy(InstanceContext callbackContext, Binding binding,
|
||||
EndpointAddress remoteAddress)
|
||||
public MtApiProxy(InstanceContext callbackContext, Binding binding, EndpointAddress remoteAddress)
|
||||
: base(callbackContext, binding, remoteAddress)
|
||||
{
|
||||
base.InnerDuplexChannel.Faulted += new EventHandler(InnerDuplexChannel_Faulted);
|
||||
base.InnerDuplexChannel.Open();
|
||||
InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
|
||||
InnerDuplexChannel.Open();
|
||||
}
|
||||
|
||||
#region IMtApi Members
|
||||
@@ -34,7 +31,7 @@ namespace MTApiService
|
||||
return Channel.SendCommand(command);
|
||||
}
|
||||
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
public List<MtQuote> GetQuotes()
|
||||
{
|
||||
return Channel.GetQuotes();
|
||||
}
|
||||
@@ -47,19 +44,19 @@ namespace MTApiService
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Close();
|
||||
Close();
|
||||
}
|
||||
catch (CommunicationException)
|
||||
{
|
||||
this.Abort();
|
||||
Abort();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
this.Abort();
|
||||
Abort();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.Abort();
|
||||
Abort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +65,9 @@ namespace MTApiService
|
||||
#region Private Methods
|
||||
private void InnerDuplexChannel_Faulted(object sender, EventArgs e)
|
||||
{
|
||||
if (Faulted != null)
|
||||
Faulted(this, e);
|
||||
Faulted?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
+175
-137
@@ -1,173 +1,208 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.ServiceModel;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
[CallbackBehavior(UseSynchronizationContext = false)]
|
||||
public class MtClient: IMtApiCallback, IDisposable
|
||||
{
|
||||
private static string SERVICE_NAME = "MtApiService";
|
||||
private const string ServiceName = "MtApiService";
|
||||
|
||||
public delegate void MtQuoteHandler(MtQuote quote);
|
||||
|
||||
#region Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient));
|
||||
|
||||
private MtApiProxy _proxy;
|
||||
private bool _isConnected;
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public void Open(string host, int port)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Open");
|
||||
Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, port);
|
||||
|
||||
if (string.IsNullOrEmpty(host))
|
||||
throw new ArgumentNullException("host", "host is null or empty");
|
||||
throw new ArgumentNullException(nameof(host), "host is null or empty");
|
||||
|
||||
if (port < 0 || port > 65536)
|
||||
throw new ArgumentOutOfRangeException("port", "port value is invalid");
|
||||
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
|
||||
|
||||
var urlService = string.Format("net.tcp://{0}:{1}/{2}", host, port, SERVICE_NAME);
|
||||
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
|
||||
|
||||
lock (mClientLocker)
|
||||
if (_proxy != null)
|
||||
{
|
||||
if (mProxy != null)
|
||||
return;
|
||||
|
||||
var bind = new NetTcpBinding(SecurityMode.None)
|
||||
{
|
||||
MaxReceivedMessageSize = 2147483647,
|
||||
MaxBufferSize = 2147483647,
|
||||
MaxBufferPoolSize = 2147483647,
|
||||
ReaderQuotas =
|
||||
{
|
||||
MaxArrayLength = 2147483647,
|
||||
MaxBytesPerRead = 2147483647,
|
||||
MaxDepth = 2147483647,
|
||||
MaxStringContentLength = 2147483647,
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
// Commented next statement since it is not required
|
||||
|
||||
mProxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
mProxy.Faulted += mProxy_Faulted;
|
||||
Log.Warn("Open: end. _proxy is not null.");
|
||||
return;
|
||||
}
|
||||
|
||||
var bind = new NetTcpBinding(SecurityMode.None)
|
||||
{
|
||||
MaxReceivedMessageSize = 2147483647,
|
||||
MaxBufferSize = 2147483647,
|
||||
MaxBufferPoolSize = 2147483647,
|
||||
SendTimeout = new TimeSpan(12, 0, 0),
|
||||
ReceiveTimeout = new TimeSpan(12, 0, 0),
|
||||
ReaderQuotas =
|
||||
{
|
||||
MaxArrayLength = 2147483647,
|
||||
MaxBytesPerRead = 2147483647,
|
||||
MaxDepth = 2147483647,
|
||||
MaxStringContentLength = 2147483647,
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
// Commented next statement since it is not required
|
||||
|
||||
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
_proxy.Faulted += ProxyFaulted;
|
||||
|
||||
Log.Debug("Open: end.");
|
||||
}
|
||||
|
||||
public void Open(int port)
|
||||
{
|
||||
Log.DebugFormat("Open: begin. port = {0}", port);
|
||||
|
||||
if (port < 0 || port > 65536)
|
||||
throw new ArgumentOutOfRangeException("port", "port value is invalid");
|
||||
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
|
||||
|
||||
var urlService = string.Format("net.pipe://localhost/{0}_{1}", SERVICE_NAME, port);
|
||||
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
|
||||
|
||||
lock (mClientLocker)
|
||||
if (_proxy != null)
|
||||
{
|
||||
if (mProxy != null)
|
||||
return;
|
||||
|
||||
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
|
||||
{
|
||||
MaxReceivedMessageSize = 2147483647,
|
||||
MaxBufferSize = 2147483647,
|
||||
MaxBufferPoolSize = 2147483647,
|
||||
ReaderQuotas =
|
||||
{
|
||||
MaxArrayLength = 2147483647,
|
||||
MaxBytesPerRead = 2147483647,
|
||||
MaxDepth = 2147483647,
|
||||
MaxStringContentLength = 2147483647,
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
// Commented next statement since it is not required
|
||||
|
||||
mProxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
mProxy.Faulted += mProxy_Faulted;
|
||||
Log.Warn("Open: end. _proxy is not null.");
|
||||
return;
|
||||
}
|
||||
|
||||
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
|
||||
{
|
||||
MaxReceivedMessageSize = 2147483647,
|
||||
MaxBufferSize = 2147483647,
|
||||
MaxBufferPoolSize = 2147483647,
|
||||
SendTimeout = new TimeSpan(12, 0, 0),
|
||||
ReceiveTimeout = new TimeSpan(12, 0, 0),
|
||||
ReaderQuotas =
|
||||
{
|
||||
MaxArrayLength = 2147483647,
|
||||
MaxBytesPerRead = 2147483647,
|
||||
MaxDepth = 2147483647,
|
||||
MaxStringContentLength = 2147483647,
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
// Commented next statement since it is not required
|
||||
|
||||
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
|
||||
_proxy.Faulted += ProxyFaulted;
|
||||
|
||||
Log.Debug("Open: end.");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Close");
|
||||
Log.Debug("Close: begin.");
|
||||
|
||||
lock (mClientLocker)
|
||||
if (_proxy != null)
|
||||
{
|
||||
if (mProxy != null)
|
||||
{
|
||||
mProxy.Faulted -= mProxy_Faulted;
|
||||
mProxy.Dispose();
|
||||
mProxy = null;
|
||||
}
|
||||
|
||||
mIsConnected = false;
|
||||
_proxy.Faulted -= ProxyFaulted;
|
||||
_proxy.Dispose();
|
||||
_proxy = null;
|
||||
}
|
||||
|
||||
_isConnected = false;
|
||||
|
||||
Log.Debug("Close: end.");
|
||||
}
|
||||
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public void Connect()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Connect");
|
||||
Log.Debug("Connect: begin.");
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Error("Connect: _proxy is not defined.");
|
||||
throw new CommunicationException("Connection failed to service. Proxy is not defined (needs to call Open)");
|
||||
}
|
||||
|
||||
if (_isConnected)
|
||||
{
|
||||
Log.Warn("Connected: end. Client is already connected.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
if (mProxy != null && mIsConnected == true)
|
||||
return;
|
||||
|
||||
mIsConnected = mProxy.Connect();
|
||||
|
||||
if (mIsConnected == false)
|
||||
throw new Exception("Connected failed");
|
||||
}
|
||||
_isConnected = _proxy.Connect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("[ERROR] MtClient::Connect: {0}", ex.Message);
|
||||
Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
throw new CommunicationException(string.Format("Connection failed to service"));
|
||||
throw new CommunicationException($"Connection failed to service. {ex.Message}");
|
||||
}
|
||||
|
||||
if (_isConnected == false)
|
||||
{
|
||||
Log.Error("Connect: end. Connection failed.");
|
||||
throw new CommunicationException("Connection failed");
|
||||
}
|
||||
|
||||
Log.Debug("Connect: end.");
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Disconnect");
|
||||
Log.Debug("Disconnect: begin.");
|
||||
|
||||
try
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
mIsConnected = false;
|
||||
_isConnected = false;
|
||||
|
||||
if (mProxy != null)
|
||||
mProxy.Disconnect();
|
||||
}
|
||||
_proxy?.Disconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("[ERROR] MtClient::Disconnect: {0}", ex.Message);
|
||||
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
Log.Debug("Disconnect: end.");
|
||||
}
|
||||
|
||||
public MtResponse SendCommand(int commandType, ArrayList commandParameters)
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public MtResponse SendCommand(int commandType, ArrayList parameters)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::SendCommand: commandType = {0}", commandType);
|
||||
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
|
||||
|
||||
MtResponse result = null;
|
||||
MtResponse result;
|
||||
|
||||
if (_isConnected == false)
|
||||
{
|
||||
Log.Error("SendCommand: Client is not connected.");
|
||||
throw new CommunicationException("Client is not connected.");
|
||||
}
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Error("SendCommand: Proxy is not defined.");
|
||||
throw new CommunicationException("Proxy is not defined.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
if (mProxy != null && mIsConnected == true)
|
||||
result = mProxy.SendCommand(new MtCommand(commandType, commandParameters));
|
||||
}
|
||||
result = _proxy.SendCommand(new MtCommand(commandType, parameters));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("[ERROR] MtClient::SendCommand: {0}", ex.Message);
|
||||
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
@@ -177,30 +212,41 @@ namespace MTApiService
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::GetQuotes");
|
||||
Log.Debug("GetQuotes: begin.");
|
||||
|
||||
IEnumerable<MtQuote> result = null;
|
||||
if (_isConnected == false)
|
||||
{
|
||||
Log.Warn("GetQuotes: end. Client is not connected.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_proxy == null)
|
||||
{
|
||||
Log.Warn("GetQuotes: end. _proxy is not defined.");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<MtQuote> result;
|
||||
|
||||
try
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
if (mProxy != null && mIsConnected == true)
|
||||
result = mProxy.GetQuotes();
|
||||
}
|
||||
result = _proxy.GetQuotes();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("[ERROR] MtClient::GetQuotes: {0}", ex.Message);
|
||||
Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
|
||||
|
||||
Close();
|
||||
|
||||
throw new CommunicationException("Service connection failed");
|
||||
throw new CommunicationException($"Service connection failed! {ex.Message}");
|
||||
}
|
||||
|
||||
return result;;
|
||||
Log.DebugFormat("GetQuotes: end. quotes count = {0}", result?.Count);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -209,74 +255,70 @@ namespace MTApiService
|
||||
|
||||
public void OnQuoteUpdate(MtQuote quote)
|
||||
{
|
||||
if (quote != null)
|
||||
{
|
||||
if (QuoteUpdated != null)
|
||||
{
|
||||
QuoteUpdated(quote);
|
||||
}
|
||||
Log.DebugFormat("OnQuoteUpdate: begin. quote = {0}", quote);
|
||||
|
||||
Debug.WriteLine("[INFO] MtClient::OnQuoteUpdate: " + quote);
|
||||
}
|
||||
if (quote == null) return;
|
||||
|
||||
QuoteUpdated?.Invoke(quote);
|
||||
|
||||
Log.Debug("OnQuoteUpdate: end.");
|
||||
}
|
||||
|
||||
public void OnQuoteAdded(MtQuote quote)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::OnQuoteAdded");
|
||||
Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
|
||||
|
||||
QuoteAdded?.Invoke(quote);
|
||||
|
||||
Log.Debug("OnQuoteAdded: end.");
|
||||
}
|
||||
|
||||
public void OnQuoteRemoved(MtQuote quote)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::OnQuoteRemoved");
|
||||
Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
|
||||
|
||||
QuoteRemoved?.Invoke(quote);
|
||||
|
||||
Log.Debug("OnQuoteRemoved: end.");
|
||||
}
|
||||
|
||||
public void OnServerStopped()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::OnServerStopped");
|
||||
Log.Debug("OnServerStopped: begin.");
|
||||
|
||||
Close();
|
||||
|
||||
ServerDisconnected?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
Log.Debug("OnServerStopped: end.");
|
||||
}
|
||||
|
||||
|
||||
public void OnMtEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.DebugFormat("OnMtEvent: begin. event = {0}", mtEvent);
|
||||
|
||||
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
|
||||
|
||||
Log.Debug("OnMtEvent: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mClientLocker)
|
||||
{
|
||||
return mProxy.State == CommunicationState.Opened && mIsConnected == true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsConnected => _proxy.State == CommunicationState.Opened && _isConnected;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
void mProxy_Faulted(object sender, EventArgs e)
|
||||
private void ProxyFaulted(object sender, EventArgs e)
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::mProxy_Faulted");
|
||||
Log.Debug("ProxyFaulted: begin.");
|
||||
|
||||
Close();
|
||||
ServerFailed?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
if (ServerFailed != null)
|
||||
{
|
||||
ServerFailed(this, EventArgs.Empty);
|
||||
}
|
||||
Log.Debug("ProxyFaulted: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -285,9 +327,11 @@ namespace MTApiService
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Debug.WriteLine("[INFO] MtClient::Dispose");
|
||||
Log.Debug("Dispose: begin.");
|
||||
|
||||
Close();
|
||||
|
||||
Log.Debug("Dispose: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -300,11 +344,5 @@ namespace MTApiService
|
||||
public event EventHandler ServerFailed;
|
||||
public event EventHandler<MtEventArgs> MtEventReceived;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private readonly object mClientLocker = new object();
|
||||
private MtApiProxy mProxy = null;
|
||||
private bool mIsConnected = false;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ServiceModel;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections;
|
||||
|
||||
namespace MTApiService
|
||||
@@ -22,5 +18,9 @@ namespace MTApiService
|
||||
[DataMember]
|
||||
public ArrayList Parameters { get; private set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CommandType = {CommandType}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+11
-3
@@ -1,4 +1,5 @@
|
||||
using System.Threading;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
@@ -10,6 +11,9 @@ namespace MTApiService
|
||||
|
||||
public MtCommandTask(MtCommand command)
|
||||
{
|
||||
if (command == null)
|
||||
throw new ArgumentNullException(nameof(command));
|
||||
|
||||
Command = command;
|
||||
}
|
||||
|
||||
@@ -20,7 +24,7 @@ namespace MTApiService
|
||||
_responseWaiter.WaitOne(time);
|
||||
lock (_locker)
|
||||
{
|
||||
return _result;
|
||||
return _result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +36,10 @@ namespace MTApiService
|
||||
}
|
||||
_responseWaiter.Set();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Command = {Command}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public class MtConnectionProfile
|
||||
|
||||
@@ -1,31 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
internal class MtCommandExecutorManager : ICommandManager
|
||||
{
|
||||
#region Private Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtCommandExecutorManager));
|
||||
|
||||
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
|
||||
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
|
||||
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Log.Debug("Stop: begin.");
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
_commandExecutors.Clear();
|
||||
_commandTasks.Clear();
|
||||
}
|
||||
|
||||
Log.Debug("Stop: end.");
|
||||
}
|
||||
|
||||
public void AddCommandExecutor(MtExpert commandExecutor)
|
||||
{
|
||||
if (commandExecutor == null)
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(commandExecutor));
|
||||
|
||||
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandExecutors.Contains(commandExecutor))
|
||||
{
|
||||
Log.Warn("AddCommandExecutor: end. Command executor already exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
_commandExecutors.Add(commandExecutor);
|
||||
if (_commandTasks.Count > 0)
|
||||
@@ -41,18 +60,25 @@ namespace MTApiService
|
||||
{
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("AddCommandExecutor: end.");
|
||||
}
|
||||
|
||||
public void RemoveCommandExecutor(MtExpert commandExecutor)
|
||||
{
|
||||
if (commandExecutor == null)
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(commandExecutor));
|
||||
|
||||
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
if (_commandExecutors.Contains(commandExecutor) == false)
|
||||
{
|
||||
Log.Warn("RemoveCommandExecutor: end. Command executor is not exist in collection.");
|
||||
return;
|
||||
}
|
||||
|
||||
_commandExecutors.Remove(commandExecutor);
|
||||
if (_commandTasks.Count > 0)
|
||||
@@ -68,23 +94,31 @@ namespace MTApiService
|
||||
{
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("RemoveCommandExecutor: end.");
|
||||
}
|
||||
|
||||
public void EnqueueCommandTask(MtCommandTask task)
|
||||
{
|
||||
if (task == null)
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
|
||||
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
_commandTasks.Enqueue(task);
|
||||
_commandTasks.Enqueue(task);
|
||||
}
|
||||
|
||||
NotifyCommandReady();
|
||||
|
||||
Log.Debug("EnqueueCommandTask: end.");
|
||||
}
|
||||
|
||||
public MtCommandTask DequeueCommandTask()
|
||||
{
|
||||
Log.Debug("DequeueCommandTask: called.");
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
|
||||
@@ -96,6 +130,8 @@ namespace MTApiService
|
||||
#region Private Methods
|
||||
private void NotifyCommandReady()
|
||||
{
|
||||
Log.Debug("NotifyCommandReady: begin.");
|
||||
|
||||
var commandExecutors = new List<MtExpert>();
|
||||
lock (_locker)
|
||||
{
|
||||
@@ -106,10 +142,14 @@ namespace MTApiService
|
||||
{
|
||||
executor.NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.DebugFormat("NotifyCommandReady: end. Notified executor count = {0}", commandExecutors.Count);
|
||||
}
|
||||
|
||||
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
|
||||
{
|
||||
Log.Debug("CommandExecutor_CommandExecuted: begin.");
|
||||
|
||||
var notify = false;
|
||||
lock (_locker)
|
||||
{
|
||||
@@ -124,14 +164,8 @@ namespace MTApiService
|
||||
NotifyCommandReady();
|
||||
}
|
||||
|
||||
Log.Debug("CommandExecutor_CommandExecuted: end.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
|
||||
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
|
||||
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+93
-68
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
@@ -6,20 +7,103 @@ namespace MTApiService
|
||||
{
|
||||
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
|
||||
|
||||
#region Private Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
|
||||
|
||||
private readonly IMetaTraderHandler _mtHadler;
|
||||
private MtCommandTask _commandTask;
|
||||
private ICommandManager _commandManager;
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
|
||||
{
|
||||
if (mtHandler == null)
|
||||
throw new ArgumentNullException(nameof(mtHandler));
|
||||
|
||||
Quote = quote;
|
||||
Handle = handle;
|
||||
_mtHadler = mtHandler;
|
||||
}
|
||||
|
||||
public void Deinit()
|
||||
{
|
||||
Log.Debug("Deinit: begin.");
|
||||
|
||||
IsEnable = false;
|
||||
FireOnDeinited();
|
||||
|
||||
Log.Debug("Deinit: end.");
|
||||
}
|
||||
|
||||
public void SendResponse(MtResponse response)
|
||||
{
|
||||
Log.DebugFormat("SendResponse: begin. response = {0}", response);
|
||||
|
||||
_commandTask.SetResult(response);
|
||||
_commandTask = null;
|
||||
FireOnCommandExecuted();
|
||||
|
||||
Log.Debug("SendResponse: end.");
|
||||
}
|
||||
|
||||
public int GetCommandType()
|
||||
{
|
||||
Log.Debug("GetCommandType: called.");
|
||||
|
||||
var commandManager = CommandManager;
|
||||
if (commandManager != null)
|
||||
{
|
||||
_commandTask = commandManager.DequeueCommandTask();
|
||||
}
|
||||
|
||||
return _commandTask?.Command?.CommandType ?? 0;
|
||||
}
|
||||
|
||||
public object GetCommandParameter(int index)
|
||||
{
|
||||
Log.DebugFormat("GetCommandType: called. index = {0}", index);
|
||||
|
||||
var command = _commandTask?.Command;
|
||||
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
|
||||
{
|
||||
return command.Parameters[index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SendEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
|
||||
|
||||
FireOnMtEvent(mtEvent);
|
||||
|
||||
Log.Debug("SendEvent: end.");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"ExpertHandle = {Handle}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
private MtQuote _quote;
|
||||
public MtQuote Quote
|
||||
public MtQuote Quote
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
return _quote;
|
||||
return _quote;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock(_locker)
|
||||
lock (_locker)
|
||||
{
|
||||
_quote = value;
|
||||
}
|
||||
@@ -28,7 +112,7 @@ namespace MTApiService
|
||||
}
|
||||
}
|
||||
|
||||
public int Handle { get; private set; }
|
||||
public int Handle { get; }
|
||||
|
||||
private bool _isEnable = true;
|
||||
public bool IsEnable
|
||||
@@ -69,73 +153,21 @@ namespace MTApiService
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
|
||||
{
|
||||
Quote = quote;
|
||||
Handle = handle;
|
||||
_mtHadler = mtHandler;
|
||||
}
|
||||
|
||||
public void Deinit()
|
||||
{
|
||||
IsEnable = false;
|
||||
FireOnDeinited();
|
||||
}
|
||||
|
||||
public void SendResponse(MtResponse response)
|
||||
{
|
||||
_commandTask.SetResult(response);
|
||||
_commandTask = null;
|
||||
FireOnCommandExecuted();
|
||||
}
|
||||
|
||||
public int GetCommandType()
|
||||
{
|
||||
var commandManager = CommandManager;
|
||||
if (commandManager != null)
|
||||
{
|
||||
_commandTask = commandManager.DequeueCommandTask();
|
||||
}
|
||||
|
||||
return _commandTask != null && _commandTask.Command != null ? _commandTask.Command.CommandType : 0;
|
||||
}
|
||||
|
||||
public object GetCommandParameter(int index)
|
||||
{
|
||||
if (_commandTask != null)
|
||||
{
|
||||
var command = _commandTask.Command;
|
||||
if (command != null && command.Parameters != null
|
||||
&& index >= 0 && index < command.Parameters.Count)
|
||||
{
|
||||
return command.Parameters[index];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SendEvent(MtEvent mtEvent)
|
||||
{
|
||||
FireOnMtEvent(mtEvent);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IMtCommandExecutor
|
||||
public void NotifyCommandReady()
|
||||
{
|
||||
Log.Debug("NotifyCommandReady: begin.");
|
||||
|
||||
SendTickToMetaTrader();
|
||||
|
||||
Log.Debug("NotifyCommandReady: end.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void SendTickToMetaTrader()
|
||||
{
|
||||
if (_mtHadler != null)
|
||||
{
|
||||
_mtHadler.SendTickToMetaTrader(Handle);
|
||||
}
|
||||
_mtHadler.SendTickToMetaTrader(Handle);
|
||||
}
|
||||
|
||||
private void FireOnQuoteChanged(MtQuote quote)
|
||||
@@ -165,12 +197,5 @@ namespace MTApiService
|
||||
public event EventHandler CommandExecuted;
|
||||
public event EventHandler<MtEventArgs> OnMtEvent;
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private readonly IMetaTraderHandler _mtHadler;
|
||||
private MtCommandTask _commandTask;
|
||||
private ICommandManager _commandManager;
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
@@ -10,34 +7,34 @@ namespace MTApiService
|
||||
public class MtMqlTradeRequest
|
||||
{
|
||||
[DataMember]
|
||||
public int Action { get; set; }
|
||||
public int Action { get; set; }
|
||||
[DataMember]
|
||||
public uint Magic { get; set; }
|
||||
public uint Magic { get; set; }
|
||||
[DataMember]
|
||||
public uint Order { get; set; }
|
||||
public uint Order { get; set; }
|
||||
[DataMember]
|
||||
public string Symbol { get; set; }
|
||||
public string Symbol { get; set; }
|
||||
[DataMember]
|
||||
public double Volume { get; set; }
|
||||
public double Volume { get; set; }
|
||||
[DataMember]
|
||||
public double Price { get; set; }
|
||||
public double Price { get; set; }
|
||||
[DataMember]
|
||||
public double Stoplimit { get; set; }
|
||||
public double Stoplimit { get; set; }
|
||||
[DataMember]
|
||||
public double Sl { get; set; }
|
||||
public double Sl { get; set; }
|
||||
[DataMember]
|
||||
public double Tp { get; set; }
|
||||
public double Tp { get; set; }
|
||||
[DataMember]
|
||||
public uint Deviation { get; set; }
|
||||
public uint Deviation { get; set; }
|
||||
[DataMember]
|
||||
public int Type { get; set; }
|
||||
public int Type { get; set; }
|
||||
[DataMember]
|
||||
public int Type_filling { get; set; }
|
||||
public int Type_filling { get; set; }
|
||||
[DataMember]
|
||||
public int Type_time { get; set; }
|
||||
public int Type_time { get; set; }
|
||||
[DataMember]
|
||||
public DateTime Expiration { get; set; }
|
||||
public DateTime Expiration { get; set; }
|
||||
[DataMember]
|
||||
public string Comment { get; set; }
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -9,12 +7,12 @@ namespace MTApiService
|
||||
{
|
||||
public class MtRegistryManager
|
||||
{
|
||||
private const string SOFTWARE = "Software";
|
||||
private const string APP_NAME = "MtApi";
|
||||
private const string PROFILES_REGKEY = "ConnectionProfiles";
|
||||
private const string HOST_REGVALUE_NAME = "Host";
|
||||
private const string PORT_REGVALUE_NAME = "Port";
|
||||
private const string SIGNATURE_REGVALUE_NAME = "MtSignature";
|
||||
private const string Software = "Software";
|
||||
private const string AppName = "MtApi";
|
||||
private const string ProfilesRegkey = "ConnectionProfiles";
|
||||
private const string HostRegvalueName = "Host";
|
||||
private const string PortRegvalueName = "Port";
|
||||
private const string SignatureRegvalueName = "MtSignature";
|
||||
|
||||
#region Public Methods
|
||||
public static IEnumerable<MtConnectionProfile> LoadConnectionProfiles()
|
||||
@@ -53,12 +51,12 @@ namespace MTApiService
|
||||
|
||||
string signature = null;
|
||||
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
|
||||
if (softwareRegKey != null)
|
||||
{
|
||||
using (softwareRegKey)
|
||||
{
|
||||
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
|
||||
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
|
||||
if (appRegKey != null)
|
||||
{
|
||||
using (appRegKey)
|
||||
@@ -73,7 +71,7 @@ namespace MTApiService
|
||||
{
|
||||
using (numberKey)
|
||||
{
|
||||
signature = numberKey.GetValue(SIGNATURE_REGVALUE_NAME).ToString();
|
||||
signature = numberKey.GetValue(SignatureRegvalueName).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +92,7 @@ namespace MTApiService
|
||||
return null;
|
||||
}
|
||||
|
||||
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
|
||||
var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
|
||||
|
||||
if (softwareRgKey == null)
|
||||
return null;
|
||||
@@ -105,35 +103,33 @@ namespace MTApiService
|
||||
{
|
||||
|
||||
//app name
|
||||
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true);
|
||||
if (appRegKey == null)
|
||||
var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
|
||||
|
||||
if (appRegKey != null)
|
||||
{
|
||||
appRegKey = softwareRgKey.CreateSubKey(APP_NAME);
|
||||
}
|
||||
|
||||
using (appRegKey)
|
||||
{
|
||||
//account name
|
||||
var accountKey = appRegKey.OpenSubKey(accountName, true);
|
||||
if (accountKey == null)
|
||||
using (appRegKey)
|
||||
{
|
||||
accountKey = appRegKey.CreateSubKey(accountName);
|
||||
}
|
||||
//account name
|
||||
var accountKey = appRegKey.OpenSubKey(accountName, true) ?? appRegKey.CreateSubKey(accountName);
|
||||
|
||||
using (accountKey)
|
||||
{
|
||||
//account number
|
||||
var numberKey = accountKey.OpenSubKey(accountNumber, true);
|
||||
if (numberKey == null)
|
||||
if (accountKey != null)
|
||||
{
|
||||
numberKey = accountKey.CreateSubKey(accountNumber);
|
||||
}
|
||||
using (accountKey)
|
||||
{
|
||||
//account number
|
||||
var numberKey = accountKey.OpenSubKey(accountNumber, true) ??
|
||||
accountKey.CreateSubKey(accountNumber);
|
||||
|
||||
using (numberKey)
|
||||
{
|
||||
numberKey.SetValue(SIGNATURE_REGVALUE_NAME, signature);
|
||||
if (numberKey != null)
|
||||
{
|
||||
using (numberKey)
|
||||
{
|
||||
numberKey.SetValue(SignatureRegvalueName, signature);
|
||||
|
||||
retVal = numberKey.ToString();
|
||||
retVal = numberKey.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,20 +138,19 @@ namespace MTApiService
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static bool ExportKey(string RegKey, string SavePath)
|
||||
public static bool ExportKey(string regKey, string savePath)
|
||||
{
|
||||
string path = "\"" + SavePath + "\"";
|
||||
string key = "\"" + RegKey + "\"";
|
||||
var path = $"\"{savePath}\"";
|
||||
var key = $"\"{regKey}\"";
|
||||
|
||||
Process proc = new Process();
|
||||
var proc = new Process();
|
||||
try
|
||||
{
|
||||
proc.StartInfo.FileName = "regedit.exe";
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc = Process.Start("regedit.exe", "/e " + path + " " + key + "");
|
||||
|
||||
if (proc != null)
|
||||
proc.WaitForExit();
|
||||
proc?.WaitForExit();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
@@ -163,8 +158,7 @@ namespace MTApiService
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (proc != null)
|
||||
proc.Dispose();
|
||||
proc?.Dispose();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -177,33 +171,38 @@ namespace MTApiService
|
||||
{
|
||||
List<MtConnectionProfile> profiles = null;
|
||||
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
|
||||
if (softwareRegKey != null)
|
||||
{
|
||||
using (softwareRegKey)
|
||||
{
|
||||
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
|
||||
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
|
||||
if (appRegKey != null)
|
||||
{
|
||||
using (appRegKey)
|
||||
{
|
||||
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
|
||||
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
|
||||
if (profilesRegKey != null)
|
||||
{
|
||||
using (profilesRegKey)
|
||||
{
|
||||
profiles = new List<MtConnectionProfile>();
|
||||
|
||||
foreach (string profileNameKey in profilesRegKey.GetSubKeyNames())
|
||||
foreach (var profileNameKey in profilesRegKey.GetSubKeyNames())
|
||||
{
|
||||
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileNameKey))
|
||||
var tempKey = profilesRegKey.OpenSubKey(profileNameKey);
|
||||
if (tempKey != null)
|
||||
{
|
||||
var profile = new MtConnectionProfile(profileNameKey);
|
||||
using (tempKey)
|
||||
{
|
||||
var profile = new MtConnectionProfile(profileNameKey)
|
||||
{
|
||||
Host = tempKey.GetValue(HostRegvalueName).ToString(),
|
||||
Port = (int) tempKey.GetValue(PortRegvalueName)
|
||||
};
|
||||
|
||||
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString();
|
||||
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
|
||||
|
||||
profiles.Add(profile);
|
||||
profiles.Add(profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,27 +219,33 @@ namespace MTApiService
|
||||
{
|
||||
MtConnectionProfile profile = null;
|
||||
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
|
||||
if (softwareRegKey != null)
|
||||
{
|
||||
using (softwareRegKey)
|
||||
{
|
||||
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
|
||||
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
|
||||
if (appRegKey != null)
|
||||
{
|
||||
using (appRegKey)
|
||||
{
|
||||
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
|
||||
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
|
||||
if (profilesRegKey != null)
|
||||
{
|
||||
using (profilesRegKey)
|
||||
{
|
||||
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileName))
|
||||
var tempKey = profilesRegKey.OpenSubKey(profileName);
|
||||
if (tempKey != null)
|
||||
{
|
||||
profile = new MtConnectionProfile(profileName);
|
||||
using (tempKey)
|
||||
{
|
||||
profile = new MtConnectionProfile(profileName)
|
||||
{
|
||||
Host = tempKey.GetValue(HostRegvalueName).ToString(),
|
||||
Port = (int) tempKey.GetValue(PortRegvalueName)
|
||||
};
|
||||
|
||||
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString();
|
||||
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +259,7 @@ namespace MTApiService
|
||||
|
||||
private static void SaveConnectionProfileToRegistry(MtConnectionProfile profile)
|
||||
{
|
||||
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
|
||||
var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
|
||||
|
||||
if (softwareRgKey == null)
|
||||
return;
|
||||
@@ -262,29 +267,30 @@ namespace MTApiService
|
||||
using (softwareRgKey)
|
||||
{
|
||||
//app name
|
||||
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true);
|
||||
if (appRegKey == null)
|
||||
var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
|
||||
|
||||
if (appRegKey != null)
|
||||
{
|
||||
appRegKey = softwareRgKey.CreateSubKey(APP_NAME);
|
||||
}
|
||||
|
||||
using (appRegKey)
|
||||
{
|
||||
//ConnectionProfiles key
|
||||
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
|
||||
if (profilesRegKey == null)
|
||||
using (appRegKey)
|
||||
{
|
||||
profilesRegKey = appRegKey.CreateSubKey(PROFILES_REGKEY);
|
||||
}
|
||||
//ConnectionProfiles key
|
||||
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true) ??
|
||||
appRegKey.CreateSubKey(ProfilesRegkey);
|
||||
|
||||
using (profilesRegKey)
|
||||
{
|
||||
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
|
||||
|
||||
using (profileKey)
|
||||
if (profilesRegKey != null)
|
||||
{
|
||||
profileKey.SetValue(HOST_REGVALUE_NAME, profile.Host);
|
||||
profileKey.SetValue(PORT_REGVALUE_NAME, profile.Port);
|
||||
using (profilesRegKey)
|
||||
{
|
||||
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
|
||||
if (profileKey != null)
|
||||
{
|
||||
using (profileKey)
|
||||
{
|
||||
profileKey.SetValue(HostRegvalueName, profile.Host);
|
||||
profileKey.SetValue(PortRegvalueName, profile.Port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,19 +299,19 @@ namespace MTApiService
|
||||
|
||||
private static void DeleteConnectionProfileFromRegistry(string profileName)
|
||||
{
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true);
|
||||
var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
|
||||
if (softwareRegKey == null)
|
||||
return;
|
||||
|
||||
using (softwareRegKey)
|
||||
{
|
||||
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true);
|
||||
var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
|
||||
if (appRegKey == null)
|
||||
return;
|
||||
|
||||
using (appRegKey)
|
||||
{
|
||||
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
|
||||
var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
|
||||
if (profilesRegKey == null)
|
||||
return;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
@@ -21,6 +20,8 @@ namespace MTApiService
|
||||
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray),
|
||||
typeof(MtResponseMqlBookInfoArray)};
|
||||
}
|
||||
|
||||
public abstract object GetValue();
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -33,6 +34,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public int Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -45,6 +53,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public long Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -57,6 +72,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public ulong Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -69,6 +91,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public double Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -81,6 +110,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public string Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -93,6 +129,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public bool Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -105,6 +148,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public double[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -117,6 +167,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public int[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -129,6 +186,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public long[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -141,6 +205,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public ArrayList Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -153,6 +224,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public MtMqlRates[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -165,6 +243,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public MtMqlTick Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
@@ -177,6 +262,13 @@ namespace MTApiService
|
||||
|
||||
[DataMember]
|
||||
public MtMqlBookInfo[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+197
-107
@@ -3,17 +3,26 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.Net;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.Net.Sockets;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
internal class MtServer : IDisposable, IMtApiServer
|
||||
{
|
||||
#region Constants
|
||||
private const int WAIT_RESPONSE_TIME = 40000; // 40 sec
|
||||
private const int STOP_EXPERT_INTERVAL = 1000; // 1 sec
|
||||
private const int WaitResponseTime = 40000; // 40 sec
|
||||
private const int StopExpertInterval = 1000; // 1 sec
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServer));
|
||||
|
||||
private readonly MtService _service;
|
||||
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
|
||||
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
|
||||
private readonly List<MtExpert> _experts = new List<MtExpert>();
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
@@ -25,99 +34,126 @@ namespace MTApiService
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public int Port { get; private set; }
|
||||
public int Port { get; }
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public void Start()
|
||||
{
|
||||
Log.Debug("Start: begin");
|
||||
|
||||
var hostsInitialized = InitHosts(Port);
|
||||
if (hostsInitialized == false)
|
||||
{
|
||||
Debug.WriteLine("Start: InitHosts failed. ");
|
||||
}
|
||||
|
||||
Log.DebugFormat("Start: end. hostsInitialized = {0}", hostsInitialized);
|
||||
}
|
||||
|
||||
private bool InitHosts(int port)
|
||||
{
|
||||
Log.DebugFormat("InitHosts: begin. port = {0}", port);
|
||||
|
||||
int count;
|
||||
|
||||
lock (_hosts)
|
||||
{
|
||||
if (_hosts.Count > 0)
|
||||
{
|
||||
Log.Info("InitHosts: end. Host's has been initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
//init local pipe host
|
||||
string localUrl = CreateConnectionAddress(null, port, true);
|
||||
ServiceHost localServiceHost = CreateServiceHost(localUrl, true);
|
||||
var localUrl = CreateConnectionAddress(null, port, true);
|
||||
var localServiceHost = CreateServiceHost(localUrl, true);
|
||||
if (localServiceHost != null)
|
||||
{
|
||||
_hosts.Add(localServiceHost);
|
||||
}
|
||||
|
||||
//init network hosts
|
||||
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
|
||||
if (ips != null)
|
||||
var dnsHostName = Dns.GetHostName();
|
||||
var ips = Dns.GetHostEntry(dnsHostName);
|
||||
if (ips == null)
|
||||
{
|
||||
foreach (IPAddress ipAddress in ips.AddressList)
|
||||
Log.WarnFormat("InitHosts: end. Dns.GetHostEntry has returned null for DNS Host Name {0}", dnsHostName);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var ipAddress in ips.AddressList)
|
||||
{
|
||||
if (ipAddress?.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
if (ipAddress != null)
|
||||
var ip = ipAddress.ToString();
|
||||
var networkUrl = CreateConnectionAddress(ip, port, false);
|
||||
var serviceHost = CreateServiceHost(networkUrl, false);
|
||||
if (serviceHost != null)
|
||||
{
|
||||
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
string ip = ipAddress.ToString();
|
||||
string networkUrl = CreateConnectionAddress(ip, port, false);
|
||||
ServiceHost serviceHost = CreateServiceHost(networkUrl, false);
|
||||
if (serviceHost != null)
|
||||
{
|
||||
_hosts.Add(serviceHost);
|
||||
}
|
||||
}
|
||||
_hosts.Add(serviceHost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = _hosts.Count;
|
||||
}
|
||||
|
||||
Log.DebugFormat("InitHosts: end. Host's count = {0}", count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private ServiceHost CreateServiceHost(string serverUrlAdress, bool local)
|
||||
{
|
||||
ServiceHost serviceHost = null;
|
||||
if (serverUrlAdress != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
serviceHost = new ServiceHost(_service);
|
||||
var binding = CreateConnectionBinding(local);
|
||||
Log.DebugFormat("CreateServiceHost: begin. serverUrlAdress = {0}; local = {1}", serverUrlAdress, local);
|
||||
|
||||
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
|
||||
serviceHost.Open();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Debug.WriteLine("CreateServiceHost: Create ServiceHost failed. " + e.Message);
|
||||
}
|
||||
if (serverUrlAdress == null)
|
||||
{
|
||||
Log.Warn("CreateServiceHost: end. serverUrlAdress is not defined");
|
||||
return null;
|
||||
}
|
||||
|
||||
ServiceHost serviceHost;
|
||||
try
|
||||
{
|
||||
serviceHost = new ServiceHost(_service);
|
||||
var binding = CreateConnectionBinding(local);
|
||||
|
||||
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
|
||||
serviceHost.Open();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.ErrorFormat("CreateServiceHost: Error! {0}", e.Message);
|
||||
serviceHost = null;
|
||||
}
|
||||
|
||||
Log.Debug("CreateServiceHost: end.");
|
||||
|
||||
return serviceHost;
|
||||
}
|
||||
|
||||
public void AddExpert(MtExpert expert)
|
||||
{
|
||||
if (expert != null)
|
||||
Log.DebugFormat("AddExpert: begin. expert {0}", expert);
|
||||
|
||||
if (expert == null)
|
||||
{
|
||||
expert.Deinited += expert_Deinited;
|
||||
expert.QuoteChanged += expert_QuoteChanged;
|
||||
expert.OnMtEvent += Expert_OnMtEvent;
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
_experts.Add(expert);
|
||||
}
|
||||
|
||||
_executorManager.AddCommandExecutor(expert);
|
||||
|
||||
_service.OnQuoteAdded(expert.Quote);
|
||||
Log.Warn("AddExpert: end. expert is not defined");
|
||||
return;
|
||||
}
|
||||
|
||||
expert.Deinited += expert_Deinited;
|
||||
expert.QuoteChanged += expert_QuoteChanged;
|
||||
expert.OnMtEvent += Expert_OnMtEvent;
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
_experts.Add(expert);
|
||||
}
|
||||
|
||||
_executorManager.AddCommandExecutor(expert);
|
||||
|
||||
_service.OnQuoteAdded(expert.Quote);
|
||||
|
||||
Log.Debug("AddExpert: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -126,25 +162,30 @@ namespace MTApiService
|
||||
|
||||
public MtResponse SendCommand(MtCommand command)
|
||||
{
|
||||
MtResponse response = null;
|
||||
Log.DebugFormat("SendCommand: begin. command {0}", command);
|
||||
|
||||
if (command != null)
|
||||
if (command == null)
|
||||
{
|
||||
var task = new MtCommandTask(command);
|
||||
_executorManager.EnqueueCommandTask(task);
|
||||
|
||||
//wait for execute command in MetaTrader
|
||||
response = task.WaitResult(WAIT_RESPONSE_TIME);
|
||||
Log.Warn("SendCommand: end. command is not defined");
|
||||
return null;
|
||||
}
|
||||
|
||||
var task = new MtCommandTask(command);
|
||||
_executorManager.EnqueueCommandTask(task);
|
||||
|
||||
//wait for execute command in MetaTrader
|
||||
var response = task.WaitResult(WaitResponseTime);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
public List<MtQuote> GetQuotes()
|
||||
{
|
||||
Log.Debug("GetQuotes: called");
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
return (from s in _experts select s.Quote);
|
||||
return _experts.Select(s => s.Quote).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,99 +194,131 @@ namespace MTApiService
|
||||
#region Private Methods
|
||||
private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
var expertsCount = 0;
|
||||
Log.DebugFormat("stopTimer_Elapsed: begin");
|
||||
|
||||
int expertsCount;
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
expertsCount = _experts.Count();
|
||||
expertsCount = _experts.Count;
|
||||
}
|
||||
|
||||
if (expertsCount == 0)
|
||||
{
|
||||
_service.OnStopServer();
|
||||
|
||||
Log.DebugFormat("stopTimer_Elapsed: experts count is 0. Call Stop().");
|
||||
|
||||
Stop();
|
||||
}
|
||||
|
||||
var stopTimer = sender as System.Timers.Timer;
|
||||
if (stopTimer != null)
|
||||
{
|
||||
stopTimer.Stop();
|
||||
stopTimer.Elapsed -= stopTimer_Elapsed;
|
||||
}
|
||||
if (stopTimer == null) return;
|
||||
|
||||
stopTimer.Stop();
|
||||
stopTimer.Elapsed -= stopTimer_Elapsed;
|
||||
|
||||
Log.DebugFormat("stopTimer_Elapsed: end");
|
||||
}
|
||||
|
||||
private string CreateConnectionAddress(string host, int port, bool local)
|
||||
private static string CreateConnectionAddress(string host, int port, bool local)
|
||||
{
|
||||
Log.DebugFormat("CreateConnectionAddress: begin. host = {0}, port = {1}, local = {2}", host, port, local);
|
||||
|
||||
string connectionAddress = null;
|
||||
|
||||
if (local == true)
|
||||
if (local)
|
||||
{
|
||||
//by Pipe
|
||||
connectionAddress = "net.pipe://localhost/MtApiService_" + port.ToString();
|
||||
connectionAddress = "net.pipe://localhost/MtApiService_" + port;
|
||||
}
|
||||
else
|
||||
{
|
||||
//by Socket
|
||||
if (host != null)
|
||||
{
|
||||
connectionAddress = "net.tcp://" + host.ToString() + ":" + port.ToString() + "/MtApiService";
|
||||
}
|
||||
connectionAddress = "net.tcp://" + host + ":" + port + "/MtApiService";
|
||||
}
|
||||
}
|
||||
|
||||
Log.DebugFormat("CreateConnectionAddress: end. connectionAddress = {0}", connectionAddress);
|
||||
|
||||
return connectionAddress;
|
||||
}
|
||||
|
||||
private static Binding CreateConnectionBinding(bool local)
|
||||
{
|
||||
Binding connectionBinding = null;
|
||||
Log.DebugFormat("CreateConnectionBinding: begin. local = {0}", local);
|
||||
|
||||
if (local == true)
|
||||
Binding connectionBinding;
|
||||
|
||||
if (local)
|
||||
{
|
||||
//by Pipe
|
||||
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
|
||||
bind.MaxReceivedMessageSize = 2147483647;
|
||||
bind.MaxBufferSize = 2147483647;
|
||||
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
|
||||
{
|
||||
MaxReceivedMessageSize = 2147483647,
|
||||
MaxBufferSize = 2147483647,
|
||||
MaxBufferPoolSize = 2147483647,
|
||||
SendTimeout = new TimeSpan(12, 0, 0),
|
||||
ReceiveTimeout = new TimeSpan(12, 0, 0),
|
||||
ReaderQuotas =
|
||||
{
|
||||
MaxArrayLength = 2147483647,
|
||||
MaxBytesPerRead = 2147483647,
|
||||
MaxDepth = 2147483647,
|
||||
MaxStringContentLength = 2147483647,
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
|
||||
// Commented next statement since it is not required
|
||||
bind.MaxBufferPoolSize = 2147483647;
|
||||
bind.ReaderQuotas.MaxArrayLength = 2147483647;
|
||||
bind.ReaderQuotas.MaxBytesPerRead = 2147483647;
|
||||
bind.ReaderQuotas.MaxDepth = 2147483647;
|
||||
bind.ReaderQuotas.MaxStringContentLength = 2147483647;
|
||||
bind.ReaderQuotas.MaxNameTableCharCount = 2147483647;
|
||||
|
||||
connectionBinding = bind;
|
||||
}
|
||||
else
|
||||
{
|
||||
//by Socket
|
||||
var bind = new NetTcpBinding(SecurityMode.None);
|
||||
bind.MaxReceivedMessageSize = 2147483647;
|
||||
bind.MaxBufferSize = 2147483647;
|
||||
var bind = new NetTcpBinding(SecurityMode.None)
|
||||
{
|
||||
MaxReceivedMessageSize = 2147483647,
|
||||
MaxBufferSize = 2147483647,
|
||||
MaxBufferPoolSize = 2147483647,
|
||||
SendTimeout = new TimeSpan(12, 0, 0),
|
||||
ReceiveTimeout = new TimeSpan(12, 0, 0),
|
||||
ReaderQuotas =
|
||||
{
|
||||
MaxArrayLength = 2147483647,
|
||||
MaxBytesPerRead = 2147483647,
|
||||
MaxDepth = 2147483647,
|
||||
MaxStringContentLength = 2147483647,
|
||||
MaxNameTableCharCount = 2147483647
|
||||
}
|
||||
};
|
||||
|
||||
// Commented next statement since it is not required
|
||||
bind.MaxBufferPoolSize = 2147483647;
|
||||
bind.ReaderQuotas.MaxArrayLength = 2147483647;
|
||||
bind.ReaderQuotas.MaxBytesPerRead = 2147483647;
|
||||
bind.ReaderQuotas.MaxDepth = 2147483647;
|
||||
bind.ReaderQuotas.MaxStringContentLength = 2147483647;
|
||||
bind.ReaderQuotas.MaxNameTableCharCount = 2147483647;
|
||||
|
||||
connectionBinding = bind;
|
||||
}
|
||||
|
||||
Log.Debug("CreateConnectionBinding: end.");
|
||||
|
||||
return connectionBinding;
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
Log.Debug("Stop: begin.");
|
||||
|
||||
_executorManager.Stop();
|
||||
|
||||
lock (_hosts)
|
||||
{
|
||||
if (_hosts.Count == 0)
|
||||
{
|
||||
Log.Debug("Stop: end. Host count is 0.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -254,15 +327,18 @@ namespace MTApiService
|
||||
host.Close();
|
||||
}
|
||||
}
|
||||
catch (TimeoutException)
|
||||
catch (TimeoutException ex)
|
||||
{
|
||||
Log.ErrorFormat("Stop: TimeoutException - {0}", ex.Message);
|
||||
|
||||
foreach (var host in _hosts)
|
||||
{
|
||||
host.Abort();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorFormat("Stop: Exception - {0}", ex.Message);
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
@@ -272,20 +348,27 @@ namespace MTApiService
|
||||
}
|
||||
|
||||
FireOnStopped();
|
||||
|
||||
Log.Debug("Stop: end.");
|
||||
}
|
||||
|
||||
private void expert_Deinited(object sender, EventArgs e)
|
||||
{
|
||||
if (sender == null)
|
||||
return;
|
||||
Log.Debug("expert_Deinited: begin.");
|
||||
|
||||
var expert = (MtExpert)sender;
|
||||
var expertsCount = 0;
|
||||
var expert = sender as MtExpert;
|
||||
if (expert == null)
|
||||
{
|
||||
Log.Warn("expert_Deinited: end. Expert is not defined.");
|
||||
return;
|
||||
}
|
||||
|
||||
int expertsCount;
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
_experts.Remove(expert);
|
||||
expertsCount = _experts.Count();
|
||||
expertsCount = _experts.Count;
|
||||
}
|
||||
|
||||
_executorManager.RemoveCommandExecutor(expert);
|
||||
@@ -299,19 +382,29 @@ namespace MTApiService
|
||||
{
|
||||
var stopTimer = new System.Timers.Timer();
|
||||
stopTimer.Elapsed += stopTimer_Elapsed;
|
||||
stopTimer.Interval = STOP_EXPERT_INTERVAL;
|
||||
stopTimer.Interval = StopExpertInterval;
|
||||
stopTimer.Start();
|
||||
}
|
||||
|
||||
Log.Debug("expert_Deinited: end.");
|
||||
}
|
||||
|
||||
private void expert_QuoteChanged(MtExpert expert, MtQuote quote)
|
||||
{
|
||||
Log.DebugFormat("expert_QuoteChanged: begin. expert = {0}, quote = {1}", expert, quote);
|
||||
|
||||
_service.QuoteUpdate(quote);
|
||||
|
||||
Log.Debug("expert_QuoteChanged: end.");
|
||||
}
|
||||
|
||||
private void Expert_OnMtEvent(object sender, MtEventArgs e)
|
||||
{
|
||||
Log.DebugFormat("Expert_OnMtEvent: begin. event = {0}", e.Event);
|
||||
|
||||
_service.OnMtEvent(e.Event);
|
||||
|
||||
Log.Debug("Expert_OnMtEvent: end.");
|
||||
}
|
||||
|
||||
private void FireOnStopped()
|
||||
@@ -328,16 +421,13 @@ namespace MTApiService
|
||||
#region IDispose
|
||||
public void Dispose()
|
||||
{
|
||||
Log.Debug("Dispose: begin");
|
||||
|
||||
Stop();
|
||||
|
||||
Log.Debug("Dispose: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private readonly MtService _service;
|
||||
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
|
||||
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
|
||||
private readonly List<MtExpert> _experts = new List<MtExpert>();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ServiceModel;
|
||||
using System.Net;
|
||||
using System.Diagnostics;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
public class MtServerInstance
|
||||
{
|
||||
#region Init_Instance
|
||||
#region Fields
|
||||
private const string LogProfileName = "MtApiService";
|
||||
|
||||
static readonly MtServerInstance mInstance = new MtServerInstance();
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance));
|
||||
private static readonly MtServerInstance Instance = new MtServerInstance();
|
||||
|
||||
private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>();
|
||||
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
|
||||
#endregion
|
||||
|
||||
#region Init Instance
|
||||
|
||||
private MtServerInstance()
|
||||
{
|
||||
{
|
||||
LogConfigurator.Setup(LogProfileName);
|
||||
}
|
||||
|
||||
static MtServerInstance()
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
public static MtServerInstance GetInstance()
|
||||
{
|
||||
return mInstance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -33,20 +38,23 @@ namespace MTApiService
|
||||
#region Public Methods
|
||||
public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::InitExpert: symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
|
||||
if (mtHandler == null)
|
||||
throw new ArgumentNullException(nameof(mtHandler));
|
||||
|
||||
MtServer server = null;
|
||||
lock (mServersDictionary)
|
||||
Log.InfoFormat("InitExpert: begin. symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
|
||||
|
||||
MtServer server;
|
||||
lock (_servers)
|
||||
{
|
||||
if (mServersDictionary.ContainsKey(port))
|
||||
if (_servers.ContainsKey(port))
|
||||
{
|
||||
server = mServersDictionary[port];
|
||||
server = _servers[port];
|
||||
}
|
||||
else
|
||||
{
|
||||
server = new MtServer(port);
|
||||
server.Stopped += new EventHandler(server_Stopped);
|
||||
mServersDictionary[port] = server;
|
||||
server.Stopped += server_Stopped;
|
||||
_servers[port] = server;
|
||||
|
||||
server.Start();
|
||||
}
|
||||
@@ -54,137 +62,172 @@ namespace MTApiService
|
||||
|
||||
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
|
||||
|
||||
lock (mExpertsDictionary)
|
||||
lock (_experts)
|
||||
{
|
||||
mExpertsDictionary[expert.Handle] = expert;
|
||||
_experts[expert.Handle] = expert;
|
||||
}
|
||||
|
||||
server.AddExpert(expert);
|
||||
|
||||
Log.Info("InitExpert: end");
|
||||
}
|
||||
|
||||
public void DeinitExpert(int expertHandle)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::DeinitExpert: expertHandle = {0}", expertHandle);
|
||||
Log.InfoFormat("DeinitExpert: begin. expertHandle = {0}", expertHandle);
|
||||
|
||||
MtExpert expert = null;
|
||||
|
||||
lock (mExpertsDictionary)
|
||||
lock (_experts)
|
||||
{
|
||||
if (mExpertsDictionary.ContainsKey(expertHandle) == true)
|
||||
if (_experts.ContainsKey(expertHandle))
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
mExpertsDictionary.Remove(expertHandle);
|
||||
expert = _experts[expertHandle];
|
||||
_experts.Remove(expertHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.Deinit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("DeinitExpert: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Log.Info("DeinitExpert: end");
|
||||
}
|
||||
|
||||
public void SendQuote(int expertHandle, string symbol, double bid, double ask)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::SendQuote: enter. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
|
||||
Log.DebugFormat("SendQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.Quote = new MtQuote(symbol, bid, ask);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("SendQuote: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Debug.WriteLine("MtApiServerInstance::SendQuote: finish.");
|
||||
Log.Debug("SendQuote: end");
|
||||
}
|
||||
|
||||
public void SendEvent(int expertHandle, int eventType, string payload)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::SendEvent called. eventType = {0}, payload = {1}", eventType, payload);
|
||||
Log.DebugFormat("SendEvent: begin. eventType = {0}, payload = {1}", eventType, payload);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.SendEvent(new MtEvent(eventType, payload));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("SendEvent: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Debug.WriteLine("MtApiServerInstance::SendEvent: finished");
|
||||
Log.Debug("SendEvent: end");
|
||||
}
|
||||
|
||||
public void SendResponse(int expertHandle, MtResponse response)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response);
|
||||
Log.DebugFormat("SendResponse: begin. id = {0}, response = {1}", expertHandle, response);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
if (expert != null)
|
||||
{
|
||||
expert.SendResponse(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WarnFormat("SendResponse: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
Debug.WriteLine("MtApiServerInstance::SendResponse: finish");
|
||||
Log.Debug("SendResponse: end");
|
||||
}
|
||||
|
||||
public int GetCommandType(int expertHandle)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::GetCommandType: expertHandle = {0}", expertHandle);
|
||||
Log.DebugFormat("GetCommandType: begin. expertHandle = {0}", expertHandle);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
return (expert != null) ? expert.GetCommandType() : 0;
|
||||
if (expert == null)
|
||||
{
|
||||
Log.WarnFormat("GetCommandType: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
var retval = expert?.GetCommandType() ?? 0;
|
||||
|
||||
Log.DebugFormat("GetCommandType: end. retval = {0}", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
public object GetCommandParameter(int expertHandle, int index)
|
||||
{
|
||||
Debug.WriteLine("MtApiServerInstance::GetCommandParameter: expertHandle = {0}, index = {1}", expertHandle, index);
|
||||
Log.DebugFormat("GetCommandParameter: begin. expertHandle = {0}, index = {1}", expertHandle, index);
|
||||
|
||||
MtExpert expert = null;
|
||||
lock (mExpertsDictionary)
|
||||
MtExpert expert;
|
||||
lock (_experts)
|
||||
{
|
||||
expert = mExpertsDictionary[expertHandle];
|
||||
expert = _experts[expertHandle];
|
||||
}
|
||||
|
||||
return (expert != null) ? expert.GetCommandParameter(index) : null;
|
||||
if (expert == null)
|
||||
{
|
||||
Log.WarnFormat("GetCommandParameter: expert with id {0} has not been found.", expertHandle);
|
||||
}
|
||||
|
||||
var retval = expert?.GetCommandParameter(index);
|
||||
|
||||
Log.DebugFormat("GetCommandParameter: end. retval = {0}", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void server_Stopped(object sender, EventArgs e)
|
||||
{
|
||||
MtServer server = (MtServer)sender;
|
||||
var server = (MtServer)sender;
|
||||
server.Stopped -= server_Stopped;
|
||||
|
||||
var port = server.Port;
|
||||
lock (mServersDictionary)
|
||||
|
||||
Log.InfoFormat("server_Stopped: port = {0}", port);
|
||||
|
||||
lock (_servers)
|
||||
{
|
||||
if (mServersDictionary.ContainsKey(port))
|
||||
if (_servers.ContainsKey(port))
|
||||
{
|
||||
mServersDictionary.Remove(port);
|
||||
_servers.Remove(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private readonly MtRegistryManager mConnectionManager = new MtRegistryManager();
|
||||
private readonly Dictionary<int, MtServer> mServersDictionary = new Dictionary<int, MtServer>();
|
||||
private readonly Dictionary<int, MtExpert> mExpertsDictionary = new Dictionary<int, MtExpert>();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+96
-45
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
@@ -18,7 +19,7 @@ namespace MTApiService
|
||||
MtResponse SendCommand(MtCommand command);
|
||||
|
||||
[OperationContract]
|
||||
IEnumerable<MtQuote> GetQuotes();
|
||||
List<MtQuote> GetQuotes();
|
||||
}
|
||||
|
||||
[ServiceContract]
|
||||
@@ -46,107 +47,149 @@ namespace MTApiService
|
||||
InstanceContextMode = InstanceContextMode.Single)]
|
||||
public sealed class MtService : IMtApi
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtService));
|
||||
|
||||
public MtService(IMtApiServer serverCallback)
|
||||
{
|
||||
if (serverCallback == null)
|
||||
throw new ArgumentNullException("serverCallback");
|
||||
throw new ArgumentNullException(nameof(serverCallback));
|
||||
|
||||
mServer = serverCallback;
|
||||
_server = serverCallback;
|
||||
}
|
||||
|
||||
#region IMtApi
|
||||
public bool Connect()
|
||||
{
|
||||
bool connected = false;
|
||||
Log.Debug("Connect: begin");
|
||||
|
||||
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
|
||||
var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
|
||||
|
||||
if (callback != null)
|
||||
if (callback == null)
|
||||
{
|
||||
Log.Warn("Connect: end. Callback is not definded.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var connected = false;
|
||||
|
||||
try
|
||||
{
|
||||
_clientsLocker.AcquireWriterLock(10000);
|
||||
|
||||
try
|
||||
{
|
||||
mClientsLocker.AcquireWriterLock(10000);
|
||||
if (_clientCallbacks.Contains(callback) == false)
|
||||
_clientCallbacks.Add(callback);
|
||||
|
||||
try
|
||||
{
|
||||
if (mClientCallbacks.Contains(callback) == false)
|
||||
mClientCallbacks.Add(callback);
|
||||
|
||||
connected = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mClientsLocker.ReleaseWriterLock();
|
||||
}
|
||||
connected = true;
|
||||
}
|
||||
catch (ApplicationException)
|
||||
finally
|
||||
{
|
||||
_clientsLocker.ReleaseWriterLock();
|
||||
}
|
||||
}
|
||||
catch (ApplicationException ex)
|
||||
{
|
||||
Log.ErrorFormat("Connect: ApplicationException - {0}", ex.Message);
|
||||
}
|
||||
|
||||
Log.DebugFormat("Connect: end. connected = {0}", connected);
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
|
||||
Log.Debug("Disconnect: begin");
|
||||
|
||||
if (callback != null)
|
||||
var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
|
||||
|
||||
if (callback == null)
|
||||
{
|
||||
Log.Warn("Disconnect: end. Callback is not definded.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_clientsLocker.AcquireWriterLock(10000);
|
||||
|
||||
try
|
||||
{
|
||||
mClientsLocker.AcquireWriterLock(10000);
|
||||
|
||||
try
|
||||
{
|
||||
mClientCallbacks.Remove(callback);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mClientsLocker.ReleaseWriterLock();
|
||||
}
|
||||
_clientCallbacks.Remove(callback);
|
||||
}
|
||||
catch (ApplicationException)
|
||||
finally
|
||||
{
|
||||
_clientsLocker.ReleaseWriterLock();
|
||||
}
|
||||
}
|
||||
catch (ApplicationException ex)
|
||||
{
|
||||
Log.ErrorFormat("Disconnect: ApplicationException - {0}", ex.Message);
|
||||
}
|
||||
|
||||
Log.Debug("Disconnect: end.");
|
||||
}
|
||||
|
||||
public MtResponse SendCommand(MtCommand command)
|
||||
{
|
||||
return mServer.SendCommand(command);
|
||||
Log.DebugFormat("SendCommand: called. command = {0}", command);
|
||||
|
||||
return _server.SendCommand(command);
|
||||
}
|
||||
|
||||
public IEnumerable<MtQuote> GetQuotes()
|
||||
public List<MtQuote> GetQuotes()
|
||||
{
|
||||
return mServer.GetQuotes();
|
||||
Log.Debug("GetQuotes: called.");
|
||||
|
||||
return _server.GetQuotes();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public void OnStopServer()
|
||||
{
|
||||
Log.Debug("OnStopServer: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnServerStopped());
|
||||
|
||||
Log.Debug("OnStopServer: end.");
|
||||
}
|
||||
|
||||
public void QuoteUpdate(MtQuote quote)
|
||||
{
|
||||
Log.Debug("QuoteUpdate: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
|
||||
|
||||
Log.Debug("QuoteUpdate: end.");
|
||||
}
|
||||
|
||||
public void OnQuoteAdded(MtQuote quote)
|
||||
{
|
||||
Log.Debug("OnQuoteAdded: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
|
||||
|
||||
Log.Debug("OnQuoteAdded: end.");
|
||||
}
|
||||
|
||||
public void OnQuoteRemoved(MtQuote quote)
|
||||
{
|
||||
Log.Debug("OnQuoteRemoved: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
|
||||
|
||||
Log.Debug("OnQuoteRemoved: end.");
|
||||
}
|
||||
|
||||
public void OnMtEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.Debug("OnMtEvent: begin.");
|
||||
|
||||
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
|
||||
|
||||
Log.Debug("OnMtEvent: end.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -154,22 +197,26 @@ namespace MTApiService
|
||||
|
||||
private void ExecuteCallbackAction(Action<IMtApiCallback> action)
|
||||
{
|
||||
Log.Debug("ExecuteCallbackAction: begin.");
|
||||
|
||||
try
|
||||
{
|
||||
mClientsLocker.AcquireReaderLock(2000);
|
||||
_clientsLocker.AcquireReaderLock(2000);
|
||||
|
||||
List<IMtApiCallback> crashedClientCallbacks = null;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var callback in mClientCallbacks)
|
||||
foreach (var callback in _clientCallbacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(callback);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorFormat("ExecuteCallbackAction: Exception - {0}", ex.Message);
|
||||
|
||||
if (crashedClientCallbacks == null)
|
||||
crashedClientCallbacks = new List<IMtApiCallback>();
|
||||
|
||||
@@ -179,29 +226,33 @@ namespace MTApiService
|
||||
|
||||
if (crashedClientCallbacks != null)
|
||||
{
|
||||
Log.WarnFormat("ExecuteCallbackAction: crashed callback count = {0}", crashedClientCallbacks.Count);
|
||||
|
||||
foreach (var crashedCallback in crashedClientCallbacks)
|
||||
{
|
||||
mClientCallbacks.Remove(crashedCallback);
|
||||
_clientCallbacks.Remove(crashedCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mClientsLocker.ReleaseReaderLock();
|
||||
_clientsLocker.ReleaseReaderLock();
|
||||
}
|
||||
}
|
||||
catch (ApplicationException)
|
||||
catch (ApplicationException ex)
|
||||
{
|
||||
//TODO: add logging
|
||||
Log.ErrorFormat("ExecuteCallbackAction: ApplicationException - {0}", ex.Message);
|
||||
}
|
||||
|
||||
Log.Debug("ExecuteCallbackAction: end.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private readonly IMtApiServer mServer;
|
||||
private readonly List<IMtApiCallback> mClientCallbacks = new List<IMtApiCallback>();
|
||||
private readonly ReaderWriterLock mClientsLocker = new ReaderWriterLock();
|
||||
private readonly IMtApiServer _server;
|
||||
private readonly List<IMtApiCallback> _clientCallbacks = new List<IMtApiCallback>();
|
||||
private readonly ReaderWriterLock _clientsLocker = new ReaderWriterLock();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.21.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.21.0")]
|
||||
[assembly: AssemblyVersion("1.0.23.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.23.0")]
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ILMerge" version="2.13.0307" targetFramework="net40" />
|
||||
<package id="log4net" version="2.0.5" targetFramework="net40" />
|
||||
<package id="MSBuild.ILMerge.Task" version="1.0.5" targetFramework="net40" />
|
||||
</packages>
|
||||
+187
-158
@@ -19,56 +19,56 @@ using namespace System::Diagnostics;
|
||||
|
||||
void convertSystemString(wchar_t* dest, String^ src)
|
||||
{
|
||||
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
|
||||
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
|
||||
dest[wcslen(wch)] = '\0';
|
||||
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
|
||||
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
|
||||
dest[wcslen(wch)] = '\0';
|
||||
}
|
||||
|
||||
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
MT4Handler^ mtHandler = gcnew MT4Handler();
|
||||
try
|
||||
{
|
||||
MT4Handler^ mtHandler = gcnew MT4Handler();
|
||||
|
||||
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:initExpert(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:initExpert(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall deinitExpert(int expertHandle, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:deinitExpert(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:deinitExpert(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:updateQuote(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
convertSystemString(err, e->Message);
|
||||
Debug::WriteLine("[ERROR] MTConnector:updateQuote(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,170 +89,199 @@ int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_
|
||||
|
||||
int _stdcall sendIntResponse(int expertHandle, int response)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendBooleanResponse(int expertHandle, int response)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool value = (response != 0) ? true : false;
|
||||
try
|
||||
{
|
||||
bool value = (response != 0) ? true : false;
|
||||
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendBooleanResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendBooleanResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendDoubleResponse(int expertHandle, double response)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendDoubleResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendDoubleResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendStringResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendStringResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendVoidResponse(int expertHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendVoidResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendVoidResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
|
||||
{
|
||||
try
|
||||
{
|
||||
array<double>^ list = gcnew array<double>(size);
|
||||
try
|
||||
{
|
||||
array<double>^ list = gcnew array<double>(size);
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
list[i] = values[i];
|
||||
}
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
list[i] = values[i];
|
||||
}
|
||||
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendDoubleArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendDoubleArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
|
||||
{
|
||||
try
|
||||
{
|
||||
array<int>^ list = gcnew array<int>(size);
|
||||
try
|
||||
{
|
||||
array<int>^ list = gcnew array<int>(size);
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
list[i] = values[i];
|
||||
}
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
list[i] = values[i];
|
||||
}
|
||||
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall sendLongResponse(int expertHandle, __int64 response)
|
||||
{
|
||||
try
|
||||
{
|
||||
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:sendLongResponse(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall getCommandType(int expertHandle, int* res)
|
||||
{
|
||||
try
|
||||
{
|
||||
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getCommandType(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getCommandType(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
|
||||
{
|
||||
try
|
||||
{
|
||||
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getIntValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getIntValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
|
||||
{
|
||||
try
|
||||
{
|
||||
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getDoubleValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getDoubleValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
|
||||
{
|
||||
try
|
||||
{
|
||||
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getStringValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MTConnector:getStringValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
|
||||
*res = val == true ? 1 : 0;
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
+14
-12
@@ -3,15 +3,17 @@ LIBRARY MTConnector
|
||||
EXPORTS initExpert
|
||||
deinitExpert
|
||||
updateQuote
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
sendEvent
|
||||
sendIntResponse
|
||||
sendBooleanResponse
|
||||
sendDoubleResponse
|
||||
sendStringResponse
|
||||
sendVoidResponse
|
||||
sendDoubleArrayResponse
|
||||
sendIntArrayResponse
|
||||
sendLongResponse
|
||||
getCommandType
|
||||
getIntValue
|
||||
getDoubleValue
|
||||
getStringValue
|
||||
getBooleanValue
|
||||
+37
-1
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApiClientUI", "TestClients\TestApiClientUI\TestApiClientUI.csproj", "{663CC515-EAAE-47D4-8933-5008C2DA1160}"
|
||||
EndProject
|
||||
@@ -37,6 +37,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MtApiSetupActions", "MtApiS
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestClients", "TestClients", "{B91FF338-E05D-4EF1-948B-A2376DB37ECA}"
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApi5Bootstrapper", "MtApi5Bootstrapper\MtApi5Bootstrapper.wixproj", "{1497E285-C228-490B-9638-565E118548FB}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A9ED070F-AB4D-4380-9DDE-5D931AC71333} = {A9ED070F-AB4D-4380-9DDE-5D931AC71333}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApiBootstrapper", "MtApiBootstrapper\MtApiBootstrapper.wixproj", "{8E63046B-56E5-4623-8808-558AD72A8F2B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{78B94552-DB17-40EC-B7C6-23D32DB85DC1} = {78B94552-DB17-40EC-B7C6-23D32DB85DC1}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -196,6 +206,32 @@ Global
|
||||
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x64.ActiveCfg = Release|x86
|
||||
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x86.ActiveCfg = Release|x86
|
||||
{10800F37-F71B-4818-8351-8CF744295F80}.Release|x86.Build.0 = Release|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|Win32.ActiveCfg = Debug|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|Win32.Build.0 = Debug|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.Build.0 = Debug|x64
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Debug|x86.Build.0 = Debug|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Release|Win32.ActiveCfg = Release|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Release|Win32.Build.0 = Release|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Release|x64.ActiveCfg = Release|x64
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Release|x86.ActiveCfg = Release|x86
|
||||
{1497E285-C228-490B-9638-565E118548FB}.Release|x86.Build.0 = Release|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Win32.ActiveCfg = Debug|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|Win32.Build.0 = Debug|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x64.ActiveCfg = Debug|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Debug|x86.Build.0 = Debug|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Win32.ActiveCfg = Release|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|Win32.Build.0 = Release|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x64.ActiveCfg = Release|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.ActiveCfg = Release|x86
|
||||
{8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
namespace MtApi
|
||||
{
|
||||
public enum EnumSeriesInfoInteger
|
||||
{
|
||||
SERIES_BARS_COUNT = 0,
|
||||
SERIES_FIRSTDATE = 1,
|
||||
SERIES_LASTBAR_DATE = 5,
|
||||
SERIES_SERVER_FIRSTDATE = 2
|
||||
}
|
||||
}
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
namespace MtApi
|
||||
{
|
||||
// https://docs.mql4.com/constants/environment_state/marketinfoconstants#enum_symbol_info_double
|
||||
public enum EnumSymbolInfoDouble
|
||||
{
|
||||
SYMBOL_BID = 1, // Bid - best sell offer
|
||||
SYMBOL_BIDHIGH = 2, // Not supported
|
||||
SYMBOL_BIDLOW = 3, // Not supported
|
||||
SYMBOL_ASK = 4, // Ask - best buy offer
|
||||
SYMBOL_ASKHIGH = 5, // Not supported
|
||||
SYMBOL_ASKLOW = 6, // Not supported
|
||||
SYMBOL_LAST = 7, // Not supported
|
||||
SYMBOL_LASTHIGH = 8, // Not supported
|
||||
SYMBOL_LASTLOW = 9, // Not supported
|
||||
SYMBOL_POINT = 16, // Symbol point value
|
||||
SYMBOL_TRADE_TICK_VALUE = 26, // Value of SYMBOL_TRADE_TICK_VALUE_PROFIT
|
||||
SYMBOL_TRADE_TICK_VALUE_PROFIT = 53, // Not supported
|
||||
SYMBOL_TRADE_TICK_VALUE_LOSS = 54, // Not supported
|
||||
SYMBOL_TRADE_TICK_SIZE = 27, // Minimal price change
|
||||
SYMBOL_TRADE_CONTRACT_SIZE = 28, // Trade contract size
|
||||
SYMBOL_VOLUME_MIN = 34, // Minimal volume for a deal
|
||||
SYMBOL_VOLUME_MAX = 35, // Maximal volume for a deal
|
||||
SYMBOL_VOLUME_STEP = 36, // Minimal volume change step for deal execution
|
||||
SYMBOL_VOLUME_LIMIT = 55, // Not supported
|
||||
SYMBOL_SWAP_LONG = 38, // Buy order swap value
|
||||
SYMBOL_SWAP_SHORT = 39, // Sell order swap value
|
||||
SYMBOL_MARGIN_INITIAL = 42, // Initial margin means the amount in the margin currency required for opening an order with the volume of one lot. It is used for checking a client's assets when he or she enters the market.
|
||||
SYMBOL_MARGIN_MAINTENANCE = 43, // The maintenance margin. If it is set, it sets the margin amount in the margin currency of the symbol, charged from one lot. It is used for checking a client's assets when his/her account state changes. If the maintenance margin is equal to 0, the initial margin is used.
|
||||
SYMBOL_MARGIN_LONG = 44, // Not supported
|
||||
SYMBOL_MARGIN_SHORT = 45, // Not supported
|
||||
SYMBOL_MARGIN_LIMIT = 46, // Not supported
|
||||
SYMBOL_MARGIN_STOP = 47, // Not supported
|
||||
SYMBOL_MARGIN_STOPLIMIT = 48, // Not supported
|
||||
SYMBOL_SESSION_VOLUME = 57, // Not supported
|
||||
SYMBOL_SESSION_TURNOVER = 58, // Not supported
|
||||
SYMBOL_SESSION_INTEREST = 59, // Not supported
|
||||
SYMBOL_SESSION_BUY_ORDERS_VOLUME = 61, // Not supported
|
||||
SYMBOL_SESSION_SELL_ORDERS_VOLUME = 63, // Not supported
|
||||
SYMBOL_SESSION_OPEN = 64, // Not supported
|
||||
SYMBOL_SESSION_CLOSE = 65, // Not supported
|
||||
SYMBOL_SESSION_AW = 66, // Not supported
|
||||
SYMBOL_SESSION_PRICE_SETTLEMENT = 67, // Not supported
|
||||
SYMBOL_SESSION_PRICE_LIMIT_MIN = 68, // Not supported
|
||||
SYMBOL_SESSION_PRICE_LIMIT_MAX = 69, // Not supported
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace MtApi
|
||||
{
|
||||
//MQL4: ENUM_SYMBOL_INFO_INTEGER
|
||||
public enum EnumSymbolInfoInteger
|
||||
{
|
||||
SYMBOL_SELECT = 0,
|
||||
SYMBOL_VISIBLE = 76,
|
||||
SYMBOL_SESSION_DEALS = 56,
|
||||
SYMBOL_SESSION_BUY_ORDERS = 60,
|
||||
SYMBOL_SESSION_SELL_ORDERS = 62,
|
||||
SYMBOL_VOLUME = 10,
|
||||
SYMBOL_VOLUMEHIGH = 11,
|
||||
SYMBOL_VOLUMELOW = 12,
|
||||
SYMBOL_TIME = 15,
|
||||
SYMBOL_DIGITS = 17,
|
||||
SYMBOL_SPREAD = 18,
|
||||
SYMBOL_SPREAD_FLOAT = 41,
|
||||
SYMBOL_TRADE_CALC_MODE = 29,
|
||||
SYMBOL_TRADE_MODE = 30,
|
||||
SYMBOL_START_TIME = 51,
|
||||
SYMBOL_EXPIRATION_TIME = 52,
|
||||
SYMBOL_TRADE_STOPS_LEVEL = 31,
|
||||
SYMBOL_TRADE_FREEZE_LEVEL = 32,
|
||||
SYMBOL_TRADE_EXEMODE = 33,
|
||||
SYMBOL_SWAP_MODE = 37,
|
||||
SYMBOL_SWAP_ROLLOVER3DAYS = 40,
|
||||
SYMBOL_EXPIRATION_MODE = 49,
|
||||
SYMBOL_FILLING_MODE = 50,
|
||||
SYMBOL_ORDER_MODE = 71
|
||||
}
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
namespace MtApi
|
||||
{
|
||||
// https://docs.mql4.com/constants/environment_state/terminalstatus#enum_terminal_info_double
|
||||
public enum EnumTerminalInfoDouble
|
||||
{
|
||||
TERMINAL_COMMUNITY_BALANCE = 25 // Balance in MQL5.community
|
||||
}
|
||||
}
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
namespace MtApi
|
||||
{
|
||||
// https://docs.mql4.com/constants/environment_state/terminalstatus#enum_terminal_info_integer
|
||||
public enum EnumTerminalInfoInteger
|
||||
{
|
||||
TERMINAL_BUILD = 5, // The client terminal build number
|
||||
TERMINAL_COMMUNITY_ACCOUNT = 23, // The flag indicates the presence of MQL5.community authorization data in the terminal
|
||||
TERMINAL_COMMUNITY_CONNECTION = 24, // Connection to MQL5.community
|
||||
TERMINAL_CONNECTED = 6, // Connection to a trade server
|
||||
TERMINAL_DLLS_ALLOWED = 7, // Permission to use DLL
|
||||
TERMINAL_TRADE_ALLOWED = 8, // Permission to trade
|
||||
TERMINAL_EMAIL_ENABLED = 9, // Permission to send e-mails using SMTP-server and login, specified in the terminal settings
|
||||
TERMINAL_FTP_ENABLED = 10, // Permission to send reports using FTP-server and login, specified in the terminal settings
|
||||
TERMINAL_NOTIFICATIONS_ENABLED = 26, // Permission to send notifications to smartphone
|
||||
TERMINAL_MAXBARS = 11, // The maximal bars count on the chart
|
||||
TERMINAL_MQID = 22, // The flag indicates the presence of MetaQuotes ID data to send Push notifications
|
||||
TERMINAL_CODEPAGE = 12, // Number of the code page of the language installed in the client terminal
|
||||
TERMINAL_CPU_CORES = 21, // The number of CPU cores in the system
|
||||
TERMINAL_DISK_SPACE = 20, // Free disk space for the MQL4\Files folder of the terminal, Mb
|
||||
TERMINAL_MEMORY_PHYSICAL = 14, // Physical memory in the system, Mb
|
||||
TERMINAL_MEMORY_TOTAL = 15, // Memory available to the process of the terminal , Mb
|
||||
TERMINAL_MEMORY_AVAILABLE = 16, // Free memory of the terminal process, Mb
|
||||
TERMINAL_MEMORY_USED = 17, // Memory used by the terminal , Mb
|
||||
TERMINAL_SCREEN_DPI = 27, // The resolution of information display on the screen is measured as number of Dots in a line per Inch (DPI). Knowing the parameter value, you can set the size of graphical objects so that they look the same on monitors with different resolution characteristics.
|
||||
TERMINAL_PING_LAST = 28 // The last known value of a ping to a trade server in microseconds. One second comprises of one million microseconds
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
public enum MarketInfoModeType
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace MtApi.Monitors
|
||||
public class TimeframeTradeMonitor : TradeMonitor
|
||||
{
|
||||
#region Fields
|
||||
private volatile bool _isStarted = false;
|
||||
private volatile bool _isStarted;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
@@ -23,13 +23,8 @@ namespace MtApi.Monitors
|
||||
// Returns:
|
||||
// true if PositionMonitor should check orders
|
||||
// otherwise, false.
|
||||
public override bool IsStarted
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isStarted;
|
||||
}
|
||||
}
|
||||
public override bool IsStarted => _isStarted;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace MtApi.Monitors
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
public TradeMonitor(MtApiClient apiClient)
|
||||
protected TradeMonitor(MtApiClient apiClient)
|
||||
{
|
||||
if (apiClient == null)
|
||||
throw new ArgumentNullException(nameof(apiClient));
|
||||
@@ -73,13 +73,7 @@ namespace MtApi.Monitors
|
||||
protected abstract void OnMtConnected();
|
||||
protected abstract void OnMtDisconnected();
|
||||
|
||||
public bool IsMtConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
return _apiClient.ConnectionState == MtConnectionState.Connected;
|
||||
}
|
||||
}
|
||||
public bool IsMtConnected => _apiClient.ConnectionState == MtConnectionState.Connected;
|
||||
|
||||
protected void Check()
|
||||
{
|
||||
@@ -113,12 +107,12 @@ namespace MtApi.Monitors
|
||||
prevOrders = _prevOrders;
|
||||
}
|
||||
|
||||
if (_prevOrders != null) //skip checking on first load orders
|
||||
if (prevOrders != null) //skip checking on first load orders
|
||||
{
|
||||
//check open orders
|
||||
foreach (var order in tradesOrders)
|
||||
{
|
||||
if (_prevOrders.Find(a => a.Ticket == order.Ticket) == null)
|
||||
if (prevOrders.Find(a => a.Ticket == order.Ticket) == null)
|
||||
{
|
||||
openedOrders.Add(order);
|
||||
}
|
||||
@@ -126,7 +120,7 @@ namespace MtApi.Monitors
|
||||
|
||||
//check closed orders
|
||||
var closeOrdersTemp = new List<MtOrder>();
|
||||
foreach (var order in _prevOrders)
|
||||
foreach (var order in prevOrders)
|
||||
{
|
||||
if (tradesOrders.Find(a => a.Ticket == order.Ticket) == null)
|
||||
{
|
||||
@@ -180,10 +174,7 @@ namespace MtApi.Monitors
|
||||
_prevOrders = null;
|
||||
}
|
||||
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
Check();
|
||||
});
|
||||
Task.Factory.StartNew(Check);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
+1
-6
@@ -5,12 +5,7 @@ namespace MtApi
|
||||
public class MqlRates
|
||||
{
|
||||
public int MtTime { get; set; }
|
||||
|
||||
public DateTime Time
|
||||
{
|
||||
get { return MtApiTimeConverter.ConvertFromMtTime(MtTime); }
|
||||
}
|
||||
|
||||
public DateTime Time => MtApiTimeConverter.ConvertFromMtTime(MtTime);
|
||||
public double Open { get; set; }
|
||||
public double High { get; set; }
|
||||
public double Low { get; set; }
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi
|
||||
{
|
||||
public class MqlTick
|
||||
{
|
||||
public int MtTime { get; set; }
|
||||
public DateTime Time => MtApiTimeConverter.ConvertFromMtTime(MtTime);
|
||||
public double Bid { get; set; }
|
||||
public double Ask { get; set; }
|
||||
public double Last { get; set; }
|
||||
public ulong Volume { get; set; }
|
||||
}
|
||||
}
|
||||
+13
-1
@@ -59,9 +59,15 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChartPeriod.cs" />
|
||||
<Compile Include="EnumSeriesInfoInteger.cs" />
|
||||
<Compile Include="EnumSymbolInfoDouble.cs" />
|
||||
<Compile Include="EnumSymbolInfoInteger.cs" />
|
||||
<Compile Include="EnumTerminalInfoDouble.cs" />
|
||||
<Compile Include="EnumTerminalInfoInteger.cs" />
|
||||
<Compile Include="ExtensionMethods.cs" />
|
||||
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
<Compile Include="MqlTick.cs" />
|
||||
<Compile Include="MtConnectionEventArgs.cs" />
|
||||
<Compile Include="MtConnectionException.cs" />
|
||||
<Compile Include="MtConnectionState.cs" />
|
||||
@@ -91,16 +97,22 @@
|
||||
<Compile Include="Requests\OrderDeleteRequest.cs" />
|
||||
<Compile Include="Requests\OrderModifyRequest.cs" />
|
||||
<Compile Include="Requests\OrderSendRequest.cs" />
|
||||
<Compile Include="Requests\SeriesInfoIntegerRequest.cs" />
|
||||
<Compile Include="Requests\SessionRequest.cs" />
|
||||
<Compile Include="Requests\RequestBase.cs" />
|
||||
<Compile Include="Requests\RequestType.cs" />
|
||||
<Compile Include="Requests\SymbolInfoDoubleRequest.cs" />
|
||||
<Compile Include="Requests\SymbolInfoTickRequest.cs" />
|
||||
<Compile Include="Responses\CopyRatesResponse.cs" />
|
||||
<Compile Include="Responses\GetOrderResponse.cs" />
|
||||
<Compile Include="Responses\GetOrdersResponse.cs" />
|
||||
<Compile Include="Responses\ICustomResponse.cs" />
|
||||
<Compile Include="Responses\OrderSendResponse.cs" />
|
||||
<Compile Include="Responses\SessionResponce.cs" />
|
||||
<Compile Include="Responses\SeriesInfoIntegerResponse.cs" />
|
||||
<Compile Include="Responses\SessionResponse.cs" />
|
||||
<Compile Include="Responses\ResponseBase.cs" />
|
||||
<Compile Include="Responses\SymbolInfoDoubleResponse.cs" />
|
||||
<Compile Include="Responses\SymbolInfoTickResponse.cs" />
|
||||
<Compile Include="SeriesIdentifier.cs" />
|
||||
<Compile Include="TimeBarArgs.cs" />
|
||||
<Compile Include="Monitors\TimeframeTradeMonitor.cs" />
|
||||
|
||||
+480
-210
File diff suppressed because it is too large
Load Diff
+15
-9
@@ -58,9 +58,15 @@ namespace MtApi
|
||||
IsVisualMode = 37,
|
||||
UninitializeReason = 38,
|
||||
ErrorDescription = 39,
|
||||
TerminalCompany = 68,
|
||||
TerminalName = 69,
|
||||
TerminalPath = 70,
|
||||
TerminalInfoString = 153,
|
||||
TerminalInfoInteger = 204,
|
||||
TerminalInfoDouble = 205,
|
||||
|
||||
//Account Information
|
||||
AccountBalance = 40,
|
||||
AccountBalance = 40,
|
||||
AccountCredit = 41,
|
||||
AccountCompany = 42,
|
||||
AccountCurrency = 43,
|
||||
@@ -91,11 +97,6 @@ namespace MtApi
|
||||
SendMail = 66,
|
||||
Sleep = 67,
|
||||
|
||||
//Client Terminal
|
||||
TerminalCompany = 68,
|
||||
TerminalName = 69,
|
||||
TerminalPath = 70,
|
||||
|
||||
//Date and Time
|
||||
Day = 71,
|
||||
DayOfWeek = 72,
|
||||
@@ -188,13 +189,18 @@ namespace MtApi
|
||||
//
|
||||
RefreshRates = 150,
|
||||
//
|
||||
TerminalInfoString = 153,
|
||||
SymbolInfoString = 154,
|
||||
|
||||
//Requests
|
||||
MtRequest = 155,
|
||||
|
||||
//Backtesting
|
||||
BacktestingReady = 156
|
||||
BacktestingReady = 156,
|
||||
|
||||
//Market Info
|
||||
SymbolInfoString = 154,
|
||||
SymbolsTotal = 200,
|
||||
SymbolName = 201,
|
||||
SymbolSelect = 202,
|
||||
SymbolInfoInteger = 203
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+85
-84
@@ -1,5 +1,6 @@
|
||||
namespace MtApi
|
||||
{
|
||||
// https://docs.mql4.com/constants/errorswarnings/errorcodes
|
||||
public enum MtErrorCode
|
||||
{
|
||||
MtApiCustomError = -1, // Error occurred in MtApi.
|
||||
@@ -10,91 +11,91 @@
|
||||
ServerBusy = 4, // Trade server is busy.
|
||||
OldVersion = 5, // Old version of the client terminal.
|
||||
NoConnection = 6, // No connection with trade server.
|
||||
NotEnoughRights = 7, // Not enough rights.
|
||||
TooFrequentRequests = 8, // Too frequent requests.
|
||||
MalfunctionalTrade = 9, // Malfunctional trade operation.
|
||||
NotEnoughRights = 7, // Not enough rights.
|
||||
TooFrequentRequests = 8, // Too frequent requests.
|
||||
MalfunctionalTrade = 9, // Malfunctional trade operation.
|
||||
AccountDisabled = 64, // Account disabled.
|
||||
InvalidAccount = 65, // Invalid account.
|
||||
TradeTimeout = 128, // Trade timeout.
|
||||
InvalidPrice = 129, // Invalid price.
|
||||
InvalidStops = 130, // Invalid stops.
|
||||
InvalidTradeVolume = 131, // Invalid trade volume.
|
||||
MarketClosed = 132, // Market is closed.
|
||||
TradeDisabled = 133, // Trade is disabled.
|
||||
NotEnoughMoney = 134, // Not enough money.
|
||||
PriceChanged = 135, // Price changed.
|
||||
OffQuotes = 136, // Off quotes.
|
||||
BrokerBusy = 137, // Broker is busy.
|
||||
Requote = 138, // Requote.
|
||||
OrderLocked = 139, // Order is locked.
|
||||
LongPositionsOnlyAllowed = 140, // Long positions only allowed.
|
||||
TooManyRequests = 141, // Too many requests.
|
||||
TradeModifyDenied = 145, // Modification denied because an order is too close to market.
|
||||
TradeContextBusy = 146, // Trade context is busy.
|
||||
TradeExpirationDenied = 147, // Expirations are denied by broker.
|
||||
TradeTooManyOrders = 148, // The amount of opened and pending orders has reached the limit set by a broker.
|
||||
InvalidAccount = 65, // Invalid account.
|
||||
TradeTimeout = 128, // Trade timeout.
|
||||
InvalidPrice = 129, // Invalid price.
|
||||
InvalidStops = 130, // Invalid stops.
|
||||
InvalidTradeVolume = 131, // Invalid trade volume.
|
||||
MarketClosed = 132, // Market is closed.
|
||||
TradeDisabled = 133, // Trade is disabled.
|
||||
NotEnoughMoney = 134, // Not enough money.
|
||||
PriceChanged = 135, // Price changed.
|
||||
OffQuotes = 136, // Off quotes.
|
||||
BrokerBusy = 137, // Broker is busy.
|
||||
Requote = 138, // Requote.
|
||||
OrderLocked = 139, // Order is locked.
|
||||
LongPositionsOnlyAllowed = 140, // Long positions only allowed.
|
||||
TooManyRequests = 141, // Too many requests.
|
||||
TradeModifyDenied = 145, // Modification denied because an order is too close to market.
|
||||
TradeContextBusy = 146, // Trade context is busy.
|
||||
TradeExpirationDenied = 147, // Expirations are denied by broker.
|
||||
TradeTooManyOrders = 148, // The amount of opened and pending orders has reached the limit set by a broker.
|
||||
|
||||
NoMqlerror = 4000, // No error.
|
||||
WrongFunctionPointer = 4001, // Wrong function pointer.
|
||||
ArrayIndexOutOfRange = 4002, // Array index is out of range.
|
||||
NoMemoryForFunctionCallStack = 4003, // No memory for function call stack.
|
||||
RecursiveStackOverflow = 4004, // Recursive stack overflow.
|
||||
NotEnoughStackForParameter = 4005, // Not enough stack for parameter.
|
||||
NoMemoryForParameterString = 4006, // No memory for parameter string.
|
||||
NoMemoryForTempString = 4007, // No memory for temp string.
|
||||
NotInitializedString = 4008, // Not initialized string.
|
||||
NotInitializedArraystring = 4009, // Not initialized string in an array.
|
||||
NoMemoryForArraystring = 4010, // No memory for an array string.
|
||||
TooLongString = 4011, // Too long string.
|
||||
RemainderFromZeroDivide = 4012, // Remainder from zero divide.
|
||||
ZeroDivide = 4013, // Zero divide.
|
||||
UnknownCommand = 4014, // Unknown command.
|
||||
WrongJump = 4015, // Wrong jump.
|
||||
NotInitializedArray = 4016, // Not initialized array.
|
||||
DllCallsNotAllowed = 4017, // DLL calls are not allowed.
|
||||
CannotLoadLibrary = 4018, // Cannot load library.
|
||||
CannotCallFunction = 4019, // Cannot call function.
|
||||
ExternalExpertCallsNotAllowed = 4020, // EA function calls are not allowed.
|
||||
NotEnoughMemoryForReturnedString = 4021, // Not enough memory for a string returned from a function.
|
||||
SystemBusy = 4022, // System is busy.
|
||||
InvalidFunctionParametersCount = 4050, // Invalid function parameters count.
|
||||
InvalidFunctionParameterValue = 4051, // Invalid function parameter value.
|
||||
StringFunctionInternalError = 4052, // String function internal error.
|
||||
SomeArrayError = 4053, // Some array error.
|
||||
IncorrectSeriesArrayUsing = 4054, // Incorrect series array using.
|
||||
CustomIndicatorError = 4055, // Custom indicator error.
|
||||
IncompatibleArrays = 4056, // Arrays are incompatible.
|
||||
GlobalVariablesProcessingError = 4057, // Global variables processing error.
|
||||
GlobalVariableNotFound = 4058, // Global variable not found.
|
||||
FunctionNotAllowedInTestingMode = 4059, // Function is not allowed in testing mode.
|
||||
FunctionNotConfirmed = 4060, // Function is not confirmed.
|
||||
SendMailError = 4061, // Mail sending error.
|
||||
StringParameterExpected = 4062, // String parameter expected.
|
||||
IntegerParameterExpected = 4063, // Integer parameter expected.
|
||||
DoubleParameterExpected = 4064, // Double parameter expected.
|
||||
ArrayAsParameterExpected = 4065, // Array as parameter expected.
|
||||
HistoryWillUpdated = 4066, // Requested history data in updating state.
|
||||
TradeError = 4067, // Some error in trade operation execution.
|
||||
EndOfFile = 4099, // End of a file.
|
||||
SomeFileError = 4100, // Some file error.
|
||||
WrongFileName = 4101, // Wrong file name.
|
||||
TooManyOpenedFiles = 4102, // Too many opened files.
|
||||
CannotOpenFile = 4103, // Cannot open file.
|
||||
IncompatibleAccessToFile = 4104, // Incompatible access to a file.
|
||||
NoOrderSelected = 4105, // No order selected.
|
||||
UnknownSymbol = 4106, // Unknown symbol.
|
||||
InvalidPriceParam = 4107, // Invalid price.
|
||||
InvalidTicket = 4108, // Invalid ticket.
|
||||
TradeNotAllowed = 4109, // Trade is not allowed.
|
||||
LongsNotAllowed = 4110, // Longs are not allowed.
|
||||
ShortsNotAllowed = 4111, // Shorts are not allowed.
|
||||
ObjectAlreadyExists = 4200, // Object already exists.
|
||||
UnknownObjectProperty = 4201, // Unknown object property.
|
||||
ObjectDoesNotExist = 4202, // Object does not exist.
|
||||
UnknownObjectType = 4203, // Unknown object type.
|
||||
NoObjectName = 4204, // No object name.
|
||||
ObjectCoordinatesError = 4205, // Object coordinates error.
|
||||
NoSpecifiedSubwindow = 4206, // No specified subwindow.
|
||||
SomeObjectError = 4207 // Some error in object operation.
|
||||
NoMqlerror = 4000, // No error.
|
||||
WrongFunctionPointer = 4001, // Wrong function pointer.
|
||||
ArrayIndexOutOfRange = 4002, // Array index is out of range.
|
||||
NoMemoryForFunctionCallStack = 4003, // No memory for function call stack.
|
||||
RecursiveStackOverflow = 4004, // Recursive stack overflow.
|
||||
NotEnoughStackForParameter = 4005, // Not enough stack for parameter.
|
||||
NoMemoryForParameterString = 4006, // No memory for parameter string.
|
||||
NoMemoryForTempString = 4007, // No memory for temp string.
|
||||
NotInitializedString = 4008, // Not initialized string.
|
||||
NotInitializedArraystring = 4009, // Not initialized string in an array.
|
||||
NoMemoryForArraystring = 4010, // No memory for an array string.
|
||||
TooLongString = 4011, // Too long string.
|
||||
RemainderFromZeroDivide = 4012, // Remainder from zero divide.
|
||||
ZeroDivide = 4013, // Zero divide.
|
||||
UnknownCommand = 4014, // Unknown command.
|
||||
WrongJump = 4015, // Wrong jump.
|
||||
NotInitializedArray = 4016, // Not initialized array.
|
||||
DllCallsNotAllowed = 4017, // DLL calls are not allowed.
|
||||
CannotLoadLibrary = 4018, // Cannot load library.
|
||||
CannotCallFunction = 4019, // Cannot call function.
|
||||
ExternalExpertCallsNotAllowed = 4020, // EA function calls are not allowed.
|
||||
NotEnoughMemoryForReturnedString = 4021, // Not enough memory for a string returned from a function.
|
||||
SystemBusy = 4022, // System is busy.
|
||||
InvalidFunctionParametersCount = 4050, // Invalid function parameters count.
|
||||
InvalidFunctionParameterValue = 4051, // Invalid function parameter value.
|
||||
StringFunctionInternalError = 4052, // String function internal error.
|
||||
SomeArrayError = 4053, // Some array error.
|
||||
IncorrectSeriesArrayUsing = 4054, // Incorrect series array using.
|
||||
CustomIndicatorError = 4055, // Custom indicator error.
|
||||
IncompatibleArrays = 4056, // Arrays are incompatible.
|
||||
GlobalVariablesProcessingError = 4057, // Global variables processing error.
|
||||
GlobalVariableNotFound = 4058, // Global variable not found.
|
||||
FunctionNotAllowedInTestingMode = 4059, // Function is not allowed in testing mode.
|
||||
FunctionNotConfirmed = 4060, // Function is not confirmed.
|
||||
SendMailError = 4061, // Mail sending error.
|
||||
StringParameterExpected = 4062, // String parameter expected.
|
||||
IntegerParameterExpected = 4063, // Integer parameter expected.
|
||||
DoubleParameterExpected = 4064, // Double parameter expected.
|
||||
ArrayAsParameterExpected = 4065, // Array as parameter expected.
|
||||
HistoryWillUpdated = 4066, // Requested history data in updating state.
|
||||
TradeError = 4067, // Some error in trade operation execution.
|
||||
EndOfFile = 4099, // End of a file.
|
||||
SomeFileError = 4100, // Some file error.
|
||||
WrongFileName = 4101, // Wrong file name.
|
||||
TooManyOpenedFiles = 4102, // Too many opened files.
|
||||
CannotOpenFile = 4103, // Cannot open file.
|
||||
IncompatibleAccessToFile = 4104, // Incompatible access to a file.
|
||||
NoOrderSelected = 4105, // No order selected.
|
||||
UnknownSymbol = 4106, // Unknown symbol.
|
||||
InvalidPriceParam = 4107, // Invalid price.
|
||||
InvalidTicket = 4108, // Invalid ticket.
|
||||
TradeNotAllowed = 4109, // Trade is not allowed.
|
||||
LongsNotAllowed = 4110, // Longs are not allowed.
|
||||
ShortsNotAllowed = 4111, // Shorts are not allowed.
|
||||
ObjectAlreadyExists = 4200, // Object already exists.
|
||||
UnknownObjectProperty = 4201, // Unknown object property.
|
||||
ObjectDoesNotExist = 4202, // Object does not exist.
|
||||
UnknownObjectType = 4203, // Unknown object type.
|
||||
NoObjectName = 4204, // No object name.
|
||||
ObjectCoordinatesError = 4205, // Object coordinates error.
|
||||
NoSpecifiedSubwindow = 4206, // No specified subwindow.
|
||||
SomeObjectError = 4207 // Some error in object operation.
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
public class MtQuote
|
||||
{
|
||||
|
||||
+23
-29
@@ -1,29 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi
|
||||
{
|
||||
public class MtSession
|
||||
{
|
||||
public string Symbol { get; set; }
|
||||
public DayOfWeek DayOfWeek { get; set; }
|
||||
public uint Index { get; set; }
|
||||
public int MtFromTime { get; set; }
|
||||
public DateTime From
|
||||
{
|
||||
get { return MtApiTimeConverter.ConvertFromMtTime(MtFromTime); }
|
||||
}
|
||||
public int MtToTime { get; set; }
|
||||
public DateTime To
|
||||
{
|
||||
get { return MtApiTimeConverter.ConvertFromMtTime(MtToTime); }
|
||||
}
|
||||
public bool HasData { get; set; }
|
||||
public SessionType Type { get; set; }
|
||||
}
|
||||
|
||||
public enum SessionType { Quote, Trade }
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace MtApi
|
||||
{
|
||||
public class MtSession
|
||||
{
|
||||
public string Symbol { get; set; }
|
||||
public DayOfWeek DayOfWeek { get; set; }
|
||||
public uint Index { get; set; }
|
||||
public int MtFromTime { get; set; }
|
||||
public DateTime From => MtApiTimeConverter.ConvertFromMtTime(MtFromTime);
|
||||
public int MtToTime { get; set; }
|
||||
public DateTime To => MtApiTimeConverter.ConvertFromMtTime(MtToTime);
|
||||
public bool HasData { get; set; }
|
||||
public SessionType Type { get; set; }
|
||||
}
|
||||
|
||||
public enum SessionType
|
||||
{
|
||||
Quote,
|
||||
Trade
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.30.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.30.0")]
|
||||
[assembly: AssemblyVersion("1.0.32.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.32.0")]
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi.Requests
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public abstract class CopyRatesRequestBase : RequestBase
|
||||
internal abstract class CopyRatesRequestBase : RequestBase
|
||||
{
|
||||
public enum CopyRatesTypeEnum
|
||||
{
|
||||
@@ -15,10 +9,7 @@ namespace MtApi.Requests
|
||||
CopyRates_3 = 3,
|
||||
}
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.CopyRates; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.CopyRates;
|
||||
|
||||
public abstract CopyRatesTypeEnum CopyRatesType { get; }
|
||||
|
||||
@@ -26,34 +17,25 @@ namespace MtApi.Requests
|
||||
public ENUM_TIMEFRAMES Timeframe { get; set; }
|
||||
}
|
||||
|
||||
public class CopyRates1Request : CopyRatesRequestBase
|
||||
internal class CopyRates1Request : CopyRatesRequestBase
|
||||
{
|
||||
public override CopyRatesTypeEnum CopyRatesType
|
||||
{
|
||||
get { return CopyRatesTypeEnum.CopyRates_1; }
|
||||
}
|
||||
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_1;
|
||||
|
||||
public int StartPos { get; set; }
|
||||
public int Count { get; set; }
|
||||
}
|
||||
|
||||
public class CopyRates2Request : CopyRatesRequestBase
|
||||
internal class CopyRates2Request : CopyRatesRequestBase
|
||||
{
|
||||
public override CopyRatesTypeEnum CopyRatesType
|
||||
{
|
||||
get { return CopyRatesTypeEnum.CopyRates_2; }
|
||||
}
|
||||
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_2;
|
||||
|
||||
public int StartTime { get; set; }
|
||||
public int Count { get; set; }
|
||||
}
|
||||
|
||||
public class CopyRates3Request : CopyRatesRequestBase
|
||||
internal class CopyRates3Request : CopyRatesRequestBase
|
||||
{
|
||||
public override CopyRatesTypeEnum CopyRatesType
|
||||
{
|
||||
get { return CopyRatesTypeEnum.CopyRates_3; }
|
||||
}
|
||||
public override CopyRatesTypeEnum CopyRatesType => CopyRatesTypeEnum.CopyRates_3;
|
||||
|
||||
public int StartTime { get; set; }
|
||||
public int StopTime { get; set; }
|
||||
|
||||
Regular → Executable
+2
-5
@@ -1,14 +1,11 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class GetOrderRequest: RequestBase
|
||||
internal class GetOrderRequest: RequestBase
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public int Select { get; set; }
|
||||
public int Pool { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.GetOrder; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.GetOrder;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -1,12 +1,9 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class GetOrdersRequest: RequestBase
|
||||
internal class GetOrdersRequest: RequestBase
|
||||
{
|
||||
public int Pool { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.GetOrders; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.GetOrders;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+3
-8
@@ -1,10 +1,8 @@
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class ICustomRequest : RequestBase
|
||||
internal class ICustomRequest : RequestBase
|
||||
{
|
||||
public enum ParametersType
|
||||
{
|
||||
@@ -22,9 +20,6 @@ namespace MtApi.Requests
|
||||
public ArrayList Params { get; set; }
|
||||
public ParametersType ParamsType { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.iCustom; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.iCustom;
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+2
-5
@@ -1,15 +1,12 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class OrderCloseByRequest: RequestBase
|
||||
internal class OrderCloseByRequest: RequestBase
|
||||
{
|
||||
public int Ticket { get; set; }
|
||||
public int Opposite { get; set; }
|
||||
|
||||
public int? ArrowColor { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.OrderCloseBy; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.OrderCloseBy;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class OrderCloseRequest: RequestBase
|
||||
internal class OrderCloseRequest: RequestBase
|
||||
{
|
||||
public int Ticket { get; set; }
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
public int? Slippage { get; set; }
|
||||
public int? ArrowColor { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.OrderClose; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.OrderClose;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -1,14 +1,11 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class OrderDeleteRequest: RequestBase
|
||||
internal class OrderDeleteRequest: RequestBase
|
||||
{
|
||||
public int Ticket { get; set; }
|
||||
|
||||
public int? ArrowColor { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.OrderDelete; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.OrderDelete;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class OrderModifyRequest: RequestBase
|
||||
internal class OrderModifyRequest: RequestBase
|
||||
{
|
||||
public int Ticket { get; set; }
|
||||
public double Price { get; set; }
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
public int? ArrowColor { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.OrderModify; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.OrderModify;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-5
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class OrderSendRequest: RequestBase
|
||||
internal class OrderSendRequest: RequestBase
|
||||
{
|
||||
public string Symbol { get; set; }
|
||||
public int Cmd { get; set; }
|
||||
@@ -15,9 +15,6 @@
|
||||
public int? Expiration { get; set; }
|
||||
public int? ArrowColor { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.OrderSend; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.OrderSend;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public abstract class RequestBase
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
internal abstract class RequestBase
|
||||
{
|
||||
public abstract RequestType RequestType { get; }
|
||||
}
|
||||
}
|
||||
public abstract RequestType RequestType { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public enum RequestType
|
||||
internal enum RequestType
|
||||
{
|
||||
Unknown = 0,
|
||||
GetOrder = 1,
|
||||
GetOrders = 2,
|
||||
OrderSend = 3,
|
||||
OrderClose = 4,
|
||||
OrderCloseBy = 5,
|
||||
OrderDelete = 6,
|
||||
OrderModify = 7,
|
||||
iCustom = 8,
|
||||
CopyRates = 9,
|
||||
Session = 10,
|
||||
Unknown = 0,
|
||||
GetOrder = 1,
|
||||
GetOrders = 2,
|
||||
OrderSend = 3,
|
||||
OrderClose = 4,
|
||||
OrderCloseBy = 5,
|
||||
OrderDelete = 6,
|
||||
OrderModify = 7,
|
||||
iCustom = 8,
|
||||
CopyRates = 9,
|
||||
Session = 10,
|
||||
SeriesInfoInteger = 11,
|
||||
SymbolInfoDouble = 12,
|
||||
SymbolInfoTick = 13
|
||||
}
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
internal class SeriesInfoIntegerRequest: RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.SeriesInfoInteger;
|
||||
|
||||
public string SymbolName { get; set; }
|
||||
public int Timeframe { get; set; }
|
||||
public int PropId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,13 @@
|
||||
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
public class SessionRequest : RequestBase
|
||||
internal class SessionRequest : RequestBase
|
||||
{
|
||||
public string Symbol { get; set; }
|
||||
public DayOfWeek DayOfWeek { get; set; }
|
||||
public int SessionIndex { get; set; }
|
||||
public SessionType SessionType { get; set; }
|
||||
|
||||
public override RequestType RequestType
|
||||
{
|
||||
get { return RequestType.Session; }
|
||||
}
|
||||
public override RequestType RequestType => RequestType.Session;
|
||||
}
|
||||
}
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
internal class SymbolInfoDoubleRequest : RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.SymbolInfoDouble;
|
||||
|
||||
public string SymbolName { get; set; }
|
||||
public int PropId { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
namespace MtApi.Requests
|
||||
{
|
||||
internal class SymbolInfoTickRequest: RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.SymbolInfoTick;
|
||||
|
||||
public string Symbol { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class CopyRatesResponse: ResponseBase
|
||||
internal class CopyRatesResponse: ResponseBase
|
||||
{
|
||||
public List<MqlRates> Rates { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class GetOrderResponse: ResponseBase
|
||||
internal class GetOrderResponse: ResponseBase
|
||||
{
|
||||
public MtOrder Order { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class GetOrdersResponse: ResponseBase
|
||||
internal class GetOrdersResponse: ResponseBase
|
||||
{
|
||||
public List<MtOrder> Orders { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+2
-8
@@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi.Responses
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class ICustomResponse: ResponseBase
|
||||
internal class ICustomResponse: ResponseBase
|
||||
{
|
||||
public double Value { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class OrderSendResponse: ResponseBase
|
||||
internal class OrderSendResponse: ResponseBase
|
||||
{
|
||||
public int Ticket { get; set; }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class ResponseBase
|
||||
internal class ResponseBase
|
||||
{
|
||||
public int ErrorCode { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SeriesInfoIntegerResponse: ResponseBase
|
||||
{
|
||||
public long Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
public class SessionResponce : ResponseBase
|
||||
internal class SessionResponse : ResponseBase
|
||||
{
|
||||
public MtSession Session { get; set; }
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SymbolInfoDoubleResponse: ResponseBase
|
||||
{
|
||||
public double Value { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi.Responses
|
||||
{
|
||||
internal class SymbolInfoTickResponse: ResponseBase
|
||||
{
|
||||
public MqlTick Tick { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi
|
||||
namespace MtApi
|
||||
{
|
||||
public enum TradeOperation
|
||||
{
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
namespace MtApi5
|
||||
{
|
||||
public enum CopyTicksFlag
|
||||
{
|
||||
Info = 1, // ticks with Bid and/or Ask changes
|
||||
Trade = 2, // ticks with changes in Last and Volume
|
||||
All = -1 // all ticks
|
||||
}
|
||||
}
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
namespace MtApi5
|
||||
{
|
||||
//Error codes from https://www.mql5.com/en/docs/constants/errorswarnings/errorcodes
|
||||
|
||||
public enum ErrorCode
|
||||
{
|
||||
ErrCustom = -1, // Error occurred in MtApi5.
|
||||
ErrSuccess = 0, // The operation completed successfully
|
||||
ErrInternalError = 4001, // Unexpected internal error
|
||||
ErrWrongInternalParameter = 4002, // Wrong parameter in the inner call of the client terminal function
|
||||
ErrInvalidParameter = 4003, // Wrong parameter when calling the system function
|
||||
ErrNotEnoughMemory = 4004, // Not enough memory to perform the system function
|
||||
ErrStructWithobjectsOrclass = 4005, // The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes
|
||||
ErrInvalidArray = 4006, // Array of a wrong type, wrong size, or a damaged object of a dynamic array
|
||||
ErrArrayResizeError = 4007, // Not enough memory for the relocation of an array, or an attempt to change the size of a static array
|
||||
ErrStringResizeError = 4008, // Not enough memory for the relocation of string
|
||||
ErrNotinitializedString = 4009, // Not initialized string
|
||||
ErrInvalidDatetime = 4010, // Invalid date and/or time
|
||||
ErrArrayBadSize = 4011, // Requested array size exceeds 2 GB
|
||||
ErrInvalidPointer = 4012, // Wrong pointer
|
||||
ErrInvalidPointerType = 4013, // Wrong type of pointer
|
||||
ErrFunctionNotAllowed = 4014, // Function is not allowed for call
|
||||
ErrResourceNameDuplicated = 4015, // The names of the dynamic and the static resource match
|
||||
ErrResourceNotFound = 4016, // Resource with this name has not been found in EX5
|
||||
ErrResourceUnsuppotedType = 4017, // Unsupported resource type or its size exceeds 16 Mb
|
||||
ErrResourceNameIsTooLong = 4018, // The resource name exceeds 63 characters
|
||||
|
||||
ErrChartWrongId = 4101, // Wrong chart ID
|
||||
ErrChartNoReply = 4102, // Chart does not respond
|
||||
ErrChartNotFound = 4103, // Chart not found
|
||||
ErrChartNoExpert = 4104, // No Expert Advisor in the chart that could handle the event
|
||||
ErrChartCannotOpen = 4105, // Chart opening error
|
||||
ErrChartCannotChange = 4106, // Failed to change chart symbol and period
|
||||
ErrChartWrongParameter = 4107, // Error value of the parameter for the function of working with charts
|
||||
ErrChartCannotCreateTimer = 4108, // Failed to create timer
|
||||
ErrChartWrongProperty = 4109, // Wrong chart property ID
|
||||
ErrChartScreenshotFailed = 4110, // Error creating screenshots
|
||||
ErrChartNavigateFailed = 4111, // Error navigating through chart
|
||||
ErrChartTemplateFailed = 4112, // Error applying template
|
||||
ErrChartWindowNotFound = 4113, // Subwindow containing the indicator was not found
|
||||
ErrChartIndicatorCannotAdd = 4114, // Error adding an indicator to chart
|
||||
ErrChartIndicatorCannotDel = 4115, // Error deleting an indicator from the chart
|
||||
ErrChartIndicatorNotFound = 4116, // Indicator not found on the specified chart
|
||||
|
||||
ErrObjectError = 4201, // Error working with a graphical object
|
||||
ErrObjectNotFound = 4202, // Graphical object was not found
|
||||
ErrObjectWrongProperty = 4203, // Wrong ID of a graphical object property
|
||||
ErrObjectGetdateFailed = 4204, // Unable to get date corresponding to the value
|
||||
ErrObjectGetvalueFailed = 4205, // Unable to get value corresponding to the date
|
||||
|
||||
ErrMarketUnknownSymbol = 4301, // Unknown symbol
|
||||
ErrMarketNotSelected = 4302, // Symbol is not selected in MarketWatch
|
||||
ErrMarketWrongProperty = 4303, // Wrong identifier of a symbol property
|
||||
ErrMarketLasttimeUnknown = 4304, // Time of the last tick is not known (no ticks)
|
||||
ErrMarketSelectError = 4305, // Error adding or deleting a symbol in MarketWatch
|
||||
|
||||
ErrHistoryNotFound = 4401, // Requested history not found
|
||||
ErrHistoryWrongProperty = 4402, // Wrong ID of the history property
|
||||
|
||||
ErrGlobalvariableNotFound = 4501, // Global variable of the client terminal is not found
|
||||
ErrGlobalvariableExists = 4502, // Global variable of the client terminal with the same name already exists
|
||||
ErrMailSendFailed = 4510, // Email sending failed
|
||||
ErrPlaySoundFailed = 4511, // Sound playing failed
|
||||
ErrMql5WrongProperty = 4512, // Wrong identifier of the program property
|
||||
ErrTerminalWrongProperty = 4513, // Wrong identifier of the terminal property
|
||||
ErrFtpSendFailed = 4514, // File sending via ftp failed
|
||||
ErrNotificationSendFailed = 4515, // Failed to send a notification
|
||||
ErrNotificationWrongParameter = 4516, // Invalid parameter for sending a notification — an empty string or NULL has been passed to the SendNotification() function
|
||||
ErrNotificationWrongSettings = 4517, // Wrong settings of notifications in the terminal (ID is not specified or permission is not set)
|
||||
ErrNotificationTooFrequent = 4518, // Too frequent sending of notifications
|
||||
ErrFtpNoserver = 4519, // FTP server is not specified
|
||||
ErrFtpNologin = 4520, // FTP login is not specified
|
||||
ErrFtpFileError = 4521, // File not found in the MQL5\Files directory to send on FTP server
|
||||
ErrFtpConnectFailed = 4522, // FTP connection failed
|
||||
ErrFtpChangedir = 4523, // FTP path not found on server
|
||||
ErrFtpClosed = 4524, // FTP connection closed
|
||||
|
||||
ErrBuffersNoMemory = 4601, // Not enough memory for the distribution of indicator buffers
|
||||
ErrBuffersWrongIndex = 4602, // Wrong indicator buffer index
|
||||
|
||||
ErrCustomWrongProperty = 4603, // Wrong ID of the custom indicator property
|
||||
|
||||
ErrAccountWrongProperty = 4701, // Wrong account property ID
|
||||
ErrTradeWrongProperty = 4751, // Wrong trade property ID
|
||||
ErrTradeDisabled = 4752, // Trading by Expert Advisors prohibited
|
||||
ErrTradePositionNotFound = 4753, // Position not found
|
||||
ErrTradeOrderNotFound = 4754, // Order not found
|
||||
ErrTradeDealNotFound = 4755, // Deal not found
|
||||
ErrTradeSendFailed = 4756, // Trade request sending failed
|
||||
|
||||
ErrIndicatorUnknownSymbol = 4801, // Unknown symbol
|
||||
ErrIndicatorCannotCreate = 4802, // Indicator cannot be created
|
||||
ErrIndicatorNoMemory = 4803, // Not enough memory to add the indicator
|
||||
ErrIndicatorCannotApply = 4804, // The indicator cannot be applied to another indicator
|
||||
ErrIndicatorCannotAdd = 4805, // Error applying an indicator to chart
|
||||
ErrIndicatorDataNotFound = 4806, // Requested data not found
|
||||
ErrIndicatorWrongHandle = 4807, // Wrong indicator handle
|
||||
ErrIndicatorWrongParameters = 4808, // Wrong number of parameters when creating an indicator
|
||||
ErrIndicatorParametersMissing = 4809, // No parameters when creating an indicator
|
||||
ErrIndicatorCustomName = 4810, // The first parameter in the array must be the name of the custom indicator
|
||||
ErrIndicatorParameterType = 4811, // Invalid parameter type in the array when creating an indicator
|
||||
ErrIndicatorWrongIndex = 4812, // Wrong index of the requested indicator buffer
|
||||
|
||||
ErrBooksCannotAdd = 4901, // Depth Of Market can not be added
|
||||
ErrBooksCannotDelete = 4902, // Depth Of Market can not be removed
|
||||
ErrBooksCannotGet = 4903, // The data from Depth Of Market can not be obtained
|
||||
ErrBooksCannotSubscribe = 4904, // Error in subscribing to receive new data from Depth Of Market
|
||||
|
||||
ErrTooManyFiles = 5001, // More than 64 files cannot be opened at the same time
|
||||
ErrWrongFilename = 5002, // Invalid file name
|
||||
ErrTooLongFilename = 5003, // Too long file name
|
||||
ErrCannotOpenFile = 5004, // File opening error
|
||||
ErrFileCachebufferError = 5005, // Not enough memory for cache to read
|
||||
ErrCannotDeleteFile = 5006, // File deleting error
|
||||
ErrInvalidFilehandle = 5007, // A file with this handle was closed, or was not opening at all
|
||||
ErrWrongFilehandle = 5008, // Wrong file handle
|
||||
ErrFileNottowrite = 5009, // The file must be opened for writing
|
||||
ErrFileNottoread = 5010, // The file must be opened for reading
|
||||
ErrFileNotbin = 5011, // The file must be opened as a binary one
|
||||
ErrFileNottxt = 5012, // The file must be opened as a text
|
||||
ErrFileNottxtorcsv = 5013, // The file must be opened as a text or CSV
|
||||
ErrFileNotcsv = 5014, // The file must be opened as CSV
|
||||
ErrFileReaderror = 5015, // File reading error
|
||||
ErrFileBinstringsize = 5016, // String size must be specified, because the file is opened as binary
|
||||
ErrIncompatibleFile = 5017, // A text file must be for string arrays, for other arrays - binary
|
||||
ErrFileIsDirectory = 5018, // This is not a file, this is a directory
|
||||
ErrFileNotExist = 5019, // File does not exist
|
||||
ErrFileCannotRewrite = 5020, // File can not be rewritten
|
||||
ErrWrongDirectoryname = 5021, // Wrong directory name
|
||||
ErrDirectoryNotExist = 5022, // Directory does not exist
|
||||
ErrFileIsnotDirectory = 5023, // This is a file, not a directory
|
||||
ErrCannotDeleteDirectory = 5024, // The directory cannot be removed
|
||||
ErrCannotCleanDirectory = 5025, // Failed to clear the directory (probably one or more files are blocked and removal operation failed)
|
||||
ErrFileWriteerror = 5026, // Failed to write a resource to a file
|
||||
ErrFileEndoffile = 5027, // Unable to read the next piece of data from a CSV file (FileReadString, FileReadNumber, FileReadDatetime, FileReadBool), since the end of file is reached
|
||||
|
||||
ErrNoStringDate = 5030, // No date in the string
|
||||
ErrWrongStringDate = 5031, // Wrong date in the string
|
||||
ErrWrongStringTime = 5032, // Wrong time in the string
|
||||
ErrStringTimeError = 5033, // Error converting string to date
|
||||
ErrStringOutOfMemory = 5034, // Not enough memory for the string
|
||||
ErrStringSmallLen = 5035, // The string length is less than expected
|
||||
ErrStringTooBignumber = 5036, // Too large number, more than ULONG_MAX
|
||||
ErrWrongFormatstring = 5037, // Invalid format string
|
||||
ErrTooManyFormatters = 5038, // Amount of format specifiers more than the parameters
|
||||
ErrTooManyParameters = 5039, // Amount of parameters more than the format specifiers
|
||||
ErrWrongStringParameter = 5040, // Damaged parameter of string type
|
||||
ErrStringposOutofrange = 5041, // Position outside the string
|
||||
ErrStringZeroadded = 5042, // 0 added to the string end, a useless operation
|
||||
ErrStringUnknowntype = 5043, // Unknown data type when converting to a string
|
||||
ErrWrongStringObject = 5044, // Damaged string object
|
||||
|
||||
ErrIncompatibleArrays = 5050, // Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only
|
||||
ErrSmallAsseriesArray = 5051, // The receiving array is declared as AS_SERIES, and it is of insufficient size
|
||||
ErrSmallArray = 5052, // Too small array, the starting position is outside the array
|
||||
ErrZerosizeArray = 5053, // An array of zero length
|
||||
ErrNumberArraysOnly = 5054, // Must be a numeric array
|
||||
ErrOnedimArraysOnly = 5055, // Must be a one-dimensional array
|
||||
ErrSeriesArray = 5056, // Timeseries cannot be used
|
||||
ErrDoubleArrayOnly = 5057, // Must be an array of type double
|
||||
ErrFloatArrayOnly = 5058, // Must be an array of type float
|
||||
ErrLongArrayOnly = 5059, // Must be an array of type long
|
||||
ErrIntArrayOnly = 5060, // Must be an array of type int
|
||||
ErrShortArrayOnly = 5061, // Must be an array of type short
|
||||
ErrCharArrayOnly = 5062, // Must be an array of type char
|
||||
|
||||
ErrOpenclNotSupported = 5100, // OpenCL functions are not supported on this computer
|
||||
ErrOpenclInternal = 5101, // Internal error occurred when running OpenCL
|
||||
ErrOpenclInvalidHandle = 5102, // Invalid OpenCL handle
|
||||
ErrOpenclContextCreate = 5103, // Error creating the OpenCL context
|
||||
ErrOpenclQueueCreate = 5104, // Failed to create a run queue in OpenCL
|
||||
ErrOpenclProgramCreate = 5105, // Error occurred when compiling an OpenCL program
|
||||
ErrOpenclTooLongKernelName = 5106, // Too long kernel name (OpenCL kernel)
|
||||
ErrOpenclKernelCreate = 5107, // Error creating an OpenCL kernel
|
||||
ErrOpenclSetKernelParameter = 5108, // Error occurred when setting parameters for the OpenCL kernel
|
||||
ErrOpenclExecute = 5109, // OpenCL program runtime error
|
||||
ErrOpenclWrongBufferSize = 5110, // Invalid size of the OpenCL buffer
|
||||
ErrOpenclWrongBufferOffset = 5111, // Invalid offset in the OpenCL buffer
|
||||
ErrOpenclBufferCreate = 5112, // Failed to create an OpenCL buffer
|
||||
|
||||
ErrWebrequestInvalidAddress = 5200, // Invalid URL
|
||||
ErrWebrequestConnectFailed = 5201, // Failed to connect to specified URL
|
||||
ErrWebrequestTimeout = 5202, // Timeout exceeded
|
||||
ErrWebrequestRequestFailed = 5203, // HTTP request failed
|
||||
|
||||
ErrUserErrorFirst = 65536 // User defined errors start with this code
|
||||
}
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
public class ExecutionException: Exception
|
||||
{
|
||||
public ExecutionException(ErrorCode errorCode, string message)
|
||||
:base(message)
|
||||
{
|
||||
ErrorCode = errorCode;
|
||||
}
|
||||
|
||||
public ErrorCode ErrorCode { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
static class ExtensionMethods
|
||||
internal static class ExtensionMethods
|
||||
{
|
||||
#region Event Methods
|
||||
public static void FireEvent(this EventHandler eventHandler, object sender)
|
||||
{
|
||||
if (eventHandler != null)
|
||||
{
|
||||
eventHandler(sender, EventArgs.Empty);
|
||||
}
|
||||
eventHandler?.Invoke(sender, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public static void FireEvent<T>(this EventHandler<T> eventHandler, object sender, T e)
|
||||
where T : EventArgs
|
||||
{
|
||||
if (eventHandler != null)
|
||||
{
|
||||
eventHandler(sender, e);
|
||||
}
|
||||
eventHandler?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
+12
-11
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
@@ -19,13 +16,17 @@ namespace MtApi5
|
||||
this.real_volume = real_volume;
|
||||
}
|
||||
|
||||
public DateTime time { get; private set; } // Period start time
|
||||
public double open { get; private set; } // Open price
|
||||
public double high { get; private set; } // The highest price of the period
|
||||
public double low { get; private set; } // The lowest price of the period
|
||||
public double close { get; private set; } // Close price
|
||||
public long tick_volume { get; private set; } // Tick volume
|
||||
public int spread { get; private set; } // Spread
|
||||
public long real_volume { get; private set; } // Trade volume
|
||||
public MqlRates()
|
||||
{
|
||||
}
|
||||
|
||||
public DateTime time { get; set; } // Period start time
|
||||
public double open { get; set; } // Open price
|
||||
public double high { get; set; } // The highest price of the period
|
||||
public double low { get; set; } // The lowest price of the period
|
||||
public double close { get; set; } // Close price
|
||||
public long tick_volume { get; set; } // Tick volume
|
||||
public int spread { get; set; } // Spread
|
||||
public long real_volume { get; set; } // Trade volume
|
||||
}
|
||||
}
|
||||
|
||||
+13
-9
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
@@ -9,17 +6,24 @@ namespace MtApi5
|
||||
{
|
||||
public MqlTick(DateTime time, double bid, double ask, double last, ulong volume)
|
||||
{
|
||||
this.time = time;
|
||||
MtTime = Mt5TimeConverter.ConvertToMtTime(time);
|
||||
this.bid = bid;
|
||||
this.ask = ask;
|
||||
this.last = last;
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
public DateTime time { get; private set; } // Time of the last prices update
|
||||
public double bid { get; private set; } // Current Bid price
|
||||
public double ask { get; private set; } // Current Ask price
|
||||
public double last { get; private set; } // Price of the last deal (Last)
|
||||
public ulong volume { get; private set; } // Volume for the current Last price
|
||||
public MqlTick()
|
||||
{
|
||||
}
|
||||
|
||||
public long MtTime { get; set; } // Time of the last prices update
|
||||
|
||||
public double bid { get; set; } // Current Bid price
|
||||
public double ask { get; set; } // Current Ask price
|
||||
public double last { get; set; } // Price of the last deal (Last)
|
||||
public ulong volume { get; set; } // Volume for the current Last price
|
||||
|
||||
public DateTime time => Mt5TimeConverter.ConvertFromMtTime(MtTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
@@ -8,7 +6,7 @@ namespace MtApi5
|
||||
{
|
||||
public ENUM_TRADE_REQUEST_ACTIONS Action { get; set; } // Trade operation type
|
||||
public uint Magic { get; set; } // Expert Advisor ID (magic number)
|
||||
public uint Order { get; set; } // Order ticket
|
||||
public ulong Order { get; set; } // Order ticket
|
||||
public string Symbol { get; set; } // Trade symbol
|
||||
public double Volume { get; set; } // Requested volume for a deal in lots
|
||||
public double Price { get; set; } // Price
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Text;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
enum Mt5CommandType
|
||||
internal enum Mt5CommandType
|
||||
{
|
||||
//NoCommand = 0
|
||||
|
||||
@@ -101,6 +101,18 @@ namespace MtApi5
|
||||
MarketBookRelease = 61,
|
||||
MarketBookGet = 62,
|
||||
OrderCloseAll = 63,
|
||||
PositionClose = 64
|
||||
|
||||
//CTrade
|
||||
PositionClose = 64,
|
||||
PositionOpen = 65,
|
||||
|
||||
//Backtesting
|
||||
BacktestingReady = 66,
|
||||
IsTesting = 67,
|
||||
|
||||
Print = 68,
|
||||
|
||||
//Requests
|
||||
MtRequest = 155,
|
||||
}
|
||||
}
|
||||
+17
-1
@@ -32,9 +32,14 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@@ -42,6 +47,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CopyTicksFlag.cs" />
|
||||
<Compile Include="MqlBookInfo.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
<Compile Include="MqlTick.cs" />
|
||||
@@ -55,10 +61,17 @@
|
||||
<Compile Include="MqlTradeResult.cs" />
|
||||
<Compile Include="Mt5QuoteEventArgs.cs" />
|
||||
<Compile Include="MtApi5Client.cs" />
|
||||
<Compile Include="MtCommandType.cs" />
|
||||
<Compile Include="Mt5CommandType.cs" />
|
||||
<Compile Include="MtConverters.cs" />
|
||||
<Compile Include="ErrorCode.cs" />
|
||||
<Compile Include="ExecutionException.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Mt5Quote.cs" />
|
||||
<Compile Include="Requests\CopyTicksRequest.cs" />
|
||||
<Compile Include="Requests\RequestBase.cs" />
|
||||
<Compile Include="Requests\RequestType.cs" />
|
||||
<Compile Include="Responses\CopyTicksResponse.cs" />
|
||||
<Compile Include="Responses\ResponseBase.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
|
||||
@@ -66,6 +79,9 @@
|
||||
<Name>MTApiService</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
+590
-489
File diff suppressed because it is too large
Load Diff
+30
-33
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MTApiService;
|
||||
using System.Collections;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
static class MtConverters
|
||||
internal static class MtConverters
|
||||
{
|
||||
#region Values Converters
|
||||
public static Mt5Quote Parse(this MtQuote quote)
|
||||
@@ -17,29 +14,29 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out MqlTradeResult result)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
result = null;
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
{
|
||||
string[] values = inputString.Split(separator);
|
||||
var values = inputString.Split(separator);
|
||||
if (values.Length == 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
retVal = int.Parse(values[0]) != 0;
|
||||
|
||||
uint retcode = uint.Parse(values[1]);
|
||||
ulong deal = ulong.Parse(values[2]);
|
||||
ulong order = ulong.Parse(values[3]);
|
||||
double volume = double.Parse(values[4]);
|
||||
double price = double.Parse(values[5]);
|
||||
double bid = double.Parse(values[6]);
|
||||
double ask = double.Parse(values[7]);
|
||||
string comment = values[8];
|
||||
uint request_id = uint.Parse(values[9]);
|
||||
var retcode = uint.Parse(values[1]);
|
||||
var deal = ulong.Parse(values[2]);
|
||||
var order = ulong.Parse(values[3]);
|
||||
var volume = double.Parse(values[4]);
|
||||
var price = double.Parse(values[5]);
|
||||
var bid = double.Parse(values[6]);
|
||||
var ask = double.Parse(values[7]);
|
||||
var comment = values[8];
|
||||
var requestId = uint.Parse(values[9]);
|
||||
|
||||
result = new MqlTradeResult(retcode, deal, order, volume, price, bid, ask, comment, request_id);
|
||||
result = new MqlTradeResult(retcode, deal, order, volume, price, bid, ask, comment, requestId);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -52,28 +49,28 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out MqlTradeCheckResult result)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
result = null;
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
{
|
||||
string[] values = inputString.Split(separator);
|
||||
var values = inputString.Split(separator);
|
||||
if (values.Length == 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
retVal = int.Parse(values[0]) != 0;
|
||||
|
||||
uint retcode = uint.Parse(values[1]);
|
||||
double balance = double.Parse(values[2]);
|
||||
double equity = double.Parse(values[3]);
|
||||
double profit = double.Parse(values[4]);
|
||||
double margin = double.Parse(values[5]);
|
||||
double margin_free = double.Parse(values[6]);
|
||||
double margin_level = double.Parse(values[7]);
|
||||
string comment = values[8];
|
||||
var retcode = uint.Parse(values[1]);
|
||||
var balance = double.Parse(values[2]);
|
||||
var equity = double.Parse(values[3]);
|
||||
var profit = double.Parse(values[4]);
|
||||
var margin = double.Parse(values[5]);
|
||||
var marginFree = double.Parse(values[6]);
|
||||
var marginLevel = double.Parse(values[7]);
|
||||
var comment = values[8];
|
||||
|
||||
result = new MqlTradeCheckResult(retcode, balance, equity, profit, margin, margin_free, margin_level, comment);
|
||||
result = new MqlTradeCheckResult(retcode, balance, equity, profit, margin, marginFree, marginLevel, comment);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -87,7 +84,7 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out double result)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
result = 0;
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
@@ -113,24 +110,24 @@ namespace MtApi5
|
||||
|
||||
public static bool ParseResult(this string inputString, char separator, out DateTime from, out DateTime to)
|
||||
{
|
||||
bool retVal = false;
|
||||
var retVal = false;
|
||||
|
||||
from = new DateTime();
|
||||
to = new DateTime();
|
||||
|
||||
if (string.IsNullOrEmpty(inputString) == false)
|
||||
{
|
||||
string[] values = inputString.Split(separator);
|
||||
var values = inputString.Split(separator);
|
||||
if (values.Length == 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
retVal = int.Parse(values[0]) != 0;
|
||||
|
||||
int iFrom = int.Parse(values[1]);
|
||||
var iFrom = int.Parse(values[1]);
|
||||
from = Mt5TimeConverter.ConvertFromMtTime(iFrom);
|
||||
|
||||
int iTo= int.Parse(values[2]);
|
||||
var iTo= int.Parse(values[2]);
|
||||
to = Mt5TimeConverter.ConvertFromMtTime(iTo);
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -148,7 +145,7 @@ namespace MtApi5
|
||||
if (request == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
int exp = Mt5TimeConverter.ConvertToMtTime(request.Expiration);
|
||||
var exp = Mt5TimeConverter.ConvertToMtTime(request.Expiration);
|
||||
|
||||
return new ArrayList { (int)request.Action, request.Magic, request.Order, request.Symbol, request.Volume
|
||||
, request.Price, request.Stoplimit, request.Sl, request.Tp, request.Deviation, (int)request.Type
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.10.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.10.0")]
|
||||
[assembly: AssemblyVersion("1.0.11.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.11.0")]
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class CopyTicksRequest: RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.CopyTicks;
|
||||
|
||||
public string SymbolName { get; set; }
|
||||
public int Flags { get; set; }
|
||||
public ulong From { get; set; }
|
||||
public uint Count { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal abstract class RequestBase
|
||||
{
|
||||
public abstract RequestType RequestType { get; }
|
||||
}
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal enum RequestType
|
||||
{
|
||||
Unknown = 0,
|
||||
CopyTicks = 1
|
||||
}
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MtApi5.Responses
|
||||
{
|
||||
internal class CopyTicksResponse: ResponseBase
|
||||
{
|
||||
public List<MqlTick> Ticks { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
namespace MtApi5.Responses
|
||||
{
|
||||
internal class ResponseBase
|
||||
{
|
||||
public int ErrorCode { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
}
|
||||
}
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net40" />
|
||||
</packages>
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
|
||||
<?if $(var.Platform) = x64 ?>
|
||||
<?define MsiSourceFileName="MtApi5Installer_x64.msi"?>
|
||||
<?define VcRedistFileName="vc_redist.x64.exe"?>
|
||||
<?else ?>
|
||||
<?define MsiSourceFileName="MtApi5Installer_x86.msi"?>
|
||||
<?define VcRedistFileName="vc_redist.x86.exe"?>
|
||||
<?endif ?>
|
||||
|
||||
<?define ProductName="!(bind.packageName.MtApi5Msi)" ?>
|
||||
<?define ProductVersion="!(bind.packageVersion.MtApi5Msi)" ?>
|
||||
<?define Manufacturer="!(bind.packageManufacturer.MtApi5Msi)" ?>
|
||||
|
||||
<Bundle Name="$(var.ProductName) Bootstrapper"
|
||||
Version="$(var.ProductVersion)"
|
||||
Manufacturer="$(var.Manufacturer)"
|
||||
UpgradeCode="1497e285-c228-490b-9638-565e118548fb">
|
||||
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
|
||||
<bal:WixStandardBootstrapperApplication LicenseFile="..\LICENSE.rtf"/>
|
||||
</BootstrapperApplicationRef>
|
||||
|
||||
<Chain>
|
||||
|
||||
<ExePackage SourceFile="..\vcredist\$(var.VcRedistFileName)"
|
||||
Name="Redist\$(var.VcRedistFileName)"
|
||||
Cache="no"
|
||||
Compressed="yes"
|
||||
InstallCommand="/install /quiet /norestart">
|
||||
<!-- Ignore "Newer version installed" error -->
|
||||
<ExitCode Value="1638" Behavior="success"/>
|
||||
</ExePackage>
|
||||
|
||||
<MsiPackage Id="MtApi5Msi"
|
||||
SourceFile="..\build\installers\$(var.Configuration)\$(var.MsiSourceFileName)"
|
||||
Visible="yes"
|
||||
DisplayInternalUI="yes" />
|
||||
|
||||
</Chain>
|
||||
</Bundle>
|
||||
</Wix>
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<ProjectGuid>1497e285-c228-490b-9638-565e118548fb</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MtApi5_Setup_$(Platform)</OutputName>
|
||||
<OutputType>Bundle</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Bundle.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixBalExtension">
|
||||
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
|
||||
<Name>WixBalExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" />
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Wix.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -6,7 +6,7 @@
|
||||
<ProductVersion>3.6</ProductVersion>
|
||||
<ProjectGuid>{a9ed070f-ab4d-4380-9dde-5d931ac71333}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MtApi5Installer</OutputName>
|
||||
<OutputName>MtApi5Installer_$(Platform)</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
@@ -22,11 +22,11 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
<OutputPath>..\build\installers\$(Configuration)\x64\</OutputPath>
|
||||
<OutputPath>..\build\installers\$(Configuration)</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\x64\</OutputPath>
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?define ProductName="MtApi5" ?>
|
||||
|
||||
<?if $(var.Platform) = x64 ?>
|
||||
<?define ProductName="MtApi5_x64" ?>
|
||||
<?define ProductPathNative="..\build\products\$(var.Configuration)\x64\"?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
||||
<?define PlatformSystemFolder = "System64Folder" ?>
|
||||
<?else ?>
|
||||
<?define ProductName="MtApi5" ?>
|
||||
<?define ProductPathNative="..\build\products\$(var.Configuration)\"?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
||||
<?define PlatformSystemFolder = "SystemFolder" ?>
|
||||
<?endif ?>
|
||||
|
||||
<?define ProductVersion="1.0.10" ?>
|
||||
<?define ProductVersion=!(bind.FileVersion.MtApi5.dll) ?>
|
||||
<?define Manufacturer="DW"?>
|
||||
<?define ProductPath="..\build\products\$(var.Configuration)\"?>
|
||||
|
||||
<Product Id="*"
|
||||
<Product Id="*"
|
||||
Name="$(var.ProductName) $(var.ProductVersion)"
|
||||
Language="1033"
|
||||
Version="$(var.ProductVersion)"
|
||||
Manufacturer="$(var.Manufacturer)"
|
||||
UpgradeCode="d72d346e-e6f7-4c23-85c6-1c42b3175599">
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
<WixVariable Id="WixUILicenseRtf" Value="..\LICENSE.rtf" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Feature Id="MtApi5" Title="$(var.ProductName)" Level="1">
|
||||
@@ -37,7 +39,7 @@
|
||||
|
||||
<Property Id="WIXUI_INSTALLDIR">INSTALLFOLDER</Property>
|
||||
<UIRef Id="WixUI_Mondo" />
|
||||
</Product>
|
||||
</Product>
|
||||
|
||||
<Fragment>
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
@@ -78,6 +80,11 @@
|
||||
</RegistryKey>
|
||||
|
||||
</Component>
|
||||
|
||||
<Component Id="NewtonsoftJsondll" Directory="INSTALLFOLDER">
|
||||
<File Id="Newtonsoft.Json.dll" Name="Newtonsoft.Json.dll" KeyPath="yes"
|
||||
src="$(var.ProductPath)Newtonsoft.Json.dll"/>
|
||||
</Component>
|
||||
|
||||
<Component Id="MTApiServiceDll" Directory="INSTALLFOLDER">
|
||||
<File Id="GAC_MTApiService.dll" Name="MTApiService.dll" KeyPath="yes"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable
+41
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
|
||||
|
||||
<?if $(var.Platform) = x64 ?>
|
||||
<?define VcRedistFileName="vc_redist.x64.exe"?>
|
||||
<?else ?>
|
||||
<?define VcRedistFileName="vc_redist.x86.exe"?>
|
||||
<?endif ?>
|
||||
|
||||
<?define MsiSourceFileName="MtApiInstaller.msi"?>
|
||||
|
||||
<?define ProductName="!(bind.packageName.MtApiMsi)" ?>
|
||||
<?define ProductVersion="!(bind.packageVersion.MtApiMsi)" ?>
|
||||
<?define Manufacturer="!(bind.packageManufacturer.MtApiMsi)" ?>
|
||||
|
||||
<Bundle Name="$(var.ProductName) Bootstrapper"
|
||||
Version="$(var.ProductVersion)"
|
||||
Manufacturer="$(var.Manufacturer)"
|
||||
UpgradeCode="8e63046b-56e5-4623-8808-558ad72a8f2b">
|
||||
|
||||
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
|
||||
<bal:WixStandardBootstrapperApplication LicenseFile="..\LICENSE.rtf"/>
|
||||
</BootstrapperApplicationRef>
|
||||
|
||||
<Chain>
|
||||
<ExePackage SourceFile="..\vcredist\$(var.VcRedistFileName)"
|
||||
Name="Redist\$(var.VcRedistFileName)"
|
||||
Cache="no"
|
||||
Compressed="yes"
|
||||
InstallCommand="/install /quiet /norestart">
|
||||
<!-- Ignore "Newer version installed" error -->
|
||||
<ExitCode Value="1638" Behavior="success"/>
|
||||
</ExePackage>
|
||||
|
||||
<MsiPackage Id="MtApiMsi"
|
||||
SourceFile="..\build\installers\$(var.Configuration)\$(var.MsiSourceFileName)"
|
||||
Visible="yes"
|
||||
DisplayInternalUI="yes" />
|
||||
</Chain>
|
||||
</Bundle>
|
||||
</Wix>
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<ProjectGuid>8e63046b-56e5-4623-8808-558ad72a8f2b</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MtApi_Setup</OutputName>
|
||||
<OutputType>Bundle</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>Debug</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>..\build\installers\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Bundle.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixBalExtension">
|
||||
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
|
||||
<Name>WixBalExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" />
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Wix.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -6,7 +6,7 @@
|
||||
<ProductVersion>3.6</ProductVersion>
|
||||
<ProjectGuid>{78b94552-db17-40ec-b7c6-23d32db85dc1}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>MtApiSetup</OutputName>
|
||||
<OutputName>MtApiInstaller</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user