✅ Place Market and Pending Orders¶
Request: primary method for opening positions and placing pending orders. Supports all order types: market buy/sell, buy/sell limit, buy/sell stop, and stop-limit.
API Information:
- Low-level API:
MT5Account.OrderSend(...)(from Go packagegithub.com/MetaRPC/GoMT5/package/Helpers) - gRPC service:
mt5_term_api.TradingHelper - Proto definition:
OrderSend(defined inmt5-term-api-trading-helper.proto)
RPC¶
- Service:
mt5_term_api.TradingHelper - Method:
OrderSend(OrderSendRequest) → OrderSendReply - Low‑level client (generated):
TradingHelperClient.OrderSend(ctx, request, opts...)
💬 Just the essentials¶
- What it is. Main trading method for placing market and pending orders.
- Why you need it. Open positions, place limit/stop orders, enter trades.
- All order types. Supports market orders, limits, stops, and stop-limits.
🎯 Purpose¶
Use it to:
- Open market positions (Buy/Sell)
- Place pending orders (Limit/Stop)
- Enter trades with SL/TP
- Execute trading strategies
- Manage order parameters
📚 Tutorial¶
For a detailed line-by-line explanation with examples, see: → OrderSend - How it works
package mt5
type MT5Account struct {
// ...
}
// OrderSend places a market or pending order.
// Returns OrderSendData with ticket number, execution price, and MqlTradeResult.
func (a *MT5Account) OrderSend(
ctx context.Context,
req *pb.OrderSendRequest,
) (*pb.OrderSendData, error)
Request message:
OrderSendRequest {
string symbol = 1; // Symbol name (REQUIRED)
TMT5_ENUM_ORDER_TYPE operation = 2; // Type of order (REQUIRED)
double volume = 3; // Requested volume for a deal in lots (REQUIRED)
optional double price = 4; // Price
optional uint64 slippage = 5; // Maximal possible deviation from the requested price
optional double stop_loss = 6; // Stop Loss level of the order
optional double take_profit = 7; // Take Profit level of the order
optional string comment = 8; // Order comment
optional uint64 expert_id = 9; // Expert Advisor ID (magic number)
optional double stop_limit_price = 10; // StopLimit level of the order
optional TMT5_ENUM_ORDER_TYPE_TIME expiration_time_type = 11; // Order expiration type
optional google.protobuf.Timestamp expiration_time = 12; // Order expiration time (for ORDER_TIME_SPECIFIED type)
}
Reply message:
🔽 Input¶
| Parameter | Type | Description |
|---|---|---|
ctx |
context.Context |
Context for deadline/timeout and cancellation |
req |
*pb.OrderSendRequest |
Request with order parameters |
Request fields:
| Field | Type | Required | Description |
|---|---|---|---|
Symbol |
string |
✅ | Trading symbol (e.g., "EURUSD") |
Operation |
TMT5_ENUM_ORDER_TYPE |
✅ | Order type (BUY=0, SELL=1, BUY_LIMIT=2, etc) |
Volume |
double |
✅ | Order volume in lots |
Price |
double |
optional | Order price (required for pending orders) |
Slippage |
uint64 |
optional | Maximum price deviation (slippage) in points |
StopLoss |
double |
optional | Stop loss price level |
TakeProfit |
double |
optional | Take profit price level |
Comment |
string |
optional | Order comment |
ExpertId |
uint64 |
optional | Expert Advisor ID (magic number) |
StopLimitPrice |
double |
optional | StopLimit level (for STOP_LIMIT orders) |
ExpirationTimeType |
TMT5_ENUM_ORDER_TYPE_TIME |
optional | Order expiration type (GTC, DAY, SPECIFIED, etc) |
ExpirationTime |
google.protobuf.Timestamp |
optional | Expiration time (for SPECIFIED type) |
⬆️ Output — OrderSendData¶
| Field | Type | Description |
|---|---|---|
ReturnedCode |
uint32 |
Operation return code (10009 = success) |
Deal |
uint64 |
Deal ticket, if it is performed |
Order |
uint64 |
Order ticket, if it is placed |
Volume |
double |
Deal volume, confirmed by broker |
Price |
double |
Deal price, confirmed by broker |
Bid |
double |
Current Bid price |
Ask |
double |
Current Ask price |
Comment |
string |
Broker comment to operation |
RequestId |
uint32 |
Request ID set by terminal during dispatch |
RetCodeExternal |
int32 |
Return code of external trading system |
ReturnedStringCode |
string |
String representation of return code |
ReturnedCodeDescription |
string |
Description of return code |
💡 Enum Usage Note: The tables show simplified constant names for readability. In Go code, use full names with the enum type prefix.
Format:
pb.<ENUM_TYPE>_<CONSTANT_NAME>Example:
pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_BUY
📘 Enum: TMT5_ENUM_ORDER_TYPE¶
| Value | Constant | Description |
|---|---|---|
| 0 | TMT5_ORDER_TYPE_BUY |
Market Buy order |
| 1 | TMT5_ORDER_TYPE_SELL |
Market Sell order |
| 2 | TMT5_ORDER_TYPE_BUY_LIMIT |
Buy Limit pending order |
| 3 | TMT5_ORDER_TYPE_SELL_LIMIT |
Sell Limit pending order |
| 4 | TMT5_ORDER_TYPE_BUY_STOP |
Buy Stop pending order |
| 5 | TMT5_ORDER_TYPE_SELL_STOP |
Sell Stop pending order |
| 6 | TMT5_ORDER_TYPE_BUY_STOP_LIMIT |
Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price |
| 7 | TMT5_ORDER_TYPE_SELL_STOP_LIMIT |
Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price |
| 8 | TMT5_ORDER_TYPE_CLOSE_BY |
Order to close a position by an opposite one |
📘 Enum: TMT5_ENUM_ORDER_TYPE_TIME¶
| Value | Constant | Description |
|---|---|---|
| 0 | TMT5_ORDER_TIME_GTC |
Good Till Cancelled (order valid until explicitly cancelled) |
| 1 | TMT5_ORDER_TIME_DAY |
Good Till Day (order valid until end of trading day) |
| 2 | TMT5_ORDER_TIME_SPECIFIED |
Good Till Specified Time (order valid until ExpirationTime) |
| 3 | TMT5_ORDER_TIME_SPECIFIED_DAY |
Good Till Specified Day (order valid until end of specified day) |
🧩 Notes & Tips¶
- Automatic reconnection: All
MT5Accountmethods have built-in protection against transient gRPC errors with automatic reconnection viaExecuteWithReconnect. - Default timeout: If context has no deadline, a default
30stimeout is applied automatically. - Nil context: If you pass
nilcontext,context.Background()is used automatically. - Use OrderCheck: Validate orders before sending with OrderCheck method.
- Slippage: Deviation parameter controls maximum acceptable slippage.
🔗 Usage Examples¶
1) Place market buy order¶
package main
import (
"context"
"fmt"
"time"
pb "github.com/MetaRPC/GoMT5/package"
"github.com/MetaRPC/GoMT5/package/Helpers"
)
func main() {
account, _ := mt5.NewMT5Account(12345, "password", "mt5.mrpc.pro:443", uuid.New())
defer account.Close()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Get current price
tick, _ := account.SymbolInfoTick(ctx, &pb.SymbolInfoTickRequest{Symbol: "EURUSD"})
sl := tick.Ask - 0.0050 // 50 pips SL
tp := tick.Ask + 0.0100 // 100 pips TP
slippage := uint64(20)
expertId := uint64(123456)
comment := "Test buy order"
data, err := account.OrderSend(ctx, &pb.OrderSendRequest{
Symbol: "EURUSD",
Operation: pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_BUY,
Volume: 0.01,
Price: &tick.Ask,
StopLoss: &sl,
TakeProfit: &tp,
Slippage: &slippage,
ExpertId: &expertId,
Comment: &comment,
})
if err != nil {
panic(err)
}
// Check if order executed successfully using helper from errors.go
if mt5.IsRetCodeSuccess(data.ReturnedCode) {
fmt.Printf("Order placed! Ticket: %d, Price: %.5f\n", data.Order, data.Price)
} else {
fmt.Printf("Order failed: %s (code: %d)\n",
mt5.GetRetCodeMessage(data.ReturnedCode),
data.ReturnedCode)
}
}
2) Place market sell order¶
func PlaceSellOrder(account *mt5.MT5Account, symbol string, volume float64) (uint64, error) {
ctx := context.Background()
// Get current price
tick, err := account.SymbolInfoTick(ctx, &pb.SymbolInfoTickRequest{Symbol: symbol})
if err != nil {
return 0, err
}
sl := tick.Bid + 0.0050
tp := tick.Bid - 0.0100
slippage := uint64(20)
comment := "Sell order"
data, err := account.OrderSend(ctx, &pb.OrderSendRequest{
Symbol: symbol,
Operation: pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_SELL,
Volume: volume,
Price: &tick.Bid,
StopLoss: &sl,
TakeProfit: &tp,
Slippage: &slippage,
Comment: &comment,
})
if err != nil {
return 0, fmt.Errorf("failed to place sell order: %w", err)
}
return data.Order, nil
}
3) Place buy limit order¶
func PlaceBuyLimit(account *mt5.MT5Account, symbol string, volume, price, sl, tp float64) (uint64, error) {
ctx := context.Background()
expertId := uint64(123456)
comment := "Buy limit order"
data, err := account.OrderSend(ctx, &pb.OrderSendRequest{
Symbol: symbol,
Operation: pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_BUY_LIMIT,
Volume: volume,
Price: &price,
StopLoss: &sl,
TakeProfit: &tp,
ExpertId: &expertId,
Comment: &comment,
})
if err != nil {
return 0, err
}
fmt.Printf("Buy limit placed at %.5f, ticket: %d\n", price, data.Order)
return data.Order, nil
}
4) Place sell stop order¶
func PlaceSellStop(account *mt5.MT5Account, symbol string, volume, stopPrice float64) (uint64, error) {
ctx := context.Background()
sl := stopPrice + 0.0050
tp := stopPrice - 0.0100
comment := "Sell stop order"
data, err := account.OrderSend(ctx, &pb.OrderSendRequest{
Symbol: symbol,
Operation: pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_SELL_STOP,
Volume: volume,
Price: &stopPrice,
StopLoss: &sl,
TakeProfit: &tp,
Comment: &comment,
})
if err != nil {
return 0, err
}
return data.Order, nil
}
5) Order with validation¶
func PlaceMarketOrder(account *mt5.MT5Account, symbol string, volume float64, isBuy bool) (uint64, error) {
ctx := context.Background()
// Get current price
tick, err := account.SymbolInfoTick(ctx, &pb.SymbolInfoTickRequest{Symbol: symbol})
if err != nil {
return 0, err
}
var operation pb.TMT5_ENUM_ORDER_TYPE
var price, sl, tp float64
if isBuy {
operation = pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_BUY
price = tick.Ask
sl = tick.Ask - 0.0050
tp = tick.Ask + 0.0100
} else {
operation = pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_SELL
price = tick.Bid
sl = tick.Bid + 0.0050
tp = tick.Bid - 0.0100
}
slippage := uint64(20)
// Send order
data, err := account.OrderSend(ctx, &pb.OrderSendRequest{
Symbol: symbol,
Operation: operation,
Volume: volume,
Price: &price,
StopLoss: &sl,
TakeProfit: &tp,
Slippage: &slippage,
})
if err != nil {
return 0, err
}
// Validate trade result using helper from errors.go
if !mt5.IsRetCodeSuccess(data.ReturnedCode) {
return 0, fmt.Errorf("order failed: %s (code: %d)",
mt5.GetRetCodeMessage(data.ReturnedCode),
data.ReturnedCode)
}
fmt.Printf("Order placed: %d at %.5f\n", data.Order, data.Price)
return data.Order, nil
}
🔧 Common Patterns¶
Market order with retry¶
func PlaceMarketOrderWithRetry(account *mt5.MT5Account, symbol string, volume float64, isBuy bool, maxRetries int) (uint64, error) {
ctx := context.Background()
slippage := uint64(50)
for i := 0; i < maxRetries; i++ {
tick, err := account.SymbolInfoTick(ctx, &pb.SymbolInfoTickRequest{Symbol: symbol})
if err != nil {
continue
}
var operation pb.TMT5_ENUM_ORDER_TYPE
var price float64
if isBuy {
operation = pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_BUY
price = tick.Ask
} else {
operation = pb.TMT5_ENUM_ORDER_TYPE_TMT5_ORDER_TYPE_SELL
price = tick.Bid
}
data, err := account.OrderSend(ctx, &pb.OrderSendRequest{
Symbol: symbol,
Operation: operation,
Volume: volume,
Price: &price,
Slippage: &slippage,
})
if err == nil && mt5.IsRetCodeSuccess(data.ReturnedCode) {
return data.Order, nil
}
time.Sleep(500 * time.Millisecond)
}
return 0, fmt.Errorf("failed after %d retries", maxRetries)
}
📚 See Also¶
- OrderCheck - Validate order before sending
- OrderModify - Modify existing orders
- OrderClose - Close positions
- SymbolInfoTick - Get current prices