Algorithmic Trading Rules Analysis
Overview
In this example, we analyze a complex algorithmic trading system with hundreds of business rules governing when and how trades can execute. We use Imandra CodeLogician to detect redundant rules, verify critical properties, and gain complete confidence in the system's behavior.
Why This Matters
Traditional testing cannot prove rules are redundant or correct across all possible inputs. Formal verification provides mathematical certainty—not just 99.9% confidence, but 100%.
Background
The Trading System
This example models an algorithmic trading execution system with several key components:
Algo Types: Different execution strategies
BENCHMARK_TIME- Execute over time benchmarked to marketBENCHMARK_VOLUME- Execute benchmarked to market volumeBENCHMARK_CLOSE- Execute with focus on closing priceBENCHMARK_CLOSE_ONLY- Execute only during market closeLIQUIDITY_SEEK_PASSIVE- Seek liquidity passivelyLIQUIDITY_SEEK_AGGRESSIVE- Seek liquidity aggressively
Trading Phases: When trading can occur
CONTINUOUS- Normal market hoursCLOSE- Market closing auction
Liquidity Destinations: Where orders are sent
- Principal destinations (1, 2, Close)
- Primary destinations (1, 2, Close)
- Independent destinations (1, 2, Close)
The Python Model
The team built a comprehensive Python model with enums, dataclasses, and validation functions:
from enum import Enum
from dataclasses import dataclass
class AlgoType(Enum):
BENCHMARK_TIME = 'benchmark time'
BENCHMARK_VOLUME = 'benchmark volume'
BENCHMARK_CLOSE = 'benchmark close'
BENCHMARK_CLOSE_ONLY = 'benchmark close - close only'
LIQUIDITY_SEEK_PASSIVE = 'liquidity seek - passive'
LIQUIDITY_SEEK_AGGRESSIVE = 'liquidity seek - aggressive'
class TradingPhase(Enum):
CONTINUOUS = 'Continuous'
CLOSE = 'Close'
class ClientID(Enum):
ABC = 'abc'
DEF = 'def'
# ... more clients
XYZ = 'xyz'
def is_trading_phase_eligible_for_algo_type(
algo_type: AlgoType,
trading_phase: TradingPhase
) -> bool:
"""Check if a trading phase is eligible for an algo type."""
eligibility_table = {
AlgoType.BENCHMARK_TIME: {
TradingPhase.CONTINUOUS: True,
TradingPhase.CLOSE: True
},
AlgoType.BENCHMARK_CLOSE_ONLY: {
TradingPhase.CONTINUOUS: False, # Only CLOSE allowed!
TradingPhase.CLOSE: True
},
# ... other algo types
}
return eligibility_table[algo_type][trading_phase]The Problem
As the trading system evolved, client-specific exceptions were added to handle special cases:
def is_trading_phase_eligible_for_client_and_algo(
client_id: ClientID,
algo_type: AlgoType,
trading_phase: TradingPhase
) -> bool:
"""Check eligibility for specific client and algo combination."""
# ⚠️ Special rule for client XYZ
if client_id == ClientID.XYZ and algo_type == AlgoType.BENCHMARK_CLOSE_ONLY:
# Client XYZ can only trade in CLOSE phase with Benchmark Close Only
return trading_phase == TradingPhase.CLOSE
# For all other cases, use the general rule
return is_trading_phase_eligible_for_algo_type(algo_type, trading_phase)The Question
Is this special case actually doing anything?
Looking at the base rule, BENCHMARK_CLOSE_ONLY already restricts all clients to the CLOSE phase only. The XYZ rule might be redundant!
The Testing Problem
Traditional testing can't definitively prove redundancy. You'd need to test:
- All client IDs (9 values)
- All algo types (6 values)
- All trading phases (2 values)
- = 108 test combinations
But even then, you're only testing specific cases—not proving the property holds universally.
The Solution
Formal Verification with CodeLogician provides mathematical proof, not just empirical testing.
The Workflow
Step 1: Write a verification function in Python:
def verify_xyz_rule_is_redundant(
client_id: ClientID,
algo_type: AlgoType,
trading_phase: TradingPhase
) -> bool:
"""Verify the special case produces identical results to the general rule."""
if client_id == ClientID.XYZ and algo_type == AlgoType.BENCHMARK_CLOSE_ONLY:
special_case_result = (trading_phase == TradingPhase.CLOSE)
general_rule_result = is_trading_phase_eligible_for_algo_type(
algo_type,
trading_phase
)
return special_case_result == general_rule_result
return TrueStep 2: Use CodeLogician to formalize to IML:
type algo_type =
| Benchmark_time
| Benchmark_volume
| Benchmark_close
| Benchmark_close_only
| Liquidity_seek_passive
| Liquidity_seek_aggressive
type trading_phase = Continuous | Close
type client_id = ABC | DEF | GHI | JLK | LMN | OPQ | RST | UVW | XYZ
let verify_xyz_rule_is_redundant
(client_id : client_id)
(algo_type : algo_type)
(trading_phase : trading_phase) : bool =
if client_id = XYZ && algo_type = Benchmark_close_only then
let special_case_result = (trading_phase = Close) in
let general_rule_result =
is_trading_phase_eligible_for_algo_type algo_type trading_phase
in
special_case_result = general_rule_result
else
trueStep 3: Generate and prove verification goals:
✓ PROVED
∀ client_id, algo_type, trading_phase:
verify_xyz_rule_is_redundant(client_id, algo_type, trading_phase) = true
Examples in Action
Detecting Redundant Rules
We formally verified that the special case rule for client XYZ with BENCHMARK_CLOSE_ONLY is completely redundant.
Verification Results
∀ client_id, algo_type, trading_phase: verify_xyz_rule_is_redundant(...) = true
The special case result always equals the general rule result.
∀ trading_phase: eligible_for_client_and_algo(XYZ, BENCHMARK_CLOSE_ONLY, tp) = eligible_for_algo_type(BENCHMARK_CLOSE_ONLY, tp)
The two functions are mathematically equivalent for XYZ + BENCHMARK_CLOSE_ONLY.
Truth Table Comparison
| Client | Algo Type | Trading Phase | Special Case | General Rule | Match? |
|---|---|---|---|---|---|
| XYZ | BENCHMARK_CLOSE_ONLY | CONTINUOUS | False | False | ✓ |
| XYZ | BENCHMARK_CLOSE_ONLY | CLOSE | True | True | ✓ |
| ABC | BENCHMARK_CLOSE_ONLY | CONTINUOUS | False | False | ✓ |
| ABC | BENCHMARK_CLOSE_ONLY | CLOSE | True | True | ✓ |
Recommendation
The special case can be safely removed. The simplified function would be:
def is_trading_phase_eligible_for_client_and_algo(
client_id: ClientID,
algo_type: AlgoType,
trading_phase: TradingPhase
) -> bool: # The general rule handles all cases correctly
return is_trading_phase_eligible_for_algo_type(
algo_type,
trading_phase
)Step-by-Step Tutorial
Expand: How to Use CodeLogician for Redundancy Detection
Step 1: Identify Suspicious Rules
Look for patterns where specific rules might duplicate base logic:
# Specific rule
if client_id == ClientID.XYZ and algo_type == AlgoType.BENCHMARK_CLOSE_ONLY:
return trading_phase == TradingPhase.CLOSE
# Base rule
AlgoType.BENCHMARK_CLOSE_ONLY: {
TradingPhase.CONTINUOUS: False,
TradingPhase.CLOSE: True
}Question: Does the specific rule add any behavior beyond the base rule?
Step 2: Create a Verification Function
Add a function that compares the specific rule to the general rule:
def verify_xyz_rule_is_redundant(
client_id: ClientID,
algo_type: AlgoType,
trading_phase: TradingPhase
) -> bool:
"""
Verify that the special case produces identical results
to the general rule.
"""
if client_id == ClientID.XYZ and algo_type == AlgoType.BENCHMARK_CLOSE_ONLY:
special_case_result = (trading_phase == TradingPhase.CLOSE)
general_rule_result = is_trading_phase_eligible_for_algo_type(
algo_type,
trading_phase
)
return special_case_result == general_rule_result
return True # Not testing this caseStep 3: Use CodeLogician to Formalize
from code_logician import create_thread, init_state, agent_formalizer
# Create a thread
thread_id = create_thread()
# Initialize with your Python code
init_state(thread_id, src_code=your_python_code, src_lang="python")
# Run automated formalization
agent_formalizer(thread_id, no_refactor=False)CodeLogician transforms your Python into IML (Imandra Modeling Language):
type client_id = ABC | DEF | GHI | JLK | LMN | OPQ | RST | UVW | XYZ
type algo_type = Benchmark_time | Benchmark_volume | ...
type trading_phase = Continuous | Close
let verify_xyz_rule_is_redundant
(client_id : client_id)
(algo_type : algo_type)
(trading_phase : trading_phase) : bool =
if client_id = XYZ && algo_type = Benchmark_close_only then
let special_case_result = (trading_phase = Close) in
let general_rule_result =
is_trading_phase_eligible_for_algo_type algo_type trading_phase
in
special_case_result = general_rule_result
else
trueStep 4: Generate Verification Goals
from code_logician import gen_vgs
gen_vgs(
thread_id,
description="""
Prove that the special case rule for client XYZ with
BENCHMARK_CLOSE_ONLY is redundant. Specifically:
1. Verify that verify_xyz_rule_is_redundant always returns true
2. Verify that the client-specific function produces identical
results to the general function
"""
)Step 5: Review Results
CodeLogician generates and proves verification goals:
✓ Verification Goal 1: PROVED
∀ client_id, algo_type, trading_phase:
verify_xyz_rule_is_redundant(client_id, algo_type, trading_phase) = true
✓ Verification Goal 2: PROVED
∀ trading_phase:
is_trading_phase_eligible_for_client_and_algo(XYZ, BENCHMARK_CLOSE_ONLY, trading_phase)
=
is_trading_phase_eligible_for_algo_type(BENCHMARK_CLOSE_ONLY, trading_phase)
Key Insights
Mathematical Certainty: We didn't just test a few cases—we proved for all possible values that the special case produces identical results to the general rule.
Why This Matters:
- Confidence: 100% certainty the rule is redundant
- Documentation: Formal proof serves as permanent documentation
- Refactoring Safety: Can remove the rule knowing behavior won't change
- No Test Gap: Traditional testing might miss edge cases
General Pattern for Detecting Redundancies
def verify_rule_is_redundant(inputs):
"""
Check if specific_rule and general_rule produce
the same result for specific conditions.
"""
if specific_conditions_apply(inputs):
specific_result = specific_rule(inputs)
general_result = general_rule(inputs)
return specific_result == general_result
return TrueThen verify: ∀ inputs: verify_rule_is_redundant(inputs) = true
When to Use This Technique
Good use cases:
- Client-specific overrides that may duplicate base rules
- Geographic/regulatory rules with complex interactions
- Product-specific business logic
- State machine transitions with redundant conditions
- Access control rules with overlapping permissions
Not suitable for:
- Performance optimizations (fast-path logic)
- Caching layers
- Logging/instrumentation code
- I/O operations
Resources
Download the Notebook
Full Documentation
The analysis includes several detailed documents:
- Redundant Rule Analysis: Complete formal verification report with truth tables
- Region Decomposition Results: All 12 possible behaviors documented
- Property Verification: Proof that Close destinations only map to Close phase
- Tutorial: Step-by-step guide for applying this technique to your code
Learn More
Key Takeaways
Redundancy Detection
Complete Coverage
Region decomposition provides mathematical proof that you've analyzed all possible behaviors—no hidden edge cases.
Property Verification
Critical business constraints can be verified universally and permanently—not just for specific test cases.
Safe Refactoring
Ready to try CodeLogician on your code?
Start formalizing and verifying your business rules today.