2024-06-16 13:57:50 +03:00
using MtApi.Monitors.Triggers ;
2016-09-09 19:10:10 +03:00
namespace MtApi.Monitors
{
2020-10-13 15:10:26 +02:00
public class TradeMonitor : MtMonitorBase
2016-09-09 19:10:10 +03:00
{
#region Fields
2024-06-16 13:57:50 +03:00
private List < MtOrder >? _prevOrders ;
private readonly object _locker = new ();
2016-09-09 19:10:10 +03:00
#endregion
#region Events
//
// Summary:
// Occurs when orders are opened or closed.
2024-06-16 13:57:50 +03:00
public event EventHandler < AvailabilityOrdersEventArgs >? AvailabilityOrdersChanged ;
2016-09-09 19:10:10 +03:00
#endregion
2020-10-13 15:10:26 +02:00
#region ctor
2020-10-13 15:52:55 +02:00
/// <summary>
/// Constructor for initializing an instance of <see cref="TradeMonitor"/>.
/// </summary>
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
/// <param name="monitorTrigger">The custom instance of <see cref="IMonitorTrigger"/> which will be used to trigger this instance of <see cref="TradeMonitor"/>.</param>
2020-10-13 15:10:26 +02:00
public TradeMonitor ( MtApiClient apiClient , IMonitorTrigger monitorTrigger ) : base ( apiClient , monitorTrigger ) { }
#endregion
2016-09-09 19:10:10 +03:00
2020-10-13 15:10:26 +02:00
protected override void OnMtConnected ()
{
InitialCheck ();
base . OnMtConnected ();
}
protected override void OnStart ()
{
if ( IsMtConnected )
InitialCheck ();
base . OnStart ();
}
2020-10-22 22:26:17 +03:00
protected override void OnTriggerRaised ()
{
if ( IsMtConnected )
Check ();
}
2020-10-13 15:10:26 +02:00
private void Check ()
2016-09-09 19:10:10 +03:00
{
try
{
CheckOrders ();
}
catch ( MtConnectionException )
{
//TODO: write error to log
}
catch ( MtExecutionException )
{
//TODO: write error to log
}
}
2020-10-13 15:10:26 +02:00
private void InitialCheck ()
{
lock ( _locker )
_prevOrders = null ;
2016-09-09 19:10:10 +03:00
2020-10-13 15:10:26 +02:00
Task . Factory . StartNew ( Check );
}
2016-09-09 19:10:10 +03:00
private void CheckOrders ()
{
var openedOrders = new List < MtOrder >();
var closedOrders = new List < MtOrder >();
2024-06-16 13:57:50 +03:00
List < MtOrder >? prevOrders ;
2016-09-09 19:10:10 +03:00
// get current orders from MetaTrader
2024-06-16 13:57:50 +03:00
var tradesOrders = ApiClient . GetOrders ( OrderSelectSource . MODE_TRADES ) ?? [];
2016-09-09 19:10:10 +03:00
2020-10-13 15:10:26 +02:00
lock ( _locker )
2016-09-09 19:10:10 +03:00
prevOrders = _prevOrders ;
2016-11-13 23:24:38 +02:00
if ( prevOrders != null ) //skip checking on first load orders
2016-09-09 19:10:10 +03:00
{
//check open orders
2020-10-13 15:10:26 +02:00
openedOrders = tradesOrders . Where ( to => prevOrders . Find ( a => a . Ticket == to . Ticket ) == null ). ToList ();
2016-09-09 19:10:10 +03:00
//check closed orders
2020-10-13 15:10:26 +02:00
var closeOrdersTemp = prevOrders . Where ( po => tradesOrders . Find ( a => a . Ticket == po . Ticket ) == null ). ToList ();
2016-09-09 19:10:10 +03:00
if ( closeOrdersTemp . Count > 0 )
{
//get closed orders from history with actual values
2024-06-16 13:57:50 +03:00
var historyOrders = ApiClient . GetOrders ( OrderSelectSource . MODE_HISTORY ) ?? [];
2020-10-13 15:10:26 +02:00
closedOrders = closeOrdersTemp . Where ( cot => historyOrders . Find ( a => a . Ticket == cot . Ticket ) != null ). ToList ();
2016-09-09 19:10:10 +03:00
}
}
2020-10-13 15:10:26 +02:00
lock ( _locker )
2016-09-09 19:10:10 +03:00
_prevOrders = tradesOrders ;
if ( openedOrders . Count > 0 || closedOrders . Count > 0 )
{
AvailabilityOrdersChanged ?. Invoke ( this , new AvailabilityOrdersEventArgs ( openedOrders , closedOrders ));
}
}
}
2020-10-13 15:10:26 +02:00
}