# TASK-02: Wire ExecutionCircuitBreaker into NT8StrategyBase

**File:** `src/NT8.Adapters/Strategies/NT8StrategyBase.cs`
**Priority:** CRITICAL
**Depends on:** TASK-01 must be done first (file already open/modified)
**Estimated time:** 45 min

---

## Background

`ExecutionCircuitBreaker` at `src/NT8.Core/Execution/ExecutionCircuitBreaker.cs` is complete and tested.
Its public API is:
- `bool ShouldAllowOrder()` — returns false when circuit is Open
- `void OnSuccess()` — call after a successful order submission
- `void OnFailure()` — call after a failed order submission
- `void RecordOrderRejection(string reason)` — call when NT8 rejects an order
- `void Reset()` — resets to Closed state

The `ExecutionCircuitBreaker` constructor:
```csharp
public ExecutionCircuitBreaker(
    ILogger<ExecutionCircuitBreaker> logger,
    int failureThreshold = 3,
    TimeSpan? timeout = null,
    TimeSpan? retryTimeout = null,
    int latencyWindowSize = 100,
    int rejectionWindowSize = 10)
```

**Problem:** It is never instantiated. `NT8StrategyBase` submits orders with no circuit breaker gate.

---

## Exact Changes Required

### 1. Add using statement at top of `NT8StrategyBase.cs`

```csharp
using NT8.Core.Execution;
using Microsoft.Extensions.Logging.Abstractions;
```

### 2. Add private field alongside the other private fields

```csharp
private ExecutionCircuitBreaker _circuitBreaker;
```

### 3. Initialize in `InitializeSdkComponents()`, after `_positionSizer = new BasicPositionSizer(_logger);`

```csharp
_circuitBreaker = new ExecutionCircuitBreaker(
    NullLogger<ExecutionCircuitBreaker>.Instance,
    failureThreshold: 3,
    timeout: TimeSpan.FromSeconds(30));
```

### 4. Gate `SubmitOrderToNT8()` — add check at top of the method

```csharp
private void SubmitOrderToNT8(OmsOrderRequest request, StrategyIntent intent)
{
    // Circuit breaker gate
    if (_circuitBreaker != null && !_circuitBreaker.ShouldAllowOrder())
    {
        var state = _circuitBreaker.GetState();
        Print(string.Format("[SDK] Circuit breaker OPEN — order blocked: {0}", state.Reason));
        if (_logger != null)
            _logger.LogWarning("Circuit breaker blocked order: {0}", state.Reason);
        return;
    }

    try
    {
        // ... EXISTING submit logic unchanged ...
        var orderName = string.Format("SDK_{0}_{1}", intent.Symbol, DateTime.Now.Ticks);
        _executionAdapter.SubmitOrder(request, orderName);

        if (request.Side == OmsOrderSide.Buy)
        { ... existing EnterLong/EnterLongLimit/etc ... }
        else if (request.Side == OmsOrderSide.Sell)
        { ... existing EnterShort/etc ... }

        if (intent.StopTicks > 0)
            SetStopLoss(orderName, CalculationMode.Ticks, (int)intent.StopTicks, false);

        if (intent.TargetTicks.HasValue && intent.TargetTicks.Value > 0)
            SetProfitTarget(orderName, CalculationMode.Ticks, (int)intent.TargetTicks.Value);

        // Mark success after submission
        if (_circuitBreaker != null)
            _circuitBreaker.OnSuccess();
    }
    catch (Exception ex)
    {
        if (_circuitBreaker != null)
            _circuitBreaker.OnFailure();

        Print(string.Format("[SDK] SubmitOrderToNT8 failed: {0}", ex.Message));
        if (_logger != null)
            _logger.LogError("SubmitOrderToNT8 failed: {0}", ex.Message);
        throw;
    }
}
```

### 5. Wire rejections in `OnOrderUpdate()`

In the existing `OnOrderUpdate()` override, after the null/name checks, add:

```csharp
// Record NT8 rejections in circuit breaker
if (orderState == NinjaTrader.Cbi.OrderState.Rejected && _circuitBreaker != null)
{
    var reason = string.Format("{0} {1}", errorCode, nativeError ?? string.Empty);
    _circuitBreaker.RecordOrderRejection(reason);
    Print(string.Format("[SDK] Order rejected by NT8: {0}", reason));
}
```

---

## Acceptance Criteria

- [ ] `ExecutionCircuitBreaker` is instantiated in `InitializeSdkComponents()`
- [ ] `SubmitOrderToNT8()` checks `ShouldAllowOrder()` before submitting — if false, prints message and returns
- [ ] `OnOrderUpdate()` calls `RecordOrderRejection()` when `orderState == OrderState.Rejected`
- [ ] `OnSuccess()` called after successful order submission
- [ ] `OnFailure()` called in catch block
- [ ] `verify-build.bat` passes with zero errors
- [ ] Existing 240+ tests still pass: `dotnet test NT8-SDK.sln --verbosity minimal`

---

## Do NOT Change

- `ExecutionCircuitBreaker.cs` — already correct, just use it
- Any Core layer files
- Any test files
