package positionservice import ( "context" "fmt" "go-admin/common/const/rediskey" "go-admin/common/helper" "go-admin/common/service" "go-admin/models/positiondto" "time" "github.com/bytedance/sonic" "github.com/go-admin-team/go-admin-core/logger" "github.com/shopspring/decimal" ) type BinancePositionManagement struct { service.Service } // 保存仓位信息 // return 仓位信息 // return 错误信息 func (e *BinancePositionManagement) SavePosition(data *positiondto.PositionAddReq, exchangeType string) (positiondto.PositionDto, error) { var key string result := positiondto.PositionDto{} switch data.SymbolType { case 1: key = fmt.Sprintf(rediskey.SpotPosition, exchangeType, data.ApiId, data.Symbol, data.Side) case 2: key = fmt.Sprintf(rediskey.FuturePosition, exchangeType, data.ApiId, data.Symbol, data.Side) default: return result, fmt.Errorf("symbol type error") } lock := helper.NewRedisLock(fmt.Sprintf(rediskey.SpotPositionLock, data.ApiId, data.Symbol, data.Side), 200, 5, 200*time.Millisecond) if ok, err := lock.AcquireWait(context.Background()); err != nil { logger.Debug("获取锁失败", err) return result, err } else if ok { defer lock.Release() val, _ := helper.DefaultRedis.GetString(key) if val != "" { sonic.Unmarshal([]byte(val), &result) } if result.Symbol == "" { result.Symbol = data.Symbol result.Side = data.Side result.ApiId = data.ApiId result.SymbolType = data.SymbolType result.PositionSide = data.PositionSide } var totalLoss decimal.Decimal if result.LastPrice.Cmp(decimal.Zero) > 0 { switch { //多 买入 case data.PositionSide == "LONG": totalLoss = result.LastPrice.Sub(data.Price).Abs().Mul(result.Quantity) case data.PositionSide == "SHORT": totalLoss = data.Price.Sub(result.LastPrice).Abs().Mul(result.Quantity) } } result.LastPrice = data.Price result.TotalLoss = result.TotalLoss.Add(totalLoss) result.Quantity = data.Quantity.Add(result.Quantity) dataVal, _ := sonic.MarshalString(result) if err := helper.DefaultRedis.SetString(key, dataVal); err != nil { logger.Errorf("保存仓位信息失败,val:%s err:%v", dataVal, err) } } return result, nil } // 获取系统内仓位信息 func (e *BinancePositionManagement) GetPosition(apiId, symbolType int, exchangeTyp, symbol, side string) (positiondto.PositionDto, error) { result := positiondto.PositionDto{} var key string switch symbolType { case 1: key = fmt.Sprintf(rediskey.SpotPosition, exchangeTyp, apiId, symbol, side) case 2: key = fmt.Sprintf(rediskey.FuturePosition, exchangeTyp, apiId, symbol, side) default: return result, fmt.Errorf("symbol type error") } val, _ := helper.DefaultRedis.GetString(key) if val != "" { sonic.Unmarshal([]byte(val), &result) } return result, nil } // 移除仓位信息 func (e *BinancePositionManagement) RemovePosition(req *positiondto.LinePreOrderPositioinDelReq) error { var key string switch req.SymbolType { case 1: key = fmt.Sprintf(rediskey.SpotPosition, req.ExchangeType, req.ApiId, req.Symbol, req.Side) case 2: key = fmt.Sprintf(rediskey.FuturePosition, req.ExchangeType, req.ApiId, req.Symbol, req.Side) default: return fmt.Errorf("symbol type error") } return helper.DefaultRedis.DeleteString(key) }