Skip to content

Strategy Development Lifecycle

Complete guide for developing, testing, and deploying trading strategies with TradAI.

Lifecycle Overview

graph LR
    Create --> Develop --> Test --> Backtest --> Register
    Register --> Stage --> ABTest["A/B Test"] --> Promote --> Deploy

Phase 1: Create Strategy

See Creating a Trading Strategy for full setup instructions (wizard, CLI options, cookiecutter, generated file structure, and implementation guide).

Key decision: Choose where to create your strategy:

Repository Purpose When to Use
tradai-uv Platform development Testing framework, infrastructure
tradai-strategies Production strategies Real trading strategies

For tradai-strategies, run just codeartifact-login first (12-hour token), then just new StrategyName.


Phase 2: Develop Strategy

Required Implementation

Every strategy must extend TradAIStrategy and implement these methods:

from tradai.strategy import TradAIStrategy, StrategyMetadata
from tradai.strategy.enums import StrategyCategory

class MomentumStrategy(TradAIStrategy):
    """Momentum-based trading strategy."""

    # Freqtrade required attributes
    timeframe = '1h'
    stoploss = -0.08
    trailing_stop = True
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.02

    # TradAI REQUIRED: Metadata
    def get_metadata(self) -> StrategyMetadata:
        return StrategyMetadata(
            name="MomentumStrategy",
            version="1.0.0",
            description="RSI-based momentum strategy",
            timeframe=self.timeframe,
            category=StrategyCategory.MOMENTUM,
            tags=["rsi", "momentum", "btc"],
        )

    # Freqtrade REQUIRED: Calculate indicators
    def populate_indicators(self, dataframe, metadata):
        dataframe['rsi'] = ta.RSI(dataframe['close'], timeperiod=14)
        dataframe['ema_fast'] = ta.EMA(dataframe['close'], timeperiod=12)
        dataframe['ema_slow'] = ta.EMA(dataframe['close'], timeperiod=26)
        return dataframe

    # Freqtrade REQUIRED: Define entry signals
    def populate_entry_trend(self, dataframe, metadata):
        # Long entry
        dataframe.loc[
            (dataframe['rsi'] < 30) &
            (dataframe['ema_fast'] > dataframe['ema_slow']),
            'enter_long'
        ] = 1

        # Short entry (if enabled)
        dataframe.loc[
            (dataframe['rsi'] > 70) &
            (dataframe['ema_fast'] < dataframe['ema_slow']),
            'enter_short'
        ] = 1

        return dataframe

    # Freqtrade REQUIRED: Define exit signals
    def populate_exit_trend(self, dataframe, metadata):
        dataframe.loc[
            (dataframe['rsi'] > 70),
            'exit_long'
        ] = 1

        dataframe.loc[
            (dataframe['rsi'] < 30),
            'exit_short'
        ] = 1

        return dataframe

Strategy Categories

Category Use Case Typical Timeframe
TREND_FOLLOWING Riding directional moves 1h, 4h, 1d
MOMENTUM Quick momentum captures 15m, 1h
MEAN_REVERSION Fading extreme moves 1h, 4h
BREAKOUT Range expansion 15m, 1h
ARBITRAGE Price discrepancies 1m

Note: Categories map to StrategyCategory enum in tradai.strategy.enums.

ML-Enabled Strategies (FreqAI)

For ML strategies, implement additional methods:

class TrendMLStrategy(TradAIStrategy):
    """ML-enhanced trend following strategy."""

    def feature_engineering_expand_all(self, dataframe, **kwargs):
        """Create features for ML model."""
        dataframe['rsi'] = ta.RSI(dataframe['close'])
        dataframe['macd'] = ta.MACD(dataframe['close'])['macd']
        # Add more features...
        return dataframe

    def feature_engineering_expand_basic(self, dataframe, **kwargs):
        """Basic features using %change."""
        dataframe['pct_change'] = dataframe['close'].pct_change()
        return dataframe

Phase 3: Test Strategy

Unit Tests

# In tradai-strategies repo:
just test-strategy momentum-strategy

# Or run specific tests:
cd strategies/momentum-strategy && uv run pytest tests/ -k "test_metadata"

Test Structure

# tests/test_strategy.py
import pytest
from momentum_strategy.strategy import MomentumStrategy

def test_metadata():
    """Test strategy metadata is valid."""
    strategy = MomentumStrategy({})
    metadata = strategy.get_metadata()

    assert metadata.name == "MomentumStrategy"
    assert metadata.version == "1.0.0"
    assert metadata.timeframe == "1h"

def test_indicators(sample_dataframe):
    """Test indicators are populated."""
    strategy = MomentumStrategy({})
    result = strategy.populate_indicators(sample_dataframe, {})

    assert 'rsi' in result.columns
    assert 'ema_fast' in result.columns
    assert 'ema_slow' in result.columns

def test_entry_signals(sample_dataframe_with_indicators):
    """Test entry signals are generated."""
    strategy = MomentumStrategy({})
    result = strategy.populate_entry_trend(sample_dataframe_with_indicators, {})

    assert 'enter_long' in result.columns
    assert result['enter_long'].sum() > 0  # At least some signals

Lint and Type Check

# Lint entire project
just lint

# Lint specific strategy
tradai strategy lint ./momentum-strategy/

Phase 4: Backtest

Running Backtests

# Quick smoke backtest (30 days)
tradai backtest quick MomentumStrategy --period 30d --local

# Full backtest (custom date range)
tradai backtest quick MomentumStrategy --timerange 20240101-20241201 --local

Via API

# Submit backtest
curl -X POST http://localhost:8000/api/v1/backtests \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "strategy": "MomentumStrategy",
      "pairs": ["BTC/USDT:USDT"],
      "timeframe": "1h",
      "date_range": {
        "start": "2024-01-01T00:00:00Z",
        "end": "2024-12-01T00:00:00Z"
      },
      "stake_amount": 100.0,
      "dry_run_wallet": 10000.0
    },
    "experiment_name": "momentum-v1-btc",
    "priority": 5
  }'

# Check status
curl http://localhost:8000/api/v1/backtests/${JOB_ID} | jq

Quality Thresholds

Metric Minimum Target
Sharpe Ratio > 1.0 > 1.5
Profit Factor > 1.2 > 1.5
Max Drawdown < 20% < 15%
Win Rate > 40% > 50%
Total Trades > 50 > 100

Phase 5: Register

Automatic Registration (CI/CD)

When you tag a release, CI automatically: 1. Runs full backtest 2. Builds Docker image 3. Pushes to ECR 4. Registers to MLflow Model Registry

# Tag release
git tag momentum-strategy-v1.0.0
git push --tags

Manual Registration

# Via CLI
tradai strategy register ./momentum-strategy --env dev --count 1

# Via API
curl -X POST http://localhost:8003/api/v1/strategies/MomentumStrategy/register \
  -H "Content-Type: application/json" \
  -d '{
    "backtest_run_id": "mlflow_run_id_here",
    "docker_image_uri": "ecr_image_uri_here",
    "description": "Initial release",
    "thresholds": {
      "min_sharpe": 1.0,
      "min_profit_factor": 1.2,
      "max_drawdown": 20.0
    }
  }'

Phase 6: Stage

Stage the strategy for validation testing (dry-run environment).

# Via CLI
tradai strategy stage MomentumStrategy --version 1

# Via API
curl -X POST http://localhost:8000/api/v1/strategies/MomentumStrategy/stage \
  -H "Content-Type: application/json" \
  -d '{"version": "1"}'

Staging Validation

Run the strategy in dry-run mode for 7 days: - Monitor for errors - Validate signal generation - Check resource usage


Phase 7: A/B Test (Optional)

Compare new version against existing champion.

# Create A/B test
curl -X POST http://localhost:8003/api/v1/models/MomentumStrategy/challenges \
  -H "Content-Type: application/json" \
  -d '{
    "champion_version": "1",
    "challenger_version": "2",
    "min_trades": 100,
    "max_duration_hours": 168,
    "enable_canary": true
  }'

# Check results
curl http://localhost:8003/api/v1/challenges/${CHALLENGE_ID}/evaluate | jq

Traffic Split (Canary)

Stage Champion Challenger
1 95% 5%
2 90% 10%
3 75% 25%
Final 50% 50%

Phase 8: Promote

Promote the strategy to Production.

# Via CLI
tradai strategy set-version MomentumStrategy 2 --stage Production

# Via API
curl -X POST http://localhost:8000/api/v1/strategies/MomentumStrategy/promote \
  -H "Content-Type: application/json" \
  -d '{
    "version": "2",
    "archive_previous": true,
    "skip_validation": false
  }'

Promotion Requirements

  • Staging validation passed (7 days)
  • A/B test results positive (if run)
  • Quality thresholds met
  • No critical errors in logs
  • Manual approval (if required)

Phase 9: Deploy

Deploy the strategy to live trading.

# Deploy to ECS
tradai deploy strategy momentum-strategy \
  --env prod \
  --version v1.0.0 \
  --mode dry-run  # or 'live'

# Via API
curl -X POST http://localhost:8000/api/v1/strategies/MomentumStrategy/run \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "dry-run",
    "timeframe": "1h",
    "symbols": ["BTC/USDT:USDT"],
    "config_overrides": {
      "stake_amount": 100
    }
  }'

Monitoring

# List running instances
curl http://localhost:8000/api/v1/strategies/MomentumStrategy/instances | jq

# View logs
curl http://localhost:8000/api/v1/strategies/MomentumStrategy/instances/${ID}/logs | jq

# Stop instance
curl -X POST http://localhost:8000/api/v1/strategies/MomentumStrategy/instances/${ID}/stop

Version Management

Semantic Versioning

<major>.<minor>.<patch>

1.0.0 - Initial release
1.1.0 - New feature (backward compatible)
1.1.1 - Bug fix
2.0.0 - Breaking change

Tagging Convention

# Format: <strategy-slug>-v<version>
git tag momentum-strategy-v1.0.0
git tag trend-ml-v2.1.3

Model Registry Stages

Stage Description Use
None Just registered Initial state
Staging Validation testing Dry-run environment
Production Live trading Real capital
Archived Deprecated Rollback candidate

Rollback

If issues are detected in production:

# Via CLI
tradai deploy rollback MomentumStrategy --env dev

# Via API
curl -X POST http://localhost:8000/api/v1/models/MomentumStrategy/rollback \
  -H "Content-Type: application/json" \
  -d '{
    "target_version": "1",
    "dry_run": false
  }'

Strategy Development:

Testing & Validation:

Deployment & Operations:

Reference: