Trading systems process diverse request types - market orders, limit orders, options, compliance checks - each requiring specialized handling. Two fundamental patterns enable this: prompt chaining for sequential multi-step processing, and routing for intelligent task distribution. Mastering these patterns is essential for building robust financial workflows.
Prompt Chaining: The Assembly Line
Prompt chaining decomposes complex tasks into a sequence of simpler steps, where each step’s output becomes the next step’s input. Like an assembly line where specialized stations perform focused tasks, prompt chains break down problems that would overwhelm a single LLM call.
Consider processing a trading order with a single prompt:
1 2 3 4 5 6 7 8
# Single prompt approach - problematic single_prompt = """ Parse this trade request, validate the order details, check risk limits, determine if margin requirements are met, execute the trade if approved, generate confirmation, and log the transaction. Request: {trade_request} """
Problems with this approach:
Cognitive overload: Too many tasks reduce accuracy on each
Debugging difficulty: Can’t tell where failures occur
No intermediate validation: Errors cascade undetected
No recovery points: Must restart entire process on failure
With chaining:
1 2 3 4 5
# Chained approach - each step focused parse_prompt = "Extract order type, symbol, quantity, and price from: {request}" validate_prompt = "Validate this order against market rules: {parsed_order}" risk_prompt = "Check position limits and margin for: {validated_order}" execute_prompt = "Generate execution instruction for: {approved_order}"
Each step can be validated, retried, or handled separately.
The Error Propagation Problem
The critical challenge with chaining: errors compound. A small mistake in step 1 becomes a disaster by step 5.
flowchart LR
S1[Step 1 Small Error] --> S2[Step 2 Amplified]
S2 --> S3[Step 3 Worse]
S3 --> S4[Step 4 Disaster]
classDef orangeClass fill:#F39C12,stroke:#333,stroke-width:2px,color:#fff
classDef pinkClass fill:#E74C3C,stroke:#333,stroke-width:2px,color:#fff
class S1 orangeClass
class S4 pinkClass
Example: A parsing error extracts quantity as 10,000 instead of 1,000. Without validation:
Risk check approves (incorrect quantity within limits)
Execution proceeds with 10x intended size
Customer loses significant money
Solution: Validation gates between every step.
Validation Strategies
Four primary approaches to validating intermediate outputs:
@validator('price') deflimit_orders_need_price(cls, v, values): if values.get('order_type') == 'limit'and v isNone: raise ValueError('Limit orders require a price') return v
defvalidate_parsed_order(output: str) -> TradeOrder: """Programmatic validation of parsed output""" try: data = json.loads(output) return TradeOrder(**data) except (json.JSONDecodeError, ValidationError) as e: raise ValidationError(f"Invalid order format: {e}")
Best for: Format validation, range checks, required fields
2. LLM-Based Validation
Use another LLM call to assess quality:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
validation_prompt = """ Review this risk assessment for a trade order. Assessment: {risk_assessment} Order details: {order} Check for: 1. All risk factors considered (market risk, credit risk, liquidity risk) 2. Calculations appear reasonable 3. Recommendation aligns with risk level 4. No obvious contradictions Rate quality 1-10 and explain any issues found. """
Best for: Subjective quality, completeness, logical consistency
critique_prompt = """ Review this trade analysis for quality: {analysis} Criteria: - All required fields present - Numbers are reasonable for the market - Conclusions follow from data Identify any issues. """
refine_prompt = """ Original analysis: {analysis} Critique: {critique} Produce an improved version addressing the critique. """
While chaining handles sequential processing, routing handles task distribution - directing different inputs to appropriate specialized handlers.
flowchart TD
I[Incoming Request] --> C[Classifier]
C --> R{Router}
R -->|Equity| EQ[Equity Handler]
R -->|Options| OPT[Options Handler]
R -->|Forex| FX[Forex Handler]
R -->|Crypto| CR[Crypto Handler]
EQ --> O[Output]
OPT --> O
FX --> O
CR --> O
classDef blueClass fill:#4A90E2,stroke:#333,stroke-width:2px,color:#fff
classDef orangeClass fill:#F39C12,stroke:#333,stroke-width:2px,color:#fff
class C blueClass
class R orangeClass
Two Stages: Classification + Dispatch
Stage 1: Classification
Determine the input’s nature, category, or intent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classification_prompt = """ Classify this trading request into one category: Request: {request} Categories: - EQUITY_ORDER: Stock buy/sell orders - OPTIONS_ORDER: Options contracts - FOREX_ORDER: Currency exchange - CRYPTO_ORDER: Cryptocurrency trades - ACCOUNT_QUERY: Balance, position inquiries - COMPLIANCE_CHECK: Regulatory verification Respond with category name only. """
Stage 2: Task Dispatch
Route to appropriate handler based on classification:
# Keyword matching ifany(word in request_lower for word in ["option", "call", "put", "strike"]): return"OPTIONS_ORDER" ifany(word in request_lower for word in ["btc", "eth", "crypto", "bitcoin"]): return"CRYPTO_ORDER" ifany(word in request_lower for word in ["eur", "usd", "forex", "fx"]): return"FOREX_ORDER" ifany(word in request_lower for word in ["buy", "sell", "stock", "shares"]): return"EQUITY_ORDER" ifany(word in request_lower for word in ["balance", "position", "holdings"]): return"ACCOUNT_QUERY"
return"UNKNOWN"
LLM-Based Classification
Better for nuanced or ambiguous requests:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
llm_classification_prompt = """ Analyze this trading request and classify it. Request: "{request}" Consider: - What action is being requested? - What asset type is involved? - Is this a trade or an inquiry? Return JSON: { "category": "CATEGORY_NAME", "confidence": 0.0-1.0, "reasoning": "brief explanation" } """
Comments