Complete mapping of During-Trade Spec to MetaAPI endpoints and fields
These fields are directly available from MetaAPI positions endpoint.
const positions = await connection.readPositions(); const symbol = positions[0].symbol; // e.g., "EURUSD"
id as the position identifier. This is equivalent to ticket.
const positions = await connection.readPositions(); const ticket = positions[0].id; // Position ID/ticket
const positions = await connection.readPositions(); const entryTime = new Date(positions[0].openTime);
POSITION_TYPE_BUY or POSITION_TYPE_SELL. Convert to "Buy"/"Sell" for display.
const positions = await connection.readPositions(); const positionType = positions[0].type; const tradeType = positionType === 'POSITION_TYPE_BUY' ? 'Buy' : 'Sell';
const positions = await connection.readPositions(); const entryPrice = positions[0].openPrice;
const positions = await connection.readPositions(); const volume = positions[0].volume; // in lots
stopLoss may be null or 0 if not set. This should trigger a warning: "Stoploss required" and status "High risk".
const positions = await connection.readPositions();
const stopLoss = positions[0].stopLoss;
if (!stopLoss || stopLoss === 0) {
warnings.push('Stoploss required');
status = 'High risk';
}
null if not set. This is acceptable (not required like SL).
const positions = await connection.readPositions(); const takeProfit = positions[0].takeProfit; // may be null
// From position const currentPrice = positions[0].currentPrice; // Or from symbol price const symbolPrice = await connection.readSymbolPrice(symbol); const currentPrice = symbolPrice.ask; // or bid, depending on position type
profit is floating P/L. For closed positions, use deals.
// For open positions const positions = await connection.readPositions(); const floatingPL = positions[0].profit; // For closed positions (from deals) const deals = await connection.readDealsByPosition(positionId); const realizedPL = deals.reduce((sum, deal) => sum + deal.profit, 0);
These fields are calculated from MetaAPI data and require symbol specifications.
contractValuePerPoint = tickValue / tickSize
// Get symbol specification
const spec = await connection.readSymbolSpecification(symbol);
const contractValuePerPoint = spec.tickValue / spec.tickSize;
// Calculate trade risk
const hasSL = position.stopLoss != null && position.stopLoss !== 0;
const tradeRiskUsd = hasSL
? Math.abs(position.openPrice - position.stopLoss) * contractValuePerPoint * position.volume
: null;
if (!hasSL) {
warnings.push('Stoploss required');
}
const hasTP = position.takeProfit != null && position.takeProfit !== 0; const tradeRewardUsd = hasTP ? Math.abs(position.takeProfit - position.openPrice) * contractValuePerPoint * position.volume : null;
const rewardRisk = (tradeRiskUsd && tradeRiskUsd > 0 && tradeRewardUsd != null)
? tradeRewardUsd / tradeRiskUsd
: null;
if (!rewardRisk) {
warnings.push('R/R cannot be calculated: missing SL or TP');
}
// Check against minimum R/R
if (rewardRisk != null && rewardRisk < cfg.minRR) {
blocks.push('R/R too low');
}
Compare actual trade with pre-trade plan to determine if trade is within plan.
// Get pre-trade plan from database
const plan = await getPretradePlan(symbol, ticket);
if (plan && plan.plannedEntry && plan.plannedSL && plan.plannedTP) {
// Calculate deviations
const dEntry = Math.abs(position.openPrice - plan.plannedEntry) / plan.plannedEntry;
const dSL = position.stopLoss
? Math.abs(position.stopLoss - plan.plannedSL) / plan.plannedSL
: Infinity;
const dTP = position.takeProfit
? Math.abs(position.takeProfit - plan.plannedTP) / plan.plannedTP
: Infinity;
const maxDev = Math.max(dEntry, dSL, dTP);
const inPlan = maxDev <= cfg.planTolerancePct;
if (!inPlan) {
warnings.push(`Out-of-plan: deviation ${(maxDev * 100).toFixed(2)}% > ${(cfg.planTolerancePct * 100).toFixed(2)}%`);
}
}
Rules for determining trade status and warnings/blocks.
stopLoss == null ⇒ warning("Stoploss required"), status = "High risk" (red), may block new orders.
tradeRiskUsd > maxRiskPerTradeUsd ⇒ warning("Risk/Trade exceeded"), status = "High risk" (red).
rewardRisk < minRR ⇒ block("R/R too low") or warning (per policy).
// Status determination logic
let status = 'Safe';
const warnings = [];
const blocks = [];
// Rule 1: Missing SL
if (!position.stopLoss || position.stopLoss === 0) {
warnings.push('Stoploss required');
status = 'High risk';
}
// Rule 2: Risk/Trade exceeded
if (tradeRiskUsd && cfg.maxRiskPerTradeUsd && tradeRiskUsd > cfg.maxRiskPerTradeUsd) {
warnings.push('Risk/Trade exceeded');
status = 'High risk';
}
// Rule 3: R/R too low
if (rewardRisk != null && rewardRisk < cfg.minRR) {
blocks.push('R/R too low');
status = 'High risk';
}
// Rule 4: Out-of-plan
if (inPlan === false) {
status = status === 'Safe' ? 'Out-of-plan' : status;
}
// Rule 5: Info status for minor warnings
if (status === 'Safe' && warnings.length > 0) {
status = 'Info';
}
| Code | Field | Status | MetaAPI Endpoint | Field Path | Notes |
|---|---|---|---|---|---|
| 5b | Symbol | AVAILABLE | readPositions() | positions[].symbol | - |
| 3c | Ticket | AVAILABLE | readPositions() | positions[].id | Position ID = Ticket |
| 4c | Time | AVAILABLE | readPositions() | positions[].openTime | - |
| 6b | Trade Type | AVAILABLE | readPositions() | positions[].type | Convert to "Buy"/"Sell" |
| 9b | Entry Price | AVAILABLE | readPositions() | positions[].openPrice | - |
| 10b | Volume | AVAILABLE | readPositions() | positions[].volume | In lots |
| 11b | Stop Loss | AVAILABLE | readPositions() | positions[].stopLoss | ⚠️ May be null - trigger warning |
| 14b | Take Profit | AVAILABLE | readPositions() | positions[].takeProfit | May be null (ok) |
| 14 | Price (Current) | AVAILABLE | readPositions() or readSymbolPrice() | positions[].currentPrice | - |
| 15 | P/L | AVAILABLE | readPositions() or readDealsByPosition() | positions[].profit | Floating PL or realized PL |
| 13b | Trade Risk (USD) | PARTIAL | Calculated | |entry - SL| × contractValue × volume | Requires symbol spec + positions |
| 16b | Trade Profit (USD) | PARTIAL | Calculated | |TP - entry| × contractValue × volume | Requires symbol spec + positions |
| 7a | Reward/Risk | PARTIAL | Calculated | tradeReward / tradeRisk | Requires both risk and profit |
| 1c/2c | In-plan / Out-of-plan | MISSING | - | - | Requires pre-trade plan from DB |
| 16 | Status | PARTIAL | Calculated | Rule engine output | Based on rules + config |
| - | contractValuePerPoint | PARTIAL | readSymbolSpecification() | tickValue / tickSize | Calculate from spec |
| - | plannedEntry/SL/TP/Volume | MISSING | - | - | Store in database |
| - | minRR, maxRiskPerTradeUsd, planTolerancePct | MISSING | - | - | Configuration values - store in DB/config |