mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-09 07:26:48 +00:00
* Initial concept for creating price tracking pairs * Completes coverage, even with a slow test * I dont know what point to hook this stuff up * Bit of a broken way of handling tracking pairs * Correctly calculates USD rates against all currencies * Removes dependency on GCT config * Failed currency statistics redesign * initial Update chart to use highcharts * Minor changes to stats * Creats funding stats to handle the stat calculations. Needs more work * tracks USD snapshots and BREAKS THINGS FURTHER * Fixed! * Adds ratio calculations and such, but its WRONG. do it at totals level dummy * End of day basic lint * Remaining lints * USD totals statistics * Minor panic fixes * Printing of funding stats, but its bad * Properly calculates overall benchmark, moves funding stat output * Adds some template charge, removes duplicate fields * New charts! * Darkcharts. funding protection when disabled * Now works with usd tracking/funding disabled! * Attempting to only show working stats based on settings. * Spruces up the goose/reporting * Completes report HTML rendering * lint and test fixes * funding statistics testing * slightly more test coverage * Test coverage * Initial documentation * Fixes tests * Database testing and rendering improvements and breakages * report and cmd rendering, linting. fix comma output. rm gct cfg * PR mode 🎉 Path field, config builder support,testing,linting,docs * minor calculation improvement * Secret lint that did not show up locally * Disable USD tracking for example configs * ShazNitNoScope * Forgotten errors * "" * literally Logarithmically logically renders the date 👀 * Fixes typos, fixes parallel test, fixes chart gui and exporting
563 lines
16 KiB
Go
563 lines
16 KiB
Go
package exchange
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/data/kline"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/event"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/fill"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/order"
|
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
|
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
|
gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
|
gctorder "github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
|
)
|
|
|
|
const testExchange = "binance"
|
|
|
|
type fakeFund struct{}
|
|
|
|
func (f *fakeFund) IncreaseAvailable(decimal.Decimal, gctorder.Side) {}
|
|
func (f *fakeFund) Release(decimal.Decimal, decimal.Decimal, gctorder.Side) error {
|
|
return nil
|
|
}
|
|
|
|
func TestReset(t *testing.T) {
|
|
t.Parallel()
|
|
e := Exchange{
|
|
CurrencySettings: []Settings{},
|
|
}
|
|
e.Reset()
|
|
if e.CurrencySettings != nil {
|
|
t.Error("expected nil")
|
|
}
|
|
}
|
|
|
|
func TestSetCurrency(t *testing.T) {
|
|
t.Parallel()
|
|
e := Exchange{}
|
|
e.SetExchangeAssetCurrencySettings("", "", currency.Pair{}, &Settings{})
|
|
if len(e.CurrencySettings) != 0 {
|
|
t.Error("expected 0")
|
|
}
|
|
cs := &Settings{
|
|
Exchange: testExchange,
|
|
UseRealOrders: true,
|
|
Pair: currency.NewPair(currency.BTC, currency.USDT),
|
|
Asset: asset.Spot,
|
|
ExchangeFee: decimal.Zero,
|
|
MakerFee: decimal.Zero,
|
|
TakerFee: decimal.Zero,
|
|
BuySide: MinMax{},
|
|
SellSide: MinMax{},
|
|
Leverage: Leverage{},
|
|
MinimumSlippageRate: decimal.Zero,
|
|
MaximumSlippageRate: decimal.Zero,
|
|
}
|
|
e.SetExchangeAssetCurrencySettings(testExchange, asset.Spot, currency.NewPair(currency.BTC, currency.USDT), cs)
|
|
result, err := e.GetCurrencySettings(testExchange, asset.Spot, currency.NewPair(currency.BTC, currency.USDT))
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !result.UseRealOrders {
|
|
t.Error("expected true")
|
|
}
|
|
e.SetExchangeAssetCurrencySettings(testExchange, asset.Spot, currency.NewPair(currency.BTC, currency.USDT), cs)
|
|
if len(e.CurrencySettings) != 1 {
|
|
t.Error("expected 1")
|
|
}
|
|
}
|
|
|
|
func TestEnsureOrderFitsWithinHLV(t *testing.T) {
|
|
t.Parallel()
|
|
adjustedPrice, adjustedAmount := ensureOrderFitsWithinHLV(decimal.NewFromInt(123), decimal.NewFromInt(1), decimal.NewFromInt(100), decimal.NewFromInt(99), decimal.NewFromInt(100))
|
|
if !adjustedAmount.Equal(decimal.NewFromInt(1)) {
|
|
t.Error("expected 1")
|
|
}
|
|
if !adjustedPrice.Equal(decimal.NewFromInt(100)) {
|
|
t.Error("expected 100")
|
|
}
|
|
|
|
adjustedPrice, adjustedAmount = ensureOrderFitsWithinHLV(decimal.NewFromInt(123), decimal.NewFromInt(1), decimal.NewFromInt(100), decimal.NewFromInt(99), decimal.NewFromInt(80))
|
|
if !adjustedAmount.Equal(decimal.NewFromFloat(0.799999992)) {
|
|
t.Errorf("received: %v, expected: %v", adjustedAmount, decimal.NewFromFloat(0.799999992))
|
|
}
|
|
if !adjustedPrice.Equal(decimal.NewFromInt(100)) {
|
|
t.Error("expected 100")
|
|
}
|
|
}
|
|
|
|
func TestCalculateExchangeFee(t *testing.T) {
|
|
t.Parallel()
|
|
fee := calculateExchangeFee(decimal.NewFromInt(1), decimal.NewFromInt(1), decimal.NewFromFloat(0.1))
|
|
if !fee.Equal(decimal.NewFromFloat(0.1)) {
|
|
t.Error("expected 0.1")
|
|
}
|
|
fee = calculateExchangeFee(decimal.NewFromInt(2), decimal.NewFromFloat(1), decimal.NewFromFloat(0.005))
|
|
if !fee.Equal(decimal.NewFromFloat(0.01)) {
|
|
t.Error("expected 0.01")
|
|
}
|
|
}
|
|
|
|
func TestSizeOrder(t *testing.T) {
|
|
t.Parallel()
|
|
e := Exchange{}
|
|
_, _, err := e.sizeOfflineOrder(decimal.Zero, decimal.Zero, decimal.Zero, nil, nil)
|
|
if !errors.Is(err, common.ErrNilArguments) {
|
|
t.Error(err)
|
|
}
|
|
cs := &Settings{}
|
|
f := &fill.Fill{
|
|
ClosePrice: decimal.NewFromInt(1337),
|
|
Amount: decimal.NewFromInt(1),
|
|
}
|
|
_, _, err = e.sizeOfflineOrder(decimal.Zero, decimal.Zero, decimal.Zero, cs, f)
|
|
if !errors.Is(err, errDataMayBeIncorrect) {
|
|
t.Errorf("received: %v, expected: %v", err, errDataMayBeIncorrect)
|
|
}
|
|
var p, a decimal.Decimal
|
|
p, a, err = e.sizeOfflineOrder(decimal.NewFromInt(10), decimal.NewFromInt(2), decimal.NewFromInt(10), cs, f)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !p.Equal(decimal.NewFromInt(10)) {
|
|
t.Error("expected 10")
|
|
}
|
|
if !a.Equal(decimal.NewFromInt(1)) {
|
|
t.Error("expected 1")
|
|
}
|
|
}
|
|
|
|
func TestPlaceOrder(t *testing.T) {
|
|
t.Parallel()
|
|
bot := &engine.Engine{}
|
|
var err error
|
|
em := engine.SetupExchangeManager()
|
|
exch, err := em.NewExchangeByName(testExchange)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exch.SetDefaults()
|
|
cfg, err := exch.GetDefaultConfig()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = exch.Setup(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
em.Add(exch)
|
|
bot.ExchangeManager = em
|
|
bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = bot.OrderManager.Start()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
e := Exchange{}
|
|
_, err = e.placeOrder(context.Background(), decimal.NewFromInt(1), decimal.NewFromInt(1), false, true, nil, nil)
|
|
if !errors.Is(err, common.ErrNilEvent) {
|
|
t.Errorf("received: %v, expected: %v", err, common.ErrNilEvent)
|
|
}
|
|
f := &fill.Fill{}
|
|
_, err = e.placeOrder(context.Background(), decimal.NewFromInt(1), decimal.NewFromInt(1), false, true, f, bot.OrderManager)
|
|
if err != nil && err.Error() != "order exchange name must be specified" {
|
|
t.Error(err)
|
|
}
|
|
|
|
f.Exchange = testExchange
|
|
_, err = e.placeOrder(context.Background(), decimal.NewFromInt(1), decimal.NewFromInt(1), false, true, f, bot.OrderManager)
|
|
if !errors.Is(err, gctorder.ErrPairIsEmpty) {
|
|
t.Errorf("received: %v, expected: %v", err, gctorder.ErrPairIsEmpty)
|
|
}
|
|
f.CurrencyPair = currency.NewPair(currency.BTC, currency.USDT)
|
|
f.AssetType = asset.Spot
|
|
f.Direction = gctorder.Buy
|
|
_, err = e.placeOrder(context.Background(), decimal.NewFromInt(1), decimal.NewFromInt(1), false, true, f, bot.OrderManager)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
_, err = e.placeOrder(context.Background(), decimal.NewFromInt(1), decimal.NewFromInt(1), true, true, f, bot.OrderManager)
|
|
if err != nil && !strings.Contains(err.Error(), "unset/default API keys") {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteOrder(t *testing.T) {
|
|
t.Parallel()
|
|
bot := &engine.Engine{}
|
|
var err error
|
|
em := engine.SetupExchangeManager()
|
|
exch, err := em.NewExchangeByName(testExchange)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exch.SetDefaults()
|
|
cfg, err := exch.GetDefaultConfig()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = exch.Setup(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
em.Add(exch)
|
|
bot.ExchangeManager = em
|
|
bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = bot.OrderManager.Start()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
p := currency.NewPair(currency.BTC, currency.USDT)
|
|
a := asset.Spot
|
|
_, err = exch.FetchOrderbook(context.Background(), p, a)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
cs := Settings{
|
|
Exchange: testExchange,
|
|
UseRealOrders: false,
|
|
Pair: p,
|
|
Asset: a,
|
|
ExchangeFee: decimal.NewFromFloat(0.01),
|
|
MakerFee: decimal.NewFromFloat(0.01),
|
|
TakerFee: decimal.NewFromFloat(0.01),
|
|
BuySide: MinMax{},
|
|
SellSide: MinMax{},
|
|
Leverage: Leverage{},
|
|
MinimumSlippageRate: decimal.Zero,
|
|
MaximumSlippageRate: decimal.NewFromInt(1),
|
|
}
|
|
e := Exchange{
|
|
CurrencySettings: []Settings{cs},
|
|
}
|
|
ev := event.Base{
|
|
Exchange: testExchange,
|
|
Time: time.Now(),
|
|
Interval: gctkline.FifteenMin,
|
|
CurrencyPair: p,
|
|
AssetType: a,
|
|
}
|
|
o := &order.Order{
|
|
Base: ev,
|
|
Direction: gctorder.Buy,
|
|
Amount: decimal.NewFromInt(10),
|
|
AllocatedFunds: decimal.NewFromInt(1337),
|
|
}
|
|
|
|
d := &kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: "",
|
|
Pair: currency.Pair{},
|
|
Asset: "",
|
|
Interval: 0,
|
|
Candles: []gctkline.Candle{
|
|
{
|
|
Close: 1,
|
|
High: 1,
|
|
Low: 1,
|
|
Volume: 1,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = d.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
d.Next()
|
|
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
cs.UseRealOrders = true
|
|
cs.CanUseExchangeLimits = true
|
|
o.Direction = gctorder.Sell
|
|
e.CurrencySettings = []Settings{cs}
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if err != nil && !strings.Contains(err.Error(), "unset/default API keys") {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteOrderBuySellSizeLimit(t *testing.T) {
|
|
t.Parallel()
|
|
bot := &engine.Engine{}
|
|
var err error
|
|
em := engine.SetupExchangeManager()
|
|
exch, err := em.NewExchangeByName(testExchange)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exch.SetDefaults()
|
|
cfg, err := exch.GetDefaultConfig()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = exch.Setup(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
em.Add(exch)
|
|
bot.ExchangeManager = em
|
|
bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = bot.OrderManager.Start()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
p := currency.NewPair(currency.BTC, currency.USDT)
|
|
a := asset.Spot
|
|
_, err = exch.FetchOrderbook(context.Background(), p, a)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = exch.UpdateOrderExecutionLimits(context.Background(), asset.Spot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
limits, err := exch.GetOrderExecutionLimits(a, p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
cs := Settings{
|
|
Exchange: testExchange,
|
|
UseRealOrders: false,
|
|
Pair: p,
|
|
Asset: a,
|
|
ExchangeFee: decimal.NewFromFloat(0.01),
|
|
MakerFee: decimal.NewFromFloat(0.01),
|
|
TakerFee: decimal.NewFromFloat(0.01),
|
|
BuySide: MinMax{
|
|
MaximumSize: decimal.NewFromFloat(0.01),
|
|
MinimumSize: decimal.Zero,
|
|
},
|
|
SellSide: MinMax{
|
|
MaximumSize: decimal.NewFromFloat(0.1),
|
|
MinimumSize: decimal.Zero,
|
|
},
|
|
Leverage: Leverage{},
|
|
MinimumSlippageRate: decimal.Zero,
|
|
MaximumSlippageRate: decimal.NewFromInt(1),
|
|
Limits: limits,
|
|
}
|
|
e := Exchange{
|
|
CurrencySettings: []Settings{cs},
|
|
}
|
|
ev := event.Base{
|
|
Exchange: testExchange,
|
|
Time: time.Now(),
|
|
Interval: gctkline.FifteenMin,
|
|
CurrencyPair: p,
|
|
AssetType: a,
|
|
}
|
|
o := &order.Order{
|
|
Base: ev,
|
|
Direction: gctorder.Buy,
|
|
Amount: decimal.NewFromInt(10),
|
|
AllocatedFunds: decimal.NewFromInt(1337),
|
|
}
|
|
|
|
d := &kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: "",
|
|
Pair: currency.Pair{},
|
|
Asset: "",
|
|
Interval: 0,
|
|
Candles: []gctkline.Candle{
|
|
{
|
|
Close: 1,
|
|
High: 1,
|
|
Low: 1,
|
|
Volume: 1,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = d.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
d.Next()
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if !errors.Is(err, errExceededPortfolioLimit) {
|
|
t.Errorf("received %v expected %v", err, errExceededPortfolioLimit)
|
|
}
|
|
o = &order.Order{
|
|
Base: ev,
|
|
Direction: gctorder.Buy,
|
|
Amount: decimal.NewFromInt(10),
|
|
AllocatedFunds: decimal.NewFromInt(1337),
|
|
}
|
|
cs.BuySide.MaximumSize = decimal.Zero
|
|
cs.BuySide.MinimumSize = decimal.NewFromFloat(0.01)
|
|
e.CurrencySettings = []Settings{cs}
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if err != nil && !strings.Contains(err.Error(), "exceed minimum size") {
|
|
t.Error(err)
|
|
}
|
|
if err != nil {
|
|
t.Error("limitReducedAmount adjusted to 0.99999999, direction BUY, should fall in buyside {MinimumSize:0.01 MaximumSize:0 MaximumTotal:0}")
|
|
}
|
|
o = &order.Order{
|
|
Base: ev,
|
|
Direction: gctorder.Sell,
|
|
Amount: decimal.NewFromInt(10),
|
|
AllocatedFunds: decimal.NewFromInt(1337),
|
|
}
|
|
cs.SellSide.MaximumSize = decimal.Zero
|
|
cs.SellSide.MinimumSize = decimal.NewFromFloat(0.01)
|
|
e.CurrencySettings = []Settings{cs}
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if err != nil && !strings.Contains(err.Error(), "exceed minimum size") {
|
|
t.Error(err)
|
|
}
|
|
if err != nil {
|
|
t.Error("limitReducedAmount adjust to 0.99999999, should fall in sell size {MinimumSize:0.01 MaximumSize:0 MaximumTotal:0}")
|
|
}
|
|
|
|
o = &order.Order{
|
|
Base: ev,
|
|
Direction: gctorder.Sell,
|
|
Amount: decimal.NewFromFloat(0.5),
|
|
AllocatedFunds: decimal.NewFromInt(1337),
|
|
}
|
|
cs.SellSide.MaximumSize = decimal.Zero
|
|
cs.SellSide.MinimumSize = decimal.NewFromInt(1)
|
|
e.CurrencySettings = []Settings{cs}
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if !errors.Is(err, errExceededPortfolioLimit) {
|
|
t.Errorf("received %v expected %v", err, errExceededPortfolioLimit)
|
|
}
|
|
|
|
o = &order.Order{
|
|
Base: ev,
|
|
Direction: gctorder.Sell,
|
|
Amount: decimal.NewFromFloat(0.02),
|
|
AllocatedFunds: decimal.NewFromFloat(0.01337),
|
|
}
|
|
cs.SellSide.MaximumSize = decimal.Zero
|
|
cs.SellSide.MinimumSize = decimal.NewFromFloat(0.01)
|
|
|
|
cs.UseRealOrders = true
|
|
cs.CanUseExchangeLimits = true
|
|
o.Direction = gctorder.Sell
|
|
e.CurrencySettings = []Settings{cs}
|
|
_, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{})
|
|
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
|
|
t.Errorf("received %v expected %v", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
|
|
}
|
|
}
|
|
|
|
func TestApplySlippageToPrice(t *testing.T) {
|
|
t.Parallel()
|
|
resp := applySlippageToPrice(gctorder.Buy, decimal.NewFromInt(1), decimal.NewFromFloat(0.9))
|
|
if !resp.Equal(decimal.NewFromFloat(1.1)) {
|
|
t.Errorf("received: %v, expected: %v", resp, decimal.NewFromFloat(1.1))
|
|
}
|
|
resp = applySlippageToPrice(gctorder.Sell, decimal.NewFromInt(1), decimal.NewFromFloat(0.9))
|
|
if !resp.Equal(decimal.NewFromFloat(0.9)) {
|
|
t.Errorf("received: %v, expected: %v", resp, decimal.NewFromFloat(0.9))
|
|
}
|
|
}
|
|
|
|
func TestReduceAmountToFitPortfolioLimit(t *testing.T) {
|
|
t.Parallel()
|
|
initialPrice := decimal.NewFromInt(100)
|
|
initialAmount := decimal.NewFromInt(10).Div(initialPrice)
|
|
portfolioAdjustedTotal := initialAmount.Mul(initialPrice)
|
|
adjustedPrice := decimal.NewFromInt(1000)
|
|
amount := decimal.NewFromInt(2)
|
|
finalAmount := reduceAmountToFitPortfolioLimit(adjustedPrice, amount, portfolioAdjustedTotal, gctorder.Buy)
|
|
if !finalAmount.Mul(adjustedPrice).Equal(portfolioAdjustedTotal) {
|
|
t.Errorf("expected value %v to match portfolio total %v", finalAmount.Mul(adjustedPrice), portfolioAdjustedTotal)
|
|
}
|
|
finalAmount = reduceAmountToFitPortfolioLimit(adjustedPrice, decimal.NewFromInt(133333333337), portfolioAdjustedTotal, gctorder.Sell)
|
|
if finalAmount != portfolioAdjustedTotal {
|
|
t.Errorf("expected value %v to match portfolio total %v", finalAmount, portfolioAdjustedTotal)
|
|
}
|
|
finalAmount = reduceAmountToFitPortfolioLimit(adjustedPrice, decimal.NewFromInt(1), portfolioAdjustedTotal, gctorder.Sell)
|
|
if !finalAmount.Equal(decimal.NewFromInt(1)) {
|
|
t.Errorf("expected value %v to match portfolio total %v", finalAmount, portfolioAdjustedTotal)
|
|
}
|
|
}
|
|
|
|
func TestVerifyOrderWithinLimits(t *testing.T) {
|
|
t.Parallel()
|
|
err := verifyOrderWithinLimits(nil, decimal.Zero, nil)
|
|
if !errors.Is(err, common.ErrNilEvent) {
|
|
t.Errorf("received %v expected %v", err, common.ErrNilEvent)
|
|
}
|
|
|
|
err = verifyOrderWithinLimits(&fill.Fill{}, decimal.Zero, nil)
|
|
if !errors.Is(err, errNilCurrencySettings) {
|
|
t.Errorf("received %v expected %v", err, errNilCurrencySettings)
|
|
}
|
|
|
|
err = verifyOrderWithinLimits(&fill.Fill{}, decimal.Zero, &Settings{})
|
|
if !errors.Is(err, errInvalidDirection) {
|
|
t.Errorf("received %v expected %v", err, errInvalidDirection)
|
|
}
|
|
f := &fill.Fill{
|
|
Direction: gctorder.Buy,
|
|
}
|
|
err = verifyOrderWithinLimits(f, decimal.Zero, &Settings{})
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received %v expected %v", err, nil)
|
|
}
|
|
s := &Settings{
|
|
BuySide: MinMax{
|
|
MinimumSize: decimal.NewFromInt(1),
|
|
MaximumSize: decimal.NewFromInt(1),
|
|
},
|
|
}
|
|
err = verifyOrderWithinLimits(f, decimal.NewFromFloat(0.5), s)
|
|
if !errors.Is(err, errExceededPortfolioLimit) {
|
|
t.Errorf("received %v expected %v", err, errExceededPortfolioLimit)
|
|
}
|
|
f.Direction = gctorder.Buy
|
|
err = verifyOrderWithinLimits(f, decimal.NewFromInt(2), s)
|
|
if !errors.Is(err, errExceededPortfolioLimit) {
|
|
t.Errorf("received %v expected %v", err, errExceededPortfolioLimit)
|
|
}
|
|
|
|
f.Direction = gctorder.Sell
|
|
s.SellSide = MinMax{
|
|
MinimumSize: decimal.NewFromInt(1),
|
|
MaximumSize: decimal.NewFromInt(1),
|
|
}
|
|
err = verifyOrderWithinLimits(f, decimal.NewFromFloat(0.5), s)
|
|
if !errors.Is(err, errExceededPortfolioLimit) {
|
|
t.Errorf("received %v expected %v", err, errExceededPortfolioLimit)
|
|
}
|
|
f.Direction = gctorder.Sell
|
|
err = verifyOrderWithinLimits(f, decimal.NewFromInt(2), s)
|
|
if !errors.Is(err, errExceededPortfolioLimit) {
|
|
t.Errorf("received %v expected %v", err, errExceededPortfolioLimit)
|
|
}
|
|
}
|