mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-07-28 11:07:48 +00:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9eedf15e9e | |||
| 373bfe4997 | |||
| 0cd8edb933 | |||
| a66f18c2b3 | |||
| 71964c3303 | |||
| 4e7f8b93f4 | |||
| 5715e7e2b8 | |||
| 833ce1f192 | |||
| 724162f29d | |||
| 739567d871 | |||
| a12ddba765 | |||
| 9a5acac2db | |||
| 7a776de8d3 | |||
| ce7953eee0 | |||
| 93aed4e44c | |||
| 4c8c3b8766 | |||
| 73ebde8b6b | |||
| e33ba5b51f | |||
| a0a4263e24 | |||
| 5d18dd4ad3 | |||
| 03ff1f9176 | |||
| f376b4e0e5 | |||
| fc54b5dd4a | |||
| dd05804082 | |||
| 4349eb3538 | |||
| e0daf9a82e | |||
| 3997b6df74 | |||
| abfe1a281a | |||
| 93bfe8e56f | |||
| bb27b4e50d | |||
| 0f809cd60a | |||
| f22a6c21f0 | |||
| 625753d83a | |||
| d621312a8b | |||
| a4df4bbf1e | |||
| 43ef628c69 | |||
| 688149bd67 | |||
| c33a5ed6f5 | |||
| 828c1185b3 | |||
| 4b384d9da2 | |||
| 26de553443 | |||
| ee81cfe012 | |||
| 5f4ae3cd9e | |||
| 13b8aa9644 | |||
| e364b313c3 | |||
| 68f2a7ae07 | |||
| 42a1da3356 | |||
| 44fab4dae1 | |||
| d1387148df | |||
| bb4ac426cd | |||
| 34b4e33cc9 | |||
| f01ec01a5f | |||
| 0c38d37559 | |||
| 897892dc89 | |||
| 1a5882b75a | |||
| 0f717f1cb7 | |||
| 5d78ad5067 | |||
| 6c45f28a05 | |||
| ca3c0e735f | |||
| f71151104b | |||
| 28816a75ac | |||
| 6023bffed6 | |||
| fd34f009cd | |||
| 1bb2b65cdf | |||
| 37e8275465 |
@@ -18,6 +18,9 @@ bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
|
||||
# Roslyn cache directories
|
||||
*.ide/
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<Window x:Class="ConnectionsManager.AboutWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="About" Height="130" Width="300"
|
||||
WindowStyle="ToolWindow"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Window.Resources>
|
||||
<BitmapImage x:Key="MtApiIcon" UriSource="pack://application:,,,/ConnectionsManager;component/favicon.ico"/>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Source="{StaticResource MtApiIcon}" Width="50" Height="50" HorizontalAlignment="Left" Margin="5"/>
|
||||
<TextBlock Grid.Column="1" Text="Connection manager for MtApi" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
|
||||
<Button Grid.Row="1" Content="OK" Margin="5"
|
||||
Width="70" IsDefault="True" IsCancel="True"
|
||||
DockPanel.Dock="Bottom"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ConnectionsManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AboutWindow.xaml
|
||||
/// </summary>
|
||||
public partial class AboutWindow : Window
|
||||
{
|
||||
public AboutWindow(Window owner)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.Owner = owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<Window x:Class="ConnectionsManager.AddProfileDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Add new connection profile" Height="180" Width="300"
|
||||
WindowStyle="ToolWindow"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Grid x:Name="_MainLayout">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Profile name" Margin="5"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Margin="5"
|
||||
Text="{Binding Path=ProfileName, UpdateSourceTrigger=PropertyChanged}"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Host" Margin="5"/>
|
||||
<ComboBox Grid.Row="1" Grid.Column="1" Margin="5"
|
||||
ItemsSource="{Binding HostList}"
|
||||
SelectedItem="{Binding Host}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Port" Margin="5"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Margin="5"
|
||||
Text="{Binding Path=Port, UpdateSourceTrigger=PropertyChanged}"
|
||||
PreviewTextInput="TextBox_PreviewTextInput"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<StackPanel Grid.Row="3" Grid.ColumnSpan="2" Margin="0,10,0,0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="OK" Width="70" Margin="4" IsDefault="True" Command="{Binding OkCommand}"/>
|
||||
<Button Content="Cancel" Width="70" Margin="4" IsCancel="True"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,97 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Net;
|
||||
|
||||
namespace ConnectionsManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AddProfileDialog.xaml
|
||||
/// </summary>
|
||||
public partial class AddProfileDialog : Window
|
||||
{
|
||||
// private const string PIPE_SERVER_NAME = "localhost(pipe)";
|
||||
private const string LOCALHOST_NAME = "localhost";
|
||||
|
||||
public string ProfileName { get; set; }
|
||||
|
||||
public static readonly DependencyProperty HostProperty = DependencyProperty.Register("Host", typeof(string), typeof(AddProfileDialog));
|
||||
public string Host
|
||||
{
|
||||
get { return (string)this.GetValue(HostProperty); }
|
||||
set { this.SetValue(HostProperty, value); }
|
||||
}
|
||||
|
||||
public string Port { get; set; }
|
||||
|
||||
public DelegateCommand OkCommand { get; set; }
|
||||
|
||||
public List<string> HostList { get; set; }
|
||||
|
||||
public AddProfileDialog(Window owner)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.Owner = owner;
|
||||
|
||||
OkCommand = new DelegateCommand(ExecuteOk, CanExecuteOk);
|
||||
_MainLayout.DataContext = this;
|
||||
|
||||
Loaded += (sender, e) => MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
|
||||
|
||||
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
|
||||
|
||||
HostList = new List<string>();
|
||||
HostList.Add(string.Empty);
|
||||
HostList.Add(LOCALHOST_NAME);
|
||||
|
||||
if (ips != null)
|
||||
{
|
||||
foreach (IPAddress ipAddress in ips.AddressList)
|
||||
{
|
||||
HostList.Add(ipAddress.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
Host = HostList.First();
|
||||
}
|
||||
|
||||
private bool CanExecuteOk(object o)
|
||||
{
|
||||
return string.IsNullOrEmpty(ProfileName) == false
|
||||
&& string.IsNullOrEmpty(Port) == false;
|
||||
}
|
||||
|
||||
private void ExecuteOk(object o)
|
||||
{
|
||||
this.DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private static bool IsTextAllowed(string text)
|
||||
{
|
||||
Regex regex = new Regex("[^0-9]+");
|
||||
return !regex.IsMatch(text);
|
||||
}
|
||||
|
||||
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
e.Handled = !IsTextAllowed(e.Text);
|
||||
}
|
||||
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
OkCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<Application x:Class="ConnectionsManager.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
namespace ConnectionsManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
<?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>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C8751BA1-6A85-468C-87BD-758F37B8C0DD}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ConnectionsManager</RootNamespace>
|
||||
<AssemblyName>ConnectionsManager</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<CodeAnalysisLogFile>bin\Debug\ConnectionsManager.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
|
||||
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
|
||||
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<CodeAnalysisLogFile>bin\Release\ConnectionsManager.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
|
||||
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
|
||||
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="AboutWindow.xaml.cs">
|
||||
<DependentUpon>AboutWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="AddProfileDialog.xaml.cs">
|
||||
<DependentUpon>AddProfileDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="DelegateCommand.cs" />
|
||||
<Compile Include="ViewModel.cs" />
|
||||
<Page Include="AboutWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="AddProfileDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
|
||||
<Project>{DE76D5C7-B99C-4467-8408-78173BDD84E0}</Project>
|
||||
<Name>MTApiService</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="favicon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy $(TargetPath) $(SolutionDir)Release\</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- 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">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace ConnectionsManager
|
||||
{
|
||||
public class DelegateCommand : ICommand
|
||||
{
|
||||
private readonly Predicate<object> _canExecute;
|
||||
private readonly Action<object> _execute;
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public DelegateCommand(Action<object> execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
public DelegateCommand(Action<object> execute,
|
||||
Predicate<object> canExecute)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
if (_canExecute == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return _canExecute(parameter);
|
||||
}
|
||||
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
_execute(parameter);
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
if (CanExecuteChanged != null)
|
||||
{
|
||||
CanExecuteChanged(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<Window x:Class="ConnectionsManager.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="MtApi Connections Manager" Height="300" Width="440"
|
||||
Loaded="Window_Loaded">
|
||||
<Grid x:Name="_MainLayout">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Menu>
|
||||
<MenuItem Header="Edit">
|
||||
<MenuItem Header="Add Profile..." Command="{Binding AddProfileCommand}"/>
|
||||
<MenuItem Header="Delete Profile" Command="{Binding DeleteProfileCommand}"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Help">
|
||||
<MenuItem Header="About" Command="{Binding ShowAboutCommand}"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<ListView Grid.Row="1"
|
||||
ItemsSource="{Binding ConnectionProfiles}"
|
||||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SelectedProfile}">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Width="140" Header="Profile" DisplayMemberBinding="{Binding Name}" />
|
||||
<GridViewColumn Width="180" Header="Host" DisplayMemberBinding="{Binding Host}" />
|
||||
<GridViewColumn Width="80" Header="Port" DisplayMemberBinding="{Binding Port}" />
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ConnectionsManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private ViewModel _vm;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_vm = new ViewModel();
|
||||
_MainLayout.DataContext = _vm;
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_vm.Initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ConnectionsManager")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ConnectionsManager")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// 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.1.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.1.0")]
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18034
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ConnectionsManager.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ConnectionsManager.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18034
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ConnectionsManager.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.ObjectModel;
|
||||
using MTApiService;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
|
||||
namespace ConnectionsManager
|
||||
{
|
||||
class ViewModel : INotifyPropertyChanged
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private ObservableCollection<MtConnectionProfile> _ConnectionProfiles = new ObservableCollection<MtConnectionProfile>();
|
||||
public ObservableCollection<MtConnectionProfile> ConnectionProfiles
|
||||
{
|
||||
get { return _ConnectionProfiles; }
|
||||
}
|
||||
|
||||
public DelegateCommand AddProfileCommand { get; private set; }
|
||||
public DelegateCommand DeleteProfileCommand { get; private set; }
|
||||
public DelegateCommand ShowAboutCommand { get; private set; }
|
||||
|
||||
private MtConnectionProfile _SelectedProfile;
|
||||
public MtConnectionProfile SelectedProfile
|
||||
{
|
||||
get { return _SelectedProfile; }
|
||||
set
|
||||
{
|
||||
_SelectedProfile = value;
|
||||
OnPropertyChanged("SelectedProfile");
|
||||
DeleteProfileCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public ViewModel()
|
||||
{
|
||||
AddProfileCommand = new DelegateCommand(ExecuteAddProfile);
|
||||
DeleteProfileCommand = new DelegateCommand(ExecuteDeleteProfile, CanExecuteDeleteProfile);
|
||||
ShowAboutCommand = new DelegateCommand(ExecuteShowAbout);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var profiles = MtRegistryManager.LoadConnectionProfiles();
|
||||
if (profiles != null)
|
||||
{
|
||||
foreach(var prof in profiles)
|
||||
{
|
||||
ConnectionProfiles.Add(prof);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void ExecuteAddProfile(object o)
|
||||
{
|
||||
var dlg = new AddProfileDialog(App.Current.MainWindow);
|
||||
var result = dlg.ShowDialog();
|
||||
|
||||
if (result == true)
|
||||
{
|
||||
var profile = new MtConnectionProfile(dlg.ProfileName);
|
||||
profile.Host = dlg.Host;
|
||||
profile.Port = int.Parse(dlg.Port);
|
||||
|
||||
MtRegistryManager.AddConnectionProfile(profile);
|
||||
ConnectionProfiles.Add(profile);
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanExecuteDeleteProfile(object o)
|
||||
{
|
||||
return SelectedProfile != null;
|
||||
}
|
||||
|
||||
private void ExecuteDeleteProfile(object o)
|
||||
{
|
||||
var result = MessageBox.Show("Do you want to delete connection profile '" + SelectedProfile.Name + "' ?"
|
||||
, "Question", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
MtRegistryManager.RemoveConnectionProfile(SelectedProfile.Name);
|
||||
ConnectionProfiles.Remove(SelectedProfile);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteShowAbout(object o)
|
||||
{
|
||||
var dlg = new AboutWindow(App.Current.MainWindow);
|
||||
dlg.ShowDialog();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region INotifyPropertyChanged
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChangedEventHandler handler = PropertyChanged;
|
||||
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 894 B |
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Security;
|
||||
|
||||
namespace Licensing
|
||||
{
|
||||
public class DigitalSignatureHelper
|
||||
{
|
||||
public static String GeneratePrivateKey()
|
||||
{
|
||||
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
|
||||
return dsa.ToXmlString(true);
|
||||
}
|
||||
|
||||
public static String GetPublicKey(String privateKey)
|
||||
{
|
||||
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
|
||||
dsa.FromXmlString(privateKey);
|
||||
return dsa.ToXmlString(false);
|
||||
}
|
||||
|
||||
public static string CreateSignature(string inputData, String privateKey)
|
||||
{
|
||||
// create the crypto-service provider:
|
||||
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
|
||||
|
||||
// setup the dsa from the private key:
|
||||
dsa.FromXmlString(privateKey);
|
||||
|
||||
byte[] data = UTF8Encoding.ASCII.GetBytes(inputData);
|
||||
|
||||
// get the signature:
|
||||
byte[] signature = dsa.SignData(data);
|
||||
|
||||
return Convert.ToBase64String(signature);
|
||||
}
|
||||
|
||||
public static bool VerifySignature(string inputData, string signature, string publicKey)
|
||||
{
|
||||
// create the crypto-service provider:
|
||||
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
|
||||
|
||||
// setup the provider from the public key:
|
||||
dsa.FromXmlString(publicKey);
|
||||
|
||||
// get the license terms data:
|
||||
//byte[] data = Convert.FromBase64String(inputData);
|
||||
byte[] data = UTF8Encoding.ASCII.GetBytes(inputData);
|
||||
|
||||
// get the signature data:
|
||||
byte[] signatureData = Convert.FromBase64String(signature);
|
||||
|
||||
// verify that the license-terms match the signature data
|
||||
if (dsa.VerifyData(data, signatureData) == false)
|
||||
throw new SecurityException("Signature Not Verified!");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?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)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{21FA6E21-EE5D-4A84-B0ED-E1D8876B41FB}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Licensing</RootNamespace>
|
||||
<AssemblyName>Licensing</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DigitalSignatureHelper.cs" />
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.Designer.cs">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
|
||||
<Project>{DE76D5C7-B99C-4467-8408-78173BDD84E0}</Project>
|
||||
<Name>MTApiService</Name>
|
||||
</ProjectReference>
|
||||
</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.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
Generated
-326
@@ -1,326 +0,0 @@
|
||||
namespace Licensing
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.textBoxPublicKey = new System.Windows.Forms.TextBox();
|
||||
this.buttonGenerateKey = new System.Windows.Forms.Button();
|
||||
this.buttonLoadKey = new System.Windows.Forms.Button();
|
||||
this.buttonSaveKey = new System.Windows.Forms.Button();
|
||||
this.textBoxPrivateKey = new System.Windows.Forms.TextBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.textBoxAccountName = new System.Windows.Forms.TextBox();
|
||||
this.textBoxAccountNumber = new System.Windows.Forms.TextBox();
|
||||
this.buttonSign = new System.Windows.Forms.Button();
|
||||
this.textBoxSignature = new System.Windows.Forms.TextBox();
|
||||
this.buttonGetPublicKey = new System.Windows.Forms.Button();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.clipboardCopyBtn = new System.Windows.Forms.Button();
|
||||
this.buttonExportPublicKey = new System.Windows.Forms.Button();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
||||
this.saveToRegBtn = new System.Windows.Forms.Button();
|
||||
this.buttonVerify = new System.Windows.Forms.Button();
|
||||
this.buttonExportSignature = new System.Windows.Forms.Button();
|
||||
this.readRegBtn = new System.Windows.Forms.Button();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
this.groupBox3.SuspendLayout();
|
||||
this.groupBox4.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBoxPublicKey
|
||||
//
|
||||
this.textBoxPublicKey.Location = new System.Drawing.Point(6, 19);
|
||||
this.textBoxPublicKey.Name = "textBoxPublicKey";
|
||||
this.textBoxPublicKey.ReadOnly = true;
|
||||
this.textBoxPublicKey.Size = new System.Drawing.Size(620, 20);
|
||||
this.textBoxPublicKey.TabIndex = 0;
|
||||
//
|
||||
// buttonGenerateKey
|
||||
//
|
||||
this.buttonGenerateKey.Location = new System.Drawing.Point(6, 45);
|
||||
this.buttonGenerateKey.Name = "buttonGenerateKey";
|
||||
this.buttonGenerateKey.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonGenerateKey.TabIndex = 2;
|
||||
this.buttonGenerateKey.Text = "Generate";
|
||||
this.buttonGenerateKey.UseVisualStyleBackColor = true;
|
||||
this.buttonGenerateKey.Click += new System.EventHandler(this.buttonGenerateKey_Click);
|
||||
//
|
||||
// buttonLoadKey
|
||||
//
|
||||
this.buttonLoadKey.Location = new System.Drawing.Point(168, 45);
|
||||
this.buttonLoadKey.Name = "buttonLoadKey";
|
||||
this.buttonLoadKey.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonLoadKey.TabIndex = 3;
|
||||
this.buttonLoadKey.Text = "Load";
|
||||
this.buttonLoadKey.UseVisualStyleBackColor = true;
|
||||
this.buttonLoadKey.Click += new System.EventHandler(this.buttonLoadKey_Click);
|
||||
//
|
||||
// buttonSaveKey
|
||||
//
|
||||
this.buttonSaveKey.Location = new System.Drawing.Point(87, 45);
|
||||
this.buttonSaveKey.Name = "buttonSaveKey";
|
||||
this.buttonSaveKey.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonSaveKey.TabIndex = 4;
|
||||
this.buttonSaveKey.Text = "Save";
|
||||
this.buttonSaveKey.UseVisualStyleBackColor = true;
|
||||
this.buttonSaveKey.Click += new System.EventHandler(this.buttonSaveKey_Click);
|
||||
//
|
||||
// textBoxPrivateKey
|
||||
//
|
||||
this.textBoxPrivateKey.Location = new System.Drawing.Point(6, 19);
|
||||
this.textBoxPrivateKey.Name = "textBoxPrivateKey";
|
||||
this.textBoxPrivateKey.ReadOnly = true;
|
||||
this.textBoxPrivateKey.Size = new System.Drawing.Size(620, 20);
|
||||
this.textBoxPrivateKey.TabIndex = 0;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(8, 48);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(47, 13);
|
||||
this.label4.TabIndex = 6;
|
||||
this.label4.Text = "Number:";
|
||||
//
|
||||
// textBoxAccountName
|
||||
//
|
||||
this.textBoxAccountName.Location = new System.Drawing.Point(67, 19);
|
||||
this.textBoxAccountName.Name = "textBoxAccountName";
|
||||
this.textBoxAccountName.Size = new System.Drawing.Size(559, 20);
|
||||
this.textBoxAccountName.TabIndex = 7;
|
||||
//
|
||||
// textBoxAccountNumber
|
||||
//
|
||||
this.textBoxAccountNumber.Location = new System.Drawing.Point(67, 45);
|
||||
this.textBoxAccountNumber.Name = "textBoxAccountNumber";
|
||||
this.textBoxAccountNumber.Size = new System.Drawing.Size(559, 20);
|
||||
this.textBoxAccountNumber.TabIndex = 7;
|
||||
//
|
||||
// buttonSign
|
||||
//
|
||||
this.buttonSign.Location = new System.Drawing.Point(10, 45);
|
||||
this.buttonSign.Name = "buttonSign";
|
||||
this.buttonSign.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonSign.TabIndex = 8;
|
||||
this.buttonSign.Text = "Sign";
|
||||
this.buttonSign.UseVisualStyleBackColor = true;
|
||||
this.buttonSign.Click += new System.EventHandler(this.buttonSign_Click);
|
||||
//
|
||||
// textBoxSignature
|
||||
//
|
||||
this.textBoxSignature.Location = new System.Drawing.Point(10, 19);
|
||||
this.textBoxSignature.Name = "textBoxSignature";
|
||||
this.textBoxSignature.Size = new System.Drawing.Size(615, 20);
|
||||
this.textBoxSignature.TabIndex = 10;
|
||||
//
|
||||
// buttonGetPublicKey
|
||||
//
|
||||
this.buttonGetPublicKey.Location = new System.Drawing.Point(6, 45);
|
||||
this.buttonGetPublicKey.Name = "buttonGetPublicKey";
|
||||
this.buttonGetPublicKey.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonGetPublicKey.TabIndex = 11;
|
||||
this.buttonGetPublicKey.Text = "Get Key";
|
||||
this.buttonGetPublicKey.UseVisualStyleBackColor = true;
|
||||
this.buttonGetPublicKey.Click += new System.EventHandler(this.buttonGetPublicKey_Click);
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.textBoxPrivateKey);
|
||||
this.groupBox1.Controls.Add(this.buttonGenerateKey);
|
||||
this.groupBox1.Controls.Add(this.buttonLoadKey);
|
||||
this.groupBox1.Controls.Add(this.buttonSaveKey);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(632, 78);
|
||||
this.groupBox1.TabIndex = 12;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Private Key";
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.clipboardCopyBtn);
|
||||
this.groupBox2.Controls.Add(this.buttonExportPublicKey);
|
||||
this.groupBox2.Controls.Add(this.textBoxPublicKey);
|
||||
this.groupBox2.Controls.Add(this.buttonGetPublicKey);
|
||||
this.groupBox2.Location = new System.Drawing.Point(12, 96);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(632, 77);
|
||||
this.groupBox2.TabIndex = 13;
|
||||
this.groupBox2.TabStop = false;
|
||||
this.groupBox2.Text = "Public Key";
|
||||
//
|
||||
// clipboardCopyBtn
|
||||
//
|
||||
this.clipboardCopyBtn.Location = new System.Drawing.Point(169, 46);
|
||||
this.clipboardCopyBtn.Name = "clipboardCopyBtn";
|
||||
this.clipboardCopyBtn.Size = new System.Drawing.Size(113, 23);
|
||||
this.clipboardCopyBtn.TabIndex = 13;
|
||||
this.clipboardCopyBtn.Text = "Copy to Clipboard";
|
||||
this.clipboardCopyBtn.UseVisualStyleBackColor = true;
|
||||
this.clipboardCopyBtn.Click += new System.EventHandler(this.clipboardCopyBtn_Click);
|
||||
//
|
||||
// buttonExportPublicKey
|
||||
//
|
||||
this.buttonExportPublicKey.Location = new System.Drawing.Point(88, 46);
|
||||
this.buttonExportPublicKey.Name = "buttonExportPublicKey";
|
||||
this.buttonExportPublicKey.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonExportPublicKey.TabIndex = 12;
|
||||
this.buttonExportPublicKey.Text = "Export";
|
||||
this.buttonExportPublicKey.UseVisualStyleBackColor = true;
|
||||
this.buttonExportPublicKey.Click += new System.EventHandler(this.buttonExportPublicKey_Click);
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this.textBoxAccountName);
|
||||
this.groupBox3.Controls.Add(this.label3);
|
||||
this.groupBox3.Controls.Add(this.textBoxAccountNumber);
|
||||
this.groupBox3.Controls.Add(this.label4);
|
||||
this.groupBox3.Location = new System.Drawing.Point(12, 180);
|
||||
this.groupBox3.Name = "groupBox3";
|
||||
this.groupBox3.Size = new System.Drawing.Size(635, 81);
|
||||
this.groupBox3.TabIndex = 14;
|
||||
this.groupBox3.TabStop = false;
|
||||
this.groupBox3.Text = "Account";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(8, 22);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(38, 13);
|
||||
this.label3.TabIndex = 5;
|
||||
this.label3.Text = "Name:";
|
||||
//
|
||||
// groupBox4
|
||||
//
|
||||
this.groupBox4.Controls.Add(this.readRegBtn);
|
||||
this.groupBox4.Controls.Add(this.saveToRegBtn);
|
||||
this.groupBox4.Controls.Add(this.buttonVerify);
|
||||
this.groupBox4.Controls.Add(this.buttonExportSignature);
|
||||
this.groupBox4.Controls.Add(this.textBoxSignature);
|
||||
this.groupBox4.Controls.Add(this.buttonSign);
|
||||
this.groupBox4.Location = new System.Drawing.Point(13, 268);
|
||||
this.groupBox4.Name = "groupBox4";
|
||||
this.groupBox4.Size = new System.Drawing.Size(631, 76);
|
||||
this.groupBox4.TabIndex = 15;
|
||||
this.groupBox4.TabStop = false;
|
||||
this.groupBox4.Text = "Signature";
|
||||
//
|
||||
// saveToRegBtn
|
||||
//
|
||||
this.saveToRegBtn.Location = new System.Drawing.Point(172, 45);
|
||||
this.saveToRegBtn.Name = "saveToRegBtn";
|
||||
this.saveToRegBtn.Size = new System.Drawing.Size(101, 23);
|
||||
this.saveToRegBtn.TabIndex = 13;
|
||||
this.saveToRegBtn.Text = "Save To Reg";
|
||||
this.saveToRegBtn.UseVisualStyleBackColor = true;
|
||||
this.saveToRegBtn.Click += new System.EventHandler(this.saveToRegBtn_Click);
|
||||
//
|
||||
// buttonVerify
|
||||
//
|
||||
this.buttonVerify.Location = new System.Drawing.Point(550, 45);
|
||||
this.buttonVerify.Name = "buttonVerify";
|
||||
this.buttonVerify.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonVerify.TabIndex = 12;
|
||||
this.buttonVerify.Text = "Verify";
|
||||
this.buttonVerify.UseVisualStyleBackColor = true;
|
||||
this.buttonVerify.Click += new System.EventHandler(this.buttonVerify_Click);
|
||||
//
|
||||
// buttonExportSignature
|
||||
//
|
||||
this.buttonExportSignature.Location = new System.Drawing.Point(91, 45);
|
||||
this.buttonExportSignature.Name = "buttonExportSignature";
|
||||
this.buttonExportSignature.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonExportSignature.TabIndex = 11;
|
||||
this.buttonExportSignature.Text = "Export";
|
||||
this.buttonExportSignature.UseVisualStyleBackColor = true;
|
||||
this.buttonExportSignature.Click += new System.EventHandler(this.buttonExportSignature_Click);
|
||||
//
|
||||
// readRegBtn
|
||||
//
|
||||
this.readRegBtn.Location = new System.Drawing.Point(279, 45);
|
||||
this.readRegBtn.Name = "readRegBtn";
|
||||
this.readRegBtn.Size = new System.Drawing.Size(132, 23);
|
||||
this.readRegBtn.TabIndex = 14;
|
||||
this.readRegBtn.Text = "Read from Registry";
|
||||
this.readRegBtn.UseVisualStyleBackColor = true;
|
||||
this.readRegBtn.Click += new System.EventHandler(this.readRegBtn_Click);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(659, 351);
|
||||
this.Controls.Add(this.groupBox4);
|
||||
this.Controls.Add(this.groupBox3);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Name = "MainForm";
|
||||
this.Text = "Liccensing";
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
this.groupBox3.ResumeLayout(false);
|
||||
this.groupBox3.PerformLayout();
|
||||
this.groupBox4.ResumeLayout(false);
|
||||
this.groupBox4.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox textBoxPublicKey;
|
||||
private System.Windows.Forms.Button buttonGenerateKey;
|
||||
private System.Windows.Forms.Button buttonLoadKey;
|
||||
private System.Windows.Forms.Button buttonSaveKey;
|
||||
private System.Windows.Forms.TextBox textBoxPrivateKey;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.TextBox textBoxAccountName;
|
||||
private System.Windows.Forms.TextBox textBoxAccountNumber;
|
||||
private System.Windows.Forms.Button buttonSign;
|
||||
private System.Windows.Forms.TextBox textBoxSignature;
|
||||
private System.Windows.Forms.Button buttonGetPublicKey;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.GroupBox groupBox2;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Button buttonExportPublicKey;
|
||||
private System.Windows.Forms.GroupBox groupBox4;
|
||||
private System.Windows.Forms.Button buttonExportSignature;
|
||||
private System.Windows.Forms.Button buttonVerify;
|
||||
private System.Windows.Forms.Button clipboardCopyBtn;
|
||||
private System.Windows.Forms.Button saveToRegBtn;
|
||||
private System.Windows.Forms.Button readRegBtn;
|
||||
}
|
||||
}
|
||||
@@ -1,352 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using MTApiService;
|
||||
|
||||
namespace Licensing
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
private bool mIsSaved = true;
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void buttonGenerateKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
textBoxPrivateKey.Text = DigitalSignatureHelper.GeneratePrivateKey();
|
||||
|
||||
mIsSaved = false;
|
||||
}
|
||||
|
||||
private void buttonGetPublicKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
string privateKey = textBoxPrivateKey.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(privateKey) == false)
|
||||
{
|
||||
textBoxPublicKey.Text = DigitalSignatureHelper.GetPublicKey(privateKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Private Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonSaveKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
string privateKey = textBoxPrivateKey.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(privateKey) == false)
|
||||
{
|
||||
SaveFileDialog dlg = new SaveFileDialog();
|
||||
|
||||
dlg.Filter = "MetaTraderApi Key Files (*.mtk)|*.mtk";
|
||||
dlg.Title = "Save MetaTraderApi Key File";
|
||||
|
||||
if (dlg.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TextWriter file = new StreamWriter(dlg.FileName, true))
|
||||
{
|
||||
file.WriteLine(privateKey);
|
||||
}
|
||||
|
||||
mIsSaved = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMsg = string.Format("Saving failed!\n{0}", ex.Message);
|
||||
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Private Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonLoadKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (mIsSaved == false)
|
||||
{
|
||||
if (MessageBox.Show("Private Key is not saved. Continue?", "Private Key", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
|
||||
return;
|
||||
}
|
||||
|
||||
OpenFileDialog dlg = new OpenFileDialog();
|
||||
|
||||
dlg.Filter = "MetaTraderApi Key Files (*.mtk)|*.mtk";
|
||||
dlg.Title = "Load MetaTraderApi Key File";
|
||||
|
||||
if (dlg.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
textBoxPrivateKey.Text = string.Empty;
|
||||
textBoxPublicKey.Text = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
using (TextReader file = new StreamReader(dlg.FileName))
|
||||
{
|
||||
textBoxPrivateKey.Text = file.ReadLine();
|
||||
}
|
||||
|
||||
mIsSaved = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMsg = string.Format("Saving failed!\n{0}", ex.Message);
|
||||
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonSign_Click(object sender, EventArgs e)
|
||||
{
|
||||
string privateKey = textBoxPrivateKey.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(privateKey) == false)
|
||||
{
|
||||
string accountName = textBoxAccountName.Text;
|
||||
string accountNumber = textBoxAccountNumber.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(accountName) == false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(accountNumber) == false)
|
||||
{
|
||||
string inputData = accountName + accountNumber;
|
||||
|
||||
textBoxSignature.Text = DigitalSignatureHelper.CreateSignature(inputData, privateKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Private Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonExportPublicKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
string publicKey = textBoxPublicKey.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(publicKey) == false)
|
||||
{
|
||||
SaveFileDialog dlg = new SaveFileDialog();
|
||||
|
||||
dlg.Filter = "MetaTraderApi Key Files (*.mtk)|*.mtk";
|
||||
dlg.Title = "Export MetaTraderApi Key File";
|
||||
|
||||
if (dlg.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TextWriter file = new StreamWriter(dlg.FileName, true))
|
||||
{
|
||||
file.WriteLine(publicKey);
|
||||
}
|
||||
|
||||
mIsSaved = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMsg = string.Format("Export failed!\n{0}", ex.Message);
|
||||
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Public Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonExportSignature_Click(object sender, EventArgs e)
|
||||
{
|
||||
string signature = textBoxSignature.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(signature) == false)
|
||||
{
|
||||
SaveFileDialog dlg = new SaveFileDialog();
|
||||
|
||||
dlg.Filter = "MetaTraderApi Key (*.mta)|*.mta";
|
||||
dlg.Title = "Export MetaTraderApi Key";
|
||||
|
||||
if (dlg.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TextWriter file = new StreamWriter(dlg.FileName))
|
||||
{
|
||||
file.WriteLine(signature);
|
||||
}
|
||||
|
||||
mIsSaved = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMsg = string.Format("Export failed!\n{0}", ex.Message);
|
||||
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Signature is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonVerify_Click(object sender, EventArgs e)
|
||||
{
|
||||
string publicKey = textBoxPublicKey.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(publicKey) == false)
|
||||
{
|
||||
string signature = textBoxSignature.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(signature) == false)
|
||||
{
|
||||
string accountName = textBoxAccountName.Text;
|
||||
string accountNumber = textBoxAccountNumber.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(accountName) == false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(accountNumber) == false)
|
||||
{
|
||||
string inputData = accountName + accountNumber;
|
||||
var verifyResult = false;
|
||||
try
|
||||
{
|
||||
verifyResult = DigitalSignatureHelper.VerifySignature(inputData, signature, publicKey);
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "Verify", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
verifyResult = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string errorMsg = string.Format("Verify process failed!\n{0}", ex.Message);
|
||||
MessageBox.Show(errorMsg, "Verify", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
verifyResult = false;
|
||||
}
|
||||
|
||||
if (verifyResult == true)
|
||||
{
|
||||
MessageBox.Show("Signature good", "Verify", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Signature is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Public Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void clipboardCopyBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Clipboard.SetText(textBoxPublicKey.Text);
|
||||
}
|
||||
|
||||
private void saveToRegBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
string signature = textBoxSignature.Text;
|
||||
string accountName = textBoxAccountName.Text;
|
||||
string accountNumber = textBoxAccountNumber.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(signature))
|
||||
{
|
||||
MessageBox.Show("Signature is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(accountName))
|
||||
{
|
||||
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(accountNumber))
|
||||
{
|
||||
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
SaveFileDialog dlg = new SaveFileDialog();
|
||||
|
||||
dlg.Filter = "Registry files (*.reg)|*.reg";
|
||||
dlg.Title = "Registry files";
|
||||
|
||||
if (dlg.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
string key = MtRegistryManager.SaveSignatureKey(accountName, accountNumber, signature);
|
||||
|
||||
bool exported = MtRegistryManager.ExportKey(key, dlg.FileName);
|
||||
|
||||
if (exported)
|
||||
{
|
||||
MessageBox.Show("Export successed.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Export failed!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readRegBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
string accountName = textBoxAccountName.Text;
|
||||
string accountNumber = textBoxAccountNumber.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(accountName))
|
||||
{
|
||||
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(accountNumber))
|
||||
{
|
||||
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
string signature = MtRegistryManager.ReadSignatureKey(accountName, accountNumber);
|
||||
textBoxSignature.Text = signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Licensing
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Licensing")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("DW")]
|
||||
[assembly: AssemblyProduct("Licensing")]
|
||||
[assembly: AssemblyCopyright("Copyright © DW 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("2c3df81b-2285-44ff-a152-0111e25d9b1a")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// 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.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -31,22 +31,6 @@ public struct CMqlRates
|
||||
int spread; // Spread
|
||||
__int64 real_volume; // Trade volume
|
||||
};
|
||||
|
||||
public struct CMqlTick
|
||||
{
|
||||
__int64 time; // Time of the last prices update
|
||||
double bid; // Current Bid price
|
||||
double ask; // Current Ask price
|
||||
double last; // Price of the last deal (Last)
|
||||
unsigned __int64 volume; // Volume for the current Last price
|
||||
};
|
||||
|
||||
public struct CMqlBookInfo
|
||||
{
|
||||
int type; // Order type from ENUM_BOOK_TYPE enumeration
|
||||
double price; // Price
|
||||
__int64 volume; // Volume
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void convertSystemString(wchar_t* dest, String^ src)
|
||||
@@ -224,35 +208,14 @@ _DLLAPI int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates value
|
||||
}, err, 0);
|
||||
}
|
||||
|
||||
_DLLAPI int _stdcall sendMqlTickResponse(int expertHandle, CMqlTick* response, wchar_t* err)
|
||||
_DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* message, wchar_t* err)
|
||||
{
|
||||
return Execute<int>([&expertHandle, response]() {
|
||||
MtMqlTick^ mtResponse = gcnew MtMqlTick();
|
||||
mtResponse->time = response->time;
|
||||
mtResponse->bid = response->bid;
|
||||
mtResponse->ask = response->ask;
|
||||
mtResponse->last = response->last;
|
||||
mtResponse->volume = response->volume;
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
|
||||
return 1;
|
||||
}, err, 0);
|
||||
}
|
||||
|
||||
_DLLAPI int _stdcall sendMqlBookInfoArrayResponse(int expertHandle, CMqlBookInfo values[], int size, wchar_t* err)
|
||||
{
|
||||
return Execute<int>([&expertHandle, values, &size]() {
|
||||
array<MtMqlBookInfo^>^ list = gcnew array<MtMqlBookInfo^>(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
MtMqlBookInfo^ info = gcnew MtMqlBookInfo();
|
||||
info->type = values[i].type;
|
||||
info->price = values[i].price;
|
||||
info->volume = values[i].volume;
|
||||
list[i] = info;
|
||||
}
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
|
||||
return 1;
|
||||
}, err, 0);
|
||||
return Execute<bool>([&expertHandle, &code, message]() {
|
||||
MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
|
||||
res->ErrorCode = code;
|
||||
MtAdapter::GetInstance()->SendResponse(expertHandle, res);
|
||||
return true;
|
||||
}, err, false);
|
||||
}
|
||||
|
||||
//----------- get values -------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -23,6 +23,7 @@
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<RootNamespace>MT5Connector</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@@ -30,28 +31,28 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -52,24 +52,45 @@ namespace MTApiService
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum LogLevel
|
||||
{
|
||||
Off,
|
||||
Debug,
|
||||
Info
|
||||
}
|
||||
|
||||
public class LogConfigurator
|
||||
{
|
||||
private const string LogFileNameExtension = "txt";
|
||||
private const string LogFileNameExtension = "log";
|
||||
|
||||
public static void Setup(string profileName)
|
||||
{
|
||||
#if (DEBUG)
|
||||
const LogLevel logLevel = LogLevel.Debug;
|
||||
#else
|
||||
const LogLevel logLevel = LogLevel.Info;
|
||||
#endif
|
||||
Setup(profileName, logLevel);
|
||||
}
|
||||
|
||||
public static void Setup(string profileName, LogLevel logLevel)
|
||||
{
|
||||
if (string.IsNullOrEmpty(profileName))
|
||||
throw new ArgumentNullException();
|
||||
|
||||
var hierarchy = (Hierarchy) LogManager.GetRepository();
|
||||
|
||||
//check if logger is already configurated to avoid creation many empty logs files
|
||||
if (hierarchy.Configured)
|
||||
return;
|
||||
|
||||
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 filename = $"{DateTime.Now:yyyy-dd-M--HH-mm-ss}-{Process.GetCurrentProcess().Id}.{LogFileNameExtension}";
|
||||
|
||||
var roller = new RollingFileAppender
|
||||
{
|
||||
@@ -84,12 +105,7 @@ namespace MTApiService
|
||||
};
|
||||
roller.ActivateOptions();
|
||||
hierarchy.Root.AddAppender(roller);
|
||||
|
||||
#if (DEBUG)
|
||||
hierarchy.Root.Level = Level.Debug;
|
||||
#else
|
||||
hierarchy.Root.Level = Level.Info;
|
||||
#endif
|
||||
hierarchy.Root.Level = ConvertLogLevel(logLevel);
|
||||
hierarchy.Configured = true;
|
||||
}
|
||||
|
||||
@@ -100,5 +116,17 @@ namespace MTApiService
|
||||
|
||||
return new MtLog(type);
|
||||
}
|
||||
|
||||
private static Level ConvertLogLevel(LogLevel logLevel)
|
||||
{
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogLevel.Debug: return Level.Debug;
|
||||
case LogLevel.Info: return Level.Info;
|
||||
case LogLevel.Off: return Level.Off;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +72,7 @@
|
||||
<Compile Include="MtClient.cs" />
|
||||
<Compile Include="MtCommandTask.cs" />
|
||||
<Compile Include="MtEvent.cs" />
|
||||
<Compile Include="MtMqlBookInfo.cs" />
|
||||
<Compile Include="MtMqlRates.cs" />
|
||||
<Compile Include="MtMqlTick.cs" />
|
||||
<Compile Include="MtMqlTradeRequest.cs" />
|
||||
<Compile Include="MtRegistryManager.cs" />
|
||||
<Compile Include="MtConnectionProfile.cs" />
|
||||
|
||||
+41
-12
@@ -4,35 +4,51 @@ namespace MTApiService
|
||||
{
|
||||
public class Mt5Expert : MtExpert
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Mt5Expert));
|
||||
private const int StopExpertInterval = 2000; // 2 sec for testing mode
|
||||
private readonly System.Timers.Timer _stopTimer = new System.Timers.Timer();
|
||||
private System.Timers.Timer _stopTimer;
|
||||
|
||||
|
||||
public Mt5Expert(int handle, string symbol, double bid, double ask, IMetaTraderHandler mtHandler, bool isTestMode) :
|
||||
base(handle, symbol, bid, ask, mtHandler)
|
||||
{
|
||||
IsTestMode = isTestMode;
|
||||
_stopTimer.Interval = StopExpertInterval;
|
||||
_stopTimer.Elapsed += _stopTimer_Elapsed;
|
||||
}
|
||||
|
||||
public bool IsTestMode { get; }
|
||||
|
||||
public override void UpdateQuote(MtQuote quote)
|
||||
public override int GetCommandType()
|
||||
{
|
||||
Log.Debug("UpdateQuote: begin.");
|
||||
|
||||
base.UpdateQuote(quote);
|
||||
Log.Debug("GetCommandType: called.");
|
||||
|
||||
if (IsTestMode)
|
||||
{
|
||||
//reset timer
|
||||
_stopTimer.Stop();
|
||||
_stopTimer.Start();
|
||||
ResetTestModeTimer();
|
||||
}
|
||||
|
||||
Log.Debug("UpdateQuote: end.");
|
||||
return base.GetCommandType();
|
||||
}
|
||||
|
||||
public override void SendEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
|
||||
|
||||
if (IsTestMode)
|
||||
{
|
||||
if (_stopTimer == null)
|
||||
{
|
||||
_stopTimer = new System.Timers.Timer
|
||||
{
|
||||
Interval = StopExpertInterval,
|
||||
AutoReset = false
|
||||
};
|
||||
_stopTimer.Elapsed += _stopTimer_Elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
base.SendEvent(mtEvent);
|
||||
|
||||
Log.Debug("SendEvent: end.");
|
||||
}
|
||||
|
||||
private void _stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
@@ -42,7 +58,20 @@ namespace MTApiService
|
||||
Log.Warn("Mt5Expert has received new tick during 2 sec in testing mode. The possible cause: user has stopped the tester manually in MetaTrader 5.");
|
||||
Deinit();
|
||||
|
||||
_stopTimer.Elapsed -= _stopTimer_Elapsed;
|
||||
_stopTimer = null;
|
||||
|
||||
Log.Debug("_stopTimer_Elapsed: end.");
|
||||
}
|
||||
|
||||
private void ResetTestModeTimer()
|
||||
{
|
||||
if (_stopTimer == null)
|
||||
return;
|
||||
|
||||
//reset timer
|
||||
_stopTimer.Stop();
|
||||
_stopTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ namespace MTApiService
|
||||
}
|
||||
|
||||
server.AddExpert(expert);
|
||||
expert.Deinited += ExpertOnDeinited;
|
||||
|
||||
Log.Info("AddExpert: end");
|
||||
}
|
||||
@@ -81,7 +82,6 @@ namespace MTApiService
|
||||
if (_experts.ContainsKey(expertHandle))
|
||||
{
|
||||
expert = _experts[expertHandle];
|
||||
_experts.Remove(expertHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +270,31 @@ namespace MTApiService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ExpertOnDeinited(object sender, EventArgs eventArgs)
|
||||
{
|
||||
Log.Debug("ExpertOnDeinited: begin.");
|
||||
|
||||
var expert = sender as MtExpert;
|
||||
if (expert == null)
|
||||
{
|
||||
Log.Warn("expert_Deinited: end. Expert is not defined.");
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_experts)
|
||||
{
|
||||
if (_experts.ContainsKey(expert.Handle))
|
||||
{
|
||||
_experts.Remove(expert.Handle);
|
||||
}
|
||||
}
|
||||
|
||||
Log.DebugFormat("ExpertOnDeinited: removed expert {0}", expert.Handle);
|
||||
|
||||
Log.Debug("ExpertOnDeinited: end.");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace MTApiService
|
||||
Log.Debug("SendResponse: end.");
|
||||
}
|
||||
|
||||
public int GetCommandType()
|
||||
public virtual int GetCommandType()
|
||||
{
|
||||
Log.Debug("GetCommandType: called.");
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace MTApiService
|
||||
return command.NamedParams.ContainsKey(name);
|
||||
}
|
||||
|
||||
public void SendEvent(MtEvent mtEvent)
|
||||
public virtual void SendEvent(MtEvent mtEvent)
|
||||
{
|
||||
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace MTApiService
|
||||
Log.Debug("SendEvent: end.");
|
||||
}
|
||||
|
||||
public virtual void UpdateQuote(MtQuote quote)
|
||||
public void UpdateQuote(MtQuote quote)
|
||||
{
|
||||
Log.DebugFormat("UpdateQuote: begin. quote = {0}", quote);
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
[DataContract]
|
||||
public class MtMqlBookInfo
|
||||
{
|
||||
[DataMember]
|
||||
public int type { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public double price { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public long volume { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MTApiService
|
||||
{
|
||||
[DataContract]
|
||||
public class MtMqlTick
|
||||
{
|
||||
[DataMember]
|
||||
public long time { get; set; } // Time of the last prices update
|
||||
|
||||
[DataMember]
|
||||
public double bid { get; set; } // Current Bid price
|
||||
|
||||
[DataMember]
|
||||
public double ask { get; set; } // Current Ask price
|
||||
|
||||
[DataMember]
|
||||
public double last { get; set; } // Price of the last deal (Last)
|
||||
|
||||
[DataMember]
|
||||
public ulong volume { get; set; } // Volume for the current Last price
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,8 @@ namespace MTApiService
|
||||
typeof(MtResponseString), typeof(MtResponseBool),
|
||||
typeof(MtResponseLong), typeof(MtResponseULong),
|
||||
typeof(MtResponseDoubleArray), typeof(MtResponseIntArray),
|
||||
typeof(MtResponseLongArray), typeof(MtResponseMqlTick),
|
||||
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray),
|
||||
typeof(MtResponseMqlBookInfoArray)};
|
||||
typeof(MtResponseLongArray),
|
||||
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray)};
|
||||
}
|
||||
|
||||
public abstract object GetValue();
|
||||
@@ -255,43 +254,4 @@ namespace MTApiService
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class MtResponseMqlTick : MtResponse
|
||||
{
|
||||
public MtResponseMqlTick(MtMqlTick value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public MtMqlTick Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class MtResponseMqlBookInfoArray : MtResponse
|
||||
{
|
||||
public MtResponseMqlBookInfoArray(MtMqlBookInfo[] value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public MtMqlBookInfo[] Value { get; private set; }
|
||||
|
||||
public override object GetValue() { return Value; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.29.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.29.0")]
|
||||
[assembly: AssemblyVersion("1.0.33.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.33.0")]
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -24,6 +24,7 @@
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<RootNamespace>MTConnector</RootNamespace>
|
||||
<ProjectName>MTConnector</ProjectName>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@@ -31,28 +32,28 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -10,8 +10,13 @@ namespace MtApi.Monitors
|
||||
Opened = opened;
|
||||
Closed = closed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all newly opened orders since the last time the monitor checked the open orders.
|
||||
/// </summary>
|
||||
public List<MtOrder> Opened { get; private set; }
|
||||
/// <summary>
|
||||
/// Contains all newly closed orders since the last time the monitor checked the open orders.
|
||||
/// </summary>
|
||||
public List<MtOrder> Closed { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using MtApi.Monitors.Triggers;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public abstract class MtMonitorBase
|
||||
{
|
||||
#region Fields
|
||||
private volatile bool _isStarted = false;
|
||||
private bool _syncTrigger;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// ApiClient
|
||||
/// </summary>
|
||||
protected MtApiClient ApiClient { get; }
|
||||
/// <summary>
|
||||
/// Returns true if the <see cref="ApiClient"/> is connected.
|
||||
/// </summary>
|
||||
public bool IsMtConnected => ApiClient.ConnectionState == MtConnectionState.Connected;
|
||||
/// <summary>
|
||||
/// Returns the trigger which will be used to raise the monitoring call.
|
||||
/// </summary>
|
||||
public IMonitorTrigger MonitorTrigger { get; }
|
||||
/// <summary>
|
||||
/// Returns true if the Monitor is started.
|
||||
/// </summary>
|
||||
public bool IsStarted { get => _isStarted; }
|
||||
/// <summary>
|
||||
/// If true, the <see cref="MonitorTrigger"/> will be stopped or started automatically when <see cref="Start"/> or <see cref="Stop"/> will be called.
|
||||
/// <para>CAUTION: If you use the MonitorTrigger for different Monitors, this will stop all monitors if you call stop and <see cref="SyncTrigger"/> is <c>true</c>.</para>
|
||||
/// </summary>
|
||||
public bool SyncTrigger { get => _syncTrigger; set => _syncTrigger = value; }
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
/// <summary>
|
||||
/// Default constructor for Monitors
|
||||
/// </summary>
|
||||
/// <param name="apiClient">The apiClient which will be used to work with.</param>
|
||||
/// <param name="monitorTrigger">The trigger which lead this Monitor to do his work.</param>
|
||||
/// <param name="syncTrigger">See property <see cref="SyncTrigger"/>.</param>
|
||||
public MtMonitorBase(MtApiClient apiClient, IMonitorTrigger monitorTrigger, bool syncTrigger = false)
|
||||
{
|
||||
ApiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
|
||||
MonitorTrigger = monitorTrigger ?? throw new ArgumentNullException(nameof(monitorTrigger));
|
||||
SyncTrigger = syncTrigger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Let the monitor listen to the <see cref="MonitorTrigger"/>.
|
||||
/// </summary>
|
||||
public virtual void Start()
|
||||
{
|
||||
if (!_isStarted)
|
||||
{
|
||||
ApiClient.ConnectionStateChanged += ApiClientConnectionStateChanged;
|
||||
MonitorTrigger.Raised += MonitorTriggerRaised;
|
||||
_isStarted = true;
|
||||
OnStart();
|
||||
if (SyncTrigger)
|
||||
MonitorTrigger.Start();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Let the monitor stop listening to the <see cref="MonitorTrigger"/>.
|
||||
/// </summary>
|
||||
public virtual void Stop()
|
||||
{
|
||||
if (_isStarted)
|
||||
{
|
||||
MonitorTrigger.Raised -= MonitorTriggerRaised;
|
||||
ApiClient.ConnectionStateChanged -= ApiClientConnectionStateChanged;
|
||||
_isStarted = false;
|
||||
OnStop();
|
||||
if (SyncTrigger)
|
||||
MonitorTrigger.Stop();
|
||||
}
|
||||
}
|
||||
private void MonitorTriggerRaised(object sender, EventArgs e) => OnTriggerRaised();
|
||||
private void ApiClientConnectionStateChanged(object sender, MtConnectionEventArgs e)
|
||||
{
|
||||
if (e.Status == MtConnectionState.Connected)
|
||||
OnMtConnected();
|
||||
else if (e.Status == MtConnectionState.Failed || e.Status == MtConnectionState.Disconnected)
|
||||
OnMtDisconnected();
|
||||
}
|
||||
/// <summary>
|
||||
/// Will be called when <see cref="Start"/> will be called.
|
||||
/// </summary>
|
||||
protected virtual void OnStart() { }
|
||||
/// <summary>
|
||||
/// Will be called when <see cref="Stop"/> will be called.
|
||||
/// </summary>
|
||||
protected virtual void OnStop() { }
|
||||
/// <summary>
|
||||
/// Will be called when the <see cref="ApiClient"/> is successfully connected.
|
||||
/// </summary>
|
||||
protected virtual void OnMtConnected() { }
|
||||
/// <summary>
|
||||
/// Will be called when <see cref="ApiClient"/> is disconnected.
|
||||
/// </summary>
|
||||
protected virtual void OnMtDisconnected() { }
|
||||
/// <summary>
|
||||
/// Will be called when the <see cref="MonitorTrigger"/> raised.
|
||||
/// </summary>
|
||||
protected abstract void OnTriggerRaised();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public class ModifiedOrdersEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of all modified orders
|
||||
/// </summary>
|
||||
public List<MtModifiedOrder> ModifiedOrders { get; }
|
||||
public ModifiedOrdersEventArgs(List<MtModifiedOrder> modifiedOrders)
|
||||
{
|
||||
ModifiedOrders = modifiedOrders;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using MtApi.Monitors.Triggers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public class ModifiedOrdersMonitor : MtMonitorBase
|
||||
{
|
||||
#region Fields
|
||||
private List<MtOrder> _lastOrders = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Define on which types of modification this monitor should raise <see cref="OrdersModified"/>
|
||||
/// </summary>
|
||||
public OrderModifiedTypes OrderModifiedTypes { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Will be raised when this monitor detects changes on open orders
|
||||
/// </summary>
|
||||
public event EventHandler<ModifiedOrdersEventArgs> OrdersModified;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
public ModifiedOrdersMonitor(MtApiClient apiClient, IMonitorTrigger monitorTrigger, OrderModifiedTypes orderModifiedTypes = OrderModifiedTypes.All, bool syncTrigger = false)
|
||||
: base(apiClient, monitorTrigger, syncTrigger)
|
||||
{
|
||||
_lastOrders = GetOrders();
|
||||
OrderModifiedTypes = orderModifiedTypes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Requests all current open orders
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<MtOrder> GetOrders() => IsMtConnected ? ApiClient.GetOrders(OrderSelectSource.MODE_TRADES) : null;
|
||||
protected override void OnTriggerRaised()
|
||||
{
|
||||
if(_lastOrders == null)
|
||||
{
|
||||
_lastOrders = GetOrders();
|
||||
return;
|
||||
}
|
||||
List<MtOrder> currentOrders = GetOrders();
|
||||
OrderModifiedTypes omt = OrderModifiedTypes;
|
||||
var mtModifiedOrders = currentOrders
|
||||
.Select(co => new MtModifiedOrder(_lastOrders.FirstOrDefault(x => x.Ticket == co.Ticket), co))
|
||||
.ToList();
|
||||
List<MtModifiedOrder> modifiedOrders = new List<MtModifiedOrder>();
|
||||
modifiedOrders.AddRange(GetMtModifiedOrdersWithModType(mtModifiedOrders, omt, OrderModifiedTypes.TakeProfit)); //If the takeprofit were changed between both calls
|
||||
modifiedOrders.AddRange(GetMtModifiedOrdersWithModType(mtModifiedOrders, omt, OrderModifiedTypes.StopLoss)); //If the stoploss were changed between both calls
|
||||
modifiedOrders.AddRange(GetMtModifiedOrdersWithModType(mtModifiedOrders, omt, OrderModifiedTypes.Operation)); //If an order changed from limit / stop order to an open order
|
||||
if (modifiedOrders.Count > 0)
|
||||
OrdersModified?.Invoke(this, new ModifiedOrdersEventArgs(modifiedOrders));
|
||||
_lastOrders = currentOrders;
|
||||
}
|
||||
private static IEnumerable<MtModifiedOrder> GetMtModifiedOrdersWithModType(IEnumerable<MtModifiedOrder> orders, OrderModifiedTypes globalSearchFlag, OrderModifiedTypes modifiedType)
|
||||
=> globalSearchFlag.HasFlag(modifiedType) ? orders.Where(o => o.ModifyType.HasFlag(modifiedType)) : new List<MtModifiedOrder>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public class MtModifiedOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// The order in its old state (before the changes)
|
||||
/// </summary>
|
||||
public MtOrder OldOrder { get; }
|
||||
/// <summary>
|
||||
/// The order in its new state (after the changes)
|
||||
/// </summary>
|
||||
public MtOrder NewOrder { get; }
|
||||
/// <summary>
|
||||
/// The changes found by this instance
|
||||
/// </summary>
|
||||
public OrderModifiedTypes ModifyType { get; private set; }
|
||||
/// <summary>
|
||||
/// Initializes an instance and compare the order in its old and new state
|
||||
/// </summary>
|
||||
/// <param name="oldOrder">The order in its old state (before the changes)</param>
|
||||
/// <param name="newOrder">The order in its new state (after the changes)</param>
|
||||
public MtModifiedOrder(MtOrder oldOrder, MtOrder newOrder)
|
||||
{
|
||||
if (oldOrder != null && newOrder != null && oldOrder.Ticket != newOrder.Ticket)
|
||||
throw new ArgumentException(nameof(oldOrder) + " and " + nameof(newOrder) + " need to have the same ticket id");
|
||||
OldOrder = oldOrder;
|
||||
NewOrder = newOrder;
|
||||
ModifyType = OrderModifiedTypes.None;
|
||||
Compare();
|
||||
}
|
||||
private void Compare()
|
||||
{
|
||||
if(NewOrder != null && OldOrder != null)
|
||||
{
|
||||
if (OldOrder.StopLoss != NewOrder.StopLoss)
|
||||
ModifyType |= OrderModifiedTypes.StopLoss;
|
||||
if (OldOrder.TakeProfit != NewOrder.TakeProfit)
|
||||
ModifyType |= OrderModifiedTypes.TakeProfit;
|
||||
if (OldOrder.Operation != NewOrder.Operation)
|
||||
ModifyType |= OrderModifiedTypes.Operation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
[Flags]
|
||||
public enum OrderModifiedTypes
|
||||
{
|
||||
None = 0x0,
|
||||
TakeProfit = 1 << 0,
|
||||
StopLoss = 1 << 1,
|
||||
Operation = 1 << 2,
|
||||
All = 7
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,18 @@
|
||||
|
||||
using MtApi.Monitors.Triggers;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public class TimeframeTradeMonitor : TradeMonitor
|
||||
{
|
||||
#region Fields
|
||||
private volatile bool _isStarted;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
public TimeframeTradeMonitor(MtApiClient apiClient)
|
||||
: base(apiClient)
|
||||
/// <summary>
|
||||
/// Constructor for initializing a new instance with a trigger instance of <see cref="NewBarTrigger"/>.
|
||||
/// <para>SyncTrigger is set to true by default</para>
|
||||
/// </summary>
|
||||
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
|
||||
public TimeframeTradeMonitor(MtApiClient apiClient)
|
||||
: base(apiClient, new NewBarTrigger(apiClient))
|
||||
{
|
||||
apiClient.OnLastTimeBar += ApiClient_OnLastTimeBar;
|
||||
SyncTrigger = true; //Sync-Trigger set to true, to have the same behavior as before
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
//
|
||||
// Summary:
|
||||
// Gets a value indicating whether the TimeframeTradeMonitor should raise checking orders
|
||||
//
|
||||
// Returns:
|
||||
// true if PositionMonitor should check orders
|
||||
// otherwise, false.
|
||||
public override bool IsStarted => _isStarted;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
protected override void OnMtConnected() {}
|
||||
|
||||
protected override void OnMtDisconnected() {}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
_isStarted = true;
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
{
|
||||
_isStarted = false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void ApiClient_OnLastTimeBar(object sender, TimeBarArgs e)
|
||||
{
|
||||
if (_isStarted)
|
||||
{
|
||||
Check();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,90 +1,47 @@
|
||||
using System.Timers;
|
||||
using System;
|
||||
using MtApi.Monitors.Triggers;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public class TimerTradeMonitor : TradeMonitor
|
||||
{
|
||||
#region Fields
|
||||
private readonly Timer _timer = new Timer();
|
||||
private readonly TimeElapsedTrigger _timeElapsedTrigger;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
public TimerTradeMonitor(MtApiClient apiClient)
|
||||
: base(apiClient)
|
||||
{
|
||||
_timer.Interval = 10000; //default interval 10 sec
|
||||
_timer.Elapsed += _timer_Elapsed;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
//
|
||||
// Summary:
|
||||
// Gets or sets the interval, expressed in milliseconds, at which to check orders
|
||||
//
|
||||
// Returns:
|
||||
// The time, in milliseconds, between checking events. The value
|
||||
// must be greater than zero, and less than or equal to System.Int32.MaxValue.
|
||||
// The default is 10000 milliseconds.
|
||||
//
|
||||
// Exceptions:
|
||||
// T:System.ArgumentException:
|
||||
// The interval is less than or equal to zero.-or-The interval is greater than System.Int32.MaxValue,
|
||||
// and the PositionMonitor is currently started.
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Interval for raising the trigger
|
||||
/// </summary>
|
||||
public double Interval
|
||||
{
|
||||
get { return _timer.Interval; }
|
||||
set { _timer.Interval = value; }
|
||||
}
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Gets a value indicating whether the PositionMonitor should raise checking orders
|
||||
//
|
||||
// Returns:
|
||||
// true if TimerTradeMonitor should check orders
|
||||
// otherwise, false.
|
||||
public override bool IsStarted
|
||||
{
|
||||
get { return _timer.Enabled; }
|
||||
get => _timeElapsedTrigger.Interval.TotalMilliseconds;
|
||||
set => _timeElapsedTrigger.Interval = TimeSpan.FromMilliseconds(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
protected override void OnStart()
|
||||
#region ctors
|
||||
/// <summary>
|
||||
/// Constructor for initializing a new instance with a default <see cref="Interval"/> of 10 seconds.
|
||||
/// <para>SyncTrigger is set to true by default</para>
|
||||
/// </summary>
|
||||
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
|
||||
public TimerTradeMonitor(MtApiClient apiClient)
|
||||
: this(apiClient, new TimeElapsedTrigger(TimeSpan.FromSeconds(10)))
|
||||
{
|
||||
if (IsMtConnected)
|
||||
{
|
||||
_timer.Start();
|
||||
}
|
||||
SyncTrigger = true; //Sync-Trigger set to true, to have the same behavior as before
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
/// <summary>
|
||||
/// Constructor for initializing a new instance with a custom instance of <see cref="TimeElapsedTrigger"/>.
|
||||
/// <para>SyncTrigger is set to false by default</para>
|
||||
/// </summary>
|
||||
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
|
||||
/// <param name="timeElapsedTrigger">The custom instance of <see cref="TimeElapsedTrigger"/> which will be used to trigger this instance of <see cref="TradeMonitor"/>.</param>
|
||||
public TimerTradeMonitor(MtApiClient apiClient, TimeElapsedTrigger timeElapsedTrigger)
|
||||
: base(apiClient, timeElapsedTrigger)
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
protected override void OnMtConnected()
|
||||
{
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
protected override void OnMtDisconnected()
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
_timer.Elapsed -= _timer_Elapsed; //unregister from events to prevent rise condition during work with orders
|
||||
|
||||
Check();
|
||||
|
||||
_timer.Elapsed += _timer_Elapsed; //register again
|
||||
_timeElapsedTrigger = timeElapsedTrigger;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
-116
@@ -1,63 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MtApi.Monitors.Triggers;
|
||||
|
||||
namespace MtApi.Monitors
|
||||
{
|
||||
public abstract class TradeMonitor
|
||||
public class TradeMonitor : MtMonitorBase
|
||||
{
|
||||
#region Fields
|
||||
private readonly MtApiClient _apiClient;
|
||||
private List<MtOrder> _prevOrders;
|
||||
private readonly object _locker = new object();
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
protected TradeMonitor(MtApiClient apiClient)
|
||||
{
|
||||
if (apiClient == null)
|
||||
throw new ArgumentNullException(nameof(apiClient));
|
||||
|
||||
_apiClient = apiClient;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
//
|
||||
// Summary:
|
||||
// Gets a value indicating whether the TradeMonitor should raise checking orders
|
||||
//
|
||||
// Returns:
|
||||
// true if TradeMonitor should check orders
|
||||
// otherwise, false.
|
||||
public abstract bool IsStarted { get; }
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Start checking orders.
|
||||
//
|
||||
public void Start()
|
||||
{
|
||||
_apiClient.ConnectionStateChanged += _apiClient_ConnectionStateChanged;
|
||||
if (IsMtConnected)
|
||||
{
|
||||
InitialCheck();
|
||||
}
|
||||
|
||||
OnStart();
|
||||
}
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Stop checking orders.
|
||||
//
|
||||
public void Stop()
|
||||
{
|
||||
_apiClient.ConnectionStateChanged -= _apiClient_ConnectionStateChanged;
|
||||
OnStop();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
//
|
||||
// Summary:
|
||||
@@ -65,17 +20,34 @@ namespace MtApi.Monitors
|
||||
public event EventHandler<AvailabilityOrdersEventArgs> AvailabilityOrdersChanged;
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
#region ctor
|
||||
/// <summary>
|
||||
/// Constructor for initializing an instance of <see cref="TradeMonitor"/>.
|
||||
/// </summary>
|
||||
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
|
||||
/// <param name="monitorTrigger">The custom instance of <see cref="IMonitorTrigger"/> which will be used to trigger this instance of <see cref="TradeMonitor"/>.</param>
|
||||
public TradeMonitor(MtApiClient apiClient, IMonitorTrigger monitorTrigger) : base(apiClient, monitorTrigger) { }
|
||||
#endregion
|
||||
|
||||
protected abstract void OnStart();
|
||||
protected abstract void OnStop();
|
||||
protected override void OnMtConnected()
|
||||
{
|
||||
InitialCheck();
|
||||
base.OnMtConnected();
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
if (IsMtConnected)
|
||||
InitialCheck();
|
||||
base.OnStart();
|
||||
}
|
||||
|
||||
protected abstract void OnMtConnected();
|
||||
protected abstract void OnMtDisconnected();
|
||||
|
||||
public bool IsMtConnected => _apiClient.ConnectionState == MtConnectionState.Connected;
|
||||
|
||||
protected void Check()
|
||||
protected override void OnTriggerRaised()
|
||||
{
|
||||
if (IsMtConnected)
|
||||
Check();
|
||||
}
|
||||
|
||||
private void Check()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -90,92 +62,48 @@ namespace MtApi.Monitors
|
||||
//TODO: write error to log
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
private void InitialCheck()
|
||||
{
|
||||
lock (_locker)
|
||||
_prevOrders = null;
|
||||
|
||||
#region Private Methods
|
||||
Task.Factory.StartNew(Check);
|
||||
}
|
||||
private void CheckOrders()
|
||||
{
|
||||
var openedOrders = new List<MtOrder>();
|
||||
var closedOrders = new List<MtOrder>();
|
||||
List<MtOrder> prevOrders;
|
||||
|
||||
// get current orders from MetaTrader
|
||||
var tradesOrders = _apiClient.GetOrders(OrderSelectSource.MODE_TRADES);
|
||||
var tradesOrders = ApiClient.GetOrders(OrderSelectSource.MODE_TRADES);
|
||||
|
||||
List<MtOrder> prevOrders;
|
||||
lock(_locker)
|
||||
{
|
||||
lock (_locker)
|
||||
prevOrders = _prevOrders;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
openedOrders.Add(order);
|
||||
}
|
||||
}
|
||||
openedOrders = tradesOrders.Where(to => prevOrders.Find(a => a.Ticket == to.Ticket) == null).ToList();
|
||||
|
||||
//check closed orders
|
||||
var closeOrdersTemp = new List<MtOrder>();
|
||||
foreach (var order in prevOrders)
|
||||
{
|
||||
if (tradesOrders.Find(a => a.Ticket == order.Ticket) == null)
|
||||
{
|
||||
closeOrdersTemp.Add(order);
|
||||
}
|
||||
}
|
||||
var closeOrdersTemp = prevOrders.Where(po => tradesOrders.Find(a => a.Ticket == po.Ticket) == null).ToList();
|
||||
|
||||
if (closeOrdersTemp.Count > 0)
|
||||
{
|
||||
//get closed orders from history with actual values
|
||||
var historyOrders = _apiClient.GetOrders(OrderSelectSource.MODE_HISTORY);
|
||||
foreach (var order in closeOrdersTemp)
|
||||
{
|
||||
var closedOrder = historyOrders.Find(a => a.Ticket == order.Ticket);
|
||||
if (closedOrder != null)
|
||||
{
|
||||
closedOrders.Add(closedOrder);
|
||||
}
|
||||
}
|
||||
var historyOrders = ApiClient.GetOrders(OrderSelectSource.MODE_HISTORY);
|
||||
closedOrders = closeOrdersTemp.Where(cot => historyOrders.Find(a => a.Ticket == cot.Ticket) != null).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
lock(_locker)
|
||||
{
|
||||
lock (_locker)
|
||||
_prevOrders = tradesOrders;
|
||||
}
|
||||
|
||||
if (openedOrders.Count > 0 || closedOrders.Count > 0)
|
||||
{
|
||||
AvailabilityOrdersChanged?.Invoke(this, new AvailabilityOrdersEventArgs(openedOrders, closedOrders));
|
||||
}
|
||||
}
|
||||
|
||||
private void _apiClient_ConnectionStateChanged(object sender, MtConnectionEventArgs e)
|
||||
{
|
||||
if (e.Status == MtConnectionState.Connected)
|
||||
{
|
||||
InitialCheck();
|
||||
OnMtConnected();
|
||||
}
|
||||
else if (e.Status == MtConnectionState.Failed || e.Status == MtConnectionState.Disconnected)
|
||||
{
|
||||
OnMtDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitialCheck()
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
_prevOrders = null;
|
||||
}
|
||||
|
||||
Task.Factory.StartNew(Check);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi.Monitors.Triggers
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for triggers which can be used to trigger a <see cref="MtMonitorBase"/>.
|
||||
/// </summary>
|
||||
public interface IMonitorTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Event will be called if the trigger raised.
|
||||
/// </summary>
|
||||
event EventHandler Raised;
|
||||
/// <summary>
|
||||
/// Returns whether the trigger is started
|
||||
/// </summary>
|
||||
bool IsStarted { get; }
|
||||
/// <summary>
|
||||
/// Stops the trigger and prevents further calls of the <see cref="Raised"/> event.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
/// <summary>
|
||||
/// Starts the trigger.
|
||||
/// </summary>
|
||||
void Start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi.Monitors.Triggers
|
||||
{
|
||||
/// <summary>
|
||||
/// Raises the <see cref="Raised"/> event if a bar is closed and a new one started.
|
||||
/// </summary>
|
||||
public class NewBarTrigger : IMonitorTrigger
|
||||
{
|
||||
#region Fields
|
||||
private volatile bool _isStarted;
|
||||
private readonly MtApiClient _apiClient;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Returns true if the trigger is started, otherwise false
|
||||
/// </summary>
|
||||
public bool IsStarted => _isStarted;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Event will be called if the trigger raised.
|
||||
/// </summary>
|
||||
public event EventHandler Raised;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
public NewBarTrigger(MtApiClient apiClient)
|
||||
{
|
||||
_apiClient = apiClient;
|
||||
_apiClient.OnLastTimeBar += _apiClient_OnLastTimeBar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
/// <summary>
|
||||
/// Starts the trigger
|
||||
/// </summary>
|
||||
public void Start() => SetIsStarted(true);
|
||||
/// <summary>
|
||||
/// Stops the trigger
|
||||
/// </summary>
|
||||
public void Stop() => SetIsStarted(false);
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
private void _apiClient_OnLastTimeBar(object sender, TimeBarArgs e)
|
||||
{
|
||||
if (_isStarted)
|
||||
Raised?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void SetIsStarted(bool value)
|
||||
{
|
||||
if (value != _isStarted)
|
||||
{
|
||||
_isStarted = value;
|
||||
if (value)
|
||||
_apiClient.OnLastTimeBar += _apiClient_OnLastTimeBar;
|
||||
else
|
||||
_apiClient.OnLastTimeBar -= _apiClient_OnLastTimeBar;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Timers;
|
||||
|
||||
namespace MtApi.Monitors.Triggers
|
||||
{
|
||||
public class TimeElapsedTrigger : IMonitorTrigger
|
||||
{
|
||||
#region Fields
|
||||
readonly Timer _timer;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Interval for raising the trigger
|
||||
/// </summary>
|
||||
public TimeSpan Interval
|
||||
{
|
||||
get => TimeSpan.FromMilliseconds(_timer.Interval);
|
||||
set => _timer.Interval = value.TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the trigger is started, otherwise false
|
||||
/// </summary>
|
||||
public bool IsStarted => _timer.Enabled;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the trigger will raise continuosly after elapsed <see cref="Interval"/>, otherwise the trigger will raise only once after elapsed <see cref="Interval"/>.
|
||||
/// </summary>
|
||||
public bool AutoReset { get => _timer.AutoReset; set => _timer.AutoReset = value; }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Returns true if the trigger is started, otherwise false
|
||||
/// </summary>
|
||||
public event EventHandler Raised;
|
||||
#endregion
|
||||
|
||||
#region ctor
|
||||
/// <summary>
|
||||
/// Constructor for initializing TimeElapsedTrigger
|
||||
/// </summary>
|
||||
/// <param name="time">Defines the interval for raising the event.</param>
|
||||
/// <param name="autoReset">If true, the trigger will raise continuosly after elapsed <see cref="Interval"/>, otherwise the trigger will raise only once after elapsed <see cref="Interval"/>.</param>
|
||||
public TimeElapsedTrigger(TimeSpan time, bool autoReset = true)
|
||||
{
|
||||
_timer = new Timer(time.TotalMilliseconds);
|
||||
_timer.Elapsed += _timer_Elapsed;
|
||||
AutoReset = autoReset;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
/// <summary>
|
||||
/// Starts the trigger
|
||||
/// </summary>
|
||||
public void Start() => _timer.Start();
|
||||
/// <summary>
|
||||
/// Stops the trigger
|
||||
/// </summary>
|
||||
public void Stop() => _timer.Stop();
|
||||
#endregion
|
||||
|
||||
#region private methods
|
||||
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
_timer.Elapsed -= _timer_Elapsed;
|
||||
Raised?.Invoke(this, EventArgs.Empty);
|
||||
_timer.Elapsed += _timer_Elapsed;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
## Monitors
|
||||
|
||||
Monitors can be used to monitor different changes on Mt4 structs.
|
||||
|
||||
## MtMonitorBase
|
||||
This is the base class for monitoring extensions. If inherited `MtMonitorBase` needs an instance of `MtApiClient` and `IMonitorTrigger`.
|
||||
|
||||
`SyncTrigger` (which can be set in the constructor or as Property) can be used to define whether the trigger should be started and stopped as well if `Start()` or `Stop()` will be called on an instance of a child class of `MtMonitorBase`.
|
||||
Keep in mind: If an `IMonitorTrigger` will be used for several monitors, `SyncTrigger` set to `true` would cause that all monitors related to this trigger would stop:
|
||||
|
||||
```
|
||||
var fooTrigger = new FooTrigger();
|
||||
var fooMonitor = new FooMonitor(apiClient, fooTrigger, true);
|
||||
var barMonitor = new FooMonitor(apiClient, fooTrigger, false);
|
||||
|
||||
fooTrigger.Start();
|
||||
barMonitor.Start();
|
||||
fooMonitor.Start();
|
||||
|
||||
fooMonitor.Stop(); //Because of SyncTrigger = true in the constructor of FooMonitor, fooTrigger.Stop() were triggered as well. Therefore barMonitor will not get any further triggers.
|
||||
```
|
||||
|
||||
## IMonitorTrigger
|
||||
An `IMonitorTrigger` is for defining when the monitor should check whether his conditions are met for invoking his event.
|
||||
|
||||
There are already two `IMonitorTrigger`s which can be used:
|
||||
### NewBarTrigger
|
||||
Triggers when a new bar starts
|
||||
### TimeElapsedTrigger
|
||||
Triggers when a defined time elapsed
|
||||
|
||||
## Default monitors:
|
||||
There are already two different monitors defined. You can extend them or define new ones by inheriting from `MtMonitorBase`.
|
||||
|
||||
### TradeMonitor
|
||||
Can be used to get updates on new opened trades or closed trades.
|
||||
|
||||
## ModifiedOrdersMonitor
|
||||
Can be used to get updates on modified trades (takeprofit, stoploss, operation).
|
||||
|
||||
`OrderModifiedTypes` defines which modifications should be monitored:
|
||||
|
||||
1. `None` would cause no monitoring. But please use `Start()` and `Stop()` instead.
|
||||
2. `TakeProfit` would cause observing whether the TakeProfit were changed.
|
||||
3. `StopLoss` would cause observing whether the StopLoss were changed.
|
||||
4. `Operation` would cause observing trades which changed from a stop / limit order to an open order.
|
||||
5. `All` would cause observing all above defined.
|
||||
|
||||
Because `OrderModifiedTypes` is defined with the Flag-Attribute, you can combine the above monitoring types with a pipe: `OrderModifiedTypes.TakeProfit | OrderModifiedTypes.StopLoss`.
|
||||
|
||||
### Example
|
||||
```
|
||||
var orderModifyMonitor = new ModifiedOrdersMonitor(
|
||||
_apiClient,
|
||||
new MtApi.Monitors.Triggers.TimeElapsedTrigger(TimeSpan.FromSeconds(1)),
|
||||
OrderModifiedTypes.All,
|
||||
true
|
||||
);
|
||||
orderModifyMonitor.OrdersModified += OrderModifyMonitor_OrdersModified;
|
||||
orderModifyMonitor.Start();
|
||||
|
||||
private void OrderModifyMonitor_OrdersModified(object sender, ModifiedOrdersEventArgs e)
|
||||
{
|
||||
//Receives the event
|
||||
}
|
||||
```
|
||||
@@ -76,6 +76,14 @@
|
||||
<Compile Include="EnumTerminalInfoInteger.cs" />
|
||||
<Compile Include="FlagFontStyle.cs" />
|
||||
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
|
||||
<Compile Include="Monitors\OrderModification\ModifiedOrdersEventArgs.cs" />
|
||||
<Compile Include="Monitors\OrderModification\ModifiedOrdersMonitor.cs" />
|
||||
<Compile Include="Monitors\OrderModification\MtModifiedOrder.cs" />
|
||||
<Compile Include="Monitors\MtMonitorBase.cs" />
|
||||
<Compile Include="Monitors\OrderModification\OrderModifiedTypes.cs" />
|
||||
<Compile Include="Monitors\Triggers\IMonitorTrigger.cs" />
|
||||
<Compile Include="Monitors\Triggers\NewBarTrigger.cs" />
|
||||
<Compile Include="Monitors\Triggers\TimeElapsedTrigger.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
<Compile Include="MqlTick.cs" />
|
||||
<Compile Include="MtChartEvent.cs" />
|
||||
|
||||
+62
-1
@@ -26,6 +26,8 @@ namespace MtApi
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private static readonly MtLog Log = LogConfigurator.GetLogger(typeof(MtApiClient));
|
||||
|
||||
private MtClient _client;
|
||||
private readonly object _locker = new object();
|
||||
private MtConnectionState _connectionState = MtConnectionState.Disconnected;
|
||||
@@ -37,7 +39,12 @@ namespace MtApi
|
||||
|
||||
public MtApiClient()
|
||||
{
|
||||
LogConfigurator.Setup(LogProfileName);
|
||||
#if (DEBUG)
|
||||
const LogLevel logLevel = LogLevel.Debug;
|
||||
#else
|
||||
const LogLevel logLevel = LogLevel.Info;
|
||||
#endif
|
||||
LogConfigurator.Setup(LogProfileName, logLevel);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -49,6 +56,7 @@ namespace MtApi
|
||||
///<param name="port">Port of host connection (default 8222) </param>
|
||||
public void BeginConnect(string host, int port)
|
||||
{
|
||||
Log.Info($"BeginConnect: host = {host}, port = {port}");
|
||||
Task.Factory.StartNew(() => Connect(host, port));
|
||||
}
|
||||
|
||||
@@ -58,6 +66,7 @@ namespace MtApi
|
||||
///<param name="port">Port of host connection (default 8222) </param>
|
||||
public void BeginConnect(int port)
|
||||
{
|
||||
Log.Info($"BeginConnect: port = {port}");
|
||||
Task.Factory.StartNew(() => Connect(port));
|
||||
}
|
||||
|
||||
@@ -66,6 +75,7 @@ namespace MtApi
|
||||
///</summary>
|
||||
public void BeginDisconnect()
|
||||
{
|
||||
Log.Info("BeginDisconnect called.");
|
||||
Task.Factory.StartNew(() => Disconnect(false));
|
||||
}
|
||||
|
||||
@@ -251,6 +261,8 @@ namespace MtApi
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit
|
||||
, string comment, int magic, DateTime expiration, Color arrowColor)
|
||||
{
|
||||
Log.Debug($"OrderSend: symbol = {symbol}, cmd = {cmd}, volume = {volume}, price = {price}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}, comment = {comment}, magic = {magic}, expiration = {expiration}, arrowColor = {arrowColor}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -271,6 +283,8 @@ namespace MtApi
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit
|
||||
, string comment, int magic, DateTime expiration)
|
||||
{
|
||||
Log.Debug($"OrderSend: symbol = {symbol}, cmd = {cmd}, volume = {volume}, price = {price}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}, comment = {comment}, magic = {magic}, expiration = {expiration}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -290,6 +304,8 @@ namespace MtApi
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit
|
||||
, string comment, int magic)
|
||||
{
|
||||
Log.Debug($"OrderSend: symbol = {symbol}, cmd = {cmd}, volume = {volume}, price = {price}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}, comment = {comment}, magic = {magic}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -308,6 +324,8 @@ namespace MtApi
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit
|
||||
, string comment)
|
||||
{
|
||||
Log.Debug($"OrderSend: symbol = {symbol}, cmd = {cmd}, volume = {volume}, price = {price}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}, comment = {comment}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -324,6 +342,8 @@ namespace MtApi
|
||||
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit)
|
||||
{
|
||||
Log.Debug($"OrderSend: symbol = {symbol}, cmd = {cmd}, volume = {volume}, price = {price}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -339,6 +359,8 @@ namespace MtApi
|
||||
|
||||
public int OrderSend(string symbol, TradeOperation cmd, double volume, string price, int slippage, double stoploss, double takeprofit)
|
||||
{
|
||||
Log.Debug($"OrderSend: symbol = {symbol}, cmd = {cmd}, volume = {volume}, price = {price}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}");
|
||||
|
||||
double dPrice;
|
||||
return double.TryParse(price, out dPrice) ?
|
||||
OrderSend(symbol, cmd, volume, dPrice, slippage, stoploss, takeprofit) : 0;
|
||||
@@ -346,6 +368,8 @@ namespace MtApi
|
||||
|
||||
public int OrderSendBuy(string symbol, double volume, int slippage)
|
||||
{
|
||||
Log.Debug($"OrderSendBuy: symbol = {symbol}, volume = {volume}, slippage = {slippage}");
|
||||
|
||||
return OrderSendBuy(symbol, volume, slippage, 0, 0, null, 0);
|
||||
}
|
||||
|
||||
@@ -366,6 +390,8 @@ namespace MtApi
|
||||
|
||||
public int OrderSendBuy(string symbol, double volume, int slippage, double stoploss, double takeprofit, string comment, int magic)
|
||||
{
|
||||
Log.Debug($"OrderSendBuy: symbol = {symbol}, volume = {volume}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}, comment = {comment}, magic = {magic}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -382,6 +408,8 @@ namespace MtApi
|
||||
|
||||
public int OrderSendSell(string symbol, double volume, int slippage, double stoploss, double takeprofit, string comment, int magic)
|
||||
{
|
||||
Log.Debug($"OrderSendSell: symbol = {symbol}, volume = {volume}, slippage = {slippage}, stoploss = {stoploss}, takeprofit = {takeprofit}, comment = {comment}, magic = {magic}");
|
||||
|
||||
var response = SendRequest<OrderSendResponse>(new OrderSendRequest
|
||||
{
|
||||
Symbol = symbol,
|
||||
@@ -398,6 +426,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderClose(int ticket, double lots, double price, int slippage, Color color)
|
||||
{
|
||||
Log.Debug($"OrderClose: ticket = {ticket}, lots = {lots}, price = {price}, slippage = {slippage}, color = {color}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderCloseRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -411,6 +441,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderClose(int ticket, double lots, double price, int slippage)
|
||||
{
|
||||
Log.Debug($"OrderClose: ticket = {ticket}, lots = {lots}, price = {price}, slippage = {slippage}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderCloseRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -423,6 +455,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderClose(int ticket, double lots, int slippage)
|
||||
{
|
||||
Log.Debug($"OrderClose: ticket = {ticket}, lots = {lots}, slippage = {slippage}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderCloseRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -434,6 +468,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderClose(int ticket, int slippage)
|
||||
{
|
||||
Log.Debug($"OrderClose: ticket = {ticket}, slippage = {slippage}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderCloseRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -444,6 +480,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderCloseBy(int ticket, int opposite, Color color)
|
||||
{
|
||||
Log.Debug($"OrderCloseBy: ticket = {ticket}, opposite = {opposite}, color = {color}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderCloseByRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -455,6 +493,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderCloseBy(int ticket, int opposite)
|
||||
{
|
||||
Log.Debug($"OrderCloseBy: ticket = {ticket}, opposite = {opposite}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderCloseByRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -465,6 +505,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderDelete(int ticket, Color color)
|
||||
{
|
||||
Log.Debug($"OrderDelete: ticket = {ticket}, color = {color}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderDeleteRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -475,6 +517,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderDelete(int ticket)
|
||||
{
|
||||
Log.Debug($"OrderDelete: ticket = {ticket}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderDeleteRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -484,6 +528,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderModify(int ticket, double price, double stoploss, double takeprofit, DateTime expiration, Color arrowColor)
|
||||
{
|
||||
Log.Debug($"OrderModify: ticket = {ticket}, price = {price}, stoploss = {stoploss}, takeprofit = {takeprofit}, expiration = {expiration}, arrowColor = {arrowColor}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderModifyRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -498,6 +544,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderModify(int ticket, double price, double stoploss, double takeprofit, DateTime expiration)
|
||||
{
|
||||
Log.Debug($"OrderModify: ticket = {ticket}, price = {price}, stoploss = {stoploss}, takeprofit = {takeprofit}, expiration = {expiration}");
|
||||
|
||||
var response = SendRequest<ResponseBase>(new OrderModifyRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
@@ -516,6 +564,8 @@ namespace MtApi
|
||||
|
||||
public bool OrderSelect(int index, OrderSelectMode select, OrderSelectSource pool)
|
||||
{
|
||||
Log.Debug($"OrderSelect: index = {index}, select = {select}, pool = {pool}");
|
||||
|
||||
var commandParameters = new ArrayList { index, (int)select, (int)pool };
|
||||
return SendCommand<bool>(MtCommandType.OrderSelect, commandParameters);
|
||||
}
|
||||
@@ -2894,6 +2944,8 @@ namespace MtApi
|
||||
{
|
||||
client.Dispose();
|
||||
message = string.IsNullOrEmpty(client.Host) ? $"Failed connection to localhost:{client.Port}. {e.Message}" : $"Failed connection to {client.Host}:{client.Port}. {e.Message}";
|
||||
|
||||
Log.Warn(message);
|
||||
}
|
||||
|
||||
if (state == MtConnectionState.Connected)
|
||||
@@ -2906,6 +2958,8 @@ namespace MtApi
|
||||
_client.ServerFailed += _client_ServerFailed;
|
||||
_client.MtEventReceived += _client_MtEventReceived;
|
||||
message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to { client.Host}:{client.Port}";
|
||||
|
||||
Log.Info(message);
|
||||
}
|
||||
|
||||
_connectionState = state;
|
||||
@@ -2973,6 +3027,7 @@ namespace MtApi
|
||||
_connectionState = state;
|
||||
}
|
||||
|
||||
Log.Info(message);
|
||||
|
||||
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(state, message));
|
||||
}
|
||||
@@ -2984,6 +3039,7 @@ namespace MtApi
|
||||
var client = Client;
|
||||
if (client == null)
|
||||
{
|
||||
Log.Warn("SendCommand: No connection");
|
||||
throw new MtConnectionException("No connection");
|
||||
}
|
||||
|
||||
@@ -2993,16 +3049,19 @@ namespace MtApi
|
||||
}
|
||||
catch (CommunicationException ex)
|
||||
{
|
||||
Log.Warn($"SendCommand: {ex.Message}");
|
||||
throw new MtConnectionException(ex.Message, ex);
|
||||
}
|
||||
|
||||
if (response == null)
|
||||
{
|
||||
Log.Warn("SendCommand: Response from MetaTrader is null");
|
||||
throw new MtExecutionException(MtErrorCode.MtApiCustomError, "Response from MetaTrader is null");
|
||||
}
|
||||
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Warn($"SendCommand: ErrorCode = {response.ErrorCode}. {response}");
|
||||
throw new MtExecutionException((MtErrorCode)response.ErrorCode, response.ToString());
|
||||
}
|
||||
|
||||
@@ -3026,12 +3085,14 @@ namespace MtApi
|
||||
|
||||
if (res == null)
|
||||
{
|
||||
Log.Warn("SendRequest: Response from MetaTrader is null");
|
||||
throw new MtExecutionException(MtErrorCode.MtApiCustomError, "Response from MetaTrader is null");
|
||||
}
|
||||
|
||||
var response = JsonConvert.DeserializeObject<T>(res);
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Warn($"SendRequest: ErrorCode = {response.ErrorCode}. {response}");
|
||||
throw new MtExecutionException((MtErrorCode)response.ErrorCode, response.ErrorMessage);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.40.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.40.0")]
|
||||
[assembly: AssemblyVersion("1.0.42.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.42.0")]
|
||||
@@ -7,6 +7,9 @@
|
||||
OP_BUYLIMIT = 2,
|
||||
OP_SELLLIMIT = 3,
|
||||
OP_BUYSTOP = 4,
|
||||
OP_SELLSTOP = 5
|
||||
OP_SELLSTOP = 5,
|
||||
OP_BALANCE = 6,
|
||||
OP_CREDIT = 7,
|
||||
OP_REBATE = 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
internal enum Mt5EventTypes
|
||||
{
|
||||
OnTradeTransaction = 1,
|
||||
OnBookEvent = 2
|
||||
OnBookEvent = 2,
|
||||
OnTick = 3,
|
||||
OnLastTimeBar = 4,
|
||||
OnLockTicks = 5
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MtApi5.Events
|
||||
{
|
||||
public class OnLastTimeBarEvent
|
||||
{
|
||||
public MqlRates Rates { get; set; }
|
||||
public string Instrument { get; set; }
|
||||
public int ExpertHandle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace MtApi5.Events
|
||||
{
|
||||
internal class OnLockTicksEvent
|
||||
{
|
||||
public string Instrument { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MtApi5.Events
|
||||
{
|
||||
internal class OnTickEvent
|
||||
{
|
||||
public MqlTick Tick { get; set; }
|
||||
public string Instrument { get; set; }
|
||||
public int ExpertHandle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ namespace MtApi5
|
||||
public ENUM_BOOK_TYPE type { get; set; } // Order type from ENUM_BOOK_TYPE enumeration
|
||||
public double price { get; set; } // Price
|
||||
public long volume { get; set; } // Volume
|
||||
public double volume_real { get; set; } // Volume for the current Last price with greater accuracy
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
+15
-2
@@ -7,7 +7,19 @@ namespace MtApi5
|
||||
{
|
||||
public MqlRates(DateTime time, double open, double high, double low, double close, long tick_volume, int spread, long real_volume)
|
||||
{
|
||||
this.time = time;
|
||||
mt_time = Mt5TimeConverter.ConvertToMtTime(time);
|
||||
this.open = open;
|
||||
this.high = high;
|
||||
this.low = low;
|
||||
this.close = close;
|
||||
this.tick_volume = tick_volume;
|
||||
this.spread = spread;
|
||||
this.real_volume = real_volume;
|
||||
}
|
||||
|
||||
internal MqlRates(long time, double open, double high, double low, double close, long tick_volume, int spread, long real_volume)
|
||||
{
|
||||
mt_time = time;
|
||||
this.open = open;
|
||||
this.high = high;
|
||||
this.low = low;
|
||||
@@ -21,7 +33,8 @@ namespace MtApi5
|
||||
{
|
||||
}
|
||||
|
||||
public DateTime time { get; set; } // Period start time
|
||||
public DateTime time => Mt5TimeConverter.ConvertFromMtTime(mt_time); // Period start time
|
||||
public long mt_time { get; set; } // Period start time (original MT 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
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@ namespace MtApi5
|
||||
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 ulong volume { get; set; } // Volume for the current Last price
|
||||
public double volume_real { get; set; } // Volume for the current Last price with greater accuracy
|
||||
|
||||
public DateTime time => Mt5TimeConverter.ConvertFromMtTime(MtTime);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,9 @@ namespace MtApi5
|
||||
//CTrade
|
||||
PositionClose = 64,
|
||||
PositionOpen = 65,
|
||||
PositionModify = 6066,
|
||||
PositionClosePartial_bySymbol = 6067,
|
||||
PositionClosePartial_byTicket = 6068,
|
||||
//PositionOpenWithResult = 1065,
|
||||
|
||||
//Backtesting
|
||||
@@ -235,6 +238,23 @@ namespace MtApi5
|
||||
Print = 68,
|
||||
ResetLastError = 143,
|
||||
SendNotification = 144, //TODO
|
||||
SendMail = 145 //TODO
|
||||
SendMail = 145, //TODO
|
||||
|
||||
//Global Variables
|
||||
GlobalVariableCheck = 146,
|
||||
GlobalVariableTime = 147,
|
||||
GlobalVariableDel = 148,
|
||||
GlobalVariableGet = 149,
|
||||
GlobalVariableName = 150,
|
||||
GlobalVariableSet = 151,
|
||||
GlobalVariablesFlush = 152,
|
||||
GlobalVariableTemp = 154,
|
||||
GlobalVariableSetOnCondition = 156,
|
||||
GlobalVariablesDeleteAll = 157,
|
||||
GlobalVariablesTotal = 158,
|
||||
|
||||
UnlockTicks = 159,
|
||||
PositionCloseAll = 160,
|
||||
TesterStop = 161
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -181,8 +181,7 @@ namespace MtApi5
|
||||
SYMBOL_BACKGROUND_COLOR = 79,
|
||||
SYMBOL_CHART_MODE = 80,
|
||||
SYMBOL_SELECT = 0,
|
||||
//FIXME: SYMBOL_VISIBLE not found in MQL5 environment!
|
||||
//SYMBOL_VISIBLE = ?
|
||||
SYMBOL_VISIBLE = 76,
|
||||
SYMBOL_SESSION_DEALS = 56,
|
||||
SYMBOL_SESSION_BUY_ORDERS = 60,
|
||||
SYMBOL_SESSION_SELL_ORDERS = 62,
|
||||
@@ -224,6 +223,9 @@ namespace MtApi5
|
||||
SYMBOL_LAST = 7,
|
||||
SYMBOL_LASTHIGH = 8,
|
||||
SYMBOL_LASTLOW = 9,
|
||||
SYMBOL_VOLUME_REAL = 10,
|
||||
SYMBOL_VOLUMEHIGH_REAL = 11,
|
||||
SYMBOL_VOLUMELOW_REAL = 12,
|
||||
SYMBOL_OPTION_STRIKE = 72,
|
||||
SYMBOL_POINT = 16,
|
||||
SYMBOL_TRADE_TICK_VALUE = 26,
|
||||
@@ -549,7 +551,6 @@ namespace MtApi5
|
||||
POSITION_SL = 6, //Stop Loss level of opened position
|
||||
POSITION_TP = 7, //Take Profit level of opened position
|
||||
POSITION_PRICE_CURRENT = 5, //Current price of the position symbol
|
||||
POSITION_COMMISSION = 8, //FIXME: Undocumented!
|
||||
POSITION_SWAP = 9, //Cumulative swap
|
||||
POSITION_PROFIT = 10 //Current profit
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
public class Mt5LockTicksEventArgs : EventArgs
|
||||
{
|
||||
internal Mt5LockTicksEventArgs(string symbol)
|
||||
{
|
||||
Symbol = symbol;
|
||||
}
|
||||
|
||||
public string Symbol { get; }
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -1,4 +1,5 @@
|
||||
using MTApiService;
|
||||
using System;
|
||||
using MTApiService;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
@@ -8,8 +9,13 @@ namespace MtApi5
|
||||
public double Bid { get; }
|
||||
public double Ask { get; }
|
||||
public int ExpertHandle { get; set; }
|
||||
public DateTime Time { get; set; }
|
||||
public double Last { get; set; }
|
||||
public ulong Volume { get; set; }
|
||||
// public long TimeMsc { get; set; }
|
||||
// public uint Flags { get; set; }
|
||||
|
||||
private Mt5Quote(string instrument, double bid, double ask)
|
||||
internal Mt5Quote(string instrument, double bid, double ask)
|
||||
{
|
||||
Instrument = instrument;
|
||||
Bid = bid;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace MtApi5
|
||||
{
|
||||
public class Mt5TimeBarArgs: EventArgs
|
||||
{
|
||||
internal Mt5TimeBarArgs(int expertHandle, string symbol, MqlRates rates)
|
||||
{
|
||||
ExpertHandle = expertHandle;
|
||||
Rates = rates;
|
||||
Symbol = symbol;
|
||||
}
|
||||
|
||||
public int ExpertHandle { get; }
|
||||
public string Symbol { get; }
|
||||
public MqlRates Rates { get; }
|
||||
}
|
||||
}
|
||||
+13
-3
@@ -32,8 +32,8 @@
|
||||
<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>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@@ -49,7 +49,12 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="CopyTicksFlag.cs" />
|
||||
<Compile Include="Events\OnBookEvent.cs" />
|
||||
<Compile Include="Events\OnLastTimeBarEvent.cs" />
|
||||
<Compile Include="Events\OnLockTicksEvent.cs" />
|
||||
<Compile Include="Events\OnTickEvent.cs" />
|
||||
<Compile Include="Events\OnTradeTransactionEvent.cs" />
|
||||
<Compile Include="Mt5LockTicksEventArgs.cs" />
|
||||
<Compile Include="Mt5TimeBarArgs.cs" />
|
||||
<Compile Include="MqlBookInfo.cs" />
|
||||
<Compile Include="MqlParam.cs" />
|
||||
<Compile Include="MqlRates.cs" />
|
||||
@@ -73,6 +78,7 @@
|
||||
<Compile Include="Events\Mt5EventTypes.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Mt5Quote.cs" />
|
||||
<Compile Include="Requests\BuyRequest.cs" />
|
||||
<Compile Include="Requests\ChartTimePriceToXyRequest.cs" />
|
||||
<Compile Include="Requests\ChartTimePriceToXyResult.cs" />
|
||||
<Compile Include="Requests\ChartXyToTimePriceRequest.cs" />
|
||||
@@ -83,14 +89,19 @@
|
||||
<Compile Include="Requests\MarketBookGetRequest.cs" />
|
||||
<Compile Include="Requests\OrderCheckRequest.cs" />
|
||||
<Compile Include="Requests\OrderCheckResult.cs" />
|
||||
<Compile Include="Requests\OrderSendAsyncRequest.cs" />
|
||||
<Compile Include="Requests\OrderSendRequest.cs" />
|
||||
<Compile Include="Requests\PositionCloseRequest.cs" />
|
||||
<Compile Include="Requests\PositionCloseResult.cs" />
|
||||
<Compile Include="Requests\PositionOpenRequest.cs" />
|
||||
<Compile Include="Requests\RequestBase.cs" />
|
||||
<Compile Include="Requests\RequestType.cs" />
|
||||
<Compile Include="Requests\OrderSendResult.cs" />
|
||||
<Compile Include="Requests\Response.cs" />
|
||||
<Compile Include="Requests\SellRequest.cs" />
|
||||
<Compile Include="Requests\SymbolInfoStringRequest.cs" />
|
||||
<Compile Include="Requests\SymbolInfoStringResult.cs" />
|
||||
<Compile Include="Requests\SymbolInfoTickRequest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
|
||||
@@ -101,7 +112,6 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<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.
|
||||
|
||||
+411
-32
@@ -40,12 +40,21 @@ namespace MtApi5
|
||||
private volatile bool _isBacktestingMode;
|
||||
private Mt5ConnectionState _connectionState = Mt5ConnectionState.Disconnected;
|
||||
private int _executorHandle;
|
||||
private readonly Dictionary<Mt5EventTypes, Action<int, string>> _mtEventHandlers =
|
||||
new Dictionary<Mt5EventTypes, Action<int, string>>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public MtApi5Client()
|
||||
{
|
||||
LogConfigurator.Setup(LogProfileName);
|
||||
|
||||
_mtEventHandlers[Mt5EventTypes.OnBookEvent] = ReceivedOnBookEvent;
|
||||
_mtEventHandlers[Mt5EventTypes.OnTick] = ReceivedOnTickEvent;
|
||||
_mtEventHandlers[Mt5EventTypes.OnTradeTransaction] = ReceivedOnTradeTransactionEvent;
|
||||
_mtEventHandlers[Mt5EventTypes.OnLastTimeBar] = ReceivedOnLastTimeBarEvent;
|
||||
_mtEventHandlers[Mt5EventTypes.OnLockTicks] = ReceivedOnLockTicksEvent;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
@@ -125,6 +134,38 @@ namespace MtApi5
|
||||
return response != null && response.RetVal;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Function is used for conducting asynchronous trade operations without waiting for the trade server's response to a sent request.
|
||||
///</summary>
|
||||
///<param name="request">Reference to a object of MqlTradeRequest type describing the trade activity of the client.</param>
|
||||
///<param name="result">Reference to a object of MqlTradeResult type describing the result of trade operation in case of a successful completion (if true is returned).</param>
|
||||
/// <returns>
|
||||
/// Returns true if the request is sent to a trade server. In case the request is not sent, it returns false.
|
||||
/// In case the request is sent, in the result variable the response code contains TRADE_RETCODE_PLACED value (code 10008) – "order placed".
|
||||
/// Successful execution means only the fact of sending, but does not give any guarantee that the request has reached the trade server and has been accepted for processing.
|
||||
/// When processing the received request, a trade server sends a reply to a client terminal notifying of change in the current state of positions,
|
||||
/// orders and deals, which leads to the generation of the Trade event.
|
||||
/// </returns>
|
||||
public bool OrderSendAsync(MqlTradeRequest request, out MqlTradeResult result)
|
||||
{
|
||||
Log.Debug($"OrderSend: request = {request}");
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
Log.Warn("OrderSend: request is not defined!");
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var response = SendRequest<OrderSendResult>(new OrderSendAsyncRequest
|
||||
{
|
||||
TradeRequest = request
|
||||
});
|
||||
|
||||
result = response?.TradeResult;
|
||||
return response != null && response.RetVal;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function calculates the margin required for the specified order type, on the current account
|
||||
///, in the current market environment not taking into account current pending orders and open positions
|
||||
@@ -512,11 +553,20 @@ namespace MtApi5
|
||||
///<summary>
|
||||
///Close all open positions.
|
||||
///</summary>
|
||||
[Obsolete("OrderCloseAll is deprecated, please use PositionCloseAll instead.")]
|
||||
public bool OrderCloseAll()
|
||||
{
|
||||
return SendCommand<bool>(Mt5CommandType.OrderCloseAll, null);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Close all open positions. Returns count of closed positions.
|
||||
///</summary>
|
||||
public int PositionCloseAll()
|
||||
{
|
||||
return SendCommand<int>(Mt5CommandType.PositionCloseAll, null);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Closes a position with the specified ticket.
|
||||
///</summary>
|
||||
@@ -529,6 +579,50 @@ namespace MtApi5
|
||||
return SendCommand<bool>(Mt5CommandType.PositionClose, commandParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies existing position
|
||||
/// </summary>
|
||||
/// <param name="ticket">>Ticket of the position</param>
|
||||
/// <param name="sl">Stop loss</param>
|
||||
/// <param name="tp">Take profit</param>
|
||||
/// <returns></returns>
|
||||
public bool PositionModify(ulong ticket, double sl, double tp)
|
||||
{
|
||||
var commandParameters = new ArrayList { ticket, sl,tp };
|
||||
|
||||
return SendCommand<bool>(Mt5CommandType.PositionModify, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Closes a position with the specified ticket.
|
||||
///</summary>
|
||||
///<param name="ticket">Ticket of the closed position.</param>
|
||||
///<param name="deviation">Maximal deviation from the current price (in points).</param>
|
||||
/// <param name="result">output result</param>
|
||||
public bool PositionClose(ulong ticket, ulong deviation, out MqlTradeResult result)
|
||||
{
|
||||
Log.Debug($"PositionClose: ticket = {ticket}, deviation = {deviation}");
|
||||
|
||||
var response = SendRequest<PositionCloseResult>(new PositionCloseRequest
|
||||
{
|
||||
Ticket = ticket,
|
||||
Deviation = deviation
|
||||
});
|
||||
|
||||
result = response?.TradeResult;
|
||||
return response != null && response.RetVal;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Closes a position with the specified ticket.
|
||||
///</summary>
|
||||
///<param name="ticket">Ticket of the closed position.</param>
|
||||
/// <param name="result">output result</param>
|
||||
public bool PositionClose(ulong ticket, out MqlTradeResult result)
|
||||
{
|
||||
return PositionClose(ticket, ulong.MaxValue, out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a position with the specified parameters.
|
||||
/// </summary>
|
||||
@@ -559,7 +653,7 @@ namespace MtApi5
|
||||
/// <param name="comment">comment</param>
|
||||
/// <param name="result">output result</param>
|
||||
/// <returns>true - successful check of the basic structures, otherwise - false.</returns>
|
||||
public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string comment , out MqlTradeResult result)
|
||||
public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string comment, out MqlTradeResult result)
|
||||
{
|
||||
Log.Debug($"PositionOpen: symbol = {symbol}, orderType = {orderType}, volume = {volume}, price = {price}, sl = {sl}, tp = {tp}, comment = {comment}");
|
||||
|
||||
@@ -577,15 +671,117 @@ namespace MtApi5
|
||||
result = response?.TradeResult;
|
||||
return response != null && response.RetVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a position with the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="symbol">symbol</param>
|
||||
/// <param name="orderType">order type to open position </param>
|
||||
/// <param name="volume">position volume</param>
|
||||
/// <param name="price">execution price</param>
|
||||
/// <param name="sl">Stop Loss price</param>
|
||||
/// <param name="tp">Take Profit price</param>
|
||||
/// <param name="result">output result</param>
|
||||
/// <returns>true - successful check of the basic structures, otherwise - false.</returns>
|
||||
public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, out MqlTradeResult result)
|
||||
{
|
||||
return PositionOpen(symbol, orderType, volume, price, sl, tp, "", out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Partially closes a position on a specified symbol in case of a "hedging" accounting.
|
||||
/// </summary>
|
||||
/// <param name="symbol">Name of a trading instrument, on which a position is closed partially.</param>
|
||||
/// <param name="volume"> Volume, by which a position should be decreased. If the value exceeds the volume of a partially closed position, it is closed in full. No position in the opposite direction is opened.</param>
|
||||
/// <param name="deviation">The maximum deviation from the current price (in points).</param>
|
||||
/// <returns>true if the basic check of structures is successful, otherwise false.</returns>
|
||||
public bool PositionClosePartial(string symbol, double volume, ulong deviation = ulong.MaxValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol, volume, deviation };
|
||||
|
||||
return SendCommand<bool>(Mt5CommandType.PositionClosePartial_bySymbol, commandParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Partially closes a position on a specified symbol in case of a "hedging" accounting.
|
||||
/// </summary>
|
||||
/// <param name="ticket">Closed position ticket.</param>
|
||||
/// <param name="volume"> Volume, by which a position should be decreased. If the value exceeds the volume of a partially closed position, it is closed in full. No position in the opposite direction is opened.</param>
|
||||
/// <param name="deviation">The maximum deviation from the current price (in points).</param>
|
||||
/// <returns>true if the basic check of structures is successful, otherwise false.</returns>
|
||||
public bool PositionClosePartial(ulong ticket, double volume, ulong deviation = ulong.MaxValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { ticket, volume, deviation };
|
||||
|
||||
return SendCommand<bool>(Mt5CommandType.PositionClosePartial_byTicket, commandParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a long position with specified parameters with current market Ask price
|
||||
/// </summary>
|
||||
/// <param name="result">output result</param>
|
||||
/// <param name="volume">Requested position volume.</param>
|
||||
/// <param name="symbol">Position symbol. If it is not specified, the current symbol will be used.</param>
|
||||
/// <param name="price">Execution price.</param>
|
||||
/// <param name="sl">Stop Loss price.</param>
|
||||
/// <param name="tp">Take Profit price.</param>
|
||||
/// <param name="comment">Comment.</param>
|
||||
/// <returns>true - successful check of the structures, otherwise - false.</returns>
|
||||
public bool Buy(out MqlTradeResult result, double volume, string symbol = null, double price = 0.0, double sl = 0.0, double tp = 0.0, string comment = null)
|
||||
{
|
||||
Log.Debug($"Buy: volume = {volume}, symbol = {symbol}, sl = {sl}, tp = {tp}, comment = {comment}");
|
||||
|
||||
var response = SendRequest<OrderSendResult>(new BuyRequest
|
||||
{
|
||||
Volume = volume,
|
||||
Symbol = symbol,
|
||||
Price = price,
|
||||
Sl = sl,
|
||||
Tp = tp,
|
||||
Comment = comment
|
||||
});
|
||||
|
||||
result = response?.TradeResult;
|
||||
return response != null && response.RetVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a short position with specified parameters with current market Bid price
|
||||
/// </summary>
|
||||
/// <param name="result">output result</param>
|
||||
/// <param name="volume">Requested position volume.</param>
|
||||
/// <param name="symbol">Position symbol. If it is not specified, the current symbol will be used.</param>
|
||||
/// <param name="price">Execution price.</param>
|
||||
/// <param name="sl">Stop Loss price.</param>
|
||||
/// <param name="tp">Take Profit price.</param>
|
||||
/// <param name="comment">Comment.</param>
|
||||
/// <returns>true - successful check of the structures, otherwise - false.</returns>
|
||||
public bool Sell(out MqlTradeResult result, double volume, string symbol = null, double price = 0.0, double sl = 0.0, double tp = 0.0, string comment = null)
|
||||
{
|
||||
Log.Debug($"Sell: volume = {volume}, symbol = {symbol}, sl = {sl}, tp = {tp}, comment = {comment}");
|
||||
|
||||
var response = SendRequest<OrderSendResult>(new SellRequest
|
||||
{
|
||||
Volume = volume,
|
||||
Symbol = symbol,
|
||||
Price = price,
|
||||
Sl = sl,
|
||||
Tp = tp,
|
||||
Comment = comment
|
||||
});
|
||||
|
||||
result = response?.TradeResult;
|
||||
return response != null && response.RetVal;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Account Information functions
|
||||
|
||||
///<summary>
|
||||
///Returns the value of the corresponding account property.
|
||||
///</summary>
|
||||
///<param name="propertyId">Identifier of the property.</param>
|
||||
public double AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE propertyId)
|
||||
///<summary>
|
||||
///Returns the value of the corresponding account property.
|
||||
///</summary>
|
||||
///<param name="propertyId">Identifier of the property.</param>
|
||||
public double AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE propertyId)
|
||||
{
|
||||
var commandParameters = new ArrayList { (int)propertyId };
|
||||
|
||||
@@ -734,7 +930,7 @@ namespace MtApi5
|
||||
ratesArray = new MqlRates[retVal.Length];
|
||||
for(var i = 0; i < retVal.Length; i++)
|
||||
{
|
||||
ratesArray[i] = new MqlRates(Mt5TimeConverter.ConvertFromMtTime(retVal[i].time)
|
||||
ratesArray[i] = new MqlRates(retVal[i].time
|
||||
, retVal[i].open
|
||||
, retVal[i].high
|
||||
, retVal[i].low
|
||||
@@ -768,7 +964,7 @@ namespace MtApi5
|
||||
ratesArray = new MqlRates[retVal.Length];
|
||||
for (var i = 0; i < retVal.Length; i++)
|
||||
{
|
||||
ratesArray[i] = new MqlRates(Mt5TimeConverter.ConvertFromMtTime(retVal[i].time)
|
||||
ratesArray[i] = new MqlRates(retVal[i].time
|
||||
, retVal[i].open
|
||||
, retVal[i].high
|
||||
, retVal[i].low
|
||||
@@ -802,7 +998,7 @@ namespace MtApi5
|
||||
ratesArray = new MqlRates[retVal.Length];
|
||||
for (var i = 0; i < retVal.Length; i++)
|
||||
{
|
||||
ratesArray[i] = new MqlRates(Mt5TimeConverter.ConvertFromMtTime(retVal[i].time)
|
||||
ratesArray[i] = new MqlRates(retVal[i].time
|
||||
, retVal[i].open
|
||||
, retVal[i].high
|
||||
, retVal[i].low
|
||||
@@ -1412,19 +1608,27 @@ namespace MtApi5
|
||||
///<param name="tick"> Link to the structure of the MqlTick type, to which the current prices and time of the last price update will be placed.</param>
|
||||
public bool SymbolInfoTick(string symbol, out MqlTick tick)
|
||||
{
|
||||
var commandParameters = new ArrayList { symbol };
|
||||
|
||||
var retVal = SendCommand<MtMqlTick>(Mt5CommandType.SymbolInfoTick, commandParameters);
|
||||
|
||||
tick = null;
|
||||
if (retVal != null)
|
||||
tick = SendRequest<MqlTick>(new SymbolInfoTickRequest
|
||||
{
|
||||
tick = new MqlTick { MtTime = retVal.time, ask = retVal.ask, bid = retVal.bid, last = retVal.last, volume = retVal.volume };
|
||||
}
|
||||
SymbolName = symbol
|
||||
});
|
||||
|
||||
return tick != null;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function returns current prices of a specified symbol in a variable of the MqlTick type.
|
||||
///</summary>
|
||||
///<param name="symbol">Symbol name.</param>
|
||||
public MqlTick SymbolInfoTick(string symbol)
|
||||
{
|
||||
var tick = SendRequest<MqlTick>(new SymbolInfoTickRequest
|
||||
{
|
||||
SymbolName = symbol
|
||||
});
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Allows receiving time of beginning and end of the specified quoting sessions for a specified symbol and weekday.
|
||||
@@ -2009,6 +2213,14 @@ namespace MtApi5
|
||||
SendCommand<object>(Mt5CommandType.Alert, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Gives program operation completion command when testing.
|
||||
///</summary>
|
||||
public void TesterStop()
|
||||
{
|
||||
SendCommand<object>(Mt5CommandType.TesterStop, null);
|
||||
}
|
||||
|
||||
#endregion // Common Functions
|
||||
|
||||
#region Object Functions
|
||||
@@ -2022,9 +2234,28 @@ namespace MtApi5
|
||||
///<param name="nwin">Number of the chart subwindow. 0 means the main chart window. The specified subwindow must exist, otherwise the function returns false.</param>
|
||||
///<param name="time">The time coordinate of the first anchor.</param>
|
||||
///<param name="price">The price coordinate of the first anchor point.</param>
|
||||
public bool ObjectCreate(long chartId, string name, ENUM_OBJECT type, int nwin, DateTime time, double price)
|
||||
///<param name="listOfCoordinates">List of further anchor points (tuple of time and price).</param>
|
||||
public bool ObjectCreate(long chartId, string name, ENUM_OBJECT type, int nwin, DateTime time, double price, List<Tuple<DateTime, double>> listOfCoordinates = null)
|
||||
{
|
||||
var commandParameters = new ArrayList { chartId, name, (int)type, nwin, Mt5TimeConverter.ConvertToMtTime(time), price };
|
||||
//Count the additional coordinates
|
||||
int iAdditionalCoordinates = (listOfCoordinates != null) ? listOfCoordinates.Count() : 0;
|
||||
if(iAdditionalCoordinates > 29)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("listOfCoordinates", "The maximum amount of coordinates in 30.");
|
||||
}
|
||||
|
||||
int nParameter = 6 + iAdditionalCoordinates * 2;
|
||||
var commandParameters = new ArrayList { nParameter, chartId, name, (int)type, nwin, Mt5TimeConverter.ConvertToMtTime(time), price };
|
||||
|
||||
if (iAdditionalCoordinates > 0)
|
||||
{
|
||||
foreach (Tuple<DateTime, double> coordinateTuple in listOfCoordinates)
|
||||
{
|
||||
commandParameters.Add(Mt5TimeConverter.ConvertToMtTime(coordinateTuple.Item1));
|
||||
commandParameters.Add(coordinateTuple.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
return SendCommand<bool>(Mt5CommandType.ObjectCreate, commandParameters);
|
||||
}
|
||||
|
||||
@@ -2887,6 +3118,135 @@ namespace MtApi5
|
||||
|
||||
#endregion
|
||||
|
||||
#region Global Variables
|
||||
|
||||
///<summary>
|
||||
///Checks the existence of a global variable with the specified name.
|
||||
///</summary>
|
||||
///<param name="name">Global variable name.</param>
|
||||
public bool GlobalVariableCheck(string name)
|
||||
{
|
||||
var commandParameters = new ArrayList { name };
|
||||
return SendCommand<bool>(Mt5CommandType.GlobalVariableCheck, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the time when the global variable was last accessed.
|
||||
///</summary>
|
||||
///<param name="name">Name of the global variable.</param>
|
||||
public DateTime GlobalVariableTime(string name)
|
||||
{
|
||||
var commandParameters = new ArrayList { name };
|
||||
var res = SendCommand<int>(Mt5CommandType.GlobalVariableTime, commandParameters);
|
||||
return Mt5TimeConverter.ConvertFromMtTime(res);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Deletes a global variable from the client terminal.
|
||||
///</summary>
|
||||
///<param name="name">Name of the global variable.</param>
|
||||
public bool GlobalVariableDel(string name)
|
||||
{
|
||||
var commandParameters = new ArrayList { name };
|
||||
return SendCommand<bool>(Mt5CommandType.GlobalVariableDel, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the value of an existing global variable of the client terminal.
|
||||
///</summary>
|
||||
///<param name="name">Global variable name.</param>
|
||||
public double GlobalVariableGet(string name)
|
||||
{
|
||||
var commandParameters = new ArrayList { name };
|
||||
return SendCommand<double>(Mt5CommandType.GlobalVariableGet, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the name of a global variable by its ordinal number.
|
||||
///</summary>
|
||||
///<param name="index">Sequence number in the list of global variables. It should be greater than or equal to 0 and less than GlobalVariablesTotal().</param>
|
||||
public string GlobalVariableName(int index)
|
||||
{
|
||||
var commandParameters = new ArrayList { index };
|
||||
return SendCommand<string>(Mt5CommandType.GlobalVariableName, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Sets a new value for a global variable. If the variable does not exist, the system creates a new global variable.
|
||||
///</summary>
|
||||
///<param name="name">Global variable name.</param>
|
||||
///<param name="value">The new numerical value.</param>
|
||||
public DateTime GlobalVariableSet(string name, double value)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, value };
|
||||
var res = SendCommand<int>(Mt5CommandType.GlobalVariableSet, commandParameters);
|
||||
return Mt5TimeConverter.ConvertFromMtTime(res);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Forcibly saves contents of all global variables to a disk.
|
||||
///</summary>
|
||||
public void GlobalVariablesFlush()
|
||||
{
|
||||
SendCommand<object>(Mt5CommandType.GlobalVariablesFlush, null);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///The function attempts to create a temporary global variable. If the variable doesn't exist, the system creates a new temporary global variable.
|
||||
///</summary>
|
||||
///<param name="name">The name of a temporary global variable.</param>
|
||||
public bool GlobalVariableTemp(string name)
|
||||
{
|
||||
var commandParameters = new ArrayList { name };
|
||||
return SendCommand<bool>(Mt5CommandType.GlobalVariableTemp, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Sets the new value of the existing global variable if the current value equals to the third parameter check_value. If there is no global variable, the function will generate an error ERR_GLOBALVARIABLE_NOT_FOUND (4501) and return false.
|
||||
///</summary>
|
||||
///<param name="name">The name of a global variable.</param>
|
||||
///<param name="value">New value.</param>
|
||||
///<param name="checkValue">The value to check the current value of the global variable.</param>
|
||||
public bool GlobalVariableSetOnCondition(string name, double value, double checkValue)
|
||||
{
|
||||
var commandParameters = new ArrayList { name, value, checkValue };
|
||||
return SendCommand<bool>(Mt5CommandType.GlobalVariableSetOnCondition, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Deletes global variables of the client terminal.
|
||||
///</summary>
|
||||
///<param name="prefixName">Name prefix global variables to remove. If you specify a prefix NULL or empty string, then all variables that meet the data criterion will be deleted.</param>
|
||||
///<param name="limitData">Date to select global variables by the time of their last modification. The function removes global variables, which were changed before this date. If the parameter is zero, then all variables that meet the first criterion (prefix) are deleted.</param>
|
||||
public int GlobalVariablesDeleteAll(string prefixName = "", DateTime? limitData = null)
|
||||
{
|
||||
if (prefixName == null)
|
||||
prefixName = "";
|
||||
var commandParameters = new ArrayList { prefixName, Mt5TimeConverter.ConvertToMtTime(limitData) };
|
||||
return SendCommand<int>(Mt5CommandType.GlobalVariablesDeleteAll, commandParameters);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Returns the total number of global variables of the client terminal.
|
||||
///</summary>
|
||||
public int GlobalVariablesTotal()
|
||||
{
|
||||
return SendCommand<int>(Mt5CommandType.GlobalVariablesTotal, null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Backtesting functions
|
||||
|
||||
///<summary>
|
||||
///The function unlock ticks in backtesting mode.
|
||||
///</summary>
|
||||
public void UnlockTicks()
|
||||
{
|
||||
SendCommand<object>(Mt5CommandType.UnlockTicks, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion // Public Methods
|
||||
|
||||
#region Properties
|
||||
@@ -2934,6 +3294,8 @@ namespace MtApi5
|
||||
public event EventHandler<Mt5ConnectionEventArgs> ConnectionStateChanged;
|
||||
public event EventHandler<Mt5TradeTransactionEventArgs> OnTradeTransaction;
|
||||
public event EventHandler<Mt5BookEventArgs> OnBookEvent;
|
||||
public event EventHandler<Mt5TimeBarArgs> OnLastTimeBar;
|
||||
public event EventHandler<Mt5LockTicksEventArgs> OnLockTicks;
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
@@ -3002,24 +3364,14 @@ namespace MtApi5
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void _client_MtEventReceived(MtEvent e)
|
||||
{
|
||||
var eventType = (Mt5EventTypes)e.EventType;
|
||||
|
||||
switch (eventType)
|
||||
{
|
||||
case Mt5EventTypes.OnTradeTransaction:
|
||||
ReceivedOnTradeTransaction(e.ExpertHandle, e.Payload);
|
||||
break;
|
||||
case Mt5EventTypes.OnBookEvent:
|
||||
ReceivedOnBookEvent(e.ExpertHandle, e.Payload);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_mtEventHandlers[eventType](e.ExpertHandle, e.Payload);
|
||||
}
|
||||
|
||||
private void ReceivedOnTradeTransaction(int expertHandler, string payload)
|
||||
private void ReceivedOnTradeTransactionEvent(int expertHandler, string payload)
|
||||
{
|
||||
var e = JsonConvert.DeserializeObject<OnTradeTransactionEvent>(payload);
|
||||
OnTradeTransaction?.Invoke(this, new Mt5TradeTransactionEventArgs
|
||||
@@ -3041,6 +3393,33 @@ namespace MtApi5
|
||||
});
|
||||
}
|
||||
|
||||
private void ReceivedOnTickEvent(int expertHandler, string payload)
|
||||
{
|
||||
var e = JsonConvert.DeserializeObject<OnTickEvent>(payload);
|
||||
var quote = new Mt5Quote(e.Instrument, e.Tick.bid, e.Tick.ask)
|
||||
{
|
||||
ExpertHandle = expertHandler,
|
||||
Volume = e.Tick.volume,
|
||||
Time = e.Tick.time,
|
||||
Last = e.Tick.last
|
||||
};
|
||||
|
||||
QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask);
|
||||
QuoteUpdate?.Invoke(this, new Mt5QuoteEventArgs(quote));
|
||||
}
|
||||
|
||||
private void ReceivedOnLastTimeBarEvent(int expertHandler, string payload)
|
||||
{
|
||||
var e = JsonConvert.DeserializeObject<OnLastTimeBarEvent>(payload);
|
||||
OnLastTimeBar?.Invoke(this, new Mt5TimeBarArgs(expertHandler, e.Instrument, e.Rates));
|
||||
}
|
||||
|
||||
private void ReceivedOnLockTicksEvent(int expertHandler, string payload)
|
||||
{
|
||||
var e = JsonConvert.DeserializeObject<OnLockTicksEvent>(payload);
|
||||
OnLockTicks?.Invoke(this, new Mt5LockTicksEventArgs(e.Instrument));
|
||||
}
|
||||
|
||||
private void Connect(string host, int port)
|
||||
{
|
||||
var client = new MtClient(host, port);
|
||||
|
||||
@@ -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.18")]
|
||||
[assembly: AssemblyFileVersion("1.0.18")]
|
||||
[assembly: AssemblyVersion("1.0.23")]
|
||||
[assembly: AssemblyFileVersion("1.0.23")]
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class BuyRequest : RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.Buy;
|
||||
|
||||
public double Volume { get; set; }
|
||||
public string Symbol { get; set; }
|
||||
public double Price { get; set; }
|
||||
public double Sl { get; set; }
|
||||
public double Tp { get; set; }
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class OrderSendAsyncRequest : RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.OrderSendAsync;
|
||||
|
||||
public MqlTradeRequest TradeRequest { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class PositionCloseRequest : RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.PositionClose;
|
||||
|
||||
public ulong Ticket { get; set; }
|
||||
public ulong Deviation { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class PositionCloseResult
|
||||
{
|
||||
public bool RetVal { get; set; }
|
||||
public MqlTradeResult TradeResult { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@ namespace MtApi5.Requests
|
||||
IndicatorCreate = 7,
|
||||
SymbolInfoString = 8,
|
||||
ChartTimePriceToXY = 9,
|
||||
ChartXYToTimePrice = 10
|
||||
ChartXYToTimePrice = 10,
|
||||
PositionClose = 11,
|
||||
SymbolInfoTick = 12,
|
||||
Buy = 13,
|
||||
Sell = 14,
|
||||
OrderSendAsync = 15
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class SellRequest : RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.Sell;
|
||||
|
||||
public double Volume { get; set; }
|
||||
public string Symbol { get; set; }
|
||||
public double Price { get; set; }
|
||||
public double Sl { get; set; }
|
||||
public double Tp { get; set; }
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MtApi5.Requests
|
||||
{
|
||||
internal class SymbolInfoTickRequest : RequestBase
|
||||
{
|
||||
public override RequestType RequestType => RequestType.SymbolInfoTick;
|
||||
|
||||
public string SymbolName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -1,24 +1,27 @@
|
||||
# MtApi - .NET API for MetaTrader trading platform (MetaQuotes).
|
||||
MtApi provides an .NET API interface to work with famous trading platfroms MetaTrader4 and MetaTrader5 (MetaQuotes).
|
||||
The api is using directly connection to MetaTrader terminal and is working with MQL functions and the most functions of the api have MQL interface.
|
||||
# MtApi - .NET API for MetaTrader Trading Platform (MetaQuotes).
|
||||
MtApi provides a .NET API to work with famous trading platfroms MetaTrader4 and MetaTrader5 (MetaQuotes).
|
||||
The API connects directly to the MetaTrader terminal and works with MQL functions. Most functions of the API have MQL interface.
|
||||
The connection can be local or remote (by TCP).
|
||||
|
||||
# MtApi structure
|
||||
# MtApi Structure
|
||||
The project has two parts:
|
||||
- client side (C#): MtApi and MtApi5;
|
||||
- server side (C# and C++/CLI): MTApiService, MTConnector, MT5Connector, MQL experts.
|
||||
Server side was designed with using WCF framework so it can be flaxible to setup connections but can be more slow compared with another connections types (for example, shared memory).
|
||||
MTApiService is common engine communication project of the API for MT4 and MT5.
|
||||
MTApiService library should be placed in Windows GAC (Global Assembly Cache). Installers in the project will copied it to GAC automatically.
|
||||
Server side was designed using WCF framework with the intention of using flexibility to setup connections. One downside of using the WCF framework is the slower speed compared to other connection types (for example, shared memory).
|
||||
MTApiService is a common engine communication project of the API for MT4 and MT5.
|
||||
MTApiService library should be placed in Windows GAC (Global Assembly Cache). Installers in the project will be copied to GAC automatically.
|
||||
|
||||
# How to build solution
|
||||
The project is supported by Visual Studio 2015.
|
||||
It also requires WIX Tools (http://wixtoolset.org/).
|
||||
# How to Build Solution
|
||||
The project is supported by Visual Studio 2017 and requires WIX Tools (http://wixtoolset.org/).
|
||||
|
||||
To make api for MetaTrader4 use MtApiInstaller and for MetaTrader5 use MtApi5Installer.
|
||||
All installers will be placed in folder "[root]\build\installers\" and all *.dll files will be placed in "[root]\build\products\".
|
||||
MQL files have been build to ex4 and stored into folders "mq4" for MetaTrader and "mq5" for MetaTrader5. They are ready to using in terminals.
|
||||
If you change source code of MQL expert you have to recompile it with MetaEditor. In this case you need to copy files "hash.mqh" and "json.mqh" to MetaEditor include folder.
|
||||
To make an API for MetaTrader4 use MtApiInstaller and for MetaTrader5 use MtApi5Installer.
|
||||
All installers will be placed in the folder "[root]\build\installers\" and all *.dll files will be placed in "[root]\build\products\".
|
||||
MQL files have been build to ex4 and stored into folders "mq4" for MetaTrader and "mq5" for MetaTrader5. They are ready to be used in terminals.
|
||||
Changing the source code of MQL expert requires recompilation with MetaEditor. Resulting in the need to copy files "hash.mqh" and "json.mqh" to the MetaEditor include folder.
|
||||
|
||||
# Home website
|
||||
Please visit http://mtapi4.net
|
||||
# Home Website
|
||||
|
||||
# Telegram Channel
|
||||
https://t.me/mtapi4
|
||||
|
||||
https://t.me/joinchat/GfnfUxvelQCLvvIvLO16-w
|
||||
@@ -439,6 +439,7 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DockPanel Grid.Row="0" LastChildFill="True">
|
||||
@@ -454,6 +455,15 @@
|
||||
<Button Command="{Binding IndicatorReleaseCommand}" Margin="2"
|
||||
Content="IndicatorRelease" HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
<WrapPanel Grid.Row="2" Margin="2">
|
||||
<Button Command="{Binding iCustomCommand}" Content="iCustom" Margin="2"/>
|
||||
<Button Command="{Binding iBullsPowerCommand}" Content="iBullPower" Margin="2"/>
|
||||
<Button Command="{Binding iBearsPowerCommand}" Content="iBearPower" Margin="2"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel Grid.Row="3">
|
||||
<Button Command="{Binding BarsCalculatedCommand}" Content="BarsCalculated" Margin="2"/>
|
||||
<Button Command="{Binding CopyBufferCommand}" Content="CopyBuffer" Margin="2"/>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -481,17 +491,28 @@
|
||||
</WrapPanel>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="CTrade">
|
||||
<WrapPanel VerticalAlignment="Top" Margin="5">
|
||||
<Button Command="{Binding PositionOpenCommand}" Content="PositionOpen" Margin="2"/>
|
||||
</WrapPanel>
|
||||
<TabItem Header="CTrade (Positions)">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Button Grid.Row="0" Command="{Binding PositionOpenCommand}" Content="PositionOpen" Margin="2" HorizontalAlignment="Left"/>
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="4">
|
||||
<TextBlock Text="Ticket:" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding PositionTicketValue}" Width="150" Margin="2"/>
|
||||
<Button Command="{Binding PositionCloseCommand}" Content="PositionClose" Margin="2"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Row="2" Command="{Binding PositionCloseAllCommand}" Content="PositionCloseAll" Margin="2" HorizontalAlignment="Left"/>
|
||||
<StackPanel Grid.Row="3" Orientation="Horizontal" Margin="4">
|
||||
<Button Command="{Binding BuyCommand}" Content="Buy" Width="60" Margin="2" HorizontalAlignment="Left"/>
|
||||
<Button Command="{Binding SellCommand}" Content="Sell" Width="60" Margin="2" HorizontalAlignment="Left"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Indicators">
|
||||
<WrapPanel VerticalAlignment="Top" Margin="5">
|
||||
<Button Command="{Binding iCustomCommand}" Content="iCustom" Margin="2"/>
|
||||
</WrapPanel>
|
||||
</TabItem>
|
||||
<TabItem Header="Chart Functions">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -565,14 +586,18 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<WrapPanel VerticalAlignment="Top" Margin="5">
|
||||
<Button Command="{Binding GetLastErrorCommand}" Content="GetLastError" Margin="2"/>
|
||||
<Button Command="{Binding ResetLastErrorCommand}" Content="ResetLastError" Margin="2"/>
|
||||
<Button Command="{Binding TesterStopCommand}" Content="TesterStop" Margin="2"/>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Margin="10" Grid.Row="1">
|
||||
<Button Grid.Row="1" Content="UnlockTicks" HorizontalAlignment="Left" Margin="5" Command="{Binding UnlockTicksCommand}"/>
|
||||
|
||||
<Grid Margin="10" Grid.Row="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
@@ -586,6 +611,42 @@
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Global Variables">
|
||||
<Grid Margin="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Column="0" Grid.Row="0" Text="Global Variable Name" Margin="2,0,0,0"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding GlobalVarName}" Margin="4,0,0,0"/>
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" Text="Global Variable Value" Margin="2,2,0,0"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding GlobalVarValue}" Margin="4,2,0,0"/>
|
||||
</Grid>
|
||||
<WrapPanel VerticalAlignment="Top" Grid.Row="1" Margin="0,5,0,0">
|
||||
<Button Command="{Binding GlobalVariableCheckCommand}" Content="GlobalVariableCheck" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableTimeCommand}" Content="GlobalVariableTime" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableDelCommand}" Content="GlobalVariableDel" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableGetCommand}" Content="GlobalVariableGet" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableNameCommand}" Content="GlobalVariableName" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableSetCommand}" Content="GlobalVariableSet" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariablesFlushCommand}" Content="GlobalVariablesFlush" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableTempCommand}" Content="GlobalVariableTemp" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariableSetOnConditionCommand}" Content="GlobalVariableSetOnCondition" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariablesDeleteAllCommand}" Content="GlobalVariablesDeleteAll" Margin="2"/>
|
||||
<Button Command="{Binding GlobalVariablesTotalCommand}" Content="GlobalVariablesTotal" Margin="2"/>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
</Grid>
|
||||
|
||||
@@ -44,6 +44,11 @@ namespace MtApi5TestClient
|
||||
public DelegateCommand CopyCloseCommand { get; private set; }
|
||||
public DelegateCommand IndicatorCreateCommand { get; private set; }
|
||||
public DelegateCommand IndicatorReleaseCommand { get; private set; }
|
||||
public DelegateCommand iCustomCommand { get; private set; }
|
||||
public DelegateCommand iBullsPowerCommand { get; private set; }
|
||||
public DelegateCommand iBearsPowerCommand { get; private set; }
|
||||
public DelegateCommand BarsCalculatedCommand { get; private set; }
|
||||
public DelegateCommand CopyBufferCommand { get; private set; }
|
||||
|
||||
public DelegateCommand CopyTickVolumeCommand { get; private set; }
|
||||
public DelegateCommand CopyRealVolumeCommand { get; private set; }
|
||||
@@ -66,13 +71,16 @@ namespace MtApi5TestClient
|
||||
public DelegateCommand MarketBookGetCommand { get; private set; }
|
||||
|
||||
public DelegateCommand PositionOpenCommand { get; private set; }
|
||||
public DelegateCommand PositionCloseCommand { get; private set; }
|
||||
public DelegateCommand PositionCloseAllCommand { get; private set; }
|
||||
public DelegateCommand BuyCommand { get; private set; }
|
||||
public DelegateCommand SellCommand { get; private set; }
|
||||
|
||||
public DelegateCommand GetLastErrorCommand { get; private set; }
|
||||
public DelegateCommand ResetLastErrorCommand { get; private set; }
|
||||
public DelegateCommand PrintCommand { get; private set; }
|
||||
public DelegateCommand AlertCommand { get; private set; }
|
||||
|
||||
public DelegateCommand iCustomCommand { get; private set; }
|
||||
public DelegateCommand TesterStopCommand { get; private set; }
|
||||
|
||||
public DelegateCommand TimeCurrentCommand { get; private set; }
|
||||
|
||||
@@ -108,6 +116,20 @@ namespace MtApi5TestClient
|
||||
public DelegateCommand TimeTradeServerCommand { get; private set; }
|
||||
public DelegateCommand TimeLocalCommand { get; private set; }
|
||||
public DelegateCommand TimeGMTCommand { get; private set; }
|
||||
|
||||
public DelegateCommand GlobalVariableCheckCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableTimeCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableDelCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableGetCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableNameCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableSetCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariablesFlushCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableTempCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariableSetOnConditionCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariablesDeleteAllCommand { get; private set; }
|
||||
public DelegateCommand GlobalVariablesTotalCommand { get; private set; }
|
||||
|
||||
public DelegateCommand UnlockTicksCommand { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@@ -229,6 +251,39 @@ namespace MtApi5TestClient
|
||||
OnPropertyChanged("ChartFunctionsChartIdValue");
|
||||
}
|
||||
}
|
||||
|
||||
private string _globalVarName;
|
||||
public string GlobalVarName
|
||||
{
|
||||
get { return _globalVarName; }
|
||||
set
|
||||
{
|
||||
_globalVarName = value;
|
||||
OnPropertyChanged("GlobalVarName");
|
||||
}
|
||||
}
|
||||
|
||||
private double _globalVarValue;
|
||||
public double GlobalVarValue
|
||||
{
|
||||
get { return _globalVarValue; }
|
||||
set
|
||||
{
|
||||
_globalVarValue = value;
|
||||
OnPropertyChanged("GlobalVarValue");
|
||||
}
|
||||
}
|
||||
|
||||
private ulong _positionTicketValue;
|
||||
public ulong PositionTicketValue
|
||||
{
|
||||
get { return _positionTicketValue; }
|
||||
set
|
||||
{
|
||||
_positionTicketValue = value;
|
||||
OnPropertyChanged("PositionTicketValue");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
@@ -240,10 +295,11 @@ namespace MtApi5TestClient
|
||||
_mtApiClient.ConnectionStateChanged += mMtApiClient_ConnectionStateChanged;
|
||||
_mtApiClient.QuoteAdded += mMtApiClient_QuoteAdded;
|
||||
_mtApiClient.QuoteRemoved += mMtApiClient_QuoteRemoved;
|
||||
_mtApiClient.QuoteUpdated += mMtApiClient_QuoteUpdated;
|
||||
_mtApiClient.QuoteUpdate += mMtApiClient_QuoteUpdate;
|
||||
_mtApiClient.OnTradeTransaction += mMtApiClient_OnTradeTransaction;
|
||||
_mtApiClient.OnBookEvent += _mtApiClient_OnBookEvent;
|
||||
_mtApiClient.OnLastTimeBar += _mtApiClient_OnLastTimeBar;
|
||||
_mtApiClient.OnLockTicks += _mtApiClient_OnLockTicks;
|
||||
|
||||
ConnectionState = _mtApiClient.ConnectionState;
|
||||
ConnectionMessage = "Disconnected";
|
||||
@@ -303,6 +359,11 @@ namespace MtApi5TestClient
|
||||
CopyCloseCommand = new DelegateCommand(ExecuteCopyClose);
|
||||
IndicatorCreateCommand = new DelegateCommand(ExecuteIndicatorCreate);
|
||||
IndicatorReleaseCommand = new DelegateCommand(ExecuteIndicatorRelease);
|
||||
iCustomCommand = new DelegateCommand(ExecuteICustom);
|
||||
iBullsPowerCommand = new DelegateCommand(ExecuteIBullsPowerCommand);
|
||||
iBearsPowerCommand = new DelegateCommand(ExecuteIBearsPowerCommand);
|
||||
BarsCalculatedCommand = new DelegateCommand(ExecuteBarsCalculatedCommand);
|
||||
CopyBufferCommand = new DelegateCommand(ExecuteCopyBufferCommand);
|
||||
|
||||
CopyTickVolumeCommand = new DelegateCommand(ExecuteCopyTickVolume);
|
||||
CopyRealVolumeCommand = new DelegateCommand(ExecuteCopyRealVolume);
|
||||
@@ -325,13 +386,16 @@ namespace MtApi5TestClient
|
||||
MarketBookGetCommand = new DelegateCommand(ExecuteMarketBookGet);
|
||||
|
||||
PositionOpenCommand = new DelegateCommand(ExecutePositionOpen);
|
||||
PositionCloseCommand = new DelegateCommand(ExecutePositionClose);
|
||||
PositionCloseAllCommand = new DelegateCommand(ExecutePositionCloseAll);
|
||||
BuyCommand = new DelegateCommand(ExecuteBuy);
|
||||
SellCommand = new DelegateCommand(ExecuteSell);
|
||||
|
||||
PrintCommand = new DelegateCommand(ExecutePrint);
|
||||
AlertCommand = new DelegateCommand(ExecuteAlert);
|
||||
GetLastErrorCommand = new DelegateCommand(ExecuteGetLastError);
|
||||
ResetLastErrorCommand = new DelegateCommand(ExecuteResetLastError);
|
||||
|
||||
iCustomCommand = new DelegateCommand(ExecuteICustom);
|
||||
TesterStopCommand = new DelegateCommand(ExecuteTesterStop);
|
||||
|
||||
ChartOpenCommand = new DelegateCommand(ExecuteChartOpen);
|
||||
ChartTimePriceToXYCommand = new DelegateCommand(ExecuteChartTimePriceToXY);
|
||||
@@ -366,6 +430,20 @@ namespace MtApi5TestClient
|
||||
TimeTradeServerCommand = new DelegateCommand(ExecuteTimeTradeServer);
|
||||
TimeLocalCommand = new DelegateCommand(ExecuteTimeLocal);
|
||||
TimeGMTCommand = new DelegateCommand(ExecuteTimeGMT);
|
||||
|
||||
GlobalVariableCheckCommand = new DelegateCommand(ExecuteGlobalVariableCheck);
|
||||
GlobalVariableTimeCommand = new DelegateCommand(ExecuteGlobalVariableTime);
|
||||
GlobalVariableDelCommand = new DelegateCommand(ExecuteGlobalVariableDel);
|
||||
GlobalVariableGetCommand = new DelegateCommand(ExecuteGlobalVariableGet);
|
||||
GlobalVariableNameCommand = new DelegateCommand(ExecuteGlobalVariableName);
|
||||
GlobalVariableSetCommand = new DelegateCommand(ExecuteGlobalVariableSet);
|
||||
GlobalVariablesFlushCommand = new DelegateCommand(ExecuteGlobalVariablesFlush);
|
||||
GlobalVariableTempCommand = new DelegateCommand(ExecuteGlobalVariableTemp);
|
||||
GlobalVariableSetOnConditionCommand = new DelegateCommand(ExecuteGlobalVariableSetOnCondition);
|
||||
GlobalVariablesDeleteAllCommand = new DelegateCommand(ExecuteGlobalVariablesDeleteAll);
|
||||
GlobalVariablesTotalCommand = new DelegateCommand(ExecuteGlobalVariablesTotal);
|
||||
|
||||
UnlockTicksCommand = new DelegateCommand(ExecuteUnlockTicks);
|
||||
}
|
||||
|
||||
private bool CanExecuteConnect(object o)
|
||||
@@ -738,6 +816,68 @@ namespace MtApi5TestClient
|
||||
AddLog($"IndicatorRelease [{indicatorHandle}]: result - {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteICustom(object o)
|
||||
{
|
||||
const string name = @"Examples\Custom Moving Average";
|
||||
int[] parameters = { 0, 21, (int)ENUM_APPLIED_PRICE.PRICE_CLOSE };
|
||||
|
||||
var retVal = await Execute(() => _mtApiClient.iCustom(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, name, parameters));
|
||||
TimeSeriesValues.IndicatorHandle = retVal;
|
||||
AddLog($"Custom Moving Average: result - {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteIBullsPowerCommand(object o)
|
||||
{
|
||||
const int maPeriod = 13;
|
||||
var retVal = await Execute(() => _mtApiClient.iBullsPower(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, maPeriod));
|
||||
TimeSeriesValues.IndicatorHandle = retVal;
|
||||
|
||||
AddLog($"iBullPower: result - {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteIBearsPowerCommand(object o)
|
||||
{
|
||||
const int maPeriod = 13;
|
||||
var retVal = await Execute(() => _mtApiClient.iBearsPower(TimeSeriesValues.SymbolValue, TimeSeriesValues.TimeFrame, maPeriod));
|
||||
TimeSeriesValues.IndicatorHandle = retVal;
|
||||
|
||||
AddLog($"iBearsPower: result - {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteBarsCalculatedCommand(object o)
|
||||
{
|
||||
var retVal = await Execute(() => _mtApiClient.BarsCalculated(TimeSeriesValues.IndicatorHandle));
|
||||
|
||||
AddLog($"BarsCalculated: result - {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteCopyBufferCommand(object o)
|
||||
{
|
||||
TimeSeriesResults.Clear();
|
||||
|
||||
var result = await Execute(() =>
|
||||
{
|
||||
var count = _mtApiClient.CopyBuffer(TimeSeriesValues.IndicatorHandle, 0, TimeSeriesValues.StartPos, TimeSeriesValues.Count, out var values);
|
||||
return count > 0 ? values : null;
|
||||
});
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
AddLog("CopyRates: result is null");
|
||||
return;
|
||||
}
|
||||
|
||||
RunOnUiThread(() =>
|
||||
{
|
||||
foreach (var value in result)
|
||||
{
|
||||
TimeSeriesResults.Add($"{value:F6}");
|
||||
}
|
||||
});
|
||||
|
||||
AddLog("CopyRates: success");
|
||||
}
|
||||
|
||||
private async void ExecuteCopyRates(object o)
|
||||
{
|
||||
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
|
||||
@@ -762,7 +902,7 @@ namespace MtApi5TestClient
|
||||
foreach (var rates in result)
|
||||
{
|
||||
TimeSeriesResults.Add(
|
||||
$"time={rates.time}; open={rates.open}; high={rates.high}; low={rates.low}; close={rates.close}; tick_volume={rates.tick_volume}; spread={rates.spread}; real_volume={rates.tick_volume}");
|
||||
$"time={rates.time}; mt_time={rates.mt_time}; open={rates.open}; high={rates.high}; low={rates.low}; close={rates.close}; tick_volume={rates.tick_volume}; spread={rates.spread}; real_volume={rates.tick_volume}");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -926,6 +1066,12 @@ namespace MtApi5TestClient
|
||||
{
|
||||
var retVal = await Execute(() => _mtApiClient.SymbolInfoDouble("EURUSD", ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID));
|
||||
AddLog($"SymbolInfoDouble(EURUSD, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID): result = {retVal}");
|
||||
retVal = await Execute(() => _mtApiClient.SymbolInfoDouble("EURUSD", ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_REAL));
|
||||
AddLog($"SymbolInfoDouble(EURUSD, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_REAL): result = {retVal}");
|
||||
retVal = await Execute(() => _mtApiClient.SymbolInfoDouble("EURUSD", ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUMEHIGH_REAL));
|
||||
AddLog($"SymbolInfoDouble(EURUSD, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUMEHIGH_REAL): result = {retVal}");
|
||||
retVal = await Execute(() => _mtApiClient.SymbolInfoDouble("EURUSD", ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUMELOW_REAL));
|
||||
AddLog($"SymbolInfoDouble(EURUSD, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUMELOW_REAL): result = {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteSymbolInfoInteger(object o)
|
||||
@@ -964,6 +1110,7 @@ namespace MtApi5TestClient
|
||||
AddLog($"SymbolInfoTick(EURUSD) tick.ask = {result.ask}");
|
||||
AddLog($"SymbolInfoTick(EURUSD) tick.last = {result.last}");
|
||||
AddLog($"SymbolInfoTick(EURUSD) tick.volume = {result.volume}");
|
||||
AddLog($"SymbolInfoTick(EURUSD) tick.volume_real = {result.volume_real}");
|
||||
}
|
||||
|
||||
private async void ExecuteSymbolInfoSessionQuote(object o)
|
||||
@@ -1034,7 +1181,7 @@ namespace MtApi5TestClient
|
||||
|
||||
for (var i = 0; i < result.Length; i++)
|
||||
{
|
||||
AddLog($"MarketBookGet: [{i}] - {result[i].price} | {result[i].volume} | {result[i].type}");
|
||||
AddLog($"MarketBookGet: [{i}] - {result[i].price} | {result[i].volume} | {result[i].type} | {result[i].volume_real}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1053,6 +1200,41 @@ namespace MtApi5TestClient
|
||||
AddLog($"PositionOpen: symbol EURUSD retVal = {retVal}, result = {tradeResult}");
|
||||
}
|
||||
|
||||
private async void ExecutePositionClose(object obj)
|
||||
{
|
||||
var ticket = PositionTicketValue;
|
||||
MqlTradeResult tradeResult = null;
|
||||
|
||||
var retVal = await Execute(() => _mtApiClient.PositionClose(ticket, out tradeResult));
|
||||
AddLog($"PositionClose: ticket {ticket} retVal = {retVal}, result = {tradeResult}");
|
||||
}
|
||||
|
||||
private async void ExecutePositionCloseAll(object obj)
|
||||
{
|
||||
var retVal = await Execute(() => _mtApiClient.PositionCloseAll());
|
||||
AddLog($"PositionCloseAll: count = {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteBuy(object obj)
|
||||
{
|
||||
const string symbol = "EURUSD";
|
||||
const double volume = 0.1;
|
||||
MqlTradeResult tradeResult = null;
|
||||
|
||||
var retVal = await Execute(() => _mtApiClient.Buy(out tradeResult, volume, symbol));
|
||||
AddLog($"Buy: symbol EURUSD retVal = {retVal}, result = {tradeResult}");
|
||||
}
|
||||
|
||||
private async void ExecuteSell(object obj)
|
||||
{
|
||||
const string symbol = "EURUSD";
|
||||
const double volume = 0.1;
|
||||
MqlTradeResult tradeResult = null;
|
||||
|
||||
var retVal = await Execute(() => _mtApiClient.Sell(out tradeResult, volume, symbol));
|
||||
AddLog($"Sell: symbol EURUSD retVal = {retVal}, result = {tradeResult}");
|
||||
}
|
||||
|
||||
private async void ExecutePrint(object obj)
|
||||
{
|
||||
var message = MessageText;
|
||||
@@ -1081,15 +1263,10 @@ namespace MtApi5TestClient
|
||||
AddLog("ResetLastError: executed.");
|
||||
}
|
||||
|
||||
private async void ExecuteICustom(object o)
|
||||
private void ExecuteTesterStop(object obj)
|
||||
{
|
||||
const string symbol = "EURUSD";
|
||||
const ENUM_TIMEFRAMES timeframe = ENUM_TIMEFRAMES.PERIOD_H1;
|
||||
const string name = @"Examples\Custom Moving Average";
|
||||
int[] parameters = { 0, 21, (int)ENUM_APPLIED_PRICE.PRICE_CLOSE };
|
||||
|
||||
var retVal = await Execute(() => _mtApiClient.iCustom(symbol, timeframe, name, parameters));
|
||||
AddLog($"Custom Moving Average: result - {retVal}");
|
||||
_mtApiClient.TesterStop();
|
||||
AddLog("TesterStop: executed.");
|
||||
}
|
||||
|
||||
private async void ExecuteTimeCurrent(object o)
|
||||
@@ -1116,6 +1293,86 @@ namespace MtApi5TestClient
|
||||
AddLog($"TimeGMT: {retVal}");
|
||||
}
|
||||
|
||||
#region Global Variable Commands
|
||||
private async void ExecuteGlobalVariableCheck(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableCheck(name));
|
||||
AddLog($"GlobalVariableCheck: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableTime(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableTime(name));
|
||||
AddLog($"GlobalVariableTime: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableDel(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableDel(name));
|
||||
AddLog($"GlobalVariableDel: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableGet(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableGet(name));
|
||||
GlobalVarValue = retVal;
|
||||
AddLog($"GlobalVariableGet: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableName(object obj)
|
||||
{
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableName(0));
|
||||
GlobalVarName = retVal;
|
||||
AddLog($"GlobalVariableName: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableSet(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var value = GlobalVarValue;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableSet(name, value));
|
||||
AddLog($"GlobalVariableSet: {retVal}");
|
||||
}
|
||||
|
||||
private void ExecuteGlobalVariablesFlush(object obj)
|
||||
{
|
||||
_mtApiClient.GlobalVariablesFlush();
|
||||
AddLog("GlobalVariablesFlush: executed.");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableTemp(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableTemp(name));
|
||||
AddLog($"GlobalVariableTemp: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariableSetOnCondition(object obj)
|
||||
{
|
||||
var name = GlobalVarName;
|
||||
var value = GlobalVarValue;
|
||||
const double checkValue = 2;
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariableSetOnCondition(name, value, checkValue));
|
||||
AddLog($"GlobalVariableSetOnCondition: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariablesDeleteAll(object obj)
|
||||
{
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariablesDeleteAll());
|
||||
AddLog($"GlobalVariablesDeleteAll: {retVal}");
|
||||
}
|
||||
|
||||
private async void ExecuteGlobalVariablesTotal(object obj)
|
||||
{
|
||||
var retVal = await Execute(() => _mtApiClient.GlobalVariablesTotal());
|
||||
AddLog($"GlobalVariablesTotal: {retVal}");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Chart Commands
|
||||
private async void ExecuteChartOpen(object o)
|
||||
{
|
||||
@@ -1417,6 +1674,11 @@ namespace MtApi5TestClient
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void ExecuteUnlockTicks(object o)
|
||||
{
|
||||
_mtApiClient.UnlockTicks();
|
||||
}
|
||||
|
||||
private static void RunOnUiThread(Action action)
|
||||
{
|
||||
Application.Current?.Dispatcher.Invoke(action);
|
||||
@@ -1427,13 +1689,13 @@ namespace MtApi5TestClient
|
||||
Application.Current?.Dispatcher.Invoke(action, args);
|
||||
}
|
||||
|
||||
private static void mMtApiClient_QuoteUpdated(object sender, string symbol, double bid, double ask)
|
||||
{
|
||||
Console.WriteLine(@"Quote: Symbol = {0}, Bid = {1}, Ask = {2}", symbol, bid, ask);
|
||||
}
|
||||
|
||||
private void mMtApiClient_QuoteUpdate(object sender, Mt5QuoteEventArgs e)
|
||||
{
|
||||
var q = e.Quote;
|
||||
|
||||
Console.WriteLine(@"Quote: Symbol = {0}, Bid = {1}, Ask = {2}, Volume = {3}, Time = {4}, Last = {5}"
|
||||
, q.Instrument, q.Bid, q.Ask, q.Volume, q.Time, q.Last);
|
||||
|
||||
if (_quotesMap.ContainsKey(e.Quote.ExpertHandle))
|
||||
{
|
||||
var qvm = _quotesMap[e.Quote.ExpertHandle];
|
||||
@@ -1493,6 +1755,16 @@ namespace MtApi5TestClient
|
||||
AddLog($"OnBookEvent: ExpertHandle = {e.ExpertHandle}, Symbol = {e.Symbol}");
|
||||
}
|
||||
|
||||
private void _mtApiClient_OnLastTimeBar(object sender, Mt5TimeBarArgs e)
|
||||
{
|
||||
AddLog($"OnLastTimeBarEvent: ExpertHandle = {e.ExpertHandle}, Symbol = {e.Symbol}, open = {e.Rates.open}, close = {e.Rates.close}, time = {e.Rates.time}, high = {e.Rates.high}, low = {e.Rates.low}");
|
||||
}
|
||||
|
||||
private void _mtApiClient_OnLockTicks(object sender, Mt5LockTicksEventArgs e)
|
||||
{
|
||||
AddLog($"OnLockTicksEvent: Symbol = {e.Symbol}");
|
||||
}
|
||||
|
||||
private void AddQuote(Mt5Quote quote)
|
||||
{
|
||||
if (_quotesMap.ContainsKey(quote.ExpertHandle))
|
||||
|
||||
@@ -212,8 +212,8 @@ namespace TestApiClientUI
|
||||
foreach (var quote in quotes)
|
||||
{
|
||||
AddNewQuote(quote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisconnected()
|
||||
@@ -456,7 +456,7 @@ namespace TestApiClientUI
|
||||
ticket = (int)listBoxSendedOrders.SelectedItems[0];
|
||||
else if (listBoxClosedOrders.SelectedItems.Count > 0)
|
||||
ticket = (int)listBoxClosedOrders.SelectedItems[0];
|
||||
|
||||
|
||||
if (ticket >= 0)
|
||||
{
|
||||
var result = _apiClient.OrderSelect(ticket, OrderSelectMode.SELECT_BY_POS);
|
||||
|
||||
@@ -86,10 +86,6 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>C:\Program Files (x86)\MtApi\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
||||
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
+814
-95
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user