Models
The models concept owns SQLAlchemy definitions for the market-domain schema.
These declarations define what can be registered as Main Sequence MetaTables and
in which dependency order. Table declaration class names use the Table suffix;
for example, AssetTable is the SQLAlchemy MetaTable declaration while
msm.api.assets.Asset is the user-facing Pydantic row object.
msm.models does not export unsuffixed row names. Imports such as
from msm.models import Asset are removed; use from msm.models import
AssetTable for schema work or from msm.api.assets import Asset for row
operations.
Pricing-specific MetaTables are not core markets models. Tables such as
IndexConventionDetailsTable, CurveTable, and
AssetCurrentPricingDetailsTable live under msm_pricing.models and are
selected through msm_pricing.meta_tables.pricing_sqlalchemy_models().
Runtime initialization should use
msm_pricing.bootstrap.attach_pricing_schemas(...), which includes core
dependencies such as AssetTable, IndexTypeTable, and IndexTable before
pricing extension tables and resolves them through direct backend attachment.
Scope
Models answer these questions:
- Which market objects are persisted as relational records?
- Which fields and indexes belong to the platform schema?
- Which relationships are database concerns rather than client concerns?
- In what order should MetaTables be registered?
Primary Modules
msm.models.__init__: aggregate model exports andmarkets_sqlalchemy_models.msm.models.registration: registration and resolution helpers for turning SQLAlchemy table declarations into Main Sequence MetaTables.msm.models.accounts: account registry, account target allocations, position sets, account groups, and account allocation models.msm.models.accounts.allocation_models: reusable account allocation-model registry rows.msm.models.accounts.core: core account registry, account target allocation, and position-set tables.msm.models.accounts.groups: account group tables.msm.models.assets: asset-related models, including the core asset registry, registered asset types, categories, memberships, and provider details.msm.models.assets.core: core asset registry.msm.models.assets.types: registered asset type definitions.msm.models.assets.bonds: one-to-one bond asset detail rows.msm.models.assets.categories: categories and memberships.msm.models.calendars: calendar identity, date, session, and event tables.msm.models.execution: execution tables.msm_portfolios.models.virtual_funds: funds.msm.models.indices: index type registry and canonical index reference rows.msm.models.issuers: issuer reference data used by bond assets.msm.models.portfolios: core portfolio identity/reference tables.msm.models.assets.provider_details: provider-specific asset metadata.msm_portfolios.models.rebalancing: rebalance strategy metadata.msm_portfolios.models.signals: signal metadata.msm.api.*andmsm_portfolios.api.*: user-facing Pydantic rows and class-owned row operations for markets MetaTables.
Key Contracts
markets_sqlalchemy_models() returns core msm models in dependency order.
msm_portfolios.models.portfolio_sqlalchemy_models() returns portfolio
construction models. Keep the owning package list updated when adding
persistent market objects so schema registration stays deterministic.
Models should represent durable schema. Runtime-only behavior belongs in
DataNodes, services, pricing classes, or msm.api row helpers depending on the
use case.
The core markets_sqlalchemy_models() list intentionally does not include
portfolio-package or optional pricing-package tables. It does include core
account allocation and virtual-fund state. Use msm_portfolios for portfolio
construction workflows and the pricing helper when a workflow needs
pricing-owned current instrument payloads, index conventions, or curve identity
rows.
Every model returned by markets_sqlalchemy_models() must be registerable as a
MetaTable in both platform-managed and external-registered modes.
Platform-managed models inherit MarketsMetaTableMixin, which assigns the
physical SQLAlchemy table name through the package naming convention. Model
classes should declare a logical identifier, __metatable_description__, and
SQLAlchemy __table_args__, but should not hand-write __tablename__.
The physical name is ms_markets__<lowercase-concept> and gains an
MSM_AUTO_REGISTER_NAMESPACE suffix when that environment variable is set
before model import.
Project-local extension models can keep the markets mixins while using a
project-owned physical table-name app segment. Set __markets_storage_app__ in
the SQLAlchemy model class, or in an abstract project-local mixin, before the
model is imported and mapped:
class MyProjectMarketsMetaTableMixin(MarketsMetaTableMixin):
__abstract__ = True
__metatable_namespace__ = "com.my_project"
__markets_storage_app__ = "my_project_markets"
class BinanceSpotAccountDetailsTable(MyProjectMarketsMetaTableMixin, MarketsBase):
__markets_base_identifier__ = "BinanceSpotAccountDetails"
__metatable_description__ = (
"Project-local Binance spot account details keyed by AssetTable.uid."
)
That changes only the SQLAlchemy physical table name, for example
my_project_markets__binancespotaccountdetails. The local mixin's
__metatable_namespace__ combines with __markets_base_identifier__ to produce
the globally unique logical catalog and row runtime identity:
com.my_project.BinanceSpotAccountDetails.
MSM_AUTO_REGISTER_NAMESPACE overrides the mixin namespace when set before
model import. That keeps tests and examples isolated without changing the
project-local model source. Existing models may still declare an already
qualified __metatable_identifier__; new extension models should prefer
__markets_base_identifier__ so the default namespace rule is visible.
__metatable_description__ is required on every concrete markets MetaTable,
including PlatformTimeIndexMetaTable storage classes used by DataNodes. The
description is table-level discovery text: it should identify the row grain,
business intention, and expected use of the table. Column labels and column
descriptions stay on SQLAlchemy column info metadata. Built-in markets and
pricing tables are validated so every physical column has a non-empty
description before registration-facing tests pass.
Built-in ms-markets models author __metatable_identifier__ as the bare logical
name, such as Asset. At runtime the shared markets identifier rule keeps the
bare name for the default markets namespace and prefixes non-default test or
example namespaces, such as mainsequence.examples.Asset.
Extension Notes
When adding a built-in library model:
- Define the SQLAlchemy class in the relevant module with a
Tablesuffix. - Add it to
markets_sqlalchemy_models()in dependency order. - Add repository operations if application code needs compiled database access.
- Add a
MarketsMetaTableRowPydantic row model undermsm.apiwhen users should manipulate typed row objects. - Add service wrappers if the operation is part of a broader application workflow.
Project-local extension models do not need to modify markets_sqlalchemy_models().
Pass the SQLAlchemy model class directly to
msm.start_engine(models=[MyExtensionTable]); bootstrap expands SQLAlchemy
ForeignKey(...) dependencies and attaches the model through the shared direct
backend lookup path.