mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
Merge pull request #1690 from c9s/c9s/xdepthmaker/convert-hedge-order-trades
FEATURE: improve trade/order converter
This commit is contained in:
commit
4925d8bfd9
85
pkg/core/converter.go
Normal file
85
pkg/core/converter.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Converter interface {
|
||||||
|
OrderConverter
|
||||||
|
TradeConverter
|
||||||
|
Initialize() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrderConverter converts the order to another order
|
||||||
|
type OrderConverter interface {
|
||||||
|
ConvertOrder(order types.Order) (types.Order, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TradeConverter converts the trade to another trade
|
||||||
|
type TradeConverter interface {
|
||||||
|
ConvertTrade(trade types.Trade) (types.Trade, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderConvertFunc func(order types.Order) (types.Order, error)
|
||||||
|
type TradeConvertFunc func(trade types.Trade) (types.Trade, error)
|
||||||
|
|
||||||
|
type DynamicConverter struct {
|
||||||
|
orderConverter OrderConvertFunc
|
||||||
|
tradeConverter TradeConvertFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDynamicConverter(orderConverter OrderConvertFunc, tradeConverter TradeConvertFunc) *DynamicConverter {
|
||||||
|
return &DynamicConverter{orderConverter: orderConverter, tradeConverter: tradeConverter}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DynamicConverter) Initialize() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DynamicConverter) ConvertOrder(order types.Order) (types.Order, error) {
|
||||||
|
return c.orderConverter(order)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DynamicConverter) ConvertTrade(trade types.Trade) (types.Trade, error) {
|
||||||
|
return c.tradeConverter(trade)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SymbolConverter converts the symbol to another symbol
|
||||||
|
type SymbolConverter struct {
|
||||||
|
FromSymbol string `json:"from"`
|
||||||
|
ToSymbol string `json:"to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSymbolConverter(fromSymbol, toSymbol string) *SymbolConverter {
|
||||||
|
return &SymbolConverter{FromSymbol: fromSymbol, ToSymbol: toSymbol}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SymbolConverter) Initialize() error {
|
||||||
|
if c.ToSymbol == "" {
|
||||||
|
return errors.New("toSymbol can not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.FromSymbol == "" {
|
||||||
|
return errors.New("fromSymbol can not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SymbolConverter) ConvertOrder(order types.Order) (types.Order, error) {
|
||||||
|
if order.Symbol == c.FromSymbol {
|
||||||
|
order.Symbol = c.ToSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
return order, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SymbolConverter) ConvertTrade(trade types.Trade) (types.Trade, error) {
|
||||||
|
if trade.Symbol == c.FromSymbol {
|
||||||
|
trade.Symbol = c.ToSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
return trade, nil
|
||||||
|
}
|
31
pkg/core/converter_test.go
Normal file
31
pkg/core/converter_test.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSymbolConverter(t *testing.T) {
|
||||||
|
converter := NewSymbolConverter("MAXEXCHANGEUSDT", "MAXUSDT")
|
||||||
|
trade, err := converter.ConvertTrade(types.Trade{
|
||||||
|
Symbol: "MAXEXCHANGEUSDT",
|
||||||
|
})
|
||||||
|
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, "MAXUSDT", trade.Symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
order, err := converter.ConvertOrder(types.Order{
|
||||||
|
SubmitOrder: types.SubmitOrder{
|
||||||
|
Symbol: "MAXEXCHANGEUSDT",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, "MAXUSDT", order.Symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,8 +12,87 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TradeConverter interface {
|
type ConverterSetting struct {
|
||||||
Convert(trade types.Trade) (types.Trade, error)
|
SymbolConverter *SymbolConverter `json:"symbolConverter" yaml:"symbolConverter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConverterSetting) getConverter() Converter {
|
||||||
|
if s.SymbolConverter != nil {
|
||||||
|
return s.SymbolConverter
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConverterSetting) InitializeConverter() (Converter, error) {
|
||||||
|
converter := s.getConverter()
|
||||||
|
if converter == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("initializing converter %T ...", converter)
|
||||||
|
err := converter.Initialize()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConverterManager struct {
|
||||||
|
ConverterSettings []ConverterSetting `json:"converters,omitempty" yaml:"converters,omitempty"`
|
||||||
|
|
||||||
|
converters []Converter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConverterManager) Initialize() error {
|
||||||
|
for _, setting := range c.ConverterSettings {
|
||||||
|
|
||||||
|
converter, err := setting.InitializeConverter()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AddConverter(converter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConverterManager) AddConverter(converter Converter) {
|
||||||
|
c.converters = append(c.converters, converter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConverterManager) ConvertOrder(order types.Order) types.Order {
|
||||||
|
if len(c.converters) == 0 {
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, converter := range c.converters {
|
||||||
|
convOrder, err := converter.ConvertOrder(order)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Errorf("converter %+v error, order: %s", converter, order.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
order = convOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConverterManager) ConvertTrade(trade types.Trade) types.Trade {
|
||||||
|
if len(c.converters) == 0 {
|
||||||
|
return trade
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, converter := range c.converters {
|
||||||
|
convTrade, err := converter.ConvertTrade(trade)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Errorf("converter %+v error, trade: %s", converter, trade.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
trade = convTrade
|
||||||
|
}
|
||||||
|
|
||||||
|
return trade
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate callbackgen -type TradeCollector
|
//go:generate callbackgen -type TradeCollector
|
||||||
|
@ -29,14 +108,14 @@ type TradeCollector struct {
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
tradeConverters []TradeConverter
|
|
||||||
|
|
||||||
recoverCallbacks []func(trade types.Trade)
|
recoverCallbacks []func(trade types.Trade)
|
||||||
|
|
||||||
tradeCallbacks []func(trade types.Trade, profit, netProfit fixedpoint.Value)
|
tradeCallbacks []func(trade types.Trade, profit, netProfit fixedpoint.Value)
|
||||||
|
|
||||||
positionUpdateCallbacks []func(position *types.Position)
|
positionUpdateCallbacks []func(position *types.Position)
|
||||||
profitCallbacks []func(trade types.Trade, profit *types.Profit)
|
profitCallbacks []func(trade types.Trade, profit *types.Profit)
|
||||||
|
|
||||||
|
ConverterManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTradeCollector(symbol string, position *types.Position, orderStore *OrderStore) *TradeCollector {
|
func NewTradeCollector(symbol string, position *types.Position, orderStore *OrderStore) *TradeCollector {
|
||||||
|
@ -55,28 +134,6 @@ func NewTradeCollector(symbol string, position *types.Position, orderStore *Orde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TradeCollector) AddTradeConverter(converter TradeConverter) {
|
|
||||||
c.tradeConverters = append(c.tradeConverters, converter)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TradeCollector) convertTrade(trade types.Trade) types.Trade {
|
|
||||||
if len(c.tradeConverters) == 0 {
|
|
||||||
return trade
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, converter := range c.tradeConverters {
|
|
||||||
convTrade, err := converter.Convert(trade)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Errorf("trade %+v converter error, trade: %s", converter, trade.String())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
trade = convTrade
|
|
||||||
}
|
|
||||||
|
|
||||||
return trade
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderStore returns the order store used by the trade collector
|
// OrderStore returns the order store used by the trade collector
|
||||||
func (c *TradeCollector) OrderStore() *OrderStore {
|
func (c *TradeCollector) OrderStore() *OrderStore {
|
||||||
return c.orderStore
|
return c.orderStore
|
||||||
|
@ -108,7 +165,7 @@ func (c *TradeCollector) BindStreamForBackground(stream types.Stream) {
|
||||||
|
|
||||||
func (c *TradeCollector) BindStream(stream types.Stream) {
|
func (c *TradeCollector) BindStream(stream types.Stream) {
|
||||||
stream.OnTradeUpdate(func(trade types.Trade) {
|
stream.OnTradeUpdate(func(trade types.Trade) {
|
||||||
c.processTrade(trade)
|
c.ProcessTrade(trade)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +201,7 @@ func (c *TradeCollector) Recover(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TradeCollector) RecoverTrade(td types.Trade) bool {
|
func (c *TradeCollector) RecoverTrade(td types.Trade) bool {
|
||||||
td = c.convertTrade(td)
|
td = c.ConvertTrade(td)
|
||||||
|
|
||||||
logrus.Debugf("checking trade: %s", td.String())
|
logrus.Debugf("checking trade: %s", td.String())
|
||||||
if c.processTrade(td) {
|
if c.processTrade(td) {
|
||||||
|
@ -260,7 +317,7 @@ func (c *TradeCollector) processTrade(trade types.Trade) bool {
|
||||||
// return true when the given trade is added
|
// return true when the given trade is added
|
||||||
// return false when the given trade is not added
|
// return false when the given trade is not added
|
||||||
func (c *TradeCollector) ProcessTrade(trade types.Trade) bool {
|
func (c *TradeCollector) ProcessTrade(trade types.Trade) bool {
|
||||||
return c.processTrade(c.convertTrade(trade))
|
return c.processTrade(c.ConvertTrade(trade))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run is a goroutine executed in the background
|
// Run is a goroutine executed in the background
|
||||||
|
@ -279,7 +336,7 @@ func (c *TradeCollector) Run(ctx context.Context) {
|
||||||
c.Process()
|
c.Process()
|
||||||
|
|
||||||
case trade := <-c.tradeC:
|
case trade := <-c.tradeC:
|
||||||
c.processTrade(c.convertTrade(trade))
|
c.processTrade(c.ConvertTrade(trade))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
"github.com/c9s/bbgo/pkg/core"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/batch"
|
"github.com/c9s/bbgo/pkg/exchange/batch"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
@ -22,6 +23,8 @@ type ProfitFixerConfig struct {
|
||||||
// ProfitFixer implements a trade-history-based profit fixer
|
// ProfitFixer implements a trade-history-based profit fixer
|
||||||
type ProfitFixer struct {
|
type ProfitFixer struct {
|
||||||
sessions map[string]types.ExchangeTradeHistoryService
|
sessions map[string]types.ExchangeTradeHistoryService
|
||||||
|
|
||||||
|
core.ConverterManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProfitFixer() *ProfitFixer {
|
func NewProfitFixer() *ProfitFixer {
|
||||||
|
@ -106,6 +109,8 @@ func (f *ProfitFixer) Fix(
|
||||||
|
|
||||||
func (f *ProfitFixer) FixFromTrades(allTrades []types.Trade, stats *types.ProfitStats, position *types.Position) error {
|
func (f *ProfitFixer) FixFromTrades(allTrades []types.Trade, stats *types.ProfitStats, position *types.Position) error {
|
||||||
for _, trade := range allTrades {
|
for _, trade := range allTrades {
|
||||||
|
trade = f.ConverterManager.ConvertTrade(trade)
|
||||||
|
|
||||||
profit, netProfit, madeProfit := position.AddTrade(trade)
|
profit, netProfit, madeProfit := position.AddTrade(trade)
|
||||||
if madeProfit {
|
if madeProfit {
|
||||||
p := position.NewProfit(trade, profit, netProfit)
|
p := position.NewProfit(trade, profit, netProfit)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
"github.com/c9s/bbgo/pkg/core"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/retry"
|
"github.com/c9s/bbgo/pkg/exchange/retry"
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/strategy/common"
|
"github.com/c9s/bbgo/pkg/strategy/common"
|
||||||
|
@ -48,6 +49,9 @@ type CrossExchangeMarketMakingStrategy struct {
|
||||||
Position *types.Position `json:"position,omitempty" persistence:"position"`
|
Position *types.Position `json:"position,omitempty" persistence:"position"`
|
||||||
ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"`
|
ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"`
|
||||||
CoveredPosition fixedpoint.Value `json:"coveredPosition,omitempty" persistence:"covered_position"`
|
CoveredPosition fixedpoint.Value `json:"coveredPosition,omitempty" persistence:"covered_position"`
|
||||||
|
|
||||||
|
core.ConverterManager
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
MakerOrderExecutor, HedgeOrderExecutor *bbgo.GeneralOrderExecutor
|
MakerOrderExecutor, HedgeOrderExecutor *bbgo.GeneralOrderExecutor
|
||||||
|
@ -78,6 +82,10 @@ func (s *CrossExchangeMarketMakingStrategy) Initialize(
|
||||||
return fmt.Errorf("maker session market %s is not defined", symbol)
|
return fmt.Errorf("maker session market %s is not defined", symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.ConverterManager.Initialize(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if s.ProfitStats == nil {
|
if s.ProfitStats == nil {
|
||||||
s.ProfitStats = types.NewProfitStats(s.makerMarket)
|
s.ProfitStats = types.NewProfitStats(s.makerMarket)
|
||||||
}
|
}
|
||||||
|
@ -106,6 +114,10 @@ func (s *CrossExchangeMarketMakingStrategy) Initialize(
|
||||||
s.makerMarket.Symbol,
|
s.makerMarket.Symbol,
|
||||||
strategyID, instanceID,
|
strategyID, instanceID,
|
||||||
s.Position)
|
s.Position)
|
||||||
|
|
||||||
|
// update converter manager
|
||||||
|
s.MakerOrderExecutor.TradeCollector().ConverterManager = s.ConverterManager
|
||||||
|
|
||||||
s.MakerOrderExecutor.BindEnvironment(environ)
|
s.MakerOrderExecutor.BindEnvironment(environ)
|
||||||
s.MakerOrderExecutor.BindProfitStats(s.ProfitStats)
|
s.MakerOrderExecutor.BindProfitStats(s.ProfitStats)
|
||||||
s.MakerOrderExecutor.Bind()
|
s.MakerOrderExecutor.Bind()
|
||||||
|
@ -121,6 +133,9 @@ func (s *CrossExchangeMarketMakingStrategy) Initialize(
|
||||||
s.HedgeOrderExecutor.BindEnvironment(environ)
|
s.HedgeOrderExecutor.BindEnvironment(environ)
|
||||||
s.HedgeOrderExecutor.BindProfitStats(s.ProfitStats)
|
s.HedgeOrderExecutor.BindProfitStats(s.ProfitStats)
|
||||||
s.HedgeOrderExecutor.Bind()
|
s.HedgeOrderExecutor.Bind()
|
||||||
|
|
||||||
|
s.HedgeOrderExecutor.TradeCollector().ConverterManager = s.ConverterManager
|
||||||
|
|
||||||
s.HedgeOrderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) {
|
s.HedgeOrderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) {
|
||||||
// bbgo.Sync(ctx, s)
|
// bbgo.Sync(ctx, s)
|
||||||
})
|
})
|
||||||
|
@ -149,6 +164,7 @@ type Strategy struct {
|
||||||
|
|
||||||
Environment *bbgo.Environment
|
Environment *bbgo.Environment
|
||||||
|
|
||||||
|
// Symbol is the maker exchange symbol
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
|
|
||||||
// HedgeSymbol is the symbol for the hedge exchange
|
// HedgeSymbol is the symbol for the hedge exchange
|
||||||
|
@ -251,6 +267,7 @@ func (s *Strategy) CrossSubscribe(sessions map[string]*bbgo.ExchangeSession) {
|
||||||
})
|
})
|
||||||
|
|
||||||
hedgeSession.Subscribe(types.KLineChannel, s.HedgeSymbol, types.SubscribeOptions{Interval: "1m"})
|
hedgeSession.Subscribe(types.KLineChannel, s.HedgeSymbol, types.SubscribeOptions{Interval: "1m"})
|
||||||
|
|
||||||
makerSession.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: "1m"})
|
makerSession.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: "1m"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +361,8 @@ func (s *Strategy) CrossRun(
|
||||||
s.CrossExchangeMarketMakingStrategy.ProfitStats = types.NewProfitStats(makerMarket)
|
s.CrossExchangeMarketMakingStrategy.ProfitStats = types.NewProfitStats(makerMarket)
|
||||||
|
|
||||||
fixer := common.NewProfitFixer()
|
fixer := common.NewProfitFixer()
|
||||||
|
fixer.ConverterManager = s.ConverterManager
|
||||||
|
|
||||||
if ss, ok := makerSession.Exchange.(types.ExchangeTradeHistoryService); ok {
|
if ss, ok := makerSession.Exchange.(types.ExchangeTradeHistoryService); ok {
|
||||||
log.Infof("adding makerSession %s to profitFixer", makerSession.Name)
|
log.Infof("adding makerSession %s to profitFixer", makerSession.Name)
|
||||||
fixer.AddExchange(makerSession.Name, ss)
|
fixer.AddExchange(makerSession.Name, ss)
|
||||||
|
|
|
@ -19,16 +19,19 @@ const (
|
||||||
PositionClosed = PositionType("Closed")
|
PositionClosed = PositionType("Closed")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ExchangeFee stores the exchange fee rate
|
||||||
type ExchangeFee struct {
|
type ExchangeFee struct {
|
||||||
MakerFeeRate fixedpoint.Value
|
MakerFeeRate fixedpoint.Value
|
||||||
TakerFeeRate fixedpoint.Value
|
TakerFeeRate fixedpoint.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PositionRisk stores the position risk data
|
||||||
type PositionRisk struct {
|
type PositionRisk struct {
|
||||||
Leverage fixedpoint.Value `json:"leverage"`
|
Leverage fixedpoint.Value `json:"leverage,omitempty"`
|
||||||
LiquidationPrice fixedpoint.Value `json:"liquidationPrice"`
|
LiquidationPrice fixedpoint.Value `json:"liquidationPrice,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Position stores the position data
|
||||||
type Position struct {
|
type Position struct {
|
||||||
Symbol string `json:"symbol" db:"symbol"`
|
Symbol string `json:"symbol" db:"symbol"`
|
||||||
BaseCurrency string `json:"baseCurrency" db:"base"`
|
BaseCurrency string `json:"baseCurrency" db:"base"`
|
||||||
|
@ -281,8 +284,14 @@ type FuturesPosition struct {
|
||||||
ExchangeFeeRates map[ExchangeName]ExchangeFee `json:"exchangeFeeRates"`
|
ExchangeFeeRates map[ExchangeName]ExchangeFee `json:"exchangeFeeRates"`
|
||||||
|
|
||||||
// Futures data fields
|
// Futures data fields
|
||||||
|
// -------------------
|
||||||
|
// Isolated margin mode
|
||||||
Isolated bool `json:"isolated"`
|
Isolated bool `json:"isolated"`
|
||||||
|
|
||||||
|
// UpdateTime is the time when the position is updated
|
||||||
UpdateTime int64 `json:"updateTime"`
|
UpdateTime int64 `json:"updateTime"`
|
||||||
|
|
||||||
|
// PositionRisk stores the position risk data
|
||||||
PositionRisk *PositionRisk
|
PositionRisk *PositionRisk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user