Files
gocryptotrader/exchanges/account/account.go
Scott 86d3724507 Futures order position tracking & FTX scaled collateral calculation (#868)
* implements futures functions and GRPC functions on new branch

* lint and test fixes

* Fix uneven split pnl. Adds collateral weight test. docs. New clear func

* Test protection if someone has zero collateral

* Uses string instead of double for accuracy

* Fixes old code panic

* context, match, docs

* Addresses Shazniterinos, var names, expanded tests

* Returns subaccount name, provides USD values when offlinecalc

* Fixes oopsie

* Fixes cool bug which allowed made up subaccount results

* Subaccount override on FTX, subaccount results for collateral

* Strenghten collateral account info checks. Improve FTX test

* English is my first language

* Fixes oopsies

* Fixes for unrealised PNL & collateral rendering

* Fixes lint and tests

* Shaznit fixes

* Secret Shaznit

* Updates account information across wrappers to include more fields

* Updates online collateral calculations. Updates RPC data

* Accurately calculates collateral offline and online minus testing

* Tests and lint chocolate

* Simplifies accountinfo results

* Fixes shaznits

* Adds new func

* Increases collateral accuracy again again again x 200

* Increases accuracy of collateral rendering

* Fixes minor merge/test issues

* Linterino

* Fixes ws test. Improves collateral calculations and rendering

* Make it prettier

* Removes the lock I put on 👀

* Adds `additional_collateral_used` field, renders orig currency

* Fixes unrelated test

* Fix test

* Correctly calculate spot margin borrow collateral

* Address fun lint surprise

See https://github.com/golangci/golangci-lint/issues/741#issuecomment-1017014331

* Strange lint fixing x2

* Continued lint journey

* Nolint the nolint to not lint the lint

* Adds two new fields to response

* More linting issues arising

* fIX3s_c4s|NG

* Fixes command flags' incorrect numbering

* FairMarket = Won
2022-02-28 16:39:36 +11:00

119 lines
2.6 KiB
Go

package account
import (
"errors"
"fmt"
"strings"
"github.com/gofrs/uuid"
"github.com/thrasher-corp/gocryptotrader/dispatch"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
)
func init() {
service = new(Service)
service.accounts = make(map[string]*Account)
service.mux = dispatch.GetNewMux()
}
// CollectBalances converts a map of sub-account balances into a slice
func CollectBalances(accountBalances map[string][]Balance, assetType asset.Item) (accounts []SubAccount, err error) {
if accountBalances == nil {
return nil, errAccountBalancesIsNil
}
if !assetType.IsValid() {
return nil, fmt.Errorf("%s, %w", assetType, asset.ErrNotSupported)
}
accounts = make([]SubAccount, len(accountBalances))
i := 0
for accountID, balances := range accountBalances {
accounts[i] = SubAccount{
ID: accountID,
AssetType: assetType,
Currencies: balances,
}
i++
}
return
}
// SubscribeToExchangeAccount subcribes to your exchange account
func SubscribeToExchangeAccount(exchange string) (dispatch.Pipe, error) {
exchange = strings.ToLower(exchange)
service.Lock()
acc, ok := service.accounts[exchange]
if !ok {
service.Unlock()
return dispatch.Pipe{},
fmt.Errorf("%s exchange account holdings not found", exchange)
}
defer service.Unlock()
return service.mux.Subscribe(acc.ID)
}
// Process processes new account holdings updates
func Process(h *Holdings) error {
if h == nil {
return errors.New("cannot be nil")
}
if h.Exchange == "" {
return errors.New("exchange name unset")
}
return service.Update(h)
}
// GetHoldings returns full holdings for an exchange
func GetHoldings(exch string, assetType asset.Item) (Holdings, error) {
if exch == "" {
return Holdings{}, errors.New("exchange name unset")
}
exch = strings.ToLower(exch)
if !assetType.IsValid() {
return Holdings{}, fmt.Errorf("assetType %v is invalid", assetType)
}
service.Lock()
defer service.Unlock()
h, ok := service.accounts[exch]
if !ok {
return Holdings{}, errors.New("exchange account holdings not found")
}
for y := range h.h.Accounts {
if h.h.Accounts[y].AssetType == assetType {
return *h.h, nil
}
}
return Holdings{}, fmt.Errorf("%v holdings data not found for %s", assetType, exch)
}
// Update updates holdings with new account info
func (s *Service) Update(a *Holdings) error {
exch := strings.ToLower(a.Exchange)
s.Lock()
acc, ok := s.accounts[exch]
if !ok {
id, err := s.mux.GetID()
if err != nil {
s.Unlock()
return err
}
s.accounts[exch] = &Account{h: a, ID: id}
s.Unlock()
return nil
}
acc.h.Accounts = a.Accounts
defer s.Unlock()
return s.mux.Publish([]uuid.UUID{acc.ID}, acc.h)
}