62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
package logic
|
||
|
||
import (
|
||
"context"
|
||
"strconv"
|
||
|
||
"git.apinb.com/quant/coin/internal/impl"
|
||
"git.apinb.com/quant/coin/internal/models"
|
||
"github.com/adshao/go-binance/v2"
|
||
"github.com/shopspring/decimal"
|
||
)
|
||
|
||
var (
|
||
CloseCache = make(map[string]float64)
|
||
)
|
||
|
||
// trySpotRallySell 跟踪止盈:浮盈≥profitArmPct 后记录阶段峰值 PnL;继续上涨则刷新峰值;
|
||
// 当未实现盈亏较峰值回落≥gridStartPct 时市价卖出(数量来自 RefreshAccount 写入的 account[sym])。
|
||
func trySpotRallySell(pos *models.SpotPosition, pnlPct float64, price float64) error {
|
||
if val, ok := CloseCache[pos.Symbol]; !ok || val == 0 {
|
||
CloseCache[pos.Symbol] = pnlPct
|
||
return nil
|
||
}
|
||
|
||
if pnlPct >= CloseCache[pos.Symbol] {
|
||
CloseCache[pos.Symbol] = pnlPct
|
||
return nil
|
||
}
|
||
|
||
if CloseCache[pos.Symbol]-pnlPct < gridStartPct {
|
||
return nil
|
||
}
|
||
|
||
// 取到持仓数量
|
||
qty := GetAccount(pos.Symbol)
|
||
qtyStr := strconv.FormatFloat(qty, 'f', -1, 64)
|
||
|
||
ctx := context.Background()
|
||
order, err := BinanceClient.NewCreateOrderService().
|
||
Symbol(pos.Symbol).
|
||
Side(binance.SideTypeSell).
|
||
Type(binance.OrderTypeMarket).
|
||
Quantity(qtyStr).
|
||
NewOrderRespType(binance.NewOrderRespTypeRESULT).
|
||
Do(ctx)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
pos.SellQuantity += parseFloat(order.ExecutedQuantity)
|
||
pos.SellPrice = decimal.NewFromFloat(price).Round(2).InexactFloat64()
|
||
pos.Status = 1
|
||
impl.DBService.Save(pos)
|
||
|
||
// 更新缓存
|
||
loadPortfolio()
|
||
|
||
CloseCache[pos.Symbol] = 0
|
||
|
||
return nil
|
||
}
|