76 lines
1.3 KiB
Go
76 lines
1.3 KiB
Go
package trader
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type RateLimiter struct {
|
|
maxPerHour int
|
|
maxParallel int
|
|
|
|
mu sync.Mutex
|
|
hourlyTrades map[int64]int // trades per hour bucket
|
|
activeTrades int
|
|
}
|
|
|
|
func NewRateLimiter(maxPerHour, maxParallel int) *RateLimiter {
|
|
return &RateLimiter{
|
|
maxPerHour: maxPerHour,
|
|
maxParallel: maxParallel,
|
|
hourlyTrades: make(map[int64]int),
|
|
activeTrades: 0,
|
|
}
|
|
}
|
|
|
|
func (r *RateLimiter) CanTrade() bool {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
// Check parallel limit
|
|
if r.activeTrades >= r.maxParallel {
|
|
return false
|
|
}
|
|
|
|
// Check hourly limit
|
|
currentHour := time.Now().Unix() / 3600
|
|
if r.hourlyTrades[currentHour] >= r.maxPerHour {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (r *RateLimiter) RecordTrade() {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
currentHour := time.Now().Unix() / 3600
|
|
r.hourlyTrades[currentHour]++
|
|
r.activeTrades++
|
|
|
|
// Clean up old hour buckets (keep last 2 hours)
|
|
for hour := range r.hourlyTrades {
|
|
if hour < currentHour-1 {
|
|
delete(r.hourlyTrades, hour)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (r *RateLimiter) ReleaseTrade() {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
if r.activeTrades > 0 {
|
|
r.activeTrades--
|
|
}
|
|
}
|
|
|
|
func (r *RateLimiter) GetStats() (hourly int, active int) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
currentHour := time.Now().Unix() / 3600
|
|
return r.hourlyTrades[currentHour], r.activeTrades
|
|
}
|