Merge pull request #381 from narumiruna/maxamount

strategy: rebalance: adjust quantity by max amount
This commit is contained in:
Yo-An Lin 2021-12-21 20:20:44 +08:00 committed by GitHub
commit 1ab20e6397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 16 deletions

View File

@ -10,11 +10,13 @@ exchangeStrategies:
interval: 24h
baseCurrency: TWD
ignoreLocked: true
weights:
targetWeights:
BTC: 40%
ETH: 20%
MAX: 20%
USDT: 10%
TWD: 10%
threshold: 2%
# max amount to buy or sell per order
maxAmount: 10_000
verbose: true

View File

@ -54,10 +54,13 @@ type Strategy struct {
Interval types.Duration `json:"interval"`
BaseCurrency string `json:"baseCurrency"`
Weights map[string]fixedpoint.Value `json:"weights"`
TargetWeights map[string]fixedpoint.Value `json:"targetWeights"`
Threshold fixedpoint.Value `json:"threshold"`
IgnoreLocked bool `json:"ignoreLocked"`
Verbose bool `json:"verbose"`
// max amount to buy or sell per order
MaxAmount fixedpoint.Value `json:"maxAmount"`
}
func (s *Strategy) ID() string {
@ -67,7 +70,7 @@ func (s *Strategy) ID() string {
func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {}
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
s.Weights = Normalize(s.Weights)
s.TargetWeights = Normalize(s.TargetWeights)
go func() {
ticker := time.NewTicker(util.MillisecondsJitter(s.Interval.Duration(), 1000))
@ -107,7 +110,7 @@ func (s *Strategy) rebalance(ctx context.Context, orderExecutor bbgo.OrderExecut
func (s *Strategy) getPrices(ctx context.Context, session *bbgo.ExchangeSession) (map[string]fixedpoint.Value, error) {
prices := make(map[string]fixedpoint.Value)
for currency := range s.Weights {
for currency := range s.TargetWeights {
if currency == s.BaseCurrency {
prices[currency] = fixedpoint.NewFromFloat(1.0)
continue
@ -128,7 +131,7 @@ func (s *Strategy) getPrices(ctx context.Context, session *bbgo.ExchangeSession)
func (s *Strategy) getQuantities(balances types.BalanceMap) map[string]fixedpoint.Value {
quantities := make(map[string]fixedpoint.Value)
for currency := range s.Weights {
for currency := range s.TargetWeights {
if s.IgnoreLocked {
quantities[currency] = balances[currency].Total()
} else {
@ -146,20 +149,22 @@ func (s *Strategy) generateSubmitOrders(prices, marketValues map[string]fixedpoi
log.Infof("total value: %f", totalValue.Float64())
for currency, target := range s.Weights {
for currency, targetWeight := range s.TargetWeights {
if currency == s.BaseCurrency {
continue
}
symbol := currency + s.BaseCurrency
weight := currentWeights[currency]
price := prices[currency]
currentWeight := currentWeights[currency]
currentPrice := prices[currency]
diff := target.Sub(weight)
if diff.Abs() < s.Threshold {
// calculate the difference between current weight and target weight
// if the difference is less than threshold, then we will not create the order
weightDifference := targetWeight.Sub(currentWeight)
if weightDifference.Abs() < s.Threshold {
continue
}
quantity := diff.Mul(totalValue).Div(price)
quantity := weightDifference.Mul(totalValue).Div(currentPrice)
side := types.SideTypeBuy
if quantity < 0.0 {
@ -167,6 +172,16 @@ func (s *Strategy) generateSubmitOrders(prices, marketValues map[string]fixedpoi
quantity = quantity.Abs()
}
if s.MaxAmount > 0 {
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, currentPrice, s.MaxAmount)
log.Infof("adjust the quantity %f (%s %s @ %f) by max amount %f",
quantity.Float64(),
symbol,
side.String(),
currentPrice.Float64(),
s.MaxAmount.Float64())
}
order := types.SubmitOrder{
Symbol: symbol,
Side: side,