mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-11 14:56:57 +08:00
feat(grid): enforce daily loss limit
- Add checkDailyLossLimit() function to check if daily loss exceeds limit - Track daily PnL with auto-reset at midnight - Pause grid when DailyLossLimitPct exceeded - Add updateDailyPnL() helper for realized PnL tracking - Prevent excessive single-day losses
This commit is contained in:
@@ -156,6 +156,42 @@ func (at *AutoTrader) checkMaxDrawdown() (bool, float64) {
|
||||
return drawdown >= gridConfig.MaxDrawdownPct, drawdown
|
||||
}
|
||||
|
||||
// checkDailyLossLimit checks if daily loss exceeds limit
|
||||
// Returns: (exceeded bool, dailyLossPct float64)
|
||||
func (at *AutoTrader) checkDailyLossLimit() (bool, float64) {
|
||||
gridConfig := at.config.StrategyConfig.GridConfig
|
||||
if gridConfig.DailyLossLimitPct <= 0 {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
at.gridState.mu.Lock()
|
||||
// Reset daily PnL if new day
|
||||
now := time.Now()
|
||||
if now.YearDay() != at.gridState.LastDailyReset.YearDay() ||
|
||||
now.Year() != at.gridState.LastDailyReset.Year() {
|
||||
at.gridState.DailyPnL = 0
|
||||
at.gridState.LastDailyReset = now
|
||||
}
|
||||
dailyPnL := at.gridState.DailyPnL
|
||||
at.gridState.mu.Unlock()
|
||||
|
||||
// Calculate daily loss as percentage of total investment
|
||||
dailyLossPct := 0.0
|
||||
if gridConfig.TotalInvestment > 0 && dailyPnL < 0 {
|
||||
dailyLossPct = (-dailyPnL) / gridConfig.TotalInvestment * 100
|
||||
}
|
||||
|
||||
return dailyLossPct >= gridConfig.DailyLossLimitPct, dailyLossPct
|
||||
}
|
||||
|
||||
// updateDailyPnL updates the daily PnL tracking
|
||||
func (at *AutoTrader) updateDailyPnL(realizedPnL float64) {
|
||||
at.gridState.mu.Lock()
|
||||
at.gridState.DailyPnL += realizedPnL
|
||||
at.gridState.TotalProfit += realizedPnL
|
||||
at.gridState.mu.Unlock()
|
||||
}
|
||||
|
||||
// emergencyExit closes all positions and cancels all orders
|
||||
func (at *AutoTrader) emergencyExit(reason string) error {
|
||||
gridConfig := at.config.StrategyConfig.GridConfig
|
||||
@@ -376,6 +412,16 @@ func (at *AutoTrader) RunGridCycle() error {
|
||||
return at.emergencyExit(fmt.Sprintf("max drawdown exceeded: %.2f%%", drawdown))
|
||||
}
|
||||
|
||||
// CRITICAL: Check daily loss limit
|
||||
dailyExceeded, dailyLossPct := at.checkDailyLossLimit()
|
||||
if dailyExceeded {
|
||||
logger.Errorf("[Grid] Daily loss limit exceeded: %.2f%%", dailyLossPct)
|
||||
at.gridState.mu.Lock()
|
||||
at.gridState.IsPaused = true
|
||||
at.gridState.mu.Unlock()
|
||||
return fmt.Errorf("daily loss limit exceeded: %.2f%%", dailyLossPct)
|
||||
}
|
||||
|
||||
// Check if grid is paused
|
||||
at.gridState.mu.RLock()
|
||||
isPaused := at.gridState.IsPaused
|
||||
|
||||
Reference in New Issue
Block a user