# AI Agent Workflow and Code Templates

## Pre-Implementation Checklist

### Before Starting ANY NT8 Integration Task:

1. **Environment Verification**
   ```bash
   cd C:\dev\nt8-sdk
   .\verify-build.bat
   # MUST output: "✅ All checks passed!"
   ```

2. **Documentation Review**
   - [ ] Read `AI_DEVELOPMENT_GUIDELINES.md`
   - [ ] Read `NT8_INTEGRATION_GUIDELINES.md` 
   - [ ] Review task-specific requirements
   - [ ] Check dependency tasks are complete

3. **Pattern Study**
   - [ ] Review existing code in `src/NT8.Core/`
   - [ ] Study similar implementations in the repository
   - [ ] Understand data flow and architecture

## Code Templates

### Template 1: NT8 Strategy Wrapper
```csharp
using System;
using System.Collections.Generic;
using NinjaTrader.Cbi;
using NinjaTrader.NinjaScript.Strategies;
using NT8.Core.Common.Interfaces;
using NT8.Core.Common.Models;
using NT8.Core.Risk;
using NT8.Core.Sizing;
using NT8.Core.Logging;

namespace NinjaTrader.NinjaScript.Strategies
{
    /// <summary>
    /// NT8 wrapper for [StrategyName] SDK strategy
    /// Bridges NinjaTrader 8 with institutional SDK framework
    /// </summary>
    public class [StrategyName]NT8Wrapper : Strategy
    {
        #region SDK Components
        private IStrategy _sdkStrategy;
        private IRiskManager _riskManager;
        private IPositionSizer _positionSizer;
        private ILogger _logger;
        #endregion

        #region NT8 Parameters (Show in UI)
        [NinjaScriptProperty]
        [Range(1, 50)]
        [Display(Name = "Stop Loss Ticks", Description = "Stop loss in ticks", Order = 1, GroupName = "Risk")]
        public int StopTicks { get; set; } = 8;

        [NinjaScriptProperty]
        [Range(1, 100)]
        [Display(Name = "Profit Target Ticks", Description = "Profit target in ticks", Order = 2, GroupName = "Risk")]
        public int TargetTicks { get; set; } = 16;

        [NinjaScriptProperty]
        [Range(100, 5000)]
        [Display(Name = "Daily Loss Limit", Description = "Maximum daily loss in dollars", Order = 3, GroupName = "Risk")]
        public double DailyLossLimit { get; set; } = 1000;

        [NinjaScriptProperty]
        [Range(50, 1000)]
        [Display(Name = "Risk Per Trade", Description = "Dollar risk per trade", Order = 4, GroupName = "Sizing")]
        public double RiskPerTrade { get; set; } = 200;
        #endregion

        #region NT8 Lifecycle
        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                InitializeNT8Properties();
                InitializeSdkComponents();
            }
            else if (State == State.DataLoaded)
            {
                ValidateConfiguration();
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < 1) return;

            try
            {
                // Convert NT8 data to SDK format
                var barData = ConvertToSdkBar();
                var context = CreateStrategyContext();

                // Get trading intent from SDK strategy
                var intent = _sdkStrategy.OnBar(barData, context);
                if (intent == null) return;

                // Risk validation
                var riskDecision = ValidateRisk(intent, context);
                if (!riskDecision.Allow)
                {
                    _logger.LogWarning("Trade rejected: {0}", riskDecision.RejectReason);
                    return;
                }

                // Position sizing
                var sizingResult = CalculatePositionSize(intent, context);
                if (sizingResult.Contracts <= 0)
                {
                    _logger.LogWarning("No contracts calculated");
                    return;
                }

                // Execute in NT8
                ExecuteTradeInNT8(intent, sizingResult);
            }
            catch (Exception ex)
            {
                _logger.LogError("OnBarUpdate error: {0}", ex.Message);
                HandleError(ex);
            }
        }
        #endregion

        #region Initialization
        private void InitializeNT8Properties()
        {
            Description = "[StrategyName] using NT8 SDK";
            Name = "[StrategyName]NT8";
            Calculate = Calculate.OnBarClose;
            EntriesPerDirection = 1;
            EntryHandling = EntryHandling.AllEntries;
            IsExitOnSessionCloseStrategy = true;
            ExitOnSessionCloseSeconds = 30;
            BarsRequiredToTrade = 20;
            StartBehavior = StartBehavior.WaitUntilFlat;
            TimeInForce = TimeInForce.Gtc;
        }

        private void InitializeSdkComponents()
        {
            try
            {
                _logger = new BasicLogger(Name);
                _riskManager = new BasicRiskManager(_logger);
                _positionSizer = new BasicPositionSizer(_logger);
                
                // Initialize specific strategy
                _sdkStrategy = new [ConcreteStrategyClass](_logger);
                
                var config = CreateSdkConfiguration();
                _sdkStrategy.Initialize(config, null, _logger);
                
                _logger.LogInformation("SDK components initialized successfully");
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(String.Format("Failed to initialize SDK: {0}", ex.Message), ex);
            }
        }
        #endregion

        #region Data Conversion
        private BarData ConvertToSdkBar()
        {
            return new BarData(
                symbol: Instrument.MasterInstrument.Name,
                time: Time[0],
                open: Open[0],
                high: High[0],
                low: Low[0],
                close: Close[0],
                volume: Volume[0],
                barSize: TimeSpan.FromMinutes(BarsPeriod.Value)
            );
        }

        private StrategyContext CreateStrategyContext()
        {
            var position = new Position(
                symbol: Instrument.MasterInstrument.Name,
                quantity: Position.Quantity,
                averagePrice: Position.AveragePrice,
                unrealizedPnL: Position.GetUnrealizedProfitLoss(PerformanceUnit.Currency),
                realizedPnL: SystemPerformance.AllTrades.TradesPerformance.Currency.CumProfit,
                lastUpdate: DateTime.UtcNow
            );

            var account = new AccountInfo(
                equity: Account.Get(AccountItem.CashValue, Currency.UsDollar),
                buyingPower: Account.Get(AccountItem.BuyingPower, Currency.UsDollar),
                dailyPnL: SystemPerformance.AllTrades.TradesPerformance.Currency.CumProfit,
                maxDrawdown: SystemPerformance.AllTrades.TradesPerformance.Currency.MaxDrawdown,
                lastUpdate: DateTime.UtcNow
            );

            var session = new MarketSession(
                sessionStart: SessionIterator.GetTradingDay().Date.Add(TimeSpan.FromHours(9.5)),
                sessionEnd: SessionIterator.GetTradingDay().Date.Add(TimeSpan.FromHours(16)),
                isRth: true,
                sessionName: "RTH"
            );

            return new StrategyContext(
                symbol: Instrument.MasterInstrument.Name,
                currentTime: DateTime.UtcNow,
                currentPosition: position,
                account: account,
                session: session,
                customData: new Dictionary<string, object>()
            );
        }
        #endregion

        #region SDK Integration
        private StrategyConfig CreateSdkConfiguration()
        {
            var parameters = new Dictionary<string, object>();
            parameters.Add("StopTicks", StopTicks);
            parameters.Add("TargetTicks", TargetTicks);
            // Add strategy-specific parameters here

            var riskConfig = new RiskConfig(
                dailyLossLimit: DailyLossLimit,
                maxTradeRisk: RiskPerTrade,
                maxOpenPositions: 3,
                emergencyFlattenEnabled: true
            );

            var sizingConfig = new SizingConfig(
                method: SizingMethod.FixedDollarRisk,
                minContracts: 1,
                maxContracts: 10,
                riskPerTrade: RiskPerTrade,
                methodParameters: new Dictionary<string, object>()
            );

            return new StrategyConfig(
                name: Name,
                symbol: Instrument.MasterInstrument.Name,
                parameters: parameters,
                riskSettings: riskConfig,
                sizingSettings: sizingConfig
            );
        }

        private RiskDecision ValidateRisk(StrategyIntent intent, StrategyContext context)
        {
            var riskConfig = new RiskConfig(
                dailyLossLimit: DailyLossLimit,
                maxTradeRisk: RiskPerTrade,
                maxOpenPositions: 3,
                emergencyFlattenEnabled: true
            );

            return _riskManager.ValidateOrder(intent, context, riskConfig);
        }

        private SizingResult CalculatePositionSize(StrategyIntent intent, StrategyContext context)
        {
            var sizingConfig = new SizingConfig(
                method: SizingMethod.FixedDollarRisk,
                minContracts: 1,
                maxContracts: 10,
                riskPerTrade: RiskPerTrade,
                methodParameters: new Dictionary<string, object>()
            );

            return _positionSizer.CalculateSize(intent, context, sizingConfig);
        }
        #endregion

        #region NT8 Order Execution
        private void ExecuteTradeInNT8(StrategyIntent intent, SizingResult sizing)
        {
            try
            {
                if (intent.Side == OrderSide.Buy)
                {
                    EnterLong(sizing.Contracts, "SDK_Long");
                    SetStopLoss("SDK_Long", CalculationMode.Ticks, intent.StopTicks);
                    if (intent.TargetTicks.HasValue)
                        SetProfitTarget("SDK_Long", CalculationMode.Ticks, intent.TargetTicks.Value);
                }
                else if (intent.Side == OrderSide.Sell)
                {
                    EnterShort(sizing.Contracts, "SDK_Short");
                    SetStopLoss("SDK_Short", CalculationMode.Ticks, intent.StopTicks);
                    if (intent.TargetTicks.HasValue)
                        SetProfitTarget("SDK_Short", CalculationMode.Ticks, intent.TargetTicks.Value);
                }

                _logger.LogInformation("Trade executed: {0} {1} contracts, Stop: {2}, Target: {3}",
                    intent.Side, sizing.Contracts, intent.StopTicks, intent.TargetTicks);
            }
            catch (Exception ex)
            {
                _logger.LogError("Trade execution failed: {0}", ex.Message);
                throw;
            }
        }
        #endregion

        #region Error Handling
        private void ValidateConfiguration()
        {
            if (StopTicks <= 0)
                throw new ArgumentException("Stop ticks must be greater than 0");
            
            if (TargetTicks <= 0)
                throw new ArgumentException("Target ticks must be greater than 0");
                
            if (DailyLossLimit <= 0)
                throw new ArgumentException("Daily loss limit must be greater than 0");
                
            if (RiskPerTrade <= 0)
                throw new ArgumentException("Risk per trade must be greater than 0");
        }

        private void HandleError(Exception ex)
        {
            // Log error and optionally halt strategy
            _logger.LogCritical("Critical error in strategy: {0}", ex.Message);
            
            // Consider emergency flatten if needed
            // _riskManager.EmergencyFlatten("Critical error occurred");
        }
        #endregion
    }
}
```

### Template 2: Data Converter Class
```csharp
using System;
using System.Collections.Generic;
using NT8.Core.Common.Models;
using NT8.Core.Logging;

namespace NT8.Adapters.NinjaTrader
{
    /// <summary>
    /// Converts between NinjaTrader 8 data formats and SDK data models
    /// Handles all data type conversions with proper error handling
    /// </summary>
    public static class NT8DataConverter
    {
        /// <summary>
        /// Convert NT8 bar data to SDK BarData format
        /// </summary>
        public static BarData ConvertBar(/* NT8 bar parameters */)
        {
            try
            {
                return new BarData(
                    symbol: /* NT8 symbol */,
                    time: /* NT8 time */,
                    open: /* NT8 open */,
                    high: /* NT8 high */,
                    low: /* NT8 low */,
                    close: /* NT8 close */,
                    volume: /* NT8 volume */,
                    barSize: /* NT8 bar size */
                );
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                    String.Format("Failed to convert NT8 bar data: {0}", ex.Message), ex);
            }
        }

        /// <summary>
        /// Convert NT8 account info to SDK AccountInfo format
        /// </summary>
        public static AccountInfo ConvertAccount(/* NT8 account parameters */)
        {
            try
            {
                return new AccountInfo(
                    equity: /* NT8 equity */,
                    buyingPower: /* NT8 buying power */,
                    dailyPnL: /* NT8 daily PnL */,
                    maxDrawdown: /* NT8 max drawdown */,
                    lastUpdate: DateTime.UtcNow
                );
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                    String.Format("Failed to convert NT8 account data: {0}", ex.Message), ex);
            }
        }

        /// <summary>
        /// Convert NT8 position to SDK Position format
        /// </summary>
        public static Position ConvertPosition(/* NT8 position parameters */)
        {
            try
            {
                return new Position(
                    symbol: /* NT8 symbol */,
                    quantity: /* NT8 quantity */,
                    averagePrice: /* NT8 average price */,
                    unrealizedPnL: /* NT8 unrealized PnL */,
                    realizedPnL: /* NT8 realized PnL */,
                    lastUpdate: DateTime.UtcNow
                );
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                    String.Format("Failed to convert NT8 position data: {0}", ex.Message), ex);
            }
        }

        /// <summary>
        /// Validate data before conversion
        /// </summary>
        private static void ValidateData(object data, string dataType)
        {
            if (data == null)
                throw new ArgumentNullException("data", String.Format("{0} data cannot be null", dataType));
        }
    }
}
```

### Template 3: Unit Test Class
```csharp
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NT8.Adapters.NinjaTrader;
using NT8.Core.Common.Models;
using System;

namespace NT8.Integration.Tests.Adapters
{
    [TestClass]
    public class NT8DataConverterTests
    {
        [TestMethod]
        public void ConvertBar_ValidData_ShouldSucceed()
        {
            // Arrange
            // Create test NT8 bar data

            // Act
            var result = NT8DataConverter.ConvertBar(/* test data */);

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual("ES", result.Symbol);
            // Add more specific assertions
        }

        [TestMethod]
        public void ConvertBar_NullData_ShouldThrowException()
        {
            // Act & Assert
            Assert.ThrowsException<ArgumentNullException>(() => 
                NT8DataConverter.ConvertBar(null));
        }

        [TestMethod]
        public void ConvertAccount_ValidData_ShouldSucceed()
        {
            // Arrange
            // Create test NT8 account data

            // Act
            var result = NT8DataConverter.ConvertAccount(/* test data */);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsTrue(result.Equity > 0);
            // Add more specific assertions
        }
    }
}
```

## Implementation Workflow

### Step-by-Step Process for Each Task:

#### Phase 1: Setup and Planning
1. **Read Task Requirements**
   - Review specific task in task breakdown
   - Understand deliverables and success criteria
   - Check dependencies on other tasks

2. **Study Existing Code**
   ```bash
   # Look at similar implementations
   find src/NT8.Core -name "*.cs" | xargs grep -l "pattern"
   ```

3. **Create File Structure**
   ```bash
   # Create required directories if needed
   mkdir -p src/NT8.Adapters/NinjaTrader
   mkdir -p src/NT8.Adapters/Wrappers
   ```

#### Phase 2: Implementation
1. **Start with Template**
   - Copy appropriate template from above
   - Replace placeholders with actual implementation
   - Follow C# 5.0 syntax requirements

2. **Implement Core Functionality**
   - Focus on main requirements first
   - Add error handling as you go
   - Use existing SDK patterns

3. **Test Early and Often**
   ```bash
   # Test compilation frequently
   .\verify-build.bat
   ```

#### Phase 3: Integration Testing
1. **Unit Tests**
   - Create comprehensive unit tests
   - Test edge cases and error conditions
   - Ensure >80% code coverage

2. **NT8 Integration**
   - Copy files to NT8 directories
   - Compile in NT8 NinjaScript Editor
   - Test on simulation account

#### Phase 4: Finalization
1. **Code Review**
   - Use `CODE_REVIEW_CHECKLIST.md`
   - Ensure all requirements met
   - Verify coding standards compliance

2. **Documentation**
   - Update relevant documentation
   - Add code comments
   - Update deployment instructions

## Common Patterns and Best Practices

### Error Handling Pattern
```csharp
try
{
    // Main logic here
}
catch (SpecificException ex)
{
    _logger.LogError("Specific error: {0}", ex.Message);
    // Handle specific case
    throw; // Re-throw if needed
}
catch (Exception ex)
{
    _logger.LogError("Unexpected error in {0}: {1}", methodName, ex.Message);
    throw new InvalidOperationException(
        String.Format("Operation failed: {0}", ex.Message), ex);
}
```

### Parameter Validation Pattern
```csharp
public ReturnType MethodName(Type parameter)
{
    if (parameter == null) 
        throw new ArgumentNullException("parameter");
    
    if (!IsValid(parameter))
        throw new ArgumentException("Invalid parameter value", "parameter");
    
    // Implementation
}
```

### Logging Pattern
```csharp
_logger.LogDebug("Method {0} called with parameter: {1}", methodName, parameter);
_logger.LogInformation("Operation completed successfully: {0}", result);
_logger.LogWarning("Potential issue detected: {0}", issue);
_logger.LogError("Error occurred: {0}", error.Message);
_logger.LogCritical("Critical failure: {0}", criticalError.Message);
```

## Quality Checkpoints

### Before Submitting Code:
- [ ] Compiles without errors (`.\verify-build.bat`)
- [ ] Follows C# 5.0 syntax requirements
- [ ] Includes comprehensive error handling
- [ ] Has unit tests with >80% coverage
- [ ] Follows established code patterns
- [ ] Includes proper documentation
- [ ] Tested with NT8 (for wrapper classes)

### Code Review Criteria:
- [ ] Meets all task requirements
- [ ] Proper integration with existing SDK
- [ ] No breaking changes to Core
- [ ] Performance acceptable
- [ ] Maintainable and readable code

This workflow and templates provide AI agents with clear guidance and proven patterns for implementing NT8 integration while maintaining the quality and compatibility standards of the SDK.