Skip to content

Commit

Permalink
feat: update position stop loss trigger price
Browse files Browse the repository at this point in the history
  • Loading branch information
yubing744 committed Apr 20, 2024
1 parent 75aed68 commit 7d59bbc
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
3 changes: 3 additions & 0 deletions pkg/exchange/okex/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ func parseWebSocketEvent(in []byte) (interface{}, error) {
return orderTrade, nil

case ChannelPositions:
data, _ := json.Marshal(event.Data)
log.WithField("data", string(data)).Info("parseWebSocketEvent_PositionUpdateEvent_data")

var positionUpdateEvents []PositionUpdateEvent
err := json.Unmarshal(event.Data, &positionUpdateEvents)
if err != nil {
Expand Down
65 changes: 65 additions & 0 deletions pkg/exchange/okex/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/c9s/bbgo/pkg/exchange/okex/okexapi"
"github.com/c9s/bbgo/pkg/exchange/retry"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)

Expand Down Expand Up @@ -255,12 +256,76 @@ func (s *Stream) handleOrderDetailsEvent(orderTrades []OrderTradeEvent) {
}
}

func (e *Stream) QueryAlgoOpenOrders(ctx context.Context, symbol string) (orders []okexapi.AlgoOrder, err error) {
instrumentID := toLocalSymbol(symbol)

for {
if err := queryAlgoOpenOrderLimiter.Wait(ctx); err != nil {
return nil, fmt.Errorf("query open orders rate limiter wait error: %w", err)
}

req := e.client.NewGetOCOAlgoOrdersRequest()
req.
InstrumentID(instrumentID)

params, _ := req.GetQueryParameters()
log.WithField("symbol", symbol).
WithField("params", params).
Info("QueryAlgoOpenOrders_start")

orders, err = req.Do(ctx)
if err != nil {
return nil, fmt.Errorf("failed to query open orders: %w", err)
}

log.WithField("symbol", symbol).
WithField("openOrders", orders).
Info("QueryAlgoOpenOrders_result")

orderLen := len(orders)
// a defensive programming to ensure the length of order response is expected.
if orderLen > defaultQueryLimit {
return nil, fmt.Errorf("unexpected open orders length %d", orderLen)
}

if orderLen < defaultQueryLimit {
break
}
}

return orders, err
}

func (s *Stream) handlePositionDetailsEvent(positionDetails []PositionUpdateEvent) {

for _, positionDetail := range positionDetails {
position, err := positionDetail.toGlobalPosition()
if err != nil {
log.WithError(err).Errorf("error converting position details into positions")
} else {
orders, err := s.QueryAlgoOpenOrders(context.Background(), position.Symbol)
if err != nil {
log.WithError(err).Error("handlePositionDetailsEvent_QueryAlgoOpenOrders_error")
}

if len(orders) > 0 {
algoOrder := orders[0]

slTriggerPx, err := fixedpoint.NewFromString(algoOrder.SlTriggerPx)
if err != nil {
position.SlTriggerPxType = algoOrder.SlTriggerPxType
position.SlOrdPx = algoOrder.SlOrdPx
position.SlTriggerPx = &slTriggerPx
}

tpTriggerPx, err := fixedpoint.NewFromString(algoOrder.TpTriggerPx)
if err != nil {
position.TpTriggerPxType = algoOrder.TpTriggerPxType
position.TpOrdPx = algoOrder.TpOrdPx
position.TpTriggerPx = &tpTriggerPx
}
}

s.EmitPositionUpdate(position)
}
}
Expand Down
28 changes: 26 additions & 2 deletions pkg/types/position.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ type PositionInfo struct {
AverageCost fixedpoint.Value `json:"averageCost" db:"average_cost"`
TradeID uint64 `json:"tradeId" db:"trade_id"`

// for update Take-profit and stop-loss
TpTriggerPx *fixedpoint.Value `json:"tpTriggerPx"`
TpTriggerPxType string `json:"tpTriggerPxType"`
TpOrdPx string `json:"tpOrdPx"`
SlTriggerPx *fixedpoint.Value `json:"slTriggerPx"`
SlTriggerPxType string `json:"slTriggerPxType"`
SlOrdPx string `json:"slOrdPx"`

OpenedAt time.Time `json:"openedAt,omitempty" db:"-"`
ChangedAt time.Time `json:"changedAt,omitempty" db:"changed_at"`
}
Expand Down Expand Up @@ -85,8 +93,12 @@ type Position struct {
ttl time.Duration

// for update Take-profit and stop-loss
TpTriggerPx *fixedpoint.Value
SlTriggerPx *fixedpoint.Value
TpTriggerPx *fixedpoint.Value `json:"tpTriggerPx"`
TpTriggerPxType string `json:"tpTriggerPxType"`
TpOrdPx string `json:"tpOrdPx"`
SlTriggerPx *fixedpoint.Value `json:"slTriggerPx"`
SlTriggerPxType string `json:"slTriggerPxType"`
SlOrdPx string `json:"slOrdPx"`
}

func (s *Position) SetTTL(ttl time.Duration) {
Expand Down Expand Up @@ -270,6 +282,18 @@ func (p *Position) Update(pos PositionInfo) bool {
p.TradeID = pos.TradeID
p.ChangedAt = pos.ChangedAt

if pos.SlTriggerPx != nil {
p.SlTriggerPx = pos.SlTriggerPx
p.SlTriggerPxType = pos.SlTriggerPxType
p.SlOrdPx = pos.SlOrdPx
}

if pos.TpTriggerPx != nil {
p.TpTriggerPx = pos.TpTriggerPx
p.TpTriggerPxType = pos.TpTriggerPxType
p.TpOrdPx = pos.TpOrdPx
}

p.EmitModify(p.Base, p.Quote, p.AverageCost)
return true
}
Expand Down

0 comments on commit 7d59bbc

Please sign in to comment.