1\交易对返回价格
This commit is contained in:
@ -602,3 +602,29 @@ func (e LinePreOrder) QueryAiCoinPrice(c *gin.Context) {
|
||||
}
|
||||
e.OK(res, "操作成功")
|
||||
}
|
||||
|
||||
// 计算回本盈利比例
|
||||
func (e LinePreOrder) CalculateBreakEevenRatio(c *gin.Context) {
|
||||
s := service.LinePreOrder{}
|
||||
req := dto.CalculateBreakEevenRatioReq{}
|
||||
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
data := dto.CalculateBreakEvenRatioResp{}
|
||||
err = s.CalculateBreakEvenRatio(&req, &data)
|
||||
if err != nil {
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(data, "操作成功")
|
||||
}
|
||||
|
||||
@ -2,19 +2,22 @@ package models
|
||||
|
||||
import (
|
||||
"go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type LineSymbol struct {
|
||||
models.Model
|
||||
|
||||
ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 字典 exchange_type"`
|
||||
ApiId string `json:"apiId" gorm:"type:int;comment:api账户id"`
|
||||
Symbol string `json:"symbol" gorm:"type:varchar(32);comment:交易对"`
|
||||
BaseAsset string `json:"baseAsset" gorm:"type:varchar(255);comment:基础货币"`
|
||||
QuoteAsset string `json:"quoteAsset" gorm:"type:varchar(255);comment:计价货币"`
|
||||
Switch string `json:"switch" gorm:"type:enum('0','1');comment:状态"`
|
||||
Type string `json:"type" gorm:"type:enum('1','2');comment:交易对类型"`
|
||||
Number int `json:"number" gorm:"->"`
|
||||
ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 字典 exchange_type"`
|
||||
ApiId string `json:"apiId" gorm:"type:int;comment:api账户id"`
|
||||
Symbol string `json:"symbol" gorm:"type:varchar(32);comment:交易对"`
|
||||
BaseAsset string `json:"baseAsset" gorm:"type:varchar(255);comment:基础货币"`
|
||||
QuoteAsset string `json:"quoteAsset" gorm:"type:varchar(255);comment:计价货币"`
|
||||
Switch string `json:"switch" gorm:"type:enum('0','1');comment:状态"`
|
||||
Type string `json:"type" gorm:"type:enum('1','2');comment:交易对类型"`
|
||||
Number int `json:"number" gorm:"->"`
|
||||
LastPrice decimal.Decimal `json:"lastPrice"gorm:"->"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@ func registerLinePreOrderRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM
|
||||
r.GET("getOrderPage", actions.PermissionAction(), api.GetOrderPage) //订单列表
|
||||
r.POST("clearUnTriggered", actions.PermissionAction(), api.ClearUnTriggered) // 清除待触发的交易对
|
||||
r.POST("aiCoinPrice", actions.PermissionAction(), api.QueryAiCoinPrice) //获取aiCoin买入点
|
||||
|
||||
r.GET("/calculate", api.CalculateBreakEevenRatio) //计算亏损后止盈百分比
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -446,6 +446,29 @@ type QueryAiCoinPriceReq struct {
|
||||
Symbol string `json:"symbol"` //交易对
|
||||
}
|
||||
|
||||
// 计算亏损止盈百分比
|
||||
type CalculateBreakEevenRatioReq struct {
|
||||
Price decimal.Decimal `form:"price"`
|
||||
Symbol string `form:"symbol"` //交易对
|
||||
ExchangeType string `form:"exchangeType"` //交易所类型 字典exchange_type
|
||||
SymbolType int `form:"symbolType"`
|
||||
BuyPrice decimal.Decimal `form:"buyPrice"` //主单购买总金额
|
||||
LossBeginPercent decimal.Decimal `form:"lossBeginPercent"` //亏损开始百分比
|
||||
LossEndPercent decimal.Decimal `form:"lossEndPercent"` //亏损截至百分比
|
||||
AddPositionType int `form:"addPositionType"` //加仓类型 1-百分比 2-实际金额
|
||||
AddPositionVal decimal.Decimal `form:"addPositionVal"` //加仓金额
|
||||
ReducePercent decimal.Decimal `form:"reducePercent"` //减仓百分比
|
||||
RemainingQuantity decimal.Decimal `form:"remainingQuantity"` //剩余数量
|
||||
TotalLossAmountU decimal.Decimal `form:"totalLossAmountU"` //累计亏损金额
|
||||
}
|
||||
|
||||
// 计算亏损返回值
|
||||
type CalculateBreakEvenRatioResp struct {
|
||||
RemainingQuantity decimal.Decimal `json:"remainingQuantity"` //剩余数量
|
||||
Ratio decimal.Decimal `json:"ratio"` //亏损止盈百分比
|
||||
TotalLossAmountU decimal.Decimal `json:"totalLossAmountU"` //总亏损金额
|
||||
}
|
||||
|
||||
type SpotQueryOrderResp struct {
|
||||
Symbol string `json:"symbol"`
|
||||
OrderId int `json:"orderId"`
|
||||
|
||||
@ -1316,3 +1316,65 @@ func (e *LinePreOrder) QueryAiCoinPrice(req *dto.QueryAiCoinPriceReq) (models.Li
|
||||
err := e.Orm.Model(&models.LineDirection{}).Where("symbol = ?", req.Symbol).Find(&info).Error
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 计算亏损百分比
|
||||
func (e *LinePreOrder) CalculateBreakEvenRatio(req *dto.CalculateBreakEevenRatioReq, data *dto.CalculateBreakEvenRatioResp) error {
|
||||
var tradeSet models2.TradeSet
|
||||
|
||||
if req.LossEndPercent.Cmp(req.LossBeginPercent) < 0 {
|
||||
return errors.New("截至亏损百分比必须大于开始亏损百分比")
|
||||
}
|
||||
|
||||
if req.SymbolType == 1 {
|
||||
val, _ := helper.DefaultRedis.GetString(fmt.Sprintf(global.TICKER_SPOT, req.ExchangeType, req.Symbol))
|
||||
|
||||
sonic.Unmarshal([]byte(val), &tradeSet)
|
||||
} else if req.SymbolType == 2 {
|
||||
val, _ := helper.DefaultRedis.GetString(fmt.Sprintf(global.TICKER_FUTURES, req.ExchangeType, req.Symbol))
|
||||
|
||||
sonic.Unmarshal([]byte(val), &tradeSet)
|
||||
} else {
|
||||
return errors.New("symbolType error")
|
||||
}
|
||||
|
||||
if tradeSet.LastPrice == "" {
|
||||
return errors.New("没有找到交易对行情")
|
||||
}
|
||||
|
||||
var addPositionBuyPrice decimal.Decimal
|
||||
|
||||
if req.AddPositionType == 1 {
|
||||
addPositionBuyPrice = req.BuyPrice.Mul(req.AddPositionVal.Div(decimal.NewFromInt(100).Truncate(4))).Truncate(2)
|
||||
} else {
|
||||
addPositionBuyPrice = req.BuyPrice.Add(req.AddPositionVal).Truncate(2)
|
||||
}
|
||||
|
||||
var percentDiff decimal.Decimal
|
||||
var reduceAmount decimal.Decimal
|
||||
nowPrice := req.Price.Mul(decimal.NewFromInt(1).Sub(req.LossEndPercent.Div(decimal.NewFromInt(100).Truncate(4))))
|
||||
addPositionAmount := addPositionBuyPrice.Div(nowPrice).Truncate(int32(tradeSet.AmountDigit))
|
||||
|
||||
//计算价格下跌价差
|
||||
if req.LossEndPercent.Cmp(req.LossBeginPercent) > 0 {
|
||||
percentDiff = req.LossEndPercent.Sub(req.LossBeginPercent).Abs()
|
||||
}
|
||||
|
||||
totalAmount := req.RemainingQuantity.Add(addPositionAmount)
|
||||
lossAmountU := req.Price.Mul(percentDiff.Div(decimal.NewFromInt(100)).Truncate(4)).Mul(req.RemainingQuantity).Truncate(int32(tradeSet.AmountDigit))
|
||||
|
||||
//计算减仓数量
|
||||
if req.ReducePercent.Cmp(decimal.NewFromInt(0)) > 0 {
|
||||
reduceAmount = totalAmount.Mul(req.ReducePercent.Div(decimal.NewFromInt(100).Truncate(4))).Truncate(int32(tradeSet.AmountDigit))
|
||||
}
|
||||
|
||||
data.RemainingQuantity = totalAmount.Sub(reduceAmount)
|
||||
data.TotalLossAmountU = lossAmountU.Add(req.TotalLossAmountU)
|
||||
|
||||
//计算百分比
|
||||
if data.RemainingQuantity.Cmp(decimal.Zero) > 0 {
|
||||
data.Ratio = data.TotalLossAmountU.Div(data.RemainingQuantity).Div(nowPrice).Mul(decimal.NewFromInt(100)).Truncate(2)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@ -44,6 +44,35 @@ func (e *LineSymbol) GetPage(c *dto.LineSymbolGetPageReq, p *actions.DataPermiss
|
||||
e.Log.Errorf("LineSymbolService GetPage error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
var key string
|
||||
|
||||
if c.Type == "1" {
|
||||
key = fmt.Sprintf(global.TICKER_SPOT, c.ExchangeType, "*")
|
||||
} else {
|
||||
key = fmt.Sprintf(global.TICKER_FUTURES, c.ExchangeType, "*")
|
||||
}
|
||||
|
||||
tickers, _ := helper.DefaultRedis.GetAllKeysAndValues(key)
|
||||
allTicker := make(map[string]commonModels.TradeSet)
|
||||
tradeSet := commonModels.TradeSet{}
|
||||
|
||||
for _, v := range tickers {
|
||||
sonic.Unmarshal([]byte(v), &tradeSet)
|
||||
|
||||
if tradeSet.Coin != "" && tradeSet.Currency != "" {
|
||||
allTicker[tradeSet.Coin+tradeSet.Currency] = tradeSet
|
||||
}
|
||||
}
|
||||
|
||||
for index := range *list {
|
||||
symbol := (*list)[index].Symbol
|
||||
|
||||
if v, ok := allTicker[symbol]; ok {
|
||||
(*list)[index].LastPrice = utility.StrToDecimal(v.LastPrice)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"go-admin/common/global"
|
||||
"go-admin/common/helper"
|
||||
"go-admin/models"
|
||||
"go-admin/pkg/utility"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -233,7 +232,7 @@ func FuturesReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, futApi FutRes
|
||||
}
|
||||
|
||||
price := reduceOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.ReducePremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit))
|
||||
num := utility.StrToDecimal(takeOrder.Num).Truncate(int32(tradeSet.AmountDigit))
|
||||
num := reduceOrder.Num.Truncate(int32(tradeSet.AmountDigit))
|
||||
var positionSide string
|
||||
|
||||
if reduceOrder.Side == "BUY" {
|
||||
@ -338,7 +337,7 @@ func FutAddPositionTrigger(db *gorm.DB, v *AddPositionList, item string, futApi
|
||||
return
|
||||
}
|
||||
|
||||
price := v.Price
|
||||
price := v.Price.Truncate(int32(tradeSet.PriceDigit))
|
||||
num, _ := decimal.NewFromString(preOrder.Num)
|
||||
|
||||
if setting.AddPositionPremium.Cmp(decimal.Zero) > 0 {
|
||||
@ -351,7 +350,7 @@ func FutAddPositionTrigger(db *gorm.DB, v *AddPositionList, item string, futApi
|
||||
Side: v.Side,
|
||||
OrderType: "LIMIT",
|
||||
Price: price,
|
||||
Quantity: num,
|
||||
Quantity: num.Truncate(int32(tradeSet.AmountDigit)),
|
||||
NewClientOrderId: v.OrderSn,
|
||||
}
|
||||
preOrderVal, _ := sonic.MarshalString(&v)
|
||||
|
||||
@ -196,7 +196,7 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
takeProfitOrder.Rate = ext.ReduceTakeProfitRatio.String()
|
||||
//止盈需要累加之前的亏损
|
||||
if totalLossAmountU.Cmp(decimal.Zero) > 0 {
|
||||
percent := totalLossAmountU.Div(totalNum).Div(price).Sub(decimal.NewFromInt(1)).Abs()
|
||||
percent := totalLossAmountU.Div(totalNum).Div(price).Abs()
|
||||
takeProfitOrder.Rate = percent.Mul(decimal.NewFromInt(100)).Add(ext.ReduceTakeProfitRatio).Truncate(2).String()
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
//加仓待触发
|
||||
addPositionOrder := DbModels.LinePreOrder{}
|
||||
|
||||
if err := db.Model(&addPositionOrder).Where("main_id =? AND order_category=3 AND status=0", preOrder.MainId).First(addPositionOrder).Error; err != nil {
|
||||
if err := db.Model(&addPositionOrder).Where("main_id =? AND order_category=3 AND status=0", preOrder.MainId).First(&addPositionOrder).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
@ -301,7 +301,8 @@ func getFuturesPositionAvailableQuantity(db *gorm.DB, apiUserInfo DbModels.LineA
|
||||
if totalNum.Cmp(decimal.Zero) <= 0 {
|
||||
totalNum = utility.StrToDecimal(preOrder.Num)
|
||||
}
|
||||
return totalNum
|
||||
|
||||
return totalNum.Truncate(int32(tradeSet.AmountDigit))
|
||||
}
|
||||
|
||||
// 获取币安合约持仓
|
||||
@ -524,16 +525,16 @@ func createFutPreAddPosition(preOrder *DbModels.LinePreOrder, db *gorm.DB, trade
|
||||
var percentage decimal.Decimal
|
||||
|
||||
if data.Site == "BUY" {
|
||||
percentage = decimal.NewFromInt(1).Add(v.AddPositionPriceRatio.Div(decimal.NewFromInt(100)))
|
||||
} else {
|
||||
percentage = decimal.NewFromInt(1).Sub(v.AddPositionPriceRatio.Div(decimal.NewFromInt(100)))
|
||||
} else {
|
||||
percentage = decimal.NewFromInt(1).Add(v.AddPositionPriceRatio.Div(decimal.NewFromInt(100)))
|
||||
}
|
||||
|
||||
dataPrice := price.Mul(percentage).Truncate(int32(tradeSet.PriceDigit))
|
||||
data.Price = dataPrice.String()
|
||||
|
||||
if v.AddPositionType == 1 {
|
||||
data.Num = preOrder.Num
|
||||
data.Num = utility.StrToDecimal(preOrder.Num).Truncate(int32(tradeSet.AmountDigit)).String()
|
||||
data.BuyPrice = "0"
|
||||
} else {
|
||||
data.BuyPrice = v.AddPositionVal.String()
|
||||
@ -588,6 +589,7 @@ func makeFuturesTakeAndReduce(preOrder *DbModels.LinePreOrder, db *gorm.DB, trad
|
||||
profitOrder := models.LinePreOrder{}
|
||||
copier.Copy(&profitOrder, preOrder)
|
||||
|
||||
profitOrder.Id = 0
|
||||
profitOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
|
||||
profitOrder.Pid = preOrder.Id
|
||||
profitOrder.OrderType = 1
|
||||
@ -598,7 +600,7 @@ func makeFuturesTakeAndReduce(preOrder *DbModels.LinePreOrder, db *gorm.DB, trad
|
||||
|
||||
//止盈需要累加之前的亏损
|
||||
if totalLossAmountU.Cmp(decimal.Zero) > 0 {
|
||||
percent := totalLossAmountU.Div(num).Div(price).Sub(decimal.NewFromInt(1)).Abs()
|
||||
percent := totalLossAmountU.Div(num).Div(price).Abs()
|
||||
profitOrder.Rate = percent.Mul(decimal.NewFromInt(100)).Add(ext.TakeProfitRatio).Truncate(2).String()
|
||||
}
|
||||
|
||||
@ -617,6 +619,7 @@ func makeFuturesTakeAndReduce(preOrder *DbModels.LinePreOrder, db *gorm.DB, trad
|
||||
stopOrder := models.LinePreOrder{}
|
||||
copier.Copy(&stopOrder, preOrder)
|
||||
|
||||
stopOrder.Id = 0
|
||||
stopOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
|
||||
stopOrder.Pid = preOrder.Id
|
||||
stopOrder.MainId = ext.MainOrderId
|
||||
|
||||
@ -83,6 +83,13 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
|
||||
return
|
||||
}
|
||||
|
||||
//判断是否有已触发交易对
|
||||
count, _ := GetSymbolTriggerCount(db, v.Symbol, 2)
|
||||
|
||||
if count > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
price, _ := decimal.NewFromString(v.Price)
|
||||
num, _ := decimal.NewFromString(preOrder.Num)
|
||||
params := OrderPlacementService{
|
||||
@ -419,13 +426,6 @@ func SpotAddPositionTrigger(db *gorm.DB, v *AddPositionList, item string, spotAp
|
||||
return
|
||||
}
|
||||
|
||||
//判断是否有已触发交易对
|
||||
count, _ := GetSymbolTriggerCount(db, v.Symbol, 2)
|
||||
|
||||
if count > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
price := v.Price
|
||||
num, _ := decimal.NewFromString(preOrder.Num)
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
takeProfitOrder.Rate = ext.ReduceTakeProfitRatio.String()
|
||||
//止盈需要累加之前的亏损
|
||||
if totalLossAmountU.Cmp(decimal.Zero) > 0 {
|
||||
percent := totalLossAmountU.Div(totalNum).Div(price).Sub(decimal.NewFromInt(1)).Abs()
|
||||
percent := totalLossAmountU.Div(totalNum).Div(price).Abs()
|
||||
takeProfitOrder.Rate = percent.Mul(decimal.NewFromInt(100)).Add(ext.ReduceTakeProfitRatio).Truncate(2).String()
|
||||
}
|
||||
|
||||
@ -252,6 +252,12 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range orders {
|
||||
if item.OrderType == 2 {
|
||||
processStopLossOrder(item)
|
||||
}
|
||||
}
|
||||
|
||||
//计算实际亏损
|
||||
if parentOrder.Price != "" {
|
||||
parentPrice := utility.StrToDecimal(parentOrder.Price)
|
||||
@ -734,7 +740,7 @@ func makeSpotTakeAndReduce(preOrder *DbModels.LinePreOrder, db *gorm.DB, tradeSe
|
||||
|
||||
//止盈需要累加之前的亏损
|
||||
if totalLossAmountU.Cmp(decimal.Zero) > 0 {
|
||||
percent := totalLossAmountU.Div(num).Div(price).Sub(decimal.NewFromInt(1)).Abs()
|
||||
percent := totalLossAmountU.Div(num).Div(price).Abs()
|
||||
profitOrder.Rate = percent.Mul(decimal.NewFromInt(100)).Add(ext.TakeProfitRatio).Truncate(2).String()
|
||||
}
|
||||
|
||||
@ -874,6 +880,7 @@ func processStopLossOrder(order models.LinePreOrder) error {
|
||||
price := utility.StrToDecimal(order.Price)
|
||||
stopLoss := dto.StopLossRedisList{
|
||||
Id: order.Id,
|
||||
MainId: order.MainId,
|
||||
PId: order.Pid,
|
||||
ApiId: order.ApiId,
|
||||
OrderTye: order.OrderType,
|
||||
|
||||
Reference in New Issue
Block a user