Skip to content

Security 类型体系 — Equity / Fixed Income / Fund

RC 系统中所有可交易的证券统一存储在 securities 表中,通过 type 字段区分三大类,每类有独立的 1:1 子表承载专属属性。

Equity(股票)Fixed Income(债券)Fund(基金)
你持有的公司的一部分所有权对发行方的债权一篮子资产的份额
收益来源股价上涨 + 股息固定票息 + 到期还本净值变动 + 分红
风险特征高波动,无保本信用风险 + 利率风险取决于底层持仓
到期日有明确到期日开放式基金无
发行方上市公司政府 / 公司基金公司
securities (主表)
├── type = 'equity' → equities (1:1)
├── type = 'fixed_income' → fixed_incomes (1:1)
└── type = 'fund' → funds (1:1)

所有证券的通用标识和元信息:

字段类型说明
typeenumequity | fund | fixed_income
namestring证券名称
symbolstring交易代码(如 AAPL
normalized_symbolstring标准化后的 symbol(去特殊字符、大写)
cusipstring(9)CUSIP 标识
isinstring(12)ISIN 标识
referencestring供应商侧唯一标识
sourceenum数据来源(morningstarbrokeragegeneric 等 47 种)
exchange_idintFK → exchanges
organization_idint所属组织

三个 scope 方法:

Security::equities() where type = 'equity'
Security::fixedIncomes() where type = 'fixed_income'
Security::funds() where type = 'fund'
字段类型说明
security_idintFK → securities.id
sector_idintFK → sectors(11 个股票板块)
category_idintFK → categories(风格类别)
capitalizationenumsmall | middle | large
valuationenumvalue | blend | growth
countrystring(3)3 字母 ISO 国家代码

股票的核心分析维度:

  • Sector → 来自 Morningstar GECS Sector 层,11 个板块(详见 Sector 分类
  • Categorycapitalization × valuation = 9 宫格 Style Box
  • Country → 用于判定 developed / emerging 市场
字段类型说明
security_idintFK → securities.id
sector_idintFK → sectors(6 个债券板块)
category_idintFK → categories
subtypeenumbond | cd | mbs
marketenumdeveloped | emerging
qualityenumaaa | aa | a | bbb | bb | b | below | unrated

债券的分析维度:

  • Subtype:bond(普通债券)、cd(大额存单)、mbs(抵押贷款支持证券)
  • Quality:信用评级,直接影响风险分析和收益假设
  • Market:发达国家 / 新兴市场
  • Sector:不同于股票的板块体系(Government、Corporate、Securitized 等)
字段类型说明
security_idintFK → securities.id
subtypeenumetf | open_end | closed_end | uit | money_market
expense_ratiofloat费率(%)

基金不直接有 sector / category,而是通过 allocations 分配表”透视”底层持仓:

关联表用途
allocations_by_asset_type大类资产分配(US/Non-US Equity、US/Non-US Bond、Cash…)
allocations_by_sector行业板块分配(11 个股票板块各占 %)
allocations_by_category风格类别分配
allocations_by_market发达 / 新兴市场分配
allocations_by_bond_quality债券信用评级分配
allocations_by_equity_style股票 9 宫格风格分配
fund_equity_portfolio股票持仓明细
fund_bond_portfolio债券持仓明细(duration、maturity)

基金的设计核心是 “透视”(look-through):虽然基金本身是一个 Security,但通过 allocations 层层拆解到底层 equity/bond,从而穿透分析客户组合的真实风险暴露。

// 基金模型上的计算属性
$fund->equity_percentage; // 底层股票占比
$fund->bond_percentage; // 底层债券占比
$fund->percentages_by_category_id; // 风格类别分布
$fund->percentages_by_equity_style; // 9 宫格分布

Fund 的 subtype 区分的是法律结构和交易机制——同样是”一篮子资产”,不同 subtype 的申赎方式、定价频率、流动性完全不同。

enum FundSubtype: string
{
case ETF = 'etf'; // 交易所交易基金
case OPEN_END = 'open_end'; // 开放式基金(共同基金)
case CLOSED_END = 'closed_end'; // 封闭式基金
case UIT = 'uit'; // 单位投资信托
case MONEY_MARKET = 'money_market'; // 货币市场基金
}
Subtype中文交易方式定价份额可变?典型例子
ETF交易所交易基金交易所实时买卖,像股票一样盘中实时市价是(授权参与人创建/赎回)SPY, QQQ
Open-End开放式基金通过基金公司每日申赎每日收盘后 NAVVTSAX
Closed-End封闭式基金交易所买卖市价(可能溢价/折价于 NAV)否(固定份额)市政债 CEF
UIT单位投资信托通过发行商申赎基于底层资产估值否(固定组合+到期日)固定收益 UIT
Money Market货币市场基金通过基金公司每日申赎稳定 $1 NAVVMFXX

1. 申购/赎回机制不同

ETF 和 Closed-End 在交易所交易(有 bid/ask spread),Open-End 和 Money Market 是按 NAV 申赎。在 brokerage 集成中直接影响持仓匹配:

// Security::matchEquityFundMoneyMarketSecuritiesBySymbol()
if ($discrete_type === 'money_market_fund') {
$query->where(self::COLUMN_TYPE, SecurityType::FUND)
->whereHas('fund', fn ($q) => $q->where('subtype', FundSubtype::MONEY_MARKET));
}

2. 现金等价物判定

Money Market Fund 被视为现金等价物,在计算投资账户的现金头寸时被特殊对待:

InvestmentAccount.php
} elseif ($position->security?->type === SecurityType::FUND
&& $position->security->fund?->subtype === FundSubtype::MONEY_MARKET) {
$carry += $position->value; // 归入现金
}

3. 供应商数据映射

不同供应商对同一类基金的叫法不同,subtype 是统一抽象层。HoldingInterface 将供应商的 discrete type 映射到系统 subtype:

HoldingInterface.php
self::DISCRETE_TYPE_ETF FundSubtype::ETF
self::DISCRETE_TYPE_OPEN_END_FUND FundSubtype::OPEN_END
self::DISCRETE_TYPE_CLOSED_END_FUND FundSubtype::CLOSED_END
self::DISCRETE_TYPE_MONEY_MARKET_FUND FundSubtype::MONEY_MARKET
self::DISCRETE_TYPE_UIT FundSubtype::UIT

4. 费率差异

ETF 通常费率最低(被动指数),Open-End 主动管理基金费率较高,Money Market 费率极低。expense_ratio 字段配合 subtype 一起影响投资回报计算。

同一张 sectors 表,通过 type 字段区分:

// SectorType enum
case EQUITY = 'equity'; // 11 个股票板块 (ID 1-12,含 Not Classified)
case BOND = 'bond'; // 6 个债券板块 (ID 13-18)
Sector TypeID 范围板块
equity1Basic Materials
equity2Consumer Cyclical
equity3Financial Services
equity4Real Estate
equity5Communication Services
equity6Energy
equity7Industrials
equity8Technology
equity9Consumer Defensive
equity10Health Care
equity11Utilities
equity12Not Classified
bond13Government
bond14Corporate
bond15Securitized
bond16Municipal
bond17Cash
bond18Others

equities.sector_idfixed_incomes.sector_id 指向同一个 sectors 表但不同的子集。

Security::createLocal() 在通过 brokerage 集成或手动录入创建证券时,按类型填充默认属性:

类型默认 Sector默认 Category其他默认值
EquityNot Classified (12)Large Growthcapitalization=Large, valuation=Blend, country=USA
Fixed IncomeGovernment (13)Governmentquality=AAA, market=Developed, subtype=入参
Fund不适用Otherexpense_ratio=0, allocations 按 S&P 500 近似分布填充

系统定义了三个通用 symbol 用于无法识别的证券:

Symbol类型用途
!?Eequity无法识别的股票
!?Ffund无法识别的基金
!?Bbond无法识别的债券

生产环境中,这三类证券的数据主要来自 Morningstar:

数据类型Morningstar 来源本地 extractor / transformer
Equity 基本数据CompanyReference + SecurityReferenceEquity\CompanyReferenceEquity\SecurityReference
Equity sector + styleAssetClassification(Data Point 3007、3001)Equity\AssetClassification
Equity 价格Price(Data Point 30003)Equity\Price
Fund 数据DataWarehouse37 + AssetClassification30 + InvestmentVehicleFund\* extractors
Fund 价格PricesFund\Price

迁移到 GEDF / Snowflake 后,Equity 数据来源变更详见 DEV-19911 Morningstar GECSequity-data-migration-v1.md

graph TD
    S["securities<br/>type: equity | fund | fixed_income<br/>name, symbol, cusip, isin"]

    E["equities<br/>sector_id (1-12)<br/>capitalization: small|middle|large<br/>valuation: value|blend|growth<br/>country"]
    FI["fixed_incomes<br/>sector_id (13-18)<br/>subtype: bond|cd|mbs<br/>quality: aaa...below<br/>market: developed|emerging"]
    F["funds<br/>subtype: etf|open_end|closed_end|uit|money_market<br/>expense_ratio"]

    S -->|type=equity| E
    S -->|type=fixed_income| FI
    S -->|type=fund| F

    F --> AAT["allocations_by_asset_type<br/>US/Non-US Equity/Bond/Cash %"]
    F --> ASEC["allocations_by_sector<br/>11 个股票板块 %"]
    F --> ACAT["allocations_by_category<br/>风格类别 %"]
    F --> AMKT["allocations_by_market<br/>发达/新兴 %"]
    F --> ABQ["allocations_by_bond_quality<br/>信用评级分布"]
    F --> AES["allocations_by_equity_style<br/>9 宫格风格分布"]
    F --> FEP["fund_equity_portfolio<br/>股票持仓明细"]
    F --> FBP["fund_bond_portfolio<br/>债券持仓明细"]

    E --> SEC_E["sectors (type=equity)<br/>11 板块"]
    FI --> SEC_B["sectors (type=bond)<br/>6 板块"]
    ASEC --> SEC_E