✅ Ensure Symbol Selected and Synchronized (EnsureSelected)¶
Sugar method: Ensures a symbol is selected in MarketWatch and synchronized with server before using it. Throws exception if synchronization fails.
API Information:
- Extension method:
MT5Service.EnsureSelected(...)(fromMT5ServiceExtensions) - Package: Part of
mt5_term_apilibrary - Underlying calls:
SymbolSelectAsync()+SymbolIsSynchronizedAsync()
Method Signature¶
public static class MT5ServiceExtensions
{
public static async Task EnsureSelected(
this MT5Service svc,
string symbol,
int timeoutSec = 10,
CancellationToken ct = default);
}
🔽 Input¶
| Parameter | Type | Description |
|---|---|---|
svc |
MT5Service |
MT5Service instance (extension method) |
symbol |
string |
Symbol name (e.g., "EURUSD", "XAUUSD") |
timeoutSec |
int |
Timeout in seconds (default: 10) |
ct |
CancellationToken |
Cancellation token |
⬆️ Output¶
| Type | Description |
|---|---|
Task |
Completes successfully if symbol is ready |
Throws:
InvalidOperationException— If symbol is not synchronized after selection
💬 Just the essentials¶
- What it is. Helper that ensures symbol is visible in MarketWatch and fully synchronized with server data before you use it.
- Why you need it. Prevents errors when accessing symbol data (ticks, properties, DOM) by ensuring symbol is ready first.
- Sanity check. If method completes without exception → symbol is ready. If throws → symbol not available or not synchronized.
🎯 Purpose¶
Use it before symbol operations:
- Before reading symbol properties (tick, spread, etc.).
- Before placing orders on a symbol.
- Before subscribing to MarketBook (DOM).
- As safety check in automated strategies.
🧩 Notes & Tips¶
- Two-step process: First selects symbol (makes it visible in MarketWatch), then verifies synchronization.
- Synchronization: Ensures symbol data is up-to-date from server. Critical for accurate prices.
- Throws on failure: Unlike low-level methods, this throws exception if symbol can't be synchronized.
- Timeout: 10 seconds is usually enough. Increase for slow connections or exotic symbols.
- Idempotent: Safe to call multiple times. Won't fail if symbol already selected.
- Used internally: Many other sugar methods call this automatically (e.g.,
PlaceMarket,GetSymbolSnapshot).
🔧 Under the Hood¶
This sugar method combines two low-level calls:
// Step 1: Select symbol (make it visible in MarketWatch)
await svc.SymbolSelectAsync(symbol, selected: true, deadline, ct);
// Step 2: Check if symbol is synchronized with server
var sync = await svc.SymbolIsSynchronizedAsync(symbol, deadline, ct);
// Step 3: Throw exception if not synchronized
if (!sync)
throw new InvalidOperationException($"Symbol '{symbol}' is not synchronized in terminal.");
What it improves:
- Combines 2 calls into 1 - simpler API
- Automatic validation - throws if symbol not ready
- Shared deadline - both calls use same timeout
- Clear error message - tells you exactly what's wrong
📊 Low-Level Alternative¶
WITHOUT sugar (manual approach):
// You have to do this manually:
var deadline = DateTime.UtcNow.AddSeconds(10);
// Step 1: Select symbol
await svc.SymbolSelectAsync("EURUSD", selected: true, deadline, ct);
// Step 2: Check synchronization
var sync = await svc.SymbolIsSynchronizedAsync("EURUSD", deadline, ct);
// Step 3: Validate manually
if (!sync)
{
throw new InvalidOperationException("Symbol 'EURUSD' is not synchronized in terminal.");
}
// Now you can use the symbol
var tick = await svc.SymbolInfoTickAsync("EURUSD", deadline, ct);
WITH sugar (one-liner):
// Sugar method does all of the above:
await svc.EnsureSelected("EURUSD");
// Now you can use the symbol
var tick = await svc.SymbolInfoTickAsync("EURUSD", ...);
Benefits:
- ✅ 3 lines → 1 line
- ✅ Automatic deadline management
- ✅ Automatic validation
- ✅ Clearer intent
🔗 Usage Examples¶
1) Basic usage - ensure symbol ready¶
// svc — MT5Service instance
await svc.EnsureSelected("EURUSD");
// Now safe to use symbol
var tick = await svc.SymbolInfoTickAsync("EURUSD");
Console.WriteLine($"EURUSD Bid: {tick.Bid}");
2) With custom timeout¶
// Use longer timeout for slow connection
await svc.EnsureSelected("BTCUSD", timeoutSec: 30);
Console.WriteLine("BTCUSD is ready");
3) With error handling¶
var symbol = "XAUUSD";
try
{
await svc.EnsureSelected(symbol);
Console.WriteLine($"✓ {symbol} is ready");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"✗ Failed to synchronize {symbol}: {ex.Message}");
return;
}
// Safe to proceed with symbol operations
var spread = await svc.GetSpreadPointsAsync(symbol);
Console.WriteLine($"Spread: {spread} points");
4) Ensure multiple symbols before trading¶
var symbols = new[] { "EURUSD", "GBPUSD", "USDJPY" };
foreach (var symbol in symbols)
{
try
{
await svc.EnsureSelected(symbol);
Console.WriteLine($"✓ {symbol} ready");
}
catch (InvalidOperationException)
{
Console.WriteLine($"✗ {symbol} not available");
}
}
5) Before placing order¶
var symbol = "EURUSD";
// Ensure symbol ready first
await svc.EnsureSelected(symbol);
// Now safe to place order
var result = await svc.BuyMarket(
symbol: symbol,
volume: 0.01,
sl: 1.0800,
tp: 1.0900
);
Console.WriteLine($"Order placed: #{result.Order}");
6) Before accessing MarketBook (DOM)¶
var symbol = "BTCUSD";
// Must ensure symbol ready before DOM subscription
await svc.EnsureSelected(symbol, timeoutSec: 15);
// Now can subscribe to DOM
var subResult = await svc.MarketBookAddAsync(symbol);
if (subResult.OpenedSuccessfully)
{
Console.WriteLine($"DOM subscription opened for {symbol}");
}
7) Parallel symbol preparation¶
var symbols = new[] { "EURUSD", "GBPUSD", "USDJPY", "XAUUSD" };
// Prepare all symbols in parallel
var tasks = symbols.Select(symbol =>
svc.EnsureSelected(symbol).ContinueWith(t =>
new { Symbol = symbol, Success = !t.IsFaulted }
)
);
var results = await Task.WhenAll(tasks);
foreach (var result in results)
{
var status = result.Success ? "✓ Ready" : "✗ Failed";
Console.WriteLine($"{result.Symbol}: {status}");
}
var readySymbols = results.Where(r => r.Success).Select(r => r.Symbol).ToList();
Console.WriteLine($"\n{readySymbols.Count} symbols ready for trading");
8) With cancellation token¶
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5)); // Cancel after 5 seconds
try
{
await svc.EnsureSelected("EURUSD", timeoutSec: 10, ct: cts.Token);
Console.WriteLine("Symbol ready");
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation cancelled (timeout)");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"Synchronization failed: {ex.Message}");
}
9) Retry pattern for unreliable symbols¶
var symbol = "EXOTIC_PAIR";
int maxRetries = 3;
int retryCount = 0;
bool success = false;
while (retryCount < maxRetries && !success)
{
try
{
await svc.EnsureSelected(symbol, timeoutSec: 15);
success = true;
Console.WriteLine($"✓ {symbol} ready after {retryCount + 1} attempt(s)");
}
catch (InvalidOperationException)
{
retryCount++;
Console.WriteLine($"Retry {retryCount}/{maxRetries}...");
await Task.Delay(2000); // Wait 2 seconds before retry
}
}
if (!success)
{
Console.WriteLine($"✗ Failed to prepare {symbol} after {maxRetries} attempts");
}
10) Integration with strategy initialization¶
public class TradingStrategy
{
private readonly MT5Service _svc;
private readonly string[] _symbols;
public TradingStrategy(MT5Service svc, string[] symbols)
{
_svc = svc;
_symbols = symbols;
}
public async Task InitializeAsync()
{
Console.WriteLine("Initializing strategy...");
// Ensure all symbols ready
foreach (var symbol in _symbols)
{
await _svc.EnsureSelected(symbol, timeoutSec: 20);
Console.WriteLine($" ✓ {symbol} ready");
}
Console.WriteLine("Strategy initialized successfully");
}
public async Task ExecuteAsync()
{
// All symbols guaranteed to be ready here
foreach (var symbol in _symbols)
{
var tick = await _svc.SymbolInfoTickAsync(symbol);
Console.WriteLine($"{symbol}: Bid={tick.Bid}");
}
}
}
// Usage
var strategy = new TradingStrategy(svc, new[] { "EURUSD", "GBPUSD" });
await strategy.InitializeAsync();
await strategy.ExecuteAsync();
🔗 Related Methods¶
📦 Low-level methods used internally:
SymbolSelectAsync()- Select/deselect symbol in MarketWatch (step 1)SymbolIsSynchronizedAsync()- Check if symbol synchronized with server (step 2)
🍬 Sugar methods that use EnsureSelected internally:
GetSymbolSnapshot()- Calls this before getting symbol dataPlaceMarket()/BuyMarket()/SellMarket()- Ensures symbol ready before placing orderPlacePending()- Ensures symbol ready before placing pending order- All
*LimitPoints()and*StopPoints()methods - Ensure symbol ready first - All
*ByRisk()methods - Ensure symbol ready before calculating volume NormalizePriceAsync()/NormalizeVolumeAsync()- Can optionally call this first
⚠️ Common Pitfalls¶
-
Symbol doesn't exist on broker:
-
Symbol exists but not tradeable:
-
Too short timeout:
Solution: Use reasonable timeout (10-30 seconds) and handle exceptions properly.