Compare commits

...

7 Commits

Author SHA1 Message Date
Viacheslav Demydiuk f376b4e0e5 MtApi (MT4) version 1.0.41 2020-08-26 22:59:21 +03:00
Viacheslav Demydiuk fc54b5dd4a Updated test application (MT5) to perform testing functions iBullsPower, iBearsPower, BarsCalculated, CopyBuffer. 2020-08-26 21:06:26 +03:00
Viacheslav Demydiuk dd05804082 Issue #201: call iBullsPower instead iBearsPower in MQL 2020-08-26 17:53:31 +03:00
Viacheslav Demydiuk 4349eb3538 Issue #186: Implemented function PositionClosePartial 2020-08-24 22:43:20 +03:00
Vyacheslav Demidyuk e0daf9a82e Merge pull request #198 from KptKuck/dev
Add switchable Events / fix typo in AddLog()
2020-08-09 11:00:55 +03:00
Christian_X3 3997b6df74 add switchable Events
The function SendMtEvent requires a lot of computing time. To improve the speed of the tester, the events can now be switched off individually
2020-06-18 05:57:05 +02:00
Christian_X3 abfe1a281a fix typo in Addlog() 2020-06-18 05:03:21 +02:00
7 changed files with 246 additions and 56 deletions
+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.40.0")]
[assembly: AssemblyFileVersion("1.0.40.0")]
[assembly: AssemblyVersion("1.0.41.0")]
[assembly: AssemblyFileVersion("1.0.41.0")]
+2
View File
@@ -102,6 +102,8 @@ namespace MtApi5
PositionClose = 64,
PositionOpen = 65,
PositionModify = 6066,
PositionClosePartial_bySymbol = 6067,
PositionClosePartial_byTicket = 6068,
//PositionOpenWithResult = 1065,
//Backtesting
+28
View File
@@ -655,6 +655,34 @@ namespace MtApi5
{
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);
}
#endregion
#region Account Information functions
+10 -5
View File
@@ -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>
@@ -498,11 +508,6 @@
</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>
+73 -16
View File
@@ -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; }
@@ -75,8 +80,6 @@ namespace MtApi5TestClient
public DelegateCommand AlertCommand { get; private set; }
public DelegateCommand TesterStopCommand { get; private set; }
public DelegateCommand iCustomCommand { get; private set; }
public DelegateCommand TimeCurrentCommand { get; private set; }
public DelegateCommand ChartOpenCommand { get; private set; }
@@ -354,6 +357,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);
@@ -385,8 +393,6 @@ namespace MtApi5TestClient
ResetLastErrorCommand = new DelegateCommand(ExecuteResetLastError);
TesterStopCommand = new DelegateCommand(ExecuteTesterStop);
iCustomCommand = new DelegateCommand(ExecuteICustom);
ChartOpenCommand = new DelegateCommand(ExecuteChartOpen);
ChartTimePriceToXYCommand = new DelegateCommand(ExecuteChartTimePriceToXY);
ChartXYToTimePriceCommand = new DelegateCommand(ExecuteChartXYToTimePrice);
@@ -806,6 +812,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;
@@ -1177,17 +1245,6 @@ namespace MtApi5TestClient
AddLog("TesterStop: executed.");
}
private async void ExecuteICustom(object o)
{
const string symbol = "EURUSD";
const ENUM_TIMEFRAMES timeframe = ENUM_TIMEFRAMES.PERIOD_H1;
const string name = @"Examples\Custom Moving Average";
int[] parameters = { 0, 21, (int)ENUM_APPLIED_PRICE.PRICE_CLOSE };
var retVal = await Execute(() => _mtApiClient.iCustom(symbol, timeframe, name, parameters));
AddLog($"Custom Moving Average: result - {retVal}");
}
private async void ExecuteTimeCurrent(object o)
{
var retVal = await Execute(() => _mtApiClient.TimeCurrent());
@@ -1676,7 +1733,7 @@ namespace MtApi5TestClient
private void _mtApiClient_OnLastTimeBar(object sender, Mt5TimeBarArgs e)
{
AddLog($"OnBookEvent: 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}");
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)
BIN
View File
Binary file not shown.
+131 -33
View File
@@ -50,6 +50,12 @@ enum LockTickType
input int Port = 8228;
input LockTickType BacktestingLockTicks = NO_LOCK;
input group "Disable Events "
input bool Enable_OnBookEvent = true;
input bool Enable_OnTickEvent = true;
input bool Enable_OnTradeTransactionEvent = true;
input bool Enable_OnLastBarEvent = true;
int ExpertHandle;
@@ -89,27 +95,31 @@ void OnTick()
long lastbar_time = SeriesInfoInteger(symbol, Period(), SERIES_LASTBAR_DATE);
if (_last_bar_open_time != lastbar_time)
{
if (_last_bar_open_time != 0)
if (_last_bar_open_time != 0 )
{
MqlRates rates_array[];
CopyRates(symbol, Period(), 1, 1, rates_array);
if(Enable_OnLastBarEvent)
{
MqlRates rates_array[];
CopyRates(symbol, Period(), 1, 1, rates_array);
MtTimeBarEvent* time_bar = new MtTimeBarEvent(symbol, rates_array[0]);
SendMtEvent(ON_LAST_TIME_BAR_EVENT, time_bar);
delete time_bar;
lastbar_time_changed = true;
MtTimeBarEvent* time_bar = new MtTimeBarEvent(symbol, rates_array[0]);
SendMtEvent(ON_LAST_TIME_BAR_EVENT, time_bar);
delete time_bar;
}
lastbar_time_changed = true;
}
_last_bar_open_time = lastbar_time;
}
MqlTick last_tick;
SymbolInfoTick(Symbol(),last_tick);
if (Enable_OnTickEvent)
{
MqlTick last_tick;
SymbolInfoTick(Symbol(),last_tick);
MtOnTickEvent * tick_event = new MtOnTickEvent(symbol, last_tick);
SendMtEvent(ON_TICK_EVENT, tick_event);
delete tick_event;
MtOnTickEvent * tick_event = new MtOnTickEvent(symbol, last_tick);
SendMtEvent(ON_TICK_EVENT, tick_event);
delete tick_event;
}
if (IsTesting())
{
@@ -132,26 +142,33 @@ void OnTradeTransaction(
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;
}
{
if(!Enable_OnTradeTransactionEvent) return;
#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
{
if(!Enable_OnBookEvent) return;
#ifdef __DEBUG_LOG__
PrintFormat("%s: %s", __FUNCTION__, symbol);
#endif
MtOnBookEvent * book_event = new MtOnBookEvent(symbol);
SendMtEvent(ON_BOOK_EVENT, book_event);
delete book_event;
}
MtOnBookEvent * book_event = new MtOnBookEvent(symbol);
SendMtEvent(ON_BOOK_EVENT, book_event);
delete book_event;
}
int preinit()
{
@@ -555,6 +572,12 @@ int executeCommand()
case 6066: //PositionModify
Execute_PositionModify();
break;
case 6067: //PositionClosePartial_bySymbol
Execute_PositionClosePartial_bySymbol();
break;
case 6068: //Execute_PositionClosePartial_byTicket
Execute_PositionClosePartial_byTicket();
break;
case 66: //BacktestingReady
Execute_BacktestingReady();
break;
@@ -3296,6 +3319,80 @@ void Execute_PositionModify()
}
}
void Execute_PositionClosePartial_bySymbol()
{
string symbol;
double volume;
ulong deviation;
if (!getStringValue(ExpertHandle, 0, symbol, _error))
{
PrintParamError("PositionClosePartial (1)", "symbol", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
if (!getDoubleValue(ExpertHandle, 1, volume, _error))
{
PrintParamError("PositionClosePartial (1)", "volume", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
if (!getULongValue(ExpertHandle, 2, deviation, _error))
{
PrintParamError("PositionClosePartial (1)", "deviation", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
CTrade trade;
bool ok = trade.PositionClosePartial(symbol, volume, deviation);
#ifdef __DEBUG_LOG__
Print("command PositionClosePartial (1): result = ", ok);
#endif
if (!sendBooleanResponse(ExpertHandle, ok, _response_error))
{
PrintResponseError("PositionClosePartial (1)", _response_error);
}
}
void Execute_PositionClosePartial_byTicket()
{
ulong ticket;
double volume;
ulong deviation;
if (!getULongValue(ExpertHandle, 0, ticket, _error))
{
PrintParamError("PositionClosePartial (2)", "ticket", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
if (!getDoubleValue(ExpertHandle, 1, volume, _error))
{
PrintParamError("PositionClosePartial (2)", "volume", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
if (!getULongValue(ExpertHandle, 2, deviation, _error))
{
PrintParamError("PositionClosePartial (2)", "deviation", _error);
sendErrorResponse(ExpertHandle, -1, _error, _response_error);
return;
}
CTrade trade;
bool ok = trade.PositionClosePartial(ticket, volume, deviation);
#ifdef __DEBUG_LOG__
Print("command PositionClosePartial (2): result = ", ok);
#endif
if (!sendBooleanResponse(ExpertHandle, ok, _response_error))
{
PrintResponseError("PositionClosePartial (2)", _response_error);
}
}
void Execute_PositionOpen(bool isTradeResultRequired)
{
string symbol;
@@ -4457,7 +4554,7 @@ void Execute_iBullsPower()
}
if (!sendIntResponse(ExpertHandle,
iBearsPower(symbol, (ENUM_TIMEFRAMES)period, ma_period),
iBullsPower(symbol, (ENUM_TIMEFRAMES)period, ma_period),
_error))
{
PrintResponseError("iBullsPower", _response_error);
@@ -7521,6 +7618,7 @@ void SendMtEvent(MtEventTypes eventType, MtEvent* mtEvent)
if (sendEvent(ExpertHandle, (int)eventType, json.toString(), _error))
{
#ifdef __DEBUG_LOG__
PrintFormat("%s: event = %s", __FUNCTION__, EnumToString(eventType));
PrintFormat("%s: payload = %s", __FUNCTION__, json.toString());
#endif
}