exchanges: Use singular futures settlement currency (#2092)

* Change settlement to singular currency

* whoops.go

* bitmex fix

* minor updates

* 64 divided by 2

* whoops2.go

* ROBOT ROCK

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* ROCK ROCK ROCK ROCK ROBOT

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* shazNit

* currencies unmarshal and code use

* Update currency/currencies.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/btse/btse_wrapper.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* reuse comment for better clarity

* collapses entire thing

* shazLint

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
This commit is contained in:
Scott
2025-11-10 13:21:54 +11:00
committed by GitHub
parent 9441f33f42
commit 61d720b72f
19 changed files with 399 additions and 471 deletions

View File

@@ -43,7 +43,6 @@ const (
bitmexEndpointActiveIntervals = "/instrument/activeIntervals"
bitmexEndpointCompositeIndex = "/instrument/compositeIndex"
bitmexEndpointIndices = "/instrument/indices"
bitmexEndpointInsuranceHistory = "/insurance"
bitmexEndpointLiquidation = "/liquidation"
bitmexEndpointLeader = "/leaderboard"
bitmexEndpointAlias = "/leaderboard/name"
@@ -70,7 +69,6 @@ const (
bitmexEndpointCancelAllOrders = "/order/all"
bitmexEndpointBulk = "/order/bulk"
bitmexEndpointCancelOrderAfter = "/order/cancelAllAfter"
bitmexEndpointClosePosition = "/order/closePosition"
bitmexEndpointPosition = "/position"
bitmexEndpointIsolatePosition = "/position/isolate"
bitmexEndpointLeveragePosition = "/position/leverage"
@@ -82,7 +80,6 @@ const (
bitmexEndpointUserCommision = "/user/commission"
bitmexEndpointUserConfirmEmail = "/user/confirmEmail"
bitmexEndpointUserConfirmTFA = "/user/confirmEnableTFA"
bitmexEndpointUserConfirmWithdrawal = "/user/confirmWithdrawal"
bitmexEndpointUserDepositAddress = "/user/depositAddress"
bitmexEndpointUserDisableTFA = "/user/disableTFA"
bitmexEndpointUserLogout = "/user/logout"
@@ -96,15 +93,7 @@ const (
bitmexEndpointUserRequestWithdraw = "/user/requestWithdrawal"
constSatoshiBTC = 1e-08
// ContractPerpetual perpetual contract type
ContractPerpetual = iota
// ContractFutures futures contract type
ContractFutures
// ContractDownsideProfit downside profit contract type
ContractDownsideProfit
// ContractUpsideProfit upside profit contract type
ContractUpsideProfit
countLimit = uint32(1000)
perpetualContractID = "FFWCSX"
spotID = "IFXXXP"

View File

@@ -186,7 +186,7 @@ type GenericRequestParams struct {
Columns string `json:"columns,omitempty"`
// Count - Number of results to fetch.
Count int32 `json:"count,omitempty"`
Count uint32 `json:"count,omitempty"`
// EndTime - Ending date filter for results.
EndTime string `json:"endTime,omitempty"`

View File

@@ -122,107 +122,107 @@ type Funding struct {
// Instrument Tradeable Contracts, Indices, and History
type Instrument struct {
AskPrice float64 `json:"askPrice"`
BankruptLimitDownPrice float64 `json:"bankruptLimitDownPrice"`
BankruptLimitUpPrice float64 `json:"bankruptLimitUpPrice"`
BidPrice float64 `json:"bidPrice"`
BuyLeg string `json:"buyLeg"`
CalcInterval string `json:"calcInterval"`
Capped bool `json:"capped"`
ClosingTimestamp time.Time `json:"closingTimestamp"`
Deleverage bool `json:"deleverage"`
Expiry string `json:"expiry"`
FairBasis float64 `json:"fairBasis"`
FairBasisRate float64 `json:"fairBasisRate"`
FairMethod string `json:"fairMethod"`
FairPrice float64 `json:"fairPrice"`
Front string `json:"front"`
FundingBaseSymbol string `json:"fundingBaseSymbol"`
FundingInterval time.Time `json:"fundingInterval"`
FundingPremiumSymbol string `json:"fundingPremiumSymbol"`
FundingQuoteSymbol string `json:"fundingQuoteSymbol"`
FundingRate float64 `json:"fundingRate"`
FundingTimestamp time.Time `json:"fundingTimestamp"`
HasLiquidity bool `json:"hasLiquidity"`
HighPrice float64 `json:"highPrice"`
ImpactAskPrice float64 `json:"impactAskPrice"`
ImpactBidPrice float64 `json:"impactBidPrice"`
ImpactMidPrice float64 `json:"impactMidPrice"`
IndicativeFundingRate float64 `json:"indicativeFundingRate"`
IndicativeSettlePrice float64 `json:"indicativeSettlePrice"`
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
InitMargin float64 `json:"initMargin"`
InsuranceFee float64 `json:"insuranceFee"`
InverseLeg string `json:"inverseLeg"`
IsInverse bool `json:"isInverse"`
IsQuanto bool `json:"isQuanto"`
LastChangePcnt float64 `json:"lastChangePcnt"`
LastPrice float64 `json:"lastPrice"`
LastPriceProtected float64 `json:"lastPriceProtected"`
LastTickDirection string `json:"lastTickDirection"`
Limit float64 `json:"limit"`
LimitDownPrice float64 `json:"limitDownPrice"`
LimitUpPrice float64 `json:"limitUpPrice"`
Listing string `json:"listing"`
LotSize float64 `json:"lotSize"`
LowPrice float64 `json:"lowPrice"`
MaintMargin float64 `json:"maintMargin"`
MakerFee float64 `json:"makerFee"`
MarkMethod string `json:"markMethod"`
MarkPrice float64 `json:"markPrice"`
MaxOrderQty float64 `json:"maxOrderQty"`
MaxPrice float64 `json:"maxPrice"`
MidPrice float64 `json:"midPrice"`
Multiplier float64 `json:"multiplier"`
OpenInterest float64 `json:"openInterest"`
OpenValue float64 `json:"openValue"`
OpeningTimestamp time.Time `json:"openingTimestamp"`
OptionMultiplier float64 `json:"optionMultiplier"`
OptionStrikePcnt float64 `json:"optionStrikePcnt"`
OptionStrikePrice float64 `json:"optionStrikePrice"`
OptionStrikeRound float64 `json:"optionStrikeRound"`
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
PositionCurrency string `json:"positionCurrency"`
PrevClosePrice float64 `json:"prevClosePrice"`
PrevPrice24h float64 `json:"prevPrice24h"`
PrevTotalTurnover float64 `json:"prevTotalTurnover"`
PrevTotalVolume float64 `json:"prevTotalVolume"`
PublishInterval string `json:"publishInterval"`
PublishTime time.Time `json:"publishTime"`
QuoteCurrency string `json:"quoteCurrency"`
QuoteToSettleMultiplier int64 `json:"quoteToSettleMultiplier"`
RebalanceInterval string `json:"rebalanceInterval"`
RebalanceTimestamp time.Time `json:"rebalanceTimestamp"`
Reference string `json:"reference"`
ReferenceSymbol string `json:"referenceSymbol"`
RelistInterval string `json:"relistInterval"`
RiskLimit float64 `json:"riskLimit"`
RiskStep float64 `json:"riskStep"`
RootSymbol string `json:"rootSymbol"`
SellLeg string `json:"sellLeg"`
SessionInterval string `json:"sessionInterval"`
SettlCurrency string `json:"settlCurrency"`
Settle string `json:"settle"`
SettledPrice float64 `json:"settledPrice"`
SettlementFee float64 `json:"settlementFee"`
State string `json:"state"`
Symbol string `json:"symbol"`
TakerFee float64 `json:"takerFee"`
Taxed bool `json:"taxed"`
TickSize float64 `json:"tickSize"`
Timestamp time.Time `json:"timestamp"`
TotalTurnover float64 `json:"totalTurnover"`
TotalVolume float64 `json:"totalVolume"`
Turnover float64 `json:"turnover"`
Turnover24h float64 `json:"turnover24h"`
Typ string `json:"typ"`
Underlying string `json:"underlying"`
UnderlyingSymbol string `json:"underlyingSymbol"`
UnderlyingToPositionMultiplier float64 `json:"underlyingToPositionMultiplier"`
UnderlyingToSettleMultiplier float64 `json:"underlyingToSettleMultiplier"`
Volume float64 `json:"volume"`
Volume24h float64 `json:"volume24h"`
Vwap float64 `json:"vwap"`
AskPrice float64 `json:"askPrice"`
BankruptLimitDownPrice float64 `json:"bankruptLimitDownPrice"`
BankruptLimitUpPrice float64 `json:"bankruptLimitUpPrice"`
BidPrice float64 `json:"bidPrice"`
BuyLeg string `json:"buyLeg"`
CalcInterval string `json:"calcInterval"`
Capped bool `json:"capped"`
ClosingTimestamp time.Time `json:"closingTimestamp"`
Deleverage bool `json:"deleverage"`
Expiry string `json:"expiry"`
FairBasis float64 `json:"fairBasis"`
FairBasisRate float64 `json:"fairBasisRate"`
FairMethod string `json:"fairMethod"`
FairPrice float64 `json:"fairPrice"`
Front string `json:"front"`
FundingBaseSymbol string `json:"fundingBaseSymbol"`
FundingInterval time.Time `json:"fundingInterval"`
FundingPremiumSymbol string `json:"fundingPremiumSymbol"`
FundingQuoteSymbol string `json:"fundingQuoteSymbol"`
FundingRate float64 `json:"fundingRate"`
FundingTimestamp time.Time `json:"fundingTimestamp"`
HasLiquidity bool `json:"hasLiquidity"`
HighPrice float64 `json:"highPrice"`
ImpactAskPrice float64 `json:"impactAskPrice"`
ImpactBidPrice float64 `json:"impactBidPrice"`
ImpactMidPrice float64 `json:"impactMidPrice"`
IndicativeFundingRate float64 `json:"indicativeFundingRate"`
IndicativeSettlePrice float64 `json:"indicativeSettlePrice"`
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
InitMargin float64 `json:"initMargin"`
InsuranceFee float64 `json:"insuranceFee"`
InverseLeg string `json:"inverseLeg"`
IsInverse bool `json:"isInverse"`
IsQuanto bool `json:"isQuanto"`
LastChangePcnt float64 `json:"lastChangePcnt"`
LastPrice float64 `json:"lastPrice"`
LastPriceProtected float64 `json:"lastPriceProtected"`
LastTickDirection string `json:"lastTickDirection"`
Limit float64 `json:"limit"`
LimitDownPrice float64 `json:"limitDownPrice"`
LimitUpPrice float64 `json:"limitUpPrice"`
Listing string `json:"listing"`
LotSize float64 `json:"lotSize"`
LowPrice float64 `json:"lowPrice"`
MaintMargin float64 `json:"maintMargin"`
MakerFee float64 `json:"makerFee"`
MarkMethod string `json:"markMethod"`
MarkPrice float64 `json:"markPrice"`
MaxOrderQty float64 `json:"maxOrderQty"`
MaxPrice float64 `json:"maxPrice"`
MidPrice float64 `json:"midPrice"`
Multiplier float64 `json:"multiplier"`
OpenInterest float64 `json:"openInterest"`
OpenValue float64 `json:"openValue"`
OpeningTimestamp time.Time `json:"openingTimestamp"`
OptionMultiplier float64 `json:"optionMultiplier"`
OptionStrikePcnt float64 `json:"optionStrikePcnt"`
OptionStrikePrice float64 `json:"optionStrikePrice"`
OptionStrikeRound float64 `json:"optionStrikeRound"`
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
PositionCurrency string `json:"positionCurrency"`
PrevClosePrice float64 `json:"prevClosePrice"`
PrevPrice24h float64 `json:"prevPrice24h"`
PrevTotalTurnover float64 `json:"prevTotalTurnover"`
PrevTotalVolume float64 `json:"prevTotalVolume"`
PublishInterval string `json:"publishInterval"`
PublishTime time.Time `json:"publishTime"`
QuoteCurrency string `json:"quoteCurrency"`
QuoteToSettleMultiplier int64 `json:"quoteToSettleMultiplier"`
RebalanceInterval string `json:"rebalanceInterval"`
RebalanceTimestamp time.Time `json:"rebalanceTimestamp"`
Reference string `json:"reference"`
ReferenceSymbol string `json:"referenceSymbol"`
RelistInterval string `json:"relistInterval"`
RiskLimit float64 `json:"riskLimit"`
RiskStep float64 `json:"riskStep"`
RootSymbol string `json:"rootSymbol"`
SellLeg string `json:"sellLeg"`
SessionInterval string `json:"sessionInterval"`
SettlementCurrency currency.Code `json:"settlCurrency"`
Settle string `json:"settle"`
SettledPrice float64 `json:"settledPrice"`
SettlementFee float64 `json:"settlementFee"`
State string `json:"state"`
Symbol string `json:"symbol"`
TakerFee float64 `json:"takerFee"`
Taxed bool `json:"taxed"`
TickSize float64 `json:"tickSize"`
Timestamp time.Time `json:"timestamp"`
TotalTurnover float64 `json:"totalTurnover"`
TotalVolume float64 `json:"totalVolume"`
Turnover float64 `json:"turnover"`
Turnover24h float64 `json:"turnover24h"`
Typ string `json:"typ"`
Underlying string `json:"underlying"`
UnderlyingSymbol string `json:"underlyingSymbol"`
UnderlyingToPositionMultiplier float64 `json:"underlyingToPositionMultiplier"`
UnderlyingToSettleMultiplier float64 `json:"underlyingToSettleMultiplier"`
Volume float64 `json:"volume"`
Volume24h float64 `json:"volume24h"`
Vwap float64 `json:"vwap"`
}
// InstrumentInterval instrument interval

View File

@@ -533,10 +533,9 @@ func (e *Exchange) GetHistoricTrades(ctx context.Context, p currency.Pair, asset
if err != nil {
return nil, err
}
limit := 1000
req := &GenericRequestParams{
Symbol: p.String(),
Count: int32(limit),
Count: countLimit,
EndTime: timestampEnd.UTC().Format("2006-01-02T15:04:05.000Z"),
}
ts := timestampStart
@@ -581,7 +580,7 @@ allTrades:
ts = tradeData[i].Timestamp
}
}
if len(tradeData) != limit {
if len(tradeData) != int(countLimit) {
break allTrades
}
}
@@ -984,25 +983,18 @@ func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Ite
if !e.SupportsAsset(item) || item == asset.Index {
return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, item)
}
marketInfo, err := e.GetInstruments(ctx, &GenericRequestParams{Reverse: true, Count: 500})
if err != nil {
return nil, err
}
resp := make([]futures.Contract, 0, len(marketInfo))
var resp []futures.Contract
switch item {
case asset.PerpetualContract:
marketInfo, err := e.GetInstruments(ctx, &GenericRequestParams{
Count: countLimit,
Filter: `{"typ": "` + perpetualContractID + `"}`,
})
if err != nil {
return nil, err
}
for x := range marketInfo {
if marketInfo[x].Typ != perpetualContractID {
continue
}
var cp, underlying currency.Pair
cp, err = currency.NewPairFromStrings(marketInfo[x].RootSymbol, marketInfo[x].QuoteCurrency)
if err != nil {
return nil, err
}
underlying, err = currency.NewPairFromStrings(marketInfo[x].RootSymbol, marketInfo[x].SettlCurrency)
cp, err := currency.NewPairFromStrings(marketInfo[x].RootSymbol, marketInfo[x].QuoteCurrency)
if err != nil {
return nil, err
}
@@ -1023,17 +1015,17 @@ func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Ite
contractSettlementType = futures.Inverse
}
resp = append(resp, futures.Contract{
Exchange: e.Name,
Name: cp,
Underlying: underlying,
Asset: item,
StartDate: s,
IsActive: marketInfo[x].State == "Open",
Status: marketInfo[x].State,
Type: futures.Perpetual,
SettlementType: contractSettlementType,
SettlementCurrencies: currency.Currencies{currency.NewCode(marketInfo[x].SettlCurrency)},
Multiplier: marketInfo[x].Multiplier,
Exchange: e.Name,
Name: cp,
Underlying: currency.NewPair(cp.Base, marketInfo[x].SettlementCurrency),
Asset: item,
StartDate: s,
IsActive: marketInfo[x].State == "Open",
Status: marketInfo[x].State,
Type: futures.Perpetual,
SettlementType: contractSettlementType,
SettlementCurrency: marketInfo[x].SettlementCurrency,
Multiplier: marketInfo[x].Multiplier,
LatestRate: fundingrate.Rate{
Time: marketInfo[x].FundingTimestamp,
Rate: decimal.NewFromFloat(marketInfo[x].FundingRate),
@@ -1041,16 +1033,16 @@ func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Ite
})
}
case asset.Futures:
marketInfo, err := e.GetInstruments(ctx, &GenericRequestParams{
Count: countLimit,
Filter: `{"typ": "` + futuresID + `"}`,
})
if err != nil {
return nil, err
}
for x := range marketInfo {
if marketInfo[x].Typ != futuresID {
continue
}
var cp, underlying currency.Pair
cp, err = currency.NewPairFromStrings(marketInfo[x].RootSymbol, marketInfo[x].Symbol[len(marketInfo[x].RootSymbol):])
if err != nil {
return nil, err
}
underlying, err = currency.NewPairFromStrings(marketInfo[x].RootSymbol, marketInfo[x].SettlCurrency)
cp, err := currency.NewPairFromStrings(marketInfo[x].RootSymbol, marketInfo[x].Symbol[len(marketInfo[x].RootSymbol):])
if err != nil {
return nil, err
}
@@ -1093,18 +1085,18 @@ func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Ite
contractSettlementType = futures.Quanto
}
resp = append(resp, futures.Contract{
Exchange: e.Name,
Name: cp,
Underlying: underlying,
Asset: item,
StartDate: startTime,
EndDate: endTime,
IsActive: marketInfo[x].State == "Open",
Status: marketInfo[x].State,
Type: ct,
SettlementCurrencies: currency.Currencies{currency.NewCode(marketInfo[x].SettlCurrency)},
Multiplier: marketInfo[x].Multiplier,
SettlementType: contractSettlementType,
Exchange: e.Name,
Name: cp,
Underlying: currency.NewPair(cp.Base, marketInfo[x].SettlementCurrency),
Asset: item,
StartDate: startTime,
EndDate: endTime,
IsActive: marketInfo[x].State == "Open",
Status: marketInfo[x].State,
Type: ct,
SettlementCurrency: marketInfo[x].SettlementCurrency,
Multiplier: marketInfo[x].Multiplier,
SettlementType: contractSettlementType,
})
}
}