Skip to main content

TradePose Models

Shared Pydantic models, enums, and schemas for all TradePose packages.

Features

  • Strategy Configuration - StrategyConfig, Blueprint, Trigger, IndicatorSpec
  • Registry & Portfolio - Multi-strategy management with unique key indexing
  • Enumerations - Freq, TradeDirection, OrderStrategy, EngagementPhase, ActionType
  • Polars Schemas - DataFrame schemas for trades and OHLCV
  • Type Safety - Full Pydantic validation with IDE autocomplete

Installation

pip install tradepose-models

Requirements:

  • Python 3.13+
  • Dependencies: pydantic, polars

Quick Start

Strategy Configuration

from tradepose_models.strategy import (
    StrategyConfig,
    Blueprint,
    Trigger,
    IndicatorSpec,
)
from tradepose_models.enums import (
    Freq,
    TradeDirection,
    TrendType,
    OrderStrategy,
)
from tradepose_models.indicators import Indicator
import polars as pl

# Create indicator
atr_spec = IndicatorSpec(
    freq=Freq.DAY_1,
    shift=1,
    indicator=Indicator.atr(period=14),
)

# Create trigger
entry_trigger = Trigger(
    name="breakout_entry",
    order_strategy=OrderStrategy.IMMEDIATE_ENTRY,
    priority=1,
    conditions=[pl.col("close") > pl.col("high").shift(1)],
    offset_expr=pl.lit(0.0),
)

# Create blueprint
blueprint = Blueprint(
    name="trend_long",
    direction=TradeDirection.LONG,
    trend_type=TrendType.TREND,
    entry_triggers=[entry_trigger],
    exit_triggers=[...],
)

# Create strategy
strategy = StrategyConfig(
    name="ES_Breakout",
    base_instrument="ES",
    base_freq=Freq.MIN_15,
    note="E-mini S&P breakout strategy",
    indicators=[atr_spec],
    base_blueprint=blueprint,
)

# Save/Load
strategy.save("strategy.json")
loaded = StrategyConfig.load("strategy.json")

Strategy Registry

Manage multiple strategies with (strategy_name, blueprint_name) unique keys:

from tradepose_models.strategy import StrategyRegistry, StrategyConfig

# Create registry
registry = StrategyRegistry()

# Add strategy (auto-splits blueprints into separate entries)
strategy = StrategyConfig.load("multi_blueprint_strategy.json")
keys = registry.add(strategy)
# keys = [(BlueprintSelection("MyStrategy", "long_bp"), BlueprintSelection("MyStrategy", "short_bp")]

# Access entries
entry = registry.get("MyStrategy", "long_bp")
print(entry.blueprint.direction)  # TradeDirection.LONG

# Get all configs for backtesting
configs = registry.get_configs()  # List[StrategyConfig] with single blueprints

Portfolio Selection

Create portfolios by selecting from registry:

from tradepose_models.strategy import StrategyRegistry

registry = StrategyRegistry()
registry.add(strategy1)  # 2 blueprints
registry.add(strategy2)  # 3 blueprints

# Create portfolio (selection view)
portfolio = registry.select(
    name="Q1_Momentum",
    selections=[
        ("Strategy1", "momentum_long"),
        ("Strategy1", "momentum_short"),
        ("Strategy2", "trend_follow"),
    ],
    capital=100000,
    currency="USD",
    platform="MT5",
)

# Get configs for BatchTester
configs = portfolio.get_configs(registry)

# Use with BatchTester
from tradepose_client import BatchTester
from tradepose_client.batch import Period

tester = BatchTester(api_key="tp_xxx")
batch = tester.submit_backtest(strategies=configs, periods=[Period.Q1(2024)])
batch.wait()

Core Concepts

Strategy Hierarchy

StrategyConfig
├── name, base_instrument, base_freq
├── indicators: List[IndicatorSpec]
├── base_blueprint: Blueprint
│   ├── name, direction, trend_type
│   ├── entry_triggers: List[Trigger]
│   │   └── conditions: List[pl.Expr], price_expr: pl.Expr
│   └── exit_triggers: List[Trigger]
└── advanced_blueprints: List[Blueprint]

Registry & Portfolio

StrategyRegistry (storage, guarantees uniqueness)
│
│  Key: (strategy_name, blueprint_name)
│
├── add(config) → auto-split blueprints
├── get(name, bp) → RegistryEntry
├── get_configs() → List[StrategyConfig]  ──> for BatchTester
└── select(...) → Portfolio
                     │
                     ▼
              Portfolio (selection view)
              ├── selections: List[(name, bp)]
              ├── capital, currency, platform
              └── get_configs(registry) → configs

API Reference

Enumerations

Freq (Time Frequency)

from tradepose_models.enums import Freq

Freq.MIN_1   # "1min"
Freq.MIN_5   # "5min"
Freq.MIN_15  # "15min"
Freq.MIN_30  # "30min"
Freq.HOUR_1  # "1h"
Freq.HOUR_4  # "4h"
Freq.DAY_1   # "1D"
Freq.WEEK_1  # "1W"
Freq.MONTH_1 # "1M"

TradeDirection

from tradepose_models.enums import TradeDirection

TradeDirection.LONG   # Long trades only
TradeDirection.SHORT  # Short trades only

TrendType

from tradepose_models.enums import TrendType

TrendType.TREND     # Trend-following
TrendType.RANGE     # Mean-reversion
TrendType.REVERSAL  # Counter-trend

OrderStrategy

from tradepose_models.enums import OrderStrategy

# Entry
OrderStrategy.IMMEDIATE_ENTRY      # Execute immediately
OrderStrategy.FAVORABLE_DELAY_ENTRY  # Wait for pullback
OrderStrategy.ADVERSE_DELAY_ENTRY   # Wait for breakout

# Exit
OrderStrategy.IMMEDIATE_EXIT  # Exit immediately
OrderStrategy.STOP_LOSS       # Fixed stop loss
OrderStrategy.TAKE_PROFIT     # Fixed profit target
OrderStrategy.TRAILING_STOP   # Dynamic trailing
OrderStrategy.BREAKEVEN       # Move to breakeven
OrderStrategy.TIMEOUT_EXIT    # Time-based exit

Currency

from tradepose_models.enums import Currency

Currency.USD, Currency.USDT, Currency.TWD
Currency.EUR, Currency.JPY
Currency.BTC, Currency.ETH
Currency.XAU, Currency.TAIEX

Platform

from tradepose_models.enums import Platform

Platform.MT5      # MetaTrader 5
Platform.BINANCE  # Binance
Platform.SHIOAJI  # Shioaji (Taiwan)
Platform.CCXT     # CCXT unified

AccountSource

from tradepose_models.enums import AccountSource

AccountSource.FTMO        # tz_offset: 2
AccountSource.IB          # tz_offset: 0
AccountSource.FIVEPERCENT # tz_offset: 2
AccountSource.BINANCE     # tz_offset: 8
AccountSource.SHIOAJI     # tz_offset: 8

# Get timezone offset
offset = AccountSource.FTMO.tz_offset()  # 2

EngagementPhase (v0.3.0)

from tradepose_models.enums import EngagementPhase

# 9-state lifecycle
EngagementPhase.PENDING     # 0: Awaiting entry
EngagementPhase.ENTERING    # 1: Entry order placed
EngagementPhase.HOLDING     # 2: Position held
EngagementPhase.EXITING     # 3: Exit order placed
EngagementPhase.CLOSED      # 4: Position closed
EngagementPhase.FAILED      # 5: Entry failed
EngagementPhase.CANCELLED   # 6: Entry cancelled
EngagementPhase.EXIT_FAILED # 7: Exit failed
EngagementPhase.EXPIRED     # 8: Entry expired

ActionType (v0.3.0)

from tradepose_models.enums import ActionType

# BrokerExecutor dispatch
ActionType.NONE            # No action needed
ActionType.MARKET_ENTRY    # execute_market_entry()
ActionType.LIMIT_ENTRY     # execute_limit_entry()
ActionType.CLOSE_POSITION  # execute_close_position()
ActionType.MODIFY_POSITION # execute_modify_position()
ActionType.MODIFY_ORDER    # execute_modify_order()
ActionType.CANCEL_ORDER    # execute_cancel_order()

Strategy Models

StrategyConfig

from tradepose_models.strategy import StrategyConfig

# Fields
strategy.name              # str: Strategy name
strategy.base_instrument   # str: Trading instrument
strategy.base_freq         # Freq: Base timeframe
strategy.note              # str: Description
strategy.indicators        # List[IndicatorSpec]
strategy.base_blueprint    # Blueprint: Primary blueprint
strategy.advanced_blueprints  # List[Blueprint]: Additional blueprints

# Methods
StrategyConfig.load(path)     # Load from JSON file
strategy.save(path)           # Save to JSON file
strategy.to_json()            # Serialize to JSON string
strategy.to_dict()            # Convert to dict
StrategyConfig.from_api(data) # Parse from API response

Blueprint

from tradepose_models.strategy import Blueprint

# Fields
blueprint.name           # str: Blueprint name
blueprint.direction      # TradeDirection: LONG/SHORT
blueprint.trend_type     # TrendType: TREND/RANGE/REVERSAL
blueprint.entry_triggers # List[Trigger]
blueprint.exit_triggers  # List[Trigger]

Trigger

from tradepose_models.strategy import Trigger
import polars as pl

trigger = Trigger(
    name="breakout",
    order_strategy=OrderStrategy.IMMEDIATE_ENTRY,
    priority=1,
    conditions=[
        pl.col("close") > pl.col("high").shift(1),
        pl.col("volume") > pl.col("volume").rolling_mean(20),
    ],
    offset_expr=pl.lit(0.0),
)

# Access Polars expressions directly
expr = trigger.conditions[0]  # pl.Expr

IndicatorSpec

from tradepose_models.strategy import IndicatorSpec
from tradepose_models.indicators import Indicator

spec = IndicatorSpec(
    freq=Freq.DAY_1,
    shift=1,
    indicator=Indicator.atr(period=14),
)

# Properties
spec.short_name()    # "ATR|14"
spec.display_name()  # "1D_ATR|14_s1"
spec.col()           # pl.col("1D_ATR|14_s1")

Registry Models

StrategyRegistry

from tradepose_models.strategy import StrategyRegistry

registry = StrategyRegistry()

# Add strategy (auto-splits blueprints)
keys = registry.add(strategy)  # Returns List[BlueprintSelection]

# Add or replace
keys = registry.add_or_replace(strategy)

# Get entry
entry = registry.get("StrategyName", "blueprint_name")

# Get original strategy (with all blueprints)
original = registry.get_strategy("StrategyName")

# Get all configs (single-blueprint each)
configs = registry.get_configs()

# Remove strategy
removed_count = registry.remove("StrategyName")

# Create portfolio
portfolio = registry.select(
    name="MyPortfolio",
    selections=[("Strat1", "bp1"), ("Strat2", "bp2")],
    capital=100000,
)

# Iteration
for entry in registry:
    print(entry.key)

# Membership
if ("StrategyName", "blueprint") in registry:
    ...

# Length
print(f"Entries: {len(registry)}")

Portfolio

from tradepose_models.strategy import Portfolio, BlueprintSelection

# Create directly
portfolio = Portfolio(
    name="Q1_Portfolio",
    selections=[BlueprintSelection(strategy_name="Strat1", blueprint_name="bp1")],
    capital=100000,
    currency="USD",
    account_source="FTMO",
    platform="MT5",
)

# Or via registry.select()
portfolio = registry.select(...)

# Get configs for backtesting
configs = portfolio.get_configs(registry)

# Immutable operations (return new instance)
new_portfolio = portfolio.add_selection("Strat2", "bp2")
new_portfolio = portfolio.remove_selection("Strat1", "bp1")

# Properties
portfolio.strategy_names     # List[str] unique names
portfolio.selection_count    # int

# Serialization
portfolio.save("portfolio.json")
loaded = Portfolio.load("portfolio.json")
portfolio.to_json()
portfolio.to_dict()

Indicators

Indicator Factory

from tradepose_models.indicators import Indicator

# Moving Averages
Indicator.sma(period=20, column="close")
Indicator.ema(period=20, column="close")
Indicator.smma(period=20, column="close")
Indicator.wma(period=20, column="close")

# Volatility
Indicator.atr(period=14)
Indicator.atr_quantile(period=14, quantile=0.5, window=252)
Indicator.bollinger_bands(period=20, num_std=2.0)

# Trend
Indicator.supertrend(multiplier=3.0, volatility_column="ATR|14")
Indicator.macd(fast=12, slow=26, signal=9)
Indicator.adx(period=14)

# Momentum
Indicator.rsi(period=14)
Indicator.cci(period=20)
Indicator.stochastic(k_period=14, d_period=3)

# Volume Profile
Indicator.market_profile(
    period=30,
    tick_size=0.25,
    value_area_pct=0.70,
)

# Raw OHLCV
Indicator.raw_ohlcv(column="close")

Usage Examples

Multi-Strategy Backtesting

from tradepose_models.strategy import StrategyConfig, StrategyRegistry
from tradepose_client import BatchTester
from tradepose_client.batch import Period

# Setup registry
registry = StrategyRegistry()

# Load multiple strategies
for path in ["strat1.json", "strat2.json", "strat3.json"]:
    strategy = StrategyConfig.load(path)
    registry.add(strategy)

print(f"Registry: {len(registry)} entries")
# Registry: 8 entries (if strategies have multiple blueprints)

# Backtest all
configs = registry.get_configs()
tester = BatchTester(api_key="tp_xxx")
batch = tester.submit_backtest(
    strategies=configs,
    periods=[Period.Q1(2024), Period.Q2(2024)],
)
batch.wait()
print(batch.trades)

Portfolio-Based Testing

# Create focused portfolio
momentum_portfolio = registry.select(
    name="Momentum_Suite",
    selections=[
        ("TrendFollower", "momentum_long"),
        ("TrendFollower", "momentum_short"),
        ("BreakoutTrader", "range_breakout"),
    ],
    capital=50000,
    currency="USD",
)

# Test portfolio only
configs = momentum_portfolio.get_configs(registry)
batch = tester.submit_backtest(strategies=configs, periods=[Period.Q1(2024)])

# Save portfolio for later
momentum_portfolio.save("momentum_portfolio.json")

Indicator with Struct Fields

from tradepose_models.strategy import IndicatorSpec, Trigger
from tradepose_models.indicators import Indicator
from tradepose_models.enums import Freq, OrderStrategy
import polars as pl

# SuperTrend returns struct with multiple fields
supertrend = IndicatorSpec(
    freq=Freq.DAY_1,
    shift=1,
    indicator=Indicator.supertrend(multiplier=3.0, volatility_column="ATR|14"),
)

# Access struct fields in conditions
trigger = Trigger(
    name="supertrend_long",
    conditions=[
        supertrend.col().struct.field("direction") == 1,  # Long signal
        supertrend.col().struct.field("supertrend") < pl.col("close"),
    ],
    offset_expr=pl.lit(0.0),
    order_strategy=OrderStrategy.IMMEDIATE_ENTRY,
    priority=1,
)

Enhanced OHLCV Timezone Schema

Enhanced OHLCV is evaluated in the owning strategy's IANA timezone. Build its complete schema with that explicit runtime value:

from tradepose_models.schemas import (
    enhanced_ohlcv_cast_schema,
    get_enhanced_ohlcv_schema,
)

complete_schema = get_enhanced_ohlcv_schema(strategy.tz)
assert complete_schema["ts"] == pl.Datetime("ms", strategy.tz)

get_enhanced_ohlcv_schema() includes ts and is intended for complete-result construction or validation. enhanced_ohlcv_cast_schema intentionally excludes ts; use it only to normalize timezone-independent columns while preserving the timezone metadata already present after an engine result or Parquet read. There is no timezone-naive or hard-coded UTC default for Enhanced OHLCV.

Trades use Datetime("ms", "UTC") so multi-strategy results can be concatenated. Trade rows do not store strategy_tz; local display needs the original strategy_name -> IANA timezone mapping, and historical evaluation timezone cannot be recovered from a trade alone if that mapping is lost.


File Structure

packages/models/src/tradepose_models/
├── __init__.py
├── base.py                 # BaseModel configuration
├── enums/
│   ├── __init__.py
│   ├── freq.py             # Time frequencies
│   ├── trade_direction.py  # LONG/SHORT
│   ├── trend_type.py       # TREND/RANGE/REVERSAL
│   ├── order_strategy.py   # Entry/exit strategies
│   ├── currency.py         # Currency types
│   ├── platform.py         # Trading platforms
│   ├── account_source.py   # Brokers/prop firms
│   └── ...
├── strategy/
│   ├── __init__.py
│   ├── config.py           # StrategyConfig
│   ├── blueprint.py        # Blueprint
│   ├── trigger.py          # Trigger
│   ├── indicator_spec.py   # IndicatorSpec
│   ├── registry.py         # StrategyRegistry, RegistryEntry, BlueprintSelection
│   ├── portfolio.py        # Portfolio
│   └── helpers.py          # Factory functions
├── indicators/
│   ├── __init__.py
│   ├── factory.py          # Indicator factory
│   └── ...                 # Indicator type definitions
├── schemas/
│   ├── __init__.py
│   ├── trades.py           # Trades schema
│   ├── performance.py      # Performance schema
│   └── enhanced_ohlcv.py   # Strategy-local Enhanced OHLCV schema and cast map
└── ...

Development

Running Tests

# Run models tests
uv run python -m pytest tests/models/ -v

# Run with coverage
uv run python -m pytest tests/models/ --cov=tradepose_models

License

MIT License - see LICENSE file for details.


Support

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tradepose_models-2.4.1.tar.gz (143.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tradepose_models-2.4.1-py3-none-any.whl (157.3 kB view details)

Uploaded Python 3

File details

Details for the file tradepose_models-2.4.1.tar.gz.

File metadata

  • Download URL: tradepose_models-2.4.1.tar.gz
  • Upload date:
  • Size: 143.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tradepose_models-2.4.1.tar.gz
Algorithm Hash digest
SHA256 bdc34934a57e4aa01d73a7863fe4461573bb1a164687765d96a5d24e8e9560e0
MD5 81c44e3e6ae6e97560ec82fb416bc08f
BLAKE2b-256 c0dfe96a8f4a2cbba0971f0b3250b7a856ccd29dcc01f11a73e2b4341333fae8

See more details on using hashes here.

Provenance

The following attestation bundles were made for tradepose_models-2.4.1.tar.gz:

Publisher: publish-python-models.yml on 2841l45j04/tradepose-monorepo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tradepose_models-2.4.1-py3-none-any.whl.

File metadata

File hashes

Hashes for tradepose_models-2.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a82e4dc35aabf5fde59bfc485fdd95e365262d36f128db874d3beb7d66924719
MD5 f18514b2bdd4d15b9a0abab3d0349dfd
BLAKE2b-256 7f6d231b35587504bdfcf7faeb436d13cb2b2a57f35fad1d5fe546ed3d9782e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for tradepose_models-2.4.1-py3-none-any.whl:

Publisher: publish-python-models.yml on 2841l45j04/tradepose-monorepo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.15.0

2 files

2.14.0

2 files

2.13.0

2 files

2.12.0

2 files

2.11.1

2 files

2.11.0

2 files

2.10.0

2 files

2.9.1

2 files

2.9.0

2 files

2.8.0

2 files

2.7.3

2 files

2.7.2

2 files

2.7.1

2 files

2.7.0

2 files

2.6.0

2 files

2.5.0

2 files

This release

2.4.1 This release

2 files

2.4.0

2 files

2.3.0

2 files

2.2.0

2 files

2.1.0

2 files

2.0.0

2 files

1.7.0

2 files

1.6.1

2 files

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page