Files
2026-06-07 21:51:20 +00:00

74 lines
2.0 KiB
Go

package execution
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
"strings"
"time"
"github.com/shopspring/decimal"
"overnight-trading-bot/internal/domain"
"overnight-trading-bot/internal/money"
)
const maxClientOrderIDLen = 36
func LimitBuyPrice(bestBid, bestAsk, tick decimal.Decimal, improveTicks int) (decimal.Decimal, error) {
if improveTicks < 0 {
improveTicks = 0
}
if !tick.IsPositive() {
return decimal.Zero, money.ErrInvalidTick
}
candidate := bestBid.Add(tick.Mul(decimal.NewFromInt(int64(improveTicks))))
upper := bestAsk.Sub(tick)
if candidate.LessThanOrEqual(upper) {
return money.RoundToTick(candidate, tick, money.RoundFloor)
}
return money.RoundToTick(bestBid, tick, money.RoundFloor)
}
func LimitSellPrice(bestBid, bestAsk, tick decimal.Decimal, improveTicks int) (decimal.Decimal, error) {
if improveTicks < 0 {
improveTicks = 0
}
if !tick.IsPositive() {
return decimal.Zero, money.ErrInvalidTick
}
candidate := bestAsk.Sub(tick.Mul(decimal.NewFromInt(int64(improveTicks))))
lower := bestBid.Add(tick)
if candidate.GreaterThanOrEqual(lower) {
return money.RoundToTick(candidate, tick, money.RoundCeil)
}
return money.RoundToTick(bestAsk, tick, money.RoundCeil)
}
func ClientOrderID(tradeDate time.Time, instrumentUID string, side domain.Side, attempt int) string {
base := fmt.Sprintf("%s|%s|%s|%d", tradeDate.Format("20060102"), instrumentUID, side, attempt)
sum := sha256.Sum256([]byte(base))
suffix := hex.EncodeToString(sum[:])
sideToken := "b"
if side == domain.SideSell {
sideToken = "s"
}
prefix := fmt.Sprintf("otb-%s-%s-%s-", tradeDate.Format("20060102"), sideToken, attemptToken(attempt))
return strings.ToLower(prefix + suffix[:maxClientOrderIDLen-len(prefix)])
}
func attemptToken(attempt int) string {
if attempt < 0 {
attempt = 0
}
token := strings.ToLower(strconv.FormatInt(int64(attempt), 36))
if len(token) > 2 {
token = token[len(token)-2:]
}
for len(token) < 2 {
token = "0" + token
}
return token
}