validate-strategy¶
Validates strategy configuration for Step Functions workflow. Validates the simplified Step Functions payload (not the full strategy config).
Overview¶
| Property | Value |
|---|---|
| Trigger | Step Functions / Direct |
| Runtime | Python 3.11 |
| Timeout | 30 seconds |
| Memory | 256 MB |
| Settings class | ValidateStrategySettings |
What This Lambda Validates¶
This handler validates the Step Functions payload only, not the full strategy configuration. The detailed config validation (stoploss, stake amounts, trailing stops, etc.) happens in the ECS container when it loads the strategy. This Lambda provides a fast, lightweight pre-check.
Input Schema: StrategyValidationRequest¶
Step Functions sends a simplified payload:
{
"strategy_name": "PascalStrategy", # Required: must be non-empty string
"timeframe": "1h", # Optional: validated if provided
"symbols": ["BTC/USDT:USDT"], # Optional: validated if provided
"start_date": "20240101", # Optional: YYYYMMDD format
"end_date": "20240131", # Optional: YYYYMMDD format
"run_id": "uuid-123", # Optional: passed through
"experiment_name": "backtest-pascal", # Optional: passed through
"freqai_enabled": false, # Optional: triggers FreqAI validation
"freqai_model_name": "pascal-model" # Required if freqai_enabled=true
}
The schema uses model_config = {"extra": "allow"} to accept extra fields from Step Functions without failing.
Output Schema¶
Responses use Step Functions compatible format via LambdaResponse.to_step_functions():
Success¶
{
"statusCode": 200,
"body": {
"success": true,
"data": {
"valid": true,
"strategy_name": "PascalStrategy",
"errors": [],
"warnings": []
},
"environment": "dev"
}
}
Validation Failure¶
{
"statusCode": 200,
"body": {
"success": true,
"data": {
"valid": false,
"strategy_name": "PascalStrategy",
"errors": [
"Invalid timeframe '1x'. Valid options: ['1d', '1h', '1m', '1w', '15m', '30m', '4h', '5m']",
"Invalid quote currency 'EUR' in BTC/EUR. Valid: ['BTC', 'BUSD', 'ETH', 'USD', 'USDT']"
],
"warnings": []
},
"environment": "dev"
}
}
Environment Variables¶
| Variable | Required | Default | Description |
|---|---|---|---|
MLFLOW_TRACKING_URI | No | - | MLflow server URL |
MLFLOW_TRACKING_USERNAME | No | - | MLflow basic auth username |
MLFLOW_TRACKING_PASSWORD | No | - | MLflow basic auth password |
MODEL_REGISTRY_NAME | No | tradai-models | MLflow registry name |
REQUIRE_MLFLOW_MODEL | No | false | Require model existence for FreqAI strategies |
Validation Steps¶
The handler executes these validation steps in order:
Step 1: Parse StrategyValidationRequest¶
Parses the event into StrategyValidationRequest using Pydantic. On parse failure, returns schema-level errors (e.g., missing strategy_name).
Step 2: Validate Timeframe (if provided)¶
Valid timeframes: 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
Step 3: Validate Symbols (if provided)¶
For each symbol: - Must contain / separator (e.g., BTC/USDT) - Base currency: 2-10 characters - Quote currency must be one of: USDT, BUSD, USD, BTC, ETH - For futures (BTC/USDT:USDT): settlement currency validated against the same set
Step 4: FreqAI Checks¶
- If
freqai_enabled=trueandfreqai_model_nameis missing: error - If
freqai_enabled=true,freqai_model_nameis set,REQUIRE_MLFLOW_MODEL=true, andMLFLOW_TRACKING_URIis configured: queries MLflow registry for model existence - MLflow check uses lazy-imported
mlflow.tracking.MlflowClientto reduce cold start
Step 5: Validate Date Range (if provided)¶
- Both
start_dateandend_datemust be 8 characters (YYYYMMDD format) start_datemust be beforeend_date
Note: strategy_version is not resolved here (#750/#783)¶
strategy_version is execution-inert — it never selects the strategy code or image (task-def selection is version-independent; images run at :latest). It is validated syntactically on BacktestConfig at submit time and carried for lineage only; this Lambda no longer receives it or resolves it against MLflow (the old resolution + resolved_version output were removed). Strategy version pinning is a v4 Release concern (#602/#366).
Validation Flow¶
flowchart TD
A[Receive Event] --> B[Parse StrategyValidationRequest]
B -->|Invalid| C[Return schema errors]
B -->|Valid| D{Timeframe provided?}
D -->|Yes| E[Validate against VALID_TIMEFRAMES set]
D -->|No| F{Symbols provided?}
E --> F
F -->|Yes| G[Validate each symbol format and currencies]
F -->|No| H{FreqAI enabled?}
G --> H
H -->|Yes| I{freqai_model_name provided?}
H -->|No| J{Dates provided?}
I -->|No| K[Error: model required]
I -->|Yes| L{REQUIRE_MLFLOW_MODEL and URI set?}
L -->|Yes| M[Query MLflow registry]
L -->|No| J
M -->|Not found| N[Error: model not found]
M -->|Found| J
K --> J
N --> J
J -->|Yes| O[Validate date range format and order]
J -->|No| R[Build ValidationResult]
O --> R
R --> S[Return via to_step_functions]
C --> S Step Functions Integration¶
{
"ValidateStrategy": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:validate-strategy",
"Parameters": {
"strategy_name.$": "$.strategy_name"
},
"ResultPath": "$.validation",
"Next": "CheckValidation"
},
"CheckValidation": {
"Type": "Choice",
"Choices": [{
"Variable": "$.validation.body.data.valid",
"BooleanEquals": true,
"Next": "LaunchBacktest"
}],
"Default": "ValidationFailed"
}
}
Pydantic Models¶
StrategyValidationRequest¶
Lightweight schema for Step Functions input. Uses extra="allow" to pass through unknown fields.
StrategyConfig¶
Full strategy configuration schema (for detailed validation if the full config is provided). Uses extra="forbid". Includes risk parameters: stoploss, trailing_stop, stake_amount, max_open_trades.
ValidationResult¶
Frozen Pydantic model with: valid, strategy_name, errors, warnings.
Related¶
- backtest-consumer - Consumes validated requests
- compare-models - Uses validated configs