mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
add max grid config and fix max price formatting
This commit is contained in:
parent
14abe3fb7e
commit
8e0b5d11a7
54
config/grid-max.yaml
Normal file
54
config/grid-max.yaml
Normal file
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
notifications:
|
||||
slack:
|
||||
defaultChannel: "dev-bbgo"
|
||||
errorChannel: "bbgo-error"
|
||||
|
||||
# if you want to route channel by symbol
|
||||
symbolChannels:
|
||||
"^BTC": "btc"
|
||||
"^ETH": "eth"
|
||||
"^BNB": "bnb"
|
||||
|
||||
# object routing rules
|
||||
routing:
|
||||
trade: "$symbol"
|
||||
order: "$symbol"
|
||||
submitOrder: "$session" # not supported yet
|
||||
pnL: "bbgo-pnl"
|
||||
|
||||
sessions:
|
||||
binance:
|
||||
exchange: binance
|
||||
envVarPrefix: binance
|
||||
|
||||
max:
|
||||
exchange: max
|
||||
envVarPrefix: max
|
||||
|
||||
riskControls:
|
||||
# This is the session-based risk controller, which let you configure different risk controller by session.
|
||||
sessionBased:
|
||||
# "max" is the session name that you want to configure the risk control
|
||||
max:
|
||||
# orderExecutors is one of the risk control
|
||||
orderExecutors:
|
||||
# symbol-routed order executor
|
||||
bySymbol:
|
||||
MAXUSDT:
|
||||
# basic risk control order executor
|
||||
basic:
|
||||
minQuoteBalance: 1000.0
|
||||
maxBaseAssetBalance: 5000.0
|
||||
minBaseAssetBalance: 10.0
|
||||
maxOrderAmount: 200.0
|
||||
|
||||
exchangeStrategies:
|
||||
- on: max
|
||||
grid:
|
||||
symbol: MAXUSDT
|
||||
interval: 1m
|
||||
baseQuantity: 200.0
|
||||
gridPips: 0.02
|
||||
gridNumber: 2
|
||||
|
|
@ -22,11 +22,15 @@ sessions:
|
|||
exchange: binance
|
||||
envVarPrefix: binance
|
||||
|
||||
max:
|
||||
exchange: max
|
||||
envVarPrefix: max
|
||||
|
||||
riskControls:
|
||||
# This is the session-based risk controller, which let you configure different risk controller by session.
|
||||
sessionBased:
|
||||
# "max" is the session name that you want to configure the risk control
|
||||
binance:
|
||||
max:
|
||||
# orderExecutors is one of the risk control
|
||||
orderExecutors:
|
||||
# symbol-routed order executor
|
||||
|
|
|
@ -135,7 +135,7 @@ func (environ *Environment) Init(ctx context.Context) (err error) {
|
|||
for interval := range types.SupportedIntervals {
|
||||
kLines, err := session.Exchange.QueryKLines(ctx, symbol, interval.String(), types.KLineQueryOptions{
|
||||
EndTime: &now,
|
||||
Limit: 100,
|
||||
Limit: 500, // indicators need at least 100
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -28,7 +28,6 @@ func (e *ExchangeOrderExecutionRouter) SubmitOrdersTo(ctx context.Context, sessi
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// e.Notify(":memo: Submitting order to %s %s %s %s with quantity: %s", session, order.Symbol, order.Type, order.Side, order.QuantityString, order)
|
||||
return es.Exchange.SubmitOrders(ctx, formattedOrders...)
|
||||
}
|
||||
|
||||
|
@ -44,9 +43,9 @@ func (e *ExchangeOrderExecutor) notifySubmitOrders(orders ...types.SubmitOrder)
|
|||
// pass submit order as an interface object.
|
||||
channel, ok := e.RouteObject(&order)
|
||||
if ok {
|
||||
e.NotifyTo(channel, ":memo: Submitting %s %s %s order with quantity: %s", order.Symbol, order.Type, order.Side, order.QuantityString, &order)
|
||||
e.NotifyTo(channel, ":memo: Submitting %s %s %s order with quantity: %s at price: %s", order.Symbol, order.Type, order.Side, order.QuantityString, order.PriceString, &order)
|
||||
} else {
|
||||
e.Notify(":memo: Submitting %s %s %s order with quantity: %s", order.Symbol, order.Type, order.Side, order.QuantityString, &order)
|
||||
e.Notify(":memo: Submitting %s %s %s order with quantity: %s at price: %s", order.Symbol, order.Type, order.Side, order.QuantityString, order.PriceString, &order)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,26 +362,33 @@ func (e *Exchange) QueryKLines(ctx context.Context, symbol, interval string, opt
|
|||
limit = options.Limit
|
||||
}
|
||||
|
||||
i, err := maxapi.ParseInterval(interval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// workaround for the kline query
|
||||
if options.EndTime != nil && options.StartTime == nil {
|
||||
startTime := options.EndTime.Add(- time.Duration(limit) * time.Minute * time.Duration(i))
|
||||
options.StartTime = &startTime
|
||||
}
|
||||
|
||||
if options.StartTime == nil {
|
||||
return nil, errors.New("start time can not be empty")
|
||||
}
|
||||
|
||||
if options.EndTime != nil {
|
||||
return nil, errors.New("end time is not supported")
|
||||
}
|
||||
|
||||
log.Infof("querying kline %s %s %v", symbol, interval, options)
|
||||
log.Infof("querying kline %s %s %+v", symbol, interval, options)
|
||||
|
||||
// avoid rate limit
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
localKlines, err := e.client.PublicService.KLines(toLocalSymbol(symbol), interval, *options.StartTime, limit)
|
||||
localKLines, err := e.client.PublicService.KLines(toLocalSymbol(symbol), interval, *options.StartTime, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kLines []types.KLine
|
||||
for _, k := range localKlines {
|
||||
for _, k := range localKLines {
|
||||
kLines = append(kLines, k.KLine())
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ func mustParseTicker(v *fastjson.Value) Ticker {
|
|||
|
||||
type Interval int64
|
||||
|
||||
func parseResolution(a string) (Interval, error) {
|
||||
func ParseInterval(a string) (Interval, error) {
|
||||
switch strings.ToLower(a) {
|
||||
|
||||
case "1m":
|
||||
|
@ -170,12 +170,21 @@ func parseResolution(a string) (Interval, error) {
|
|||
case "1h":
|
||||
return 60, nil
|
||||
|
||||
case "2h":
|
||||
return 60 * 2, nil
|
||||
|
||||
case "3h":
|
||||
return 60 * 3, nil
|
||||
|
||||
case "4h":
|
||||
return 60 * 4, nil
|
||||
|
||||
case "6h":
|
||||
return 60 * 6, nil
|
||||
|
||||
case "8h":
|
||||
return 60 * 8, nil
|
||||
|
||||
case "12h":
|
||||
return 60 * 12, nil
|
||||
|
||||
|
@ -190,7 +199,7 @@ func parseResolution(a string) (Interval, error) {
|
|||
|
||||
}
|
||||
|
||||
return 0, errors.New("incorrect resolution")
|
||||
return 0, errors.Errorf("incorrect resolution: %q", a)
|
||||
}
|
||||
|
||||
type KLine struct {
|
||||
|
@ -224,7 +233,7 @@ func (s *PublicService) KLines(symbol string, resolution string, start time.Time
|
|||
queries := url.Values{}
|
||||
queries.Set("market", symbol)
|
||||
|
||||
interval, err := parseResolution(resolution)
|
||||
interval, err := ParseInterval(resolution)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -232,7 +241,7 @@ func (s *PublicService) KLines(symbol string, resolution string, start time.Time
|
|||
|
||||
nilTime := time.Time{}
|
||||
if start != nilTime {
|
||||
queries.Set("timestamp", strconv.FormatInt(start.Unix(), 64))
|
||||
queries.Set("timestamp", strconv.FormatInt(start.Unix(), 10))
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
|
|
|
@ -39,10 +39,18 @@ type BOLL struct {
|
|||
}
|
||||
|
||||
func (inc *BOLL) LastUpBand() float64 {
|
||||
if len(inc.UpBand) == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return inc.UpBand[len(inc.UpBand)-1]
|
||||
}
|
||||
|
||||
func (inc *BOLL) LastDownBand() float64 {
|
||||
if len(inc.DownBand) == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return inc.DownBand[len(inc.DownBand)-1]
|
||||
}
|
||||
|
||||
|
@ -85,6 +93,8 @@ func (inc *BOLL) calculateAndUpdate(kLines []types.KLine) {
|
|||
// update end time
|
||||
inc.EndTime = kLines[index].EndTime
|
||||
|
||||
// log.Infof("update boll: sma=%f, up=%f, down=%f", sma, upBand, downBand)
|
||||
|
||||
inc.EmitUpdate(sma, upBand, downBand)
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ func (s *Strategy) updateBidOrders(orderExecutor bbgo.OrderExecutor, session *bb
|
|||
}
|
||||
|
||||
var downBand = s.boll.LastDownBand()
|
||||
if downBand <= 0.0 {
|
||||
return
|
||||
}
|
||||
|
||||
var startPrice = downBand
|
||||
|
||||
var submitOrders []types.SubmitOrder
|
||||
|
@ -130,6 +134,10 @@ func (s *Strategy) updateAskOrders(orderExecutor bbgo.OrderExecutor, session *bb
|
|||
}
|
||||
|
||||
var upBand = s.boll.LastUpBand()
|
||||
if upBand <= 0.0 {
|
||||
return
|
||||
}
|
||||
|
||||
var startPrice = upBand
|
||||
|
||||
var submitOrders []types.SubmitOrder
|
||||
|
|
|
@ -45,11 +45,10 @@ func (m Market) FormatPriceCurrency(val float64) string {
|
|||
|
||||
func (m Market) FormatPrice(val float64) string {
|
||||
// p := math.Pow10(m.PricePrecision)
|
||||
|
||||
prec := int(math.Abs(math.Log10(m.MinPrice)))
|
||||
p := math.Pow10(prec)
|
||||
val = math.Trunc(val*p) / p
|
||||
return strconv.FormatFloat(val, 'f', m.PricePrecision, 64)
|
||||
return strconv.FormatFloat(val, 'f', prec, 64)
|
||||
}
|
||||
|
||||
func (m Market) FormatQuantity(val float64) string {
|
||||
|
|
Loading…
Reference in New Issue
Block a user