bbgo_origin/pkg/risk/riskcontrol/balance_check.go
2023-10-24 20:56:26 +08:00

50 lines
1.4 KiB
Go

package riskcontrol
import (
"fmt"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
log "github.com/sirupsen/logrus"
)
type BalanceCheck struct {
ExpectedBalances map[string]fixedpoint.Value `json:"exceptedBalances"`
BalanceCheckTorlerance fixedpoint.Value `json:"balanceCheckTorlerance"`
}
func (c *BalanceCheck) Validate() error {
if len(c.ExpectedBalances) == 0 {
return fmt.Errorf("expectedBalances is empty")
}
if c.BalanceCheckTorlerance.IsZero() {
return fmt.Errorf("balanceCheckTorlerance is zero")
}
for _, v := range c.ExpectedBalances {
if v.IsZero() {
return fmt.Errorf("expected balance is zero")
}
}
return nil
}
func (c *BalanceCheck) Check(balances types.BalanceMap) error {
for currency, exceptedBalance := range c.ExpectedBalances {
b, ok := balances[currency]
if !ok {
return fmt.Errorf("balance of %s not found", currency)
}
// | (actual - expected) / expected | <= torlerance
balanceErr := exceptedBalance.Sub(b.Available).Div(exceptedBalance).Abs()
log.Infof("[BalanceCheck] %s, expected: %s, actual: %s, error: %.2f%%", currency, exceptedBalance, b.Available, balanceErr.Float64()*100)
if balanceErr.Compare(c.BalanceCheckTorlerance) >= 0 {
return fmt.Errorf("balance of %s is not matched, expected: %s, actual: %s, error: %.2f%%", currency, exceptedBalance, b.Available, balanceErr.Float64()*100)
}
}
return nil
}