mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-19 21:58:10 +00:00
Issue #122: Implemented UnlockTicks function in MtApi (MT5)
This commit is contained in:
+41
-12
@@ -4,35 +4,51 @@ namespace MTApiService
|
|||||||
{
|
{
|
||||||
public class Mt5Expert : MtExpert
|
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 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) :
|
public Mt5Expert(int handle, string symbol, double bid, double ask, IMetaTraderHandler mtHandler, bool isTestMode) :
|
||||||
base(handle, symbol, bid, ask, mtHandler)
|
base(handle, symbol, bid, ask, mtHandler)
|
||||||
{
|
{
|
||||||
IsTestMode = isTestMode;
|
IsTestMode = isTestMode;
|
||||||
_stopTimer.Interval = StopExpertInterval;
|
|
||||||
_stopTimer.Elapsed += _stopTimer_Elapsed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsTestMode { get; }
|
public bool IsTestMode { get; }
|
||||||
|
|
||||||
public override void UpdateQuote(MtQuote quote)
|
public override int GetCommandType()
|
||||||
{
|
{
|
||||||
Log.Debug("UpdateQuote: begin.");
|
Log.Debug("GetCommandType: called.");
|
||||||
|
|
||||||
base.UpdateQuote(quote);
|
|
||||||
|
|
||||||
if (IsTestMode)
|
if (IsTestMode)
|
||||||
{
|
{
|
||||||
//reset timer
|
ResetTestModeTimer();
|
||||||
_stopTimer.Stop();
|
|
||||||
_stopTimer.Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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.");
|
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();
|
Deinit();
|
||||||
|
|
||||||
|
_stopTimer.Elapsed -= _stopTimer_Elapsed;
|
||||||
|
_stopTimer = null;
|
||||||
|
|
||||||
Log.Debug("_stopTimer_Elapsed: end.");
|
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);
|
server.AddExpert(expert);
|
||||||
|
expert.Deinited += ExpertOnDeinited;
|
||||||
|
|
||||||
Log.Info("AddExpert: end");
|
Log.Info("AddExpert: end");
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,6 @@ namespace MTApiService
|
|||||||
if (_experts.ContainsKey(expertHandle))
|
if (_experts.ContainsKey(expertHandle))
|
||||||
{
|
{
|
||||||
expert = _experts[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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace MTApiService
|
|||||||
Log.Debug("SendResponse: end.");
|
Log.Debug("SendResponse: end.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetCommandType()
|
public virtual int GetCommandType()
|
||||||
{
|
{
|
||||||
Log.Debug("GetCommandType: called.");
|
Log.Debug("GetCommandType: called.");
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ namespace MTApiService
|
|||||||
return command.NamedParams.ContainsKey(name);
|
return command.NamedParams.ContainsKey(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendEvent(MtEvent mtEvent)
|
public virtual void SendEvent(MtEvent mtEvent)
|
||||||
{
|
{
|
||||||
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
|
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ namespace MTApiService
|
|||||||
Log.Debug("SendEvent: end.");
|
Log.Debug("SendEvent: end.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateQuote(MtQuote quote)
|
public void UpdateQuote(MtQuote quote)
|
||||||
{
|
{
|
||||||
Log.DebugFormat("UpdateQuote: begin. quote = {0}", quote);
|
Log.DebugFormat("UpdateQuote: begin. quote = {0}", quote);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
{
|
{
|
||||||
OnTradeTransaction = 1,
|
OnTradeTransaction = 1,
|
||||||
OnBookEvent = 2,
|
OnBookEvent = 2,
|
||||||
OnTick = 3
|
OnTick = 3,
|
||||||
|
OnLastTimeBar = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-3
@@ -7,7 +7,6 @@ namespace MtApi5
|
|||||||
{
|
{
|
||||||
public MqlRates(DateTime time, double open, double high, double low, double close, long tick_volume, int spread, long real_volume)
|
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);
|
mt_time = Mt5TimeConverter.ConvertToMtTime(time);
|
||||||
this.open = open;
|
this.open = open;
|
||||||
this.high = high;
|
this.high = high;
|
||||||
@@ -20,7 +19,6 @@ namespace MtApi5
|
|||||||
|
|
||||||
internal MqlRates(long time, double open, double high, double low, double close, long tick_volume, int spread, long real_volume)
|
internal MqlRates(long time, double open, double high, double low, double close, long tick_volume, int spread, long real_volume)
|
||||||
{
|
{
|
||||||
this.time = Mt5TimeConverter.ConvertFromMtTime(time);
|
|
||||||
mt_time = time;
|
mt_time = time;
|
||||||
this.open = open;
|
this.open = open;
|
||||||
this.high = high;
|
this.high = high;
|
||||||
@@ -35,7 +33,7 @@ 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 long mt_time { get; set; } // Period start time (original MT time)
|
||||||
public double open { get; set; } // Open price
|
public double open { get; set; } // Open price
|
||||||
public double high { get; set; } // The highest price of the period
|
public double high { get; set; } // The highest price of the period
|
||||||
|
|||||||
@@ -248,6 +248,8 @@ namespace MtApi5
|
|||||||
GlobalVariableTemp = 154,
|
GlobalVariableTemp = 154,
|
||||||
GlobalVariableSetOnCondition = 156,
|
GlobalVariableSetOnCondition = 156,
|
||||||
GlobalVariablesDeleteAll = 157,
|
GlobalVariablesDeleteAll = 157,
|
||||||
GlobalVariablesTotal = 158
|
GlobalVariablesTotal = 158,
|
||||||
|
|
||||||
|
UnlockTicks = 159
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,8 +49,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="CopyTicksFlag.cs" />
|
<Compile Include="CopyTicksFlag.cs" />
|
||||||
<Compile Include="Events\OnBookEvent.cs" />
|
<Compile Include="Events\OnBookEvent.cs" />
|
||||||
|
<Compile Include="Events\OnLastTimeBarEvent.cs" />
|
||||||
<Compile Include="Events\OnTickEvent.cs" />
|
<Compile Include="Events\OnTickEvent.cs" />
|
||||||
<Compile Include="Events\OnTradeTransactionEvent.cs" />
|
<Compile Include="Events\OnTradeTransactionEvent.cs" />
|
||||||
|
<Compile Include="Mt5TimeBarArgs.cs" />
|
||||||
<Compile Include="MqlBookInfo.cs" />
|
<Compile Include="MqlBookInfo.cs" />
|
||||||
<Compile Include="MqlParam.cs" />
|
<Compile Include="MqlParam.cs" />
|
||||||
<Compile Include="MqlRates.cs" />
|
<Compile Include="MqlRates.cs" />
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ namespace MtApi5
|
|||||||
_mtEventHandlers[Mt5EventTypes.OnBookEvent] = ReceivedOnBookEvent;
|
_mtEventHandlers[Mt5EventTypes.OnBookEvent] = ReceivedOnBookEvent;
|
||||||
_mtEventHandlers[Mt5EventTypes.OnTick] = ReceivedOnTickEvent;
|
_mtEventHandlers[Mt5EventTypes.OnTick] = ReceivedOnTickEvent;
|
||||||
_mtEventHandlers[Mt5EventTypes.OnTradeTransaction] = ReceivedOnTradeTransaction;
|
_mtEventHandlers[Mt5EventTypes.OnTradeTransaction] = ReceivedOnTradeTransaction;
|
||||||
|
_mtEventHandlers[Mt5EventTypes.OnLastTimeBar] = ReceivedOnLastTimeBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
@@ -3057,6 +3058,18 @@ namespace MtApi5
|
|||||||
}
|
}
|
||||||
#endregion
|
#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
|
#endregion // Public Methods
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -3104,6 +3117,7 @@ namespace MtApi5
|
|||||||
public event EventHandler<Mt5ConnectionEventArgs> ConnectionStateChanged;
|
public event EventHandler<Mt5ConnectionEventArgs> ConnectionStateChanged;
|
||||||
public event EventHandler<Mt5TradeTransactionEventArgs> OnTradeTransaction;
|
public event EventHandler<Mt5TradeTransactionEventArgs> OnTradeTransaction;
|
||||||
public event EventHandler<Mt5BookEventArgs> OnBookEvent;
|
public event EventHandler<Mt5BookEventArgs> OnBookEvent;
|
||||||
|
public event EventHandler<Mt5TimeBarArgs> OnLastTimeBar;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
@@ -3216,6 +3230,12 @@ namespace MtApi5
|
|||||||
QuoteUpdate?.Invoke(this, new Mt5QuoteEventArgs(quote));
|
QuoteUpdate?.Invoke(this, new Mt5QuoteEventArgs(quote));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReceivedOnLastTimeBar(int expertHandler, string payload)
|
||||||
|
{
|
||||||
|
var e = JsonConvert.DeserializeObject<OnLastTimeBarEvent>(payload);
|
||||||
|
OnLastTimeBar?.Invoke(this, new Mt5TimeBarArgs(expertHandler, e.Instrument, e.Rates));
|
||||||
|
}
|
||||||
|
|
||||||
private void Connect(string host, int port)
|
private void Connect(string host, int port)
|
||||||
{
|
{
|
||||||
var client = new MtClient(host, port);
|
var client = new MtClient(host, port);
|
||||||
|
|||||||
@@ -574,6 +574,7 @@
|
|||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<WrapPanel VerticalAlignment="Top" Margin="5">
|
<WrapPanel VerticalAlignment="Top" Margin="5">
|
||||||
@@ -581,7 +582,9 @@
|
|||||||
<Button Command="{Binding ResetLastErrorCommand}" Content="ResetLastError" Margin="2"/>
|
<Button Command="{Binding ResetLastErrorCommand}" Content="ResetLastError" Margin="2"/>
|
||||||
</WrapPanel>
|
</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>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ namespace MtApi5TestClient
|
|||||||
public DelegateCommand GlobalVariableSetOnConditionCommand { get; private set; }
|
public DelegateCommand GlobalVariableSetOnConditionCommand { get; private set; }
|
||||||
public DelegateCommand GlobalVariablesDeleteAllCommand { get; private set; }
|
public DelegateCommand GlobalVariablesDeleteAllCommand { get; private set; }
|
||||||
public DelegateCommand GlobalVariablesTotalCommand { get; private set; }
|
public DelegateCommand GlobalVariablesTotalCommand { get; private set; }
|
||||||
|
|
||||||
|
public DelegateCommand UnlockTicksCommand { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -289,6 +291,7 @@ namespace MtApi5TestClient
|
|||||||
_mtApiClient.QuoteUpdate += mMtApiClient_QuoteUpdate;
|
_mtApiClient.QuoteUpdate += mMtApiClient_QuoteUpdate;
|
||||||
_mtApiClient.OnTradeTransaction += mMtApiClient_OnTradeTransaction;
|
_mtApiClient.OnTradeTransaction += mMtApiClient_OnTradeTransaction;
|
||||||
_mtApiClient.OnBookEvent += _mtApiClient_OnBookEvent;
|
_mtApiClient.OnBookEvent += _mtApiClient_OnBookEvent;
|
||||||
|
_mtApiClient.OnLastTimeBar += _mtApiClient_OnOnLastTimeBar;
|
||||||
|
|
||||||
ConnectionState = _mtApiClient.ConnectionState;
|
ConnectionState = _mtApiClient.ConnectionState;
|
||||||
ConnectionMessage = "Disconnected";
|
ConnectionMessage = "Disconnected";
|
||||||
@@ -424,6 +427,8 @@ namespace MtApi5TestClient
|
|||||||
GlobalVariableSetOnConditionCommand = new DelegateCommand(ExecuteGlobalVariableSetOnCondition);
|
GlobalVariableSetOnConditionCommand = new DelegateCommand(ExecuteGlobalVariableSetOnCondition);
|
||||||
GlobalVariablesDeleteAllCommand = new DelegateCommand(ExecuteGlobalVariablesDeleteAll);
|
GlobalVariablesDeleteAllCommand = new DelegateCommand(ExecuteGlobalVariablesDeleteAll);
|
||||||
GlobalVariablesTotalCommand = new DelegateCommand(ExecuteGlobalVariablesTotal);
|
GlobalVariablesTotalCommand = new DelegateCommand(ExecuteGlobalVariablesTotal);
|
||||||
|
|
||||||
|
UnlockTicksCommand = new DelegateCommand(ExecuteUnlockTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanExecuteConnect(object o)
|
private bool CanExecuteConnect(object o)
|
||||||
@@ -1564,6 +1569,11 @@ namespace MtApi5TestClient
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private void ExecuteUnlockTicks(object o)
|
||||||
|
{
|
||||||
|
_mtApiClient.UnlockTicks();
|
||||||
|
}
|
||||||
|
|
||||||
private static void RunOnUiThread(Action action)
|
private static void RunOnUiThread(Action action)
|
||||||
{
|
{
|
||||||
Application.Current?.Dispatcher.Invoke(action);
|
Application.Current?.Dispatcher.Invoke(action);
|
||||||
@@ -1640,6 +1650,11 @@ namespace MtApi5TestClient
|
|||||||
AddLog($"OnBookEvent: ExpertHandle = {e.ExpertHandle}, Symbol = {e.Symbol}");
|
AddLog($"OnBookEvent: ExpertHandle = {e.ExpertHandle}, Symbol = {e.Symbol}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void _mtApiClient_OnOnLastTimeBar(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}");
|
||||||
|
}
|
||||||
|
|
||||||
private void AddQuote(Mt5Quote quote)
|
private void AddQuote(Mt5Quote quote)
|
||||||
{
|
{
|
||||||
if (_quotesMap.ContainsKey(quote.ExpertHandle))
|
if (_quotesMap.ContainsKey(quote.ExpertHandle))
|
||||||
|
|||||||
Binary file not shown.
+108
-8
@@ -41,9 +41,17 @@
|
|||||||
bool getBooleanValue(int expertHandle, int paramIndex, bool& res, string& err);
|
bool getBooleanValue(int expertHandle, int paramIndex, bool& res, string& err);
|
||||||
#import
|
#import
|
||||||
|
|
||||||
//#define __DEBUG_LOG__
|
#define __DEBUG_LOG__
|
||||||
|
|
||||||
|
enum LockTickType
|
||||||
|
{
|
||||||
|
NO_LOCK,
|
||||||
|
LOCK_EVERY_TICK,
|
||||||
|
LOCK_EVERY_CANDLE
|
||||||
|
};
|
||||||
|
|
||||||
input int Port = 8228;
|
input int Port = 8228;
|
||||||
|
input LockTickType BacktestingLockTicks = NO_LOCK;
|
||||||
|
|
||||||
int ExpertHandle;
|
int ExpertHandle;
|
||||||
|
|
||||||
@@ -53,6 +61,9 @@ bool isCrashed = false;
|
|||||||
|
|
||||||
bool IsRemoteReadyForTesting = false;
|
bool IsRemoteReadyForTesting = false;
|
||||||
|
|
||||||
|
long _last_bar_open_time = 0;
|
||||||
|
bool _is_ticks_locked = false;
|
||||||
|
|
||||||
string PARAM_SEPARATOR = ";";
|
string PARAM_SEPARATOR = ";";
|
||||||
|
|
||||||
int OnInit()
|
int OnInit()
|
||||||
@@ -74,14 +85,44 @@ void OnDeinit(const int reason)
|
|||||||
|
|
||||||
void OnTick()
|
void OnTick()
|
||||||
{
|
{
|
||||||
|
string symbol = Symbol();
|
||||||
|
|
||||||
|
bool lastbar_time_changed = false;
|
||||||
|
long lastbar_time = SeriesInfoInteger(symbol, Period(), SERIES_LASTBAR_DATE);
|
||||||
|
if (_last_bar_open_time != lastbar_time)
|
||||||
|
{
|
||||||
|
if (_last_bar_open_time != 0)
|
||||||
|
{
|
||||||
|
MqlRates rates_array[];
|
||||||
|
CopyRates(symbol, Period(), 1, 1, rates_array);
|
||||||
|
|
||||||
|
MtTimeBar* timeBar = new MtTimeBar(symbol, rates_array[0]);
|
||||||
|
SendMtEvent(LAST_TIME_BAR_EVENT, timeBar);
|
||||||
|
delete timeBar;
|
||||||
|
|
||||||
|
lastbar_time_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_last_bar_open_time = lastbar_time;
|
||||||
|
}
|
||||||
|
|
||||||
MqlTick last_tick;
|
MqlTick last_tick;
|
||||||
SymbolInfoTick(Symbol(),last_tick);
|
SymbolInfoTick(Symbol(),last_tick);
|
||||||
|
|
||||||
MtOnTickEvent * tick_event = new MtOnTickEvent(Symbol(), last_tick);
|
MtOnTickEvent * tick_event = new MtOnTickEvent(symbol, last_tick);
|
||||||
SendMtEvent(ON_TICK_EVENT, tick_event);
|
SendMtEvent(ON_TICK_EVENT, tick_event);
|
||||||
delete tick_event;
|
delete tick_event;
|
||||||
|
|
||||||
if (IsTesting()) OnTimer();
|
if (IsTesting())
|
||||||
|
{
|
||||||
|
if (BacktestingLockTicks == LOCK_EVERY_TICK ||
|
||||||
|
(BacktestingLockTicks == LOCK_EVERY_CANDLE && lastbar_time_changed))
|
||||||
|
{
|
||||||
|
_is_ticks_locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnTimer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTradeTransaction(
|
void OnTradeTransaction(
|
||||||
@@ -224,10 +265,12 @@ void OnTimer()
|
|||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
int executedCommand = executeCommand();
|
int executedCommand = executeCommand();
|
||||||
|
|
||||||
|
if (_is_ticks_locked)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (executedCommand == 0)
|
if (executedCommand == 0)
|
||||||
{
|
break;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,6 +784,9 @@ int executeCommand()
|
|||||||
case 158: //GlobalVariablesTotal
|
case 158: //GlobalVariablesTotal
|
||||||
Execute_GlobalVariablesTotal();
|
Execute_GlobalVariablesTotal();
|
||||||
break;
|
break;
|
||||||
|
case 159: //UnlockTiks
|
||||||
|
Execute_UnlockTicks();
|
||||||
|
break;
|
||||||
case 204: //TerminalInfoInteger
|
case 204: //TerminalInfoInteger
|
||||||
Execute_TerminalInfoInteger();
|
Execute_TerminalInfoInteger();
|
||||||
break;
|
break;
|
||||||
@@ -6461,6 +6507,22 @@ void Execute_GlobalVariablesTotal()
|
|||||||
SEND_INT_RESPONSE(res)
|
SEND_INT_RESPONSE(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Execute_UnlockTicks()
|
||||||
|
{
|
||||||
|
if (!IsTesting())
|
||||||
|
{
|
||||||
|
Print("WARNING: function UnlockTicks can be used only for backtesting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_is_ticks_locked = false;
|
||||||
|
|
||||||
|
if (!sendVoidResponse(ExpertHandle, _response_error))
|
||||||
|
{
|
||||||
|
PrintResponseError("UnlockTicks", _response_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Execute_TerminalInfoInteger()
|
void Execute_TerminalInfoInteger()
|
||||||
{
|
{
|
||||||
int propertyId;
|
int propertyId;
|
||||||
@@ -7220,7 +7282,8 @@ enum MtEventTypes
|
|||||||
{
|
{
|
||||||
ON_TRADE_TRANSACTION_EVENT = 1,
|
ON_TRADE_TRANSACTION_EVENT = 1,
|
||||||
ON_BOOK_EVENT = 2,
|
ON_BOOK_EVENT = 2,
|
||||||
ON_TICK_EVENT = 3
|
ON_TICK_EVENT = 3,
|
||||||
|
LAST_TIME_BAR_EVENT = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
class MtEvent
|
class MtEvent
|
||||||
@@ -7296,6 +7359,29 @@ private:
|
|||||||
MqlTick _tick;
|
MqlTick _tick;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MtTimeBar: public MtEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MtTimeBar(string symbol, const MqlRates& rates)
|
||||||
|
{
|
||||||
|
_symbol = symbol;
|
||||||
|
_rates = rates;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual JSONObject* CreateJson()
|
||||||
|
{
|
||||||
|
JSONObject *jo = new JSONObject();
|
||||||
|
jo.put("Rates", MqlRatesToJson(_rates));
|
||||||
|
jo.put("Instrument", new JSONString(_symbol));
|
||||||
|
jo.put("ExpertHandle", new JSONNumber(ExpertHandle));
|
||||||
|
return jo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _symbol;
|
||||||
|
MqlRates _rates;
|
||||||
|
};
|
||||||
|
|
||||||
void SendMtEvent(MtEventTypes eventType, MtEvent* mtEvent)
|
void SendMtEvent(MtEventTypes eventType, MtEvent* mtEvent)
|
||||||
{
|
{
|
||||||
#ifdef __DEBUG_LOG__
|
#ifdef __DEBUG_LOG__
|
||||||
@@ -7478,4 +7564,18 @@ JSONObject* MqlTradeRequestToJson(MqlTradeRequest& request)
|
|||||||
jo.put("MtExpiration", new JSONNumber((int)request.expiration));
|
jo.put("MtExpiration", new JSONNumber((int)request.expiration));
|
||||||
jo.put("Comment", new JSONString(request.comment));
|
jo.put("Comment", new JSONString(request.comment));
|
||||||
return jo;
|
return jo;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject* MqlRatesToJson(MqlRates& rates)
|
||||||
|
{
|
||||||
|
JSONObject *jo = new JSONObject();
|
||||||
|
jo.put("mt_time", new JSONNumber((int)rates.time));
|
||||||
|
jo.put("open", new JSONNumber(rates.open));
|
||||||
|
jo.put("high", new JSONNumber(rates.high));
|
||||||
|
jo.put("low", new JSONNumber(rates.low));
|
||||||
|
jo.put("close", new JSONNumber(rates.close));
|
||||||
|
jo.put("tick_volume", new JSONNumber(rates.tick_volume));
|
||||||
|
jo.put("spread", new JSONNumber(rates.spread));
|
||||||
|
jo.put("real_volume", new JSONNumber(rates.real_volume));
|
||||||
|
return jo;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user