mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-31 15:10:42 +00:00
Backtester: Live trading upgrades (#1023)
* Modifications for a smoother live run * Fixes data appending * Successfully allows multi-currency live trading. Adds multiple currencies to live DCA strategy * Attempting to get cash and carry working * Poor attempts at sorting out data and appending it properly with USD in mind * =designs new live data handler * Updates cash and carry strat to work * adds test coverage. begins closeallpositions function * Updates cash and carry to work live * New kline.Event type. Cancels orders on close. Rn types * =Fixes USD funding issue * =fixes tests * fixes tests AGAIN * adds coverage to close all orders * crummy tests, should override * more tests * more tests * more coverage * removes scourge of currency.Pair maps. More tests * missed currency stuff * Fixes USD data issue & collateral issue. Needs to close ALL orders * Now triggers updates on the very first data entry * All my problems are solved now???? * fixes tests, extends coverage * there is some really funky candle stuff going on * my brain is melting * better shutdown management, fixes freezing bug * fixes data duplication issues, adds retries to requests * reduces logging, adds verbose options * expands coverage over all new functionality * fixes fun bug from curr == curr to curr.Equal(curr) * fixes setup issues and tests * starts adding external wallet amounts for funding * more setup for assets * setup live fund calcs and placing orders * successfully performs automated cash and carry * merge fixes * funding properly set at all times * fixes some bugs, need to address currencystatistics still * adds 'appeneded' trait, attempts to fix some stats * fixes stat bugs, adds cool new fetchfees feature * fixes terrible processing bugs * tightens realorder stats, sadly loses some live stats * this actually sets everything correctly for bothcd ..cd ..cd ..cd ..cd ..! * fix tests * coverage * beautiful new test coverage * docs * adds new fee getter delayer * commits from the correct directory * Lint * adds verbose to fund manager * Fix bug in t2b2 strat. Update dca live config. Docs * go mod tidy * update buf * buf + test improvement * Post merge fixes * fixes surprise offset bug * fix sizing restrictions for cash and carry * fix server lints * merge fixes * test fixesss * lintle fixles * slowloris * rn run to task, bug fixes, close all on close * rpc lint and fixes * bugfix: order manager not processing orders properly * somewhat addresses nits * absolutely broken end of day commit * absolutely massive knockon effects from nits * massive knockon effects continue * fixes things * address remaining nits * jk now fixes things * addresses the easier nits * more nit fixers * more niterinos addressederinos * refactors holdings and does some nits * so buf * addresses some nits, fixes holdings bugs * cleanup * attempts to fix alert chans to prevent many chans waiting? * terrible code, will revert * to be reviewed in detail tomorrow * Fixes up channel system * smashes those nits * fixes extra candles, fixes collateral bug, tests * fixes data races, introduces reflection * more checks n tests * Fixes cash and carry issues. Fixes more cool bugs * fixes ~typer~ typo * replace spot strats from ftx to binance * fixes all the tests I just destroyed * removes example path, rm verbose * 1) what 2) removes FTX references from the Backtester * renamed, non-working strategies * Removes FTX references almost as fast as sbf removes funds * regen docs, add contrib names,sort contrib names * fixes merge renamings * Addresses nits. Fixes setting API credentials. Fixes Binance limit retrieval * Fixes live order bugs with real orders and without * Apply suggestions from code review Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update backtester/engine/live.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update backtester/engine/live.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update backtester/config/strategyconfigbuilder/main.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * updates docs * even better docs Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
@@ -115,7 +115,7 @@ func GetHoldings(exch string, creds *Credentials, assetType asset.Item) (Holding
|
||||
for item, balance := range currencyHoldings {
|
||||
balance.m.Lock()
|
||||
currencyBalances[target] = Balance{
|
||||
CurrencyName: currency.Code{Item: item, UpperCase: true},
|
||||
Currency: currency.Code{Item: item, UpperCase: true},
|
||||
Total: balance.total,
|
||||
Hold: balance.hold,
|
||||
Free: balance.free,
|
||||
@@ -281,10 +281,10 @@ func (s *Service) Update(incoming *Holdings, creds *Credentials) error {
|
||||
}
|
||||
|
||||
for y := range incoming.Accounts[x].Currencies {
|
||||
bal := currencyBalances[incoming.Accounts[x].Currencies[y].CurrencyName.Item]
|
||||
bal := currencyBalances[incoming.Accounts[x].Currencies[y].Currency.Item]
|
||||
if bal == nil {
|
||||
bal = &ProtectedBalance{}
|
||||
currencyBalances[incoming.Accounts[x].Currencies[y].CurrencyName.Item] = bal
|
||||
currencyBalances[incoming.Accounts[x].Currencies[y].Currency.Item] = bal
|
||||
}
|
||||
bal.load(incoming.Accounts[x].Currencies[y])
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestCollectBalances(t *testing.T) {
|
||||
accounts, err := CollectBalances(
|
||||
map[string][]Balance{
|
||||
"someAccountID": {
|
||||
{CurrencyName: currency.BTC, Total: 40000, Hold: 1},
|
||||
{Currency: currency.BTC, Total: 40000, Hold: 1},
|
||||
},
|
||||
},
|
||||
asset.Spot,
|
||||
@@ -31,7 +31,7 @@ func TestCollectBalances(t *testing.T) {
|
||||
if subAccount.AssetType != asset.Spot {
|
||||
t.Error("subAccount AssetType not set correctly")
|
||||
}
|
||||
if balance.CurrencyName != currency.BTC || balance.Total != 40000 || balance.Hold != 1 {
|
||||
if balance.Currency != currency.BTC || balance.Total != 40000 || balance.Hold != 1 {
|
||||
t.Error("subAccount currency balance not set correctly")
|
||||
}
|
||||
if err != nil {
|
||||
@@ -112,9 +112,9 @@ func TestGetHoldings(t *testing.T) {
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
Currency: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -132,9 +132,9 @@ func TestGetHoldings(t *testing.T) {
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
Currency: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -182,9 +182,9 @@ func TestGetHoldings(t *testing.T) {
|
||||
t.Errorf("expecting 1337 but received %s", u.Accounts[0].ID)
|
||||
}
|
||||
|
||||
if !u.Accounts[0].Currencies[0].CurrencyName.Equal(currency.BTC) {
|
||||
if !u.Accounts[0].Currencies[0].Currency.Equal(currency.BTC) {
|
||||
t.Errorf("expecting BTC but received %s",
|
||||
u.Accounts[0].Currencies[0].CurrencyName)
|
||||
u.Accounts[0].Currencies[0].Currency)
|
||||
}
|
||||
|
||||
if u.Accounts[0].Currencies[0].Total != 100 {
|
||||
@@ -228,9 +228,9 @@ func TestGetHoldings(t *testing.T) {
|
||||
AssetType: asset.MarginFunding,
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 100000,
|
||||
Hold: 20,
|
||||
Currency: currency.BTC,
|
||||
Total: 100000,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -309,9 +309,9 @@ func TestGetBalance(t *testing.T) {
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 2,
|
||||
Hold: 1,
|
||||
Currency: currency.BTC,
|
||||
Total: 2,
|
||||
Hold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -424,9 +424,9 @@ func TestUpdate(t *testing.T) {
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
Currency: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -436,9 +436,9 @@ func TestUpdate(t *testing.T) {
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
Currency: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -456,9 +456,9 @@ func TestUpdate(t *testing.T) {
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
Currency: currency.BTC,
|
||||
Total: 100,
|
||||
Hold: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -50,9 +50,9 @@ type SubAccount struct {
|
||||
Currencies []Balance
|
||||
}
|
||||
|
||||
// Balance is a sub type to store currency name and individual totals
|
||||
// Balance is a sub-type to store currency name and individual totals
|
||||
type Balance struct {
|
||||
CurrencyName currency.Code
|
||||
Currency currency.Code
|
||||
Total float64
|
||||
Hold float64
|
||||
Free float64
|
||||
|
||||
@@ -118,7 +118,7 @@ func (c *Credentials) Equal(other *Credentials) bool {
|
||||
other != nil &&
|
||||
c.Key == other.Key &&
|
||||
c.ClientID == other.ClientID &&
|
||||
c.SubAccount == other.SubAccount
|
||||
(c.SubAccount == other.SubAccount || c.SubAccount == "" && other.SubAccount == "main" || c.SubAccount == "main" && other.SubAccount == "")
|
||||
}
|
||||
|
||||
// ContextCredentialsStore protects the stored credentials for use in a context
|
||||
|
||||
@@ -104,10 +104,10 @@ func (a *Alphapoint) UpdateAccountInfo(ctx context.Context, assetType asset.Item
|
||||
balances := make([]account.Balance, len(acc.Currencies))
|
||||
for i := range acc.Currencies {
|
||||
balances[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(acc.Currencies[i].Name),
|
||||
Total: float64(acc.Currencies[i].Balance),
|
||||
Hold: float64(acc.Currencies[i].Hold),
|
||||
Free: float64(acc.Currencies[i].Balance) - float64(acc.Currencies[i].Hold),
|
||||
Currency: currency.NewCode(acc.Currencies[i].Name),
|
||||
Total: float64(acc.Currencies[i].Balance),
|
||||
Hold: float64(acc.Currencies[i].Hold),
|
||||
Free: float64(acc.Currencies[i].Balance) - float64(acc.Currencies[i].Hold),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1189,10 +1189,9 @@ func (b *Binance) FetchSpotExchangeLimits(ctx context.Context) ([]order.MinMaxLe
|
||||
assets = append(assets, asset.Spot)
|
||||
case "MARGIN":
|
||||
assets = append(assets, asset.Margin)
|
||||
case "LEVERAGED", "TRD_GRP_003", "TRD_GRP_004", "TRD_GRP_005": // unused permissions
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled asset type for exchange limits loading %s",
|
||||
spot.Symbols[x].Permissions[y])
|
||||
// "LEVERAGED", "TRD_GRP_003", "TRD_GRP_004", "TRD_GRP_005" etc are unused permissions
|
||||
// for spot exchange limits
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -706,10 +706,10 @@ func (b *Binance) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
locked := raw.Balances[i].Locked.InexactFloat64()
|
||||
|
||||
currencyBalance = append(currencyBalance, account.Balance{
|
||||
CurrencyName: currency.NewCode(raw.Balances[i].Asset),
|
||||
Total: free + locked,
|
||||
Hold: locked,
|
||||
Free: free,
|
||||
Currency: currency.NewCode(raw.Balances[i].Asset),
|
||||
Total: free + locked,
|
||||
Hold: locked,
|
||||
Free: free,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -723,10 +723,10 @@ func (b *Binance) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
var currencyDetails []account.Balance
|
||||
for i := range accData.Assets {
|
||||
currencyDetails = append(currencyDetails, account.Balance{
|
||||
CurrencyName: currency.NewCode(accData.Assets[i].Asset),
|
||||
Total: accData.Assets[i].WalletBalance,
|
||||
Hold: accData.Assets[i].WalletBalance - accData.Assets[i].AvailableBalance,
|
||||
Free: accData.Assets[i].AvailableBalance,
|
||||
Currency: currency.NewCode(accData.Assets[i].Asset),
|
||||
Total: accData.Assets[i].WalletBalance,
|
||||
Hold: accData.Assets[i].WalletBalance - accData.Assets[i].AvailableBalance,
|
||||
Free: accData.Assets[i].AvailableBalance,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -742,10 +742,10 @@ func (b *Binance) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
currencyDetails := accountCurrencyDetails[accData[i].AccountAlias]
|
||||
accountCurrencyDetails[accData[i].AccountAlias] = append(
|
||||
currencyDetails, account.Balance{
|
||||
CurrencyName: currency.NewCode(accData[i].Asset),
|
||||
Total: accData[i].Balance,
|
||||
Hold: accData[i].Balance - accData[i].AvailableBalance,
|
||||
Free: accData[i].AvailableBalance,
|
||||
Currency: currency.NewCode(accData[i].Asset),
|
||||
Total: accData[i].Balance,
|
||||
Hold: accData[i].Balance - accData[i].AvailableBalance,
|
||||
Free: accData[i].AvailableBalance,
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -761,7 +761,7 @@ func (b *Binance) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
var currencyDetails []account.Balance
|
||||
for i := range accData.UserAssets {
|
||||
currencyDetails = append(currencyDetails, account.Balance{
|
||||
CurrencyName: currency.NewCode(accData.UserAssets[i].Asset),
|
||||
Currency: currency.NewCode(accData.UserAssets[i].Asset),
|
||||
Total: accData.UserAssets[i].Free + accData.UserAssets[i].Locked,
|
||||
Hold: accData.UserAssets[i].Locked,
|
||||
Free: accData.UserAssets[i].Free,
|
||||
@@ -1772,7 +1772,7 @@ func (b *Binance) GetHistoricCandlesExtended(ctx context.Context, pair currency.
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", b.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -441,10 +441,10 @@ func (bi *Binanceus) UpdateAccountInfo(ctx context.Context, assetType asset.Item
|
||||
locked := theAccount.Balances[i].Locked.InexactFloat64()
|
||||
|
||||
currencyBalance[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(theAccount.Balances[i].Asset),
|
||||
Total: freeBalance + locked,
|
||||
Hold: locked,
|
||||
Free: freeBalance,
|
||||
Currency: currency.NewCode(theAccount.Balances[i].Asset),
|
||||
Total: freeBalance + locked,
|
||||
Hold: locked,
|
||||
Free: freeBalance,
|
||||
}
|
||||
}
|
||||
acc.Currencies = currencyBalance
|
||||
@@ -957,7 +957,7 @@ func (bi *Binanceus) GetHistoricCandlesExtended(ctx context.Context, pair curren
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", bi.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -516,10 +516,10 @@ func (b *Bitfinex) UpdateAccountInfo(ctx context.Context, assetType asset.Item)
|
||||
if Accounts[i].ID == accountBalance[x].Type {
|
||||
Accounts[i].Currencies = append(Accounts[i].Currencies,
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(accountBalance[x].Currency),
|
||||
Total: accountBalance[x].Amount,
|
||||
Hold: accountBalance[x].Amount - accountBalance[x].Available,
|
||||
Free: accountBalance[x].Available,
|
||||
Currency: currency.NewCode(accountBalance[x].Currency),
|
||||
Total: accountBalance[x].Amount,
|
||||
Hold: accountBalance[x].Amount - accountBalance[x].Available,
|
||||
Free: accountBalance[x].Available,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1174,7 +1174,7 @@ func (b *Bitfinex) GetHistoricCandlesExtended(ctx context.Context, pair currency
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", b.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -380,10 +380,10 @@ func (b *Bithumb) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
}
|
||||
|
||||
exchangeBalances = append(exchangeBalances, account.Balance{
|
||||
CurrencyName: currency.NewCode(key),
|
||||
Total: totalAmount,
|
||||
Hold: hold,
|
||||
Free: avail,
|
||||
Currency: currency.NewCode(key),
|
||||
Total: totalAmount,
|
||||
Hold: hold,
|
||||
Free: avail,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -513,8 +513,8 @@ func (b *Bitmex) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
|
||||
accountBalances[accountID] = append(
|
||||
accountBalances[accountID], account.Balance{
|
||||
CurrencyName: currency.NewCode(wallet.Currency),
|
||||
Total: wallet.Amount,
|
||||
Currency: currency.NewCode(wallet.Currency),
|
||||
Total: wallet.Amount,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -442,10 +442,10 @@ func (b *Bitstamp) UpdateAccountInfo(ctx context.Context, assetType asset.Item)
|
||||
currencies := make([]account.Balance, 0, len(accountBalance))
|
||||
for k, v := range accountBalance {
|
||||
currencies = append(currencies, account.Balance{
|
||||
CurrencyName: currency.NewCode(k),
|
||||
Total: v.Balance,
|
||||
Hold: v.Reserved,
|
||||
Free: v.Available,
|
||||
Currency: currency.NewCode(k),
|
||||
Total: v.Balance,
|
||||
Hold: v.Reserved,
|
||||
Free: v.Available,
|
||||
})
|
||||
}
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
@@ -956,7 +956,7 @@ func (b *Bitstamp) GetHistoricCandlesExtended(ctx context.Context, pair currency
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", b.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -410,10 +410,10 @@ func (b *Bittrex) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
currencies := make([]account.Balance, len(balanceData))
|
||||
for i := range balanceData {
|
||||
currencies[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(balanceData[i].CurrencySymbol),
|
||||
Total: balanceData[i].Total,
|
||||
Hold: balanceData[i].Total - balanceData[i].Available,
|
||||
Free: balanceData[i].Available,
|
||||
Currency: currency.NewCode(balanceData[i].CurrencySymbol),
|
||||
Total: balanceData[i].Total,
|
||||
Hold: balanceData[i].Total - balanceData[i].Available,
|
||||
Free: balanceData[i].Available,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,7 +1044,7 @@ func (b *Bittrex) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
})
|
||||
}
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -447,10 +447,10 @@ func (b *BTCMarkets) UpdateAccountInfo(ctx context.Context, assetType asset.Item
|
||||
acc.AssetType = assetType
|
||||
for x := range data {
|
||||
acc.Currencies = append(acc.Currencies, account.Balance{
|
||||
CurrencyName: currency.NewCode(data[x].AssetName),
|
||||
Total: data[x].Balance,
|
||||
Hold: data[x].Locked,
|
||||
Free: data[x].Available,
|
||||
Currency: currency.NewCode(data[x].AssetName),
|
||||
Total: data[x].Balance,
|
||||
Hold: data[x].Locked,
|
||||
Free: data[x].Available,
|
||||
})
|
||||
}
|
||||
resp.Accounts = append(resp.Accounts, acc)
|
||||
@@ -1148,7 +1148,7 @@ func (b *BTCMarkets) GetHistoricCandlesExtended(ctx context.Context, p currency.
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", b.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -401,10 +401,10 @@ func (b *BTSE) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (acc
|
||||
currencies := make([]account.Balance, len(balance))
|
||||
for b := range balance {
|
||||
currencies[b] = account.Balance{
|
||||
CurrencyName: currency.NewCode(balance[b].Currency),
|
||||
Total: balance[b].Total,
|
||||
Hold: balance[b].Total - balance[b].Available,
|
||||
Free: balance[b].Available,
|
||||
Currency: currency.NewCode(balance[b].Currency),
|
||||
Total: balance[b].Total,
|
||||
Hold: balance[b].Total - balance[b].Available,
|
||||
Free: balance[b].Available,
|
||||
}
|
||||
}
|
||||
a.Exchange = b.Name
|
||||
|
||||
@@ -712,10 +712,10 @@ func (by *Bybit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
currencyBalance := make([]account.Balance, len(balances))
|
||||
for i := range balances {
|
||||
currencyBalance[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(balances[i].CoinName),
|
||||
Total: balances[i].Total,
|
||||
Hold: balances[i].Locked,
|
||||
Free: balances[i].Total - balances[i].Locked,
|
||||
Currency: currency.NewCode(balances[i].CoinName),
|
||||
Total: balances[i].Total,
|
||||
Hold: balances[i].Locked,
|
||||
Free: balances[i].Total - balances[i].Locked,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,10 +731,10 @@ func (by *Bybit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
currencyBalance := make([]account.Balance, len(balances))
|
||||
for coinName, data := range balances {
|
||||
currencyBalance[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(coinName),
|
||||
Total: data.WalletBalance,
|
||||
Hold: data.WalletBalance - data.AvailableBalance,
|
||||
Free: data.AvailableBalance,
|
||||
Currency: currency.NewCode(coinName),
|
||||
Total: data.WalletBalance,
|
||||
Hold: data.WalletBalance - data.AvailableBalance,
|
||||
Free: data.AvailableBalance,
|
||||
}
|
||||
i++
|
||||
}
|
||||
@@ -749,10 +749,10 @@ func (by *Bybit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
|
||||
acc.Currencies = []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.USD,
|
||||
Total: balance.WalletBalance,
|
||||
Hold: balance.WalletBalance - balance.AvailableBalance,
|
||||
Free: balance.AvailableBalance,
|
||||
Currency: currency.USD,
|
||||
Total: balance.WalletBalance,
|
||||
Hold: balance.WalletBalance - balance.AvailableBalance,
|
||||
Free: balance.AvailableBalance,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2037,7 +2037,7 @@ func (by *Bybit) GetHistoricCandlesExtended(ctx context.Context, pair currency.P
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", by.Name, summary)
|
||||
}
|
||||
klineItem.RemoveDuplicates()
|
||||
klineItem.RemoveDuplicateCandlesByTime()
|
||||
klineItem.RemoveOutsideRange(start, end)
|
||||
klineItem.SortCandlesByTimestamp(false)
|
||||
return klineItem, nil
|
||||
|
||||
@@ -329,7 +329,7 @@ func (c *CoinbasePro) UpdateAccountInfo(ctx context.Context, assetType asset.Ite
|
||||
profileID := accountBalance[i].ProfileID
|
||||
currencies := accountCurrencies[profileID]
|
||||
accountCurrencies[profileID] = append(currencies, account.Balance{
|
||||
CurrencyName: currency.NewCode(accountBalance[i].Currency),
|
||||
Currency: currency.NewCode(accountBalance[i].Currency),
|
||||
Total: accountBalance[i].Balance,
|
||||
Hold: accountBalance[i].Hold,
|
||||
Free: accountBalance[i].Available,
|
||||
@@ -1013,7 +1013,7 @@ func (c *CoinbasePro) GetHistoricCandlesExtended(ctx context.Context, p currency
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", c.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -324,60 +324,60 @@ func (c *COINUT) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
|
||||
var balances = []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.BCH,
|
||||
Total: bal.BCH,
|
||||
Currency: currency.BCH,
|
||||
Total: bal.BCH,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: bal.BTC,
|
||||
Currency: currency.BTC,
|
||||
Total: bal.BTC,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.BTG,
|
||||
Total: bal.BTG,
|
||||
Currency: currency.BTG,
|
||||
Total: bal.BTG,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.CAD,
|
||||
Total: bal.CAD,
|
||||
Currency: currency.CAD,
|
||||
Total: bal.CAD,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.ETC,
|
||||
Total: bal.ETC,
|
||||
Currency: currency.ETC,
|
||||
Total: bal.ETC,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.ETH,
|
||||
Total: bal.ETH,
|
||||
Currency: currency.ETH,
|
||||
Total: bal.ETH,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.LCH,
|
||||
Total: bal.LCH,
|
||||
Currency: currency.LCH,
|
||||
Total: bal.LCH,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.LTC,
|
||||
Total: bal.LTC,
|
||||
Currency: currency.LTC,
|
||||
Total: bal.LTC,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.MYR,
|
||||
Total: bal.MYR,
|
||||
Currency: currency.MYR,
|
||||
Total: bal.MYR,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.SGD,
|
||||
Total: bal.SGD,
|
||||
Currency: currency.SGD,
|
||||
Total: bal.SGD,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.USD,
|
||||
Total: bal.USD,
|
||||
Currency: currency.USD,
|
||||
Total: bal.USD,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.USDT,
|
||||
Total: bal.USDT,
|
||||
Currency: currency.USDT,
|
||||
Total: bal.USDT,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.XMR,
|
||||
Total: bal.XMR,
|
||||
Currency: currency.XMR,
|
||||
Total: bal.XMR,
|
||||
},
|
||||
{
|
||||
CurrencyName: currency.ZEC,
|
||||
Total: bal.ZEC,
|
||||
Currency: currency.ZEC,
|
||||
Total: bal.ZEC,
|
||||
},
|
||||
}
|
||||
info.Exchange = c.Name
|
||||
|
||||
@@ -1444,7 +1444,7 @@ func (b *Base) CalculateTotalCollateral(ctx context.Context, calculator *order.T
|
||||
}
|
||||
|
||||
// GetCollateralCurrencyForContract returns the collateral currency for an asset and contract pair
|
||||
func (b *Base) GetCollateralCurrencyForContract(asset.Item, currency.Pair) (currency.Code, asset.Item, error) {
|
||||
func (b *Base) GetCollateralCurrencyForContract(a asset.Item, cp currency.Pair) (currency.Code, asset.Item, error) {
|
||||
return currency.Code{}, asset.Empty, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
|
||||
@@ -2644,3 +2644,41 @@ func TestSetRequester(t *testing.T) {
|
||||
t.Fatal("requester not set correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCollateralCurrencyForContract(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{}
|
||||
_, _, err := b.GetCollateralCurrencyForContract(asset.Futures, currency.NewPair(currency.XRP, currency.BABYDOGE))
|
||||
if !errors.Is(err, common.ErrNotYetImplemented) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrNotYetImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrencyForRealisedPNL(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{}
|
||||
_, _, err := b.GetCurrencyForRealisedPNL(asset.Empty, currency.EMPTYPAIR)
|
||||
if !errors.Is(err, common.ErrNotYetImplemented) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrNotYetImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasAssetTypeAccountSegregation(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{
|
||||
Name: "RAWR",
|
||||
Features: Features{
|
||||
Supports: FeaturesSupported{
|
||||
REST: true,
|
||||
RESTCapabilities: protocol.Features{
|
||||
HasAssetTypeAccountSegregation: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
has := b.HasAssetTypeAccountSegregation()
|
||||
if !has {
|
||||
t.Errorf("expected '%v' received '%v'", true, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ func (e *EXMO) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (acc
|
||||
currencies := make([]account.Balance, 0, len(result.Balances))
|
||||
for x, y := range result.Balances {
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(x)
|
||||
exchangeCurrency.Currency = currency.NewCode(x)
|
||||
for z, w := range result.Reserved {
|
||||
if z != x {
|
||||
continue
|
||||
|
||||
@@ -764,7 +764,11 @@ func (f *FTX) Order(
|
||||
req := make(map[string]interface{})
|
||||
req["market"] = marketName
|
||||
req["side"] = side
|
||||
req["price"] = price
|
||||
if orderType == "market" {
|
||||
req["price"] = nil
|
||||
} else {
|
||||
req["price"] = price
|
||||
}
|
||||
req["type"] = orderType
|
||||
req["size"] = size
|
||||
if reduceOnly {
|
||||
@@ -922,7 +926,7 @@ func (f *FTX) DeleteTriggerOrder(ctx context.Context, orderID string) (string, e
|
||||
|
||||
// GetFills gets order fills data and ensures that all
|
||||
// fills are retrieved from the supplied timeframe
|
||||
func (f *FTX) GetFills(ctx context.Context, market currency.Pair, item asset.Item, startTime, endTime time.Time) ([]FillsData, error) {
|
||||
func (f *FTX) GetFills(ctx context.Context, market currency.Pair, item asset.Item, startTime, endTime time.Time, orderID string) ([]FillsData, error) {
|
||||
var resp []FillsData
|
||||
var nextEnd = endTime
|
||||
limit := 200
|
||||
@@ -946,6 +950,9 @@ func (f *FTX) GetFills(ctx context.Context, market currency.Pair, item asset.Ite
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(nextEnd.Unix(), 10))
|
||||
}
|
||||
if orderID != "" {
|
||||
params.Set("orderId", orderID)
|
||||
}
|
||||
endpoint := common.EncodeURLValues(getFills, params)
|
||||
err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &data)
|
||||
if err != nil {
|
||||
|
||||
@@ -678,6 +678,7 @@ func TestSubmitOrder(t *testing.T) {
|
||||
Amount: 1,
|
||||
AssetType: asset.Spot,
|
||||
ClientOrderID: "order12345679$$$$$",
|
||||
RetrieveFees: true,
|
||||
}
|
||||
_, err = f.SubmitOrder(context.Background(), orderSubmission)
|
||||
if err != nil {
|
||||
@@ -766,25 +767,30 @@ func TestGetFills(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetFills(context.Background(),
|
||||
currency.Pair{}, asset.Futures, time.Now().Add(time.Hour*24*365), time.Now())
|
||||
currency.Pair{}, asset.Futures, time.Now().Add(time.Hour*24*365), time.Now(), "")
|
||||
if !errors.Is(err, errStartTimeCannotBeAfterEndTime) {
|
||||
t.Errorf("received '%v' expected '%v'", err, errStartTimeCannotBeAfterEndTime)
|
||||
}
|
||||
|
||||
_, err = f.GetFills(context.Background(),
|
||||
currency.Pair{}, asset.Futures, time.Time{}, time.Time{})
|
||||
currency.Pair{}, asset.Futures, time.Time{}, time.Time{}, "")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
|
||||
_, err = f.GetFills(context.Background(),
|
||||
currency.Pair{}, asset.Futures, time.Now().Add(-time.Hour*24*365), time.Now())
|
||||
currency.Pair{}, asset.Futures, time.Now().Add(-time.Hour*24*365), time.Now(), "")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
|
||||
_, err = f.GetFills(context.Background(),
|
||||
spotPair, asset.Spot, time.Now().Add(-time.Hour*24*365), time.Now())
|
||||
spotPair, asset.Spot, time.Now().Add(-time.Hour*24*365), time.Now(), "")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
_, err = f.GetFills(context.Background(),
|
||||
currency.EMPTYPAIR, asset.Futures, time.Time{}, time.Time{}, "177453606715")
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
@@ -2819,3 +2825,36 @@ func TestGetReferralRebateRate(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCollateralCurrencyForContract(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, a, err := f.GetCollateralCurrencyForContract(asset.Futures, currency.NewPair(currency.XRP, currency.BABYDOGE))
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
if a != asset.Futures {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", a, asset.Futures)
|
||||
}
|
||||
if !c.Equal(currency.USD) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", c, currency.USD)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrencyForRealisedPNL(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, a, err := f.GetCurrencyForRealisedPNL(asset.Futures, currency.NewPair(currency.XRP, currency.BABYDOGE))
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
if a != asset.Spot {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", a, asset.Spot)
|
||||
}
|
||||
if !c.Equal(currency.USD) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", c, currency.USD)
|
||||
}
|
||||
|
||||
_, _, err = f.GetCurrencyForRealisedPNL(asset.Spot, currency.NewPair(currency.SHIB, currency.DOGE))
|
||||
if !errors.Is(err, order.ErrNotFuturesAsset) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, order.ErrNotFuturesAsset)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ type OrderData struct {
|
||||
ClientID string `json:"clientId"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
FilledSize float64 `json:"filledSize"`
|
||||
Future currency.Pair `json:"future"`
|
||||
Future string `json:"future"`
|
||||
ID int64 `json:"id"`
|
||||
IOC bool `json:"ioc"`
|
||||
Market currency.Pair `json:"market"`
|
||||
|
||||
@@ -168,6 +168,14 @@ func (f *FTX) SetDefaults() {
|
||||
f.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
f.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
f.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
|
||||
|
||||
err = f.LoadCollateralWeightings(context.TODO())
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys,
|
||||
"%s failed to store collateral weightings. Err: %s",
|
||||
f.Name,
|
||||
err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -206,15 +214,6 @@ func (f *FTX) Setup(exch *config.Exchange) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = f.CurrencyPairs.IsAssetEnabled(asset.Futures); err == nil {
|
||||
err = f.LoadCollateralWeightings(context.TODO())
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys,
|
||||
"%s failed to store collateral weightings. Err: %s",
|
||||
f.Name,
|
||||
err)
|
||||
}
|
||||
}
|
||||
return f.Websocket.SetupNewConnection(stream.ConnectionSetup{
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
@@ -490,7 +489,7 @@ func (f *FTX) UpdateAccountInfo(ctx context.Context, a asset.Item) (account.Hold
|
||||
hold := balances[x].Total - balances[x].AvailableWithoutBorrow
|
||||
acc.Currencies = append(acc.Currencies,
|
||||
account.Balance{
|
||||
CurrencyName: balances[x].Coin,
|
||||
Currency: balances[x].Coin,
|
||||
Total: balances[x].Total,
|
||||
Hold: hold,
|
||||
AvailableWithoutBorrow: balances[x].AvailableWithoutBorrow,
|
||||
@@ -648,10 +647,10 @@ func (f *FTX) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitRe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.Side == order.Ask {
|
||||
if s.Side.IsShort() {
|
||||
s.Side = order.Sell
|
||||
}
|
||||
if s.Side == order.Bid {
|
||||
if s.Side.IsLong() {
|
||||
s.Side = order.Buy
|
||||
}
|
||||
|
||||
@@ -674,7 +673,43 @@ func (f *FTX) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitRe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.DeriveSubmitResponse(strconv.FormatInt(tempResp.ID, 10))
|
||||
resp, err := s.DeriveSubmitResponse(strconv.FormatInt(tempResp.ID, 10))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !s.RetrieveFees {
|
||||
return resp, nil
|
||||
}
|
||||
time.Sleep(s.RetrieveFeeDelay)
|
||||
fills, err := f.GetFills(ctx, s.Pair, s.AssetType, time.Time{}, time.Time{}, strconv.FormatInt(tempResp.ID, 10))
|
||||
if err != nil {
|
||||
// choosing to return with no error so that a valid order is still returned to caller
|
||||
log.Errorf(log.ExchangeSys, "could not retrieve fees for order %v: %v", tempResp.ID, err)
|
||||
return resp, nil
|
||||
}
|
||||
for i := range fills {
|
||||
resp.Fee += fills[i].Fee
|
||||
var side order.Side
|
||||
side, err = order.StringToOrderSide(fills[i].Side)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.FeeAsset.IsEmpty() {
|
||||
resp.FeeAsset = fills[i].FeeCurrency
|
||||
}
|
||||
resp.Trades = append(resp.Trades, order.TradeHistory{
|
||||
Price: fills[i].Price,
|
||||
Amount: fills[i].Size,
|
||||
Fee: fills[i].Fee,
|
||||
Exchange: f.Name,
|
||||
TID: strconv.FormatInt(fills[i].TradeID, 10),
|
||||
Side: side,
|
||||
Timestamp: fills[i].Time,
|
||||
IsMaker: fills[i].Liquidity == "maker",
|
||||
FeeAsset: fills[i].FeeCurrency.String(),
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
@@ -1270,7 +1305,7 @@ func (f *FTX) GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", f.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
@@ -1696,7 +1731,7 @@ func (f *FTX) GetFuturesPositions(ctx context.Context, request *order.PositionsR
|
||||
allPositions:
|
||||
for {
|
||||
var fills []FillsData
|
||||
fills, err = f.GetFills(ctx, request.Pairs[x], request.Asset, request.StartDate, endTime)
|
||||
fills, err = f.GetFills(ctx, request.Pairs[x], request.Asset, request.StartDate, endTime, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1760,12 +1795,15 @@ func (f *FTX) GetFuturesPositions(ctx context.Context, request *order.PositionsR
|
||||
}
|
||||
|
||||
// GetCollateralCurrencyForContract returns the collateral currency for an asset and contract pair
|
||||
func (f *FTX) GetCollateralCurrencyForContract(_ asset.Item, _ currency.Pair) (currency.Code, asset.Item, error) {
|
||||
func (f *FTX) GetCollateralCurrencyForContract(a asset.Item, _ currency.Pair) (currency.Code, asset.Item, error) {
|
||||
return currency.USD, asset.Futures, nil
|
||||
}
|
||||
|
||||
// GetCurrencyForRealisedPNL returns where to put realised PNL
|
||||
func (f *FTX) GetCurrencyForRealisedPNL(_ asset.Item, _ currency.Pair) (currency.Code, asset.Item, error) {
|
||||
func (f *FTX) GetCurrencyForRealisedPNL(a asset.Item, _ currency.Pair) (currency.Code, asset.Item, error) {
|
||||
if !a.IsFutures() {
|
||||
return currency.EMPTYCODE, asset.Empty, fmt.Errorf("%v %w", a, order.ErrNotFuturesAsset)
|
||||
}
|
||||
return currency.USD, asset.Spot, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -357,10 +357,10 @@ func (g *Gateio) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
var currData []account.Balance
|
||||
for k := range resp.Result {
|
||||
currData = append(currData, account.Balance{
|
||||
CurrencyName: currency.NewCode(k),
|
||||
Total: resp.Result[k].Available + resp.Result[k].Freeze,
|
||||
Hold: resp.Result[k].Freeze,
|
||||
Free: resp.Result[k].Available,
|
||||
Currency: currency.NewCode(k),
|
||||
Total: resp.Result[k].Available + resp.Result[k].Freeze,
|
||||
Hold: resp.Result[k].Freeze,
|
||||
Free: resp.Result[k].Available,
|
||||
})
|
||||
}
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
@@ -383,8 +383,8 @@ func (g *Gateio) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
}
|
||||
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
Hold: lockedF,
|
||||
Currency: currency.NewCode(x),
|
||||
Hold: lockedF,
|
||||
})
|
||||
}
|
||||
default:
|
||||
@@ -402,7 +402,7 @@ func (g *Gateio) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
|
||||
var updated bool
|
||||
for i := range balances {
|
||||
if !balances[i].CurrencyName.Equal(currency.NewCode(x)) {
|
||||
if !balances[i].Currency.Equal(currency.NewCode(x)) {
|
||||
continue
|
||||
}
|
||||
balances[i].Total = balances[i].Hold + availAmount
|
||||
@@ -413,8 +413,8 @@ func (g *Gateio) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
}
|
||||
if !updated {
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
Total: availAmount,
|
||||
Currency: currency.NewCode(x),
|
||||
Total: availAmount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,10 +324,10 @@ func (g *Gemini) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
currencies := make([]account.Balance, len(accountBalance))
|
||||
for i := range accountBalance {
|
||||
currencies[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(accountBalance[i].Currency),
|
||||
Total: accountBalance[i].Amount,
|
||||
Hold: accountBalance[i].Amount - accountBalance[i].Available,
|
||||
Free: accountBalance[i].Available,
|
||||
Currency: currency.NewCode(accountBalance[i].Currency),
|
||||
Total: accountBalance[i].Amount,
|
||||
Hold: accountBalance[i].Amount - accountBalance[i].Available,
|
||||
Free: accountBalance[i].Available,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -436,10 +436,10 @@ func (h *HitBTC) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
currencies := make([]account.Balance, 0, len(accountBalance))
|
||||
for i := range accountBalance {
|
||||
currencies = append(currencies, account.Balance{
|
||||
CurrencyName: currency.NewCode(accountBalance[i].Currency),
|
||||
Total: accountBalance[i].Available + accountBalance[i].Reserved,
|
||||
Hold: accountBalance[i].Reserved,
|
||||
Free: accountBalance[i].Available,
|
||||
Currency: currency.NewCode(accountBalance[i].Currency),
|
||||
Total: accountBalance[i].Available + accountBalance[i].Reserved,
|
||||
Hold: accountBalance[i].Reserved,
|
||||
Free: accountBalance[i].Available,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -951,7 +951,7 @@ func (h *HitBTC) GetHistoricCandlesExtended(ctx context.Context, pair currency.P
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", h.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -639,8 +639,8 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
continue
|
||||
}
|
||||
currData := account.Balance{
|
||||
CurrencyName: currency.NewCode(resp.Data[i].List[0].Currency),
|
||||
Total: resp.Data[i].List[0].Balance,
|
||||
Currency: currency.NewCode(resp.Data[i].List[0].Currency),
|
||||
Total: resp.Data[i].List[0].Balance,
|
||||
}
|
||||
if len(resp.Data[i].List) > 1 && resp.Data[i].List[1].Type == "frozen" {
|
||||
currData.Hold = resp.Data[i].List[1].Balance
|
||||
@@ -668,7 +668,7 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
for j := range balances {
|
||||
frozen := balances[j].Type == "frozen"
|
||||
for i := range currencyDetails {
|
||||
if currencyDetails[i].CurrencyName.String() == balances[j].Currency {
|
||||
if currencyDetails[i].Currency.String() == balances[j].Currency {
|
||||
if frozen {
|
||||
currencyDetails[i].Hold = balances[j].Balance
|
||||
} else {
|
||||
@@ -681,14 +681,14 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
if frozen {
|
||||
currencyDetails = append(currencyDetails,
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
Hold: balances[j].Balance,
|
||||
Currency: currency.NewCode(balances[j].Currency),
|
||||
Hold: balances[j].Balance,
|
||||
})
|
||||
} else {
|
||||
currencyDetails = append(currencyDetails,
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(balances[j].Currency),
|
||||
Total: balances[j].Balance,
|
||||
Currency: currency.NewCode(balances[j].Currency),
|
||||
Total: balances[j].Balance,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -706,10 +706,10 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
var mainAcctBalances []account.Balance
|
||||
for x := range acctInfo.Data {
|
||||
mainAcctBalances = append(mainAcctBalances, account.Balance{
|
||||
CurrencyName: currency.NewCode(acctInfo.Data[x].Symbol),
|
||||
Total: acctInfo.Data[x].MarginBalance,
|
||||
Hold: acctInfo.Data[x].MarginFrozen,
|
||||
Free: acctInfo.Data[x].MarginAvailable,
|
||||
Currency: currency.NewCode(acctInfo.Data[x].Symbol),
|
||||
Total: acctInfo.Data[x].MarginBalance,
|
||||
Hold: acctInfo.Data[x].MarginFrozen,
|
||||
Free: acctInfo.Data[x].MarginAvailable,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -733,10 +733,10 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
}
|
||||
for y := range a.Data {
|
||||
currencyDetails = append(currencyDetails, account.Balance{
|
||||
CurrencyName: currency.NewCode(a.Data[y].Symbol),
|
||||
Total: a.Data[y].MarginBalance,
|
||||
Hold: a.Data[y].MarginFrozen,
|
||||
Free: a.Data[y].MarginAvailable,
|
||||
Currency: currency.NewCode(a.Data[y].Symbol),
|
||||
Total: a.Data[y].MarginBalance,
|
||||
Hold: a.Data[y].MarginFrozen,
|
||||
Free: a.Data[y].MarginAvailable,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -751,10 +751,10 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
var mainAcctBalances []account.Balance
|
||||
for x := range mainAcctData.AccData {
|
||||
mainAcctBalances = append(mainAcctBalances, account.Balance{
|
||||
CurrencyName: currency.NewCode(mainAcctData.AccData[x].Symbol),
|
||||
Total: mainAcctData.AccData[x].MarginBalance,
|
||||
Hold: mainAcctData.AccData[x].MarginFrozen,
|
||||
Free: mainAcctData.AccData[x].MarginAvailable,
|
||||
Currency: currency.NewCode(mainAcctData.AccData[x].Symbol),
|
||||
Total: mainAcctData.AccData[x].MarginBalance,
|
||||
Hold: mainAcctData.AccData[x].MarginFrozen,
|
||||
Free: mainAcctData.AccData[x].MarginAvailable,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -778,10 +778,10 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
}
|
||||
for y := range a.AssetsData {
|
||||
currencyDetails = append(currencyDetails, account.Balance{
|
||||
CurrencyName: currency.NewCode(a.AssetsData[y].Symbol),
|
||||
Total: a.AssetsData[y].MarginBalance,
|
||||
Hold: a.AssetsData[y].MarginFrozen,
|
||||
Free: a.AssetsData[y].MarginAvailable,
|
||||
Currency: currency.NewCode(a.AssetsData[y].Symbol),
|
||||
Total: a.AssetsData[y].MarginBalance,
|
||||
Hold: a.AssetsData[y].MarginFrozen,
|
||||
Free: a.AssetsData[y].MarginAvailable,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,10 +286,10 @@ func (i *ItBit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
fullBalance := make([]account.Balance, 0, len(amounts))
|
||||
for key := range amounts {
|
||||
fullBalance = append(fullBalance, account.Balance{
|
||||
CurrencyName: currency.NewCode(key),
|
||||
Total: amounts[key].Total,
|
||||
Hold: amounts[key].Hold,
|
||||
Free: amounts[key].Free,
|
||||
Currency: currency.NewCode(key),
|
||||
Total: amounts[key].Total,
|
||||
Hold: amounts[key].Hold,
|
||||
Free: amounts[key].Free,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -183,17 +183,14 @@ func (k *Item) FillMissingDataWithEmptyEntries(i *IntervalRangeHolder) {
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveDuplicates removes any duplicate candles
|
||||
func (k *Item) RemoveDuplicates() {
|
||||
// RemoveDuplicateCandlesByTime removes any duplicate candles
|
||||
func (k *Item) RemoveDuplicateCandlesByTime() {
|
||||
var newCandles []Candle
|
||||
candleMap := make(map[int64]struct{})
|
||||
for x := range k.Candles {
|
||||
if x == 0 {
|
||||
newCandles = append(newCandles, k.Candles[x])
|
||||
continue
|
||||
}
|
||||
if !k.Candles[x].Time.Equal(k.Candles[x-1].Time) {
|
||||
// don't add duplicate
|
||||
if _, ok := candleMap[k.Candles[x].Time.UnixNano()]; !ok {
|
||||
newCandles = append(newCandles, k.Candles[x])
|
||||
candleMap[k.Candles[x].Time.UnixNano()] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,3 +563,20 @@ func CreateIntervalTime(tt time.Time) IntervalTime {
|
||||
func (i *IntervalTime) Equal(tt time.Time) bool {
|
||||
return tt.Unix() == i.Ticks
|
||||
}
|
||||
|
||||
// EqualSource checks whether two sets of candles
|
||||
// come from the same data source
|
||||
func (k *Item) EqualSource(i *Item) error {
|
||||
if k == nil || i == nil {
|
||||
return common.ErrNilPointer
|
||||
}
|
||||
if k.Exchange != i.Exchange ||
|
||||
k.Asset != i.Asset ||
|
||||
!k.Pair.Equal(i.Pair) {
|
||||
return fmt.Errorf("%v %v %v %w %v %v %v", k.Exchange, k.Asset, k.Pair, ErrItemNotEqual, i.Exchange, i.Asset, i.Pair)
|
||||
}
|
||||
if !k.UnderlyingPair.IsEmpty() && !i.UnderlyingPair.IsEmpty() && !k.UnderlyingPair.Equal(i.UnderlyingPair) {
|
||||
return fmt.Errorf("%w %v %v", ErrItemUnderlyingNotEqual, k.UnderlyingPair, i.UnderlyingPair)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -879,6 +879,7 @@ func BenchmarkJustifyIntervalTimeStoringUnixValues2(b *testing.B) {
|
||||
}
|
||||
|
||||
func TestConvertToNewInterval(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := ConvertToNewInterval(nil, OneMin)
|
||||
if !errors.Is(err, errNilKline) {
|
||||
t.Errorf("received '%v' expected '%v'", err, errNilKline)
|
||||
@@ -966,6 +967,7 @@ func TestConvertToNewInterval(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetClosePriceAtTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
tt := time.Now()
|
||||
k := Item{
|
||||
Candles: []Candle{
|
||||
@@ -991,3 +993,34 @@ func TestGetClosePriceAtTime(t *testing.T) {
|
||||
t.Errorf("received '%v' expected '%v'", err, ErrNotFoundAtTime)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveDuplicateCandlesByTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
tt := time.Now()
|
||||
k := Item{
|
||||
Candles: []Candle{
|
||||
{
|
||||
// out of order duplicate time
|
||||
Time: tt.Add(time.Hour),
|
||||
Close: 1337,
|
||||
},
|
||||
{
|
||||
Time: tt,
|
||||
Close: 1337,
|
||||
},
|
||||
{
|
||||
Time: tt.Add(time.Hour),
|
||||
Close: 1338,
|
||||
},
|
||||
},
|
||||
}
|
||||
k.RemoveDuplicateCandlesByTime()
|
||||
if len(k.Candles) != 2 {
|
||||
t.Errorf("received '%v' expected '%v'", len(k.Candles), 2)
|
||||
}
|
||||
k.Candles[0].Time = tt
|
||||
k.RemoveDuplicateCandlesByTime()
|
||||
if len(k.Candles) != 1 {
|
||||
t.Errorf("received '%v' expected '%v'", len(k.Candles), 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,14 +51,18 @@ var (
|
||||
ErrCanOnlyDownscaleCandles = errors.New("interval must be a longer duration to scale")
|
||||
// ErrWholeNumberScaling returns when old interval data cannot neatly fit into new interval size
|
||||
ErrWholeNumberScaling = errors.New("new interval must scale properly into new candle")
|
||||
errNilKline = errors.New("kline item is nil")
|
||||
// ErrNotFoundAtTime returned when looking up a candle at a specific time
|
||||
ErrNotFoundAtTime = errors.New("candle not found at time")
|
||||
|
||||
// ErrItemNotEqual returns when comparison between two kline items fail
|
||||
ErrItemNotEqual = errors.New("kline item not equal")
|
||||
// ErrItemUnderlyingNotEqual returns when the underlying pair is not equal
|
||||
ErrItemUnderlyingNotEqual = errors.New("kline item underlying pair not equal")
|
||||
// ErrValidatingParams defines an error when the kline params are either not
|
||||
// enabled or are invalid.
|
||||
ErrValidatingParams = errors.New("kline param(s) are invalid")
|
||||
|
||||
errNilKline = errors.New("kline item is nil")
|
||||
|
||||
// SupportedIntervals is a list of all supported intervals
|
||||
SupportedIntervals = []Interval{
|
||||
FifteenSecond,
|
||||
|
||||
@@ -604,8 +604,8 @@ func (k *Kraken) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
continue
|
||||
}
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(translatedCurrency),
|
||||
Total: bal[key],
|
||||
Currency: currency.NewCode(translatedCurrency),
|
||||
Total: bal[key],
|
||||
})
|
||||
}
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
@@ -620,8 +620,8 @@ func (k *Kraken) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
for name := range bal.Accounts {
|
||||
for code := range bal.Accounts[name].Balances {
|
||||
balances = append(balances, account.Balance{
|
||||
CurrencyName: currency.NewCode(code).Upper(),
|
||||
Total: bal.Accounts[name].Balances[code],
|
||||
Currency: currency.NewCode(code).Upper(),
|
||||
Total: bal.Accounts[name].Balances[code],
|
||||
})
|
||||
}
|
||||
info.Accounts = append(info.Accounts, account.SubAccount{
|
||||
|
||||
@@ -338,10 +338,10 @@ func (l *Lbank) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
return info, parseErr
|
||||
}
|
||||
acc.Currencies = append(acc.Currencies, account.Balance{
|
||||
CurrencyName: c,
|
||||
Total: totalVal,
|
||||
Hold: totalHold,
|
||||
Free: totalVal - totalHold,
|
||||
Currency: c,
|
||||
Total: totalVal,
|
||||
Hold: totalHold,
|
||||
Free: totalVal - totalHold,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -980,7 +980,7 @@ func (l *Lbank) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pa
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", l.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -295,10 +295,10 @@ func (l *LocalBitcoins) UpdateAccountInfo(ctx context.Context, assetType asset.I
|
||||
AssetType: assetType,
|
||||
Currencies: []account.Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
Total: accountBalance.Total.Balance,
|
||||
Hold: accountBalance.Total.Balance - accountBalance.Total.Sendable,
|
||||
Free: accountBalance.Total.Sendable,
|
||||
Currency: currency.BTC,
|
||||
Total: accountBalance.Total.Balance,
|
||||
Hold: accountBalance.Total.Balance - accountBalance.Total.Sendable,
|
||||
Free: accountBalance.Total.Sendable,
|
||||
}},
|
||||
})
|
||||
|
||||
|
||||
@@ -562,10 +562,10 @@ func (o *OKCoin) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
|
||||
}
|
||||
currencyAccount.Currencies = append(currencyAccount.Currencies,
|
||||
account.Balance{
|
||||
CurrencyName: currency.NewCode(currencies[i].Currency),
|
||||
Total: totalValue,
|
||||
Hold: hold,
|
||||
Free: totalValue - hold,
|
||||
Currency: currency.NewCode(currencies[i].Currency),
|
||||
Total: totalValue,
|
||||
Hold: hold,
|
||||
Free: totalValue - hold,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1048,7 +1048,7 @@ func (o *OKCoin) GetHistoricCandles(ctx context.Context, pair currency.Pair, a a
|
||||
return kline.Item{}, err
|
||||
}
|
||||
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
@@ -1098,7 +1098,7 @@ func (o *OKCoin) GetHistoricCandlesExtended(ctx context.Context, pair currency.P
|
||||
if len(summary) > 0 {
|
||||
log.Warnf(log.ExchangeSys, "%v - %v", o.Base.Name, summary)
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -527,10 +527,10 @@ func (ok *Okx) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (acc
|
||||
free := balances[i].AvailBal
|
||||
locked := balances[i].FrozenBalance
|
||||
currencyBalance[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(balances[i].Currency),
|
||||
Total: balances[i].Balance,
|
||||
Hold: locked,
|
||||
Free: free,
|
||||
Currency: currency.NewCode(balances[i].Currency),
|
||||
Total: balances[i].Balance,
|
||||
Hold: locked,
|
||||
Free: free,
|
||||
}
|
||||
}
|
||||
acc.Currencies = currencyBalance
|
||||
@@ -1439,7 +1439,7 @@ func (ok *Okx) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pai
|
||||
})
|
||||
}
|
||||
}
|
||||
ret.RemoveDuplicates()
|
||||
ret.RemoveDuplicateCandlesByTime()
|
||||
ret.RemoveOutsideRange(start, end)
|
||||
ret.SortCandlesByTimestamp(false)
|
||||
return ret, nil
|
||||
|
||||
@@ -1945,3 +1945,16 @@ func TestGetOrdersRequest_Filter(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidOrderSubmissionSide(t *testing.T) {
|
||||
t.Parallel()
|
||||
if IsValidOrderSubmissionSide(UnknownSide) {
|
||||
t.Error("expected false")
|
||||
}
|
||||
if !IsValidOrderSubmissionSide(Buy) {
|
||||
t.Error("expected true")
|
||||
}
|
||||
if IsValidOrderSubmissionSide(CouldNotBuy) {
|
||||
t.Error("expected false")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ var (
|
||||
// Submit contains all properties of an order that may be required
|
||||
// for an order to be created on an exchange
|
||||
// Each exchange has their own requirements, so not all fields
|
||||
// are required to be populated
|
||||
// need to be populated
|
||||
type Submit struct {
|
||||
Exchange string
|
||||
Type Type
|
||||
@@ -62,6 +62,13 @@ type Submit struct {
|
||||
TriggerPrice float64
|
||||
ClientID string // TODO: Shift to credentials
|
||||
ClientOrderID string
|
||||
// RetrieveFees use if an API submit order response does not return fees
|
||||
// enabling this will perform additional request(s) to retrieve them
|
||||
// and set it in the SubmitResponse
|
||||
RetrieveFees bool
|
||||
// RetrieveFeeDelay some exchanges take time to properly save order data
|
||||
// and cannot retrieve fees data immediately
|
||||
RetrieveFeeDelay time.Duration
|
||||
}
|
||||
|
||||
// SubmitResponse is what is returned after submitting an order to an exchange
|
||||
@@ -90,6 +97,7 @@ type SubmitResponse struct {
|
||||
OrderID string
|
||||
Trades []TradeHistory
|
||||
Fee float64
|
||||
FeeAsset currency.Code
|
||||
Cost float64
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,10 @@ const (
|
||||
orderSubmissionValidSides = Buy | Sell | Bid | Ask | Long | Short
|
||||
shortSide = Short | Sell | Ask
|
||||
longSide = Long | Buy | Bid
|
||||
inactiveStatuses = Filled | Cancelled | InsufficientBalance | MarketUnavailable | Rejected | PartiallyCancelled | Expired | Closed | AnyStatus | Cancelling | Liquidated
|
||||
activeStatuses = Active | Open | PartiallyFilled | New | PendingCancel | Hidden | AutoDeleverage | Pending
|
||||
notPlaced = InsufficientBalance | MarketUnavailable | Rejected
|
||||
|
||||
inactiveStatuses = Filled | Cancelled | InsufficientBalance | MarketUnavailable | Rejected | PartiallyCancelled | Expired | Closed | AnyStatus | Cancelling | Liquidated
|
||||
activeStatuses = Active | Open | PartiallyFilled | New | PendingCancel | Hidden | AutoDeleverage | Pending
|
||||
notPlaced = InsufficientBalance | MarketUnavailable | Rejected
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -39,7 +40,12 @@ var (
|
||||
errOrderDetailIsNil = errors.New("order detail is nil")
|
||||
)
|
||||
|
||||
// Validate checks the supplied data and returns whether or not it's valid
|
||||
// IsValidOrderSubmissionSide validates that the order side is a valid submission direction
|
||||
func IsValidOrderSubmissionSide(s Side) bool {
|
||||
return s != UnknownSide && orderSubmissionValidSides&s == s
|
||||
}
|
||||
|
||||
// Validate checks the supplied data and returns whether it's valid
|
||||
func (s *Submit) Validate(opt ...validate.Checker) error {
|
||||
if s == nil {
|
||||
return ErrSubmissionIsNil
|
||||
@@ -61,8 +67,8 @@ func (s *Submit) Validate(opt ...validate.Checker) error {
|
||||
return fmt.Errorf("'%s' %w", s.AssetType, asset.ErrNotSupported)
|
||||
}
|
||||
|
||||
if s.Side == UnknownSide || orderSubmissionValidSides&s.Side != s.Side {
|
||||
return ErrSideIsInvalid
|
||||
if !IsValidOrderSubmissionSide(s.Side) {
|
||||
return fmt.Errorf("%w %v", ErrSideIsInvalid, s.Side)
|
||||
}
|
||||
|
||||
if s.Type != Market && s.Type != Limit {
|
||||
|
||||
@@ -419,8 +419,8 @@ func (p *Poloniex) UpdateAccountInfo(ctx context.Context, assetType asset.Item)
|
||||
currencies := make([]account.Balance, 0, len(accountBalance.Currency))
|
||||
for x, y := range accountBalance.Currency {
|
||||
currencies = append(currencies, account.Balance{
|
||||
CurrencyName: currency.NewCode(x),
|
||||
Total: y,
|
||||
Currency: currency.NewCode(x),
|
||||
Total: y,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -311,9 +311,8 @@ func (y *Yobit) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac
|
||||
currencies := make([]account.Balance, 0, len(accountBalance.FundsInclOrders))
|
||||
for x, y := range accountBalance.FundsInclOrders {
|
||||
var exchangeCurrency account.Balance
|
||||
exchangeCurrency.CurrencyName = currency.NewCode(x)
|
||||
exchangeCurrency.Currency = currency.NewCode(x)
|
||||
exchangeCurrency.Total = y
|
||||
exchangeCurrency.Hold = 0
|
||||
for z, w := range accountBalance.Funds {
|
||||
if z == x {
|
||||
exchangeCurrency.Hold = y - w
|
||||
|
||||
@@ -386,10 +386,10 @@ func (z *ZB) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (accou
|
||||
}
|
||||
|
||||
balances[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(coins[i].EnName),
|
||||
Total: hold + avail,
|
||||
Hold: hold,
|
||||
Free: avail,
|
||||
Currency: currency.NewCode(coins[i].EnName),
|
||||
Total: hold + avail,
|
||||
Hold: hold,
|
||||
Free: avail,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user