Morningstar Security Master
Morningstar is RightCapital’s primary source for Security Master data — the reference database for all securities (equities, funds, ETFs) including prices, classifications, and identifiers.
Repository: gitlab.rightcapital.io/integrations/morningstar Tech Stack: Laravel 12 (PHP 8.4), MySQL (dual-database), AWS S3, FTP Owners: Yan Hu, Tingsong Xu
What Data Does It Provide?
Section titled “What Data Does It Provide?”| Category | Examples |
|---|---|
| Identifiers | Morningstar ID, Performance ID, CUSIP (partial), ISIN, Ticker |
| Basic Info | Name, type (equity/fund), company, exchange |
| Pricing | Daily close prices |
| Classifications | Sector, industry, category, holding style |
| Fund Details | Expense ratio, allocations (asset type, bond quality, equity style, market, sector) |
| Portfolios | Top equity holdings, bond holdings |
Architecture
Section titled “Architecture”Dual-Database Design
Section titled “Dual-Database Design”The service operates across two MySQL databases:
| Database | Purpose | Key Tables |
|---|---|---|
| morningstar (default) | Raw extracted data from Morningstar files | securities, companies, funds, prices, files, imports |
| api | Processed data in RightCapital core-model schema | securities, equities, funds, allocations_by_*, fund_*_portfolios |
The api database uses the rightcapital/core-models package schema — the same tables that retail-api reads from.
Data Pipeline
Section titled “Data Pipeline”flowchart TD
FTP["Morningstar FTP Server<br/><code>ftp.morningstar.com</code>"]
S3["AWS S3 Bucket"]
MDB["Morningstar DB<br/>(raw data)"]
ADB["API DB<br/>(core-models)"]
RAPI["Retail API"]
FTP -->|"<b>retrieve</b><br/>hourly, prod only<br/>ZIP/GZ files"| S3
S3 -->|"<b>data:import</b><br/>download & extract"| MDB
MDB -->|"<b>data:transform</b><br/>parse allocations,<br/>portfolios, styles"| MDB
MDB -->|"<b>sync:push</b><br/>copy to core-models"| ADB
ADB -->|"<b>webhook</b><br/>POST /v2/webhooks/"| RAPI
Pipeline Commands
Section titled “Pipeline Commands”The full daily pipeline runs via php artisan process (4:15 AM ET, Tue-Sat):
1. File Retrieval (retrieve)
Section titled “1. File Retrieval (retrieve)”Schedule: Every hour (production only), monitored by Cronitor.
| Step | Command | What It Does |
|---|---|---|
| Download | file:retrieve | Connects to ftp.morningstar.com (user: ondemandrightcapital). Lists files matching patterns in config/morningstar.php. Validates trigger files (.ctrl / _trigger.txt) exist. Uploads ZIP/GZ to S3. |
| Status | file:update-status | Marks imports table entries from NEW → READY. |
2. Data Import (data:import)
Section titled “2. Data Import (data:import)”Downloads files from S3 to /var/opt/morningstar, extracts archives, and runs extractors.
Data Groups:
| Group | Content | Extractors |
|---|---|---|
equity | Stock reference data, company info, prices | SecurityReference, CompanyReference, AssetClassification, Price |
fund_FO/FE/FC/FM | Fund data (DataWarehouse XML), prices | DataWarehouse37, AssetClassification30, Price |
Each group has daily + monthly file variants. Files are downloaded from specific FTP folders:
- Equity:
/Daily/NRA/Reference_v3/,/Daily/NRA/Price/, etc. - Fund:
/Daily/DataWarehouse_v3/,/Modules/daily/Prices/, etc.
3. Data Transform (data:transform)
Section titled “3. Data Transform (data:transform)”Processes securities in chunks of 5,000:
- Runs
Transformeron each security - Parses allocations across 6 dimensions (asset type, bond quality, category, equity style, market, sector)
- Maps Morningstar taxonomies to RightCapital’s 14 asset classes
- Stores result as JSON in
securities.derivedcolumn - Saves prices to
morningstar.pricestable
Key mapping file: Transformers/Mapping.php — defines:
- 14 categories (Large Growth, Bonds, etc.)
- 9 holding styles (Large Value, Mid Growth, etc.)
- 11 sectors (Technology, Healthcare, etc.)
- Geographic markets and market caps
- Bond quality ratings (AAA through Unrated)
4. Sync Push (sync:push)
Section titled “4. Sync Push (sync:push)”Copies processed data from morningstar DB → api DB (core-models):
- Securities: Insert/update with
api_idforeign key mapping - Child records: Equities, funds, all allocation types, portfolios
- Lifecycle: Disables securities without prices (
has_price=0), enforces blacklist (e.g., symbolPDRG) - Webhook to retail-api: Notifies about security deletions
- Cache flush: Invalidates Redis keys for prices, security lookups, trashed IDs
Interaction with Retail API
Section titled “Interaction with Retail API”Webhook Endpoints
Section titled “Webhook Endpoints”The service communicates with retail-api via HTTP webhooks:
| Endpoint | Purpose | Payload |
|---|---|---|
POST /v2/webhooks/morningstar/security | Notify security deletions | {action: 'delete', security_ids: [...]} |
POST /v2/webhooks/cache | Flush Redis cache | {redis: {client: 'Morningstar', models: {security: []}, globs: ['Price:LatestArray:*', 'Security:Lookup:*'], keys: ['Security:TrashedIds']}} |
Auth: Basic Auth with user Morningstar, password from env RETAIL_API_KEY.
Helper: send_request_to_retail_api(path, body) in app/Support/helpers.php.
Retail API Side
Section titled “Retail API Side”Retail-api receives these webhooks at SecurityController (app/Http/Controllers/Webhooks/Morningstar/SecurityController.php), protected by auth.internal:Morningstar middleware.
On security deletion, retail-api fires a SecurityDeleted event that:
- Detaches positions (copies security metadata to
custom_securityJSON) - Deletes target category mix allocations using the security
- Nullifies security references in stock plan accounts
Data Structures
Section titled “Data Structures”Morningstar DB: securities Table
Section titled “Morningstar DB: securities Table”id AUTO_INCREMENTmorningstar_id CHAR(10), unique -- e.g., "F00000MLJO"morningstar_performance_id CHAR(10), unique -- e.g., "0P00015GFM"morningstar_company_id FK → companies.morningstar_idsymbol VARCHAR, indexedcusip CHAR(9), nullable, indexedisin CHAR(12), nullable, indexedtype ENUM('equity', 'fund')api_exchange_id TINYINT UNSIGNEDname VARCHAR, nullableapi_id INT, nullable, indexed -- FK to retail-api securitiesapi_deleted BOOLEANhas_price BOOLEANderived TEXT (JSON) -- transformed data for all child modelsSecurity Matching
Section titled “Security Matching”When vendor integrations sync holdings into retail-api, each holding must be matched to a Security Master record. Matching priority:
- CUSIP — Most reliable (but limited coverage post-2018)
- ISIN — International standard
- Symbol + Name verification — Symbol lookup + name similarity check
- AI Name Matching (DEV-19528, in progress) — Replaces
similar_textwith LLM-based name comparison for symbol-matched candidates
Cron Jobs
Section titled “Cron Jobs”Deployed via Kubernetes CronJobs (deploy/cron-jobs.yaml.gotmpl):
| Job | Schedule | Environment | Resource |
|---|---|---|---|
retrieve | 0 * * * * (hourly) | Production only | 1 CPU |
process | 15 4 * * 2,3,4,5,6 (4:15 AM ET, Tue-Sat) | All | 1 CPU, 1Gi RAM |
All jobs monitored via Cronitor with health pings on start/complete/fail.
Configuration
Section titled “Configuration”Key Environment Variables
Section titled “Key Environment Variables”| Variable | Purpose |
|---|---|
MORNINGSTAR_FTP_PASSWORD | FTP credential for ftp.morningstar.com |
DB_* / DB_API_* | Morningstar DB / API DB connection |
AWS_BUCKET | S3 bucket for file staging |
RETAIL_API_URL | Retail API base URL for webhooks |
RETAIL_API_KEY | Basic Auth password for webhook calls |
CRONITOR_API_KEY | Monitoring credentials |
File Pattern Configuration
Section titled “File Pattern Configuration”config/morningstar.php defines 7 download specs: FTP folders, file name patterns, and trigger file suffixes for equity references, asset classifications, prices, fund data warehouse, and fund prices.
Morningstar Office Sunset (DEV-19366)
Section titled “Morningstar Office Sunset (DEV-19366)”Morningstar Office was an OAuth-based integration where advisors synced household/account/holding data directly into retail-api. It was sunset on February 28, 2026.
Data migration was executed in two phases:
- Phase A (completed): Detached 3,778 positions from MO securities, converted 11,571 active accounts to manual (
source = NULL), soft-deleted 228 integrations - Phase B (deferred): Cleanup of MO securities, trashed accounts, and hard-delete of integrations
See Morningstar Office for details.
Related
Section titled “Related”- Morningstar Office — Data sync integration (sunset 2026/02/28)
- Morningstar Advisor Workstation — Report generation (active)
- Security Matching Enhancement (DEV-19528) — AI name matching proposal
- Notion: Morningstar Home — Team wiki
- Notion: Integration 的组成 — Architecture overview