mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-15 11:48:09 +00:00
Merge branch 'dev'
This commit is contained in:
@@ -4,15 +4,17 @@ namespace MtApi5
|
|||||||
{
|
{
|
||||||
public class Mt5TimeBarArgs: EventArgs
|
public class Mt5TimeBarArgs: EventArgs
|
||||||
{
|
{
|
||||||
internal Mt5TimeBarArgs(int expertHandle, string symbol, MqlRates rates)
|
internal Mt5TimeBarArgs(int expertHandle, string symbol, ENUM_TIMEFRAMES timeframe, MqlRates rates)
|
||||||
{
|
{
|
||||||
ExpertHandle = expertHandle;
|
ExpertHandle = expertHandle;
|
||||||
Rates = rates;
|
Rates = rates;
|
||||||
Symbol = symbol;
|
Symbol = symbol;
|
||||||
|
Timeframe = timeframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExpertHandle { get; }
|
public int ExpertHandle { get; }
|
||||||
public string Symbol { get; }
|
public string Symbol { get; }
|
||||||
|
public ENUM_TIMEFRAMES Timeframe { get; }
|
||||||
public MqlRates Rates { get; }
|
public MqlRates Rates { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-2
@@ -32,11 +32,24 @@ namespace MtApi5
|
|||||||
|
|
||||||
private HashSet<int> _experts = [];
|
private HashSet<int> _experts = [];
|
||||||
private Dictionary<int, Mt5Quote> _quotes = [];
|
private Dictionary<int, Mt5Quote> _quotes = [];
|
||||||
|
private volatile int _command_timeout = 30000; // 30 seconds
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
private IMtLogger Log { get; }
|
private IMtLogger Log { get; }
|
||||||
|
|
||||||
|
// Time in milliseconds to wait for a response from MetaTrader for a command. Default is 30 seconds.
|
||||||
|
public int CommandTimeout
|
||||||
|
{
|
||||||
|
get => _command_timeout;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
throw new ArgumentException("Command timeout must be greater than zero.");
|
||||||
|
_command_timeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MtApi5Client(IMtLogger? log = null)
|
public MtApi5Client(IMtLogger? log = null)
|
||||||
{
|
{
|
||||||
_mtEventHandlers[Mt5EventTypes.OnBookEvent] = ReceivedOnBookEvent;
|
_mtEventHandlers[Mt5EventTypes.OnBookEvent] = ReceivedOnBookEvent;
|
||||||
@@ -3533,7 +3546,7 @@ namespace MtApi5
|
|||||||
var e = JsonConvert.DeserializeObject<OnLastTimeBarEvent>(payload);
|
var e = JsonConvert.DeserializeObject<OnLastTimeBarEvent>(payload);
|
||||||
if (e == null || string.IsNullOrEmpty(e.Instrument) || e.Rates == null)
|
if (e == null || string.IsNullOrEmpty(e.Instrument) || e.Rates == null)
|
||||||
return;
|
return;
|
||||||
OnLastTimeBar?.Invoke(this, new Mt5TimeBarArgs(expertHandle, e.Instrument, e.Rates));
|
OnLastTimeBar?.Invoke(this, new Mt5TimeBarArgs(expertHandle, e.Instrument, e.Timeframe, e.Rates));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReceivedOnLockTicksEvent(int expertHandle, string payload)
|
private void ReceivedOnLockTicksEvent(int expertHandle, string payload)
|
||||||
@@ -3588,7 +3601,7 @@ namespace MtApi5
|
|||||||
var payloadJson = payload == null ? string.Empty : JsonConvert.SerializeObject(payload);
|
var payloadJson = payload == null ? string.Empty : JsonConvert.SerializeObject(payload);
|
||||||
Log.Debug($"SendCommand: sending '{payloadJson}' ...");
|
Log.Debug($"SendCommand: sending '{payloadJson}' ...");
|
||||||
|
|
||||||
var responseJson = client.SendCommand(expertHandle, (int)commandType, payloadJson);
|
var responseJson = client.SendCommand(expertHandle, (int)commandType, payloadJson, CommandTimeout);
|
||||||
|
|
||||||
Log.Debug($"SendCommand: received response JSON [{responseJson}]");
|
Log.Debug($"SendCommand: received response JSON [{responseJson}]");
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
{
|
{
|
||||||
public MqlRates? Rates { get; set; }
|
public MqlRates? Rates { get; set; }
|
||||||
public string? Instrument { get; set; }
|
public string? Instrument { get; set; }
|
||||||
|
public ENUM_TIMEFRAMES Timeframe { get; set; }
|
||||||
public int ExpertHandle { get; set; }
|
public int ExpertHandle { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ namespace MtClient
|
|||||||
logger_.Debug($"MtRpcClient.Disconnect: success");
|
logger_.Debug($"MtRpcClient.Disconnect: success");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? SendCommand(int expertHandle, int commandType, string payload)
|
public string? SendCommand(int expertHandle, int commandType, string payload, int timeout = 10000) // 10 sec
|
||||||
{
|
{
|
||||||
CommandTask<string> commandTask = new();
|
CommandTask<string> commandTask = new();
|
||||||
int commandId;
|
int commandId;
|
||||||
@@ -78,7 +78,7 @@ namespace MtClient
|
|||||||
MtCommand command = new(expertHandle, commandType, commandId, payload);
|
MtCommand command = new(expertHandle, commandType, commandId, payload);
|
||||||
Send(command);
|
Send(command);
|
||||||
|
|
||||||
var response = commandTask.WaitResponse(10000); // 10 sec
|
var response = commandTask.WaitResponse(timeout);
|
||||||
lock (tasks_)
|
lock (tasks_)
|
||||||
{
|
{
|
||||||
tasks_.Remove(commandId);
|
tasks_.Remove(commandId);
|
||||||
|
|||||||
@@ -167,6 +167,7 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Label Grid.Row="0" Content="Quotes" Background="LightYellow" />
|
<Label Grid.Row="0" Content="Quotes" Background="LightYellow" />
|
||||||
<ListView Grid.Row="1" Margin="2"
|
<ListView Grid.Row="1" Margin="2"
|
||||||
@@ -183,6 +184,11 @@
|
|||||||
</ListView.View>
|
</ListView.View>
|
||||||
</ListView>
|
</ListView>
|
||||||
<Button Grid.Row="2" Content="Refresh Quotes" Margin="2" Command="{Binding RefreshQuotesCommand}"/>
|
<Button Grid.Row="2" Content="Refresh Quotes" Margin="2" Command="{Binding RefreshQuotesCommand}"/>
|
||||||
|
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Left" Margin="2">
|
||||||
|
<TextBlock Text="Command timeout (ms):" VerticalAlignment="Center" Margin="2"/>
|
||||||
|
<TextBox Text="{Binding CommandTimeout}" Width="100" Margin="2"/>
|
||||||
|
<Button Content="Apply" Margin="2" Command="{Binding TimeoutApplyCommand}"/>
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -163,6 +163,8 @@ namespace MtApi5TestClient
|
|||||||
|
|
||||||
public DelegateCommand GetSymbolsCommand { get; private set; }
|
public DelegateCommand GetSymbolsCommand { get; private set; }
|
||||||
public DelegateCommand RefreshQuotesCommand { get; private set; }
|
public DelegateCommand RefreshQuotesCommand { get; private set; }
|
||||||
|
|
||||||
|
public DelegateCommand TimeoutApplyCommand { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -210,6 +212,17 @@ namespace MtApi5TestClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int _command_timeout;
|
||||||
|
public int CommandTimeout
|
||||||
|
{
|
||||||
|
get { return _command_timeout; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_command_timeout = value;
|
||||||
|
OnPropertyChanged("CommandTimeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ObservableCollection<QuoteViewModel> Quotes { get; } = new ObservableCollection<QuoteViewModel>();
|
public ObservableCollection<QuoteViewModel> Quotes { get; } = new ObservableCollection<QuoteViewModel>();
|
||||||
|
|
||||||
private QuoteViewModel _selectedQuote;
|
private QuoteViewModel _selectedQuote;
|
||||||
@@ -350,6 +363,7 @@ namespace MtApi5TestClient
|
|||||||
ConnectionState = _mtApiClient.ConnectionState;
|
ConnectionState = _mtApiClient.ConnectionState;
|
||||||
ConnectionMessage = "Disconnected";
|
ConnectionMessage = "Disconnected";
|
||||||
Port = 8228; //default local port
|
Port = 8228; //default local port
|
||||||
|
CommandTimeout = _mtApiClient.CommandTimeout;
|
||||||
|
|
||||||
InitCommands();
|
InitCommands();
|
||||||
|
|
||||||
@@ -494,6 +508,8 @@ namespace MtApi5TestClient
|
|||||||
|
|
||||||
GetSymbolsCommand = new DelegateCommand(ExecuteGetSymbols);
|
GetSymbolsCommand = new DelegateCommand(ExecuteGetSymbols);
|
||||||
RefreshQuotesCommand = new DelegateCommand(ExecuteRefreshQuotes);
|
RefreshQuotesCommand = new DelegateCommand(ExecuteRefreshQuotes);
|
||||||
|
|
||||||
|
TimeoutApplyCommand = new DelegateCommand(ExecuteTimeoutApply);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanExecuteConnect(object o)
|
private bool CanExecuteConnect(object o)
|
||||||
@@ -1773,6 +1789,12 @@ namespace MtApi5TestClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExecuteTimeoutApply(object o)
|
||||||
|
{
|
||||||
|
_mtApiClient.CommandTimeout = CommandTimeout;
|
||||||
|
AddLog($"TimeoutApply: timeout = {CommandTimeout} milliseconds");
|
||||||
|
}
|
||||||
|
|
||||||
private static void RunOnUiThread(Action action)
|
private static void RunOnUiThread(Action action)
|
||||||
{
|
{
|
||||||
Application.Current?.Dispatcher.Invoke(action);
|
Application.Current?.Dispatcher.Invoke(action);
|
||||||
@@ -1851,7 +1873,7 @@ namespace MtApi5TestClient
|
|||||||
|
|
||||||
private void _mtApiClient_OnLastTimeBar(object sender, Mt5TimeBarArgs e)
|
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}");
|
AddLog($"OnLastTimeBarEvent: ExpertHandle = {e.ExpertHandle}, Symbol = {e.Symbol}, Timeframe = {e.Timeframe}, 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)
|
private void _mtApiClient_OnLockTicks(object sender, Mt5LockTicksEventArgs e)
|
||||||
|
|||||||
Binary file not shown.
+6
-2
@@ -82,7 +82,7 @@ void OnTick()
|
|||||||
MqlRates rates_array[];
|
MqlRates rates_array[];
|
||||||
CopyRates(symbol, Period(), 1, 1, rates_array);
|
CopyRates(symbol, Period(), 1, 1, rates_array);
|
||||||
|
|
||||||
MtTimeBarEvent time_bar(symbol, rates_array[0]);
|
MtTimeBarEvent time_bar(symbol, (int)Period(), rates_array[0]);
|
||||||
SendMtEvent(ON_LAST_TIME_BAR_EVENT, time_bar);
|
SendMtEvent(ON_LAST_TIME_BAR_EVENT, time_bar);
|
||||||
}
|
}
|
||||||
lastbar_time_changed = true;
|
lastbar_time_changed = true;
|
||||||
@@ -2960,6 +2960,7 @@ string Execute_UnlockTicks()
|
|||||||
return CreateErrorResponse(-1, "UnlockTicks can be used only for backtesting");
|
return CreateErrorResponse(-1, "UnlockTicks can be used only for backtesting");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_is_ticks_locked = false;
|
||||||
return CreateSuccessResponse();
|
return CreateSuccessResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3662,9 +3663,10 @@ private:
|
|||||||
class MtTimeBarEvent: public MtObject
|
class MtTimeBarEvent: public MtObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MtTimeBarEvent(string symbol, const MqlRates& rates)
|
MtTimeBarEvent(string symbol, int timeframe, const MqlRates& rates)
|
||||||
{
|
{
|
||||||
_symbol = symbol;
|
_symbol = symbol;
|
||||||
|
_timeframe = timeframe;
|
||||||
_rates = rates;
|
_rates = rates;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3673,12 +3675,14 @@ public:
|
|||||||
JSONObject *jo = new JSONObject();
|
JSONObject *jo = new JSONObject();
|
||||||
jo.put("Rates", MqlRatesToJson(_rates));
|
jo.put("Rates", MqlRatesToJson(_rates));
|
||||||
jo.put("Instrument", new JSONString(_symbol));
|
jo.put("Instrument", new JSONString(_symbol));
|
||||||
|
jo.put("Timeframe", new JSONNumber(_timeframe));
|
||||||
jo.put("ExpertHandle", new JSONNumber(ExpertHandle));
|
jo.put("ExpertHandle", new JSONNumber(ExpertHandle));
|
||||||
return jo;
|
return jo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string _symbol;
|
string _symbol;
|
||||||
|
int _timeframe;
|
||||||
MqlRates _rates;
|
MqlRates _rates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user