Files
nofx/trader
ZhouYongyou 75932b0bc8 fix(trader+decision): prevent quantity=0 error with min notional checks
## Problem (Bug Report)
User encountered API error when opening BTC position:
- Account equity: 9.20 USDT
- AI suggested: ~7.36 USDT position
- Error: `code=-4003, msg=Quantity less than or equal to zero.`

## Root Cause Analysis

### Issue 1: Quantity Truncated to 0
```
quantity = 7.36 / 101808.2 ≈ 0.00007228 BTC
formatted (%.3f) → "0.000"  Rounded down to 0!
```

BTCUSDT precision is 3 decimals (stepSize=0.001), causing small quantities to round to 0.

### Issue 2: Missing CheckMinNotional in Open Methods
-  CloseLong() and CloseShort() have CheckMinNotional()
-  OpenLong() and OpenShort() **missing** CheckMinNotional()

### Issue 3: No Minimum Position Size Validation
- AI could suggest position_size_usd < minimum notional value
- No validation prevented tiny positions that would fail

---

## Fixes Applied

### 1. trader/binance_futures.go

**OpenLong() and OpenShort()** - Added two checks:

```go
//  Check if formatted quantity became 0 (rounding issue)
quantityFloat, _ := strconv.ParseFloat(quantityStr, 64)
if quantityFloat <= 0 {
    return error("Quantity too small, formatted to 0...")
}

//  Check minimum notional value (Binance requires ≥10 USDT)
if err := t.CheckMinNotional(symbol, quantityFloat); err != nil {
    return err
}
```

**Impact**: Prevents API errors by catching invalid quantities before submission.

---

### 2. decision/engine.go - validateDecision()

Added minimum position size validation:

```go
const minPositionSizeGeneral = 15.0   // Altcoins
const minPositionSizeBTCETH = 100.0   // BTC/ETH (high price + precision limits)

if symbol == BTC/ETH && position_size_usd < 100 {
    return error("BTC/ETH requires ≥100 USDT to avoid rounding to 0")
}
if position_size_usd < 15 {
    return error("Position size must be ≥15 USDT (min notional requirement)")
}
```

**Impact**: Rejects invalid decisions before execution, saving API calls.

---

### 3. decision/engine.go - buildSystemPrompt()

Updated hard constraints in AI prompt:

```
6. 最小开仓金额: **BTC/ETH ≥100 USDT | 山寨币 ≥15 USDT**
   (⚠️ 低于此金额会因精度问题导致开仓失败)
```

**Impact**: AI proactively avoids suggesting too-small positions.

---

## Testing

### Before Fix
-  User equity 9.20 USDT → suggested 7.36 USDT BTC position → **FAIL**
-  No validation, error only at API level

### After Fix
-  AI validation rejects position_size_usd < 100 for BTC
-  Binance trader checks quantity != 0 before submission
-  Clear error: "BTC/ETH requires ≥100 USDT..."

### Test Matrix

| Symbol | position_size_usd | Price | quantity | Formatted | Result |
|--------|-------------------|-------|----------|-----------|--------|
| BTCUSDT | 7.36 | 101808.2 | 0.00007228 | "0.000" |  Rejected (validation) |
| BTCUSDT | 150 | 101808.2 | 0.00147 | "0.001" |  Pass |
| ADAUSDT | 15 | 1.2 | 12.5 | "12.500" |  Pass |

---

## Impact

**Immediate**:
-  Prevents quantity=0 API errors
-  Clear error messages guide users
-  Saves wasted API calls

**Long-term**:
-  AI learns minimum position sizes
-  Better user experience for small accounts
-  Prevents confusion from cryptic API errors

---

## Related
- Diagnostic report: /tmp/quantity_zero_diagnosis.md
- Binance min notional: 10 USDT (hardcoded in GetMinNotional())
2025-11-05 01:13:06 +08:00
..