Skip to content

Commit

Permalink
bithumb: Add basic exchange order execution limits (thrasher-corp#726)
Browse files Browse the repository at this point in the history
* bithumn: Add basic exchange order execution limits

* WOW

* bithumb: add calculation for minimum amounts based off front end calculations regards @thrasher

* bithumb: fix nits
  • Loading branch information
shazbert authored Jul 29, 2021
1 parent a238131 commit 431c0fd
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 1 deletion.
41 changes: 41 additions & 0 deletions exchanges/bithumb/bithumb.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"net/http"
"net/url"
"reflect"
Expand All @@ -16,6 +17,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
)

Expand Down Expand Up @@ -619,3 +622,41 @@ func (b *Bithumb) GetCandleStick(symbol, interval string) (resp OHLCVResponse, e
err = b.SendHTTPRequest(exchange.RestSpot, path, &resp)
return
}

// FetchExchangeLimits fetches spot order execution limits
func (b *Bithumb) FetchExchangeLimits() ([]order.MinMaxLevel, error) {
ticks, err := b.GetAllTickers()
if err != nil {
return nil, err
}

var limits []order.MinMaxLevel
for code, data := range ticks {
c := currency.NewCode(code)
cp := currency.NewPair(c, currency.KRW)
if err != nil {
return nil, err
}

limits = append(limits, order.MinMaxLevel{
Pair: cp,
Asset: asset.Spot,
MinAmount: getAmountMinimum(data.ClosingPrice),
})
}
return limits, nil
}

// getAmountMinimum derives the minimum amount based on current price. This
// keeps amount in line with front end, rounded to 4 decimal places. As
// transaction policy:
// https://en.bithumb.com/customer_support/info_guide?seq=537&categorySeq=302
// Seems to not be inline with front end limits.
func getAmountMinimum(unitPrice float64) float64 {
if unitPrice <= 0 {
return 0
}
ratio := 500 / unitPrice
pow := math.Pow(10, float64(4))
return math.Ceil(ratio*pow) / pow // Round up our units
}
80 changes: 80 additions & 0 deletions exchanges/bithumb/bithumb_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bithumb

import (
"errors"
"log"
"os"
"testing"
Expand Down Expand Up @@ -616,3 +617,82 @@ func TestGetHistoricTrades(t *testing.T) {
t.Error(err)
}
}

func TestUpdateOrderExecutionLimits(t *testing.T) {
err := b.UpdateOrderExecutionLimits("")
if err != nil {
t.Fatal(err)
}
cp := currency.NewPair(currency.BTC, currency.KRW)
limit, err := b.GetOrderExecutionLimits(asset.Spot, cp)
if err != nil {
t.Fatal(err)
}

err = limit.Conforms(46241000, 0.00001, order.Limit)
if !errors.Is(err, order.ErrAmountBelowMin) {
t.Fatalf("expected error %v but received %v",
order.ErrAmountBelowMin,
err)
}

err = limit.Conforms(46241000, 0.0001, order.Limit)
if !errors.Is(err, nil) {
t.Fatalf("expected error %v but received %v",
nil,
err)
}
}

func TestGetAmountMinimum(t *testing.T) {
testCases := []struct {
name string
unitprice float64
expected float64
}{
{
name: "ETH-KRW",
unitprice: 2638000.0,
expected: 0.0002,
},
{
name: "DOGE-KRW",
unitprice: 236.5,
expected: 2.1142,
},
{
name: "XRP-KRW",
unitprice: 818.8,
expected: 0.6107,
},
{
name: "LTC-KRW",
unitprice: 160100,
expected: 0.0032,
},
{
name: "BTC-KRW",
unitprice: 46079000,
expected: 0.0001,
},
{
name: "nonsense",
unitprice: 0,
expected: 0,
},
}

for i := range testCases {
tt := &testCases[i]
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
minAmount := getAmountMinimum(tt.unitprice)
if minAmount != tt.expected {
t.Fatalf("expected: %f but received: %f for unit price: %f",
tt.expected,
minAmount,
tt.unitprice)
}
})
}
}
19 changes: 18 additions & 1 deletion exchanges/bithumb/bithumb_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,19 @@ func (b *Bithumb) Run() {
b.PrintEnabledPairs()
}

err := b.UpdateOrderExecutionLimits("")
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to set exchange order execution limits. Err: %v",
b.Name,
err)
}

if !b.GetEnabledFeatures().AutoPairUpdates {
return
}

err := b.UpdateTradablePairs(false)
err = b.UpdateTradablePairs(false)
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", b.Name, err)
}
Expand Down Expand Up @@ -797,3 +805,12 @@ func (b *Bithumb) GetHistoricCandles(pair currency.Pair, a asset.Item, start, en
func (b *Bithumb) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, start, end time.Time, interval kline.Interval) (kline.Item, error) {
return b.GetHistoricCandles(pair, a, start, end, interval)
}

// UpdateOrderExecutionLimits sets exchange executions for a required asset type
func (b *Bithumb) UpdateOrderExecutionLimits(_ asset.Item) error {
limits, err := b.FetchExchangeLimits()
if err != nil {
return fmt.Errorf("cannot update exchange execution limits: %w", err)
}
return b.LoadLimits(limits)
}

0 comments on commit 431c0fd

Please sign in to comment.