FTX: Funding rates, payments & stats + order manager tracking (#976)

* Adds basic PoC for calculating/retrieving position data

* A very unfortunate day of miscalculations

* Adds position summary and funding rate details to RPC

* Offline funding rate calculations

* More helpers, more stats, refining data, automated retrieval

* Adds new rpc server commands and attempts some organisation

* lower string, lower stress

* Adds ordermanager config. Fleshes outcli. Tracks positions automatically

* Adds new separation for funding payments/rates

* Combines funding rates and payments

* Fun test coverage

* ALL THE TESTS... I hope

* Fixes

* polishes ftx tests. improves perp check. Loops rates

* Final touches before nit attax

* buff 💪

* Stops NotYetImplemented spam with one simple trick!

* Some lovely little niteroos

* linteroo

* Clarifies a couple of errors to help narrow likely end user problems

* Fixes asset type bug, fixes closed position order return, fixes unset status bug

* Fixes order manager handling when no rates are available yet

* Continues on no funding rates instead. Removes err

* Don't show predicted rate if the time is zero

* Addresses scenario with no funding rate payments

* Bug fixes and commentary before updating maps to use *currency.Item

* Adds a pair key type

* Polishes pKey, fixes map order bug

* key is not a property in the event someone changes the base/quote

* Adds improvements to order processing...Breaks it all

* Shakes up the design of things by removing a function

* Fixes issues with order manager positions. Limits update range

* Fixes build issues. Identification of bad tests.

* Merges and fixes features from master and this branch

* buff linter 💪

* re-gen

* proto regen

* Addresses some nits. But not all of them.

* Fixes issue where funding rates weren't returned 🎉

* completes transition futures tracking to map[*currency.Item]map[*currency.Item]

* who did that? not me

* removes redundant check on account of being redundant and unnecessary

* so buf

* addresses nits: duplications, startTime, loops, go tidy, typos

* fixes minor mistakes

* fixes 🍣 🐻 changes to int64
This commit is contained in:
Scott
2022-08-23 12:16:50 +10:00
committed by GitHub
parent e93ee83563
commit 46cadd6f15
50 changed files with 9249 additions and 3730 deletions

View File

@@ -15,6 +15,7 @@ import (
"text/template"
"time"
"github.com/shopspring/decimal"
"github.com/thrasher-corp/gocryptotrader/common/file"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -508,6 +509,41 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
Error: msg,
Response: jsonifyInterface([]interface{}{""}),
})
fundingRateRequest := &order.FundingRatesRequest{
Asset: assetTypes[i],
Pairs: currency.Pairs{p},
StartDate: time.Now().Add(-time.Hour),
EndDate: time.Now(),
}
var fundingRateResponse []order.FundingRates
fundingRateResponse, err = e.GetFundingRates(context.TODO(), fundingRateRequest)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{fundingRateRequest}),
Function: "GetFundingRates",
Error: msg,
Response: jsonifyInterface([]interface{}{fundingRateResponse}),
})
var isPerpetualFutures bool
isPerpetualFutures, err = e.IsPerpetualFutureCurrency(assetTypes[i], p)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{assetTypes[i], p}),
Function: "IsPerpetualFutureCurrency",
Error: msg,
Response: jsonifyInterface([]interface{}{isPerpetualFutures}),
})
}
var fetchAccountInfoResponse account.Holdings
@@ -665,7 +701,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{config.OrderSubmission.OrderID}),
SentParams: jsonifyInterface([]interface{}{config.OrderSubmission.OrderID, p, assetTypes[i]}),
Function: "GetOrderInfo",
Error: msg,
Response: jsonifyInterface([]interface{}{r15}),
@@ -676,6 +712,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
Side: testOrderSide,
Pairs: []currency.Pair{p},
AssetType: assetTypes[i],
StartTime: time.Now().Add(-time.Hour),
EndTime: time.Now(),
}
var getOrderHistoryResponse []order.Detail
getOrderHistoryResponse, err = e.GetOrderHistory(context.TODO(), &historyRequest)
@@ -696,6 +734,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
Side: testOrderSide,
Pairs: []currency.Pair{p},
AssetType: assetTypes[i],
StartTime: time.Now().Add(-time.Hour),
EndTime: time.Now(),
}
var getActiveOrdersResponse []order.Detail
getActiveOrdersResponse, err = e.GetActiveOrders(context.TODO(), &orderRequest)
@@ -872,6 +912,109 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
Response: marginRateHistoryResponse,
})
positionSummaryRequest := &order.PositionSummaryRequest{
Asset: assetTypes[i],
Pair: p,
}
var positionSummaryResponse *order.PositionSummary
positionSummaryResponse, err = e.GetPositionSummary(context.TODO(), positionSummaryRequest)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{positionSummaryRequest}),
Function: "GetPositionSummary",
Error: msg,
Response: jsonifyInterface([]interface{}{positionSummaryResponse}),
})
calculatePNLRequest := &order.PNLCalculatorRequest{
Pair: p,
Underlying: p.Base,
Asset: assetTypes[i],
EntryPrice: decimal.NewFromInt(1337),
OpeningDirection: testOrderSide,
OrderDirection: testOrderSide,
Time: time.Now(),
Exposure: decimal.NewFromInt(1337),
EntryAmount: decimal.NewFromInt(1337),
PreviousPrice: decimal.NewFromInt(1337),
}
var calculatePNLResponse *order.PNLResult
calculatePNLResponse, err = e.CalculatePNL(context.TODO(), calculatePNLRequest)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{calculatePNLRequest}),
Function: "CalculatePNL",
Error: msg,
Response: jsonifyInterface([]interface{}{calculatePNLResponse}),
})
collateralCalculator := &order.CollateralCalculator{
CollateralCurrency: p.Quote,
Asset: assetTypes[i],
Side: testOrderSide,
USDPrice: decimal.NewFromInt(1337),
FreeCollateral: decimal.NewFromInt(1337),
LockedCollateral: decimal.NewFromInt(1337),
UnrealisedPNL: decimal.NewFromInt(1337),
}
var scaleCollateralResponse *order.CollateralByCurrency
scaleCollateralResponse, err = e.ScaleCollateral(context.TODO(), collateralCalculator)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{collateralCalculator}),
Function: "ScaleCollateral",
Error: msg,
Response: jsonifyInterface([]interface{}{scaleCollateralResponse}),
})
totalCollateralCalculator := &order.TotalCollateralCalculator{
CollateralAssets: []order.CollateralCalculator{*collateralCalculator},
}
var calculateTotalCollateralResponse *order.TotalCollateralResponse
calculateTotalCollateralResponse, err = e.CalculateTotalCollateral(context.TODO(), totalCollateralCalculator)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{totalCollateralCalculator}),
Function: "CalculateTotalCollateral",
Error: msg,
Response: jsonifyInterface([]interface{}{calculateTotalCollateralResponse}),
})
var futuresPositionsResponse []order.PositionDetails
futuresPositionsRequest := &order.PositionsRequest{
Asset: assetTypes[i],
Pairs: currency.Pairs{p},
StartDate: time.Now().Add(-time.Hour),
}
futuresPositionsResponse, err = e.GetFuturesPositions(context.TODO(), futuresPositionsRequest)
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{futuresPositionsRequest}),
Function: "GetFuturesPositions",
Error: msg,
Response: jsonifyInterface([]interface{}{futuresPositionsResponse}),
})
response = append(response, responseContainer)
}
return response