File size: 6,048 Bytes
0125724
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""
TradeSense AI — Institutional Capacity & Market Impact Engine
Implements:
1. Almgren-Chriss non-linear square-root market impact modeling.
2. Capacity sensitivity curves across Base (gamma=0.10), Adverse (gamma=0.25), and Severe (gamma=0.50) scenarios.
3. AUM scaling tiers ($100K -> $100M) and Breakeven Capacity identification.
"""

from typing import List, Dict, Any, Optional, Tuple
from datetime import date, datetime, timezone
import numpy as np
import pandas as pd
from pydantic import BaseModel, Field


class AUMTierResult(BaseModel):
    """Execution and return performance at a specific AUM scaling tier."""
    aum_usd: float
    aum_label: str
    order_size_usd: float
    avg_daily_volume_usd: float
    participation_rate_pct: float
    fixed_slippage_bps: float
    market_impact_bps: float
    total_friction_drag_bps: float
    net_return_pct: float
    net_sharpe: float
    is_institutionally_viable: bool  # True if Net Sharpe >= 1.0 and Participation <= 5%


class CapacityScenarioResult(BaseModel):
    """Capacity analysis under a specific market impact parameter scenario."""
    scenario_name: str
    gamma_impact_coeff: float
    tiers: List[AUMTierResult]
    breakeven_capacity_usd: float
    max_viable_aum_usd: float


class CapacityAnalysisReport(BaseModel):
    """Consolidated institutional capacity report."""
    base_scenario: CapacityScenarioResult
    adverse_scenario: CapacityScenarioResult
    severe_scenario: CapacityScenarioResult
    recommended_deployment_capacity_usd: float
    capacity_classification: str


class CapacityEngine:
    """
    Simulates non-linear market impact, participation rates, and AUM scalability.
    """

    AUM_TIERS = [
        (100_000, "$100K"),
        (1_000_000, "$1M"),
        (5_000_000, "$5M"),
        (10_000_000, "$10M"),
        (25_000_000, "$25M"),
        (50_000_000, "$50M"),
        (100_000_000, "$100M"),
    ]

    @classmethod
    def evaluate_aum_capacity(
        cls,
        base_annual_return_pct: float = 75.4,
        base_annual_volatility_pct: float = 16.0,
        annual_turnover: float = 8.5,
        avg_asset_adv_usd: float = 10_000_000_000.0,  # $10B ADV for mega-caps
        gamma_impact: float = 0.10,
        scenario_name: str = "Base_Impact (gamma=0.10)",
    ) -> CapacityScenarioResult:
        """
        Calculates square-root Almgren-Chriss market impact across AUM tiers.
        """
        tiers: List[AUMTierResult] = []
        max_viable = 0.0
        breakeven = 100_000_000.0

        for aum, label in cls.AUM_TIERS:
            # Rebalance size per asset (assuming 4 active tranche legs)
            order_usd = (aum / 4.0)
            part_rate = (order_usd / (avg_asset_adv_usd + 1e-9)) * 100.0

            # Almgren-Chriss impact in bps = gamma * vol * sqrt(Order / ADV) * 10,000
            impact_bps = gamma_impact * (base_annual_volatility_pct / 100.0) * np.sqrt(order_usd / avg_asset_adv_usd) * 10000.0
            fixed_slippage_bps = 5.0

            total_friction_bps = fixed_slippage_bps + impact_bps
            # Annual friction drag = (Total bps / 10,000) * Annual Turnover * 100%
            drag_pct = (total_friction_bps / 10000.0) * annual_turnover * 100.0

            net_ret = base_annual_return_pct - drag_pct
            net_sr = net_ret / (base_annual_volatility_pct + 1e-9)

            is_viable = (net_sr >= 1.0) and (part_rate <= 5.0)
            if is_viable:
                max_viable = aum
            elif breakeven == 100_000_000.0 and net_sr < 1.0:
                breakeven = aum

            tiers.append(AUMTierResult(
                aum_usd=float(aum),
                aum_label=label,
                order_size_usd=round(order_usd, 2),
                avg_daily_volume_usd=avg_asset_adv_usd,
                participation_rate_pct=round(part_rate, 4),
                fixed_slippage_bps=fixed_slippage_bps,
                market_impact_bps=round(float(impact_bps), 2),
                total_friction_drag_bps=round(float(total_friction_bps), 2),
                net_return_pct=round(float(net_ret), 2),
                net_sharpe=round(float(net_sr), 2),
                is_institutionally_viable=is_viable,
            ))

        return CapacityScenarioResult(
            scenario_name=scenario_name,
            gamma_impact_coeff=gamma_impact,
            tiers=tiers,
            breakeven_capacity_usd=breakeven,
            max_viable_aum_usd=max_viable,
        )

    @classmethod
    def run_capacity_stress_suite(
        cls,
        base_annual_return_pct: float = 75.4,
        base_annual_volatility_pct: float = 16.0,
        annual_turnover: float = 8.5,
    ) -> CapacityAnalysisReport:
        """
        Runs full sensitivity across Base (0.10), Adverse (0.25), and Severe (0.50).
        """
        base = cls.evaluate_aum_capacity(
            base_annual_return_pct, base_annual_volatility_pct, annual_turnover,
            gamma_impact=0.10, scenario_name="Base_Market_Impact (gamma=0.10)"
        )
        adverse = cls.evaluate_aum_capacity(
            base_annual_return_pct, base_annual_volatility_pct, annual_turnover,
            gamma_impact=0.25, scenario_name="Adverse_Market_Impact (gamma=0.25)"
        )
        severe = cls.evaluate_aum_capacity(
            base_annual_return_pct, base_annual_volatility_pct, annual_turnover,
            gamma_impact=0.50, scenario_name="Severe_Market_Impact (gamma=0.50)"
        )

        rec_cap = adverse.max_viable_aum_usd

        if rec_cap >= 25_000_000.0:
            classification = "HIGH_INSTITUTIONAL_CAPACITY (>= $25M)"
        elif rec_cap >= 5_000_000.0:
            classification = "MODERATE_CAPACITY ($5M - $25M)"
        else:
            classification = "NICHE_CONSTRAINED_CAPACITY (< $5M)"

        return CapacityAnalysisReport(
            base_scenario=base,
            adverse_scenario=adverse,
            severe_scenario=severe,
            recommended_deployment_capacity_usd=rec_cap,
            capacity_classification=classification,
        )