mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 00:36:56 +08:00
fix: use strategy config for position value ratio validation instead of hardcoded 1.5x
This commit is contained in:
@@ -278,6 +278,8 @@ func GetFullDecisionWithStrategy(ctx *Context, mcpClient mcp.AIClient, engine *S
|
|||||||
ctx.Account.TotalEquity,
|
ctx.Account.TotalEquity,
|
||||||
riskConfig.BTCETHMaxLeverage,
|
riskConfig.BTCETHMaxLeverage,
|
||||||
riskConfig.AltcoinMaxLeverage,
|
riskConfig.AltcoinMaxLeverage,
|
||||||
|
riskConfig.BTCETHMaxPositionValueRatio,
|
||||||
|
riskConfig.AltcoinMaxPositionValueRatio,
|
||||||
)
|
)
|
||||||
|
|
||||||
if decision != nil {
|
if decision != nil {
|
||||||
@@ -1297,7 +1299,7 @@ func formatFloatSlice(values []float64) string {
|
|||||||
// AI Response Parsing
|
// AI Response Parsing
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
func parseFullDecisionResponse(aiResponse string, accountEquity float64, btcEthLeverage, altcoinLeverage int) (*FullDecision, error) {
|
func parseFullDecisionResponse(aiResponse string, accountEquity float64, btcEthLeverage, altcoinLeverage int, btcEthPosRatio, altcoinPosRatio float64) (*FullDecision, error) {
|
||||||
cotTrace := extractCoTTrace(aiResponse)
|
cotTrace := extractCoTTrace(aiResponse)
|
||||||
|
|
||||||
decisions, err := extractDecisions(aiResponse)
|
decisions, err := extractDecisions(aiResponse)
|
||||||
@@ -1308,7 +1310,7 @@ func parseFullDecisionResponse(aiResponse string, accountEquity float64, btcEthL
|
|||||||
}, fmt.Errorf("failed to extract decisions: %w", err)
|
}, fmt.Errorf("failed to extract decisions: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateDecisions(decisions, accountEquity, btcEthLeverage, altcoinLeverage); err != nil {
|
if err := validateDecisions(decisions, accountEquity, btcEthLeverage, altcoinLeverage, btcEthPosRatio, altcoinPosRatio); err != nil {
|
||||||
return &FullDecision{
|
return &FullDecision{
|
||||||
CoTTrace: cotTrace,
|
CoTTrace: cotTrace,
|
||||||
Decisions: decisions,
|
Decisions: decisions,
|
||||||
@@ -1474,16 +1476,16 @@ func compactArrayOpen(s string) string {
|
|||||||
// Decision Validation
|
// Decision Validation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
func validateDecisions(decisions []Decision, accountEquity float64, btcEthLeverage, altcoinLeverage int) error {
|
func validateDecisions(decisions []Decision, accountEquity float64, btcEthLeverage, altcoinLeverage int, btcEthPosRatio, altcoinPosRatio float64) error {
|
||||||
for i, decision := range decisions {
|
for i, decision := range decisions {
|
||||||
if err := validateDecision(&decision, accountEquity, btcEthLeverage, altcoinLeverage); err != nil {
|
if err := validateDecision(&decision, accountEquity, btcEthLeverage, altcoinLeverage, btcEthPosRatio, altcoinPosRatio); err != nil {
|
||||||
return fmt.Errorf("decision #%d validation failed: %w", i+1, err)
|
return fmt.Errorf("decision #%d validation failed: %w", i+1, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateDecision(d *Decision, accountEquity float64, btcEthLeverage, altcoinLeverage int) error {
|
func validateDecision(d *Decision, accountEquity float64, btcEthLeverage, altcoinLeverage int, btcEthPosRatio, altcoinPosRatio float64) error {
|
||||||
validActions := map[string]bool{
|
validActions := map[string]bool{
|
||||||
"open_long": true,
|
"open_long": true,
|
||||||
"open_short": true,
|
"open_short": true,
|
||||||
@@ -1499,10 +1501,12 @@ func validateDecision(d *Decision, accountEquity float64, btcEthLeverage, altcoi
|
|||||||
|
|
||||||
if d.Action == "open_long" || d.Action == "open_short" {
|
if d.Action == "open_long" || d.Action == "open_short" {
|
||||||
maxLeverage := altcoinLeverage
|
maxLeverage := altcoinLeverage
|
||||||
maxPositionValue := accountEquity * 1.5
|
posRatio := altcoinPosRatio
|
||||||
|
maxPositionValue := accountEquity * posRatio
|
||||||
if d.Symbol == "BTCUSDT" || d.Symbol == "ETHUSDT" {
|
if d.Symbol == "BTCUSDT" || d.Symbol == "ETHUSDT" {
|
||||||
maxLeverage = btcEthLeverage
|
maxLeverage = btcEthLeverage
|
||||||
maxPositionValue = accountEquity * 10
|
posRatio = btcEthPosRatio
|
||||||
|
maxPositionValue = accountEquity * posRatio
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.Leverage <= 0 {
|
if d.Leverage <= 0 {
|
||||||
@@ -1533,9 +1537,9 @@ func validateDecision(d *Decision, accountEquity float64, btcEthLeverage, altcoi
|
|||||||
tolerance := maxPositionValue * 0.01
|
tolerance := maxPositionValue * 0.01
|
||||||
if d.PositionSizeUSD > maxPositionValue+tolerance {
|
if d.PositionSizeUSD > maxPositionValue+tolerance {
|
||||||
if d.Symbol == "BTCUSDT" || d.Symbol == "ETHUSDT" {
|
if d.Symbol == "BTCUSDT" || d.Symbol == "ETHUSDT" {
|
||||||
return fmt.Errorf("BTC/ETH single coin position value cannot exceed %.0f USDT (10x account equity), actual: %.0f", maxPositionValue, d.PositionSizeUSD)
|
return fmt.Errorf("BTC/ETH single coin position value cannot exceed %.0f USDT (%.1fx account equity), actual: %.0f", maxPositionValue, posRatio, d.PositionSizeUSD)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("altcoin single coin position value cannot exceed %.0f USDT (1.5x account equity), actual: %.0f", maxPositionValue, d.PositionSizeUSD)
|
return fmt.Errorf("altcoin single coin position value cannot exceed %.0f USDT (%.1fx account equity), actual: %.0f", maxPositionValue, posRatio, d.PositionSizeUSD)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if d.StopLoss <= 0 || d.TakeProfit <= 0 {
|
if d.StopLoss <= 0 || d.TakeProfit <= 0 {
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ func TestLeverageFallback(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
err := validateDecision(&tt.decision, tt.accountEquity, tt.btcEthLeverage, tt.altcoinLeverage)
|
// Use default position value ratios for testing (10x for BTC/ETH, 1.5x for altcoins)
|
||||||
|
err := validateDecision(&tt.decision, tt.accountEquity, tt.btcEthLeverage, tt.altcoinLeverage, 10.0, 1.5)
|
||||||
|
|
||||||
// Check error status
|
// Check error status
|
||||||
if (err != nil) != tt.wantError {
|
if (err != nil) != tt.wantError {
|
||||||
|
|||||||
Reference in New Issue
Block a user