✏️ Modify Order or Position¶
Request: modify existing order or position parameters - update Stop Loss, Take Profit, price (for pending orders), or expiration time.
API Information:
- SDK wrapper:
MT5Account.orderModify(...)(from packageio.metarpc.mt5) - gRPC service:
mt5_term_api.TradingHelper - Proto definition:
OrderModify(defined inmt5-term-api-trading-helper.proto)
RPC¶
- Service:
mt5_term_api.TradingHelper - Method:
OrderModify(OrderModifyRequest) → OrderModifyReply - Low‑level client (generated):
TradingHelperGrpc.TradingHelperBlockingStub.orderModify(request) - SDK wrapper (high-level):
package io.metarpc.mt5;
public class MT5Account {
/**
* Modifies an existing order or position parameters.
* Use this to update stop loss, take profit, price, or other parameters of an open position or pending order.
*
* @param request Modification request with order ticket and new parameters to update
* @return Response indicating success or failure of the modification
* @throws ApiExceptionMT5 if the modification fails or connection is lost
*/
public Mt5TermApiTradingHelper.OrderModifyReply orderModify(
Mt5TermApiTradingHelper.OrderModifyRequest request) throws ApiExceptionMT5;
}
Request message: OrderModifyRequest { ticket, stop_loss?, take_profit?, price?, expiration_time_type?, expiration_time?, stop_limit? }
Reply message: OrderModifyReply { data: OrderModifyData } or { error: Error }
🔽 Input - OrderModifyRequest¶
| Parameter | Type | Required | Description |
|---|---|---|---|
ticket |
long |
✅ | Order or position ticket number |
stop_loss |
double |
❌ | New Stop Loss price level |
take_profit |
double |
❌ | New Take Profit price level |
price |
double |
❌ | New order price (pending orders only) |
expiration_time_type |
TMT5_ENUM_ORDER_TYPE_TIME |
❌ | New expiration type (pending orders only) |
expiration_time |
Timestamp |
❌ | New expiration time (pending orders only) |
stop_limit |
double |
❌ | New stop limit price (stop-limit orders only) |
Important:
- ticket is the only required field
- At least one optional parameter must be provided
- price, expiration_time_type, expiration_time, stop_limit - only for pending orders
- stop_loss, take_profit - for both positions and pending orders
Enum: TMT5_ENUM_ORDER_TYPE_TIME (Time-in-Force)¶
| Value | Number | Description |
|---|---|---|
TMT5_ORDER_TIME_GTC |
0 | Good Till Cancel (default) |
TMT5_ORDER_TIME_DAY |
1 | Good Till End of Trading Day |
TMT5_ORDER_TIME_SPECIFIED |
2 | Good Till Specified Time |
TMT5_ORDER_TIME_SPECIFIED_DAY |
3 | Good Till End of Specified Day (23:59:59) |
⬆️ Output - OrderModifyData¶
| Field | Type | Description |
|---|---|---|
returned_code |
int |
Operation return code (10009 = success) |
deal |
long |
Deal ticket (usually 0 for modify operations) |
order |
long |
Order ticket that was modified |
volume |
double |
Order volume |
price |
double |
Current/modified price |
bid |
double |
Current Bid price |
ask |
double |
Current Ask price |
comment |
String |
Broker comment (error description if failed) |
request_id |
int |
Request ID |
Success Code:¶
10009- TRADE_RETCODE_DONE - Modification successful
Common Error Codes:¶
10004- TRADE_RETCODE_REJECT - Request rejected10016- TRADE_RETCODE_INVALID_STOPS - Invalid stop levels10025- TRADE_RETCODE_INVALID_FILL - Invalid fill type10027- TRADE_RETCODE_ERROR_ORDER - Order not found
💬 Just the essentials¶
- What it is. RPC to modify existing orders or positions.
- For positions. Update Stop Loss and Take Profit only.
- For pending orders. Can also modify price, expiration, stop limit.
- At least one change. Must provide at least one parameter to modify.
- Return code. Check
returned_code- 10009 means success. - No partial changes. If modification fails, no changes are applied.
- Use cases. Trailing stops, breakeven stops, TP adjustment, order price updates.
🎯 Purpose¶
Use this method when you need to:
- Add or update Stop Loss on an open position.
- Add or update Take Profit on an open position.
- Implement trailing stop logic.
- Move stops to breakeven after profit target.
- Adjust pending order prices.
- Update order expiration times.
- Protect profits by moving stops.
🧩 Notes & Tips¶
- Ticket required. Must provide valid ticket number of order or position.
- Positions. Can only modify SL/TP for open positions.
- Pending orders. Can modify price, SL/TP, expiration, and stop limit.
- Stop levels. Broker enforces minimum distance from current price.
- Zero to remove. Set SL or TP to 0.0 to remove protection.
- Price validation. Broker validates stop levels based on symbol properties.
- Return code. Always check
returned_codefor success (10009). - Auto-reconnect. Uses
executeWithReconnect()for reliability.
🔗 Usage Examples¶
1) Add Stop Loss to position¶
import io.metarpc.mt5.MT5Account;
import io.metarpc.mt5.exceptions.ApiExceptionMT5;
import mt5_term_api.Mt5TermApiTradingHelper;
public class Example {
public static void main(String[] args) {
MT5Account account = new MT5Account(12345678, "password");
try {
account.connect("demo.mt5server.com", 443, "EURUSD");
long positionTicket = 123456789; // Your position ticket
// Add Stop Loss
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(positionTicket)
.setStopLoss(1.09500)
.build();
Mt5TermApiTradingHelper.OrderModifyReply reply =
account.orderModify(request);
var data = reply.getData();
if (data.getReturnedCode() == 10009) {
System.out.printf("✅ Stop Loss set to %.5f%n", 1.09500);
} else {
System.out.printf("❌ Modification failed: %s (code: %d)%n",
data.getComment(), data.getReturnedCode());
}
} catch (ApiExceptionMT5 e) {
System.err.println("Error: " + e.getMessage());
} finally {
account.close();
}
}
}
2) Update both SL and TP¶
public class StopModifier {
/**
* Update Stop Loss and Take Profit
*/
public static boolean updateStops(
MT5Account account,
long ticket,
double newStopLoss,
double newTakeProfit) throws ApiExceptionMT5 {
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setStopLoss(newStopLoss)
.setTakeProfit(newTakeProfit)
.build();
var reply = account.orderModify(request);
var data = reply.getData();
if (data.getReturnedCode() == 10009) {
System.out.printf("✅ Updated stops for ticket #%d%n", ticket);
System.out.printf(" Stop Loss: %.5f%n", newStopLoss);
System.out.printf(" Take Profit: %.5f%n", newTakeProfit);
return true;
} else {
System.out.printf("❌ Failed: %s (code: %d)%n",
data.getComment(), data.getReturnedCode());
return false;
}
}
}
// Usage
boolean success = StopModifier.updateStops(
account,
123456789, // Ticket
1.09500, // New SL
1.10500 // New TP
);
3) Trailing stop implementation¶
public class TrailingStop {
/**
* Implement trailing stop logic
*/
public static void trailStop(
MT5Account account,
long ticket,
boolean isBuy,
int trailDistancePips) throws ApiExceptionMT5 {
// Get current position info
var positions = account.openedOrders(
Mt5TermApiAccountHelper.BMT5_ENUM_OPENED_ORDER_SORT_TYPE.BMT5_SORT_BY_TICKET_ASC
).getData().getPositionInfosList();
var position = positions.stream()
.filter(p -> p.getTicket() == ticket)
.findFirst()
.orElseThrow(() -> new ApiExceptionMT5("Position not found"));
double currentPrice = position.getPriceCurrent();
double currentSL = position.getStopLoss();
String symbol = position.getSymbol();
// Calculate pip value
double pipValue = symbol.contains("JPY") ? 0.01 : 0.0001;
double trailDistance = trailDistancePips * pipValue;
// Calculate new SL
double newSL;
if (isBuy) {
newSL = currentPrice - trailDistance;
// Only move SL up, never down
if (currentSL > 0 && newSL <= currentSL) {
System.out.println("SL already optimal, no update needed");
return;
}
} else {
newSL = currentPrice + trailDistance;
// Only move SL down, never up
if (currentSL > 0 && newSL >= currentSL) {
System.out.println("SL already optimal, no update needed");
return;
}
}
// Update SL
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setStopLoss(newSL)
.build();
var reply = account.orderModify(request);
if (reply.getData().getReturnedCode() == 10009) {
System.out.printf("✅ Trailing stop updated: %.5f → %.5f%n",
currentSL, newSL);
} else {
System.out.printf("❌ Failed to update: %s%n",
reply.getData().getComment());
}
}
}
// Usage - trail stop 50 pips behind current price
TrailingStop.trailStop(account, 123456789, true, 50);
4) Move stop to breakeven¶
public class BreakevenStop {
/**
* Move stop loss to breakeven when profit threshold reached
*/
public static boolean moveToBreakeven(
MT5Account account,
long ticket,
boolean isBuy,
int profitThresholdPips,
int breakevenOffsetPips) throws ApiExceptionMT5 {
// Get position
var positions = account.openedOrders(
Mt5TermApiAccountHelper.BMT5_ENUM_OPENED_ORDER_SORT_TYPE.BMT5_SORT_BY_TICKET_ASC
).getData().getPositionInfosList();
var position = positions.stream()
.filter(p -> p.getTicket() == ticket)
.findFirst()
.orElseThrow(() -> new ApiExceptionMT5("Position not found"));
String symbol = position.getSymbol();
double openPrice = position.getPriceOpen();
double currentPrice = position.getPriceCurrent();
double currentSL = position.getStopLoss();
// Calculate pip value
double pipValue = symbol.contains("JPY") ? 0.01 : 0.0001;
// Calculate profit in pips
double profitPips;
if (isBuy) {
profitPips = (currentPrice - openPrice) / pipValue;
} else {
profitPips = (openPrice - currentPrice) / pipValue;
}
System.out.printf("Current profit: %.1f pips%n", profitPips);
// Check if threshold reached
if (profitPips < profitThresholdPips) {
System.out.printf("Threshold not reached (need %.1f pips)%n",
(double) profitThresholdPips);
return false;
}
// Calculate breakeven price with offset
double breakevenPrice = openPrice + (breakevenOffsetPips * pipValue * (isBuy ? 1 : -1));
// Check if already at breakeven or better
if (isBuy && currentSL >= breakevenPrice) {
System.out.println("Already at breakeven or better");
return false;
}
if (!isBuy && currentSL > 0 && currentSL <= breakevenPrice) {
System.out.println("Already at breakeven or better");
return false;
}
// Move to breakeven
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setStopLoss(breakevenPrice)
.build();
var reply = account.orderModify(request);
if (reply.getData().getReturnedCode() == 10009) {
System.out.printf("✅ Moved to breakeven: %.5f%n", breakevenPrice);
return true;
} else {
System.out.printf("❌ Failed: %s%n", reply.getData().getComment());
return false;
}
}
}
// Usage - move to breakeven when 20 pips profit, with +2 pip offset
boolean moved = BreakevenStop.moveToBreakeven(
account, 123456789, true, 20, 2
);
5) Modify pending order price¶
public class PendingOrderModifier {
/**
* Update pending order price
*/
public static boolean updateOrderPrice(
MT5Account account,
long orderTicket,
double newPrice) throws ApiExceptionMT5 {
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(orderTicket)
.setPrice(newPrice)
.build();
var reply = account.orderModify(request);
var data = reply.getData();
if (data.getReturnedCode() == 10009) {
System.out.printf("✅ Order price updated to %.5f%n", newPrice);
return true;
} else {
System.out.printf("❌ Failed: %s (code: %d)%n",
data.getComment(), data.getReturnedCode());
return false;
}
}
/**
* Update pending order with new price and stops
*/
public static boolean updatePendingOrder(
MT5Account account,
long orderTicket,
double newPrice,
double newSL,
double newTP) throws ApiExceptionMT5 {
var builder = Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(orderTicket)
.setPrice(newPrice);
if (newSL > 0) builder.setStopLoss(newSL);
if (newTP > 0) builder.setTakeProfit(newTP);
var reply = account.orderModify(builder.build());
var data = reply.getData();
if (data.getReturnedCode() == 10009) {
System.out.printf("✅ Pending order updated%n");
System.out.printf(" Price: %.5f%n", newPrice);
if (newSL > 0) System.out.printf(" SL: %.5f%n", newSL);
if (newTP > 0) System.out.printf(" TP: %.5f%n", newTP);
return true;
} else {
System.out.printf("❌ Failed: %s%n", data.getComment());
return false;
}
}
}
// Usage
PendingOrderModifier.updateOrderPrice(account, 123456, 1.10000);
6) Remove Stop Loss or Take Profit¶
public class StopRemover {
/**
* Remove Stop Loss (set to 0)
*/
public static boolean removeStopLoss(
MT5Account account,
long ticket) throws ApiExceptionMT5 {
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setStopLoss(0.0) // 0 removes SL
.build();
var reply = account.orderModify(request);
if (reply.getData().getReturnedCode() == 10009) {
System.out.println("✅ Stop Loss removed");
return true;
} else {
System.out.printf("❌ Failed: %s%n",
reply.getData().getComment());
return false;
}
}
/**
* Remove Take Profit (set to 0)
*/
public static boolean removeTakeProfit(
MT5Account account,
long ticket) throws ApiExceptionMT5 {
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setTakeProfit(0.0) // 0 removes TP
.build();
var reply = account.orderModify(request);
if (reply.getData().getReturnedCode() == 10009) {
System.out.println("✅ Take Profit removed");
return true;
} else {
System.out.printf("❌ Failed: %s%n",
reply.getData().getComment());
return false;
}
}
/**
* Remove both SL and TP
*/
public static boolean removeAllStops(
MT5Account account,
long ticket) throws ApiExceptionMT5 {
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setStopLoss(0.0)
.setTakeProfit(0.0)
.build();
var reply = account.orderModify(request);
if (reply.getData().getReturnedCode() == 10009) {
System.out.println("✅ All stops removed");
return true;
} else {
System.out.printf("❌ Failed: %s%n",
reply.getData().getComment());
return false;
}
}
}
// Usage
StopRemover.removeStopLoss(account, 123456789);
7) Batch modify multiple positions¶
import java.util.*;
public class BatchModifier {
/**
* Modify SL for multiple positions
*/
public static Map<Long, Boolean> batchUpdateStopLoss(
MT5Account account,
Map<Long, Double> ticketToSL) {
Map<Long, Boolean> results = new LinkedHashMap<>();
System.out.printf("Updating %d positions...%n", ticketToSL.size());
System.out.println("═".repeat(50));
for (var entry : ticketToSL.entrySet()) {
long ticket = entry.getKey();
double stopLoss = entry.getValue();
try {
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket)
.setStopLoss(stopLoss)
.build();
var reply = account.orderModify(request);
boolean success = reply.getData().getReturnedCode() == 10009;
results.put(ticket, success);
String status = success ? "✅" : "❌";
System.out.printf("%s Ticket #%d: SL %.5f%n",
status, ticket, stopLoss);
} catch (ApiExceptionMT5 e) {
results.put(ticket, false);
System.out.printf("❌ Ticket #%d: %s%n", ticket, e.getMessage());
}
}
long successCount = results.values().stream()
.filter(success -> success)
.count();
System.out.println("═".repeat(50));
System.out.printf("Success: %d/%d%n", successCount, ticketToSL.size());
return results;
}
}
// Usage
Map<Long, Double> updates = Map.of(
123456L, 1.09500,
789012L, 1.29500,
345678L, 140.500
);
var results = BatchModifier.batchUpdateStopLoss(account, updates);
8) Smart stop modifier with validation¶
public class SmartStopModifier {
/**
* Modify stops with validation and error handling
*/
public static boolean modifyStopsWithValidation(
MT5Account account,
long ticket,
Double newSL,
Double newTP) throws ApiExceptionMT5 {
// Get current position info
var positions = account.openedOrders(
Mt5TermApiAccountHelper.BMT5_ENUM_OPENED_ORDER_SORT_TYPE.BMT5_SORT_BY_TICKET_ASC
).getData().getPositionInfosList();
var position = positions.stream()
.filter(p -> p.getTicket() == ticket)
.findFirst()
.orElseThrow(() -> new ApiExceptionMT5("Position not found: " + ticket));
String symbol = position.getSymbol();
double currentPrice = position.getPriceCurrent();
boolean isBuy = position.getType() ==
Mt5TermApiAccountHelper.BMT5_ENUM_POSITION_TYPE.BMT5_POSITION_TYPE_BUY;
// Get symbol info for validation
var symbolInfo = account.symbolInfoDouble(
symbol,
Mt5TermApiMarketInfo.SymbolInfoDoubleProperty.SYMBOL_TRADE_STOPS_LEVEL
);
double stopLevel = symbolInfo.getData().getRequestedValue() * 0.00001; // Convert to price
System.out.printf("Modifying position #%d (%s %s)%n",
ticket, isBuy ? "BUY" : "SELL", symbol);
System.out.printf("Current price: %.5f%n", currentPrice);
System.out.printf("Min stop distance: %.5f%n", stopLevel);
// Build request
var builder = Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(ticket);
boolean hasChanges = false;
if (newSL != null && newSL > 0) {
// Validate SL distance
double slDistance = Math.abs(currentPrice - newSL);
if (slDistance < stopLevel) {
System.out.printf("⚠️ Stop Loss too close (%.5f < %.5f)%n",
slDistance, stopLevel);
return false;
}
builder.setStopLoss(newSL);
hasChanges = true;
System.out.printf("New SL: %.5f%n", newSL);
}
if (newTP != null && newTP > 0) {
// Validate TP distance
double tpDistance = Math.abs(currentPrice - newTP);
if (tpDistance < stopLevel) {
System.out.printf("⚠️ Take Profit too close (%.5f < %.5f)%n",
tpDistance, stopLevel);
return false;
}
builder.setTakeProfit(newTP);
hasChanges = true;
System.out.printf("New TP: %.5f%n", newTP);
}
if (!hasChanges) {
System.out.println("No changes to apply");
return false;
}
// Execute modification
var reply = account.orderModify(builder.build());
var data = reply.getData();
if (data.getReturnedCode() == 10009) {
System.out.println("✅ Modification successful");
return true;
} else {
System.out.printf("❌ Failed: %s (code: %d)%n",
data.getComment(), data.getReturnedCode());
return false;
}
}
}
// Usage
boolean success = SmartStopModifier.modifyStopsWithValidation(
account,
123456789,
1.09500, // New SL
1.10500 // New TP
);
🔄 Low-level gRPC call (for reference)¶
import io.grpc.*;
import mt5_term_api.*;
// Build request
Mt5TermApiTradingHelper.OrderModifyRequest request =
Mt5TermApiTradingHelper.OrderModifyRequest.newBuilder()
.setTicket(123456789)
.setStopLoss(1.09500)
.setTakeProfit(1.10500)
.build();
// Add metadata
Metadata headers = new Metadata();
Metadata.Key<String> idKey = Metadata.Key.of("id", Metadata.ASCII_STRING_MARSHALLER);
headers.put(idKey, instanceId.toString());
// Modify order
Mt5TermApiTradingHelper.OrderModifyReply reply = tradingHelperClient
.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(headers))
.orderModify(request);
// Check result
if (reply.hasError()) {
throw new ApiExceptionMT5(reply.getError());
}
if (reply.getData().getReturnedCode() == 10009) {
System.out.println("Modification successful");
}
📌 Important Notes¶
What Can Be Modified:¶
Open Positions:¶
- ✅ Stop Loss
- ✅ Take Profit
- ❌ Price (cannot change entry price)
- ❌ Volume (use partial close instead)
Pending Orders:¶
- ✅ Stop Loss
- ✅ Take Profit
- ✅ Order Price
- ✅ Stop Limit Price
- ✅ Expiration Time
- ❌ Order Type (delete and create new instead)
Stop Level Requirements:¶
- Broker enforces minimum distance from current price
- Check
SYMBOL_TRADE_STOPS_LEVELviasymbolInfoDouble() - Too-close stops will be rejected with code 10016
Removing Stops:¶
- Set SL or TP to
0.0to remove - Useful for manual management or special strategies
Best Practices:¶
- Always validate stop distances before modification
- Check return code for success (10009)
- Handle errors gracefully (log and retry if needed)
- Use trailing stops for trend-following strategies
- Move to breakeven to protect profits