Skip to content

Check Margin Availability (CheckMarginAvailabilityAsync) ⭐

⭐ CRITICAL METHOD: Check if account has enough free margin for order - one-shot pre-flight check!

API: MT5Service.CheckMarginAvailabilityAsync(...) Region: [13] ORDER VALIDATION ⭐

Signature

public static async Task<(bool hasEnough, double freeMargin, double required)>
    CheckMarginAvailabilityAsync(
        this MT5Service svc,
        string symbol,
        double volume,
        bool isBuy,
        double price = 0,
        int timeoutSec = 20,
        CancellationToken ct = default)

Returns

Tuple: (bool hasEnough, double freeMargin, double required)

  • hasEnough - true if can afford order
  • freeMargin - Current free margin
  • required - Required margin for this order

Quick Examples

1. Basic Check

var (hasEnough, free, required) = await svc.CheckMarginAvailabilityAsync(
    "EURUSD",
    volume: 1.0,
    isBuy: true);

if (hasEnough)
{
    Console.WriteLine($"✅ Can trade: ${free:F2} >= ${required:F2}");
    await svc.BuyMarketAsync("EURUSD", 1.0);
}
else
{
    Console.WriteLine($"❌ Insufficient: ${free:F2} < ${required:F2}");
}

2. With Risk Management

var (hasMargin, _, _) = await svc.CheckMarginAvailabilityAsync("EURUSD", 10.0, true);
if (hasMargin)
{
    await svc.BuyMarketByRisk("EURUSD", stopPoints: 50, riskMoney: 100);
}
else
{
    Console.WriteLine("⚠️ Insufficient margin - skipping trade");
}

3. Compare Buy vs Sell

var (canBuy, freeBuy, reqBuy) = await svc.CheckMarginAvailabilityAsync(
    "EURUSD", 1.0, isBuy: true);
var (canSell, freeSell, reqSell) = await svc.CheckMarginAvailabilityAsync(
    "EURUSD", 1.0, isBuy: false);

Console.WriteLine($"BUY:  ${reqBuy:F2} - {(canBuy ? "✅" : "❌")}");
Console.WriteLine($"SELL: ${reqSell:F2} - {(canSell ? "✅" : "❌")}");

4. Multi-Symbol Portfolio Check

var symbols = new[] { "EURUSD", "GBPUSD", "USDJPY" };
double totalRequired = 0;

foreach (var symbol in symbols)
{
    var (_, _, required) = await svc.CheckMarginAvailabilityAsync(symbol, 0.10, true);
    totalRequired += required;
}

var (hasEnough, freeMargin, _) = await svc.CheckMarginAvailabilityAsync(
    symbols[0], 0, true);  // Get current free margin

Console.WriteLine($"Total margin needed: ${totalRequired:F2}");
Console.WriteLine($"Free margin: ${freeMargin:F2}");
Console.WriteLine(hasEnough ? "✅ Can trade all" : "❌ Insufficient for portfolio");

5. Progressive Volume Increase

public async Task<double> FindMaxAffordableVolume(
    MT5Service svc,
    string symbol,
    bool isBuy)
{
    double volume = 0.01;
    double maxVolume = 0;

    while (volume <= 100.0)
    {
        var (hasEnough, _, _) = await svc.CheckMarginAvailabilityAsync(
            symbol, volume, isBuy);

        if (hasEnough)
        {
            maxVolume = volume;
            volume *= 2;  // Double volume
        }
        else
        {
            break;
        }
    }

    Console.WriteLine($"Max affordable volume: {maxVolume} lots");
    return maxVolume;
}

// Usage:
double maxVol = await FindMaxAffordableVolume(svc, "EURUSD", isBuy: true);

Under the Hood

// Step 1: Calculate required margin (parallel with free margin query)
var marginReq = new OrderCalcMarginRequest
{
    Symbol = symbol,
    OrderType = isBuy ? ENUM_ORDER_TYPE_TF.OrderTypeTfBuy : ENUM_ORDER_TYPE_TF.OrderTypeTfSell,
    Volume = volume,
    OpenPrice = price
};

var marginTask = svc.OrderCalcMarginAsync(marginReq, deadline, ct);
var freeMarginTask = svc.GetFreeMarginAsync(deadline, ct);

await Task.WhenAll(marginTask, freeMarginTask);  // Parallel execution

// Step 2: Compare
var requiredMargin = (await marginTask).Margin;
var freeMargin = await freeMarginTask;
bool hasEnough = freeMargin >= requiredMargin;

return (hasEnough, freeMargin, requiredMargin);

Performance: Executes margin calculation and free margin query in parallel for speed!

  • CalculateBuyMarginAsync() - BUY margin only
  • CalculateSellMarginAsync() - SELL margin only
  • ValidateOrderAsync() - Full validation (slower, more comprehensive)

When to Use

Method Use When
CheckMarginAvailabilityAsync() ⭐ Quick margin check before placing order
CalculateBuyMarginAsync() Only need margin amount (no comparison)
ValidateOrderAsync() Need full validation (symbol, stops, etc.)

Common Pitfalls

// ❌ WRONG: Ignoring the check
await svc.BuyMarketAsync("EURUSD", 10.0);  // May fail!

// ✅ CORRECT: Always check first
var (hasEnough, _, _) = await svc.CheckMarginAvailabilityAsync("EURUSD", 10.0, true);
if (hasEnough)
{
    await svc.BuyMarketAsync("EURUSD", 10.0);
}

Summary

CheckMarginAvailabilityAsync provides one-shot margin verification:

  • ✅ Returns bool + both values (free and required)
  • ✅ Parallel execution for speed
  • ✅ Perfect for pre-trade validation
  • ⭐ Use before ALL large orders!
// Professional pattern:
var (hasMargin, free, required) = await svc.CheckMarginAvailabilityAsync(
    "EURUSD", 1.0, isBuy: true);

if (hasMargin)
{
    await svc.BuyMarketByRisk("EURUSD", 50, 100);
}
else
{
    Console.WriteLine($"Need ${required:F2}, have ${free:F2}");
}

Check margin first, avoid margin calls! 🛡️