bbgo_origin/pkg/risk/riskcontrol/position.go

46 lines
1.8 KiB
Go

package riskcontrol
import (
log "github.com/sirupsen/logrus"
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
//go:generate callbackgen -type PositionRiskControl
type PositionRiskControl struct {
hardLimit fixedpoint.Value
quantity fixedpoint.Value
releasePositionCallbacks []func(quantity fixedpoint.Value, side types.SideType)
}
func NewPositionRiskControl(hardLimit, quantity fixedpoint.Value, tradeCollector *bbgo.TradeCollector) *PositionRiskControl {
p := &PositionRiskControl{
hardLimit: hardLimit,
quantity: quantity,
}
// register position update handler: check if position is over the hard limit
tradeCollector.OnPositionUpdate(func(position *types.Position) {
if fixedpoint.Compare(position.Base, hardLimit) > 0 {
log.Infof("position %f is over hardlimit %f, releasing position...", position.Base.Float64(), hardLimit.Float64())
p.EmitReleasePosition(position.Base.Sub(hardLimit), types.SideTypeSell)
} else if fixedpoint.Compare(position.Base, hardLimit.Neg()) < 0 {
log.Infof("position %f is over hardlimit %f, releasing position...", position.Base.Float64(), hardLimit.Float64())
p.EmitReleasePosition(position.Base.Neg().Sub(hardLimit), types.SideTypeBuy)
}
})
return p
}
// ModifiedQuantity returns quantity controlled by position risks
// For buy orders, mod quantity = min(hardlimit - position, quanity), limiting by positive position
// For sell orders, mod quantity = min(hardlimit - (-position), quanity), limiting by negative position
func (p *PositionRiskControl) ModifiedQuantity(position fixedpoint.Value) (buyQuantity, sellQuantity fixedpoint.Value) {
return fixedpoint.Min(p.hardLimit.Sub(position), p.quantity),
fixedpoint.Min(p.hardLimit.Add(position), p.quantity)
}