π’ Count Open Positions (CountOpenPositions)ΒΆ
Sugar method: Returns the exact count of open positions (fastest way to get count).
API Information:
- Method:
sugar.CountOpenPositions() - Timeout: 3 seconds
- Returns: Integer count
π Method SignatureΒΆ
π½ Input / β¬οΈ OutputΒΆ
| Input | Type | Description |
|---|---|---|
| None | - | No parameters required |
| Output | Type | Description |
|---|---|---|
int |
integer | Number of open positions |
error |
error |
Error if count failed |
π¬ Just the EssentialsΒΆ
- What it is: Get count of open positions without fetching any position data.
- Why you need it: Fastest way to count - more efficient than
len(GetOpenPositions()). - Sanity check: Returns 0 if no positions. Most efficient counting method.
π― When to UseΒΆ
β Quick count - Fast integer answer without fetching data
β Validation - Check position count limits
β Dashboards - Display count efficiently
β Monitoring - Track position count over time
π Usage ExamplesΒΆ
1) Basic usage - get countΒΆ
count, err := sugar.CountOpenPositions()
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Open positions: %d\n", count)
if count == 0 {
fmt.Println("No positions - ready to trade")
} else {
fmt.Printf("Currently managing %d positions\n", count)
}
2) Position limit enforcementΒΆ
maxPositions := 10
count, _ := sugar.CountOpenPositions()
fmt.Printf("Position count: %d / %d max\n", count, maxPositions)
if count >= maxPositions {
fmt.Println("β Position limit reached - cannot open new trades")
return
}
remaining := maxPositions - count
fmt.Printf("β
Can open %d more positions\n", remaining)
3) Before opening positionΒΆ
maxSimultaneous := 5
// Check current count
count, _ := sugar.CountOpenPositions()
if count >= maxSimultaneous {
fmt.Printf("β οΈ Already at max (%d positions)\n", maxSimultaneous)
fmt.Println(" Wait for position to close before opening new")
return
}
fmt.Printf("Current: %d/%d - opening new position...\n", count, maxSimultaneous)
ticket, _ := sugar.BuyMarket("EURUSD", 0.1)
fmt.Printf("β
Opened #%d (now %d/%d)\n", ticket, count+1, maxSimultaneous)
4) Monitor position count changesΒΆ
func MonitorPositionCount(sugar *mt5.MT5Sugar, duration time.Duration) {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
timeout := time.After(duration)
previousCount := -1
for {
select {
case <-timeout:
return
case <-ticker.C:
count, _ := sugar.CountOpenPositions()
if previousCount == -1 {
fmt.Printf("Initial count: %d positions\n", count)
} else if count > previousCount {
fmt.Printf("π Count increased: %d β %d (+%d)\n",
previousCount, count, count-previousCount)
} else if count < previousCount {
fmt.Printf("π Count decreased: %d β %d (-%d)\n",
previousCount, count, previousCount-count)
} else {
fmt.Printf("β‘οΈ Count unchanged: %d\n", count)
}
previousCount = count
}
}
}
// Usage: Monitor for 5 minutes
MonitorPositionCount(sugar, 5*time.Minute)
5) Dashboard counterΒΆ
func ShowDashboard(sugar *mt5.MT5Sugar) {
count, _ := sugar.CountOpenPositions()
balance, _ := sugar.GetBalance()
equity, _ := sugar.GetEquity()
profit, _ := sugar.GetProfit()
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
fmt.Println("β ACCOUNT DASHBOARD β")
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
fmt.Printf("Positions: %d\n", count)
fmt.Printf("Balance: $%.2f\n", balance)
fmt.Printf("Equity: $%.2f\n", equity)
fmt.Printf("Profit: $%.2f\n", profit)
if count > 0 {
avgProfitPerPosition := profit / float64(count)
fmt.Printf("Avg P/L: $%.2f per position\n", avgProfitPerPosition)
}
}
// Usage:
ticker := time.NewTicker(5 * time.Second)
for range ticker.C {
ShowDashboard(sugar)
fmt.Println()
}
6) Position count alertΒΆ
warnThreshold := 7
maxThreshold := 10
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for range ticker.C {
count, _ := sugar.CountOpenPositions()
fmt.Printf("[%s] Positions: %d ",
time.Now().Format("15:04:05"), count)
if count >= maxThreshold {
fmt.Println("π΄ MAX REACHED")
} else if count >= warnThreshold {
fmt.Println("π‘ WARNING")
} else {
fmt.Println("π’ OK")
}
}
7) Compare position count with targetΒΆ
targetPositions := 3
count, _ := sugar.CountOpenPositions()
fmt.Printf("Target: %d positions\n", targetPositions)
fmt.Printf("Current: %d positions\n", count)
diff := count - targetPositions
if diff == 0 {
fmt.Println("β
At target")
} else if diff > 0 {
fmt.Printf("β οΈ %d over target\n", diff)
} else {
fmt.Printf("π %d below target\n", -diff)
}
8) Wait for all positions to closeΒΆ
fmt.Println("Waiting for all positions to close...")
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
timeout := time.After(10 * time.Minute)
for {
select {
case <-timeout:
count, _ := sugar.CountOpenPositions()
fmt.Printf("β° Timeout - still %d positions open\n", count)
return
case <-ticker.C:
count, _ := sugar.CountOpenPositions()
if count == 0 {
fmt.Println("β
All positions closed!")
return
}
fmt.Printf("%d positions remaining...\n", count)
}
}
9) Position count statisticsΒΆ
func TrackPositionCountStats(sugar *mt5.MT5Sugar, duration time.Duration) {
ticker := time.NewTicker(1 * time.Minute)
defer ticker.Stop()
timeout := time.After(duration)
minCount := 999999
maxCount := 0
totalCount := 0
samples := 0
for {
select {
case <-timeout:
avgCount := float64(totalCount) / float64(samples)
fmt.Println("\nβββββββββββββββββββββββββββββββββββββββββ")
fmt.Println("β POSITION COUNT STATISTICS β")
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
fmt.Printf("Duration: %v\n", duration)
fmt.Printf("Samples: %d\n", samples)
fmt.Printf("Minimum: %d positions\n", minCount)
fmt.Printf("Maximum: %d positions\n", maxCount)
fmt.Printf("Average: %.1f positions\n", avgCount)
return
case <-ticker.C:
count, _ := sugar.CountOpenPositions()
if count < minCount {
minCount = count
}
if count > maxCount {
maxCount = count
}
totalCount += count
samples++
fmt.Printf("Count: %d (min: %d, max: %d, avg: %.1f)\n",
count, minCount, maxCount, float64(totalCount)/float64(samples))
}
}
}
// Usage: Track for 1 hour
TrackPositionCountStats(sugar, 1*time.Hour)
10) Advanced position count managerΒΆ
type PositionCountManager struct {
MinPositions int
MaxPositions int
TargetPositions int
}
func (pcm *PositionCountManager) GetStatus(sugar *mt5.MT5Sugar) string {
count, err := sugar.CountOpenPositions()
if err != nil {
return "ERROR"
}
if count < pcm.MinPositions {
return "UNDEREXPOSED"
} else if count > pcm.MaxPositions {
return "OVEREXPOSED"
} else if count == pcm.TargetPositions {
return "OPTIMAL"
} else {
return "NORMAL"
}
}
func (pcm *PositionCountManager) ShowReport(sugar *mt5.MT5Sugar) {
count, _ := sugar.CountOpenPositions()
status := pcm.GetStatus(sugar)
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
fmt.Println("β POSITION COUNT MANAGER β")
fmt.Println("βββββββββββββββββββββββββββββββββββββββββ")
fmt.Printf("Current: %d positions\n", count)
fmt.Printf("Target: %d positions\n", pcm.TargetPositions)
fmt.Printf("Range: %d - %d\n", pcm.MinPositions, pcm.MaxPositions)
fmt.Printf("Status: %s\n\n", status)
// Show recommendations
switch status {
case "UNDEREXPOSED":
needed := pcm.MinPositions - count
fmt.Printf("π‘ Recommendation: Open %d more positions\n", needed)
case "OVEREXPOSED":
excess := count - pcm.MaxPositions
fmt.Printf("β οΈ Warning: Close %d positions\n", excess)
case "OPTIMAL":
fmt.Println("β
Perfect - at target")
case "NORMAL":
fmt.Println("β
Within acceptable range")
}
}
func (pcm *PositionCountManager) CanOpenNew(sugar *mt5.MT5Sugar) bool {
count, _ := sugar.CountOpenPositions()
return count < pcm.MaxPositions
}
// Usage:
manager := &PositionCountManager{
MinPositions: 2,
TargetPositions: 5,
MaxPositions: 10,
}
manager.ShowReport(sugar)
if manager.CanOpenNew(sugar) {
fmt.Println("\nβ
Approved to open new position")
} else {
fmt.Println("\nβ Cannot open - at maximum")
}
π Related MethodsΒΆ
π¬ Symbol-specific:
CountOpenPositionsBySymbol()- Count for specific symbol
π¬ Related checks:
HasOpenPosition()- Boolean check (faster)GetPositionTickets()- Get tickets (slower but still fast)GetOpenPositions()- Full data (slowest)
β οΈ Common PitfallsΒΆ
1) Using GetOpenPositions() when you only need countΒΆ
// β WRONG - fetching all data just to count
positions, _ := sugar.GetOpenPositions()
count := len(positions) // Wasteful!
// β
CORRECT - dedicated count method
count, _ := sugar.CountOpenPositions() // Much faster!
2) Not handling errorsΒΆ
// β WRONG - ignoring errors
count, _ := sugar.CountOpenPositions()
if count >= 10 {
// Might be wrong if error occurred!
}
// β
CORRECT - check errors
count, err := sugar.CountOpenPositions()
if err != nil {
fmt.Printf("Count failed: %v\n", err)
return
}
3) Assuming count means specific positions existΒΆ
// β WRONG - count doesn't tell you WHICH positions
count, _ := sugar.CountOpenPositions()
if count > 0 {
// Can't assume anything about the positions themselves
}
// β
CORRECT - fetch positions if you need details
count, _ := sugar.CountOpenPositions()
if count > 0 {
positions, _ := sugar.GetOpenPositions()
// Now work with actual positions
}
π Pro TipsΒΆ
-
Fastest count - Use this instead of
len(GetOpenPositions()) -
Limits - Perfect for enforcing position count limits
-
Monitoring - Track count changes over time
-
Dashboards - Display count without overhead
-
Combine with Has - Use
HasOpenPosition()for boolean, this for count
π Performance HierarchyΒΆ
From fastest to slowest:
1. HasOpenPosition() - Boolean only
2. CountOpenPositions() - Integer count β YOU ARE HERE
3. GetPositionTickets() - Ticket numbers only
4. GetOpenPositions() - Full position data
Use CountOpenPositions() when you:
- Need exact count
- Don't need position details
- Want to enforce limits
- Track count over time
See also: HasOpenPosition.md, GetOpenPositions.md