# TASK-05: Add CME Holiday Awareness to SessionManager

**File:** `src/NT8.Core/MarketData/SessionManager.cs`
**Priority:** MEDIUM
**No dependencies**
**Estimated time:** 30 min

---

## Background

`IsRegularTradingHours()` currently only checks session time windows. It has no awareness of CME holidays, so the system would attempt to trade on Christmas, Thanksgiving, etc. when markets are closed.

---

## Exact Changes Required

### 1. Add a static holiday set as a private field on `SessionManager`

Add this inside the class (near the other private fields):

```csharp
// CME US Futures holidays — markets closed all day on these dates.
// Update annually. Dates are in the format new DateTime(year, month, day).
private static readonly System.Collections.Generic.HashSet<DateTime> _cmeHolidays =
    new System.Collections.Generic.HashSet<DateTime>
    {
        // 2025 holidays
        new DateTime(2025, 1, 1),   // New Year's Day
        new DateTime(2025, 1, 20),  // Martin Luther King Jr. Day
        new DateTime(2025, 2, 17),  // Presidents' Day
        new DateTime(2025, 4, 18),  // Good Friday
        new DateTime(2025, 5, 26),  // Memorial Day
        new DateTime(2025, 6, 19),  // Juneteenth
        new DateTime(2025, 7, 4),   // Independence Day
        new DateTime(2025, 9, 1),   // Labor Day
        new DateTime(2025, 11, 27), // Thanksgiving
        new DateTime(2025, 12, 25), // Christmas Day

        // 2026 holidays
        new DateTime(2026, 1, 1),   // New Year's Day
        new DateTime(2026, 1, 19),  // Martin Luther King Jr. Day
        new DateTime(2026, 2, 16),  // Presidents' Day
        new DateTime(2026, 4, 3),   // Good Friday
        new DateTime(2026, 5, 25),  // Memorial Day
        new DateTime(2026, 6, 19),  // Juneteenth
        new DateTime(2026, 7, 4),   // Independence Day (observed Mon 7/3 if falls on Sat — keep both just in case)
        new DateTime(2026, 9, 7),   // Labor Day
        new DateTime(2026, 11, 26), // Thanksgiving
        new DateTime(2026, 12, 25), // Christmas Day
    };
```

### 2. Add a helper method

```csharp
/// <summary>
/// Returns true if the given UTC date is a CME holiday (market closed all day).
/// </summary>
private static bool IsCmeHoliday(DateTime utcTime)
{
    // Convert to ET for holiday date comparison
    try
    {
        var estTime = TimeZoneInfo.ConvertTimeFromUtc(utcTime,
            TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));
        return _cmeHolidays.Contains(estTime.Date);
    }
    catch (Exception)
    {
        return false;
    }
}
```

### 3. Update `IsRegularTradingHours()` to check holidays first

The existing method body is:
```csharp
var sessionInfo = GetCurrentSession(symbol, time);
return sessionInfo.IsRegularHours;
```

Replace with:
```csharp
// Markets are fully closed on CME holidays
if (IsCmeHoliday(time))
{
    _logger.LogInformation("Holiday detected for {0} on {1} — market closed.", symbol, time.Date);
    return false;
}

var sessionInfo = GetCurrentSession(symbol, time);
return sessionInfo.IsRegularHours;
```

---

## Acceptance Criteria

- [ ] `IsRegularTradingHours("ES", new DateTime(2025, 12, 25, 14, 0, 0, DateTimeKind.Utc))` returns `false`
- [ ] `IsRegularTradingHours("ES", new DateTime(2025, 12, 26, 14, 0, 0, DateTimeKind.Utc))` returns `true` (normal day)
- [ ] `IsRegularTradingHours("ES", new DateTime(2025, 11, 27, 14, 0, 0, DateTimeKind.Utc))` returns `false` (Thanksgiving)
- [ ] `verify-build.bat` passes
- [ ] All existing tests pass
