Legacy alphaswarm.core.types shim
Status: Phase 5 finalization shipped. The module is now a thin compatibility shim over
alphaswarm.core.domain.
Why a shim and not a delete
The legacy module is imported by ~140 files across the codebase (strategies, brokers, REST routes, paper-trading session, backtest engines, RL apps, tests). A hard delete would break every one of them in the same commit.
The shim approach preserves backward compatibility while making the domain types the recommended path:
- Every public name still imports -- no breaking change for the 140 existing importers.
- Each domain-replaceable class is marked DEPRECATED in its
docstring with a
.. deprecated:: 5.0Sphinx directive pointing at the canonical type. - Bridge methods on each legacy class let callers convert to the
domain shape with one method call:
Symbol.to_instrument_id()OrderRequest.to_domain_order(client_order_id=, account=)OrderData.to_domain_order()/OrderData.from_domain_order(...)TradeData.from_execution_report(...)PositionData.from_account_position_row(...)AccountData.from_account_row(account_row, balances=...)
- Domain re-exports at module bottom let callers migrate one
import at a time --
from alphaswarm.core.types import DomainOrderworks without rewriting the import line.
Three categories of type
Category 1 -- Domain replacement available
| Legacy | Domain canonical |
|---|---|
Symbol | alphaswarm.core.domain.identifiers.InstrumentId |
Exchange | alphaswarm.core.domain.identifiers.Venue (string-valued ID) |
AssetClass | alphaswarm.core.domain.enums.AssetClass (richer) |
SecurityType | alphaswarm.core.domain.enums.InstrumentClass |
OrderType | alphaswarm.core.domain.enums.OrderType (superset) |
OrderSide | alphaswarm.core.domain.enums.OrderSide (superset) |
OrderStatus | alphaswarm.core.domain.enums.OrderStatus (superset) |
Direction | alphaswarm.core.domain.enums.PositionSide |
OrderRequest | alphaswarm.core.domain.orders.DomainOrder |
OrderData | alphaswarm.core.domain.orders.DomainOrder |
AccountData | alphaswarm.persistence.models_accounts.AccountRow + balances |
PositionData | alphaswarm.persistence.models_accounts.AccountPositionRow |
TradeData | alphaswarm.trading.execution.ExecutionReport |
The legacy classes in this category are shims. Their docstring carries
.. deprecated:: 5.0 and points at the canonical type.
Category 2 -- Authoritative here (no domain replacement)
Market-data records and data-plane routing have no domain equivalents because the domain layer is about identity / orders / accounts, not the data plane:
BarData,TradeBar(alias),QuoteBar,TickData,Tick(alias)SubscriptionDataConfig,Interval,Resolution,TickType,DataNormalizationMode
Framework value objects for the alpha / portfolio stages:
Signal,PortfolioTarget
Backtest event-loop types:
Event,EventType,MarketEvent,SignalEvent,OrderEvent_Msg,FillEvent_Msg
Legacy framework patterns for the existing PaperTradingSession:
OrderEvent(state-transition record, NOT the messaging event),OrderTicket,SecurityHolding,Cash,CashBook
These types remain authoritative here.
Category 3 -- Domain re-exports
Every Phase 1-5 domain type is re-exported from alphaswarm.core.types so
callers can incrementally migrate. The recommended long-term migration
is from alphaswarm.core.domain import ..., but the shim re-exports let you
do it one import line at a time:
# Both work after Phase 5. The second is the recommended long-term form.
from alphaswarm.core.types import DomainOrder, InstrumentId, OmsType
from alphaswarm.core.domain import DomainOrder, InstrumentId, OmsType
The re-exports cover every name from
alphaswarm/core/domain/enums.py,
alphaswarm/core/domain/identifiers.py,
and alphaswarm/core/domain/orders.py.
Names that would collide with the legacy enums get a Domain prefix:
| Legacy | Domain re-export |
|---|---|
OrderType | DomainOrderType |
OrderSide | DomainOrderSide |
OrderStatus | DomainOrderStatus |
AssetClass | DomainAssetClass |
AccountType (legacy doesn't exist) | DomainAccountType |
Everything else (InstrumentId, ClientOrderId, OrderListId,
DomainOrder, LimitOrder, StopMarketOrder, OrderList,
PositionSide, OmsType, ContingencyType, TriggerType,
TimeInForce, TrailingOffsetType, InstrumentClass,
LiquiditySide, AggressorSide, ...) is re-exported under its
original name.
Migration workflow
For a file currently using legacy types:
-
Drop in domain bridges where convenient. No import changes needed:
from alphaswarm.core.types import OrderRequest
req = OrderRequest(...)
domain = req.to_domain_order() # bridge to canonical -
Switch single imports incrementally. Replace one legacy import at a time with the domain re-export through the shim:
# Before
from alphaswarm.core.types import OrderType, OrderSide, OrderStatus
# After (works today, no functional change)
from alphaswarm.core.types import (
DomainOrderType as OrderType,
DomainOrderSide as OrderSide,
DomainOrderStatus as OrderStatus,
) -
Final form -- direct from domain. Once the entire file is migrated, drop the shim:
from alphaswarm.core.domain.enums import OrderType, OrderSide, OrderStatus
Why we keep the legacy enums (instead of aliasing to domain)
The temptation is "just OrderType = DomainOrderType". We don't,
because:
- Existing DB rows persist the legacy string values. The legacy
enum has
STOP = "stop"; the domain hasSTOP_MARKET = "stop_market". Renaming the enum would invalidate every previously-savedorder_typecolumn. - YAML strategy configs use the legacy values. Backward compat with shipped strategy YAML is a hard requirement.
- Some legacy values have NO domain equivalent.
OrderStatus.NEW(legacy) maps toOrderStatus.ACCEPTED(domain) but the legacy state machine has a different topology (no PENDING_UPDATE / PENDING_CANCEL).
The legacy enums are therefore kept verbatim; the deprecation directive points callers at the richer domain enum, and the re-exports give callers an opt-in path.
When the shim can finally be deleted
The shim file disappears when:
- Every importer has migrated to
from alphaswarm.core.domain import ... - Every persisted legacy enum value has been migrated to the
domain canonical (
stop->stop_market,cancelled->canceled,new->accepted,partial->partially_filled) - Every shipped YAML strategy config has been rewritten to use the domain values
That migration is a separate, multi-PR effort tracked outside this Phase 5 finalization. The shim stays put until it's done.
Bridge method reference
from alphaswarm.core.types import (
Symbol, OrderRequest, OrderData, TradeData,
PositionData, AccountData,
)
# Symbol <-> InstrumentId
sym = Symbol.parse("AAPL.NASDAQ")
iid = sym.to_instrument_id()
back = Symbol.from_instrument_id(iid)
# OrderRequest -> DomainOrder
req = OrderRequest(symbol=sym, side=..., order_type=..., quantity=10)
domain = req.to_domain_order(client_order_id="cl-1", gateway="alpaca")
# OrderData round-trip
data = OrderData(...)
domain = data.to_domain_order()
rebuilt = OrderData.from_domain_order(domain, gateway="alpaca")
# TradeData from ExecutionReport
from alphaswarm.trading.execution import ExecutionReport
trade = TradeData.from_execution_report(report)
# PositionData from AccountPositionRow
from alphaswarm.persistence.models_accounts import AccountPositionRow
pos = PositionData.from_account_position_row(row)
# AccountData snapshot from persistence rows
from alphaswarm.persistence.models_accounts import AccountRow, AccountBalanceRow
snapshot = AccountData.from_account_row(account_row, balances=balance_rows)