Files
nt8-sdk/docs/architecture/interface_stability_contract.md
mo fb4f5d3bde
Some checks failed
Build and Test / build (push) Has been cancelled
chore: Add project configuration and documentation
- Kilocode AI agent rules and guidelines
- Setup and implementation guides
- Architecture documentation
- Build and verification references
2026-02-15 14:59:36 -05:00

728 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Interface Stability Contract - SDK ↔ Adapter Boundary
**Version**: 1.0
**Date**: February 14, 2026
**Status**: DRAFT - Needs Review & Approval
---
## Purpose
This document defines the **stable API contract** between:
- **NT8.Core.dll** (SDK - platform-agnostic)
- **NT8.Adapters.dll** (Adapters - platform-specific)
**Goal**: Ensure SDK updates don't break adapters, and vice versa.
---
## Design Principles
### 1. **Stable Interfaces, Evolving Implementations**
- Interfaces are contracts (change rarely)
- Implementations can evolve freely (change often)
- Adapters depend on interfaces, NOT implementations
### 2. **Semantic Versioning**
- **MAJOR**: Breaking changes to interfaces
- **MINOR**: New features (backward compatible)
- **PATCH**: Bug fixes (no API changes)
### 3. **Explicit Deprecation Cycle**
- Deprecated methods stay for 2+ minor versions
- Mark with `[Obsolete]` attribute
- Provide migration path in docs
---
## Current Interface Contract (v1.0)
### Core SDK Interfaces (STABLE)
These interfaces define the boundary. **Changes require MAJOR version bump.**
#### 1. Strategy Interface
```csharp
// src/NT8.Core/Common/Interfaces/IStrategy.cs
// VERSION: 1.0.0
// STABILITY: STABLE
public interface IStrategy
{
// Properties
StrategyMetadata Metadata { get; }
// Methods
void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger);
StrategyIntent OnBar(BarData bar, StrategyContext context);
StrategyIntent OnTick(TickData tick, StrategyContext context);
Dictionary<string, object> GetParameters();
void SetParameters(Dictionary<string, object> parameters);
}
```
**Stability Guarantee:**
- ✅ Method signatures won't change
- ✅ Method names won't change
- ✅ Return types won't change (may add properties to returned objects)
- ✅ Parameter types won't change (may add optional parameters)
**Allowed Changes:**
- Add new optional methods with default implementations
- Add properties to `StrategyMetadata`
- Add properties to `StrategyConfig`
- ❌ Cannot remove existing methods
- ❌ Cannot change existing method signatures
---
#### 2. Data Models (STABLE)
```csharp
// src/NT8.Core/Common/Models/BarData.cs
// VERSION: 1.0.0
// STABILITY: STABLE
public class BarData
{
// Core properties (IMMUTABLE)
public string Symbol { get; set; }
public DateTime Time { get; set; }
public double Open { get; set; }
public double High { get; set; }
public double Low { get; set; }
public double Close { get; set; }
public long Volume { get; set; }
public TimeSpan BarSize { get; set; }
// Constructor (IMMUTABLE signature)
public BarData(
string symbol,
DateTime time,
double open,
double high,
double low,
double close,
long volume,
TimeSpan barSize)
{ ... }
}
```
**Stability Guarantee:**
- ✅ Existing properties keep same names
- ✅ Existing properties keep same types
- ✅ Constructor signature won't change (may add overloads)
- ✅ Property getters/setters won't change behavior
**Allowed Changes:**
- Add new properties (with sensible defaults)
- Add new constructor overloads
- Add helper methods
- ❌ Cannot rename existing properties
- ❌ Cannot change property types
- ❌ Cannot remove properties
---
#### 3. Strategy Intent (STABLE)
```csharp
// src/NT8.Core/Common/Models/StrategyIntent.cs
// VERSION: 1.0.0
// STABILITY: STABLE
public class StrategyIntent
{
// Core properties (IMMUTABLE)
public string IntentId { get; private set; }
public DateTime Timestamp { get; private set; }
public string Symbol { get; set; }
public OrderSide Side { get; set; }
public OrderType EntryType { get; set; }
public double? LimitPrice { get; set; }
public int StopTicks { get; set; }
public int? TargetTicks { get; set; }
public double Confidence { get; set; }
public string Reason { get; set; }
public Dictionary<string, object> Metadata { get; set; }
// Constructor (IMMUTABLE signature)
public StrategyIntent(
string symbol,
OrderSide side,
OrderType entryType,
double? limitPrice,
int stopTicks,
int? targetTicks,
double confidence,
string reason,
Dictionary<string, object> metadata)
{ ... }
// Validation (IMMUTABLE signature)
public bool IsValid() { ... }
}
```
**Stability Guarantee:**
- ✅ All property names fixed
- ✅ All property types fixed
-`IsValid()` signature fixed
- ✅ Enums can add new values (but not remove)
**Allowed Changes:**
- Add new optional properties
- Add new validation methods
- Add enum values to `OrderSide`, `OrderType`
- ❌ Cannot remove properties
- ❌ Cannot change property types
- ❌ Cannot remove enum values
---
#### 4. Strategy Context (STABLE)
```csharp
// src/NT8.Core/Common/Models/StrategyContext.cs
// VERSION: 1.0.0
// STABILITY: STABLE
public class StrategyContext
{
// Core properties (IMMUTABLE)
public string Symbol { get; set; }
public DateTime CurrentTime { get; set; }
public Position CurrentPosition { get; set; }
public AccountInfo Account { get; set; }
public MarketSession Session { get; set; }
public Dictionary<string, object> CustomData { get; set; }
// Constructor (IMMUTABLE signature)
public StrategyContext(
string symbol,
DateTime currentTime,
Position currentPosition,
AccountInfo account,
MarketSession session,
Dictionary<string, object> customData)
{ ... }
}
```
**Stability Guarantee:**
- ✅ Context structure is stable
- ✅ Nested objects (`Position`, `AccountInfo`, `MarketSession`) can add properties
-`CustomData` dictionary for extensibility
**Allowed Changes:**
- Add properties to `Position`, `AccountInfo`, `MarketSession`
- Add new top-level properties to `StrategyContext`
- ❌ Cannot remove existing properties
- ❌ Cannot change property types
---
### Adapter Interface (SEMI-STABLE)
This is platform-specific. Can evolve more freely.
```csharp
// src/NT8.Adapters/NinjaTrader/INT8Adapter.cs
// VERSION: 1.0.0
// STABILITY: SEMI-STABLE (can evolve between minor versions)
public interface INT8Adapter
{
// Initialization
void Initialize(IRiskManager riskManager, IPositionSizer positionSizer);
// Data conversion (SDK models as return types = STABLE)
BarData ConvertToSdkBar(string symbol, DateTime time, double open, double high, double low, double close, long volume, int barSize);
AccountInfo ConvertToSdkAccount(double equity, double buyingPower, double dailyPnL, double maxDrawdown, DateTime lastUpdate);
Position ConvertToSdkPosition(string symbol, int quantity, double averagePrice, double unrealizedPnL, double realizedPnL, DateTime lastUpdate);
// Intent execution (SDK models as parameters = STABLE)
void ExecuteIntent(StrategyIntent intent, SizingResult sizing);
// NT8 callbacks (NT8-specific parameters = CAN CHANGE)
void OnOrderUpdate(string orderId, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, string orderState, DateTime time, string errorCode, string nativeError);
void OnExecutionUpdate(string executionId, string orderId, double price, int quantity, string marketPosition, DateTime time);
}
```
**Stability Guarantee:**
- ✅ Methods that return SDK models are stable
- ✅ Methods that accept SDK models are stable
- 🟡 NT8-specific signatures can evolve (minor versions)
**Allowed Changes:**
- Add new conversion methods
- Add optional parameters to NT8-specific methods
- Add new callback methods
- ❌ Cannot change SDK model signatures
- 🟡 Can change NT8-specific signatures (with deprecation)
---
## Versioning Strategy
### SDK Core (NT8.Core.dll)
```
Version Format: MAJOR.MINOR.PATCH
1.0.0 → Initial release (Phase 1)
1.1.0 → Add new optional features (Phase 2)
1.2.0 → More new features (Phase 3)
2.0.0 → Breaking interface changes (major refactor)
```
**Breaking Changes (MAJOR bump):**
- Remove methods from `IStrategy`
- Change method signatures in core interfaces
- Remove properties from data models
- Change property types in data models
**Compatible Changes (MINOR bump):**
- Add new optional interface methods (with defaults)
- Add new properties to data models
- Add new data models
- Add new interfaces
**Bug Fixes (PATCH bump):**
- Fix bugs in implementations
- Performance improvements
- Internal refactoring
- Documentation updates
---
### Adapters (NT8.Adapters.dll)
```
Version Format: Matches SDK version for compatibility
NT8.Core 1.0.0 → NT8.Adapters 1.0.x (compatible)
NT8.Core 1.1.0 → NT8.Adapters 1.1.x (compatible)
NT8.Core 2.0.0 → NT8.Adapters 2.0.x (requires rewrite)
```
**Adapter versions MUST match SDK MAJOR.MINOR**
---
## Interface Evolution Examples
### Example 1: Adding Optional Feature (MINOR version)
**Scenario**: Add support for multiple targets
```csharp
// v1.0.0 - Original
public class StrategyIntent
{
public int? TargetTicks { get; set; }
// ...
}
// v1.1.0 - Enhanced (BACKWARD COMPATIBLE)
public class StrategyIntent
{
public int? TargetTicks { get; set; } // Keep for compatibility
// NEW: Optional multiple targets
public List<int> TargetTicksList { get; set; } // Defaults to null
// Helper to maintain compatibility
public int? GetPrimaryTarget()
{
if (TargetTicksList != null && TargetTicksList.Count > 0)
return TargetTicksList[0];
return TargetTicks;
}
}
```
**Adapter Impact**: ✅ None - old code still works
**Strategy Impact**: ✅ None - can optionally use new feature
---
### Example 2: Deprecating Old Method (MINOR version with warning)
**Scenario**: Rename method for clarity
```csharp
// v1.0.0 - Original
public interface IStrategy
{
StrategyIntent OnBar(BarData bar, StrategyContext context);
}
// v1.1.0 - Add new, deprecate old
public interface IStrategy
{
[Obsolete("Use OnBarClose instead. Will be removed in v2.0.0")]
StrategyIntent OnBar(BarData bar, StrategyContext context);
// NEW preferred method
StrategyIntent OnBarClose(BarData bar, StrategyContext context);
}
// v1.2.0 - Still support both
// ... same as v1.1.0 ...
// v2.0.0 - Remove old (BREAKING CHANGE)
public interface IStrategy
{
StrategyIntent OnBarClose(BarData bar, StrategyContext context);
}
```
**Migration Timeline**:
- v1.1.0: Add new method, deprecate old (warning)
- v1.2.0: Keep both (warning)
- v2.0.0: Remove old (breaking change, requires adapter update)
---
### Example 3: Breaking Change (MAJOR version)
**Scenario**: Change position model to support multi-symbol
```csharp
// v1.x.x - Original
public class StrategyContext
{
public Position CurrentPosition { get; set; } // Single position
}
// v2.0.0 - Breaking change
public class StrategyContext
{
public Dictionary<string, Position> Positions { get; set; } // Multi-symbol
// Helper for single-symbol strategies
public Position GetPosition(string symbol)
{
return Positions.ContainsKey(symbol) ? Positions[symbol] : null;
}
}
```
**Adapter Impact**: ❌ Must update - breaking change
**Migration Required**: Yes, all adapters need rewrite
**Version Bump**: 1.x.x → 2.0.0
---
## Compatibility Matrix
### SDK ↔ Adapter Compatibility
| SDK Version | Adapter Version | Compatible? | Notes |
|-------------|-----------------|-------------|-------|
| 1.0.0 | 1.0.x | ✅ Yes | Perfect match |
| 1.1.0 | 1.0.x | ✅ Yes | Forward compatible |
| 1.1.0 | 1.1.x | ✅ Yes | Perfect match |
| 1.2.0 | 1.1.x | ✅ Yes | Forward compatible |
| 2.0.0 | 1.x.x | ❌ No | Breaking change |
| 2.0.0 | 2.0.x | ✅ Yes | Perfect match |
**Rule**: Adapter MINOR can be less than SDK MINOR (forward compatible)
**Rule**: Adapter MAJOR must equal SDK MAJOR
---
## Contract Testing
### Automated Contract Tests
Create tests that verify interface stability:
```csharp
// tests/NT8.Core.Tests/Contracts/InterfaceStabilityTests.cs
[Fact]
public void IStrategy_Interface_Should_Be_Stable()
{
var type = typeof(IStrategy);
// Verify method count hasn't decreased
var methods = type.GetMethods();
Assert.True(methods.Length >= 5, "IStrategy methods removed!");
// Verify specific methods exist
Assert.NotNull(type.GetMethod("OnBar"));
Assert.NotNull(type.GetMethod("OnTick"));
Assert.NotNull(type.GetMethod("Initialize"));
// Verify method signatures
var onBarMethod = type.GetMethod("OnBar");
Assert.Equal(typeof(StrategyIntent), onBarMethod.ReturnType);
var parameters = onBarMethod.GetParameters();
Assert.Equal(2, parameters.Length);
Assert.Equal(typeof(BarData), parameters[0].ParameterType);
Assert.Equal(typeof(StrategyContext), parameters[1].ParameterType);
}
[Fact]
public void BarData_Properties_Should_Be_Stable()
{
var type = typeof(BarData);
// Verify required properties exist
Assert.NotNull(type.GetProperty("Symbol"));
Assert.NotNull(type.GetProperty("Time"));
Assert.NotNull(type.GetProperty("Open"));
Assert.NotNull(type.GetProperty("High"));
Assert.NotNull(type.GetProperty("Low"));
Assert.NotNull(type.GetProperty("Close"));
Assert.NotNull(type.GetProperty("Volume"));
// Verify property types haven't changed
Assert.Equal(typeof(string), type.GetProperty("Symbol").PropertyType);
Assert.Equal(typeof(DateTime), type.GetProperty("Time").PropertyType);
Assert.Equal(typeof(double), type.GetProperty("Open").PropertyType);
}
[Fact]
public void StrategyIntent_Constructor_Should_Be_Stable()
{
var type = typeof(StrategyIntent);
// Verify constructor exists with expected parameters
var constructor = type.GetConstructor(new[]
{
typeof(string), // symbol
typeof(OrderSide), // side
typeof(OrderType), // entryType
typeof(double?), // limitPrice
typeof(int), // stopTicks
typeof(int?), // targetTicks
typeof(double), // confidence
typeof(string), // reason
typeof(Dictionary<string, object>) // metadata
});
Assert.NotNull(constructor);
}
```
**Run these tests** in CI/CD to catch accidental breaking changes!
---
## Adapter-Safe Practices
### For SDK Developers
**DO:**
- ✅ Add optional parameters with defaults
- ✅ Add new properties with sensible defaults
- ✅ Add new interfaces for new features
- ✅ Add helper methods to existing classes
- ✅ Mark deprecated methods with `[Obsolete]`
- ✅ Run contract tests before release
**DON'T:**
- ❌ Remove existing methods
- ❌ Change method signatures
- ❌ Rename properties
- ❌ Change property types
- ❌ Remove enum values
- ❌ Break existing constructors
### For Adapter Developers
**DO:**
- ✅ Depend only on interfaces, not implementations
- ✅ Use factory patterns for object creation
- ✅ Handle new optional properties gracefully
- ✅ Catch and log unknown enum values
- ✅ Version-check SDK at runtime if needed
**DON'T:**
- ❌ Depend on internal implementation details
- ❌ Assume fixed property counts
- ❌ Hard-code enum values
- ❌ Access private members via reflection
---
## Naming Conventions (IMMUTABLE)
These naming patterns are **contracts** and won't change:
### Interface Names
```
Pattern: I{Concept}
Examples: IStrategy, IRiskManager, IPositionSizer, ILogger
```
### Model Classes
```
Pattern: {Concept}{Type}
Examples: BarData, TickData, StrategyIntent, StrategyContext
```
### Enums
```
Pattern: {Concept}{Optional Suffix}
Examples: OrderSide, OrderType, TickType, RiskLevel
```
### Methods
```
Pattern: {Verb}{Noun}
Examples: OnBar, OnTick, Initialize, ValidateOrder, CalculateSize
```
### Properties
```
Pattern: {Noun} or {Adjective}{Noun}
Examples: Symbol, Timestamp, CurrentPosition, DailyPnL
```
**These patterns are STABLE and won't change.**
---
## Extension Points (For Future Growth)
### 1. Metadata Dictionaries
```csharp
public Dictionary<string, object> Metadata { get; set; }
```
**Use for**: Adding data without breaking compatibility
### 2. Optional Parameters
```csharp
public void Initialize(
StrategyConfig config,
IMarketDataProvider dataProvider,
ILogger logger,
Dictionary<string, object> options = null) // Extension point
```
### 3. Interface Composition
```csharp
// Instead of changing IStrategy, create new interface
public interface IAdvancedStrategy : IStrategy
{
void OnMarketDepth(MarketDepthData depth);
}
```
### 4. Feature Flags
```csharp
public class StrategyMetadata
{
public Dictionary<string, bool> SupportedFeatures { get; set; }
}
```
**Adapters can check**: `if (metadata.SupportedFeatures["MultiTarget"]) { ... }`
---
## Documentation Requirements
### For Every Interface Change
**Must Document:**
1. **What changed** (method/property added/removed/changed)
2. **Why it changed** (business reason)
3. **Version** it changed in
4. **Migration path** for adapters
5. **Deprecation timeline** (if applicable)
**Example**:
```markdown
## v1.1.0 - January 2026
### Added
- `StrategyIntent.TargetTicksList` - Support for multiple profit targets
- **Migration**: Not required. Old code using `TargetTicks` still works.
- **New feature**: Strategies can now specify multiple targets.
### Deprecated
- `IStrategy.OnBar()` - Deprecated in favor of `OnBarClose()`
- **Reason**: Clearer naming for bar-close strategies
- **Timeline**: Will be removed in v2.0.0 (12+ months)
- **Migration**: Replace `OnBar` with `OnBarClose` (same signature)
```
---
## Approval Process
### Before Releasing Interface Changes
**Required Reviews:**
1. ✅ Technical review (breaking vs. non-breaking)
2. ✅ Contract tests pass
3. ✅ Documentation updated
4. ✅ Migration guide written (if needed)
5. ✅ Version number updated correctly
**For Breaking Changes:**
1. ✅ All of the above, plus:
2. ✅ Deprecation period completed (2+ minor versions)
3. ✅ Adapter developers notified 30+ days in advance
4. ✅ Migration tooling provided (if possible)
---
## Summary
### The Contract
**SDK Core provides:**
- Stable interfaces (`IStrategy`, `IRiskManager`, `IPositionSizer`)
- Stable data models (`BarData`, `StrategyIntent`, `StrategyContext`)
- Versioned API (semantic versioning)
- Backward compatibility within MAJOR versions
**Adapters rely on:**
- Interface contracts (not implementations)
- Data model structures
- Method signatures
- Enum values
**The promise:**
- SDK can evolve WITHOUT breaking adapters (within MAJOR version)
- Adapters can evolve WITHOUT rewriting SDK
- Clear versioning communicates compatibility
- Deprecation gives time to migrate
---
## Action Items
### Immediate (Before Phase 1 Release)
- [ ] Review all public interfaces for stability
- [ ] Add contract tests to CI/CD
- [ ] Document current interface versions
- [ ] Establish version numbering (start at 1.0.0)
- [ ] Get team approval on this contract
### Ongoing
- [ ] Run contract tests on every build
- [ ] Review all PR's for interface stability
- [ ] Document changes in CHANGELOG.md
- [ ] Notify adapter developers of deprecations
- [ ] Maintain compatibility matrix
---
**Version History:**
- v1.0 (2026-02-14): Initial draft
- [Future versions will be listed here]