Files
group_fqcd_jr/app/model/advisor_product.py
T

285 lines
16 KiB
Python
Raw Normal View History

2026-09-11 12:47:01 +08:00
"""ORM mappings for additive advisory product reference tables.
The immutable ``fin_product`` catalogue remains mapped by ``FundProduct`` in
``app.model.fund``. This module only maps the new advisory evidence tables.
"""
from datetime import date, datetime
from decimal import Decimal
from typing import Any
from sqlalchemy import JSON, BigInteger, Date, DateTime, Numeric, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.model.base import Base
2026-09-11 13:20:09 +08:00
class AdvisorProductIndustryExposure(Base):
__tablename__ = "advisor_product_industry_exposure"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
industry_code: Mapped[str] = mapped_column(String(32), nullable=False)
industry_name: Mapped[str] = mapped_column(String(128), nullable=False)
exposure_weight_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False)
as_of_date: Mapped[date] = mapped_column(Date, nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
2026-09-11 12:47:01 +08:00
class AdvisorProductReferenceSnapshot(Base):
__tablename__ = "advisor_product_reference_snapshot"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
as_of_date: Mapped[date] = mapped_column(Date, nullable=False)
fund_type: Mapped[str] = mapped_column(String(64), nullable=False)
fund_asset_scale_billion: Mapped[Decimal] = mapped_column(Numeric(18, 4), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
risk_mapping_version: Mapped[str] = mapped_column(String(32), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductPriceHistory(Base):
__tablename__ = "advisor_product_price_history"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
trade_date: Mapped[date] = mapped_column(Date, nullable=False)
price_kind: Mapped[str] = mapped_column(String(16), nullable=False)
close_price: Mapped[Decimal] = mapped_column(Numeric(18, 6), nullable=False)
turnover_amount: Mapped[Decimal | None] = mapped_column(Numeric(24, 2))
source: Mapped[str] = mapped_column(String(64), nullable=False)
source_updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductMetricSnapshot(Base):
__tablename__ = "advisor_product_metric_snapshot"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
as_of_date: Mapped[date] = mapped_column(Date, nullable=False)
trailing_20d_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(10, 4))
trailing_120d_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(10, 4))
annualized_volatility_pct: Mapped[Decimal | None] = mapped_column(Numeric(10, 4))
max_drawdown_pct: Mapped[Decimal | None] = mapped_column(Numeric(10, 4))
average_daily_turnover_amount: Mapped[Decimal | None] = mapped_column(Numeric(24, 2))
observation_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
calculation_version: Mapped[str] = mapped_column(String(16), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
2026-09-11 14:44:29 +08:00
class AdvisorProductAssetClassification(Base):
__tablename__ = "advisor_product_asset_classification"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
as_of_date: Mapped[date] = mapped_column(Date, nullable=False)
asset_class: Mapped[str] = mapped_column(String(32), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductDataQualitySnapshot(Base):
__tablename__ = "advisor_product_data_quality_snapshot"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
as_of_date: Mapped[date] = mapped_column(Date, nullable=False)
observation_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
expected_trading_days: Mapped[int] = mapped_column(BigInteger, nullable=False)
price_coverage_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False)
turnover_coverage_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False)
max_abs_daily_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(10, 4))
status: Mapped[str] = mapped_column(String(16), nullable=False)
reason_codes: Mapped[list[str]] = mapped_column(JSON, nullable=False)
rule_version: Mapped[str] = mapped_column(String(16), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorAllocationBacktestRun(Base):
__tablename__ = "advisor_allocation_backtest_run"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
backtest_no: Mapped[str] = mapped_column(String(36), unique=True, nullable=False)
started_on: Mapped[date] = mapped_column(Date, nullable=False)
ended_on: Mapped[date] = mapped_column(Date, nullable=False)
profile_risk_level: Mapped[str] = mapped_column(String(8), nullable=False)
return_target_lower_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False)
max_drawdown_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False)
liquidity_requirement: Mapped[str] = mapped_column(String(32), nullable=False)
status: Mapped[str] = mapped_column(String(32), nullable=False)
observation_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
static_total_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4))
dynamic_total_return_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4))
static_max_drawdown_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4))
dynamic_max_drawdown_pct: Mapped[Decimal | None] = mapped_column(Numeric(12, 4))
dynamic_rebalance_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
liquidity_history_coverage_pct: Mapped[Decimal] = mapped_column(Numeric(7, 4), nullable=False)
limitations: Mapped[list[str]] = mapped_column(JSON, nullable=False)
strategy_version: Mapped[str] = mapped_column(String(32), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
2026-09-11 12:47:01 +08:00
class AdvisorProductSuitabilityReference(Base):
__tablename__ = "advisor_product_suitability_reference"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
sales_institution: Mapped[str] = mapped_column(String(128), nullable=False)
risk_level: Mapped[str] = mapped_column(String(8), nullable=False)
effective_from: Mapped[date] = mapped_column(Date, nullable=False)
effective_until: Mapped[date | None] = mapped_column(Date)
source_url: Mapped[str] = mapped_column(String(1024), nullable=False)
document_title: Mapped[str] = mapped_column(String(256), nullable=False)
document_published_at: Mapped[date | None] = mapped_column(Date)
document_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
review_status: Mapped[str] = mapped_column(String(16), nullable=False)
verified_by: Mapped[str | None] = mapped_column(String(128))
verified_at: Mapped[datetime | None] = mapped_column(DateTime)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductContractSnapshot(Base):
__tablename__ = "advisor_product_contract_snapshot"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
effective_from: Mapped[date] = mapped_column(Date, nullable=False)
effective_until: Mapped[date | None] = mapped_column(Date)
fund_type: Mapped[str] = mapped_column(String(64), nullable=False)
investment_scope: Mapped[str] = mapped_column(Text, nullable=False)
performance_benchmark: Mapped[str | None] = mapped_column(String(256))
risk_return_characteristics: Mapped[str] = mapped_column(Text, nullable=False)
custodian_name: Mapped[str | None] = mapped_column(String(128))
management_fee_rate_pct: Mapped[Decimal | None] = mapped_column(Numeric(9, 6))
custodian_fee_rate_pct: Mapped[Decimal | None] = mapped_column(Numeric(9, 6))
inception_date: Mapped[date | None] = mapped_column(Date)
source_url: Mapped[str] = mapped_column(String(1024), nullable=False)
document_title: Mapped[str] = mapped_column(String(256), nullable=False)
document_published_at: Mapped[date | None] = mapped_column(Date)
document_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
review_status: Mapped[str] = mapped_column(String(16), nullable=False)
verified_by: Mapped[str | None] = mapped_column(String(128))
verified_at: Mapped[datetime | None] = mapped_column(DateTime)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductGovernanceCandidate(Base):
__tablename__ = "advisor_product_governance_candidate_snapshot"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
data_kind: Mapped[str] = mapped_column(String(16), nullable=False)
sales_institution: Mapped[str | None] = mapped_column(String(128))
observed_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
effective_from: Mapped[date] = mapped_column(Date, nullable=False)
risk_level: Mapped[str | None] = mapped_column(String(8))
payload: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False)
source_url: Mapped[str] = mapped_column(String(1024), nullable=False)
document_title: Mapped[str] = mapped_column(String(256), nullable=False)
document_published_at: Mapped[date | None] = mapped_column(Date)
document_sha256: Mapped[str] = mapped_column(String(64), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
review_status: Mapped[str] = mapped_column(String(16), nullable=False)
reviewed_by: Mapped[int | None] = mapped_column(BigInteger)
reviewed_at: Mapped[datetime | None] = mapped_column(DateTime)
review_comment: Mapped[str | None] = mapped_column(String(1000))
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductGovernanceSyncRun(Base):
__tablename__ = "advisor_product_governance_sync_run"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
run_no: Mapped[str] = mapped_column(String(36), nullable=False, unique=True)
source: Mapped[str] = mapped_column(String(64), nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False)
product_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
change_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
error_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
detail: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False)
started_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
completed_at: Mapped[datetime | None] = mapped_column(DateTime)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorProductMarketQuoteSnapshot(Base):
__tablename__ = "advisor_product_market_quote_snapshot"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
product_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
observed_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
last_price: Mapped[Decimal] = mapped_column(Numeric(18, 6), nullable=False)
previous_close: Mapped[Decimal | None] = mapped_column(Numeric(18, 6))
change_pct: Mapped[Decimal | None] = mapped_column(Numeric(10, 4))
volume: Mapped[Decimal | None] = mapped_column(Numeric(24, 4))
turnover_amount: Mapped[Decimal | None] = mapped_column(Numeric(24, 2))
quote_status: Mapped[str] = mapped_column(String(16), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorMarketQuoteSourceRun(Base):
__tablename__ = "advisor_market_quote_source_run"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
sync_run_no: Mapped[str] = mapped_column(String(36), nullable=False)
source: Mapped[str] = mapped_column(String(64), nullable=False)
priority_order: Mapped[int] = mapped_column(BigInteger, nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False)
requested_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
quote_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
error_type: Mapped[str | None] = mapped_column(String(128))
started_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
completed_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorMarketQuoteSourceHealth(Base):
__tablename__ = "advisor_market_quote_source_health"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
source: Mapped[str] = mapped_column(String(64), nullable=False, unique=True)
status: Mapped[str] = mapped_column(String(16), nullable=False)
consecutive_failure_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
last_success_at: Mapped[datetime | None] = mapped_column(DateTime)
last_failure_at: Mapped[datetime | None] = mapped_column(DateTime)
last_error_type: Mapped[str | None] = mapped_column(String(128))
last_requested_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
last_quote_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
class AdvisorMarketQuoteAlert(Base):
__tablename__ = "advisor_market_quote_alert"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
alert_no: Mapped[str] = mapped_column(String(36), nullable=False, unique=True)
source: Mapped[str] = mapped_column(String(64), nullable=False)
alert_type: Mapped[str] = mapped_column(String(64), nullable=False)
severity: Mapped[str] = mapped_column(String(16), nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False)
occurrence_count: Mapped[int] = mapped_column(BigInteger, nullable=False)
detail: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False)
first_observed_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
last_observed_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
resolved_at: Mapped[datetime | None] = mapped_column(DateTime)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)