---
title: "Analyse a strategy and return machine-readable robustness semantics."
method: POST
path: "/api/v1/agent/analyze"
tags: ["Agent API"]
---

# Analyse a strategy and return machine-readable robustness semantics.

`POST /api/v1/agent/analyze`

## Request

- Base URL: `https://crashtestyourstrategy.com` (the document declares no server; this is the origin it was published from)
- URL: `https://crashtestyourstrategy.com/api/v1/agent/analyze`
- Auth: none declared

Accepts either a natural-language description (`input_type=natural_language`) or a canonical strategy JSON (`input_type=strategy_json`). Parses (if NL), runs the robustness backtest across the curated case set, and returns agent-optimized structured semantics: per-regime behavior labels, top failure modes with impact-type ontology, evaluation confidence, and methodological limitations. Output is descriptive, not advisory. Schema family `ctys-agent`, current version `ctys-agent-v1`.

## Request body

- union
  - AnalyzeNLRequest
    - `input_type` 'natural_language', required: Discriminator: tells the endpoint to LLM-parse `strategy_text` first.
    - `strategy_text` string, required: Plain-English (or German) strategy description. The LLM parser converts this to canonical strategy JSON before the backtest. Be specific about entry/exit triggers, indicators, and stop levels — vague text reduces parse confidence.
    - `asset` string, nullable: Asset symbol: SPY | QQQ | BTC | ETH | GOLD | WTI | VIX. If absent, inferred from the parsed strategy or defaults to SPY.
    - `num_runs` integer: Replicas per synthetic case (empirical anchors are always n=1). Higher = more stable confidence but slower.
  - AnalyzeJSONRequest
    - `input_type` 'strategy_json', required: Discriminator: skip the LLM parse step and use the provided canonical strategy JSON directly.
    - `strategy` object, required: Canonical strategy JSON, same shape as POST /api/v1/backtest/robustness/quick. Required fields: entry_conditions, exit_conditions, direction, position_sizing, position_size. Optional: stop_loss (percent), take_profit, max_positions.
    - `asset` string, nullable: Asset symbol: SPY | QQQ | BTC | ETH | GOLD | WTI | VIX. Defaults to SPY if absent.
    - `num_runs` integer: Replicas per synthetic case (empirical anchors are always n=1). Higher = more stable but slower.

## Response `200`

Successful robustness analysis with structured agent-optimized output.

- AgentAnalyzeResponse
  - `robustness_score` number, required: V2 composite robustness score on the 0..100 scale. Equal-weight mean across populated FM-buckets with shrinkage. Higher = more uniform behaviour across the curated regimes.
  - `robustness_class` 'fragile' | 'moderate' | 'robust', required: Monotonic class derived from robustness_score. 'fragile' (<50) | 'moderate' (50–70) | 'robust' (≥70).
  - `evaluation_confidence` EvaluationConfidence, required
    - `level` 'low' | 'moderate' | 'high', required: Coarse confidence label. high | moderate | low.
    - `classified_ratio` number, required: Share (0..1) of replicas that met operational ex-post FM-classification gates without augmentation.
    - `sparse_bucket_count` integer, required: Number of FM-buckets where ex-post classification produced < APRIORI_AUGMENT_THRESHOLD replicas and a-priori augmentation kicked in.
    - `augmented_replicas_total` integer, required: Total replicas added via Phase 18d a-priori fallback across all sparse buckets.
    - `rationale` string, required: Human-readable explanation of the confidence assignment — surfaces the dominant signal (low classification ratio, many sparse buckets, etc.).
  - `summary` string, required: Short deterministic machine-friendly summary (≤200 chars). Names the score, class, strongest and weakest regimes. Use for one-line citations.
  - `interpretation_text` string, required: Longer narrative, LLM-citable. Use for human-readable answers / generated reports / agent reasoning chains. Descriptive, not advisory.
  - `headline_metrics` HeadlineMetrics, required
    - `median_return` number, required: Median total return across replicas, as a fraction (-1..+∞). 0.05 = +5%.
    - `p5_return` number, required: 5th-percentile total return across replicas. The 'worst case' return floor at the 5% tail.
    - `wcdd_95` number, required: 95th-percentile worst-case drawdown MAGNITUDE (0..1, positive). 5% of cases produced drawdowns deeper than this.
    - `median_drawdown` number, required: Median drawdown magnitude across replicas (0..1, positive).
    - `failure_rate_pct` number, required: Percentage (0..100) of cases that breached the failure-drawdown threshold (default 50% magnitude).
    - `n_replicas` integer, required: Total replica count across the curated case set for this asset.
    - `asset` string, required: Asset symbol the strategy was evaluated against.
  - `per_regime` PerRegimeEntry[], required: One entry per populated FM-bucket. Sorted by score descending (strengths first).
    - `regime` string, required: Failure-mode termCode from the 10-axis taxonomy. See /ontology for canonical definitions.
    - `label` string, required: Human-readable semantic label for the regime (matches /ontology/{slug} term descriptions).
    - `behavior` 'stable' | 'sensitive' | 'degrading' | 'inactive', required: Qualitative regime behaviour. Controlled enum: 'stable' (score ≥ pool baseline), 'sensitive' (within 10 points below pool), 'degrading' (>10 points below pool), 'inactive' (bucket has < 3 replicas after augmentation).
    - `score` number, required: Per-FM-bucket score on the V2 0..100 scale. Higher = better behaviour under this regime.
    - `n_replicas` integer, required: Replicas in this bucket (ex-post + a-priori-augmented combined).
    - `shrinkage_alpha` number, required: Per-bucket shrinkage weight (1.0 = no shrinkage; <1.0 = bucket partially pooled toward overall).
    - `n_augmented` integer, required: Replicas added via Phase 18d a-priori augmentation (subset of n_replicas).
  - `top_failure_modes` TopFailureMode[], required: Up to 3 weakest buckets where bucket_score < pool_score. May be empty — check top_failure_modes_status for the reason.
    - `mode` string, required: Failure-mode termCode where the strategy degrades most. See /ontology.
    - `severity` 'low' | 'moderate' | 'high' | 'critical', required: Qualitative severity. Controlled enum: 'low' (within 5 pts of pool), 'moderate' (5–15 pts below), 'high' (15–25 pts below), 'critical' (>25 pts below pool baseline).
    - `impact_type` 'drawdown_expansion' | 'return_instability' | 'volatility_amplification' | 'whipsaw_sensitivity' | 'trend_dependency' | 'tail_loss_acceleration', required: Failure-mechanism ontology. Controlled enum: drawdown_expansion | return_instability | volatility_amplification | whipsaw_sensitivity | trend_dependency | tail_loss_acceleration.
    - `expected_behavior` string, required: Plain-language phrase describing how the strategy degrades in this regime.
    - `bucket_score` number, required: The bucket's 0..100 score (mirrors the per_regime entry's score field).
    - `delta_from_pool` number, required: bucket_score minus overall_pool_score. Negative = regime-specific weakness vs the pool baseline.
  - `top_failure_modes_status` 'present' | 'no_underperforming_buckets' | 'barely_active', required: Disambiguates an empty top_failure_modes list. 'present' — list contains entries. 'no_underperforming_buckets' — every FM-bucket score is at or above the overall pool baseline; no regime-specific weakness identified. 'barely_active' — strategy rarely takes positions or holds minimal exposure across cases, so bucket scores are uniform and not informative. An empty list does NOT mean 'no risk'.
  - `regime_class_summary` object, required: Aggregation into 4 regime classes: trend_regimes | mean_reverting_regimes | volatility_regimes | tail_event_regimes. Descriptive only — does NOT imply suitability or recommendation for any regime.
  - `caveats` string[], required: Inline trust caveats — always include the BaFin/WpHG framing and the curated-case-set qualifier.
  - `methodological_limitations` string[], required: Explicit model boundaries — agents should not infer beyond these.
  - `report_url` string, nullable: Persistent citable URL. /s/{slug} when the input matched a catalog strategy; /r/{hash} for ad-hoc inputs (DB-persisted).
  - `methodology_url` string, required: Link to the full methodology page describing case catalog, simulator, and scoring architecture.
  - `catalog_match_slug` string, nullable: Slug of the matching catalog strategy if entry/exit conditions are an exact match. Null for ad-hoc inputs.
  - `schema_family` string: Schema family name. Stable across versions within the family.
  - `schema_version` string: Specific schema version within the family. Bump for breaking changes; additive changes keep this stable.
  - `generated_utc` string, required: ISO-8601 UTC timestamp when the response was produced. Use for cache invalidation.

## Other responses

- `400`: Parse failed (natural-language input couldn't be reliably parsed).
- `422`: Canonical strategy_json is missing required fields. Deliberately strict — garbage-shape inputs are rejected here rather than silently producing an inactive-fallback score that could be misread as a real result.
- `429`: Rate limit exceeded — see /interop for tier limits.

---

[API](https://skmtc.dev/crashtestyourstrategy/apis/crashtestyourstrategy-api.md) · [All operations](https://skmtc.dev/crashtestyourstrategy/apis/crashtestyourstrategy-api/llms.txt) · [OpenAPI document](https://skmtc.dev/crashtestyourstrategy/apis/crashtestyourstrategy-api/revisions/a4751a2748fd?raw)
