diff --git a/dbt_project/models/markets/factor_analysis_return.sql b/dbt_project/models/markets/factor_analysis_return.sql new file mode 100644 index 0000000..921437d --- /dev/null +++ b/dbt_project/models/markets/factor_analysis_return.sql @@ -0,0 +1 @@ +{{ calculate_market_analysis_return('stg_factor_etfs') }} diff --git a/dbt_project/models/markets/factor_sector_correlation.sql b/dbt_project/models/markets/factor_sector_correlation.sql new file mode 100644 index 0000000..fa4b552 --- /dev/null +++ b/dbt_project/models/markets/factor_sector_correlation.sql @@ -0,0 +1,285 @@ +{{ config( + description='Latest factor ETF performance and rolling correlation to sector, style, and thematic ETFs' +) }} + +WITH factor_metadata AS ( + SELECT * + FROM UNNEST([ + STRUCT('VLUE' AS factor_symbol, 'value' AS factor_name), + STRUCT('QUAL' AS factor_symbol, 'quality' AS factor_name), + STRUCT('MTUM' AS factor_symbol, 'momentum' AS factor_name), + STRUCT('SIZE' AS factor_symbol, 'size' AS factor_name), + STRUCT('USMV' AS factor_symbol, 'minimum_volatility' AS factor_name) + ]) +), + +comparison_metadata AS ( + SELECT * + FROM UNNEST([ + STRUCT('XLK' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Technology' AS comparison_name), + STRUCT('XLC' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Communication Services' AS comparison_name), + STRUCT('XLY' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Consumer Discretionary' AS comparison_name), + STRUCT('XLF' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Financials' AS comparison_name), + STRUCT('XLI' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Industrials' AS comparison_name), + STRUCT('XLU' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Utilities' AS comparison_name), + STRUCT('XLP' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Consumer Staples' AS comparison_name), + STRUCT('XLRE' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Real Estate' AS comparison_name), + STRUCT('XLB' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Materials' AS comparison_name), + STRUCT('XLE' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Energy' AS comparison_name), + STRUCT('XLV' AS comparison_symbol, 'sector_etf' AS comparison_universe, 'Health Care' AS comparison_name), + STRUCT('SPY' AS comparison_symbol, 'broad_market_etf' AS comparison_universe, 'S&P 500' AS comparison_name), + STRUCT('QQQ' AS comparison_symbol, 'broad_market_etf' AS comparison_universe, 'Nasdaq 100' AS comparison_name), + STRUCT('DIA' AS comparison_symbol, 'broad_market_etf' AS comparison_universe, 'Dow Jones Industrial Average' AS comparison_name), + STRUCT('RSP' AS comparison_symbol, 'broad_market_etf' AS comparison_universe, 'S&P 500 Equal Weight' AS comparison_name), + STRUCT('IWM' AS comparison_symbol, 'style_etf' AS comparison_universe, 'Russell 2000' AS comparison_name), + STRUCT('IWD' AS comparison_symbol, 'style_etf' AS comparison_universe, 'Russell 1000 Value' AS comparison_name), + STRUCT('IWF' AS comparison_symbol, 'style_etf' AS comparison_universe, 'Russell 1000 Growth' AS comparison_name), + STRUCT('IYT' AS comparison_symbol, 'thematic_etf' AS comparison_universe, 'Transportation' AS comparison_name), + STRUCT('SOXX' AS comparison_symbol, 'thematic_etf' AS comparison_universe, 'Semiconductors' AS comparison_name) + ]) +), + +factor_prices AS ( + SELECT + symbol AS factor_symbol, + exchange, + date, + adj_close, + SAFE_DIVIDE( + adj_close - LAG(adj_close) OVER ( + PARTITION BY symbol, exchange + ORDER BY date + ), + LAG(adj_close) OVER ( + PARTITION BY symbol, exchange + ORDER BY date + ) + ) AS factor_daily_return + FROM {{ ref('stg_factor_etfs') }} + WHERE adj_close IS NOT NULL +), + +sector_prices AS ( + SELECT + symbol AS comparison_symbol, + exchange, + date, + adj_close, + SAFE_DIVIDE( + adj_close - LAG(adj_close) OVER ( + PARTITION BY symbol, exchange + ORDER BY date + ), + LAG(adj_close) OVER ( + PARTITION BY symbol, exchange + ORDER BY date + ) + ) AS comparison_daily_return + FROM {{ ref('stg_us_sectors') }} + WHERE adj_close IS NOT NULL +), + +major_index_prices AS ( + SELECT + major_indices.symbol AS comparison_symbol, + major_indices.exchange, + major_indices.date, + major_indices.adj_close, + SAFE_DIVIDE( + major_indices.adj_close - LAG(major_indices.adj_close) OVER ( + PARTITION BY major_indices.symbol, major_indices.exchange + ORDER BY major_indices.date + ), + LAG(major_indices.adj_close) OVER ( + PARTITION BY major_indices.symbol, major_indices.exchange + ORDER BY major_indices.date + ) + ) AS comparison_daily_return + FROM {{ ref('stg_major_indices') }} AS major_indices + INNER JOIN comparison_metadata + ON major_indices.symbol = comparison_metadata.comparison_symbol + WHERE major_indices.adj_close IS NOT NULL + AND comparison_metadata.comparison_universe != 'sector_etf' +), + +comparison_prices AS ( + SELECT + comparison_symbol, + exchange, + date, + adj_close, + comparison_daily_return + FROM sector_prices + UNION ALL + SELECT + comparison_symbol, + exchange, + date, + adj_close, + comparison_daily_return + FROM major_index_prices +), + +latest_common_date AS ( + SELECT MAX(factor_prices.date) AS as_of_date + FROM factor_prices + INNER JOIN comparison_prices + ON factor_prices.date = comparison_prices.date +), + +joined_returns AS ( + SELECT + factor_prices.factor_symbol, + comparison_prices.comparison_symbol, + factor_prices.date, + factor_prices.factor_daily_return, + comparison_prices.comparison_daily_return + FROM factor_prices + INNER JOIN comparison_prices + ON factor_prices.date = comparison_prices.date + CROSS JOIN latest_common_date AS latest + WHERE factor_prices.factor_daily_return IS NOT NULL + AND comparison_prices.comparison_daily_return IS NOT NULL + AND factor_prices.date BETWEEN DATE_SUB(latest.as_of_date, INTERVAL 365 DAY) + AND latest.as_of_date +), + +rolling_correlations AS ( + SELECT + latest.as_of_date, + joined_returns.factor_symbol, + joined_returns.comparison_symbol, + COUNTIF( + joined_returns.date >= DATE_SUB(latest.as_of_date, INTERVAL 90 DAY) + ) AS observations_3mo, + ROUND(CORR( + CASE + WHEN joined_returns.date >= DATE_SUB(latest.as_of_date, INTERVAL 90 DAY) + THEN joined_returns.factor_daily_return + END, + CASE + WHEN joined_returns.date >= DATE_SUB(latest.as_of_date, INTERVAL 90 DAY) + THEN joined_returns.comparison_daily_return + END + ), 4) AS corr_3mo, + COUNT(*) AS observations_1yr, + ROUND(CORR(joined_returns.factor_daily_return, joined_returns.comparison_daily_return), 4) AS corr_1yr + FROM joined_returns + CROSS JOIN latest_common_date AS latest + GROUP BY latest.as_of_date, joined_returns.factor_symbol, joined_returns.comparison_symbol +), + +latest_factor_performance AS ( + SELECT + symbol AS factor_symbol, + date, + pct_change_1mo, + pct_change_3mo, + pct_change_1yr, + std_diff_1yr + FROM {{ ref('factor_analysis_return') }} + QUALIFY ROW_NUMBER() OVER ( + PARTITION BY symbol + ORDER BY date DESC + ) = 1 +), + +sector_performance AS ( + SELECT + symbol AS comparison_symbol, + date, + pct_change_1mo, + pct_change_3mo, + pct_change_1yr, + std_diff_1yr + FROM {{ ref('us_sector_analysis_return') }} +), + +major_index_performance AS ( + SELECT + major_indices.symbol AS comparison_symbol, + major_indices.date, + major_indices.pct_change_1mo, + major_indices.pct_change_3mo, + major_indices.pct_change_1yr, + major_indices.std_diff_1yr + FROM {{ ref('major_indicies_analysis_return') }} AS major_indices + INNER JOIN comparison_metadata + ON major_indices.symbol = comparison_metadata.comparison_symbol + WHERE comparison_metadata.comparison_universe != 'sector_etf' +), + +comparison_performance AS ( + SELECT + comparison_symbol, + date, + pct_change_1mo, + pct_change_3mo, + pct_change_1yr, + std_diff_1yr + FROM sector_performance + UNION ALL + SELECT + comparison_symbol, + date, + pct_change_1mo, + pct_change_3mo, + pct_change_1yr, + std_diff_1yr + FROM major_index_performance +), + +latest_comparison_performance AS ( + SELECT + comparison_symbol, + date, + pct_change_1mo, + pct_change_3mo, + pct_change_1yr, + std_diff_1yr + FROM comparison_performance + QUALIFY ROW_NUMBER() OVER ( + PARTITION BY comparison_symbol + ORDER BY date DESC + ) = 1 +) + +SELECT + CONCAT( + correlations.factor_symbol, + ':', + correlations.comparison_symbol, + ':', + CAST(correlations.as_of_date AS STRING) + ) AS factor_sector_key, + correlations.as_of_date, + correlations.factor_symbol, + factor_metadata.factor_name, + correlations.comparison_symbol, + comparison_metadata.comparison_name, + comparison_metadata.comparison_universe, + correlations.comparison_symbol AS sector_symbol, + comparison_metadata.comparison_name AS sector_name, + correlations.observations_3mo, + correlations.corr_3mo, + correlations.observations_1yr, + correlations.corr_1yr, + factor_performance.pct_change_1mo AS factor_return_1mo, + factor_performance.pct_change_3mo AS factor_return_3mo, + factor_performance.pct_change_1yr AS factor_return_1yr, + comparison_performance.pct_change_1mo AS sector_return_1mo, + comparison_performance.pct_change_3mo AS sector_return_3mo, + comparison_performance.pct_change_1yr AS sector_return_1yr, + ROUND(factor_performance.pct_change_3mo - comparison_performance.pct_change_3mo, 2) AS factor_sector_return_spread_3mo, + ROUND(factor_performance.pct_change_1yr - comparison_performance.pct_change_1yr, 2) AS factor_sector_return_spread_1yr, + factor_performance.std_diff_1yr AS factor_volatility_proxy_1yr, + comparison_performance.std_diff_1yr AS sector_volatility_proxy_1yr +FROM rolling_correlations AS correlations +LEFT JOIN factor_metadata + ON correlations.factor_symbol = factor_metadata.factor_symbol +LEFT JOIN comparison_metadata + ON correlations.comparison_symbol = comparison_metadata.comparison_symbol +LEFT JOIN latest_factor_performance AS factor_performance + ON correlations.factor_symbol = factor_performance.factor_symbol +LEFT JOIN latest_comparison_performance AS comparison_performance + ON correlations.comparison_symbol = comparison_performance.comparison_symbol diff --git a/dbt_project/models/markets/schema.yml b/dbt_project/models/markets/schema.yml index c854a90..373c3af 100644 --- a/dbt_project/models/markets/schema.yml +++ b/dbt_project/models/markets/schema.yml @@ -341,6 +341,99 @@ models: tests: - not_null + - name: factor_analysis_return + description: > + Daily OHLCV price data and rolling returns for US equity factor ETFs + covering value, quality, momentum, size, and minimum volatility. + Grain: one row per factor ETF symbol per exchange per trading day. + tests: + - unique_combination: + arguments: + combination_of_columns: ['symbol', 'exchange', 'date'] + columns: + - name: symbol + description: Factor ETF symbol. + tests: + - not_null + - name: exchange + description: Exchange where the ETF is traded. + tests: + - not_null + - name: date + description: Trading date. + tests: + - not_null + - name: current_price + description: Current adjusted close price. + - name: current_volume + description: Current day's trading volume. + - name: pct_change_1mo + description: Percentage change from 1 month ago to current price. + - name: pct_change_3mo + description: Percentage change from 3 months ago to current price. + - name: pct_change_1yr + description: Percentage change from 1 year ago to current price. + - name: std_diff_1yr + description: Standard deviation of daily price differences over the past 1 year. + + - name: factor_sector_correlation + description: > + Latest rolling correlations and relative performance spreads between + US equity factor ETFs and sector, broad market, style, and thematic ETFs. + Supports factor rotation, sector exposure, and thematic relationship analysis. + tests: + - unique_combination: + arguments: + combination_of_columns: ['factor_sector_key'] + columns: + - name: factor_sector_key + description: Stable key for factor, sector, and as-of date. + tests: + - not_null + - unique + - name: as_of_date + description: Latest common trading date used for the correlation window. + tests: + - not_null + - name: factor_symbol + description: Factor ETF ticker symbol. + tests: + - not_null + - name: factor_name + description: Factor exposure represented by the ETF. + tests: + - not_null + - accepted_values: + arguments: + values: ['value', 'quality', 'momentum', 'size', 'minimum_volatility'] + - name: comparison_symbol + description: Compared ETF ticker symbol. + tests: + - not_null + - name: comparison_name + description: Human-readable compared ETF name. + - name: comparison_universe + description: Compared ETF universe. + tests: + - not_null + - accepted_values: + arguments: + values: ['sector_etf', 'broad_market_etf', 'style_etf', 'thematic_etf'] + - name: sector_symbol + description: Backward-compatible compared ETF ticker symbol. + tests: + - not_null + - name: sector_name + description: Backward-compatible compared ETF name. + - name: corr_3mo + description: Rolling 3-month daily-return correlation between the factor ETF and compared ETF. + - name: corr_1yr + description: Rolling 1-year daily-return correlation between the factor ETF and compared ETF. + - name: factor_sector_return_spread_3mo + description: Factor ETF 3-month return minus compared ETF 3-month return. + - name: factor_sector_return_spread_1yr + description: Factor ETF 1-year return minus compared ETF 1-year return. + - name: sp500_companies_analysis_return description: > Daily OHLCV price data and rolling returns for S&P 500 companies. diff --git a/dbt_project/models/markets/technical/schema.yml b/dbt_project/models/markets/technical/schema.yml index 2f32494..81190eb 100644 --- a/dbt_project/models/markets/technical/schema.yml +++ b/dbt_project/models/markets/technical/schema.yml @@ -26,6 +26,7 @@ models: - fixed_income_etf - currency_etf - commodity_etf + - factor_etf - global_market - name: symbol tests: diff --git a/dbt_project/models/markets/technical/technical_price_universe.sql b/dbt_project/models/markets/technical/technical_price_universe.sql index 113a5fb..f45d992 100644 --- a/dbt_project/models/markets/technical/technical_price_universe.sql +++ b/dbt_project/models/markets/technical/technical_price_universe.sql @@ -24,6 +24,7 @@ {'model': 'stg_fixed_income', 'universe': 'fixed_income_etf'}, {'model': 'stg_currency', 'universe': 'currency_etf'}, {'model': 'stg_commodity_etfs', 'universe': 'commodity_etf'}, + {'model': 'stg_factor_etfs', 'universe': 'factor_etf'}, {'model': 'stg_global_markets', 'universe': 'global_market'}, ] %} diff --git a/dbt_project/models/semantic_layer/asset_daily_returns.sql b/dbt_project/models/semantic_layer/asset_daily_returns.sql index c1c3d17..6b60cf5 100644 --- a/dbt_project/models/semantic_layer/asset_daily_returns.sql +++ b/dbt_project/models/semantic_layer/asset_daily_returns.sql @@ -7,6 +7,7 @@ WITH stocks AS ( symbol, symbol AS stock_symbol, CAST(NULL AS STRING) AS sector_etf_symbol, + CAST(NULL AS STRING) AS factor_etf_symbol, CAST(NULL AS STRING) AS commodity_name, CAST(NULL AS STRING) AS commodity_unit, exchange, @@ -26,6 +27,7 @@ sector_etfs AS ( symbol, CAST(NULL AS STRING) AS stock_symbol, symbol AS sector_etf_symbol, + CAST(NULL AS STRING) AS factor_etf_symbol, CAST(NULL AS STRING) AS commodity_name, CAST(NULL AS STRING) AS commodity_unit, exchange, @@ -36,6 +38,26 @@ sector_etfs AS ( FROM {{ ref('us_sector_analysis_return') }} ), +factor_etfs AS ( + SELECT + CONCAT('factor_etf:', exchange, ':', symbol) AS asset_key, + 'factor_etf' AS asset_class, + symbol AS asset_id, + symbol AS asset_name, + symbol, + CAST(NULL AS STRING) AS stock_symbol, + CAST(NULL AS STRING) AS sector_etf_symbol, + symbol AS factor_etf_symbol, + CAST(NULL AS STRING) AS commodity_name, + CAST(NULL AS STRING) AS commodity_unit, + exchange, + date AS trade_date, + current_price, + std_diff_1yr, + pct_change_1yr + FROM {{ ref('factor_analysis_return') }} +), + commodities AS ( SELECT CONCAT('commodity:', commodity_name, ':', commodity_unit) AS asset_key, @@ -45,6 +67,7 @@ commodities AS ( CAST(NULL AS STRING) AS symbol, CAST(NULL AS STRING) AS stock_symbol, CAST(NULL AS STRING) AS sector_etf_symbol, + CAST(NULL AS STRING) AS factor_etf_symbol, commodity_name, commodity_unit, CAST(NULL AS STRING) AS exchange, @@ -64,6 +87,7 @@ unioned_assets AS ( symbol, stock_symbol, sector_etf_symbol, + factor_etf_symbol, commodity_name, commodity_unit, exchange, @@ -83,6 +107,7 @@ unioned_assets AS ( symbol, stock_symbol, sector_etf_symbol, + factor_etf_symbol, commodity_name, commodity_unit, exchange, @@ -102,6 +127,27 @@ unioned_assets AS ( symbol, stock_symbol, sector_etf_symbol, + factor_etf_symbol, + commodity_name, + commodity_unit, + exchange, + trade_date, + current_price, + std_diff_1yr, + pct_change_1yr + FROM factor_etfs + + UNION ALL + + SELECT + asset_key, + asset_class, + asset_id, + asset_name, + symbol, + stock_symbol, + sector_etf_symbol, + factor_etf_symbol, commodity_name, commodity_unit, exchange, @@ -120,6 +166,7 @@ SELECT symbol, stock_symbol, sector_etf_symbol, + factor_etf_symbol, commodity_name, commodity_unit, exchange, @@ -130,5 +177,5 @@ SELECT FROM unioned_assets QUALIFY ROW_NUMBER() OVER ( PARTITION BY asset_key, trade_date - ORDER BY current_price DESC + ORDER BY current_price DESC NULLS LAST ) = 1 diff --git a/dbt_project/models/semantic_layer/schema.yml b/dbt_project/models/semantic_layer/schema.yml index 0fcf7cc..5a4c0b3 100644 --- a/dbt_project/models/semantic_layer/schema.yml +++ b/dbt_project/models/semantic_layer/schema.yml @@ -15,7 +15,7 @@ models: - name: asset_daily_returns description: > - Normalized daily return fact table across stocks, sector ETFs, and input + Normalized daily return fact table across stocks, sector ETFs, factor ETFs, and input commodities. Grain: one row per asset per trading day. tests: - unique_combination: @@ -39,7 +39,7 @@ models: - not_null - accepted_values: arguments: - values: ['stock', 'sector_etf', 'commodity'] + values: ['stock', 'sector_etf', 'factor_etf', 'commodity'] - name: asset_id description: Source identifier for the asset within its asset class. dimension: @@ -64,6 +64,10 @@ models: description: Sector ETF ticker symbol for sector ETF rows. dimension: type: categorical + - name: factor_etf_symbol + description: Factor ETF ticker symbol for factor ETF rows. + dimension: + type: categorical - name: commodity_name description: Commodity name for commodity rows. dimension: @@ -156,7 +160,7 @@ models: semantic_models: - name: asset_daily_returns description: > - Normalized daily return fact table across stocks, sector ETFs, and input + Normalized daily return fact table across stocks, sector ETFs, factor ETFs, and input commodities. Grain: one row per asset per trading day. model: ref('asset_daily_returns') defaults: @@ -178,6 +182,8 @@ semantic_models: type: categorical - name: sector_etf_symbol type: categorical + - name: factor_etf_symbol + type: categorical - name: commodity_name type: categorical - name: commodity_unit @@ -693,6 +699,62 @@ semantic_models: agg: average expr: mortgage_3m_change + - name: factor_sector_relationships + description: > + Latest rolling correlation and relative performance between US equity + factor ETFs and sector, broad market, style, and thematic ETFs. + model: ref('factor_sector_correlation') + defaults: + agg_time_dimension: as_of_date + entities: + - name: factor_sector_pair + type: primary + expr: factor_sector_key + dimensions: + - name: as_of_date + type: time + type_params: + time_granularity: day + - name: factor_symbol + type: categorical + - name: factor_name + type: categorical + - name: comparison_symbol + type: categorical + - name: comparison_name + type: categorical + - name: comparison_universe + type: categorical + - name: sector_symbol + type: categorical + - name: sector_name + type: categorical + measures: + - name: factor_sector_corr_3mo_measure + description: Average rolling 3-month daily-return correlation between selected factors and comparison ETFs. + agg: average + expr: corr_3mo + - name: factor_sector_corr_1yr_measure + description: Average rolling 1-year daily-return correlation between selected factors and comparison ETFs. + agg: average + expr: corr_1yr + - name: factor_return_3mo_measure + description: Average selected factor ETF 3-month return. + agg: average + expr: factor_return_3mo + - name: factor_return_1yr_measure + description: Average selected factor ETF 1-year return. + agg: average + expr: factor_return_1yr + - name: factor_sector_return_spread_3mo_measure + description: Average factor-minus-comparison 3-month return spread. + agg: average + expr: factor_sector_return_spread_3mo + - name: factor_sector_return_spread_1yr_measure + description: Average factor-minus-comparison 1-year return spread. + agg: average + expr: factor_sector_return_spread_1yr + metrics: - name: asset_volatility_proxy label: Asset Price Volatility (1-Year StdDev) @@ -1110,3 +1172,45 @@ metrics: type_params: measure: name: mortgage_3m_change_measure + - name: factor_sector_corr_3mo + label: Factor-Sector Correlation 3M + description: Average rolling 3-month daily-return correlation between selected factors and comparison ETFs. + type: simple + type_params: + measure: + name: factor_sector_corr_3mo_measure + - name: factor_sector_corr_1yr + label: Factor-Sector Correlation 1Y + description: Average rolling 1-year daily-return correlation between selected factors and comparison ETFs. + type: simple + type_params: + measure: + name: factor_sector_corr_1yr_measure + - name: factor_return_3mo + label: Factor Return 3M + description: Average selected factor ETF 3-month trailing return. + type: simple + type_params: + measure: + name: factor_return_3mo_measure + - name: factor_return_1yr + label: Factor Return 1Y + description: Average selected factor ETF 1-year trailing return. + type: simple + type_params: + measure: + name: factor_return_1yr_measure + - name: factor_sector_return_spread_3mo + label: Factor-Sector Return Spread 3M + description: Average factor-minus-comparison 3-month return spread. + type: simple + type_params: + measure: + name: factor_sector_return_spread_3mo_measure + - name: factor_sector_return_spread_1yr + label: Factor-Sector Return Spread 1Y + description: Average factor-minus-comparison 1-year return spread. + type: simple + type_params: + measure: + name: factor_sector_return_spread_1yr_measure diff --git a/dbt_project/models/staging/schema.yml b/dbt_project/models/staging/schema.yml index 9e98b78..51e435b 100644 --- a/dbt_project/models/staging/schema.yml +++ b/dbt_project/models/staging/schema.yml @@ -97,6 +97,26 @@ models: tests: - not_null + - name: stg_factor_etfs + description: > + Raw data from MarketStack API for US equity factor ETFs covering value, + quality, momentum, size, and minimum volatility exposures. + tests: + - ohlc_consistency: + config: + severity: warn + - usd_currency_only: + column_name: price_currency + config: + severity: warn + columns: + - name: date + tests: + - not_null + - name: symbol + tests: + - not_null + - name: stg_major_indices description: > raw data from MarketStack API for Major Indices diff --git a/dbt_project/models/staging/stg_factor_etfs.sql b/dbt_project/models/staging/stg_factor_etfs.sql new file mode 100644 index 0000000..2343837 --- /dev/null +++ b/dbt_project/models/staging/stg_factor_etfs.sql @@ -0,0 +1,22 @@ +SELECT + open, + high, + low, + close, + volume, + adj_high, + adj_low, + adj_close, + adj_open, + adj_volume, + split_factor, + dividend, + name, + exchange_code, + asset_type, + price_currency, + symbol, + exchange, + SAFE_CAST(SUBSTR(CAST(date AS STRING), 1, 10) AS DATE) AS date +FROM {{ ref('stg_major_indices') }} +WHERE symbol IN ('VLUE', 'MTUM', 'QUAL', 'USMV', 'SIZE') diff --git a/macro_agents/src/macro_agents/defs/constants/market_stack_constants.py b/macro_agents/src/macro_agents/defs/constants/market_stack_constants.py index e2becb3..65aebb4 100644 --- a/macro_agents/src/macro_agents/defs/constants/market_stack_constants.py +++ b/macro_agents/src/macro_agents/defs/constants/market_stack_constants.py @@ -1,3 +1,13 @@ +# US equity factor ETFs. iShares frames factor investing around value, +# quality, momentum, size, and minimum volatility. +FACTOR_ETFS = [ + "VLUE", # iShares Edge MSCI USA Value Factor + "MTUM", # iShares Edge MSCI USA Momentum Factor + "QUAL", # iShares Edge MSCI USA Quality Factor + "USMV", # iShares Edge MSCI USA Min Vol Factor + "SIZE", # iShares Edge MSCI USA Size Factor +] + # Major US market indices and broad market ETFs # Note: VIX removed - MarketStack returns 406 for VIX.INDX; use FRED VIXCLS instead MAJOR_INDICES_TICKERS = [ @@ -10,11 +20,7 @@ "SOXX", "IWD", # iShares Russell 1000 Value "IWF", # iShares Russell 1000 Growth - "VLUE", # iShares Edge MSCI USA Value Factor - "MTUM", # iShares Edge MSCI USA Momentum Factor - "QUAL", # iShares Edge MSCI USA Quality Factor - "USMV", # iShares Edge MSCI USA Min Vol Factor - "SIZE", # iShares Edge MSCI USA Min Vol Factor + *FACTOR_ETFS, ] # US sector ETFs