This commit is contained in:
2026-05-10 23:23:38 +08:00
parent 00dac88290
commit 1ee43872fe
12 changed files with 357 additions and 266 deletions

View File

@@ -10,19 +10,19 @@ import (
"github.com/adshao/go-binance/v2"
)
// trySpotInitialEntry 视为空仓时按配置 OrderQty(基础币)市价买入,数量按 LOT_SIZE 向下取整。
// trySpotInitialEntry 视为空仓时按配置 OrderQtyUsdtUSDT 名义)市价买入,数量按现价换算后按 LOT_SIZE 向下取整。
func trySpotInitialEntry(ctx context.Context, client *binance.Client, balances []binance.Balance, w spotSymbol, st *models.SpotPosition, price float64) error {
want := w.OrderQty
wantUsdt := w.OrderQtyUsdt
order, qtyStr, err := executeSpotMarketBuy(ctx, client, balances, w, price)
if err != nil {
return err
}
applyBuyFill(st, order)
log.Printf("logic: %s 反弹≥%.2f%% 后初始建仓数量 %s (配置 %.8f), 成交均价约 %.4f", w.Symbol, buyReboundPct*100, qtyStr, want, st.AvgCostUSDT)
log.Printf("logic: %s 反弹≥%.2f%% 后初始建仓数量 %s (配置 %.2f USDT), 成交均价约 %.4f", w.Symbol, buyReboundPct*100, qtyStr, wantUsdt, st.AvgCostUSDT)
return nil
}
// trySpotDipAdd 相对当前均价达到第 (DipAddsDone+1) 档跌幅5%/15%/30%/50%)且未锁波段时,先等反弹 buyReboundPct 再按 OrderQty 买入;最多加仓 maxDipAdds 次。
// trySpotDipAdd 相对当前均价达到第 (DipAddsDone+1) 档跌幅5%/15%/30%/50%)且未锁波段时,先等反弹 buyReboundPct 再按 OrderQtyUsdt 买入;最多加仓 maxDipAdds 次。
func trySpotDipAdd(ctx context.Context, client *binance.Client, balances []binance.Balance, w spotSymbol, price float64, st *models.SpotPosition) error {
if st.DipAddsDone >= maxDipAdds {
return nil
@@ -43,7 +43,7 @@ func trySpotDipAdd(ctx context.Context, client *binance.Client, balances []binan
if !spotReboundReady(&st.DipReboundLow, price) {
return nil
}
want := w.OrderQty
wantUsdt := w.OrderQtyUsdt
order, qtyStr, err := executeSpotMarketBuy(ctx, client, balances, w, price)
if err != nil {
return err
@@ -53,13 +53,13 @@ func trySpotDipAdd(ctx context.Context, client *binance.Client, balances []binan
st.DipLegLocked = true
st.DipReboundLow = 0
resetSpotTrail(st)
log.Printf("logic: %s 第 %d 次超跌(跌幅%.0f%%)反弹≥%.2f%% 后加仓数量 %s (配置 %.8f), 新成本约 %.4f", w.Symbol, st.DipAddsDone, draw*100, buyReboundPct*100, qtyStr, want, st.AvgCostUSDT)
log.Printf("logic: %s 第 %d 次超跌(跌幅%.0f%%)反弹≥%.2f%% 后加仓数量 %s (配置 %.2f USDT), 新成本约 %.4f", w.Symbol, st.DipAddsDone, draw*100, buyReboundPct*100, qtyStr, wantUsdt, st.AvgCostUSDT)
return nil
}
// executeSpotMarketBuy 校验 USDT 后下市价买单FULL返回成交回报与已取整数量字符串。
func executeSpotMarketBuy(ctx context.Context, client *binance.Client, balances []binance.Balance, w spotSymbol, price float64) (*binance.CreateOrderResponse, string, error) {
qtyStr, _, err := spotBuyQtyString(w)
qtyStr, _, err := spotBuyQtyString(w, price)
if err != nil {
return nil, "", err
}
@@ -84,9 +84,12 @@ func executeSpotMarketBuy(ctx context.Context, client *binance.Client, balances
return order, qtyStr, nil
}
// spotBuyQtyString 将配置的 OrderQty 按交易对 LOT_SIZE 向下取整为下单字符串want 为配置原值
func spotBuyQtyString(w spotSymbol) (qtyStr string, want float64, err error) {
want = w.OrderQty
// spotBuyQtyString 将 OrderQtyUsdt 按现价换为基础币数量,再按 LOT_SIZE 向下取整为下单字符串want 为换算后的基础币数量(取整前)
func spotBuyQtyString(w spotSymbol, price float64) (qtyStr string, want float64, err error) {
if price <= 0 {
return "", 0, fmt.Errorf("%s: 现价无效,无法由 OrderQtyUsdt 换算数量", w.Symbol)
}
want = w.OrderQtyUsdt / price
step := spotLotStep(w.Symbol)
ok := false
qtyStr, ok, err = formatQtyToLotStep(want, step)
@@ -94,7 +97,7 @@ func spotBuyQtyString(w spotSymbol) (qtyStr string, want float64, err error) {
return "", want, err
}
if !ok {
return "", want, fmt.Errorf("%s: OrderQty=%g 按 LOT_SIZE(%s) 取整后为 0请调大数量或检查交易对", w.Symbol, want, step)
return "", want, fmt.Errorf("%s: OrderQtyUsdt=%g USDT 按现价与 LOT_SIZE(%s) 取整后为 0请调大 OrderQtyUsdt≥%.0f或检查交易对", w.Symbol, w.OrderQtyUsdt, step, minOrderQtyUsdt)
}
return qtyStr, want, nil
}