pivotshort: improve price grouping

This commit is contained in:
c9s 2022-07-02 18:51:17 +08:00
parent f940bb8e0a
commit 1e8ac0d08a
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
4 changed files with 94 additions and 45 deletions

View File

@ -54,6 +54,7 @@ exchangeStrategies:
# minDistance is used to ignore the place that is too near to the current price
minDistance: 3%
groupDistance: 1%
# ratio is the ratio of the resistance price,
# higher the ratio, lower the price

View File

@ -106,7 +106,6 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
// we need the price cross the break line or we do nothing
if !(openPrice.Compare(breakPrice) > 0 && closePrice.Compare(breakPrice) < 0) {
log.Infof("%s kline is not between the break low price %f", kline.Symbol, breakPrice.Float64())
return
}

View File

@ -17,11 +17,12 @@ type ResistanceShort struct {
types.IntervalWindow
MinDistance fixedpoint.Value `json:"minDistance"`
NumLayers int `json:"numLayers"`
LayerSpread fixedpoint.Value `json:"layerSpread"`
Quantity fixedpoint.Value `json:"quantity"`
Ratio fixedpoint.Value `json:"ratio"`
MinDistance fixedpoint.Value `json:"minDistance"`
GroupDistance fixedpoint.Value `json:"groupDistance"`
NumLayers int `json:"numLayers"`
LayerSpread fixedpoint.Value `json:"layerSpread"`
Quantity fixedpoint.Value `json:"quantity"`
Ratio fixedpoint.Value `json:"ratio"`
session *bbgo.ExchangeSession
orderExecutor *bbgo.GeneralOrderExecutor
@ -39,6 +40,10 @@ func (s *ResistanceShort) Bind(session *bbgo.ExchangeSession, orderExecutor *bbg
s.activeOrders = bbgo.NewActiveOrderBook(s.Symbol)
s.activeOrders.BindStream(session.UserDataStream)
if s.GroupDistance.IsZero() {
s.GroupDistance = fixedpoint.NewFromFloat(0.01)
}
store, _ := session.MarketDataStore(s.Symbol)
s.resistancePivot = &indicator.Pivot{IntervalWindow: s.IntervalWindow}
@ -65,13 +70,12 @@ func (s *ResistanceShort) Bind(session *bbgo.ExchangeSession, orderExecutor *bbg
func (s *ResistanceShort) findNextResistancePriceAndPlaceOrders(closePrice fixedpoint.Value) {
// if the close price is still lower than the resistance price, then we don't have to update
if closePrice.Compare(s.nextResistancePrice) <= 0 {
if closePrice.Compare(s.nextResistancePrice.Mul(one.Add(s.Ratio))) <= 0 {
return
}
minDistance := s.MinDistance.Float64()
lows := s.resistancePivot.Lows
resistancePrices := findPossibleResistancePrices(closePrice.Float64(), minDistance, lows)
resistancePrices := findPossibleResistancePrices(closePrice.Float64()*(1.0+minDistance), s.GroupDistance.Float64(), s.resistancePivot.Lows)
log.Infof("last price: %f, possible resistance prices: %+v", closePrice.Float64(), resistancePrices)
@ -151,51 +155,68 @@ func (s *ResistanceShort) placeResistanceOrders(ctx context.Context, resistanceP
}
func findPossibleSupportPrices(closePrice float64, minDistance float64, lows []float64) []float64 {
// sort float64 in increasing order
// lower to higher prices
sort.Float64s(lows)
return group(lower(lows, closePrice), minDistance)
}
var supportPrices []float64
var last = closePrice
for i := len(lows) - 1; i >= 0; i-- {
price := lows[i]
func lower(arr []float64, x float64) []float64 {
sort.Float64s(arr)
var rst []float64
for _, a := range arr {
// filter prices that are lower than the current closed price
if price > closePrice {
if a > x {
continue
}
if (price / last) < (1.0 - minDistance) {
continue
}
supportPrices = append(supportPrices, price)
last = price
rst = append(rst, a)
}
return supportPrices
return rst
}
func higher(arr []float64, x float64) []float64 {
sort.Float64s(arr)
var rst []float64
for _, a := range arr {
// filter prices that are lower than the current closed price
if a < x {
continue
}
rst = append(rst, a)
}
return rst
}
func group(arr []float64, minDistance float64) []float64 {
var groups []float64
var grp = []float64{arr[0]}
for _, price := range arr {
avg := average(grp)
if (price / avg) > (1.0 + minDistance) {
groups = append(groups, avg)
grp = []float64{price}
} else {
grp = append(grp, price)
}
}
if len(grp) > 0 {
groups = append(groups, average(grp))
}
return groups
}
func findPossibleResistancePrices(closePrice float64, minDistance float64, lows []float64) []float64 {
// sort float64 in increasing order
// lower to higher prices
sort.Float64s(lows)
var resistancePrices []float64
var last = closePrice
for _, price := range lows {
// filter prices that are lower than the current closed price
if price < closePrice {
continue
}
if (price / last) < (1.0 + minDistance) {
continue
}
resistancePrices = append(resistancePrices, price)
last = price
}
return resistancePrices
return group(higher(lows, closePrice), minDistance)
}
func average(arr []float64) float64 {
s := 0.0
for _, a := range arr {
s += a
}
return s / float64(len(arr))
}

View File

@ -0,0 +1,28 @@
package pivotshort
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_findPossibleResistancePrices(t *testing.T) {
prices := findPossibleResistancePrices(19000.0, 0.01, []float64{
23020.0,
23040.0,
23060.0,
24020.0,
24040.0,
24060.0,
})
assert.Equal(t, []float64{23035, 24040}, prices)
prices = findPossibleResistancePrices(19000.0, 0.01, []float64{
23020.0,
23040.0,
23060.0,
})
assert.Equal(t, []float64{23035}, prices)
}