74 lines
2.0 KiB
Go
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
|
|
}
|