- Kilocode AI agent rules and guidelines - Setup and implementation guides - Architecture documentation - Build and verification references
19 KiB
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
// 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)
// 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)
// 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)
// 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 - ✅
CustomDatadictionary 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.
// 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
// 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
// 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
// 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:
// 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
public Dictionary<string, object> Metadata { get; set; }
Use for: Adding data without breaking compatibility
2. Optional Parameters
public void Initialize(
StrategyConfig config,
IMarketDataProvider dataProvider,
ILogger logger,
Dictionary<string, object> options = null) // Extension point
3. Interface Composition
// Instead of changing IStrategy, create new interface
public interface IAdvancedStrategy : IStrategy
{
void OnMarketDepth(MarketDepthData depth);
}
4. Feature Flags
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:
- What changed (method/property added/removed/changed)
- Why it changed (business reason)
- Version it changed in
- Migration path for adapters
- Deprecation timeline (if applicable)
Example:
## 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:
- ✅ Technical review (breaking vs. non-breaking)
- ✅ Contract tests pass
- ✅ Documentation updated
- ✅ Migration guide written (if needed)
- ✅ Version number updated correctly
For Breaking Changes:
- ✅ All of the above, plus:
- ✅ Deprecation period completed (2+ minor versions)
- ✅ Adapter developers notified 30+ days in advance
- ✅ 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]