Offline worst case trade fees (#274)

* Really basic getSimulated fee function everywhere

* Worst case fees for all exchanges

* Adds tests, fixes comment spacing. Adds wrapper logic. Makes test api key var name consistent. Removes some okcoin ETT tests

* Removes redundant functions

* linting issues. Fixes introduces huobi issues

* More linting

* Stops trying to hide ETT problems, uses iota

* Skips ETT tests for now
This commit is contained in:
Scott
2019-04-09 19:38:31 +10:00
committed by Adrian Gallagher
parent eeda97bbaf
commit e56fc26d93
83 changed files with 814 additions and 136 deletions

View File

@@ -10,8 +10,8 @@ import (
const (
onlineTest = false
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -29,13 +29,13 @@ func TestSetDefaults(t *testing.T) {
}
func testSetAPIKey(a *Alphapoint) {
a.APIKey = testAPIKey
a.APISecret = testAPISecret
a.APIKey = apiKey
a.APISecret = apiSecret
a.AuthenticatedAPISupport = true
}
func testIsAPIKeysSet(a *Alphapoint) bool {
if testAPIKey != "" && testAPISecret != "" && a.AuthenticatedAPISupport {
if apiKey != "" && apiSecret != "" && a.AuthenticatedAPISupport {
return true
}
return false

View File

@@ -454,6 +454,8 @@ func (a *ANX) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getCryptocurrencyWithdrawalFee(feeBuilder.Pair.Base)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.FiatCurrency, feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -461,6 +463,11 @@ func (a *ANX) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func (a *ANX) calculateTradingFee(purchasePrice, amount float64, isMaker bool) float64 {
var fee float64

View File

@@ -11,8 +11,8 @@ import (
// Please supply your own keys here for due diligence testing
const (
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -54,8 +54,8 @@ func TestSetup(t *testing.T) {
t.Error("Test Failed - ANX Setup() init error")
}
a.Setup(&anxConfig)
a.APIKey = testAPIKey
a.APISecret = testAPISecret
a.APIKey = apiKey
a.APISecret = apiSecret
a.AuthenticatedAPISupport = true
if !a.Enabled {
@@ -138,6 +138,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
a.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
a.SetDefaults()
TestSetup(t)
@@ -341,7 +356,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
}
func TestGetAccountInfo(t *testing.T) {
if testAPIKey != "" || testAPISecret != "" {
if apiKey != "" || apiSecret != "" {
_, err := a.GetAccountInfo()
if err != nil {
t.Error("test failed - GetAccountInfo() error:", err)

View File

@@ -367,6 +367,10 @@ func (a *ANX) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (a *ANX) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (a.APIKey == "" || a.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return a.GetFee(feeBuilder)
}

View File

@@ -710,6 +710,8 @@ func (b *Binance) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, multiplier)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.Pair.Base)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -717,6 +719,11 @@ func (b *Binance) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
// getMultiplier retrieves account based taker/maker fees
func (b *Binance) getMultiplier(isMaker bool) (float64, error) {
var multiplier float64

View File

@@ -11,8 +11,8 @@ import (
// Please supply your own keys here for due diligence testing
const (
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -31,8 +31,8 @@ func TestSetup(t *testing.T) {
}
binanceConfig.AuthenticatedAPISupport = true
binanceConfig.APIKey = testAPIKey
binanceConfig.APISecret = testAPISecret
binanceConfig.APIKey = apiKey
binanceConfig.APISecret = apiSecret
b.Setup(&binanceConfig)
}
@@ -140,7 +140,7 @@ func TestGetBestPrice(t *testing.T) {
func TestNewOrder(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
_, err := b.NewOrder(&NewOrderRequest{
@@ -160,7 +160,7 @@ func TestNewOrder(t *testing.T) {
func TestCancelExistingOrder(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
@@ -173,7 +173,7 @@ func TestCancelExistingOrder(t *testing.T) {
func TestQueryOrder(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
@@ -186,7 +186,7 @@ func TestQueryOrder(t *testing.T) {
func TestOpenOrders(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
@@ -199,7 +199,7 @@ func TestOpenOrders(t *testing.T) {
func TestAllOrders(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
@@ -210,7 +210,7 @@ func TestAllOrders(t *testing.T) {
}
func TestGetAccount(t *testing.T) {
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
t.Parallel()
@@ -240,13 +240,28 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if testAPIKey != "" || testAPISecret != "" {
if apiKey != "" || apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.1) || err != nil {
t.Error(err)
@@ -455,7 +470,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
func TestGetAccountInfo(t *testing.T) {
b.SetDefaults()
TestSetup(t)
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}

View File

@@ -324,6 +324,10 @@ func (b *Binance) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Binance) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -1086,6 +1086,8 @@ func (b *Bitfinex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getInternationalBankDepositFee(feeBuilder.Amount)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -1093,6 +1095,12 @@ func (b *Bitfinex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
// does not require an API request, requires manual updating
func getOfflineTradeFee(price, amount float64) float64 {
return 0.001 * price * amount
}
// GetCryptocurrencyWithdrawalFee returns an estimate of fee based on type of transaction
func (b *Bitfinex) GetCryptocurrencyWithdrawalFee(c currency.Code, accountFees AccountFees) (fee float64, err error) {
switch result := accountFees.Withdraw[c.String()].(type) {

View File

@@ -14,8 +14,8 @@ import (
// Please supply your own keys here to do better tests
const (
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -30,8 +30,8 @@ func TestSetup(t *testing.T) {
t.Error("Test Failed - Bitfinex Setup() init error")
}
b.Setup(&bfxConfig)
b.APIKey = testAPIKey
b.APISecret = testAPISecret
b.APIKey = apiKey
b.APISecret = apiSecret
if !b.Enabled || b.AuthenticatedAPISupport || b.RESTPollingDelay != time.Duration(10) ||
b.Verbose || b.Websocket.IsEnabled() || len(b.BaseCurrencies) < 1 ||
len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 {
@@ -619,12 +619,27 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if testAPIKey != "" || testAPISecret != "" {
if apiKey != "" || apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)

View File

@@ -329,6 +329,10 @@ func (b *Bitfinex) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitfinex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -403,6 +403,8 @@ func (b *Bitflyer) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getDepositFee(feeBuilder.BankTransactionType, feeBuilder.FiatCurrency)
case exchange.InternationalBankWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.BankTransactionType, feeBuilder.FiatCurrency, feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -411,10 +413,9 @@ func (b *Bitflyer) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
}
// calculateTradingFee returns fee when performing a trade
func calculateTradingFee(purchasePrice, amount float64) float64 {
fee := 0.0015
func calculateTradingFee(price, amount float64) float64 {
// bitflyer has fee tiers, but does not disclose them via API, so the largest has to be assumed
return fee * amount * purchasePrice
return 0.0012 * price * amount
}
func getDepositFee(bankTransactionType exchange.InternationalBankTransactionType, c currency.Code) (fee float64) {

View File

@@ -12,8 +12,8 @@ import (
// Please supply your own keys here for due diligence testing
const (
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -32,8 +32,8 @@ func TestSetup(t *testing.T) {
}
bitflyerConfig.AuthenticatedAPISupport = true
bitflyerConfig.APIKey = testAPIKey
bitflyerConfig.APISecret = testAPISecret
bitflyerConfig.APIKey = apiKey
bitflyerConfig.APISecret = apiSecret
b.Setup(&bitflyerConfig)
}
@@ -159,12 +159,27 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if testAPIKey != "" || testAPISecret != "" {
if apiKey != "" || apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Error(err)

View File

@@ -236,5 +236,9 @@ func (b *Bitflyer) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest)
// GetFeeByType returns an estimate of fee based on the type of transaction
func (b *Bitflyer) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -619,6 +619,8 @@ func (b *Bithumb) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getWithdrawalFee(feeBuilder.Pair.Base)
case exchange.InternationalBankWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FiatCurrency)
case exchange.OfflineTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -628,8 +630,7 @@ func (b *Bithumb) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
// calculateTradingFee returns fee when performing a trade
func calculateTradingFee(purchasePrice, amount float64) float64 {
fee := 0.0015
return fee * amount * purchasePrice
return 0.0025 * amount * purchasePrice
}
// getDepositFee returns fee on a currency when depositing small amounts to bithumb

View File

@@ -11,8 +11,8 @@ import (
// Please supply your own keys here for due diligence testing
const (
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -31,8 +31,8 @@ func TestSetup(t *testing.T) {
}
bitConfig.AuthenticatedAPISupport = true
bitConfig.APIKey = testAPIKey
bitConfig.APISecret = testAPISecret
bitConfig.APIKey = apiKey
bitConfig.APISecret = apiSecret
b.Setup(&bitConfig)
}
@@ -79,7 +79,7 @@ func TestGetTransactionHistory(t *testing.T) {
func TestGetAccountBalance(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
@@ -90,7 +90,7 @@ func TestGetAccountBalance(t *testing.T) {
}
func TestGetWalletAddress(t *testing.T) {
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
@@ -159,7 +159,7 @@ func TestWithdrawCrypto(t *testing.T) {
func TestRequestKRWDepositDetails(t *testing.T) {
t.Parallel()
if testAPIKey == "" || testAPISecret == "" {
if apiKey == "" || apiSecret == "" {
t.Skip()
}
_, err := b.RequestKRWDepositDetails()
@@ -201,31 +201,46 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0015), resp)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0025), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(1500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(1500), resp)
if resp, err := b.GetFee(feeBuilder); resp != float64(2500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(2500), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0015), resp)
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0025), resp)
t.Error(err)
}
@@ -406,7 +421,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
func TestGetAccountInfo(t *testing.T) {
t.Parallel()
if testAPIKey != "" || testAPISecret != "" {
if apiKey != "" || apiSecret != "" {
_, err := b.GetAccountInfo()
if err != nil {
t.Error("test failed - Bithumb GetAccountInfo() error", err)
@@ -505,7 +520,7 @@ func TestWithdrawInternationalBank(t *testing.T) {
}
func TestGetDepositAddress(t *testing.T) {
if testAPIKey != "" && testAPISecret != "" {
if apiKey != "" && apiSecret != "" {
_, err := b.GetDepositAddress(currency.BTC, "")
if err != nil {
t.Error("Test Failed - GetDepositAddress() error", err)

View File

@@ -326,6 +326,10 @@ func (b *Bithumb) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bithumb) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -938,9 +938,11 @@ func (b *Bitmex) CaptureError(resp, reType interface{}) error {
func (b *Bitmex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
var fee float64
var err error
if feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -948,10 +950,14 @@ func (b *Bitmex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, err
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.000750 * price * amount
}
// calculateTradingFee returns the fee for trading any currency on Bittrex
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) float64 {
var fee = 0.000750
if isMaker {
fee -= 0.000250
}

View File

@@ -13,8 +13,8 @@ import (
// Please supply your own keys here for due diligence testing
const (
testAPIKey = ""
testAPISecret = ""
apiKey = ""
apiSecret = ""
canManipulateRealOrders = false
)
@@ -32,8 +32,8 @@ func TestSetup(t *testing.T) {
t.Error("Test Failed - Bitmex Setup() init error")
}
bitmexConfig.AuthenticatedAPISupport = true
bitmexConfig.APIKey = testAPIKey
bitmexConfig.APISecret = testAPISecret
bitmexConfig.APIKey = apiKey
bitmexConfig.APISecret = apiSecret
b.Setup(&bitmexConfig)
}
@@ -369,12 +369,26 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00075) || err != nil {
t.Error(err)
@@ -576,7 +590,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
}
func TestGetAccountInfo(t *testing.T) {
if testAPIKey != "" || testAPISecret != "" {
if apiKey != "" || apiSecret != "" {
_, err := b.GetAccountInfo()
if err != nil {
t.Error("Test Failed - GetAccountInfo() error", err)

View File

@@ -305,6 +305,10 @@ func (b *Bitmex) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitmex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -164,6 +164,8 @@ func (b *Bitstamp) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getInternationalBankDepositFee(feeBuilder.Amount)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -171,6 +173,11 @@ func (b *Bitstamp) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0025 * price * amount
}
// getInternationalBankWithdrawalFee returns international withdrawal fee
func getInternationalBankWithdrawalFee(amount float64) float64 {
fee := amount * 0.0009

View File

@@ -70,6 +70,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)

View File

@@ -94,6 +94,10 @@ func (b *Bitstamp) GetTickerPrice(p currency.Pair, assetType string) (ticker.Pri
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitstamp) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -530,6 +530,8 @@ func (b *Bittrex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee, err = b.GetWithdrawalFee(feeBuilder.Pair.Base)
case exchange.OfflineTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -554,7 +556,7 @@ func (b *Bittrex) GetWithdrawalFee(c currency.Code) (float64, error) {
}
// calculateTradingFee returns the fee for trading any currency on Bittrex
func calculateTradingFee(purchasePrice, amount float64) float64 {
var fee = 0.0025
return fee * purchasePrice * amount
func calculateTradingFee(price, amount float64) float64 {
return 0.0025 * price * amount
}

View File

@@ -228,6 +228,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)

View File

@@ -300,6 +300,10 @@ func (b *Bittrex) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bittrex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -104,6 +104,8 @@ func (b *BTCC) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getCryptocurrencyWithdrawalFee(feeBuilder.Pair.Base)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.FiatCurrency, feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -111,6 +113,11 @@ func (b *BTCC) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.001 * price * amount
}
func getCryptocurrencyWithdrawalFee(c currency.Code) float64 {
return WithdrawalFees[c]
}

View File

@@ -84,6 +84,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)

View File

@@ -158,6 +158,10 @@ func (b *BTCC) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *BTCC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -506,6 +506,8 @@ func (b *BTCMarkets) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getCryptocurrencyWithdrawalFee(feeBuilder.Pair.Base)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.FiatCurrency)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -513,6 +515,11 @@ func (b *BTCMarkets) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0085 * price * amount
}
func calculateTradingFee(tradingFee TradingFee, purchasePrice, amount float64) (fee float64) {
fee = tradingFee.TradingFeeRate / 100000000
return fee * amount * purchasePrice

View File

@@ -174,6 +174,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)

View File

@@ -332,6 +332,10 @@ func (b *BTCMarkets) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *BTCMarkets) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -298,10 +298,17 @@ func (b *BTSE) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getInternationalBankDepositFee(feeBuilder.Amount)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0015 * price * amount
}
// getInternationalBankDepositFee returns international deposit fee
// Only when the initial deposit amount is less than $1000 or equivalent,
// BTSE will charge a small fee (0.25% or $3 USD equivalent, whichever is greater).

View File

@@ -140,6 +140,27 @@ func TestFormatWithdrawPermissions(t *testing.T) {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
feeBuilder := &exchange.FeeBuilder{
FeeType: exchange.CryptocurrencyTradeFee,
Pair: currency.NewPair(currency.BTC, currency.USD),
IsMaker: true,
Amount: 1000,
}
b.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)

View File

@@ -348,5 +348,9 @@ func (b *BTSE) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([]e
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *BTSE) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (b.APIKey == "" || b.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
}

View File

@@ -854,6 +854,8 @@ func (c *CoinbasePro) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getInternationalBankWithdrawalFee(feeBuilder.FiatCurrency)
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.FiatCurrency)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
@@ -863,6 +865,11 @@ func (c *CoinbasePro) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0025 * price * amount
}
func (c *CoinbasePro) calculateTradingFee(trailingVolume []Volume, base, quote currency.Code, delimiter string, purchasePrice, amount float64, isMaker bool) float64 {
var fee float64
for _, i := range trailingVolume {

View File

@@ -230,6 +230,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
c.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
c.SetDefaults()
TestSetup(t)

View File

@@ -288,6 +288,10 @@ func (c *CoinbasePro) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (c *CoinbasePro) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (c.APIKey == "" || c.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return c.GetFee(feeBuilder)
}

View File

@@ -409,6 +409,8 @@ func (c *COINUT) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.FiatCurrency,
feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.Pair, feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
@@ -418,6 +420,14 @@ func (c *COINUT) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(c currency.Pair, price, amount float64) float64 {
if c.IsCryptoFiatPair() {
return 0.0035 * price * amount
}
return 0.002 * price * amount
}
func (c *COINUT) calculateTradingFee(base, quote currency.Code, purchasePrice, amount float64, isMaker bool) float64 {
var fee float64

View File

@@ -59,6 +59,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
c.GetFeeByType(feeBuilder)
if apiKey == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
c.SetDefaults()
TestSetup(t)

View File

@@ -383,6 +383,10 @@ func (c *COINUT) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (c *COINUT) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if c.APIKey == "" && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return c.GetFee(feeBuilder)
}

View File

@@ -31,41 +31,42 @@ const (
)
// FeeType custom type for calculating fees based on method
type FeeType string
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types
type InternationalBankTransactionType string
type FeeType uint8
// Const declarations for fee types
const (
BankFee FeeType = "bankFee"
InternationalBankDepositFee FeeType = "internationalBankDepositFee"
InternationalBankWithdrawalFee FeeType = "internationalBankWithdrawalFee"
CryptocurrencyTradeFee FeeType = "cryptocurrencyTradeFee"
CyptocurrencyDepositFee FeeType = "cyptocurrencyDepositFee"
CryptocurrencyWithdrawalFee FeeType = "cryptocurrencyWithdrawalFee"
BankFee FeeType = iota
InternationalBankDepositFee
InternationalBankWithdrawalFee
CryptocurrencyTradeFee
CyptocurrencyDepositFee
CryptocurrencyWithdrawalFee
OfflineTradeFee
)
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types
type InternationalBankTransactionType uint8
// Const declarations for international transaction types
const (
WireTransfer InternationalBankTransactionType = "wireTransfer"
PerfectMoney InternationalBankTransactionType = "perfectMoney"
Neteller InternationalBankTransactionType = "neteller"
AdvCash InternationalBankTransactionType = "advCash"
Payeer InternationalBankTransactionType = "payeer"
Skrill InternationalBankTransactionType = "skrill"
Simplex InternationalBankTransactionType = "simplex"
SEPA InternationalBankTransactionType = "sepa"
Swift InternationalBankTransactionType = "swift"
RapidTransfer InternationalBankTransactionType = "rapidTransfer"
MisterTangoSEPA InternationalBankTransactionType = "misterTangoSepa"
Qiwi InternationalBankTransactionType = "qiwi"
VisaMastercard InternationalBankTransactionType = "visaMastercard"
WebMoney InternationalBankTransactionType = "webMoney"
Capitalist InternationalBankTransactionType = "capitalist"
WesternUnion InternationalBankTransactionType = "westernUnion"
MoneyGram InternationalBankTransactionType = "moneyGram"
Contact InternationalBankTransactionType = "contact"
WireTransfer InternationalBankTransactionType = iota
PerfectMoney
Neteller
AdvCash
Payeer
Skrill
Simplex
SEPA
Swift
RapidTransfer
MisterTangoSEPA
Qiwi
VisaMastercard
WebMoney
Capitalist
WesternUnion
MoneyGram
Contact
)
// SubmitOrderResponse is what is returned after submitting an order to an
@@ -78,25 +79,22 @@ type SubmitOrderResponse struct {
// FeeBuilder is the type which holds all parameters required to calculate a fee
// for an exchange
type FeeBuilder struct {
FeeType FeeType
// Used for calculating crypto trading fees, deposits & withdrawals
Pair currency.Pair
IsMaker bool
// Fiat currency used for bank deposits & withdrawals
IsMaker bool
PurchasePrice float64
Amount float64
FeeType FeeType
FiatCurrency currency.Code
BankTransactionType InternationalBankTransactionType
// Used to multiply for fee calculations
PurchasePrice float64
Amount float64
Pair currency.Pair
}
// OrderCancellation type required when requesting to cancel an order
type OrderCancellation struct {
AccountID string
OrderID string
CurrencyPair currency.Pair
WalletAddress string
Side OrderSide
CurrencyPair currency.Pair
}
// WithdrawRequest used for wrapper crypto and FIAT withdraw methods

View File

@@ -421,7 +421,7 @@ func (e *EXMO) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = e.calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.Pair.Base)
case exchange.InternationalBankWithdrawalFee:
@@ -432,6 +432,8 @@ func (e *EXMO) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getInternationalBankDepositFee(feeBuilder.FiatCurrency,
feeBuilder.Amount,
feeBuilder.BankTransactionType)
case exchange.OfflineTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
@@ -445,14 +447,8 @@ func getCryptocurrencyWithdrawalFee(c currency.Code) float64 {
return WithdrawalFees[c]
}
func (e *EXMO) calculateTradingFee(purchasePrice, amount float64) float64 {
fee := 0.002
return fee * amount * purchasePrice
}
func calculateTradingFee(purchasePrice, amount float64) float64 {
fee := 0.002
return fee * amount * purchasePrice
func calculateTradingFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func getInternationalBankWithdrawalFee(c currency.Code, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {

View File

@@ -116,6 +116,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
e.GetFeeByType(feeBuilder)
if APIKey == "" || APISecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
e.SetDefaults()
TestSetup(t)

View File

@@ -316,6 +316,10 @@ func (e *EXMO) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (e *EXMO) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (e.APIKey == "" || e.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return e.GetFee(feeBuilder)
}

View File

@@ -538,6 +538,8 @@ func (g *Gateio) GetFee(feeBuilder *exchange.FeeBuilder) (fee float64, err error
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.Pair.Base)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
@@ -547,6 +549,11 @@ func (g *Gateio) GetFee(feeBuilder *exchange.FeeBuilder) (fee float64, err error
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func calculateTradingFee(feeForPair, purchasePrice, amount float64) float64 {
return (feeForPair / 100) * purchasePrice * amount
}

View File

@@ -156,6 +156,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
g.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
g.SetDefaults()
TestSetup(t)

View File

@@ -332,6 +332,10 @@ func (g *Gateio) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (g *Gateio) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (g.APIKey == "" || g.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return g.GetFee(feeBuilder)
}

View File

@@ -546,6 +546,8 @@ func (g *Gemini) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
// Could do via trade history, but would require analysis of response and dates to determine level of fee
case exchange.InternationalBankWithdrawalFee:
fee = 0
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -554,6 +556,11 @@ func (g *Gemini) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.01 * price * amount
}
func calculateTradingFee(notionVolume *NotionalVolume, purchasePrice, amount float64, isMaker bool) float64 {
var volumeFee float64
if isMaker {

View File

@@ -247,6 +247,24 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
TestAddSession(t)
TestSetDefaults(t)
TestSetup(t)
var feeBuilder = setFeeBuilder()
Session[1].GetFeeByType(feeBuilder)
if apiKey1 == "" || apiSecret1 == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
if apiKey1 != "" && apiSecret1 != "" {
@@ -342,7 +360,6 @@ func TestGetActiveOrders(t *testing.T) {
TestAddSession(t)
TestSetDefaults(t)
TestSetup(t)
Session[1].Verbose = true
var getOrdersRequest = exchange.GetOrdersRequest{
OrderType: exchange.AnyOrderType,
@@ -361,7 +378,6 @@ func TestGetOrderHistory(t *testing.T) {
TestAddSession(t)
TestSetDefaults(t)
TestSetup(t)
Session[1].Verbose = true
var getOrdersRequest = exchange.GetOrdersRequest{
OrderType: exchange.AnyOrderType,

View File

@@ -259,6 +259,10 @@ func (g *Gemini) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (g *Gemini) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (g.APIKey == "" || g.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return g.GetFee(feeBuilder)
}

View File

@@ -641,11 +641,21 @@ func (h *HitBTC) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
case exchange.CyptocurrencyDepositFee:
fee = calculateCryptocurrencyDepositFee(feeBuilder.Pair.Base,
feeBuilder.Amount)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func calculateCryptocurrencyDepositFee(c currency.Code, amount float64) float64 {
var fee float64
if c == currency.BTC {

View File

@@ -75,6 +75,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
h.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
h.SetDefaults()
TestSetup(t)

View File

@@ -286,6 +286,10 @@ func (h *HitBTC) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HitBTC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (h.APIKey == "" || h.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return h.GetFee(feeBuilder)
}

View File

@@ -914,8 +914,8 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
// GetFee returns an estimate of fee based on type of transaction
func (h *HUOBI) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
var fee float64
if feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
if feeBuilder.FeeType == exchange.OfflineTradeFee || feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
fee = calculateTradingFee(feeBuilder.Pair, feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -924,7 +924,9 @@ func (h *HUOBI) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64) float64 {
feePercent := 0.002
return feePercent * purchasePrice * amount
func calculateTradingFee(c currency.Pair, price, amount float64) float64 {
if c.IsCryptoFiatPair() {
return 0.001 * price * amount
}
return 0.002 * price * amount
}

View File

@@ -305,6 +305,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
h.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()

View File

@@ -393,6 +393,10 @@ func (h *HUOBI) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HUOBI) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (h.APIKey == "" || h.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return h.GetFee(feeBuilder)
}

View File

@@ -885,8 +885,8 @@ func (h *HUOBIHADAX) SendAuthenticatedHTTPRequest(method, endpoint string, value
// GetFee returns an estimate of fee based on type of transaction
func (h *HUOBIHADAX) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
var fee float64
if feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
if feeBuilder.FeeType == exchange.OfflineTradeFee || feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
fee = calculateTradingFee(feeBuilder.Pair, feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -895,9 +895,11 @@ func (h *HUOBIHADAX) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64) float64 {
feePercent := 0.002
return feePercent * purchasePrice * amount
func calculateTradingFee(c currency.Pair, price, amount float64) float64 {
if c.IsCryptoFiatPair() {
return 0.001 * price * amount
}
return 0.002 * price * amount
}
// GetDepositWithdrawalHistory returns deposit or withdrawal data

View File

@@ -285,6 +285,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
h.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()

View File

@@ -349,6 +349,10 @@ func (h *HUOBIHADAX) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HUOBIHADAX) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (h.APIKey == "" || h.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return h.GetFee(feeBuilder)
}

View File

@@ -428,6 +428,8 @@ func (i *ItBit) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.FiatCurrency, feeBuilder.BankTransactionType)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
@@ -437,12 +439,17 @@ func (i *ItBit) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0035 * price * amount
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) float64 {
// TODO: Itbit has volume discounts, but not API endpoint to get the exact volume numbers
// When support is added, this needs to be updated to calculate the accurate volume fee
feePercent := 0.0025
feePercent := 0.0035
if isMaker {
feePercent = 0
feePercent = -0.0003
}
return feePercent * purchasePrice * amount
}

View File

@@ -154,21 +154,36 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
i.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := i.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
if resp, err := i.GetFee(feeBuilder); resp != float64(0.0035) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.002), resp)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0035), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := i.GetFee(feeBuilder); resp != float64(2500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(2500), resp)
if resp, err := i.GetFee(feeBuilder); resp != float64(3500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(3500), resp)
t.Error(err)
}

View File

@@ -301,6 +301,10 @@ func (i *ItBit) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (i *ItBit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (i.APIKey == "" || i.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return i.GetFee(feeBuilder)
}

View File

@@ -1020,6 +1020,8 @@ func (k *Kraken) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
case exchange.InternationalBankWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FiatCurrency)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -1028,6 +1030,11 @@ func (k *Kraken) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0016 * price * amount
}
func getWithdrawalFee(c currency.Code) float64 {
return WithdrawalFees[c]
}

View File

@@ -256,6 +256,22 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
// TestGetFee logic test
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
k.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
k.SetDefaults()
TestSetup(t)

View File

@@ -312,6 +312,10 @@ func (k *Kraken) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (k *Kraken) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (k.APIKey == "" || k.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return k.GetFee(feeBuilder)
}

View File

@@ -388,6 +388,8 @@ func (l *LakeBTC) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
// fees for withdrawals are dynamic. They cannot be calculated in
// advance as they are manually performed via the website, it can only
// be determined when submitting the request
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
@@ -397,6 +399,11 @@ func (l *LakeBTC) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
if isMaker {
// TODO: Volume based fee calculation

View File

@@ -148,6 +148,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
l.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()

View File

@@ -276,6 +276,10 @@ func (l *LakeBTC) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *LakeBTC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (l.APIKey == "" || l.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return l.GetFee(feeBuilder)
}

View File

@@ -108,6 +108,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
l.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
l.SetDefaults()
var feeBuilder = setFeeBuilder()

View File

@@ -303,6 +303,10 @@ func (l *LocalBitcoins) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *LocalBitcoins) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (l.APIKey == "" || l.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return l.GetFee(feeBuilder)
}

View File

@@ -1040,6 +1040,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
o.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
TestSetDefaults(t)
var feeBuilder = setFeeBuilder()
@@ -1059,7 +1074,7 @@ func TestGetFee(t *testing.T) {
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := o.GetFee(feeBuilder); resp != float64(0.00100) || err != nil {
if resp, err := o.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0005), resp)
t.Error(err)
}

View File

@@ -1553,6 +1553,7 @@ func TestGetETTOrderDetails(t *testing.T) {
// TestGetETTConstituents API endpoint test
func TestGetETTConstituents(t *testing.T) {
t.Skip("ETT currently unavailable")
TestSetDefaults(t)
t.Parallel()
_, err := o.GetETTConstituents("OK06ETT")
@@ -1563,6 +1564,7 @@ func TestGetETTConstituents(t *testing.T) {
// TestGetETTSettlementPriceHistory API endpoint test
func TestGetETTSettlementPriceHistory(t *testing.T) {
t.Skip("ETT currently unavailable")
TestSetDefaults(t)
t.Parallel()
_, err := o.GetETTSettlementPriceHistory("OK06ETT")
@@ -1810,7 +1812,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFee fee calcuation test
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
o.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
TestSetDefaults(t)
t.Parallel()
@@ -1833,8 +1849,8 @@ func TestGetFee(t *testing.T) {
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := o.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.001), resp)
if resp, err := o.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0005), resp)
t.Error(err)
}

View File

@@ -680,6 +680,8 @@ func (o *OKGroup) GetFee(feeBuilder *exchange.FeeBuilder) (fee float64, _ error)
break
}
}
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -688,10 +690,15 @@ func (o *OKGroup) GetFee(feeBuilder *exchange.FeeBuilder) (fee float64, _ error)
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.0015 * price * amount
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
// TODO volume based fees
if isMaker {
fee = 0.001
fee = 0.0005
} else {
fee = 0.0015
}

View File

@@ -414,6 +414,10 @@ func (o *OKGroup) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (o *OKGroup) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (o.APIKey == "" || o.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return o.GetFee(feeBuilder)
}

View File

@@ -914,6 +914,8 @@ func (p *Poloniex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.Pair.Base)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -922,6 +924,11 @@ func (p *Poloniex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func calculateTradingFee(feeInfo Fee, purchasePrice, amount float64, isMaker bool) (fee float64) {
if isMaker {
fee = feeInfo.MakerFee

View File

@@ -99,6 +99,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
p.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
p.SetDefaults()
TestSetup(t)

View File

@@ -310,6 +310,10 @@ func (p *Poloniex) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (p *Poloniex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (p.APIKey == "" || p.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return p.GetFee(feeBuilder)
}

View File

@@ -399,6 +399,8 @@ func (y *Yobit) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = getInternationalBankWithdrawalFee(feeBuilder.FiatCurrency,
feeBuilder.Amount,
feeBuilder.BankTransactionType)
case exchange.OfflineTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -407,9 +409,8 @@ func (y *Yobit) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64) (fee float64) {
fee = 0.002
return fee * amount * purchasePrice
func calculateTradingFee(price, amount float64) (fee float64) {
return 0.002 * price * amount
}
func getWithdrawalFee(c currency.Code) float64 {

View File

@@ -147,6 +147,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
y.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
y.SetDefaults()
TestSetup(t)

View File

@@ -280,6 +280,10 @@ func (y *Yobit) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (y *Yobit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (y.APIKey == "" || y.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return y.GetFee(feeBuilder)
}

View File

@@ -422,6 +422,8 @@ func (z *ZB) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.Pair.Base)
case exchange.OfflineTradeFee:
fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
@@ -430,6 +432,11 @@ func (z *ZB) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, nil
}
// getOfflineTradeFee calculates the worst case-scenario trading fee
func getOfflineTradeFee(price, amount float64) float64 {
return 0.002 * price * amount
}
func calculateTradingFee(purchasePrice, amount float64) (fee float64) {
fee = 0.002
return fee * amount * purchasePrice

View File

@@ -138,6 +138,21 @@ func setFeeBuilder() *exchange.FeeBuilder {
}
}
// TestGetFeeByTypeOfflineTradeFee logic test
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
z.GetFeeByType(feeBuilder)
if apiKey == "" || apiSecret == "" {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
} else {
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
}
}
}
func TestGetFee(t *testing.T) {
z.SetDefaults()
TestSetup(t)

View File

@@ -307,6 +307,10 @@ func (z *ZB) GetWebsocket() (*exchange.Websocket, error) {
// GetFeeByType returns an estimate of fee based on type of transaction
func (z *ZB) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (z.APIKey == "" || z.APISecret == "") && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return z.GetFee(feeBuilder)
}