π Reading Limited Trade Event Stream (ReadTrades)ΒΆ
Request: Subscribe to trade events stream and read a limited number of events or until timeout.
OverviewΒΆ
ReadTrades is a convenience wrapper over OnTradeAsync that automatically limits the stream by:
- Maximum number of events
- Duration timeout
This is useful for monitoring trade executions, fills, position changes, and order events without managing complex cancellation logic.
Method SignatureΒΆ
public static async IAsyncEnumerable<OnTradeData> ReadTrades(
this MT5Service svc,
int maxEvents = 20,
int durationSec = 5,
[EnumeratorCancellation] CancellationToken ct = default)
ParametersΒΆ
| Parameter | Type | Default | Description |
|---|---|---|---|
svc |
MT5Service |
- | Extension method target |
maxEvents |
int |
20 |
Maximum number of trade events to read before stopping |
durationSec |
int |
5 |
Maximum duration in seconds before timeout |
ct |
CancellationToken |
default |
Optional cancellation token |
Return ValueΒΆ
Type: IAsyncEnumerable<OnTradeData>
Returns an async stream of trade event data. The stream automatically stops when either:
maxEventstrade events have been received, ORdurationSecseconds have elapsed, OR- The cancellation token is triggered
How It WorksΒΆ
- Creates a linked cancellation token source from the provided
ct - Sets a timeout of
durationSecseconds - Subscribes to
OnTradeAsyncfor all account trade events - Yields each trade event until:
- Counter reaches
maxEvents, or - Timeout is reached, or
- Cancellation is requested
- Automatically disposes the cancellation token source
Common Use CasesΒΆ
1οΈβ£ Monitor Recent Trade ActivityΒΆ
Watch for next 10 trade events within 30 seconds:
Console.WriteLine("Monitoring trade events...\n");
await foreach (var trade in svc.ReadTrades(maxEvents: 10, durationSec: 30))
{
Console.WriteLine($"[{trade.EventType}] {trade.Symbol} | Volume: {trade.Volume} | Price: {trade.Price:F5}");
}
2οΈβ£ Confirm Order ExecutionΒΆ
Wait for specific trade event after placing order:
// Place a market order
var orderRequest = new MrpcMqlTradeRequest
{
Action = MRPC_ENUM_TRADE_REQUEST_ACTIONS.TradeActionDeal,
Symbol = "EURUSD",
Volume = 0.01,
Price = ask,
OrderType = ENUM_ORDER_TYPE_TF.OrderTypeTfBuy,
TypeFilling = MRPC_ENUM_ORDER_TYPE_FILLING.OrderFillingFok,
TypeTime = MRPC_ENUM_ORDER_TYPE_TIME.OrderTimeGtc
};
var sendResult = await svc.OrderSendAsync(new OrderSendRequest { MqlTradeRequest = orderRequest });
Console.WriteLine($"Order sent. Ticket: {sendResult.Deal}. Waiting for trade event...");
// Monitor for confirmation
await foreach (var trade in svc.ReadTrades(maxEvents: 5, durationSec: 10))
{
if (trade.Deal == sendResult.Deal)
{
Console.WriteLine($"β Trade confirmed! Deal: {trade.Deal}, Price: {trade.Price:F5}, Volume: {trade.Volume}");
break;
}
}
3οΈβ£ Log Trade Events for DebuggingΒΆ
Capture all trade events during a specific operation:
var tradeLog = new List<OnTradeData>();
await foreach (var trade in svc.ReadTrades(maxEvents: 50, durationSec: 60))
{
tradeLog.Add(trade);
Console.WriteLine($"{trade.EventType,-20} | {trade.Symbol,-8} | Deal: {trade.Deal} | Order: {trade.Order}");
}
Console.WriteLine($"\nCaptured {tradeLog.Count} trade events.");
4οΈβ£ Wait for Position CloseΒΆ
Monitor trades until a specific position is closed:
ulong positionTicket = 123456789; // Position ticket to monitor
await foreach (var trade in svc.ReadTrades(maxEvents: 100, durationSec: 120))
{
Console.WriteLine($"Event: {trade.EventType} | Position: {trade.Position}");
if (trade.EventType == "TRADE_ACTION_DEAL" && trade.Position == positionTicket)
{
Console.WriteLine($"β Position {positionTicket} closed! Deal: {trade.Deal}, Profit: {trade.Profit:F2}");
break;
}
}
5οΈβ£ Count Trades in Time WindowΒΆ
Count how many trades occur in a 30-second window:
int tradeCount = 0;
await foreach (var trade in svc.ReadTrades(maxEvents: 1000, durationSec: 30))
{
tradeCount++;
Console.WriteLine($"Trade #{tradeCount}: {trade.EventType} on {trade.Symbol}");
}
Console.WriteLine($"\nTotal trades in 30 seconds: {tradeCount}");
OnTradeData StructureΒΆ
Each yielded event contains:
public class OnTradeData
{
public string EventType { get; set; } // Event type (e.g., "TRADE_ACTION_DEAL")
public string Symbol { get; set; } // Symbol name
public ulong Deal { get; set; } // Deal ticket
public ulong Order { get; set; } // Order ticket
public ulong Position { get; set; } // Position ticket
public double Volume { get; set; } // Volume in lots
public double Price { get; set; } // Execution price
public double Profit { get; set; } // Profit/loss
public double Commission { get; set; } // Commission charged
public double Swap { get; set; } // Swap charged
public string Comment { get; set; } // Order/deal comment
public Google.Protobuf.WellKnownTypes.Timestamp Time { get; set; } // Event time
// ... additional fields
}
Trade Event TypesΒΆ
Common event types you'll see in OnTradeData.EventType:
| Event Type | Description |
|---|---|
TRADE_ACTION_DEAL |
Market order executed (position opened/closed) |
TRADE_ACTION_PENDING |
Pending order placed |
TRADE_ACTION_SLTP |
Stop Loss / Take Profit modified |
TRADE_ACTION_MODIFY |
Pending order modified |
TRADE_ACTION_REMOVE |
Pending order cancelled |
TRADE_ACTION_CLOSE_BY |
Position closed by opposite position |
Notes & TipsΒΆ
- Real-time monitoring: Trade events arrive in real-time as they occur on the account
- Auto-termination: Stream stops automatically when limits are reached
- Timeout handling: If no trades occur within
durationSec, stream terminates - Thread-safe: Uses linked cancellation tokens for clean shutdown
- Resource management: Automatically disposes cancellation token source
- Use case: Perfect for order execution confirmation, debugging, and short-term monitoring
- Production: For long-running monitoring, use
OnTradeAsyncdirectly
ComparisonΒΆ
| Feature | ReadTrades (Sugar) |
OnTradeAsync (Low-level) |
|---|---|---|
| Auto-limit by count | β Built-in | β Manual counter needed |
| Auto-timeout | β Built-in | β Manual CancelAfter needed |
| Simplicity | β One-liner | β Requires setup code |
| Flexibility | β οΈ Limited | β Full control |
| Best for | Testing, confirmation | Production, continuous monitoring |
Related MethodsΒΆ
- ReadTicks β Similar helper for tick data streams
OnTradeAsync(MT5Account) β Low-level trade event stream subscriptionOnSymbolTickAsync(MT5Account) β Low-level tick streamOrderSendAsync(MT5Account) β Place orders that generate trade events
Example: Complete Trade MonitoringΒΆ
Console.WriteLine("=== Trade Event Monitor ===");
Console.WriteLine("Monitoring for 60 seconds or 20 events...\n");
var eventCounts = new Dictionary<string, int>();
await foreach (var trade in svc.ReadTrades(maxEvents: 20, durationSec: 60))
{
// Count event types
if (!eventCounts.ContainsKey(trade.EventType))
eventCounts[trade.EventType] = 0;
eventCounts[trade.EventType]++;
// Display event details
Console.WriteLine($"ββ Trade Event #{eventCounts.Values.Sum()}");
Console.WriteLine($"β Type: {trade.EventType}");
Console.WriteLine($"β Symbol: {trade.Symbol}");
Console.WriteLine($"β Deal: {trade.Deal}");
Console.WriteLine($"β Order: {trade.Order}");
Console.WriteLine($"β Position: {trade.Position}");
Console.WriteLine($"β Volume: {trade.Volume:F2} lots");
Console.WriteLine($"β Price: {trade.Price:F5}");
Console.WriteLine($"β Profit: {trade.Profit:F2}");
Console.WriteLine($"β Time: {trade.Time}");
Console.WriteLine($"ββββββββββββββββββββββββββββββ\n");
}
Console.WriteLine("\n=== Summary ===");
foreach (var (eventType, count) in eventCounts)
{
Console.WriteLine($"{eventType}: {count} events");
}
Sample Output:
=== Trade Event Monitor ===
Monitoring for 60 seconds or 20 events...
ββ Trade Event #1
β Type: TRADE_ACTION_DEAL
β Symbol: EURUSD
β Deal: 123456789
β Order: 987654321
β Position: 555555555
β Volume: 0.10 lots
β Price: 1.08450
β Profit: 0.00
β Time: 2025-01-17 10:30:45
ββββββββββββββββββββββββββββββ
ββ Trade Event #2
β Type: TRADE_ACTION_SLTP
β Symbol: EURUSD
β Deal: 0
β Order: 987654321
β Position: 555555555
β Volume: 0.10 lots
β Price: 1.08450
β Profit: 0.00
β Time: 2025-01-17 10:31:02
ββββββββββββββββββββββββββββββ
=== Summary ===
TRADE_ACTION_DEAL: 1 events
TRADE_ACTION_SLTP: 1 events
Advanced Pattern: Order Execution TrackerΒΆ
public static async Task<OnTradeData?> WaitForOrderFill(
MT5Service svc,
ulong orderTicket,
int timeoutSec = 30)
{
await foreach (var trade in svc.ReadTrades(maxEvents: 100, durationSec: timeoutSec))
{
if (trade.Order == orderTicket && trade.EventType == "TRADE_ACTION_DEAL")
{
return trade; // Found the fill event
}
}
return null; // Timeout - order not filled
}
// Usage:
var result = await svc.OrderSendAsync(orderRequest);
var fillEvent = await WaitForOrderFill(svc, result.Order, timeoutSec: 10);
if (fillEvent != null)
{
Console.WriteLine($"β Order filled at {fillEvent.Price:F5}");
}
else
{
Console.WriteLine("β οΈ Order fill timeout");
}