Compare commits

..

7 Commits

25 changed files with 894 additions and 258 deletions
+8
View File
@@ -104,6 +104,14 @@ _DLLAPI int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid,
}, err, 0);
}
_DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{
return Execute<bool>([&expertHandle, &eventType, payload]() {
MtAdapter::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
return true;
}, err, false);
}
_DLLAPI int _stdcall sendIntResponse(int expertHandle, int response, wchar_t* err)
{
return Execute<int>([&expertHandle, &response]() {
+8
View File
@@ -0,0 +1,8 @@
namespace MtApi5.Events
{
internal enum Mt5EventTypes
{
OnTradeTransaction = 1,
OnBookEvent = 2
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi5.Events
{
internal class OnBookEvent
{
public string Symbol { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi5.Events
{
internal class OnTradeTransactionEvent
{
public MqlTradeTransaction Trans { get; set; }
public MqlTradeRequest Request { get; set; }
public MqlTradeResult Result { get; set; }
}
}
+9 -8
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// ReSharper disable InconsistentNaming
namespace MtApi5
{
public class MqlBookInfo
@@ -14,8 +10,13 @@ namespace MtApi5
this.volume = volume;
}
public ENUM_BOOK_TYPE type { get; private set; } // Order type from ENUM_BOOK_TYPE enumeration
public double price { get; private set; } // Price
public long volume { get; private set; } // Volume
public ENUM_BOOK_TYPE type { get; } // Order type from ENUM_BOOK_TYPE enumeration
public double price { get; } // Price
public long volume { get; } // Volume
public override string ToString()
{
return $"{type}|{price}|{volume}";
}
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace MtApi5
{
public class MqlParam
{
public ENUM_DATATYPE DataType { get; set; }
public long? IntegerValue { get; set; }
public double? DoubleValue { get; set; }
public string StringValue { get; set; }
}
}
+11 -3
View File
@@ -1,5 +1,6 @@
// ReSharper disable InconsistentNaming
using System;
using Newtonsoft.Json;
namespace MtApi5
{
@@ -18,16 +19,23 @@ namespace MtApi5
public ENUM_ORDER_TYPE Type { get; set; } // Order type
public ENUM_ORDER_TYPE_FILLING Type_filling { get; set; } // Order execution type
public ENUM_ORDER_TYPE_TIME Type_time { get; set; } // Order expiration type
public DateTime Expiration { get; set; } // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type)
[JsonIgnore]
public DateTime Expiration // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type)
{
get { return Mt5TimeConverter.ConvertFromMtTime(MtExpiration); }
set { MtExpiration = Mt5TimeConverter.ConvertToMtTime(value); }
}
public string Comment { get; set; } // Order comment
public ulong Position { get; set; } // Position ticket
public ulong PositionBy { get; set; } // The ticket of an opposite position
public int MtExpiration => Mt5TimeConverter.ConvertToMtTime(Expiration);
public int MtExpiration { get; private set; }
public override string ToString()
{
return $"{Symbol}|{Volume}|{Price}|{Volume}|{Action}";
return $"Action={Action}; Magic={Magic}; Order={Order}; Symbol={Symbol}; Volume={Volume}; Price={Price}; Stoplimit={Stoplimit}; Sl={Sl}; Tp={Tp}; Deviation={Deviation}; Type={Type}; Type_filling={Type_filling}; Type_time={Type_time}; Expiration={Expiration}; Comment={Comment}; Position={Position}; PositionBy={PositionBy}";
}
}
}
+39
View File
@@ -0,0 +1,39 @@
using System;
using Newtonsoft.Json;
namespace MtApi5
{
public class MqlTradeTransaction
{
public ulong Deal { get; set; } // Deal ticket
public ulong Order { get; set; } // Order ticket
public string Symbol { get; set; } // Trade symbol name
public ENUM_TRADE_TRANSACTION_TYPE Type { get; set; } // Trade transaction type
public ENUM_ORDER_TYPE OrderType { get; set; } // Order type
public ENUM_ORDER_STATE OrderState { get; set; } // Order state
public ENUM_DEAL_TYPE DealType { get; set; } // Deal type
public ENUM_ORDER_TYPE_TIME TimeType { get; set; } // Order type by action period
[JsonIgnore]
public DateTime TimeExpiration // Order expiration time
{
get { return Mt5TimeConverter.ConvertFromMtTime(MtTimeExpiration); }
set { MtTimeExpiration = Mt5TimeConverter.ConvertToMtTime(value); }
}
public double Price { get; set; } // Price
public double PriceTrigger { get; set; } // Stop limit order activation price
public double PriceSl { get; set; } // Stop Loss level
public double PriceTp { get; set; } // Take Profit level
public double Volume { get; set; } // Volume in lots
public ulong Position { get; set; } // Position ticket
public ulong PositionBy { get; set; } // Ticket of an opposite position
public int MtTimeExpiration { get; private set; }
public override string ToString()
{
return $"Deal={Deal}; Order={Order}; Symbol={Symbol}; Type={Type}; OrderType={OrderType}; OrderState={OrderState}; DealType={DealType}; TimeType={TimeType}; TimeExpiration={TimeExpiration}; Price={Price}; PriceTrigger{PriceTrigger}; PriceSl={PriceSl}; PriceTp={PriceTp}; Volume={Volume}; Position={Position}; PositionBy={PositionBy}";
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using System;
namespace MtApi5
{
public class Mt5BookEventArgs : EventArgs
{
public int ExpertHandle { get; set; }
public string Symbol { get; set; } //Symbol of OnBookEvent event.
}
}
+4 -2
View File
@@ -95,7 +95,7 @@ namespace MtApi5
SymbolInfoSessionTrade = 59,
MarketBookAdd = 60,
MarketBookRelease = 61,
MarketBookGet = 62,
//MarketBookGet = 62,
OrderCloseAll = 63,
//CTrade
@@ -177,6 +177,8 @@ namespace MtApi5
TimeCurrent = 127,
TimeTradeServer = 128,
TimeLocal = 129,
TimeGMT = 130
TimeGMT = 130,
IndicatorRelease = 131
}
}
+74 -10
View File
@@ -582,16 +582,16 @@ namespace MtApi5
public enum ENUM_TRADE_TRANSACTION_TYPE
{
TRADE_TRANSACTION_ORDER_ADD = 0, //Adding a new open order
TRADE_TRANSACTION_ORDER_UPDATE = 1, //Updating an open order
TRADE_TRANSACTION_ORDER_DELETE = 2, //Removing an order from the list of the open ones
TRADE_TRANSACTION_DEAL_ADD = 6, //Adding a deal to the history
TRADE_TRANSACTION_DEAL_UPDATE = 7, //Updating a deal in the history
TRADE_TRANSACTION_DEAL_DELETE = 8, //Deleting a deal from the history
TRADE_TRANSACTION_HISTORY_ADD = 3, //Adding an order to the history as a result of execution or cancellation
TRADE_TRANSACTION_HISTORY_UPDATE = 4, //Changing an order located in the orders history
TRADE_TRANSACTION_HISTORY_DELETE = 5, //Deleting an order from the orders history
TRADE_TRANSACTION_POSITION = 9, //Changing a position not related to a deal execution
TRADE_TRANSACTION_REQUEST = 10 //Notification of the fact that a trade request has been processed by a server and processing result has been received
TRADE_TRANSACTION_ORDER_UPDATE = 1, //Updating an open order. The updates include not only evident changes from the client terminal or a trade server sides but also changes of an order state when setting it (for example, transition from ORDER_STATE_STARTED to ORDER_STATE_PLACED or from ORDER_STATE_PLACED to ORDER_STATE_PARTIAL, etc.).
TRADE_TRANSACTION_ORDER_DELETE = 2, //Removing an order from the list of the open ones. An order can be deleted from the open ones as a result of setting an appropriate request or execution (filling) and moving to the history.
TRADE_TRANSACTION_DEAL_ADD = 6, //Adding a deal to the history. The action is performed as a result of an order execution or performing operations with an account balance.
TRADE_TRANSACTION_DEAL_UPDATE = 7, //Updating a deal in the history. There may be cases when a previously executed deal is changed on a server. For example, a deal has been changed in an external trading system (exchange) where it was previously transferred by a broker.
TRADE_TRANSACTION_DEAL_DELETE = 8, //Deleting a deal from the history. There may be cases when a previously executed deal is deleted from a server. For example, a deal has been deleted in an external trading system (exchange) where it was previously transferred by a broker.
TRADE_TRANSACTION_HISTORY_ADD = 3, //Adding an order to the history as a result of execution or cancellation.
TRADE_TRANSACTION_HISTORY_UPDATE = 4, //Changing an order located in the orders history. This type is provided for enhancing functionality on a trade server side.
TRADE_TRANSACTION_HISTORY_DELETE = 5, //Deleting an order from the orders history. This type is provided for enhancing functionality on a trade server side.
TRADE_TRANSACTION_POSITION = 9, //Changing a position not related to a deal execution. This type of transaction shows that a position has been changed on a trade server side. Position volume, open price, Stop Loss and Take Profit levels can be changed. Data on changes are submitted in MqlTradeTransaction structure via OnTradeTransaction handler. Position change (adding, changing or closing), as a result of a deal execution, does not lead to the occurrence of TRADE_TRANSACTION_POSITION transaction.
TRADE_TRANSACTION_REQUEST = 10 //Notification of the fact that a trade request has been processed by a server and processing result has been received. Only type field (trade transaction type) must be analyzed for such transactions in MqlTradeTransaction structure. The second and third parameters of OnTradeTransaction (request and result) must be analyzed for additional data.
}
#endregion //Trade Transaction Types
@@ -784,4 +784,68 @@ namespace MtApi5
}
#endregion //Smoothing Methods
#region Indicator constants
public enum ENUM_INDICATOR
{
IND_AC = 5, // Accelerator Oscillator
IND_AD = 6, // Accumulation/Distribution
IND_ADX = 8, // Average Directional Index
IND_ADXW = 9, // ADX by Welles Wilder
IND_ALLIGATOR = 7, // Alligator
IND_AMA = 40, // Adaptive Moving Average
IND_AO = 11, // Awesome Oscillator
IND_ATR = 10, // Average True Range
IND_BANDS = 13, // Bollinger Bands®
IND_BEARS = 12, // Bears Power
IND_BULLS = 14, // Bulls Power
IND_BWMFI = 22, // Market Facilitation Index
IND_CCI = 15, // Commodity Channel Index
IND_CHAIKIN = 41, // Chaikin Oscillator
IND_CUSTOM = 43, // Custom indicator
IND_DEMA = 36, // Double Exponential Moving Average
IND_DEMARKER = 16, // DeMarker
IND_ENVELOPES = 17, // Envelopes
IND_FORCE = 18, // Force Index
IND_FRACTALS = 19, // Fractals
IND_FRAMA = 39, // Fractal Adaptive Moving Average
IND_GATOR = 20, // Gator Oscillator
IND_ICHIMOKU = 21, // Ichimoku Kinko Hyo
IND_MA = 26, // Moving Average
IND_MACD = 23, // MACD
IND_MFI = 25, // Money Flow Index
IND_MOMENTUM = 24, // Momentum
IND_OBV = 28, // On Balance Volume
IND_OSMA = 27, // OsMA
IND_RSI = 30, // Relative Strength Index
IND_RVI = 31, // Relative Vigor Index
IND_SAR = 29, // Parabolic SAR
IND_STDDEV = 32, // Standard Deviation
IND_STOCHASTIC = 33, // Stochastic Oscillator
IND_TEMA = 37, // Triple Exponential Moving Average
IND_TRIX = 38, // Triple Exponential Moving Averages Oscillator
IND_VIDYA = 42, // Variable Index Dynamic Average
IND_VOLUMES = 34, // Volumes
IND_WPR = 35 // Williams' Percent Ranges
}
public enum ENUM_DATATYPE
{
TYPE_BOOL = 1,
TYPE_CHAR = 2,
TYPE_UCHAR = 3,
TYPE_SHORT = 4,
TYPE_USHORT = 5,
TYPE_COLOR = 6,
TYPE_INT = 7,
TYPE_UINT = 8,
TYPE_DATETIME = 9,
TYPE_LONG = 10,
TYPE_ULONG = 11,
TYPE_FLOAT = 12,
TYPE_DOUBLE = 13,
TYPE_STRING = 14
}
#endregion
}
+12
View File
@@ -0,0 +1,12 @@
using System;
namespace MtApi5
{
public class Mt5TradeTransactionEventArgs : EventArgs
{
public int ExpertHandle { get; set; }
public MqlTradeTransaction Trans { get; set; } // trade transaction structure
public MqlTradeRequest Request { get; set; } // request structure
public MqlTradeResult Result { get; set; } // result structure
}
}
+9
View File
@@ -48,10 +48,15 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CopyTicksFlag.cs" />
<Compile Include="Events\OnBookEvent.cs" />
<Compile Include="Events\OnTradeTransactionEvent.cs" />
<Compile Include="MqlBookInfo.cs" />
<Compile Include="MqlParam.cs" />
<Compile Include="MqlRates.cs" />
<Compile Include="MqlTick.cs" />
<Compile Include="MqlTradeCheckResult.cs" />
<Compile Include="MqlTradeTransaction.cs" />
<Compile Include="Mt5BookEventArgs.cs" />
<Compile Include="Mt5TimeConverter.cs" />
<Compile Include="Mt5Enums.cs" />
<Compile Include="Mt5ConnectionEventArgs.cs" />
@@ -59,15 +64,19 @@
<Compile Include="MqlTradeRequest.cs" />
<Compile Include="MqlTradeResult.cs" />
<Compile Include="Mt5QuoteEventArgs.cs" />
<Compile Include="Mt5TradeTransactionEventArgs.cs" />
<Compile Include="MtApi5Client.cs" />
<Compile Include="Mt5CommandType.cs" />
<Compile Include="MtConverters.cs" />
<Compile Include="ErrorCode.cs" />
<Compile Include="ExecutionException.cs" />
<Compile Include="Events\Mt5EventTypes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Mt5Quote.cs" />
<Compile Include="Requests\CopyTicksRequest.cs" />
<Compile Include="Requests\ICustomRequest.cs" />
<Compile Include="Requests\IndicatorCreateRequest.cs" />
<Compile Include="Requests\MarketBookGetRequest.cs" />
<Compile Include="Requests\OrderCheckRequest.cs" />
<Compile Include="Requests\OrderCheckResult.cs" />
<Compile Include="Requests\OrderSendRequest.cs" />
+75 -14
View File
@@ -8,6 +8,7 @@ using System.ServiceModel;
using MtApi5.Requests;
using Newtonsoft.Json;
using System.Threading.Tasks;
using MtApi5.Events;
namespace MtApi5
{
@@ -1262,6 +1263,32 @@ namespace MtApi5
});
return response;
}
///<summary>
///The function returns the handle of a specified technical indicator created based on the array of parameters of MqlParam type.
///</summary>
///<param name="symbol">Name of a symbol, on data of which the indicator is calculated. NULL means the current symbol.</param>
///<param name="period">The value of the timeframe can be one of values of the ENUM_TIMEFRAMES enumeration, 0 means the current timeframe.</param>
///<param name="indicatorType">Indicator type, can be one of values of the ENUM_INDICATOR enumeration.</param>
///<param name="parameters">An array of MqlParam type, whose elements contain the type and value of each input parameter of a technical indicator.</param>
public int IndicatorCreate(string symbol, ENUM_TIMEFRAMES period, ENUM_INDICATOR indicatorType, List<MqlParam> parameters = null)
{
var response = SendRequest<int>(new IndicatorCreateRequest
{
Symbol = symbol,
Period = period,
IndicatorType = indicatorType,
Parameters = parameters
});
return response;
}
public bool IndicatorRelease(int indicatorHandle)
{
var commandParameters = new ArrayList { indicatorHandle };
return SendCommand<bool>(Mt5CommandType.IndicatorRelease, commandParameters);
}
#endregion
#region Market Info
@@ -1434,22 +1461,13 @@ namespace MtApi5
///<param name="book">Reference to an array of Depth of Market records.</param>
public bool MarketBookGet(string symbol, out MqlBookInfo[] book)
{
var commandParameters = new ArrayList { symbol };
var retVal = SendCommand<MtMqlBookInfo[]>(Mt5CommandType.MarketBookGet, commandParameters);
book = null;
if (retVal != null)
var response = SendRequest<List<MqlBookInfo>>(new MarketBookGetRequest
{
book = new MqlBookInfo[retVal.Length];
Symbol = symbol
});
foreach (var t in retVal)
{
book[0] = new MqlBookInfo((ENUM_BOOK_TYPE)t.type, t.price, t.volume);
}
}
return book != null;
book = response?.ToArray();
return response != null;
}
#endregion
@@ -2368,6 +2386,8 @@ namespace MtApi5
public event EventHandler<Mt5QuoteEventArgs> QuoteAdded;
public event EventHandler<Mt5QuoteEventArgs> QuoteRemoved;
public event EventHandler<Mt5ConnectionEventArgs> ConnectionStateChanged;
public event EventHandler<Mt5TradeTransactionEventArgs> OnTradeTransaction;
public event EventHandler<Mt5BookEventArgs> OnBookEvent;
#endregion
#region Private Methods
@@ -2421,6 +2441,7 @@ namespace MtApi5
_client.QuoteUpdated += _client_QuoteUpdated;
_client.ServerDisconnected += _client_ServerDisconnected;
_client.ServerFailed += _client_ServerFailed;
_client.MtEventReceived += _client_MtEventReceived;
message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to { client.Host}:{client.Port}";
}
@@ -2435,6 +2456,45 @@ 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();
}
}
private void ReceivedOnTradeTransaction(int expertHandler, string payload)
{
var e = JsonConvert.DeserializeObject<OnTradeTransactionEvent>(payload);
OnTradeTransaction?.Invoke(this, new Mt5TradeTransactionEventArgs
{
ExpertHandle = expertHandler,
Trans = e.Trans,
Request = e.Request,
Result = e.Result
});
}
private void ReceivedOnBookEvent(int expertHandler, string payload)
{
var e = JsonConvert.DeserializeObject<OnBookEvent>(payload);
OnBookEvent?.Invoke(this, new Mt5BookEventArgs
{
ExpertHandle = expertHandler,
Symbol = e.Symbol
});
}
private void Connect(string host, int port)
{
var client = new MtClient(host, port);
@@ -2465,6 +2525,7 @@ namespace MtApi5
_client.QuoteUpdated -= _client_QuoteUpdated;
_client.ServerDisconnected -= _client_ServerDisconnected;
_client.ServerFailed -= _client_ServerFailed;
_client.MtEventReceived -= _client_MtEventReceived;
if (!failed)
{
+2 -2
View File
@@ -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.16")]
[assembly: AssemblyFileVersion("1.0.16")]
[assembly: AssemblyVersion("1.0.17")]
[assembly: AssemblyFileVersion("1.0.17")]
+14
View File
@@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace MtApi5.Requests
{
internal class IndicatorCreateRequest: RequestBase
{
public override RequestType RequestType => RequestType.IndicatorCreate;
public string Symbol { get; set; }
public ENUM_TIMEFRAMES Period { get; set; }
public ENUM_INDICATOR IndicatorType { get; set; }
public List<MqlParam> Parameters { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi5.Requests
{
internal class MarketBookGetRequest: RequestBase
{
public override RequestType RequestType => RequestType.MarketBookGet;
public string Symbol { get; set; }
}
}
+3 -1
View File
@@ -9,6 +9,8 @@ namespace MtApi5.Requests
iCustom = 2,
OrderSend = 3,
PositionOpen = 4,
OrderCheck = 5
OrderCheck = 5,
MarketBookGet = 6,
IndicatorCreate = 7
}
}
+55 -21
View File
@@ -84,6 +84,13 @@
<x:Type TypeName="mtapi5:ENUM_TIMEFRAMES"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="ENUM_INDICATOR_Key" MethodName="GetValues"
ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="mtapi5:ENUM_INDICATOR"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<Grid x:Name="_MainLayout">
@@ -305,32 +312,37 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1">
<Grid Grid.Column="1" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0">
<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" Text="Symbol Name" Margin="1"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="TimeFrame" Margin="1" HorizontalAlignment="Right"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="StartPos" Margin="1" HorizontalAlignment="Right"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Count" Margin="1" HorizontalAlignment="Right"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding TimeSeriesValues.SymbolValue}" Margin="1"/>
<ComboBox Grid.Row="1" Grid.Column="1" Margin="1"
ItemsSource="{Binding Source={StaticResource ENUM_TIMEFRAMES_Key}}"
SelectedItem="{Binding TimeSeriesValues.TimeFrame}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding TimeSeriesValues.StartPos}" Margin="1"/>
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding TimeSeriesValues.Count}" Margin="1"/>
</Grid>
<TextBox Grid.Row="0" Text="symbolName"/>
<TextBox Grid.Row="1" Grid.Column="0" Text="timeframe"/>
<TextBox Grid.Row="2" Grid.Column="0" Text="startPos"/>
<TextBox Grid.Row="3" Grid.Column="0" Text="count"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding TimeSeriesValues.SymbolValue}"/>
<ComboBox Grid.Row="1" Grid.Column="1"
ItemsSource="{Binding Source={StaticResource ENUM_TIMEFRAMES_Key}}"
SelectedItem="{Binding TimeSeriesValues.TimeFrame}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding TimeSeriesValues.StartPos}"/>
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding TimeSeriesValues.Count}"/>
<WrapPanel Grid.Row="4" Grid.ColumnSpan="2" Grid.Column="0" Margin="10">
<WrapPanel Grid.Row="1" Grid.Column="0" Margin="5">
<Button Command="{Binding CopyRatesCommand}" Margin="1"
Content="CopyRates" HorizontalAlignment="Left" />
<Button Command="{Binding CopyTimesCommand}" Margin="1"
@@ -351,11 +363,33 @@
Content="CopySpread" HorizontalAlignment="Left" />
<Button Command="{Binding CopyTicksCommand}" Margin="1"
Content="CopyTicks" HorizontalAlignment="Left" />
</WrapPanel>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Row="0" Grid.Column="0"
ItemsSource="{Binding Source={StaticResource ENUM_INDICATOR_Key}}"
SelectedItem="{Binding TimeSeriesValues.IndicatorType}"/>
<Button Grid.Row="0" Grid.Column="1" Command="{Binding IndicatorCreateCommand}" Margin="2"
Content="IndicatorCreate" HorizontalAlignment="Left" />
<Label Grid.Row="1" Grid.Column="0" Content="Indicator handle:" Margin="2"/>
<TextBox Grid.Row="1" Grid.Column="0" Margin="2" Width="30" PreviewTextInput="NumberValidationTextBox" Text="{Binding TimeSeriesValues.IndicatorHandle}"></TextBox>
<Button Grid.Row="1" Grid.Column="1" Command="{Binding IndicatorReleaseCommand}" Margin="2"
Content="IndicatorRelease" HorizontalAlignment="Left" />
</Grid>
</Grid>
<ListBox ItemsSource="{Binding TimeSeriesResults}" />
<ListBox Grid.Column="0" ItemsSource="{Binding TimeSeriesResults}" />
</Grid>
</TabItem>
+12 -17
View File
@@ -1,37 +1,32 @@
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.Text.RegularExpressions;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MtApi5TestClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
public partial class MainWindow
{
ViewModel _vm { get; set; }
private ViewModel Vm { get; }
public MainWindow()
{
InitializeComponent();
_vm = new ViewModel();
_MainLayout.DataContext = _vm;
Vm = new ViewModel();
_MainLayout.DataContext = Vm;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_vm.Close();
Vm.Close();
}
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
{
var regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}
}
}
@@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MtApi5;
using MtApi5;
using System.ComponentModel;
namespace MtApi5TestClient
{
public class TimeSeriesValueViewModel : INotifyPropertyChanged
{
private string _SymbolValue;
private string _symbolValue;
public string SymbolValue
{
get { return _SymbolValue; }
get { return _symbolValue; }
set
{
_SymbolValue = value;
_symbolValue = value;
OnPropertyChanged("SymbolValue");
}
}
@@ -24,13 +20,36 @@ namespace MtApi5TestClient
public int StartPos { get; set; }
public int Count { get; set; }
private int _indicatorHandle;
public int IndicatorHandle
{
get { return _indicatorHandle; }
set
{
_indicatorHandle = value;
OnPropertyChanged("IndicatorHandle");
}
}
private ENUM_INDICATOR _indicatorType = ENUM_INDICATOR.IND_MACD;
public ENUM_INDICATOR IndicatorType
{
get { return _indicatorType; }
set
{
_indicatorType = value;
OnPropertyChanged("IndicatorType");
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
+68 -8
View File
@@ -35,6 +35,8 @@ namespace MtApi5TestClient
public DelegateCommand CopyHighCommand { get; private set; }
public DelegateCommand CopyLowCommand { get; private set; }
public DelegateCommand CopyCloseCommand { get; private set; }
public DelegateCommand IndicatorCreateCommand { get; private set; }
public DelegateCommand IndicatorReleaseCommand { get; private set; }
public DelegateCommand CopyTickVolumeCommand { get; private set; }
public DelegateCommand CopyRealVolumeCommand { get; private set; }
@@ -172,6 +174,8 @@ namespace MtApi5TestClient
_mtApiClient.QuoteAdded += mMtApiClient_QuoteAdded;
_mtApiClient.QuoteRemoved += mMtApiClient_QuoteRemoved;
_mtApiClient.QuoteUpdated += mMtApiClient_QuoteUpdated;
_mtApiClient.OnTradeTransaction += mMtApiClient_OnTradeTransaction;
_mtApiClient.OnBookEvent += _mtApiClient_OnBookEvent;
_quotesMap = new Dictionary<string, QuoteViewModel>();
@@ -226,6 +230,8 @@ namespace MtApi5TestClient
CopyHighCommand = new DelegateCommand(ExecuteCopyHigh);
CopyLowCommand = new DelegateCommand(ExecuteCopyLow);
CopyCloseCommand = new DelegateCommand(ExecuteCopyClose);
IndicatorCreateCommand = new DelegateCommand(ExecuteIndicatorCreate);
IndicatorReleaseCommand = new DelegateCommand(ExecuteIndicatorRelease);
CopyTickVolumeCommand = new DelegateCommand(ExecuteCopyTickVolume);
CopyRealVolumeCommand = new DelegateCommand(ExecuteCopyRealVolume);
@@ -548,6 +554,48 @@ namespace MtApi5TestClient
AddLog("CopyClose: success");
}
private async void ExecuteIndicatorCreate(object o)
{
var parameters = new List<MqlParam>
{
new MqlParam
{
DataType = ENUM_DATATYPE.TYPE_INT,
IntegerValue = 12
},
new MqlParam
{
DataType = ENUM_DATATYPE.TYPE_INT,
IntegerValue = 26
},
new MqlParam
{
DataType = ENUM_DATATYPE.TYPE_INT,
IntegerValue = 9
},
new MqlParam
{
DataType = ENUM_DATATYPE.TYPE_INT,
IntegerValue = (int)ENUM_APPLIED_PRICE.PRICE_CLOSE
}
};
var retVal = await Execute(() =>
_mtApiClient.IndicatorCreate(TimeSeriesValues.SymbolValue,
TimeSeriesValues.TimeFrame, TimeSeriesValues.IndicatorType, parameters));
TimeSeriesValues.IndicatorHandle = retVal;
AddLog($"IndicatorCreate [IND_MA]: result - {retVal}");
}
private async void ExecuteIndicatorRelease(object o)
{
var indicatorHandle = TimeSeriesValues.IndicatorHandle;
var retVal = await Execute(() => _mtApiClient.IndicatorRelease(indicatorHandle));
AddLog($"IndicatorRelease [{indicatorHandle}]: result - {retVal}");
}
private async void ExecuteCopyRates(object o)
{
if (string.IsNullOrEmpty(TimeSeriesValues?.SymbolValue)) return;
@@ -807,14 +855,14 @@ namespace MtApi5TestClient
private async void ExecuteMarketBookAdd(object o)
{
var retVal = await Execute(() => _mtApiClient.MarketBookAdd("CHFJPY"));
AddLog($"MarketBookAdd(CHFJPY): result = {retVal}");
var retVal = await Execute(() => _mtApiClient.MarketBookAdd("EURUSD"));
AddLog($"MarketBookAdd(EURUSD): result = {retVal}");
}
private async void ExecuteMarketBookRelease(object o)
{
var retVal = await Execute(() => _mtApiClient.MarketBookRelease("CHFJPY"));
AddLog($"MarketBookRelease(CHFJPY): result = {retVal}");
var retVal = await Execute(() => _mtApiClient.MarketBookRelease("EURUSD"));
AddLog($"MarketBookRelease(EURUSD): result = {retVal}");
}
private async void ExecuteMarketBookGet(object o)
@@ -832,13 +880,11 @@ namespace MtApi5TestClient
return;
}
AddLog("MarketBookGet(EURUSD): success");
AddLog($"MarketBookGet(EURUSD): success. Count = {result.Length}");
for (var i = 0; i < result.Length; i++)
{
AddLog($"MarketBookGet: book[{i}].price = {result[i].price}");
AddLog($"MarketBookGet: book[{i}].price = {result[i].volume}");
AddLog($"MarketBookGet: book[{i}].price = {result[i].type}");
AddLog($"MarketBookGet: [{i}] - {result[i].price} | {result[i].volume} | {result[i].type}");
}
}
@@ -964,6 +1010,16 @@ namespace MtApi5TestClient
}
}
private void mMtApiClient_OnTradeTransaction(object sender, Mt5TradeTransactionEventArgs e)
{
AddLog($"OnTradeTransaction: ExpertHandle = {e.ExpertHandle}.{Environment.NewLine}Transaction = {e.Trans}.{Environment.NewLine}Request = {e.Request}.{Environment.NewLine}Result = {e.Result}.");
}
private void _mtApiClient_OnBookEvent(object sender, Mt5BookEventArgs e)
{
AddLog($"OnBookEvent: ExpertHandle = {e.ExpertHandle}, Symbol = {e.Symbol}");
}
private void AddQuote(Mt5Quote quote)
{
if (quote == null)
@@ -1039,6 +1095,10 @@ namespace MtApi5TestClient
{
result = func();
}
catch (ExecutionException ex)
{
AddLog($"Exception: {ex.ErrorCode} - {ex.Message}");
}
catch (Exception ex)
{
AddLog($"Exception: {ex.Message}");
BIN
View File
Binary file not shown.
+416 -161
View File
@@ -29,6 +29,8 @@
bool sendMqlBookInfoArrayResponse(int expertHandle, MqlBookInfo& values[], int size, string& err);
bool sendErrorResponse(int expertHandle, int code, string message, string& err);
bool sendEvent(int expertHandle, int eventType, string payload, string& err);
bool getCommandType(int expertHandle, int& res, string& err);
bool getIntValue(int expertHandle, int paramIndex, int& res, string& err);
bool getUIntValue(int expertHandle, int paramIndex, uint& res, string& err);
@@ -45,7 +47,6 @@ input int Port = 8228;
int ExpertHandle;
//string message;
string _error;
string _response_error;
bool isCrashed = false;
@@ -77,6 +78,32 @@ void OnTick()
if (IsTesting()) OnTimer();
}
void OnTradeTransaction(
const MqlTradeTransaction& trans, // trade transaction structure
const MqlTradeRequest& request, // request structure
const MqlTradeResult& result // result structure
)
{
#ifdef __DEBUG_LOG__
PrintFormat("%s:", __FUNCTION__);
#endif
MtOnTradeTransactionEvent* trans_event = new MtOnTradeTransactionEvent(trans, request, result);
SendMtEvent(ON_TRADE_TRANSACTION_EVENT, trans_event);
delete trans_event;
}
void OnBookEvent(const string& symbol)
{
#ifdef __DEBUG_LOG__
PrintFormat("%s: %s", __FUNCTION__, symbol);
#endif
MtOnBookEvent * book_event = new MtOnBookEvent(symbol);
SendMtEvent(ON_BOOK_EVENT, book_event);
delete book_event;
}
int preinit()
{
StringInit(_response_error,1000,0);
@@ -482,9 +509,8 @@ int executeCommand()
case 61: //MarketBookRelease
Execute_MarketBookRelease();
break;
case 62: //MarketBookGet
Execute_MarketBookGet();
break;
// case 62: //MarketBookGet
// break;
case 65: //PositionOpen
Execute_PositionOpen(false);
break;
@@ -675,7 +701,10 @@ int executeCommand()
break;
case 130: //TimeGMT
Execute_TimeGMT();
break;
break;
case 131: //IndicatorRelease
Execute_IndicatorRelease();
break;
default:
Print("Unknown command type = ", commandType);
sendVoidResponse(ExpertHandle, _response_error);
@@ -3036,38 +3065,6 @@ void Execute_MarketBookRelease()
}
}
void Execute_MarketBookGet()
{
string symbol;
StringInit(symbol, 100, 0);
if (!getStringValue(ExpertHandle, 0, symbol, _error))
{
PrintParamError("MarketBookGet", "symbol", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
MqlBookInfo book[];
bool retVal = MarketBookGet(symbol, book);
if(retVal)
{
int size = ArraySize(book);
if (!sendMqlBookInfoArrayResponse(ExpertHandle, book, size, _response_error))
{
PrintResponseError("MarketBookGet", _response_error);
}
}
else
{
if (!sendVoidResponse(ExpertHandle, _response_error))
{
PrintResponseError("MarketBookGet", _response_error);
}
}
}
void Execute_PositionOpen(bool isTradeResultRequired)
{
string symbol;
@@ -5470,6 +5467,30 @@ void Execute_TimeGMT()
PrintResponseError("TimeGMT", _response_error);
}
}
#define GET_VALUE_OR_RETURN_WITH_SENDING_ERROR(get_func, argument_id, argument, cmd_name, param_name) if (!get_func(ExpertHandle, argument_id, argument, _error)) \
{ \
PrintParamError(cmd_name, param_name, _error); \
sendErrorResponse(ExpertHandle, -1, _error, _response_error); \
return; \
} \
#define GET_INTEGER_VALUE(argument_id, argument, cmd_name, param_name) GET_VALUE_OR_RETURN_WITH_SENDING_ERROR(getIntValue, argument_id, argument, cmd_name, param_name)
void Execute_IndicatorRelease()
{
int indicator_handle;
GET_INTEGER_VALUE(0, indicator_handle, "IndicatorRelease", "indicator_handle");
#ifdef __DEBUG_LOG__
PrintFormat("%s: indicator_handle = %d", __FUNCTION__, indicator_handle);
#endif
if (!sendBooleanResponse(ExpertHandle, IndicatorRelease(indicator_handle), _error))
{
PrintResponseError("IndicatorRelease", _response_error);
}
}
void PrintParamError(string paramName)
{
@@ -5599,6 +5620,8 @@ bool OrderCloseAll()
return true;
}
//------------ Requests -------------------------------------------------------
string OnRequest(string json)
{
string response = "";
@@ -5634,6 +5657,12 @@ string OnRequest(string json)
case 5: //OrderCheck
response = ExecuteRequest_OrderCheck(jo);
break;
case 6: //MarketBookGet
response = ExecuteRequest_MarketBookGet(jo);
break;
case 7: //IndicatorCreate
response = ExecuteRequest_IndicatorCreate(jo);
break;
default:
PrintFormat("%s [WARNING]: Unknown request type %d", __FUNCTION__, requestType);
response = CreateErrorResponse(-1, "Unknown request type");
@@ -5681,17 +5710,6 @@ string CreateSuccessResponse(string responseName, JSONValue* responseBody)
return result;
}
JSONObject* Serialize(MqlTick& tick)
{
JSONObject *jo = new JSONObject();
jo.put("MtTime", new JSONNumber(tick.time));
jo.put("bid", new JSONNumber(tick.bid));
jo.put("ask", new JSONNumber(tick.ask));
jo.put("last", new JSONNumber(tick.last));
jo.put("volume", new JSONNumber(tick.volume));
return jo;
}
string ExecuteRequest_CopyTicks(JSONObject *jo)
{
if (jo.getValue("SymbolName") == NULL)
@@ -5716,10 +5734,10 @@ string ExecuteRequest_CopyTicks(JSONObject *jo)
JSONArray* jaTicks = new JSONArray();
for(int i = 0; i < received; i++)
{
jaTicks.put(i, Serialize(ticks[i]));
jaTicks.put(i, MqlTickToJson(ticks[i]));
}
return CreateSuccessResponse("Value", jaTicks);;
return CreateSuccessResponse("Value", jaTicks);
}
string ExecuteRequest_iCustom(JSONObject *jo)
@@ -5830,107 +5848,15 @@ int iCustomT(string symbol, ENUM_TIMEFRAMES timeframe, string name, T &p[], int
#define PRINT_MSG_AND_RETURN_VALUE(msg,value) PrintFormat("%s: %s",__FUNCTION__,msg);return value
#define CHECK_JSON_VALUE(jo, name_value, return_fail_result) if (jo.getValue(name_value) == NULL) { PRINT_MSG_AND_RETURN_VALUE(StringFormat("failed to get %s from JSON!", name_value), return_fail_result); }
bool JsonToMqlTradeRequest(JSONObject *jo, MqlTradeRequest& request)
{
//Action
CHECK_JSON_VALUE(jo, "Action", false);
request.action = (ENUM_TRADE_REQUEST_ACTIONS) jo.getInt("Action");
//Magic
CHECK_JSON_VALUE(jo, "Magic", false);
request.magic = jo.getLong("Magic");
//Order
CHECK_JSON_VALUE(jo, "Order", false);
request.order = jo.getLong("Magic");
//Symbol
CHECK_JSON_VALUE(jo, "Symbol", false);
StringInit(request.symbol, 100, 0);
request.symbol = jo.getString("Symbol");
//Volume
CHECK_JSON_VALUE(jo, "Volume", false);
request.volume = jo.getDouble("Volume");
//Price
CHECK_JSON_VALUE(jo, "Price", false);
request.price = jo.getDouble("Price");
//Stoplimit
CHECK_JSON_VALUE(jo, "Stoplimit", false);
request.stoplimit = jo.getDouble("Stoplimit");
//Sl
CHECK_JSON_VALUE(jo, "Sl", false);
request.sl = jo.getDouble("Sl");
//Tp
CHECK_JSON_VALUE(jo, "Tp", false);
request.tp = jo.getDouble("Tp");
//Deviation
CHECK_JSON_VALUE(jo, "Deviation", false);
request.deviation = jo.getLong("Deviation");
//Type
CHECK_JSON_VALUE(jo, "Type", false);
request.type = (ENUM_ORDER_TYPE)jo.getInt("Type");
//Type_filling
CHECK_JSON_VALUE(jo, "Type_filling", false);
request.type_filling = (ENUM_ORDER_TYPE_FILLING)jo.getInt("Type_filling");
//Type_time
CHECK_JSON_VALUE(jo, "Type_time", false);
request.type_time = (ENUM_ORDER_TYPE_TIME)jo.getInt("Type_time");
//MtExpiration
CHECK_JSON_VALUE(jo, "MtExpiration", false);
request.expiration = (datetime)jo.getInt("MtExpiration");
//Comment
if (jo.getValue("Comment") != NULL)
{
StringInit(request.comment, 1000, 0);
request.comment = jo.getString("Comment");
}
//Position
CHECK_JSON_VALUE(jo, "Position", false);
request.position = jo.getLong("Position");
//PositionBy
CHECK_JSON_VALUE(jo, "PositionBy", false);
request.position_by = jo.getLong("PositionBy");
return true;
}
JSONObject* MqlTradeResultToJson(MqlTradeResult& result)
{
JSONObject* jo = new JSONObject();
jo.put("Retcode", new JSONNumber(result.retcode));
jo.put("Deal", new JSONNumber(result.deal));
jo.put("Order", new JSONNumber(result.order));
jo.put("Volume", new JSONNumber(result.volume));
jo.put("Price", new JSONNumber(result.price));
jo.put("Bid", new JSONNumber(result.bid));
jo.put("Ask", new JSONNumber(result.ask));
jo.put("Comment", new JSONString(result.comment));
jo.put("Request_id", new JSONNumber(result.request_id));
return jo;
}
string ExecuteRequest_OrderSend(JSONObject *jo)
{
CHECK_JSON_VALUE(jo, "TradeRequest", CreateErrorResponse(-1, "Undefinded mandatory parameter TradeRequest"));
JSONObject* trade_request_jo = jo.getObject("TradeRequest");
MqlTradeRequest trade_request = {0};
JsonToMqlTradeRequest(trade_request_jo, trade_request);
bool converted = JsonToMqlTradeRequest(trade_request_jo, trade_request);
if (converted == false)
return CreateErrorResponse(-1, "Failed to parse parameter TradeRequest");
MqlTradeResult trade_result = {0};
bool ok = OrderSend(trade_request, trade_result);
@@ -5997,22 +5923,6 @@ string ExecuteRequest_PositionOpen(JSONObject *jo)
return CreateSuccessResponse("Value", result_value_jo);
}
JSONObject* MqlTradeCheckResultToJson(MqlTradeCheckResult& result)
{
JSONObject* jo = new JSONObject();
jo.put("Retcode", new JSONNumber(result.retcode));
jo.put("Balance", new JSONNumber(result.balance));
jo.put("Equity", new JSONNumber(result.equity));
jo.put("Profit", new JSONNumber(result.profit));
jo.put("Margin", new JSONNumber(result.margin));
jo.put("Margin_free", new JSONNumber(result.margin_free));
jo.put("Margin_level", new JSONNumber(result.margin_level));
jo.put("Comment", new JSONString(result.comment));
return jo;
}
string ExecuteRequest_OrderCheck(JSONObject *jo)
{
CHECK_JSON_VALUE(jo, "TradeRequest", CreateErrorResponse(-1, "Undefinded mandatory parameter TradeRequest"));
@@ -6033,4 +5943,349 @@ string ExecuteRequest_OrderCheck(JSONObject *jo)
result_value_jo.put("TradeCheckResult", MqlTradeCheckResultToJson(trade_check_result));
return CreateSuccessResponse("Value", result_value_jo);
}
JSONObject* MqlBookInfoToJson(MqlBookInfo& info)
{
JSONObject *jo = new JSONObject();
jo.put("type", new JSONNumber((int)info.type));
jo.put("price", new JSONNumber(info.price));
jo.put("volume", new JSONNumber(info.volume));
return jo;
}
string ExecuteRequest_MarketBookGet(JSONObject *jo)
{
CHECK_JSON_VALUE(jo, "Symbol", CreateErrorResponse(-1, "Undefinded mandatory parameter Symbol"));
string symbol = jo.getString("Symbol");
MqlBookInfo info_array[];
bool ok = MarketBookGet(symbol, info_array);
#ifdef __DEBUG_LOG__
PrintFormat("%s: return value = %s.", __FUNCTION__, ok ? "true" : "false");
#endif
if (!ok)
return CreateErrorResponse(GetLastError(), "MarketBookGet failed");
int size = ArraySize(info_array);
JSONArray* book_ja = new JSONArray();
for(int i = 0; i < size; i++)
{
book_ja.put(i, MqlBookInfoToJson(info_array[i]));
}
#ifdef __DEBUG_LOG__
PrintFormat("%s: array size = %d.", __FUNCTION__, size);
#endif
return CreateSuccessResponse("Value", book_ja);
}
string ExecuteRequest_IndicatorCreate(JSONObject *jo)
{
//Symbol
string symbol;
if (jo.getValue("Symbol") != NULL)
{
symbol = jo.getString("Symbol");
}
CHECK_JSON_VALUE(jo, "Period", CreateErrorResponse(-1, "Undefinded mandatory parameter Period"));
ENUM_TIMEFRAMES period = (ENUM_TIMEFRAMES) jo.getInt("Period");
CHECK_JSON_VALUE(jo, "IndicatorType", CreateErrorResponse(-1, "Undefinded mandatory parameter IndicatorType"));
ENUM_INDICATOR indicator_type = (ENUM_INDICATOR) jo.getInt("IndicatorType");
int indicator_handle = -1;
if (jo.getValue("Parameters") != NULL)
{
JSONArray parameters_ja = jo.getArray("Parameters");
int size = parameters_ja.size();
if (size > 0)
{
MqlParam parameters[];
ArrayResize(parameters, size);
for (int i = 0; i < size; i++)
{
JSONObject param_jo = parameters_ja.getObject(i);
parameters[i].type = (ENUM_DATATYPE)param_jo.getInt("DataType");
if (param_jo.getValue("IntegerValue") != NULL)
{
parameters[i].integer_value = param_jo.getLong("IntegerValue");
}
if (param_jo.getValue("DoubleValue") != NULL)
{
parameters[i].double_value = param_jo.getDouble("DoubleValue");
}
if (param_jo.getValue("StringValue") != NULL)
{
parameters[i].string_value = param_jo.getString("StringValue");
}
}
#ifdef __DEBUG_LOG__
PrintFormat("%s: symbol = %s, period = %d, indicator_type = %d, size = %d.", __FUNCTION__, symbol, period, indicator_type, size);
#endif
indicator_handle = IndicatorCreate(symbol, period, indicator_type, size, parameters);
}
}
else
{
#ifdef __DEBUG_LOG__
PrintFormat("%s: symbol = %s, period = %d, indicator_type = %d.", __FUNCTION__, symbol, period, indicator_type);
#endif
indicator_handle = IndicatorCreate(symbol, period, indicator_type);
}
#ifdef __DEBUG_LOG__
PrintFormat("%s: result indicator handle = %d", __FUNCTION__, indicator_handle);
#endif
return CreateSuccessResponse("Value", new JSONNumber(indicator_handle));
}
//------------ Events -------------------------------------------------------
enum MtEventTypes
{
ON_TRADE_TRANSACTION_EVENT = 1,
ON_BOOK_EVENT = 2
};
class MtEvent
{
public:
virtual JSONObject* CreateJson() = 0;
};
class MtOnTradeTransactionEvent : public MtEvent
{
public:
MtOnTradeTransactionEvent(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result)
{
_trans = trans;
_request = request;
_result = result;
}
virtual JSONObject* CreateJson()
{
JSONObject *jo = new JSONObject();
jo.put("Trans", MqlTradeTransactionToJson(_trans));
jo.put("Request", MqlTradeRequestToJson(_request));
jo.put("Result", MqlTradeResultToJson(_result));
return jo;
}
private:
MqlTradeTransaction _trans;
MqlTradeRequest _request;
MqlTradeResult _result;
};
class MtOnBookEvent : public MtEvent
{
public:
MtOnBookEvent(const string& symbol)
{
_symbol = symbol;
}
virtual JSONObject* CreateJson()
{
JSONObject *jo = new JSONObject();
jo.put("Symbol", new JSONString(_symbol));
return jo;
}
private:
string _symbol;
};
void SendMtEvent(MtEventTypes eventType, MtEvent* mtEvent)
{
#ifdef __DEBUG_LOG__
PrintFormat("%s: eventType = %d", __FUNCTION__, eventType);
#endif
JSONObject* json = mtEvent.CreateJson();
if (sendEvent(ExpertHandle, (int)eventType, json.toString(), _error))
{
#ifdef __DEBUG_LOG__
PrintFormat("%s: payload = %s", __FUNCTION__, json.toString());
#endif
}
else
{
PrintFormat("[ERROR] SendMtEvent: %s", _error);
}
delete json;
}
//-------------JSON converters -----------------------------------------
bool JsonToMqlTradeRequest(JSONObject *jo, MqlTradeRequest& request)
{
//Action
CHECK_JSON_VALUE(jo, "Action", false);
request.action = (ENUM_TRADE_REQUEST_ACTIONS) jo.getInt("Action");
//Magic
CHECK_JSON_VALUE(jo, "Magic", false);
request.magic = jo.getLong("Magic");
//Order
CHECK_JSON_VALUE(jo, "Order", false);
request.order = jo.getLong("Magic");
//Symbol
CHECK_JSON_VALUE(jo, "Symbol", false);
StringInit(request.symbol, 100, 0);
request.symbol = jo.getString("Symbol");
//Volume
CHECK_JSON_VALUE(jo, "Volume", false);
request.volume = jo.getDouble("Volume");
//Price
CHECK_JSON_VALUE(jo, "Price", false);
request.price = jo.getDouble("Price");
//Stoplimit
CHECK_JSON_VALUE(jo, "Stoplimit", false);
request.stoplimit = jo.getDouble("Stoplimit");
//Sl
CHECK_JSON_VALUE(jo, "Sl", false);
request.sl = jo.getDouble("Sl");
//Tp
CHECK_JSON_VALUE(jo, "Tp", false);
request.tp = jo.getDouble("Tp");
//Deviation
CHECK_JSON_VALUE(jo, "Deviation", false);
request.deviation = jo.getLong("Deviation");
//Type
CHECK_JSON_VALUE(jo, "Type", false);
request.type = (ENUM_ORDER_TYPE)jo.getInt("Type");
//Type_filling
CHECK_JSON_VALUE(jo, "Type_filling", false);
request.type_filling = (ENUM_ORDER_TYPE_FILLING)jo.getInt("Type_filling");
//Type_time
CHECK_JSON_VALUE(jo, "Type_time", false);
request.type_time = (ENUM_ORDER_TYPE_TIME)jo.getInt("Type_time");
//Expiration
CHECK_JSON_VALUE(jo, "MtExpiration", false);
request.expiration = (datetime)jo.getInt("MtExpiration");
//Comment
if (jo.getValue("Comment") != NULL)
{
StringInit(request.comment, 1000, 0);
request.comment = jo.getString("Comment");
}
//Position
CHECK_JSON_VALUE(jo, "Position", false);
request.position = jo.getLong("Position");
//PositionBy
CHECK_JSON_VALUE(jo, "PositionBy", false);
request.position_by = jo.getLong("PositionBy");
return true;
}
JSONObject* MqlTickToJson(MqlTick& tick)
{
JSONObject *jo = new JSONObject();
jo.put("MtTime", new JSONNumber(tick.time));
jo.put("bid", new JSONNumber(tick.bid));
jo.put("ask", new JSONNumber(tick.ask));
jo.put("last", new JSONNumber(tick.last));
jo.put("volume", new JSONNumber(tick.volume));
return jo;
}
JSONObject* MqlTradeResultToJson(MqlTradeResult& result)
{
JSONObject* jo = new JSONObject();
jo.put("Retcode", new JSONNumber(result.retcode));
jo.put("Deal", new JSONNumber(result.deal));
jo.put("Order", new JSONNumber(result.order));
jo.put("Volume", new JSONNumber(result.volume));
jo.put("Price", new JSONNumber(result.price));
jo.put("Bid", new JSONNumber(result.bid));
jo.put("Ask", new JSONNumber(result.ask));
jo.put("Comment", new JSONString(result.comment));
jo.put("Request_id", new JSONNumber(result.request_id));
return jo;
}
JSONObject* MqlTradeCheckResultToJson(MqlTradeCheckResult& result)
{
JSONObject* jo = new JSONObject();
jo.put("Retcode", new JSONNumber(result.retcode));
jo.put("Balance", new JSONNumber(result.balance));
jo.put("Equity", new JSONNumber(result.equity));
jo.put("Profit", new JSONNumber(result.profit));
jo.put("Margin", new JSONNumber(result.margin));
jo.put("Margin_free", new JSONNumber(result.margin_free));
jo.put("Margin_level", new JSONNumber(result.margin_level));
jo.put("Comment", new JSONString(result.comment));
return jo;
}
JSONObject* MqlTradeTransactionToJson(MqlTradeTransaction& trans)
{
JSONObject *jo = new JSONObject();
jo.put("Deal", new JSONNumber(trans.deal));
jo.put("Order", new JSONNumber(trans.order));
jo.put("Symbol", new JSONString(trans.symbol));
jo.put("Type", new JSONNumber((int)trans.type));
jo.put("OrderType", new JSONNumber((int)trans.order_type));
jo.put("OrderState", new JSONNumber((int)trans.order_state));
jo.put("DealType", new JSONNumber((int)trans.deal_type));
jo.put("TimeType", new JSONNumber((int)trans.time_type));
jo.put("MtTimeExpiration", new JSONNumber((int)trans.time_expiration));
jo.put("Price", new JSONNumber(trans.price));
jo.put("PriceTrigger", new JSONNumber(trans.price_trigger));
jo.put("PriceSl", new JSONNumber(trans.price_sl));
jo.put("PriceTp", new JSONNumber(trans.price_tp));
jo.put("Volume", new JSONNumber(trans.volume));
jo.put("Position", new JSONNumber(trans.position));
jo.put("PositionBy", new JSONNumber(trans.position_by));
return jo;
}
JSONObject* MqlTradeRequestToJson(MqlTradeRequest& request)
{
JSONObject *jo = new JSONObject();
jo.put("Action", new JSONNumber((int)request.action));
jo.put("Magic", new JSONNumber(request.magic));
jo.put("Order", new JSONNumber(request.order));
jo.put("Symbol", new JSONString(request.symbol));
jo.put("Volume", new JSONNumber(request.volume));
jo.put("Price", new JSONNumber(request.price));
jo.put("Stoplimit", new JSONNumber(request.stoplimit));
jo.put("Sl", new JSONNumber(request.sl));
jo.put("Tp", new JSONNumber(request.tp));
jo.put("Deviation", new JSONNumber(request.deviation));
jo.put("Type", new JSONNumber((int)request.type));
jo.put("Type_filling", new JSONNumber((int)request.type_filling));
jo.put("Type_time", new JSONNumber((int)request.type_time));
jo.put("MtExpiration", new JSONNumber((int)request.expiration));
jo.put("Comment", new JSONString(request.comment));
return jo;
}
+1 -1
View File
@@ -257,7 +257,7 @@ public:
{
return (string)_long;
} else {
return (string)_dbl;
return (_dbl!=0) ? (string)_dbl : "0";
}
}
};