# Tradepose Models (共用模型包)

**Shared Pydantic models for the entire Tradepose platform workspace.**

> **重點：這是一個共用的模型包，所有 workspace 成員都可以依賴！**
> **Key Point: This is a SHARED package - all workspace members can depend on it!**

## 📦 Purpose (用途)

This package contains **shared models, schemas, enums, and types** that are used across multiple packages in the Tradepose platform. The primary goal is to ensure **consistency and type safety** across all services.

**共用模型的目的：**
- ✅ 確保所有服務使用相同的數據結構
- ✅ 提供統一的枚舉類型和業務邏輯
- ✅ 避免重複定義相同的模型
- ✅ 保證跨服務的類型安全

## 📂 Package Structure (包結構)

```
tradepose_models/
├── __init__.py                     # Package exports (統一導出接口)
│
├── enums/                          # Enumerations module (枚舉模組)
│   ├── __init__.py
│   ├── freq.py                    # Freq enum
│   ├── order_strategy.py          # OrderStrategy enum
│   ├── weekday.py                 # Weekday enum
│   ├── indicator_type.py          # IndicatorType enum
│   ├── trade_direction.py         # TradeDirection enum
│   ├── trend_type.py              # TrendType enum
│   ├── task_status.py             # TaskStatus enum
│   ├── operation_type.py          # OperationType enum
│   └── export_type.py             # ExportType enum
│
├── broker/                         # Broker models module (券商模型模組)
│   ├── __init__.py
│   ├── account_config.py          # BrokerType, MarketType, BrokerAccount
│   └── account_models.py          # AccountBalance, AccountInfo, MarginInfo
│
├── trading/                        # Trading models module (交易模型模組)
│   ├── __init__.py
│   ├── orders.py                  # Order, OrderSubmitRequest, ExecutionReport
│   ├── positions.py               # Position, ClosedPosition
│   └── trades_execution.py        # TradeExecution
│
├── instruments/                    # Instruments module (商品模型模組)
│   ├── __init__.py
│   ├── instrument.py              # Instrument, AssetClass
│   └── symbol_map.py              # SymbolNormalizer utility
│
├── indicators/                     # Indicator models module (指標模型模組)
│   ├── __init__.py
│   ├── base.py                    # PolarsExprField base utilities
│   ├── moving_average.py          # SMA, EMA, SMMA, WMA
│   ├── volatility.py              # ATR, ATRQuantile
│   ├── trend.py                   # SuperTrend, MACD, ADX
│   ├── momentum.py                # RSI, CCI, Stochastic
│   ├── other.py                   # BollingerBands, RawOhlcv
│   ├── market_profile.py          # MarketProfile + configs
│   └── factory.py                 # Indicator factory class
│
├── strategy/                       # Strategy configuration module (策略配置模組)
│   ├── __init__.py
│   ├── indicator_spec.py          # IndicatorSpec + IndicatorConfig
│   ├── trigger.py                 # Trigger model
│   ├── blueprint.py               # Blueprint model
│   ├── config.py                  # StrategyConfig + parse_strategy
│   └── helpers.py                 # create_* helper functions
│
├── schemas/                        # Polars schemas module (Polars 模式模組)
│   ├── __init__.py
│   ├── enhanced_ohlcv.py          # enhanced_ohlcv_schema
│   ├── trades.py                  # trades_schema
│   └── performance.py             # performance_schema
│
├── export/                         # Export API module (導出 API 模組)
│   ├── __init__.py
│   ├── task.py                    # ExportTaskResponse, ResultSummary
│   └── request.py                 # OnDemandOhlcvRequest
│
├── auth/                           # Authentication models (認證模型模組)
├── billing/                        # Billing models (計費模型模組)
├── gateway/                        # Gateway models (Gateway 模型模組)
│
├── shared.py                       # Gateway shared models (Gateway 共用模型)
├── validators.py                   # Shared validation utilities (共用驗證工具)
└── types.py                        # Common type definitions (通用類型定義)
```

### Module Organization (模組組織)

| Module | Purpose | Key Components |
|--------|---------|----------------|
| `enums/` | Trading and system enumerations | `Freq`, `OrderStrategy`, `TradeDirection`, `TrendType`, `TaskStatus`, `OperationType`, `ExportType` |
| `broker/` | Broker account and credential models | `BrokerType`, `MarketType`, `BrokerAccount`, `BrokerCredentials`, `AccountBalance`, `AccountInfo` |
| `trading/` | Trading execution models | `Order`, `OrderSubmitRequest`, `ExecutionReport`, `Position`, `TradeExecution`, `OrderSide`, `OrderType`, `OrderStatus` |
| `instruments/` | Trading instrument models | `Instrument`, `AssetClass`, `InstrumentStatus`, `SymbolNormalizer` utility |
| `indicators/` | Strongly-typed indicator models | Moving averages, volatility, trend, momentum indicators + factory |
| `strategy/` | Strategy configuration models | `IndicatorSpec`, `Trigger`, `Blueprint`, `StrategyConfig` + helpers |
| `schemas/` | Polars DataFrame schemas | `enhanced_ohlcv_schema`, `trades_schema`, `performance_schema` |
| `export/` | Export task and request models | `ExportTaskResponse`, `OnDemandOhlcvRequest` |
| `auth/` | Authentication models | API keys, authentication tokens |
| `billing/` | Billing and subscription models | Plans, subscriptions, usage tracking |
| `gateway/` | Gateway-specific models | Gateway response models |
| `shared.py` | Shared models | Legacy shared models |
| `validators.py` | Reusable Pydantic validators | Custom field validators |
| `types.py` | Type aliases and custom types | `UserId`, `Timestamp`, etc. |

## 🤔 When to Use Shared Models vs Package-Specific Models

### Decision Matrix (決策矩陣)

| Model Type | Location | Why | Example |
|------------|----------|-----|---------|
| **Enums** (枚舉) | ✅ **Shared Package** | Used across all services for consistency | `TaskStatus`, `PlanTier`, `OperationType` |
| **Domain Models** (業務模型) | ✅ **Shared Package** | Core business logic shared by multiple services | `PlanLimits`, `SubscriptionPlan` |
| **Common DTOs** (通用數據傳輸) | ✅ **Shared Package** | Data structures passed between services | `TaskResponse`, `AuthUser` |
| **API Request/Response** (API 請求響應) | ❌ **Package-Specific** | Tied to specific API contract | `CheckoutRequest`, `APIKeyCreateResponse` |
| **Database Models** (數據庫模型) | ❌ **Package-Specific** | Specific to package's database schema | `User`, `Subscription`, `Usage` |
| **Infrastructure Models** (基礎設施模型) | ❌ **Package-Specific** | Implementation-specific internal models | `StreamEvent`, `TaskMetadata` |
| **Webhook Payloads** (Webhook 數據) | ❌ **Package-Specific** | External integration details | `WebhookEvent`, `SubscriptionCreatedData` |

### Rule of Thumb (經驗法則)

**✅ Put in Shared Package when:**
- 2 or more packages need the same model
- It represents core business logic or domain concepts
- It's an enum or constant that must be consistent across services
- It's a DTO used for inter-service communication

**🏠 放在共用包的條件：**
- 兩個或更多包需要相同的模型
- 代表核心業務邏輯或領域概念
- 是必須在服務間保持一致的枚舉或常量
- 用於服務間通訊的數據傳輸對象

**❌ Keep in Package-Specific when:**
- Only used within a single package
- Tied to HTTP API contract (request/response models)
- Database-specific (ORM models, query results)
- Implementation details (internal infrastructure)

**🏠 保留在專屬包的條件：**
- 僅在單一包內使用
- 綁定到 HTTP API 契約（請求/響應模型）
- 數據庫專屬（ORM 模型、查詢結果）
- 實作細節（內部基礎設施）

## 📝 Practical Examples (實際範例)

### Example 1: Shared Enum (共用枚舉)

**Bad ❌ - Duplicated in each package:**
```python
# packages/gateway/models.py
class TaskStatus(str, Enum):
    PENDING = "pending"
    COMPLETED = "completed"

# packages/worker/models.py
class TaskStatus(str, Enum):  # Duplicated!
    PENDING = "pending"
    COMPLETED = "completed"
```

**Good ✅ - Shared in models package:**
```python
# packages/models/src/tradepose_models/enums.py
class TaskStatus(str, Enum):
    """Task execution status - used across all services."""
    PENDING = "pending"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"

# packages/gateway/src/tradepose_gateway/routes/tasks.py
from tradepose_models.enums import TaskStatus

# packages/worker/src/worker.py
from tradepose_models.enums import TaskStatus
```

### Example 2: Package-Specific API Models (專屬的 API 模型)

**Correct ✅ - API models stay in gateway:**
```python
# packages/gateway/src/tradepose_gateway/models/api_models.py
class CreateCheckoutRequest(BaseModel):
    """Gateway-specific API request model."""
    plan_id: str
    success_url: str
    cancel_url: str

class CreateCheckoutResponse(BaseModel):
    """Gateway-specific API response model."""
    checkout_url: str
    checkout_id: str
```

These models are **NOT** moved to shared package because they are specific to the gateway's HTTP API contract.

### Example 3: Shared Domain Model (共用業務模型)

**Good ✅ - Domain model in shared package:**
```python
# packages/models/src/tradepose_models/schemas.py
class PlanLimits(BaseModel):
    """Rate limits and quotas for subscription plans.

    Used by:
    - Gateway: to enforce rate limits
    - Client: to display plan capabilities
    - Billing service: to validate usage
    """
    max_requests_per_minute: int
    max_concurrent_tasks: int
    max_strategies: int

# packages/gateway/src/tradepose_gateway/middleware/rate_limit.py
from tradepose_models.schemas import PlanLimits

# packages/client/src/tradepose_client/plans.py
from tradepose_models.schemas import PlanLimits
```

## 🔄 Migration Guide (遷移指南)

### How to Move Models from Gateway to Shared Package

**Step 1: Identify the model to share**
```python
# Currently in: packages/gateway/src/tradepose_gateway/models/task_models.py
class TaskStatus(str, Enum):
    PENDING = "pending"
    COMPLETED = "completed"
```

**Step 2: Move to appropriate shared file**
```python
# Move to: packages/models/src/tradepose_models/enums.py
class TaskStatus(str, Enum):
    """Task execution status (shared across all services)."""
    PENDING = "pending"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"
```

**Step 3: Export from package `__init__.py`**
```python
# packages/models/src/tradepose_models/__init__.py
from tradepose_models.enums import TaskStatus

__all__ = ["TaskStatus"]
```

**Step 4: Update imports in gateway**
```python
# packages/gateway/src/tradepose_gateway/routes/tasks.py
# Before:
from tradepose_gateway.models.task_models import TaskStatus

# After:
from tradepose_models.enums import TaskStatus
```

**Step 5: Remove old definition from gateway**
```python
# Delete from: packages/gateway/src/tradepose_gateway/models/task_models.py
# (model is now in shared package)
```

## 📦 Installation & Usage

### For Workspace Members

All workspace packages automatically have access to `tradepose-models`. Add it to your dependencies:

```toml
# packages/your-package/pyproject.toml
[project]
dependencies = [
    "tradepose-models",
    "polars>=1.34.0",  # Required for Polars Expr support
]

[tool.uv.sources]
tradepose-models = { workspace = true }
```

### Import Examples

#### Flat Imports (Backward Compatible)

```python
# Import enums
from tradepose_models import Freq, OrderStrategy, TradeDirection, TrendType

# Import indicator models
from tradepose_models import SMAIndicator, ATRIndicator, SuperTrendIndicator

# Import indicator factory
from tradepose_models import Indicator

# Import strategy models
from tradepose_models import IndicatorSpec, Trigger, Blueprint, StrategyConfig

# Import helper functions
from tradepose_models import create_indicator_spec, create_trigger, create_blueprint

# Import schemas
from tradepose_models import enhanced_ohlcv_schema, trades_schema, performance_schema

# Import export models
from tradepose_models import ExportTaskResponse, OnDemandOhlcvRequest
```

#### Modular Imports (Recommended)

```python
# Import from specific modules for better code organization
from tradepose_models.enums import Freq, OrderStrategy, TradeDirection, TaskStatus
from tradepose_models.broker import BrokerType, BrokerAccount, MarketType, AccountBalance
from tradepose_models.trading import Order, OrderSubmitRequest, Position, OrderSide, OrderType
from tradepose_models.instruments import Instrument, SymbolNormalizer, AssetClass
from tradepose_models.indicators import Indicator, SMAIndicator, ATRIndicator
from tradepose_models.strategy import IndicatorSpec, Trigger, Blueprint
from tradepose_models.schemas import enhanced_ohlcv_schema
from tradepose_models.export import ExportTaskResponse
```

### Usage Examples

#### Example 1: Creating Indicators

```python
from tradepose_models import Indicator, create_indicator_spec, Freq

# Create indicator configurations using factory
sma_20 = Indicator.sma(period=20)
atr_14 = Indicator.atr(period=14)
supertrend = Indicator.supertrend(multiplier=3.0, volatility_column="ATR|14")

# Create indicator specifications
sma_spec = create_indicator_spec(
    freq=Freq.MIN_1,
    indicator=sma_20,
    instrument_id="ES",
    shift=1
)

# Get column name and Polars expression
column_name = sma_spec.display_name()  # "ES_1min_SMA|20.close"
expr = sma_spec.col()  # pl.col("ES_1min_SMA|20.close")
```

#### Example 2: Creating Strategy Configuration

```python
import polars as pl
from tradepose_models import (
    create_indicator_spec,
    create_trigger,
    create_blueprint,
    Indicator,
    Freq,
    OrderStrategy,
    TradeDirection,
    TrendType,
)

# Define indicators
sma_20 = create_indicator_spec(Freq.MIN_5, Indicator.sma(20))
sma_50 = create_indicator_spec(Freq.MIN_5, Indicator.sma(50))

# Create entry trigger
entry = create_trigger(
    name="golden_cross",
    conditions=[
        sma_20.col() > sma_50.col(),
        pl.col("volume") > 1000
    ],
    price_expr=pl.col("open"),
    order_strategy=OrderStrategy.IMMEDIATE_ENTRY,
    priority=1
)

# Create exit trigger
exit_trigger = create_trigger(
    name="death_cross",
    conditions=[sma_20.col() < sma_50.col()],
    price_expr=pl.col("open"),
    order_strategy=OrderStrategy.IMMEDIATE_EXIT,
    priority=1
)

# Create blueprint
blueprint = create_blueprint(
    name="SMA_Crossover",
    direction=TradeDirection.LONG,
    entry_triggers=[entry],
    exit_triggers=[exit_trigger],
    trend_type=TrendType.TREND
)
```

#### Example 3: Using Polars Schemas

```python
import polars as pl
from tradepose_models.schemas import trades_schema, performance_schema

# Read trades data with schema validation
trades_df = pl.read_parquet("trades.parquet", schema=trades_schema)

# Read performance metrics
performance_df = pl.read_parquet("performance.parquet", schema=performance_schema)

# Type-safe data access
print(trades_df["entry_time"])  # Datetime column
print(trades_df["pnl"])  # Float64 column
print(performance_df["sharpe_ratio"])  # Float64 column
```

#### Example 4: Broker and Trading Models

```python
from datetime import datetime
from decimal import Decimal
from tradepose_models.broker import (
    BrokerType, MarketType, BrokerAccount,
    BrokerCredentials, AccountStatus
)
from tradepose_models.trading import (
    OrderSubmitRequest, OrderSide, OrderType,
    TimeInForce, OrderStrategy
)
from tradepose_models.instruments import SymbolNormalizer

# Create broker account configuration
account = BrokerAccount(
    id="account_123",
    user_id="user_456",
    name="My Binance Account",
    broker_type=BrokerType.BINANCE,
    credentials=BrokerCredentials(
        api_key="your_api_key",
        api_secret="your_api_secret",
    ),
    available_markets=[MarketType.SPOT, MarketType.FUTURES],
    default_market=MarketType.SPOT,
    environment="production",
    status=AccountStatus.ACTIVE,
    created_at=datetime.now(),
    updated_at=datetime.now(),
)

# Normalize symbol
unified_symbol = SymbolNormalizer.normalize_binance_spot("BTCUSDT")  # → "BTC-USDT"
broker_symbol = SymbolNormalizer.denormalize("BTC-USDT", "binance")   # → "BTCUSDT"

# Create order request
order_request = OrderSubmitRequest(
    user_id="user_456",
    account_id="account_123",
    symbol=unified_symbol,
    side=OrderSide.BUY,
    order_type=OrderType.LIMIT,
    quantity=Decimal("0.001"),
    price=Decimal("50000"),
    time_in_force=TimeInForce.GTC,
    order_strategy=OrderStrategy.IMMEDIATE_ENTRY,
)
```

## 🏗️ Current Status (目前狀態)

**Version**: 0.1.0
**Status**: Basic structure established

### Planned Models to Extract (計劃提取的模型)

The following models from gateway will be migrated to this shared package:

**Enums**:
- ✅ `TaskStatus` (PENDING → PROCESSING → COMPLETED/FAILED)
- ✅ `OperationType` (backtest, strategy operations)
- ✅ `PlanTier` (FREE, PRO, ENTERPRISE)

**Schemas**:
- ✅ `PlanLimits` - Rate limiting quotas
- ✅ `TaskResponse` - Standard task response format
- ✅ `AuthUser` - Authenticated user context

**Types**:
- ✅ `UserId` - User identifier type
- ✅ `APIKeyHash` - Hashed API key type

## 🤝 Contributing

When adding new shared models:

1. **Ask**: Will 2+ packages use this model?
2. **Check**: Is it a domain concept or implementation detail?
3. **Document**: Add clear docstrings explaining usage
4. **Export**: Update `__init__.py` to export the model
5. **Test**: Ensure all dependent packages can import it

## 📚 Related Documentation

- [Gateway Package](../gateway/README.md)
- [Client Package](../client/README.md)
- [Workspace Structure](../../README.md)

---

**Questions?** Check the decision matrix above or review existing models for examples.
