Buy Limit by Points (BuyLimitPoints)ΒΆ
Sugar method: Places Buy Limit pending order using point-based offset from current Ask price - no manual price calculation!
API Information:
- Extension method:
MT5Service.BuyLimitPoints(...)(fromMT5ServiceExtensions) - Package: Part of
mt5_term_apilibrary - Region: [09] PENDING HELPERS (BY POINTS)
- Underlying calls:
SymbolInfoTickAsync()+SymbolInfoDoubleAsync()+NormalizePriceAsync()+OrderSendAsync()
Method SignatureΒΆ
public static async Task<OrderSendData> BuyLimitPoints(
this MT5Service svc,
string symbol,
double volume,
double priceOffsetPoints,
double? slPoints = null,
double? tpPoints = null,
string? comment = null,
int deviationPoints = 0,
int timeoutSec = 15,
CancellationToken ct = default)
π½ InputΒΆ
| Parameter | Type | Description |
|---|---|---|
svc |
MT5Service |
MT5Service instance (extension method) |
symbol |
string |
Symbol name (e.g., "EURUSD", "XAUUSD") |
volume |
double |
Volume in lots (e.g., 0.01, 0.1, 1.0) |
priceOffsetPoints |
double |
Distance in points below current Ask (always positive) |
slPoints |
double? |
Optional stop-loss distance in points below entry price |
tpPoints |
double? |
Optional take-profit distance in points above entry price |
comment |
string? |
Optional order comment |
deviationPoints |
int |
Maximum price deviation in points (default: 0) |
timeoutSec |
int |
RPC timeout in seconds (default: 15) |
ct |
CancellationToken |
Cancellation token |
β¬οΈ OutputΒΆ
| Type | Description |
|---|---|
Task<OrderSendData> |
Order send result with ticket number and execution details |
Key fields:
Order- Order ticket number (ulong)ReturnedCode- MT5 return code (10009 = success)Comment- Server response comment
π¬ Just the essentialsΒΆ
- What it is: Buy Limit helper - places order BELOW current Ask using point-based offset instead of absolute price.
- Why you need it: No manual price calculation! Just say "50 points below" and SL/TP in points from entry.
- Sanity check: Buy Limit = buy BELOW current price (cheaper). Offset is always positive, method subtracts from Ask automatically.
π― PurposeΒΆ
Use it for:
- Buy on dips - Enter long when price pulls back
- Support level entries - Place orders at support zones
- Retracement trades - Buy after pullback in uptrend
- Dollar-cost averaging - Multiple Buy Limits at different levels
- Point-based strategies - Work in points, not prices
π§ Under the HoodΒΆ
// Step 1: Get current market quote
var tick = await svc.SymbolInfoTickAsync(symbol, deadline, ct);
var point = await svc.SymbolInfoDoubleAsync(symbol, SymbolPoint, deadline, ct);
// Step 2: Calculate entry price (BELOW Ask for Buy Limit)
var rawPrice = tick.Ask - Math.Abs(priceOffsetPoints) * point;
var price = await svc.NormalizePriceAsync(symbol, rawPrice, timeoutSec, ct);
// Step 3: Calculate SL/TP from entry price
double sl = slPoints.HasValue ? price - slPoints.Value * point : 0;
double tp = tpPoints.HasValue ? price + tpPoints.Value * point : 0;
// Step 4: Build and send pending order request (operationCode: 2 = BuyLimit)
var req = BuildPendingRequest(symbol, volume, price, sl, tp, comment, deviationPoints, 2);
return await svc.OrderSendAsync(req, deadline, ct);
What it improves:
- Auto price calculation - converts points to absolute price
- Auto Bid/Ask selection - uses Ask as base for Buy orders
- Auto normalization - price rounded to tick size
- Point-based SL/TP - distances from entry, not from current price
π Usage ExamplesΒΆ
Example 1: Basic Buy Limit 50 Points BelowΒΆ
// Buy Limit 50 points below current Ask
var result = await svc.BuyLimitPoints(
symbol: "EURUSD",
volume: 0.01,
priceOffsetPoints: 50);
if (result.ReturnedCode == 10009)
{
Console.WriteLine($"β
Buy Limit placed: Ticket #{result.Order}");
}
Example 2: Buy Limit with SL and TPΒΆ
// Buy Limit 30 points below with 20-point SL and 50-point TP
var result = await svc.BuyLimitPoints(
symbol: "EURUSD",
volume: 0.05,
priceOffsetPoints: 30,
slPoints: 20, // 20 points below entry
tpPoints: 50); // 50 points above entry
Console.WriteLine($"β
Order #{result.Order}");
Console.WriteLine($" Entry offset: 30 points below Ask");
Console.WriteLine($" SL: 20 points, TP: 50 points");
Example 3: Multiple Buy Limits (Grid Strategy)ΒΆ
// Place grid of Buy Limit orders at different levels
int[] offsets = { 20, 40, 60, 80, 100 };
Console.WriteLine("Placing Buy Limit grid:");
foreach (var offset in offsets)
{
var result = await svc.BuyLimitPoints(
"EURUSD",
0.01,
priceOffsetPoints: offset,
slPoints: 30,
tpPoints: 60);
if (result.ReturnedCode == 10009)
{
Console.WriteLine($" β
{offset}pts below: Ticket #{result.Order}");
}
}
// Output:
// Placing Buy Limit grid:
// β
20pts below: Ticket #12345
// β
40pts below: Ticket #12346
// β
60pts below: Ticket #12347
// β
80pts below: Ticket #12348
// β
100pts below: Ticket #12349
Example 4: ATR-Based Dynamic OffsetΒΆ
// Use ATR for dynamic offset calculation
double atr = 0.0015; // ATR value for EURUSD
double point = await svc.GetPointAsync("EURUSD");
// Convert ATR to points
double atrPoints = atr / point;
// Place Buy Limit at 0.5x ATR below (pullback entry)
double offset = atrPoints * 0.5;
var result = await svc.BuyLimitPoints(
"EURUSD",
0.01,
priceOffsetPoints: offset,
slPoints: atrPoints * 1.5, // 1.5x ATR stop
tpPoints: atrPoints * 3.0); // 3x ATR target
Console.WriteLine($"ATR-based Buy Limit: {offset:F0} points below");
Console.WriteLine($" SL: {atrPoints * 1.5:F0}pts, TP: {atrPoints * 3.0:F0}pts");
Example 5: Support Level EntryΒΆ
public async Task PlaceBuyAtSupport(
MT5Service svc,
string symbol,
double supportLevel)
{
// Get current Ask
var tick = await svc.SymbolInfoTickAsync(symbol);
double point = await svc.GetPointAsync(symbol);
// Calculate offset from current Ask to support level
double offsetPrice = tick.Ask - supportLevel;
double offsetPoints = offsetPrice / point;
if (offsetPoints > 0) // Support is below current price
{
var result = await svc.BuyLimitPoints(
symbol,
0.01,
priceOffsetPoints: offsetPoints,
slPoints: 50,
tpPoints: 150);
Console.WriteLine($"β
Buy Limit at support {supportLevel:F5}");
Console.WriteLine($" Offset: {offsetPoints:F0} points below Ask");
}
else
{
Console.WriteLine($"β οΈ Support {supportLevel:F5} is above current Ask!");
}
}
// Usage:
await PlaceBuyAtSupport(svc, "EURUSD", supportLevel: 1.0850);
Example 6: With Order CommentΒΆ
// Buy Limit with strategy identifier
var result = await svc.BuyLimitPoints(
symbol: "GBPUSD",
volume: 0.02,
priceOffsetPoints: 40,
slPoints: 30,
tpPoints: 90,
comment: "BuyDip_Strategy_v2");
Console.WriteLine($"β
Order #{result.Order} - Comment: BuyDip_Strategy_v2");
Example 7: Calculate Entry Price Before PlacingΒΆ
var tick = await svc.SymbolInfoTickAsync("EURUSD");
double point = await svc.GetPointAsync("EURUSD");
double offsetPoints = 50;
// Calculate what the entry price will be
double entryPrice = tick.Ask - offsetPoints * point;
Console.WriteLine($"Current Ask: {tick.Ask:F5}");
Console.WriteLine($"Entry will be: {entryPrice:F5} (50 points below)");
Console.WriteLine($"Placing order...");
var result = await svc.BuyLimitPoints(
"EURUSD",
0.01,
priceOffsetPoints: offsetPoints,
slPoints: 20,
tpPoints: 60);
Console.WriteLine($"β
Order #{result.Order} placed at ~{entryPrice:F5}");
Example 8: Error HandlingΒΆ
try
{
var result = await svc.BuyLimitPoints(
"EURUSD",
0.01,
priceOffsetPoints: 50,
slPoints: 20,
tpPoints: 60);
if (result.ReturnedCode == 10009)
{
Console.WriteLine($"β
Success: Ticket #{result.Order}");
}
else
{
Console.WriteLine($"β Order failed: {result.Comment}");
Console.WriteLine($" Return code: {result.ReturnedCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"β Exception: {ex.Message}");
}
Example 9: Risk-Based Volume with Buy LimitΒΆ
// Calculate volume based on risk
double riskMoney = 100.0;
double slPoints = 30;
double volume = await svc.CalcVolumeForRiskAsync(
"EURUSD",
stopPoints: slPoints,
riskMoney: riskMoney);
// Place Buy Limit with calculated volume
var result = await svc.BuyLimitPoints(
"EURUSD",
volume: volume,
priceOffsetPoints: 40,
slPoints: slPoints,
tpPoints: 100);
Console.WriteLine($"β
Risk-based order placed:");
Console.WriteLine($" Volume: {volume} lots");
Console.WriteLine($" Risk: ${riskMoney} if SL hit");
Console.WriteLine($" Ticket: #{result.Order}");
Example 10: Compare Manual vs Auto CalculationΒΆ
var tick = await svc.SymbolInfoTickAsync("EURUSD");
double point = await svc.GetPointAsync("EURUSD");
double offsetPoints = 50;
double slPoints = 20;
double tpPoints = 60;
// β MANUAL WAY (error-prone):
double entryPriceManual = tick.Ask - offsetPoints * point;
entryPriceManual = await svc.NormalizePriceAsync("EURUSD", entryPriceManual);
double slManual = entryPriceManual - slPoints * point;
double tpManual = entryPriceManual + tpPoints * point;
var reqManual = new OrderSendRequest
{
Symbol = "EURUSD",
Volume = 0.01,
Price = entryPriceManual,
StopLoss = slManual,
TakeProfit = tpManual,
Operation = ENUM_ORDER_TYPE.OrderTypeBuyLimit
};
var resultManual = await svc.OrderSendAsync(reqManual);
Console.WriteLine($"Manual way: {resultManual.Order}");
// β
AUTO WAY (clean):
var resultAuto = await svc.BuyLimitPoints(
"EURUSD",
0.01,
priceOffsetPoints: 50,
slPoints: 20,
tpPoints: 60);
Console.WriteLine($"Auto way: {resultAuto.Order}");
π Related MethodsΒΆ
π¦ Methods used internally:
SymbolInfoTickAsync()- Gets current Bid/AskSymbolInfoDoubleAsync(SymbolPoint)- Gets point sizeNormalizePriceAsync()- Normalizes entry priceOrderSendAsync()- Sends pending order request
π¬ Related Sugar methods:
SellLimitPoints()- Sell Limit with point-based offsetBuyStopPoints()- Buy Stop with point-based offsetSellStopPoints()- Sell Stop with point-based offsetPlacePending()- Generic pending order (requires absolute price)PriceFromOffsetPointsAsync()- Calculate price only (no order placement)
π Alternative approaches:
PlacePending()- More flexible but requires manual price calculationPriceFromOffsetPointsAsync()+PlacePending()- Two-step approach
β οΈ Common PitfallsΒΆ
-
Confusing offset direction:
-
Negative offset (method handles it):
-
SL/TP direction confusion:
-
Using pips instead of points:
// β WRONG: Confusing pips with points await svc.BuyLimitPoints("EURUSD", 0.01, priceOffsetPoints: 5); // For 5-digit broker, this is 0.5 pips, not 5 pips! // β CORRECT: Convert pips to points for 5-digit brokers double pips = 5; double points = pips * 10; // 1 pip = 10 points on 5-digit await svc.BuyLimitPoints("EURUSD", 0.01, priceOffsetPoints: points); -
Offset too small (broker minimum distance):
// β May fail if offset violates broker's minimum stop level await svc.BuyLimitPoints("EURUSD", 0.01, priceOffsetPoints: 5); // Broker may require minimum 10 points distance // β CORRECT: Check broker requirements // Most brokers require 10-50 points minimum for pending orders await svc.BuyLimitPoints("EURUSD", 0.01, priceOffsetPoints: 50);
π‘ SummaryΒΆ
BuyLimitPoints simplifies Buy Limit order placement:
- β Work in points, not absolute prices
- β Auto-calculates entry price BELOW Ask
- β SL/TP as point distances from entry
- β Auto-normalizes prices to tick size
- β Perfect for buy-on-dip strategies
// Instead of manual calculation:
var tick = await svc.SymbolInfoTickAsync("EURUSD");
double price = tick.Ask - 50 * 0.00001; // β Manual, error-prone
await svc.PlacePending("EURUSD", 0.01, ENUM_ORDER_TYPE.OrderTypeBuyLimit, price, ...);
// Use one clean call:
await svc.BuyLimitPoints("EURUSD", 0.01, priceOffsetPoints: 50); // β
Clean!
Buy the dip with precision! π