seventh version

This commit is contained in:
2026-06-08 11:11:50 +00:00
parent 8a552dec56
commit ebea17b411
11 changed files with 511 additions and 138 deletions
+2 -1
View File
@@ -33,6 +33,7 @@ type ManagerConfig struct {
type PreTradeInput struct {
Portfolio domain.Portfolio
OpenPositions int
ClosingPosition bool
DailyPnL decimal.Decimal
WeeklyPnL decimal.Decimal
MonthlyDrawdownPct decimal.Decimal
@@ -91,7 +92,7 @@ func (m Manager) PreTradeCheck(input PreTradeInput) PreTradeResult {
return reject("trading_status_unknown_before_order")
case input.TradingStatus != domain.TradingStatusNormal:
return reject("trading_status_not_normal")
case m.cfg.MaxOpenPositions > 0 && input.OpenPositions >= m.cfg.MaxOpenPositions:
case !input.ClosingPosition && m.cfg.MaxOpenPositions > 0 && input.OpenPositions >= m.cfg.MaxOpenPositions:
return reject("max_open_positions")
case DailyLossBreached(input.DailyPnL, input.Portfolio.Equity, m.cfg.MaxDailyLossPct):
return reject("max_daily_loss")
+28
View File
@@ -0,0 +1,28 @@
package risk
import (
"testing"
"github.com/shopspring/decimal"
"overnight-trading-bot/internal/domain"
)
func TestPreTradeClosingPositionBypassesOpenPositionLimit(t *testing.T) {
manager := NewManager(nil, ManagerConfig{MaxOpenPositions: 1})
input := PreTradeInput{
Portfolio: domain.Portfolio{Equity: decimal.NewFromInt(1000)},
OpenPositions: 1,
TradingStatus: domain.TradingStatusNormal,
ClosingPosition: true,
}
result := manager.PreTradeCheck(input)
if !result.Allowed {
t.Fatalf("closing position rejected: %s", result.Reason)
}
input.ClosingPosition = false
result = manager.PreTradeCheck(input)
if result.Allowed || result.Reason != "max_open_positions" {
t.Fatalf("entry result=%+v, want max_open_positions reject", result)
}
}