mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Binance,Okx: Add Leverage, MarginType, Positions and CollateralMode support (#1220)
* init * surprise train commit * basic distinctions * the terms of binance are confusing * renames and introduction of allocatedMargin * add new margin funcs * pulling out wires * implement proper getposition stuff * bad coding day * investigate order manager next * a broken mess, but a progressing one * finally completes some usdtmargined stuff * coinMfutures eludes me * expand to okx * imports fix * completes okx wrapper implementations * cleans and polishes before rpc implementations * rpc setup, order manager features, exch features * more rpc, collateral and margin things * mini test * looking at rpc response, expansion of features * reorganising before the storm * changing how futures requests work * cleanup and tests of cli usage * remove silly client side logic * cleanup * collateral package, typo fix, margin err, rpc derive * uses convert.StringToFloat ONLY ON STRUCTS FROM THIS PR * fix binance order history bug * niteroos * adds new funcs to exchange standards testing * more post merge fixes * fix binance * replace simepletimeformat * fix for merge * merge fixes * micro fixes * order side now required for leverage * fix up the rest * global -> portfolio collateral * Update exchanges/collateral/collateral_test.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * adds fields and todos * rm field redundancy * lint fix oopsie daisy * fixes panic, expands error and cli explanations (sorry shaz) * ensures casing is appropriate for underlying * Adds a shiny TODO --------- Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
@@ -483,10 +483,7 @@ func (bot *Engine) Start() error {
|
||||
bot.ExchangeManager,
|
||||
bot.CommunicationsManager,
|
||||
&bot.ServicesWG,
|
||||
bot.Config.OrderManager.Verbose,
|
||||
bot.Config.OrderManager.ActivelyTrackFuturesPositions,
|
||||
bot.Config.OrderManager.FuturesTrackingSeekDuration,
|
||||
); err != nil {
|
||||
&bot.Config.OrderManager); err != nil {
|
||||
gctlog.Errorf(gctlog.Global, "Order manager unable to setup: %s", err)
|
||||
} else {
|
||||
bot.OrderManager = o
|
||||
|
||||
@@ -133,13 +133,7 @@ func (bot *Engine) SetSubsystem(subSystemName string, enable bool) error {
|
||||
case OrderManagerName:
|
||||
if enable {
|
||||
if bot.OrderManager == nil {
|
||||
bot.OrderManager, err = SetupOrderManager(
|
||||
bot.ExchangeManager,
|
||||
bot.CommunicationsManager,
|
||||
&bot.ServicesWG,
|
||||
bot.Config.OrderManager.Verbose,
|
||||
bot.Config.OrderManager.ActivelyTrackFuturesPositions,
|
||||
bot.Config.OrderManager.FuturesTrackingSeekDuration)
|
||||
bot.OrderManager, err = SetupOrderManager(bot.ExchangeManager, bot.CommunicationsManager, &bot.ServicesWG, &bot.Config.OrderManager)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/communications/base"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
@@ -24,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
// SetupOrderManager will boot up the OrderManager
|
||||
func SetupOrderManager(exchangeManager iExchangeManager, communicationsManager iCommsManager, wg *sync.WaitGroup, verbose, activelyTrackFuturesPositions bool, futuresTrackingSeekDuration time.Duration) (*OrderManager, error) {
|
||||
func SetupOrderManager(exchangeManager iExchangeManager, communicationsManager iCommsManager, wg *sync.WaitGroup, cfg *config.OrderManager) (*OrderManager, error) {
|
||||
if exchangeManager == nil {
|
||||
return nil, errNilExchangeManager
|
||||
}
|
||||
@@ -34,10 +35,18 @@ func SetupOrderManager(exchangeManager iExchangeManager, communicationsManager i
|
||||
if wg == nil {
|
||||
return nil, errNilWaitGroup
|
||||
}
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("%w OrderManager", errNilConfig)
|
||||
}
|
||||
|
||||
var respectOrderHistoryLimits bool
|
||||
if cfg.RespectOrderHistoryLimits != nil {
|
||||
respectOrderHistoryLimits = *cfg.RespectOrderHistoryLimits
|
||||
}
|
||||
om := &OrderManager{
|
||||
shutdown: make(chan struct{}),
|
||||
activelyTrackFuturesPositions: activelyTrackFuturesPositions,
|
||||
activelyTrackFuturesPositions: cfg.ActivelyTrackFuturesPositions,
|
||||
respectOrderHistoryLimits: respectOrderHistoryLimits,
|
||||
orderStore: store{
|
||||
Orders: make(map[string][]*order.Detail),
|
||||
exchangeManager: exchangeManager,
|
||||
@@ -45,16 +54,19 @@ func SetupOrderManager(exchangeManager iExchangeManager, communicationsManager i
|
||||
wg: wg,
|
||||
futuresPositionController: order.SetupPositionController(),
|
||||
},
|
||||
verbose: verbose,
|
||||
verbose: cfg.Verbose,
|
||||
cfg: orderManagerConfig{
|
||||
CancelOrdersOnShutdown: cfg.CancelOrdersOnShutdown,
|
||||
},
|
||||
}
|
||||
if activelyTrackFuturesPositions {
|
||||
if futuresTrackingSeekDuration > 0 {
|
||||
futuresTrackingSeekDuration = -futuresTrackingSeekDuration
|
||||
if cfg.ActivelyTrackFuturesPositions {
|
||||
if cfg.FuturesTrackingSeekDuration > 0 {
|
||||
cfg.FuturesTrackingSeekDuration *= -1
|
||||
}
|
||||
if futuresTrackingSeekDuration == 0 {
|
||||
futuresTrackingSeekDuration = defaultOrderSeekTime
|
||||
if cfg.FuturesTrackingSeekDuration == 0 {
|
||||
cfg.FuturesTrackingSeekDuration = defaultOrderSeekTime
|
||||
}
|
||||
om.futuresPositionSeekDuration = futuresTrackingSeekDuration
|
||||
om.futuresPositionSeekDuration = cfg.FuturesTrackingSeekDuration
|
||||
}
|
||||
return om, nil
|
||||
}
|
||||
@@ -699,9 +711,9 @@ func (m *OrderManager) processOrders() {
|
||||
wg.Add(1)
|
||||
go m.processMatchingOrders(exchanges[x], orders, &wg)
|
||||
}
|
||||
|
||||
if m.activelyTrackFuturesPositions && enabledAssets[y].IsFutures() {
|
||||
var positions []order.PositionDetails
|
||||
supportedFeatures := exchanges[x].GetSupportedFeatures()
|
||||
if m.activelyTrackFuturesPositions && enabledAssets[y].IsFutures() && supportedFeatures.FuturesCapabilities.OrderManagerPositionTracking {
|
||||
var positions []order.PositionResponse
|
||||
var sd time.Time
|
||||
sd, err = m.orderStore.futuresPositionController.LastUpdated()
|
||||
if err != nil {
|
||||
@@ -711,10 +723,11 @@ func (m *OrderManager) processOrders() {
|
||||
if sd.IsZero() {
|
||||
sd = time.Now().Add(m.futuresPositionSeekDuration)
|
||||
}
|
||||
positions, err = exchanges[x].GetFuturesPositions(context.TODO(), &order.PositionsRequest{
|
||||
Asset: enabledAssets[y],
|
||||
Pairs: pairs,
|
||||
StartDate: sd,
|
||||
positions, err = exchanges[x].GetFuturesPositionOrders(context.TODO(), &order.PositionsRequest{
|
||||
Asset: enabledAssets[y],
|
||||
Pairs: pairs,
|
||||
StartDate: sd,
|
||||
RespectOrderHistoryLimits: m.respectOrderHistoryLimits,
|
||||
})
|
||||
if err != nil {
|
||||
if !errors.Is(err, common.ErrNotYetImplemented) {
|
||||
@@ -728,7 +741,7 @@ func (m *OrderManager) processOrders() {
|
||||
}
|
||||
err = m.processFuturesPositions(exchanges[x], &positions[z])
|
||||
if err != nil {
|
||||
log.Errorf(log.OrderMgr, "unable to process future positions for %v %v %v. err: %v", positions[z].Exchange, positions[z].Asset, positions[z].Pair, err)
|
||||
log.Errorf(log.OrderMgr, "unable to process future positions for %v %v %v. err: %v", exchanges[x].GetName(), positions[z].Asset, positions[z].Pair, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,7 +754,7 @@ func (m *OrderManager) processOrders() {
|
||||
}
|
||||
|
||||
// processFuturesPositions ensures any open position found is kept up to date in the order manager
|
||||
func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, position *order.PositionDetails) error {
|
||||
func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, position *order.PositionResponse) error {
|
||||
if !m.activelyTrackFuturesPositions {
|
||||
return errFuturesTrackingDisabled
|
||||
}
|
||||
@@ -749,14 +762,15 @@ func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, posit
|
||||
return fmt.Errorf("%w IBotExchange", common.ErrNilPointer)
|
||||
}
|
||||
if position == nil {
|
||||
return fmt.Errorf("%w PositionDetails", common.ErrNilPointer)
|
||||
return fmt.Errorf("%w PositionResponse", common.ErrNilPointer)
|
||||
}
|
||||
if len(position.Orders) == 0 {
|
||||
return fmt.Errorf("%w position for '%v' '%v' '%v' has no orders", errNilOrder, position.Exchange, position.Asset, position.Pair)
|
||||
return fmt.Errorf("%w position for '%v' '%v' '%v' has no orders", errNilOrder, exch.GetName(), position.Asset, position.Pair)
|
||||
}
|
||||
sort.Slice(position.Orders, func(i, j int) bool {
|
||||
return position.Orders[i].Date.Before(position.Orders[j].Date)
|
||||
})
|
||||
feat := exch.GetSupportedFeatures()
|
||||
var err error
|
||||
for i := range position.Orders {
|
||||
err = m.orderStore.futuresPositionController.TrackNewOrder(&position.Orders[i])
|
||||
@@ -764,7 +778,7 @@ func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, posit
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = m.orderStore.futuresPositionController.GetOpenPosition(position.Exchange, position.Asset, position.Pair)
|
||||
_, err = m.orderStore.futuresPositionController.GetOpenPosition(exch.GetName(), position.Asset, position.Pair)
|
||||
if err != nil {
|
||||
if errors.Is(err, order.ErrPositionNotFound) {
|
||||
return nil
|
||||
@@ -773,11 +787,14 @@ func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, posit
|
||||
}
|
||||
tick, err := exch.FetchTicker(context.TODO(), position.Pair, position.Asset)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w when fetching ticker data for %v %v %v", err, position.Exchange, position.Asset, position.Pair)
|
||||
return fmt.Errorf("%w when fetching ticker data for %v %v %v", err, exch.GetName(), position.Asset, position.Pair)
|
||||
}
|
||||
_, err = m.UpdateOpenPositionUnrealisedPNL(position.Exchange, position.Asset, position.Pair, tick.Last, tick.LastUpdated)
|
||||
_, err = m.UpdateOpenPositionUnrealisedPNL(exch.GetName(), position.Asset, position.Pair, tick.Last, tick.LastUpdated)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w when updating unrealised PNL for %v %v %v", err, position.Exchange, position.Asset, position.Pair)
|
||||
return fmt.Errorf("%w when updating unrealised PNL for %v %v %v", err, exch.GetName(), position.Asset, position.Pair)
|
||||
}
|
||||
if !feat.FuturesCapabilities.FundingRates {
|
||||
return nil
|
||||
}
|
||||
isPerp, err := exch.IsPerpetualFutureCurrency(position.Asset, position.Pair)
|
||||
if err != nil {
|
||||
|
||||
@@ -120,18 +120,17 @@ func (f omfExchange) ModifyOrder(_ context.Context, action *order.Modify) (*orde
|
||||
return modResp, nil
|
||||
}
|
||||
|
||||
func (f omfExchange) GetFuturesPositions(_ context.Context, req *order.PositionsRequest) ([]order.PositionDetails, error) {
|
||||
func (f omfExchange) GetFuturesPositionOrders(_ context.Context, req *order.PositionsRequest) ([]order.PositionResponse, error) {
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := make([]order.PositionDetails, len(req.Pairs))
|
||||
resp := make([]order.PositionResponse, len(req.Pairs))
|
||||
tt := time.Now()
|
||||
for i := range req.Pairs {
|
||||
resp[i] = order.PositionDetails{
|
||||
Exchange: f.GetName(),
|
||||
Asset: req.Asset,
|
||||
Pair: req.Pairs[i],
|
||||
resp[i] = order.PositionResponse{
|
||||
Asset: req.Asset,
|
||||
Pair: req.Pairs[i],
|
||||
Orders: []order.Detail{
|
||||
{
|
||||
Exchange: f.GetName(),
|
||||
@@ -156,28 +155,28 @@ func (f omfExchange) GetFuturesPositions(_ context.Context, req *order.Positions
|
||||
}
|
||||
|
||||
func TestSetupOrderManager(t *testing.T) {
|
||||
_, err := SetupOrderManager(nil, nil, nil, false, false, 0)
|
||||
_, err := SetupOrderManager(nil, nil, nil, nil)
|
||||
if !errors.Is(err, errNilExchangeManager) {
|
||||
t.Errorf("error '%v', expected '%v'", err, errNilExchangeManager)
|
||||
}
|
||||
_, err = SetupOrderManager(NewExchangeManager(), nil, nil, false, false, 0)
|
||||
_, err = SetupOrderManager(NewExchangeManager(), nil, nil, nil)
|
||||
if !errors.Is(err, errNilCommunicationsManager) {
|
||||
t.Errorf("error '%v', expected '%v'", err, errNilCommunicationsManager)
|
||||
}
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, nil, false, false, 0)
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, nil, &config.OrderManager{})
|
||||
if !errors.Is(err, errNilWaitGroup) {
|
||||
t.Errorf("error '%v', expected '%v'", err, errNilWaitGroup)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, false, false, 0)
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, false, true, 0)
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, &config.OrderManager{ActivelyTrackFuturesPositions: true, FuturesTrackingSeekDuration: 0})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, false, true, 1337)
|
||||
_, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, &config.OrderManager{ActivelyTrackFuturesPositions: true, FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -190,7 +189,7 @@ func TestOrderManagerStart(t *testing.T) {
|
||||
t.Errorf("error '%v', expected '%v'", err, ErrNilSubsystem)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
m, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, false, false, 0)
|
||||
m, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -211,7 +210,7 @@ func TestOrderManagerIsRunning(t *testing.T) {
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
m, err := SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, false, false, 0)
|
||||
m, err := SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -236,7 +235,7 @@ func TestOrderManagerStop(t *testing.T) {
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
m, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, false, false, 0)
|
||||
m, err = SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -281,7 +280,7 @@ func OrdersSetup(t *testing.T) *OrderManager {
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
m, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, 0)
|
||||
m, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -749,7 +748,7 @@ func TestProcessOrders(t *testing.T) {
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
m, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, 0)
|
||||
m, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1445,7 +1444,7 @@ func TestOrderManagerAdd(t *testing.T) {
|
||||
func TestGetAllOpenFuturesPositions(t *testing.T) {
|
||||
t.Parallel()
|
||||
wg := &sync.WaitGroup{}
|
||||
o, err := SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, wg, false, false, time.Hour)
|
||||
o, err := SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1473,7 +1472,7 @@ func TestGetAllOpenFuturesPositions(t *testing.T) {
|
||||
func TestGetOpenFuturesPosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
wg := &sync.WaitGroup{}
|
||||
o, err := SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, wg, false, false, time.Hour)
|
||||
o, err := SetupOrderManager(NewExchangeManager(), &CommunicationManager{}, wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1521,7 +1520,12 @@ func TestGetOpenFuturesPosition(t *testing.T) {
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
o, err = SetupOrderManager(em, &CommunicationManager{}, wg, false, true, time.Hour)
|
||||
o, err = SetupOrderManager(em, &CommunicationManager{}, wg, &config.OrderManager{
|
||||
Enabled: convert.BoolPtr(true),
|
||||
FuturesTrackingSeekDuration: time.Hour,
|
||||
Verbose: true,
|
||||
ActivelyTrackFuturesPositions: true,
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1611,7 +1615,7 @@ func TestProcessFuturesPositions(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
o, err = SetupOrderManager(em, &CommunicationManager{}, &wg, false, true, time.Hour)
|
||||
o, err = SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{ActivelyTrackFuturesPositions: true, FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1622,11 +1626,10 @@ func TestProcessFuturesPositions(t *testing.T) {
|
||||
t.Errorf("received '%v', expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
position := &order.PositionDetails{
|
||||
Exchange: b.Name,
|
||||
Asset: asset.Spot,
|
||||
Pair: cp,
|
||||
Orders: nil,
|
||||
position := &order.PositionResponse{
|
||||
Asset: asset.Spot,
|
||||
Pair: cp,
|
||||
Orders: nil,
|
||||
}
|
||||
err = o.processFuturesPositions(fakeExchange, position)
|
||||
if !errors.Is(err, errNilOrder) {
|
||||
@@ -1657,4 +1660,10 @@ func TestProcessFuturesPositions(t *testing.T) {
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
|
||||
b.Features.Supports.FuturesCapabilities.FundingRates = true
|
||||
err = o.processFuturesPositions(fakeExchange, position)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ type OrderManager struct {
|
||||
verbose bool
|
||||
activelyTrackFuturesPositions bool
|
||||
futuresPositionSeekDuration time.Duration
|
||||
respectOrderHistoryLimits bool
|
||||
}
|
||||
|
||||
// store holds all orders by exchange
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/binance"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/collateral"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
||||
@@ -58,7 +59,7 @@ type fExchange struct {
|
||||
exchange.IBotExchange
|
||||
}
|
||||
|
||||
func (f fExchange) GetPositionSummary(context.Context, *order.PositionSummaryRequest) (*order.PositionSummary, error) {
|
||||
func (f fExchange) GetFuturesPositionSummary(context.Context, *order.PositionSummaryRequest) (*order.PositionSummary, error) {
|
||||
leet := decimal.NewFromInt(1337)
|
||||
return &order.PositionSummary{
|
||||
MaintenanceMarginRequirement: leet,
|
||||
@@ -67,27 +68,55 @@ func (f fExchange) GetPositionSummary(context.Context, *order.PositionSummaryReq
|
||||
CollateralUsed: leet,
|
||||
MarkPrice: leet,
|
||||
CurrentSize: leet,
|
||||
BreakEvenPrice: leet,
|
||||
AverageOpenPrice: leet,
|
||||
RecentPNL: leet,
|
||||
MarginFraction: leet,
|
||||
PositionPNL: leet,
|
||||
MaintenanceMarginFraction: leet,
|
||||
FreeCollateral: leet,
|
||||
TotalCollateral: leet,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f fExchange) GetFuturesPositions(_ context.Context, req *order.PositionsRequest) ([]order.PositionDetails, error) {
|
||||
func (f fExchange) ChangePositionMargin(_ context.Context, req *margin.PositionChangeRequest) (*margin.PositionChangeResponse, error) {
|
||||
return &margin.PositionChangeResponse{
|
||||
Exchange: f.GetName(),
|
||||
Pair: req.Pair,
|
||||
Asset: req.Asset,
|
||||
AllocatedMargin: req.NewAllocatedMargin,
|
||||
MarginType: req.MarginType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f fExchange) SetLeverage(_ context.Context, _ asset.Item, _ currency.Pair, _ margin.Type, _ float64, _ order.Side) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f fExchange) GetLeverage(_ context.Context, _ asset.Item, _ currency.Pair, _ margin.Type, _ order.Side) (float64, error) {
|
||||
return 1337, nil
|
||||
}
|
||||
|
||||
func (f fExchange) SetMarginType(_ context.Context, _ asset.Item, _ currency.Pair, _ margin.Type) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f fExchange) SetCollateralMode(_ context.Context, _ asset.Item, _ collateral.Mode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f fExchange) GetCollateralMode(_ context.Context, _ asset.Item) (collateral.Mode, error) {
|
||||
return collateral.SingleMode, nil
|
||||
}
|
||||
|
||||
func (f fExchange) GetFuturesPositionOrders(_ context.Context, req *order.PositionsRequest) ([]order.PositionResponse, error) {
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := make([]order.PositionDetails, len(req.Pairs))
|
||||
resp := make([]order.PositionResponse, len(req.Pairs))
|
||||
tt := time.Now()
|
||||
for i := range req.Pairs {
|
||||
resp[i] = order.PositionDetails{
|
||||
Exchange: f.GetName(),
|
||||
Asset: req.Asset,
|
||||
Pair: req.Pairs[i],
|
||||
resp[i] = order.PositionResponse{
|
||||
Asset: req.Asset,
|
||||
Pair: req.Pairs[i],
|
||||
Orders: []order.Detail{
|
||||
{
|
||||
Exchange: f.GetName(),
|
||||
@@ -288,7 +317,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
|
||||
CollateralCurrency: currency.USD,
|
||||
AvailableMaintenanceCollateral: decimal.NewFromInt(1338),
|
||||
AvailableCollateral: decimal.NewFromInt(1337),
|
||||
UsedBreakdown: &order.UsedCollateralBreakdown{
|
||||
UsedBreakdown: &collateral.UsedBreakdown{
|
||||
LockedInStakes: decimal.NewFromInt(3),
|
||||
LockedInNFTBids: decimal.NewFromInt(3),
|
||||
LockedInFeeVoucher: decimal.NewFromInt(3),
|
||||
@@ -296,7 +325,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
|
||||
LockedInSpotOrders: decimal.NewFromInt(3),
|
||||
LockedAsCollateral: decimal.NewFromInt(3),
|
||||
},
|
||||
BreakdownByCurrency: []order.CollateralByCurrency{
|
||||
BreakdownByCurrency: []collateral.ByCurrency{
|
||||
{
|
||||
Currency: currency.USD,
|
||||
TotalFunds: decimal.NewFromInt(1330),
|
||||
@@ -307,7 +336,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
|
||||
Currency: currency.DOGE,
|
||||
TotalFunds: decimal.NewFromInt(1000),
|
||||
ScaledUsed: decimal.NewFromInt(6),
|
||||
ScaledUsedBreakdown: &order.UsedCollateralBreakdown{
|
||||
ScaledUsedBreakdown: &collateral.UsedBreakdown{
|
||||
LockedInStakes: decimal.NewFromInt(1),
|
||||
LockedInNFTBids: decimal.NewFromInt(1),
|
||||
LockedInFeeVoucher: decimal.NewFromInt(1),
|
||||
@@ -332,7 +361,7 @@ func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollate
|
||||
// to do the bare minimum required with no API calls or credentials required
|
||||
func (f fExchange) UpdateAccountInfo(_ context.Context, a asset.Item) (account.Holdings, error) {
|
||||
if a == asset.Futures {
|
||||
return account.Holdings{}, errAssetTypeDisabled
|
||||
return account.Holdings{}, asset.ErrNotSupported
|
||||
}
|
||||
return account.Holdings{
|
||||
Exchange: f.GetName(),
|
||||
@@ -1249,8 +1278,8 @@ func TestUpdateAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Futures.String()})
|
||||
if !errors.Is(err, errAssetTypeDisabled) {
|
||||
t.Errorf("received '%v', expected '%v'", err, errAssetTypeDisabled)
|
||||
if !errors.Is(err, currency.ErrAssetNotFound) {
|
||||
t.Errorf("received '%v', expected '%v'", err, currency.ErrAssetNotFound)
|
||||
}
|
||||
|
||||
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{
|
||||
@@ -1286,7 +1315,7 @@ func TestGetOrders(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false, false, 0)
|
||||
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1396,7 +1425,7 @@ func TestGetOrder(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false, false, 0)
|
||||
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -1483,8 +1512,8 @@ func TestCheckVars(t *testing.T) {
|
||||
e.SetEnabled(true)
|
||||
|
||||
err = checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
||||
if !errors.Is(err, errAssetTypeDisabled) {
|
||||
t.Errorf("expected %v, got %v", errAssetTypeDisabled, err)
|
||||
if !errors.Is(err, currency.ErrPairManagerNotInitialised) {
|
||||
t.Errorf("expected %v, got %v", currency.ErrPairManagerNotInitialised, err)
|
||||
}
|
||||
|
||||
fmt1 := currency.PairStore{
|
||||
@@ -1935,7 +1964,7 @@ func TestGetManagedOrders(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false, false, 0)
|
||||
om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -2256,7 +2285,7 @@ func TestCurrencyStateTradingPair(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFuturesPositions(t *testing.T) {
|
||||
func TestGetFuturesPositionsOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
@@ -2297,7 +2326,7 @@ func TestGetFuturesPositions(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -2313,7 +2342,7 @@ func TestGetFuturesPositions(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
_, err = s.GetFuturesPositions(context.Background(), &gctrpc.GetFuturesPositionsRequest{
|
||||
_, err = s.GetFuturesPositionsOrders(context.Background(), &gctrpc.GetFuturesPositionsOrdersRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
@@ -2322,66 +2351,11 @@ func TestGetFuturesPositions(t *testing.T) {
|
||||
Quote: cp.Quote.String(),
|
||||
},
|
||||
})
|
||||
if !errors.Is(err, exchange.ErrCredentialsAreEmpty) {
|
||||
t.Fatalf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
|
||||
}
|
||||
|
||||
ctx := account.DeployCredentialsToContext(context.Background(),
|
||||
&account.Credentials{
|
||||
Key: "wow",
|
||||
Secret: "super wow",
|
||||
},
|
||||
)
|
||||
|
||||
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
|
||||
Exchange: "test",
|
||||
Asset: asset.Futures.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
},
|
||||
IncludeFullOrderData: true,
|
||||
IncludeFullFundingRates: true,
|
||||
IncludePredictedRate: true,
|
||||
GetPositionStats: true,
|
||||
GetFundingPayments: true,
|
||||
})
|
||||
if !errors.Is(err, ErrExchangeNotFound) {
|
||||
t.Errorf("received '%v', expected '%v'", err, ErrExchangeNotFound)
|
||||
}
|
||||
|
||||
od := &order.Detail{
|
||||
Price: 1337,
|
||||
Amount: 1337,
|
||||
Fee: 1.337,
|
||||
Exchange: fakeExchangeName,
|
||||
OrderID: "test",
|
||||
Side: order.Long,
|
||||
Status: order.Open,
|
||||
AssetType: asset.Futures,
|
||||
Date: time.Now(),
|
||||
Pair: cp,
|
||||
}
|
||||
err = s.OrderManager.orderStore.futuresPositionController.TrackNewOrder(od)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
},
|
||||
IncludeFullOrderData: true,
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
|
||||
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
|
||||
_, err = s.GetFuturesPositionsOrders(context.Background(), &gctrpc.GetFuturesPositionsOrdersRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Spot.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
@@ -2424,6 +2398,7 @@ func TestGetCollateral(t *testing.T) {
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
b.Features.Supports.FuturesCapabilities.Collateral = true
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
@@ -2965,6 +2940,7 @@ func TestGetFundingRates(t *testing.T) {
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
b.Features.Supports.FuturesCapabilities.FundingRates = true
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
@@ -2973,7 +2949,7 @@ func TestGetFundingRates(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -3073,7 +3049,7 @@ func TestGetLatestFundingRate(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -3164,6 +3140,7 @@ func TestGetManagedPosition(t *testing.T) {
|
||||
Available: currency.Pairs{cp, cp2},
|
||||
Enabled: currency.Pairs{cp, cp2},
|
||||
}
|
||||
b.Features.Supports.FuturesCapabilities.OrderManagerPositionTracking = true
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
@@ -3172,7 +3149,7 @@ func TestGetManagedPosition(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -3221,7 +3198,7 @@ func TestGetManagedPosition(t *testing.T) {
|
||||
}
|
||||
|
||||
request.Asset = asset.Futures.String()
|
||||
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
|
||||
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -3314,7 +3291,7 @@ func TestGetAllManagedPositions(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, time.Hour)
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -3335,7 +3312,7 @@ func TestGetAllManagedPositions(t *testing.T) {
|
||||
}
|
||||
|
||||
request := &gctrpc.GetAllManagedPositionsRequest{}
|
||||
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, false, true, time.Hour)
|
||||
s.OrderManager, err = SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{FuturesTrackingSeekDuration: time.Hour, ActivelyTrackFuturesPositions: true})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
@@ -3706,3 +3683,383 @@ func TestGetOrderbookAmountByImpact(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", impact.AmountRequired, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangePositionMargin(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exch.SetDefaults()
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
|
||||
cp, err := currency.NewPairFromString("btc-mad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
err = em.Add(fakeExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.ChangePositionMargin(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
req := &gctrpc.ChangePositionMarginRequest{}
|
||||
_, err = s.ChangePositionMargin(context.Background(), req)
|
||||
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
|
||||
t.Errorf("received '%v' expected '%v'", err, currency.ErrCurrencyPairEmpty)
|
||||
}
|
||||
|
||||
req.Exchange = fakeExchangeName
|
||||
req.Pair = &gctrpc.CurrencyPair{
|
||||
Delimiter: "-",
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
}
|
||||
req.Asset = asset.USDTMarginedFutures.String()
|
||||
req.MarginSide = "BOTH"
|
||||
req.OriginalAllocatedMargin = 1337
|
||||
req.NewAllocatedMargin = 1338
|
||||
req.MarginType = "isolated"
|
||||
_, err = s.ChangePositionMargin(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetLeverage(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exch.SetDefaults()
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
|
||||
cp, err := currency.NewPairFromString("btc-mad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
err = em.Add(fakeExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.SetLeverage(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
req := &gctrpc.SetLeverageRequest{}
|
||||
_, err = s.SetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.Exchange = fakeExchangeName
|
||||
req.Pair = &gctrpc.CurrencyPair{
|
||||
Delimiter: "-",
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
}
|
||||
req.UnderlyingPair = &gctrpc.CurrencyPair{
|
||||
Delimiter: "-",
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
}
|
||||
req.Asset = asset.USDTMarginedFutures.String()
|
||||
req.MarginType = "isolated"
|
||||
req.Leverage = 1337
|
||||
_, err = s.SetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.OrderSide = "lol"
|
||||
_, err = s.SetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, order.ErrSideIsInvalid) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.OrderSide = order.Long.String()
|
||||
_, err = s.SetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLeverage(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exch.SetDefaults()
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
|
||||
cp, err := currency.NewPairFromString("btc-mad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
err = em.Add(fakeExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.GetLeverage(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
req := &gctrpc.GetLeverageRequest{}
|
||||
_, err = s.GetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.Exchange = fakeExchangeName
|
||||
req.Pair = &gctrpc.CurrencyPair{
|
||||
Delimiter: "-",
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
}
|
||||
req.UnderlyingPair = &gctrpc.CurrencyPair{
|
||||
Delimiter: "-",
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
}
|
||||
req.Asset = asset.USDTMarginedFutures.String()
|
||||
req.MarginType = "isolated"
|
||||
lev, err := s.GetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
if lev.Leverage != 1337 {
|
||||
t.Errorf("received '%v' expected '%v'", lev, 1337)
|
||||
}
|
||||
|
||||
req.OrderSide = "lol"
|
||||
_, err = s.GetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, order.ErrSideIsInvalid) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.OrderSide = order.Long.String()
|
||||
_, err = s.GetLeverage(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetMarginType(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exch.SetDefaults()
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
|
||||
cp, err := currency.NewPairFromString("btc-mad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
err = em.Add(fakeExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.SetMarginType(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
req := &gctrpc.SetMarginTypeRequest{}
|
||||
_, err = s.SetMarginType(context.Background(), req)
|
||||
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.Exchange = fakeExchangeName
|
||||
req.Pair = &gctrpc.CurrencyPair{
|
||||
Delimiter: "-",
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
}
|
||||
req.Asset = asset.USDTMarginedFutures.String()
|
||||
req.MarginType = "isolated"
|
||||
_, err = s.SetMarginType(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetCollateralMode(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exch.SetDefaults()
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
|
||||
cp, err := currency.NewPairFromString("btc-mad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
ConfigFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
RequestFormat: ¤cy.PairFormat{Delimiter: "/"},
|
||||
Available: currency.Pairs{cp},
|
||||
Enabled: currency.Pairs{cp},
|
||||
}
|
||||
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
err = em.Add(fakeExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.SetCollateralMode(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
req := &gctrpc.SetCollateralModeRequest{}
|
||||
_, err = s.SetCollateralMode(context.Background(), req)
|
||||
if !errors.Is(err, ErrExchangeNameIsEmpty) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.Exchange = fakeExchangeName
|
||||
req.Asset = asset.USDTMarginedFutures.String()
|
||||
req.CollateralMode = "single"
|
||||
_, err = s.SetCollateralMode(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCollateralMode(t *testing.T) {
|
||||
t.Parallel()
|
||||
em := NewExchangeManager()
|
||||
exch, err := em.NewExchangeByName("binance")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exch.SetDefaults()
|
||||
b := exch.GetBase()
|
||||
b.Name = fakeExchangeName
|
||||
b.Enabled = true
|
||||
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
|
||||
b.CurrencyPairs.Pairs[asset.USDTMarginedFutures] = ¤cy.PairStore{
|
||||
AssetEnabled: convert.BoolPtr(true),
|
||||
}
|
||||
|
||||
fakeExchange := fExchange{
|
||||
IBotExchange: exch,
|
||||
}
|
||||
err = em.Add(fakeExchange)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
|
||||
_, err = s.GetCollateralMode(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
req := &gctrpc.GetCollateralModeRequest{}
|
||||
_, err = s.GetCollateralMode(context.Background(), req)
|
||||
if !errors.Is(err, ErrExchangeNameIsEmpty) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
req.Exchange = fakeExchangeName
|
||||
req.Asset = asset.USDTMarginedFutures.String()
|
||||
_, err = s.GetCollateralMode(context.Background(), req)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
@@ -133,7 +134,7 @@ func TestWebsocketRoutineManagerHandleData(t *testing.T) {
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, false, false, 0)
|
||||
om, err := SetupOrderManager(em, &CommunicationManager{}, &wg, &config.OrderManager{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("error '%v', expected '%v'", err, nil)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user