mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-27 09:15:15 +00:00
add price risk control
This commit is contained in:
parent
2058ce808b
commit
53309616c3
40
pkg/risk/riskcontrol/price.go
Normal file
40
pkg/risk/riskcontrol/price.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package riskcontrol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
indicatorv2 "github.com/c9s/bbgo/pkg/indicator/v2"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PriceRiskControl struct {
|
||||||
|
referencePrice *indicatorv2.EWMAStream
|
||||||
|
lossThreshold fixedpoint.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPriceRiskControl(refPrice *indicatorv2.EWMAStream, threshold fixedpoint.Value) *PriceRiskControl {
|
||||||
|
return &PriceRiskControl{
|
||||||
|
referencePrice: refPrice,
|
||||||
|
lossThreshold: threshold,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PriceRiskControl) IsSafe(side types.SideType, price fixedpoint.Value, quantity fixedpoint.Value) bool {
|
||||||
|
refPrice := fixedpoint.NewFromFloat(r.referencePrice.Last(0))
|
||||||
|
// calculate profit
|
||||||
|
var profit fixedpoint.Value
|
||||||
|
if side == types.SideTypeBuy {
|
||||||
|
profit = refPrice.Sub(price).Mul(quantity)
|
||||||
|
} else if side == types.SideTypeSell {
|
||||||
|
profit = price.Sub(refPrice).Mul(quantity)
|
||||||
|
}
|
||||||
|
return profit.Compare(r.lossThreshold) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PriceRiskControl) IsSafeLimitOrder(o types.SubmitOrder) (bool, error) {
|
||||||
|
if !(o.Type == types.OrderTypeLimit || o.Type == types.OrderTypeLimitMaker) {
|
||||||
|
return false, fmt.Errorf("order type is not limit order")
|
||||||
|
}
|
||||||
|
return r.IsSafe(o.Side, o.Price, o.Quantity), nil
|
||||||
|
}
|
63
pkg/risk/riskcontrol/price_test.go
Normal file
63
pkg/risk/riskcontrol/price_test.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package riskcontrol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
indicatorv2 "github.com/c9s/bbgo/pkg/indicator/v2"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_IsSafe(t *testing.T) {
|
||||||
|
refPrice := 30000.00
|
||||||
|
lossThreshold := fixedpoint.NewFromFloat(-100)
|
||||||
|
|
||||||
|
window := types.IntervalWindow{Window: 30, Interval: types.Interval1m}
|
||||||
|
refPriceEWMA := indicatorv2.EWMA2(nil, window.Window)
|
||||||
|
refPriceEWMA.PushAndEmit(refPrice)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
side types.SideType
|
||||||
|
price fixedpoint.Value
|
||||||
|
quantity fixedpoint.Value
|
||||||
|
isSafe bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "BuyingHighSafe",
|
||||||
|
side: types.SideTypeBuy,
|
||||||
|
price: fixedpoint.NewFromFloat(30040.0),
|
||||||
|
quantity: fixedpoint.NewFromFloat(1.0),
|
||||||
|
isSafe: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SellingLowSafe",
|
||||||
|
side: types.SideTypeSell,
|
||||||
|
price: fixedpoint.NewFromFloat(29960.0),
|
||||||
|
quantity: fixedpoint.NewFromFloat(1.0),
|
||||||
|
isSafe: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BuyingHighLoss",
|
||||||
|
side: types.SideTypeBuy,
|
||||||
|
price: fixedpoint.NewFromFloat(30040.0),
|
||||||
|
quantity: fixedpoint.NewFromFloat(10.0),
|
||||||
|
isSafe: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SellingLowLoss",
|
||||||
|
side: types.SideTypeSell,
|
||||||
|
price: fixedpoint.NewFromFloat(29960.0),
|
||||||
|
quantity: fixedpoint.NewFromFloat(10.0),
|
||||||
|
isSafe: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
var riskControl = NewPriceRiskControl(refPriceEWMA, lossThreshold)
|
||||||
|
assert.Equal(t, tc.isSafe, riskControl.IsSafe(tc.side, tc.price, tc.quantity))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user