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:
Scott
2023-09-26 16:16:31 +10:00
committed by GitHub
parent a2ae99ed7f
commit 5f2f6f884b
67 changed files with 11558 additions and 4475 deletions

View File

@@ -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

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.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] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.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] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.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] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.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] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{Delimiter: "/"},
RequestFormat: &currency.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] = &currency.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)
}
}

View File

@@ -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)
}