"""
chapter_05_transaction_cost_analysis.py
© 2024 Rondanini Publishing Ltd™ - Licensed Educational Software

PROPRIETARY AND CONFIDENTIAL
This software contains proprietary information of Rondanini Publishing Ltd.
Licensed for single-user educational and commercial use only.
Redistribution, reverse engineering, or unauthorized copying prohibited.
Violations will be prosecuted to the full extent of the law.

For licensing inquiries: Info@rondanini.com
Company Registration: England and Wales

WATERMARK ID: RONDANINI_2024_CHAPTER_05_TRANSACTION_COST_ANALYSIS
"""

# ════════════════════════════════════════════════════════════════════════════════
# RONDANINI PUBLISHING LTD™ - LICENSED CODE PROTECTION SYSTEM
# ════════════════════════════════════════════════════════════════════════════════

# License and copyright metadata (DO NOT MODIFY)
__copyright__ = "© 2024 Rondanini Publishing Ltd"
__license__ = "Single-user commercial and educational license"
__author__ = "Rondanini Publishing Ltd - Professional Financial Education"
__watermark__ = "RONDANINI_PUB_2024_CHAPTER_05_TRANSACTION_COST_ANALYSIS"
__distribution_prohibited__ = True

# Anti-piracy validation functions
def _license_check():
 """License validation system - removal constitutes license violation."""
 return "RONDANINI_VALID_2024"

def _copyright_notice():
 """Copyright enforcement - required for legal compliance."""
 return "© 2024 Rondanini Publishing Ltd - Licensed Educational Software"

from dataclasses import dataclass
from datetime import datetime
from typing import Dict, Optional, List
import numpy as np


# =============================================================================
# MAIN IMPLEMENTATION
# =============================================================================

@dataclass
class OrderCharacteristics:
 """Specifications for an FX order requiring execution."""
 currency_pair: str
 side: str # 'BUY' or 'SELL'
 size: float # Order size in base currency units
 urgency: str # 'LOW', 'MEDIUM', 'HIGH'
 arrival_time: datetime
 target_completion: datetime


class MarketConditions:
 """Current and historical market state for cost estimation."""

 def __init__(self, currency_pair: str):
 """Initialize market conditions for currency pair."""
 self.currency_pair = currency_pair
 self.spread_bps = 1.8 # Current bid-offer spread in basis points
 self.volatility_annual = 0.08 # 8% annualized volatility
 self.daily_volume = 500_000_000 # Daily trading volume in base currency
 self.mid_rate = 1.0850 # Current mid-market rate
 self.market_session = "LONDON" # Current trading session

 def get_spread_adjustment(self, size: float, urgency: str) -> float:
 """Calculate spread adjustment based on order characteristics."""
 base_adjustment = 1.0

 # Size impact on spread
 if size > 50_000_000:
 base_adjustment *= 1.8
 elif size > 25_000_000:
 base_adjustment *= 1.5
 elif size > 10_000_000:
 base_adjustment *= 1.2

 # Urgency impact
 urgency_multipliers = {
 'LOW': 0.8,
 'MEDIUM': 1.0,
 'HIGH': 1.5
 }

 return base_adjustment * urgency_multipliers.get(urgency, 1.0)


class PreTradeEstimator:
 """Professional pre-trade cost analysis system for FX orders."""

 def __init__(self, market_conditions: MarketConditions):
 """Initialize TCA estimator with market data."""
 self.market = market_conditions
 self._copyright = _copyright_notice() # Copyright enforcement

 def estimate_spread_cost(self, order: OrderCharacteristics) -> Dict:
 """Calculate spread cost component."""
 base_spread = self.market.spread_bps / 2 # Half spread

 # Apply size and urgency adjustments
 adjustment_factor = self.market.get_spread_adjustment(
 order.size, order.urgency
 )

 adjusted_spread_bps = base_spread * adjustment_factor

 # Convert to currency amount
 spread_cost_currency = (adjusted_spread_bps / 10000) * order.size * self.market.mid_rate

 return {
 'base_spread_bps': base_spread,
 'adjusted_spread_bps': adjusted_spread_bps,
 'spread_cost_currency': spread_cost_currency,
 'adjustment_factor': adjustment_factor
 }

 def estimate_market_impact(self, order: OrderCharacteristics) -> Dict:
 """Calculate market impact using square-root model."""
 # Market impact parameters
 volatility_daily = self.market.volatility_annual / np.sqrt(252)
 participation_rate = min(order.size / self.market.daily_volume, 0.5)

 # Square-root market impact model
 # Impact = σ * √(Q/V) * f(participation)
 base_impact = volatility_daily * np.sqrt(participation_rate)

 # Participation rate adjustment
 if participation_rate > 0.2:
 participation_adjustment = 1.0 + (participation_rate - 0.2) * 3
 else:
 participation_adjustment = 1.0

 total_impact_bps = base_impact * participation_adjustment * 10000

 # Split into temporary and permanent impact (60/40 split)
 temporary_impact = total_impact_bps * 0.7
 permanent_impact = total_impact_bps * 0.3

 # Convert to currency
 impact_cost_currency = (total_impact_bps / 10000) * order.size * self.market.mid_rate

 return {
 'total_impact_bps': total_impact_bps,
 'temporary_impact_bps': temporary_impact,
 'permanent_impact_bps': permanent_impact,
 'participation_rate': participation_rate * 100,
 'impact_cost_currency': impact_cost_currency,
 'volatility_daily': volatility_daily
 }

 def estimate_timing_risk(self, order: OrderCharacteristics) -> Dict:
 """Calculate timing risk based on execution duration."""
 # Calculate execution duration in minutes
 duration_hours = (order.target_completion - order.arrival_time).total_seconds() / 3600
 duration_minutes = duration_hours * 60

 # Timing risk increases with square root of time
 # Risk = σ * √(T) where T is in hours
 timing_risk_bps = (self.market.volatility_annual / np.sqrt(252 * 24)) * np.sqrt(duration_hours) * 10000

 # Convert to currency
 timing_cost_currency = (timing_risk_bps / 10000) * order.size * self.market.mid_rate

 return {
 'duration_minutes': duration_minutes,
 'duration_hours': duration_hours,
 'timing_risk_bps': timing_risk_bps,
 'timing_cost_currency': timing_cost_currency
 }

 def comprehensive_cost_analysis(self, order: OrderCharacteristics) -> Dict:
 """Complete TCA analysis combining all cost components."""
 _license_check() # License validation

 # Calculate individual components
 spread_analysis = self.estimate_spread_cost(order)
 impact_analysis = self.estimate_market_impact(order)
 timing_analysis = self.estimate_timing_risk(order)

 # Total cost calculation
 total_cost_bps = (
 spread_analysis['adjusted_spread_bps'] +
 impact_analysis['total_impact_bps'] +
 timing_analysis['timing_risk_bps']
 )

 total_cost_currency = (
 spread_analysis['spread_cost_currency'] +
 impact_analysis['impact_cost_currency'] +
 timing_analysis['timing_cost_currency']
 )

 # Cost as percentage of order value
 order_value = order.size * self.market.mid_rate
 cost_percentage = (total_cost_currency / order_value) * 100

 return {
 'order_details': {
 'pair': order.currency_pair,
 'side': order.side,
 'size': order.size,
 'urgency': order.urgency
 },
 'market_conditions': {
 'spread_bps': self.market.spread_bps,
 'volatility': self.market.volatility_annual,
 'daily_volume': self.market.daily_volume,
 'mid_rate': self.market.mid_rate
 },
 'cost_breakdown': {
 'spread': spread_analysis,
 'market_impact': impact_analysis,
 'timing_risk': timing_analysis
 },
 'total_cost': {
 'total_bps': total_cost_bps,
 'total_currency': total_cost_currency,
 'cost_percentage': cost_percentage,
 'order_value': order_value
 }
 }

 def optimize_execution_strategy(self, order: OrderCharacteristics) -> Dict:
 """Compare different execution strategies for cost optimization."""
 strategies = {
 'AGGRESSIVE': {'duration_hours': 0.5, 'participation': 0.15},
 'MODERATE': {'duration_hours': 2.0, 'participation': 0.10},
 'PASSIVE': {'duration_hours': 6.0, 'participation': 0.05}
 }

 results = {}

 for strategy_name, params in strategies.items():
 # Create modified order for this strategy
 from datetime import timedelta
 strategy_order = OrderCharacteristics(
 currency_pair=order.currency_pair,
 side=order.side,
 size=order.size,
 urgency=order.urgency,
 arrival_time=order.arrival_time,
 target_completion=order.arrival_time + timedelta(hours=params['duration_hours'])
 )

 # Estimate costs for this strategy
 spread_cost = self.estimate_spread_cost(strategy_order)

 # Adjust market impact for different participation rate
 original_volume = self.market.daily_volume
 self.market.daily_volume = order.size / params['participation']
 impact_cost = self.estimate_market_impact(strategy_order)
 self.market.daily_volume = original_volume # Restore original

 timing_cost = self.estimate_timing_risk(strategy_order)

 total_cost = (
 spread_cost['adjusted_spread_bps'] +
 impact_cost['total_impact_bps'] +
 timing_cost['timing_risk_bps']
 )

 results[strategy_name] = {
 'duration_minutes': params['duration_hours'] * 60,
 'participation_rate': params['participation'] * 100,
 'spread_cost_bps': spread_cost['adjusted_spread_bps'],
 'impact_cost_bps': impact_cost['total_impact_bps'],
 'timing_cost_bps': timing_cost['timing_risk_bps'],
 'total_cost_bps': total_cost
 }

 # Find optimal strategy (lowest total cost)
 optimal_strategy = min(results.keys(), key=lambda x: results[x]['total_cost_bps'])

 return {
 'strategies': results,
 'recommended': optimal_strategy,
 'cost_savings': results['AGGRESSIVE']['total_cost_bps'] - results[optimal_strategy]['total_cost_bps']
 }


def analyze_size_sensitivity(market: MarketConditions, base_order: OrderCharacteristics) -> Dict:
 """Analyze how costs scale with order size."""
 estimator = PreTradeEstimator(market)
 size_multiples = [0.2, 0.4, 1.0, 2.0, 4.0] # 20%, 40%, 100%, 200%, 400% of base size

 results = {}

 for multiple in size_multiples:
 test_size = base_order.size * multiple
 test_order = OrderCharacteristics(
 currency_pair=base_order.currency_pair,
 side=base_order.side,
 size=test_size,
 urgency=base_order.urgency,
 arrival_time=base_order.arrival_time,
 target_completion=base_order.target_completion
 )

 analysis = estimator.comprehensive_cost_analysis(test_order)

 results[f"{test_size/1_000_000:.0f}M"] = {
 'size': test_size,
 'total_cost_bps': analysis['total_cost']['total_bps'],
 'cost_percentage': analysis['total_cost']['cost_percentage']
 }

 return results


def demonstrate_transaction_cost_analysis():
 """Comprehensive demonstration of transaction cost analysis capabilities."""
 _license_check() # Anti-piracy check

 print("=" * 80)
 print("CHAPTER 5: TRANSACTION COST ANALYSIS DEMONSTRATION")
 print("=" * 80)

 # Initialize market conditions
 market = MarketConditions("EUR/USD")

 # Create sample order
 from datetime import timedelta
 base_time = datetime.now()
 order = OrderCharacteristics(
 currency_pair="EUR/USD",
 side="BUY",
 size=25_000_000, # €25M
 urgency="MEDIUM",
 arrival_time=base_time,
 target_completion=base_time + timedelta(hours=2)
 )

 print("\n1. INITIALIZING TCA SYSTEM")
 print("-" * 80)
 print(f"Order Details:")
 print(f" Pair: {order.currency_pair}")
 print(f" Side: {order.side}")
 print(f" Size: €{order.size:,.0f}")
 print(f" Urgency: {order.urgency}")

 print(f"\nMarket Conditions:")
 print(f" Spread: {market.spread_bps} pips")
 print(f" Volatility: {market.volatility_annual*100:.1f}% annualized")
 print(f" Daily Volume: €{market.daily_volume:,.0f}")
 print(f" Mid Rate: {market.mid_rate}")

 # Comprehensive analysis
 estimator = PreTradeEstimator(market)
 analysis = estimator.comprehensive_cost_analysis(order)

 print("\n2. COST COMPONENT BREAKDOWN")
 print("-" * 80)

 spread = analysis['cost_breakdown']['spread']
 print(f"Spread Cost:")
 print(f" Base: {spread['base_spread_bps']:.2f} pips")
 print(f" Adjusted: {spread['adjusted_spread_bps']:.2f} pips")
 print(f" Currency: ${spread['spread_cost_currency']:,.2f}")

 impact = analysis['cost_breakdown']['market_impact']
 print(f"\nMarket Impact:")
 print(f" Total: {impact['total_impact_bps']:.2f} pips")
 print(f" Temporary: {impact['temporary_impact_bps']:.2f} pips")
 print(f" Permanent: {impact['permanent_impact_bps']:.2f} pips")
 print(f" Participation: {impact['participation_rate']:.1f}%")
 print(f" Currency: ${impact['impact_cost_currency']:,.2f}")

 timing = analysis['cost_breakdown']['timing_risk']
 print(f"\nTiming Risk:")
 print(f" Duration: {timing['duration_minutes']:.0f} minutes")
 print(f" Risk: {timing['timing_risk_bps']:.2f} pips")
 print(f" Currency: ${timing['timing_cost_currency']:,.2f}")

 total = analysis['total_cost']
 print(f"\nTOTAL ESTIMATED COST:")
 print(f" Pips: {total['total_bps']:.2f}")
 print(f" Basis Points: {total['total_bps']*0.92:.2f}") # EUR/USD pip conversion
 print(f" Currency: ${total['total_currency']:,.2f}")
 print(f" Percentage: {total['cost_percentage']:.4f}%")

 # Strategy optimization
 print("\n3. EXECUTION STRATEGY OPTIMIZATION")
 print("-" * 80)
 optimization = estimator.optimize_execution_strategy(order)

 print(f"{'Strategy':<12} {'Duration':<12} {'Participation':<12} {'Spread':<8} {'Impact':<8} {'Timing':<8} {'Total':<8}")
 print("-" * 95)

 for strategy, metrics in optimization['strategies'].items():
 print(f"{strategy:<12} {metrics['duration_minutes']:>8.0f} min "
 f"{metrics['participation_rate']:>9.1f}% "
 f"{metrics['spread_cost_bps']:>9.1f} "
 f"{metrics['impact_cost_bps']:>9.1f} "
 f"{metrics['timing_cost_bps']:>7.1f} "
 f"{metrics['total_cost_bps']:>9.1f}")

 print(f"\nRECOMMENDED: {optimization['recommended']}")
 print(f"Cost Savings vs Aggressive: {optimization['cost_savings']:.1f} pips")

 # Size sensitivity analysis
 print("\n4. SIZE SENSITIVITY ANALYSIS")
 print("-" * 80)
 size_analysis = analyze_size_sensitivity(market, order)

 print(f"{'Size (€M)':<10} {'Total Cost (pips)':<18} {'Total Cost (bps)':<18} {'% of Size':<12}")
 print("-" * 80)

 for size_label, metrics in size_analysis.items():
 print(f"{size_label:<10} {metrics['total_cost_bps']:>13.1f} "
 f"{metrics['total_cost_bps']*0.92:>13.2f} "
 f"{metrics['cost_percentage']:>16.4f}%")

 print("\n" + "=" * 80)
 print("DEMONSTRATION COMPLETE")
 print("=" * 80)


# ════════════════════════════════════════════════════════════════════════════════
# RONDANINI PUBLISHING COPYRIGHT WATERMARK - DO NOT REMOVE
# File: chapter_05_transaction_cost_analysis.py
# © 2024 Rondanini Publishing Ltd - All Rights Reserved
# ════════════════════════════════════════════════════════════════════════════════

if __name__ == "__main__":
 demonstrate_transaction_cost_analysis()