Price from Offset Points (PriceFromOffsetPointsAsync)¶
Sugar method: Calculates pending order price by offset in points from current market price - no manual calculation needed!
API Information:
- Extension method:
MT5Service.PriceFromOffsetPointsAsync(...)(fromMT5ServiceExtensions) - Package: Part of
mt5_term_apilibrary - Region: [08] VOLUME & PRICE UTILITIES
- Underlying calls:
SymbolInfoTickAsync()+SymbolInfoDoubleAsync()+NormalizePriceAsync()
Method Signature¶
public static async Task<double> PriceFromOffsetPointsAsync(
this MT5Service svc,
string symbol,
ENUM_ORDER_TYPE type,
double offsetPoints,
int timeoutSec = 10,
CancellationToken ct = default)
🔽 Input¶
| Parameter | Type | Description |
|---|---|---|
svc |
MT5Service |
MT5Service instance (extension method) |
symbol |
string |
Symbol name (e.g., "EURUSD", "XAUUSD") |
type |
ENUM_ORDER_TYPE |
Order type (BuyLimit, SellLimit, BuyStop, SellStop) |
offsetPoints |
double |
Distance in points from current price |
timeoutSec |
int |
RPC timeout in seconds (default: 10) |
ct |
CancellationToken |
Cancellation token |
⬆️ Output¶
| Type | Description |
|---|---|
Task<double> |
Normalized price for pending order placement |
💬 Just the essentials¶
- What it is: Auto-calculates pending order price from point offset - handles Bid/Ask selection and normalization.
- Why you need it: No manual price calculation! Just say "50 points above/below" and get exact price.
- Sanity check: BUY orders use Ask as base, SELL orders use Bid. Result is normalized to tick size.
🎯 Purpose¶
Use it for:
- Pending order placement - Calculate entry price by points offset
- Point-based strategies - Work in points, not prices
- Dynamic price levels - Offset from current market, not fixed prices
- Simplified order logic - Less math, clearer intent
- Error prevention - Auto-selects correct base price (Bid/Ask)
🔧 Under the Hood¶
var deadline = DateTime.UtcNow.AddSeconds(timeoutSec);
// Step 1: Get current quote
var tick = await svc.SymbolInfoTickAsync(symbol, deadline, ct);
// Step 2: Get point size
var point = await svc.SymbolInfoDoubleAsync(symbol, SymbolPoint, deadline, ct);
// Step 3: Determine base price (Ask for BUY, Bid for SELL)
int orderTypeInt = Convert.ToInt32((object)type);
bool isBuy = orderTypeInt == 0 || orderTypeInt == 2 || orderTypeInt == 4 || orderTypeInt == 6;
double basePrice = isBuy ? tick.Ask : tick.Bid;
// Step 4: Calculate price with offset
// BUY orders: Add offset (above Ask)
// SELL orders: Subtract offset (below Bid)
double rawPrice = basePrice + (isBuy ? +1.0 : -1.0) * (offsetPoints * point);
// Step 5: Normalize to tick size
return await svc.NormalizePriceAsync(symbol, rawPrice, timeoutSec, ct);
What it improves:
- Auto Bid/Ask selection - uses correct base price for order type
- Auto direction - BUY adds, SELL subtracts
- Auto normalization - result is broker-ready
- Point-based thinking - work in points, not raw prices
🔗 Usage Examples¶
Example 1: Buy Limit 50 Points Below¶
// Buy Limit 50 points below current Ask
double price = await svc.PriceFromOffsetPointsAsync(
symbol: "EURUSD",
type: ENUM_ORDER_TYPE.OrderTypeBuyLimit,
offsetPoints: 50);
Console.WriteLine($"Buy Limit price: {price:F5}");
// Place order at calculated price
await svc.PlacePending("EURUSD", 0.01, ENUM_ORDER_TYPE.OrderTypeBuyLimit,
price, sl: price - 50 * point, tp: price + 100 * point);
Example 2: Sell Limit 30 Points Above¶
// Sell Limit 30 points above current Bid
double price = await svc.PriceFromOffsetPointsAsync(
symbol: "GBPUSD",
type: ENUM_ORDER_TYPE.OrderTypeSellLimit,
offsetPoints: 30);
Console.WriteLine($"Sell Limit price: {price:F5}");
await svc.PlacePending("GBPUSD", 0.05, ENUM_ORDER_TYPE.OrderTypeSellLimit,
price, sl: price + 40 * point, tp: price - 80 * point);
Example 3: Buy Stop 40 Points Above (Breakout)¶
// Buy Stop 40 points above current Ask (breakout long)
double price = await svc.PriceFromOffsetPointsAsync(
symbol: "XAUUSD",
type: ENUM_ORDER_TYPE.OrderTypeBuyStop,
offsetPoints: 40);
Console.WriteLine($"Buy Stop price (breakout): {price:F2}");
await svc.PlacePending("XAUUSD", 0.01, ENUM_ORDER_TYPE.OrderTypeBuyStop,
price, sl: price - 30 * point, tp: price + 100 * point);
Example 4: Sell Stop 25 Points Below (Breakdown)¶
// Sell Stop 25 points below current Bid (breakdown short)
double price = await svc.PriceFromOffsetPointsAsync(
symbol: "USDJPY",
type: ENUM_ORDER_TYPE.OrderTypeSellStop,
offsetPoints: 25);
Console.WriteLine($"Sell Stop price (breakdown): {price:F3}");
await svc.PlacePending("USDJPY", 0.1, ENUM_ORDER_TYPE.OrderTypeSellStop,
price, sl: price + 35 * point, tp: price - 75 * point);
Example 5: Compare Manual vs Auto Calculation¶
// ❌ MANUAL WAY (error-prone):
var tick = await svc.SymbolInfoTickAsync("EURUSD");
var point = await svc.GetPointAsync("EURUSD");
// For Buy Limit: use Ask as base, subtract offset
double manualPrice = tick.Ask - (50 * point);
// Need to normalize manually too!
manualPrice = await svc.NormalizePriceAsync("EURUSD", manualPrice);
Console.WriteLine($"Manual calculation: {manualPrice:F5}");
// ✅ AUTO WAY (clean):
double autoPrice = await svc.PriceFromOffsetPointsAsync(
"EURUSD",
ENUM_ORDER_TYPE.OrderTypeBuyLimit,
50);
Console.WriteLine($"Auto calculation: {autoPrice:F5}");
// Both should be identical
Console.WriteLine($"Match: {Math.Abs(manualPrice - autoPrice) < 0.000001}");
Example 6: Dynamic Pending Order Grid¶
// Place grid of Buy Limit orders at different levels
int[] offsets = { 20, 40, 60, 80, 100 };
Console.WriteLine("Buy Limit Grid:");
foreach (var offset in offsets)
{
double price = await svc.PriceFromOffsetPointsAsync(
"EURUSD",
ENUM_ORDER_TYPE.OrderTypeBuyLimit,
offset);
Console.WriteLine($" {offset}pts below: {price:F5}");
// Place order
await svc.PlacePending("EURUSD", 0.01,
ENUM_ORDER_TYPE.OrderTypeBuyLimit, price);
}
// Output:
// Buy Limit Grid:
// 20pts below: 1.09030
// 40pts below: 1.09010
// 60pts below: 1.08990
// 80pts below: 1.08970
// 100pts below: 1.08950
Example 7: ATR-Based Pending Order¶
// Use ATR indicator for dynamic offset
double atr = 0.0015; // ATR value
double point = await svc.GetPointAsync("EURUSD");
// Convert ATR to points
double atrPoints = atr / point;
// Place Buy Stop 1.5x ATR above (breakout)
double buyStopOffset = atrPoints * 1.5;
double buyStopPrice = await svc.PriceFromOffsetPointsAsync(
"EURUSD",
ENUM_ORDER_TYPE.OrderTypeBuyStop,
buyStopOffset);
// Place Sell Stop 1.5x ATR below (breakdown)
double sellStopOffset = atrPoints * 1.5;
double sellStopPrice = await svc.PriceFromOffsetPointsAsync(
"EURUSD",
ENUM_ORDER_TYPE.OrderTypeSellStop,
sellStopOffset);
Console.WriteLine($"ATR: {atr:F5} ({atrPoints:F0} points)");
Console.WriteLine($"Buy Stop (1.5x ATR): {buyStopPrice:F5}");
Console.WriteLine($"Sell Stop (1.5x ATR): {sellStopPrice:F5}");
Example 8: Support/Resistance Offset Orders¶
public async Task PlaceBreakoutOrders(
MT5Service svc,
string symbol,
double resistanceOffset,
double supportOffset)
{
// Buy Stop above resistance
double buyStopPrice = await svc.PriceFromOffsetPointsAsync(
symbol,
ENUM_ORDER_TYPE.OrderTypeBuyStop,
resistanceOffset);
// Sell Stop below support
double sellStopPrice = await svc.PriceFromOffsetPointsAsync(
symbol,
ENUM_ORDER_TYPE.OrderTypeSellStop,
supportOffset);
Console.WriteLine($"Breakout Orders for {symbol}:");
Console.WriteLine($" Buy Stop: {buyStopPrice:F5} ({resistanceOffset}pts above)");
Console.WriteLine($" Sell Stop: {sellStopPrice:F5} ({supportOffset}pts below)");
// Place orders
await svc.PlacePending(symbol, 0.01, ENUM_ORDER_TYPE.OrderTypeBuyStop, buyStopPrice);
await svc.PlacePending(symbol, 0.01, ENUM_ORDER_TYPE.OrderTypeSellStop, sellStopPrice);
}
// Usage:
await PlaceBreakoutOrders(svc, "EURUSD", resistanceOffset: 50, supportOffset: 50);
Example 9: All Order Types Example¶
string symbol = "EURUSD";
double offset = 30; // 30 points
var orderTypes = new[]
{
(ENUM_ORDER_TYPE.OrderTypeBuyLimit, "Buy Limit"),
(ENUM_ORDER_TYPE.OrderTypeSellLimit, "Sell Limit"),
(ENUM_ORDER_TYPE.OrderTypeBuyStop, "Buy Stop"),
(ENUM_ORDER_TYPE.OrderTypeSellStop, "Sell Stop")
};
Console.WriteLine($"Prices for {offset}pt offset on {symbol}:");
Console.WriteLine("");
foreach (var (type, label) in orderTypes)
{
double price = await svc.PriceFromOffsetPointsAsync(symbol, type, offset);
Console.WriteLine($"{label,-12}: {price:F5}");
}
// Output:
// Prices for 30pt offset on EURUSD:
//
// Buy Limit : 1.09020
// Sell Limit : 1.09080
// Buy Stop : 1.09080
// Sell Stop : 1.08990
Example 10: Validate Calculated Price¶
var tick = await svc.SymbolInfoTickAsync("EURUSD");
double offsetPoints = 50;
double price = await svc.PriceFromOffsetPointsAsync(
"EURUSD",
ENUM_ORDER_TYPE.OrderTypeBuyLimit,
offsetPoints);
Console.WriteLine($"Current Ask: {tick.Ask:F5}");
Console.WriteLine($"Calculated price: {price:F5}");
// For Buy Limit, price should be BELOW Ask
if (price < tick.Ask)
{
double diff = tick.Ask - price;
double point = await svc.GetPointAsync("EURUSD");
double pointsDiff = diff / point;
Console.WriteLine($"✅ Valid: {pointsDiff:F0} points below Ask");
}
else
{
Console.WriteLine($"❌ Invalid: Price should be below Ask for Buy Limit!");
}
🔗 Related Methods¶
📦 Methods used internally:
SymbolInfoTickAsync()- Gets current Bid/AskSymbolInfoDoubleAsync(SymbolPoint)- Gets point sizeNormalizePriceAsync()- Normalizes calculated price
🍬 Methods that use this:
BuyLimitPoints()- Uses this for Buy Limit price calculationSellLimitPoints()- Uses this for Sell Limit price calculationBuyStopPoints()- Uses this for Buy Stop price calculationSellStopPoints()- Uses this for Sell Stop price calculation
📊 Alternative approaches:
- Manual calculation using SymbolInfoTickAsync + GetPointAsync (verbose)
- Point-based pending helpers (simpler but less flexible)
⚠️ Common Pitfalls¶
-
Confusing offset direction:
-
Using wrong order type:
// ❌ WRONG: Using market order type double price = await svc.PriceFromOffsetPointsAsync( "EURUSD", ENUM_ORDER_TYPE.OrderTypeBuy, // ❌ Market order! 50); // ✅ CORRECT: Use pending order type double price = await svc.PriceFromOffsetPointsAsync( "EURUSD", ENUM_ORDER_TYPE.OrderTypeBuyLimit, // ✅ Pending order 50); -
Not understanding Bid/Ask basis:
📊 Price Calculation Summary¶
| Order Type | Base Price | Direction | Result |
|---|---|---|---|
| BuyLimit | Ask | Down (−) | Ask − (offset × point) |
| SellLimit | Bid | Up (+) | Bid + (offset × point) |
| BuyStop | Ask | Up (+) | Ask + (offset × point) |
| SellStop | Bid | Down (−) | Bid − (offset × point) |
💡 Summary¶
PriceFromOffsetPointsAsync simplifies pending order pricing:
- ✅ Auto-selects base price (Bid/Ask)
- ✅ Auto-applies offset direction
- ✅ Auto-normalizes result
- ✅ Work in points, not raw prices
// Instead of manual calculation:
var tick = await svc.SymbolInfoTickAsync("EURUSD");
var point = await svc.GetPointAsync("EURUSD");
double price = tick.Ask - (50 * point); // ❌ Manual, error-prone
price = await svc.NormalizePriceAsync("EURUSD", price);
// Use one clean call:
double price = await svc.PriceFromOffsetPointsAsync(
"EURUSD",
ENUM_ORDER_TYPE.OrderTypeBuyLimit,
50); // ✅ Auto everything!
Think in points, get perfect prices! 🚀