deving
This commit is contained in:
89
internal/logic/open.go
Normal file
89
internal/logic/open.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.apinb.com/quant/coin/internal/impl"
|
||||
"git.apinb.com/quant/coin/internal/models"
|
||||
binance "github.com/adshao/go-binance/v2"
|
||||
)
|
||||
|
||||
// OpenPosition 按交易对用配置的 OrderQtyUsdt 市价买入首笔;更新内存、写入数据库并 loadPortfolio 刷新持仓缓存。
|
||||
// 若链上可用基础币名义已达「有仓」阈值则只同步数量与成本写库,不再重复下单。
|
||||
func CreateNewSpotPosition(symbol string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := RefreshAccount(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
account := GetAccount("USDT")
|
||||
if account <= 10 {
|
||||
return errors.New("USDT 余额不足")
|
||||
}
|
||||
}
|
||||
|
||||
qty, err := CalculateQty(symbol)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
order, err := BinanceClient.NewCreateOrderService().
|
||||
Symbol(symbol).
|
||||
Side(binance.SideTypeBuy).
|
||||
Type(binance.OrderTypeMarket).
|
||||
Quantity(qty).
|
||||
NewOrderRespType(binance.NewOrderRespTypeRESULT).
|
||||
Do(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
position := &models.SpotPosition{
|
||||
BaseAsset: spotBaseFromSymbol(symbol),
|
||||
Symbol: symbol,
|
||||
Quantity: parseFloat(order.ExecutedQuantity),
|
||||
AvgCostUSDT: parseFloat(order.Price),
|
||||
}
|
||||
|
||||
if err := impl.DBService.Create(position).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := loadPortfolio(); err != nil {
|
||||
log.Printf("logic: OpenPosition 刷新持仓缓存失败: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CalculateQty(symbol string) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
defer cancel()
|
||||
prices, err := BinanceClient.NewListPricesService().Symbol(symbol).Do(ctx)
|
||||
if err != nil || len(prices) == 0 {
|
||||
return "", err
|
||||
}
|
||||
price, err := strconv.ParseFloat(prices[0].Price, 64)
|
||||
if err != nil || price <= 0 {
|
||||
return "", errors.New("现价无效")
|
||||
}
|
||||
cfg := getSymbolInfo(symbol)
|
||||
if cfg == nil {
|
||||
return "", errors.New("交易对不存在")
|
||||
}
|
||||
want := InvestUsdt[cfg.Symbol] / price
|
||||
step := cfg.LotSizeFilter().StepSize
|
||||
qtyStr, ok, err := formatQtyToLotStep(want, step)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !ok {
|
||||
return "", errors.New("数量不足")
|
||||
}
|
||||
return qtyStr, nil
|
||||
}
|
||||
Reference in New Issue
Block a user