Merge pull request #437 from zhouyongyou/fix/margin-calculation

fix(margin): correct position sizing formula to prevent insufficient margin errors
This commit is contained in:
Icyoung
2025-11-05 16:13:37 +08:00
committed by GitHub
4 changed files with 84 additions and 19 deletions

View File

@@ -342,26 +342,25 @@
## 仓位计算公式
```
仓位大小(USD) = 可用资金 × 风险预算 / 止损距离百分比
仓位数量(Coins) = 仓位大小(USD) / 当前价格
```
**重要**position_size_usd 是**名义价值**(包含杠杆),非保证金需求。
**示例**
```
账户净值10,000 USDT
风险预算2%(信心度 90-95
止损距离2%50,000 → 49,000
**计算步骤**
1. **可用保证金** = Available Cash × 0.95 × Allocation %预留5%给手续费)
2. **名义价值** = 可用保证金 × Leverage
3. **position_size_usd** = 名义价值(这是 JSON 中应填写的值
4. **Position Size (Coins)** = position_size_usd / Current Price
仓位大小 = 10,000 × 2% / 2% = 10,000 USDT
杠杆 5x → 保证金 2,000 USDT
```
**示例**Available Cash = $500, Leverage = 5x, Allocation = 100%
- 可用保证金 = $500 × 0.95 × 100% = $475
- position_size_usd = $475 × 5 = **$2,375** ← JSON 中填写此值
- 实际占用保证金 = $475剩余 $25 用于手续费
## 杠杆选择指
## 杠杆选择指
- 信心度 85-87: 3-5x 杠杆
- 信心度 88-92: 5-10x 杠杆
- 信心度 93-95: 10-15x 杠杆
基于信心度的杠杆配置:
- 信心度 <85 → 不开仓
- 信心度 85-90 → 杠杆 1-3x风险预算 1.5%
- 信心度 90-95 → 杠杆 3-8x风险预算 2%
- 信心度 >95: 最高 20x 杠杆(谨慎)
## 风险控制原则

View File

@@ -106,6 +106,21 @@
3. 寻找新机会: 有强信号吗?多空机会?
4. 输出决策: 思维链分析 + JSON
# 仓位大小计算
**重要**`position_size_usd` 是**名义价值**(包含杠杆),非保证金需求。
**计算步骤**
1. **可用保证金** = Available Cash × 0.95 × 配置比例预留5%手续费)
2. **名义价值** = 可用保证金 × Leverage
3. **position_size_usd** = 名义价值JSON中填写此值
4. **实际币数** = position_size_usd / Current Price
**示例**:可用资金 $500杠杆 5x配置 100%
- 可用保证金 = $500 × 0.95 = $475
- position_size_usd = $475 × 5 = **$2,375** ← JSON填此值
- 实际占用保证金 = $475剩余 $25 用于手续费
---
记住:

View File

@@ -51,10 +51,19 @@ You have exactly SIX possible actions per decision cycle:
# POSITION SIZING FRAMEWORK
Calculate position size using this formula:
**IMPORTANT**: `position_size_usd` is the **notional value** (includes leverage), NOT margin requirement.
Position Size (USD) = Available Cash × Leverage × Allocation %
Position Size (Coins) = Position Size (USD) / Current Price
## Calculation Steps:
1. **Available Margin** = Available Cash × 0.95 × Allocation % (reserve 5% for fees)
2. **Notional Value** = Available Margin × Leverage
3. **position_size_usd** = Notional Value (this is the value for JSON)
4. **Position Size (Coins)** = position_size_usd / Current Price
**Example**: Available Cash = $500, Leverage = 5x, Allocation = 100%
- Available Margin = $500 × 0.95 × 100% = $475
- position_size_usd = $475 × 5 = **$2,375** ← Fill this value in JSON
- Actual margin used = $475, remaining $25 for fees
## Sizing Considerations

View File

@@ -744,6 +744,27 @@ func (at *AutoTrader) executeOpenLongWithRecord(decision *decision.Decision, act
actionRecord.Quantity = quantity
actionRecord.Price = marketData.CurrentPrice
// ⚠️ 保证金验证防止保证金不足错误code=-2019
requiredMargin := decision.PositionSizeUSD / float64(decision.Leverage)
balance, err := at.trader.GetBalance()
if err != nil {
return fmt.Errorf("获取账户余额失败: %w", err)
}
availableBalance := 0.0
if avail, ok := balance["availableBalance"].(float64); ok {
availableBalance = avail
}
// 手续费估算Taker费率 0.04%
estimatedFee := decision.PositionSizeUSD * 0.0004
totalRequired := requiredMargin + estimatedFee
if totalRequired > availableBalance {
return fmt.Errorf("❌ 保证金不足: 需要 %.2f USDT保证金 %.2f + 手续费 %.2f),可用 %.2f USDT",
totalRequired, requiredMargin, estimatedFee, availableBalance)
}
// 设置仓位模式
if err := at.trader.SetMarginMode(decision.Symbol, at.config.IsCrossMargin); err != nil {
log.Printf(" ⚠️ 设置仓位模式失败: %v", err)
@@ -803,6 +824,27 @@ func (at *AutoTrader) executeOpenShortWithRecord(decision *decision.Decision, ac
actionRecord.Quantity = quantity
actionRecord.Price = marketData.CurrentPrice
// ⚠️ 保证金验证防止保证金不足错误code=-2019
requiredMargin := decision.PositionSizeUSD / float64(decision.Leverage)
balance, err := at.trader.GetBalance()
if err != nil {
return fmt.Errorf("获取账户余额失败: %w", err)
}
availableBalance := 0.0
if avail, ok := balance["availableBalance"].(float64); ok {
availableBalance = avail
}
// 手续费估算Taker费率 0.04%
estimatedFee := decision.PositionSizeUSD * 0.0004
totalRequired := requiredMargin + estimatedFee
if totalRequired > availableBalance {
return fmt.Errorf("❌ 保证金不足: 需要 %.2f USDT保证金 %.2f + 手续费 %.2f),可用 %.2f USDT",
totalRequired, requiredMargin, estimatedFee, availableBalance)
}
// 设置仓位模式
if err := at.trader.SetMarginMode(decision.Symbol, at.config.IsCrossMargin); err != nil {
log.Printf(" ⚠️ 设置仓位模式失败: %v", err)