3.6 KiB
3.6 KiB
Task 3 — Wire ExecutionCircuitBreaker
Priority: HIGH
Estimated time: 1.5–2 hours
Depends on: Task 1 (NT8StrategyBase changes)
Status: TODO
Problem
ExecutionCircuitBreaker in src/NT8.Core/Execution/ExecutionCircuitBreaker.cs is a complete, well-tested class.
It is never instantiated or connected to any live order flow. Orders are submitted regardless of latency or rejection conditions.
What Needs to Change
File: src/NT8.Adapters/Strategies/NT8StrategyBase.cs
Step 1: Add ExecutionCircuitBreaker as a field on NT8StrategyBase.
private ExecutionCircuitBreaker _circuitBreaker;
Step 2: Initialize it in OnStateChange → State.DataLoaded:
// Use Microsoft.Extensions.Logging NullLogger for now (or wire to BasicLogger)
_circuitBreaker = new ExecutionCircuitBreaker(
new NullLogger<ExecutionCircuitBreaker>(),
failureThreshold: 3,
timeout: TimeSpan.FromSeconds(30));
Step 3: Gate ALL order submissions through the circuit breaker.
In the method that calls ExecuteIntent() (or wherever orders flow from strategy intent to the adapter), add:
private bool TrySubmitIntent(StrategyIntent intent, StrategyContext context)
{
if (!_circuitBreaker.ShouldAllowOrder())
{
var state = _circuitBreaker.GetState();
Print(string.Format("[NT8-SDK] Circuit breaker OPEN — order blocked. Reason: {0}", state.Reason));
return false;
}
try
{
_orderAdapter.ExecuteIntent(intent, context, _strategyConfig);
_circuitBreaker.OnSuccess();
return true;
}
catch (Exception ex)
{
_circuitBreaker.OnFailure();
_circuitBreaker.RecordOrderRejection(ex.Message);
Print(string.Format("[NT8-SDK] Order execution failed: {0}", ex.Message));
return false;
}
}
Step 4: Wire OnOrderUpdate rejections back to the circuit breaker.
In NT8StrategyBase.OnOrderUpdate():
protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice,
int quantity, int filled, double averageFillPrice,
OrderState orderState, DateTime time, ErrorCode error, string nativeError)
{
if (orderState == OrderState.Rejected)
{
if (_circuitBreaker != null)
{
_circuitBreaker.RecordOrderRejection(
string.Format("NT8 rejected order: {0} {1}", error, nativeError));
}
}
// Pass through to adapter for state tracking
if (_orderAdapter != null)
{
_orderAdapter.OnOrderUpdate(
order != null ? order.Name : "unknown",
limitPrice, stopPrice, quantity, filled,
averageFillPrice,
orderState != null ? orderState.ToString() : "unknown",
time, error.ToString(), nativeError ?? string.Empty);
}
}
Acceptance Criteria
ExecutionCircuitBreakeris instantiated inNT8StrategyBase- All order submissions go through
_circuitBreaker.ShouldAllowOrder()— if false, order is blocked and logged - NT8 order rejections call
_circuitBreaker.RecordOrderRejection() - 3 consecutive rejections open the circuit breaker (blocks further orders for 30 seconds)
- After 30 seconds, circuit breaker enters half-open and allows one test order
verify-build.batpasses
Files to Modify
| File | Action |
|---|---|
src/NT8.Adapters/Strategies/NT8StrategyBase.cs |
Add circuit breaker field, initialize, gate submissions, wire rejections |
Files to NOT Change
src/NT8.Core/Execution/ExecutionCircuitBreaker.cs— complete and correct, do not touch- Any test files