Skip to content

πŸ” Get Position By Ticket (GetPositionByTicket)ΒΆ

Sugar method: Retrieves detailed information about a specific position by ticket number.

API Information:

  • Method: sugar.GetPositionByTicket(ticket)
  • Timeout: 10 seconds (it calls GetOpenPositions() and searches the result)
  • Returns: *pb.PositionInfo structure

πŸ“‹ Method SignatureΒΆ

func (s *MT5Sugar) GetPositionByTicket(ticket uint64) (*pb.PositionInfo, error)

pb.PositionInfo is the generated protobuf message (pb "github.com/MetaRPC/GoMT5/package"). Its fields:

Field Type Meaning
Index uint32 Position index
Ticket uint64 Position ticket
Symbol string Trading symbol
Type pb.BMT5_ENUM_POSITION_TYPE pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY (0) or ..._SELL (1)
Volume float64 Position volume (lots)
PriceOpen float64 Entry price
PriceCurrent float64 Current price
StopLoss float64 Stop Loss price (0 if none)
TakeProfit float64 Take Profit price (0 if none)
Profit float64 Current profit/loss
Swap float64 Swap/rollover
PositionCommission float64 Commission
OpenTime *timestamppb.Timestamp Open time, broker server time
OpenTimeUtc *timestamppb.Timestamp The same moment in UTC
LastUpdateTime / LastUpdateTimeUtc *timestamppb.Timestamp Last change
MagicNumber int64 Magic number
Identifier int64 Position identifier
Reason pb.BMT5_ENUM_POSITION_REASON Why the position was opened
Comment, ExternalId string Comment, external id
AccountLogin int64 Account login

πŸ”½ Input / ⬆️ OutputΒΆ

Input Type Description
ticket uint64 Position ticket number
Output Type Description
*pb.PositionInfo struct Position details
error error "position with ticket N not found" if no open position has that ticket, or the GetOpenPositions error

πŸ’¬ Just the EssentialsΒΆ

  • What it is: Get all information about a specific position.
  • Why you need it: Check profit, check if still open, get entry price, check SL/TP.
  • Sanity check: Returns an error (never nil, nil) if the position doesn't exist (closed or never existed). The pointer is nil whenever err != nil, so check the error before using it. Only open positions are searched - a pending order ticket is "not found".

🎯 When to Use¢

βœ… Check profit - Monitor specific position P/L

βœ… Verify existence - Check if position still open

βœ… Get details - Before modifying or closing

βœ… Track position - Monitor progress of specific trade


πŸ”— Usage ExamplesΒΆ

1) Basic usage - get position detailsΒΆ

ticket := uint64(12345)

pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("Position not found: %v\n", err)
    return
}

fmt.Printf("Position #%d:\n", pos.Ticket)
fmt.Printf("  Symbol:   %s\n", pos.Symbol)
fmt.Printf("  Type:     %s\n", pos.Type) // BMT5_POSITION_TYPE_BUY / BMT5_POSITION_TYPE_SELL
fmt.Printf("  Volume:   %.2f lots\n", pos.Volume)
fmt.Printf("  Entry:    %.5f\n", pos.PriceOpen)
fmt.Printf("  Current:  %.5f\n", pos.PriceCurrent)
fmt.Printf("  SL:       %.5f\n", pos.StopLoss)
fmt.Printf("  TP:       %.5f\n", pos.TakeProfit)
fmt.Printf("  Profit:   $%.2f\n", pos.Profit)

2) Check if position still existsΒΆ

ticket := uint64(12345)

_, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("❌ Position #%d no longer exists (closed or SL/TP hit)\n", ticket)
    return
}

fmt.Printf("βœ… Position #%d is still open\n", ticket)

3) Monitor position until targetΒΆ

ticket := uint64(12345)
targetProfit := 100.0

ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()

fmt.Printf("Monitoring position #%d until $%.2f profit\n", ticket, targetProfit)

for range ticker.C {
    pos, err := sugar.GetPositionByTicket(ticket)
    if err != nil {
        fmt.Println("Position closed")
        return
    }

    fmt.Printf("Profit: $%.2f / $%.2f (%.1f%%)\n",
        pos.Profit, targetProfit, (pos.Profit/targetProfit)*100)

    if pos.Profit >= targetProfit {
        fmt.Printf("🎯 Target reached! Final profit: $%.2f\n", pos.Profit)
        return
    }
}

4) Calculate pips profitΒΆ

ticket := uint64(12345)

pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("Position not found: %v\n", err)
    return
}

// Calculate pips (EURUSD: 1 pip = 0.0001 = 10 points)
var pips float64
if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
    pips = (pos.PriceCurrent - pos.PriceOpen) / 0.0001
} else {
    pips = (pos.PriceOpen - pos.PriceCurrent) / 0.0001
}

fmt.Printf("Position #%d:\n", pos.Ticket)
fmt.Printf("  Type:        %s\n", pos.Type)
fmt.Printf("  Entry:       %.5f\n", pos.PriceOpen)
fmt.Printf("  Current:     %.5f\n", pos.PriceCurrent)
fmt.Printf("  Pips:        %.1f\n", pips)
fmt.Printf("  Dollar P/L:  $%.2f\n", pos.Profit)

5) Check time in tradeΒΆ

ticket := uint64(12345)

pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("Position not found: %v\n", err)
    return
}

// OpenTimeUtc for durations; OpenTime is the broker server's wall clock
duration := time.Since(pos.OpenTimeUtc.AsTime())

fmt.Printf("Position #%d opened at %s (broker time)\n",
    pos.Ticket, pos.OpenTime.AsTime().Format("2006-01-02 15:04:05"))
fmt.Printf("Time in trade: %v\n", duration.Round(time.Minute))
fmt.Printf("Current P/L: $%.2f\n", pos.Profit)

if duration > 24*time.Hour {
    fmt.Println("⚠️  Position open for more than 24 hours")
}

6) Verify SL/TP are setΒΆ

ticket := uint64(12345)

pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("Position not found: %v\n", err)
    return
}

fmt.Printf("Position #%d protection check:\n", pos.Ticket)

if pos.StopLoss == 0 {
    fmt.Println("  ❌ No Stop Loss - DANGEROUS!")
} else {
    fmt.Printf("  βœ… Stop Loss: %.5f\n", pos.StopLoss)
}

if pos.TakeProfit == 0 {
    fmt.Println("  ⚠️  No Take Profit")
} else {
    fmt.Printf("  βœ… Take Profit: %.5f\n", pos.TakeProfit)
}

7) Display position summaryΒΆ

func ShowPositionSummary(sugar *mt5.MT5Sugar, ticket uint64) {
    pos, err := sugar.GetPositionByTicket(ticket)
    if err != nil {
        fmt.Printf("Position #%d not found\n", ticket)
        return
    }

    fmt.Println("╔═══════════════════════════════════════╗")
    fmt.Println("β•‘       POSITION SUMMARY                β•‘")
    fmt.Println("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•")
    fmt.Printf("Ticket:      #%d\n", pos.Ticket)
    fmt.Printf("Symbol:      %s\n", pos.Symbol)
    fmt.Printf("Type:        %s\n", pos.Type)
    fmt.Printf("Volume:      %.2f lots\n", pos.Volume)
    fmt.Println()
    fmt.Printf("Entry:       %.5f\n", pos.PriceOpen)
    fmt.Printf("Current:     %.5f\n", pos.PriceCurrent)
    fmt.Printf("Stop Loss:   %.5f\n", pos.StopLoss)
    fmt.Printf("Take Profit: %.5f\n", pos.TakeProfit)
    fmt.Println()

    // Calculate pips (EURUSD: 1 pip = 0.0001 = 10 points)
    var pips float64
    if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
        pips = (pos.PriceCurrent - pos.PriceOpen) / 0.0001
    } else {
        pips = (pos.PriceOpen - pos.PriceCurrent) / 0.0001
    }

    fmt.Printf("Pips:        %.1f\n", pips)
    fmt.Printf("Profit:      $%.2f\n", pos.Profit)
    fmt.Printf("Commission:  $%.2f\n", pos.PositionCommission)
    fmt.Printf("Swap:        $%.2f\n", pos.Swap)
    fmt.Printf("Net:         $%.2f\n", pos.Profit+pos.PositionCommission+pos.Swap)
    fmt.Println()
    fmt.Printf("Opened:      %s (broker time)\n", pos.OpenTime.AsTime().Format("2006-01-02 15:04:05"))
    fmt.Printf("Duration:    %v\n", time.Since(pos.OpenTimeUtc.AsTime()).Round(time.Minute))
}

// Usage:
ShowPositionSummary(sugar, 12345)

8) Distance to SL/TPΒΆ

ticket := uint64(12345)

pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("Position not found: %v\n", err)
    return
}

info, _ := sugar.GetSymbolInfo(pos.Symbol)

fmt.Printf("Position #%d distances:\n", pos.Ticket)

if pos.StopLoss > 0 {
    var slDistance float64
    if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
        slDistance = (pos.PriceCurrent - pos.StopLoss) / info.Point
    } else {
        slDistance = (pos.StopLoss - pos.PriceCurrent) / info.Point
    }
    fmt.Printf("  Distance to SL: %.0f points\n", slDistance)
}

if pos.TakeProfit > 0 {
    var tpDistance float64
    if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
        tpDistance = (pos.TakeProfit - pos.PriceCurrent) / info.Point
    } else {
        tpDistance = (pos.PriceCurrent - pos.TakeProfit) / info.Point
    }
    fmt.Printf("  Distance to TP: %.0f points\n", tpDistance)
}

9) Position risk/reward ratioΒΆ

ticket := uint64(12345)

pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Printf("Position not found: %v\n", err)
    return
}

if pos.StopLoss > 0 && pos.TakeProfit > 0 {
    var riskPips, rewardPips float64 // (EURUSD: 1 pip = 0.0001 = 10 points)

    if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
        riskPips = (pos.PriceOpen - pos.StopLoss) / 0.0001
        rewardPips = (pos.TakeProfit - pos.PriceOpen) / 0.0001
    } else {
        riskPips = (pos.StopLoss - pos.PriceOpen) / 0.0001
        rewardPips = (pos.PriceOpen - pos.TakeProfit) / 0.0001
    }

    rr := rewardPips / riskPips

    fmt.Printf("Position #%d Risk/Reward:\n", pos.Ticket)
    fmt.Printf("  Risk:   %.0f pips\n", riskPips)
    fmt.Printf("  Reward: %.0f pips\n", rewardPips)
    fmt.Printf("  R:R:    1:%.1f\n", rr)

    if rr < 2.0 {
        fmt.Println("  ⚠️  R:R less than 1:2")
    } else {
        fmt.Println("  βœ… Good R:R ratio")
    }
}

10) Advanced position monitorΒΆ

func MonitorPosition(sugar *mt5.MT5Sugar, ticket uint64, duration time.Duration) {
    fmt.Println("╔═══════════════════════════════════════╗")
    fmt.Println("β•‘       POSITION MONITOR                β•‘")
    fmt.Println("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•")

    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()

    timeout := time.After(duration)

    highestProfit := 0.0
    lowestProfit := 0.0

    for {
        select {
        case <-timeout:
            fmt.Println("\n⏰ Monitoring ended")
            return

        case <-ticker.C:
            pos, err := sugar.GetPositionByTicket(ticket)
            if err != nil {
                fmt.Println("\n❌ Position closed")
                return
            }

            // Track high/low
            if pos.Profit > highestProfit {
                highestProfit = pos.Profit
            }
            if pos.Profit < lowestProfit {
                lowestProfit = pos.Profit
            }

            // Calculate pips (EURUSD: 1 pip = 0.0001 = 10 points)
            var pips float64
            if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
                pips = (pos.PriceCurrent - pos.PriceOpen) / 0.0001
            } else {
                pips = (pos.PriceOpen - pos.PriceCurrent) / 0.0001
            }

            // Display update
            fmt.Printf("[%s] ", time.Now().Format("15:04:05"))
            fmt.Printf("%.5f | ", pos.PriceCurrent)
            fmt.Printf("%.1f pips | ", pips)
            fmt.Printf("$%.2f ", pos.Profit)

            if pos.Profit > 0 {
                fmt.Printf("πŸ“ˆ")
            } else {
                fmt.Printf("πŸ“‰")
            }

            fmt.Printf(" (High: $%.2f, Low: $%.2f)\n", highestProfit, lowestProfit)
        }
    }
}

// Usage: Monitor for 30 minutes
MonitorPosition(sugar, 12345, 30*time.Minute)

🍬 Other position info:

  • GetOpenPositions() - Get all positions
  • GetPositionsBySymbol() - Get positions for specific symbol

🍬 Position management:

  • ModifyPositionSLTP() - Modify position after getting info
  • ClosePosition() - Close position

⚠️ Common Pitfalls¢

1) Not checking for errorsΒΆ

// ❌ WRONG - position might not exist
pos, _ := sugar.GetPositionByTicket(ticket)
fmt.Printf("Profit: $%.2f\n", pos.Profit) // nil pointer panic when not found!

// βœ… CORRECT - check error
pos, err := sugar.GetPositionByTicket(ticket)
if err != nil {
    fmt.Println("Position not found")
    return
}

2) Using wrong ticket numberΒΆ

// ❌ WRONG - using position from hours ago
oldTicket := uint64(12345)
pos, _ := sugar.GetPositionByTicket(oldTicket) // Might be closed!

// βœ… CORRECT - use fresh ticket from recent open
// (BuyMarket returns the order ticket; MT5 uses it as the position ticket of a market order)
ticket, _ := sugar.BuyMarket("EURUSD", 0.1)
pos, err := sugar.GetPositionByTicket(ticket)

3) Assuming price directionΒΆ

// ❌ WRONG - assuming BUY
pips := (pos.PriceCurrent - pos.PriceOpen) / 0.0001

// βœ… CORRECT - check position type
var pips float64
if pos.Type == pb.BMT5_ENUM_POSITION_TYPE_BMT5_POSITION_TYPE_BUY {
    pips = (pos.PriceCurrent - pos.PriceOpen) / 0.0001
} else {
    pips = (pos.PriceOpen - pos.PriceCurrent) / 0.0001
}

πŸ’Ž Pro TipsΒΆ

  1. Check errors - Position might be closed

  2. Cache ticket - Store ticket when opening position

  3. Type checking - Always check BUY vs SELL for calculations

  4. Monitor changes - Compare values over time

  5. Use for decisions - Check profit before modifying/closing


See also: GetOpenPositions.md, ModifyPositionSLTP.md, ClosePosition.md