Skip to content

✏️ ModifyOrder (GoMT4)

Goal: change SL/TP for market orders or price/expiration for pending orders — with proper rounding and validation.

Real code references:

  • Account methods: examples/mt4/MT4Account.go (e.g., OrderModify, SymbolParams)
  • Example: examples/mt4/MT4_service.go (ShowOrderModifyExample)

✅ 1) Preconditions

  • You know the ticket of the order you want to modify.
  • Symbol is visible and parameters are known (Digits/LotStep/Frozen levels if applicable).
  • For market orders: you can modify SL/TP only.
  • For pending orders: you can modify price and expiration (and SL/TP too).

🔍 2) Get current order & symbol parameters

// 1) Read symbol params (for rounding)
info, err := account.SymbolParams(ctx, symbol)
if err != nil { return err }
digits := int(info.GetDigits())
point  := math.Pow10(-digits)

// 2) (Optional) Read current order data to decide new SL/TP
ord, err := account.OrderByTicket(ctx, ticket)
if err != nil { return err }
side := ord.GetType() // BUY/SELL or pending types

🧮 3) Helpers (reuse)

func roundPrice(p float64, digits int) float64 {
    mul := math.Pow10(digits)
    return math.Round(p*mul) / mul
}

📝 4) Modify SL/TP for market order

  • Compute SL/TP relative to current market price (Bid for SELL, Ask for BUY).
  • Round to symbol Digits.
q, err := account.Quote(ctx, symbol)
if err != nil { return err }
var sl, tp *float64

switch ord.GetType() {
case pb.OrderType_OP_BUY:
    entry := q.GetAsk()
    s := roundPrice(entry - 20*point, digits)
    t := roundPrice(entry + 40*point, digits)
    sl, tp = &s, &t
case pb.OrderType_OP_SELL:
    entry := q.GetBid()
    s := roundPrice(entry + 20*point, digits)
    t := roundPrice(entry - 40*point, digits)
    sl, tp = &s, &t
}

resp, err := account.OrderModify(
    ctx,
    ticket,
    nil,      // price stays the same for market order
    sl, tp,   // new SL/TP
    nil,      // expiration (not used for market)
)
if err != nil {
    return fmt.Errorf("modify failed: %w", err)
}
fmt.Printf("✅ Modified SL/TP for ticket %d at %s\n", ticket, time.Now().Format(time.RFC3339))

⏰ 5) Modify pending: price and expiration

  • For pendings, you can change the entry price and expiration.
  • Ensure price is on the correct side of the market (e.g., Buy Limit < Ask, Buy Stop > Ask).
// New pending price
desired := 1.09500
price   := roundPrice(desired, digits)

// Move expiry +12 hours
expiry := timestamppb.New(time.Now().Add(12 * time.Hour))

resp, err := account.OrderModify(
    ctx,
    ticket,
    &price, // ⬅️ new pending price
    nil, nil,
    expiry, // ⬅️ new expiration
)
if err != nil {
    return fmt.Errorf("modify pending failed: %w", err)
}
fmt.Printf("✅ Pending modified! Ticket=%d NewPrice=%.5f NewExpiry=%s\n",
    ticket, price, expiry.AsTime().Format("2006-01-02 15:04:05"))

⚠️ Pitfalls & checks

  • Rounding: always round to Digits (SL/TP/price).
  • Side rules:

  • Buy Limit < current Ask, Sell Limit > current Bid.

  • Buy Stop > current Ask, Sell Stop < current Bid.
  • Freeze level: some brokers restrict how close to price you can modify. If you hit freeze, increase distance.
  • Context timeouts: wrap modify calls with short timeout (3–8s). Retry only transport errors.

🔗 See also

  • CloseOrder.md — how to close market orders safely.
  • PlacePendingOrder.md — how to place pending with correct price/expiry.
  • RoundVolumePrice.md — helpers for volume/price alignment.