Skip to content

Commit bb5ca0a

Browse files
Merge pull request #33 from C00ldudeNoonan/this-and-that
This and that
2 parents c29eee7 + 6d9608c commit bb5ca0a

30 files changed

Lines changed: 2517 additions & 230 deletions

dbt_project/models/analysis/base_historical_analysis.sql

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ WITH return_data as (
9494
'sector' as category
9595
FROM {{ ref('us_sector_analysis_return') }}
9696

97+
),
98+
99+
quarterly_returns AS (
100+
SELECT
101+
*,
102+
-- Get first month's close price in the quarter (earliest date)
103+
FIRST_VALUE(monthly_avg_close) OVER (
104+
PARTITION BY symbol, category, year_val, quarter_num
105+
ORDER BY month_date ASC
106+
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
107+
) AS quarter_first_month_close,
108+
-- Get last month's close price in the quarter (latest date)
109+
LAST_VALUE(monthly_avg_close) OVER (
110+
PARTITION BY symbol, category, year_val, quarter_num
111+
ORDER BY month_date ASC
112+
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
113+
) AS quarter_last_month_close
114+
FROM return_data
97115
)
98116

99117
SELECT
@@ -110,9 +128,22 @@ SELECT
110128
rt.pct_change_q3_forward,
111129
rt.pct_change_q4_forward,
112130
rt.category,
131+
-- Calculate quarterly total return: (last month - first month) / first month * 100
132+
CASE
133+
WHEN rt.quarter_first_month_close IS NOT NULL
134+
AND rt.quarter_first_month_close > 0
135+
AND rt.quarter_last_month_close IS NOT NULL
136+
THEN ROUND(
137+
(rt.quarter_last_month_close - rt.quarter_first_month_close) / rt.quarter_first_month_close * 100,
138+
2
139+
)
140+
ELSE NULL
141+
END AS quarterly_total_return_pct,
142+
rt.quarter_first_month_close,
143+
rt.quarter_last_month_close,
113144
fr.series_name,
114145
fr.value,
115146
fr.period_diff
116-
FROM return_data rt
147+
FROM quarterly_returns rt
117148
LEFT JOIN {{ ref('fred_monthly_diff') }} fr
118149
on rt.month_date = cast(fr.date as date)

dbt_project/models/analysis/leading_econ_return_indicator.sql

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ WITH economic_changes AS (
1515
fsm.category AS economic_category,
1616
bha.value AS current_econ_value,
1717
bha.monthly_avg_close,
18+
bha.quarterly_total_return_pct,
1819
bha.pct_change_q1_forward,
1920
bha.pct_change_q2_forward,
2021
bha.pct_change_q3_forward,
@@ -88,12 +89,22 @@ correlation_analysis AS (
8889
AS corr_econ_q2_returns,
8990
CORR(econ_mom_change_pct, pct_change_q3_forward)
9091
AS corr_econ_q3_returns,
92+
93+
-- Correlation between economic MoM change and quarterly total returns
94+
CORR(econ_mom_change_pct, quarterly_total_return_pct)
95+
AS corr_econ_quarterly_total_return,
9196

9297
-- Average returns when economic data is growing vs declining
9398
AVG(CASE WHEN econ_mom_change_pct > 0 THEN pct_change_q1_forward END)
9499
AS avg_q1_return_when_econ_growing,
95100
AVG(CASE WHEN econ_mom_change_pct < 0 THEN pct_change_q1_forward END)
96101
AS avg_q1_return_when_econ_declining,
102+
103+
-- Average quarterly total returns when economic data is growing vs declining
104+
AVG(CASE WHEN econ_mom_change_pct > 0 THEN quarterly_total_return_pct END)
105+
AS avg_quarterly_total_return_when_econ_growing,
106+
AVG(CASE WHEN econ_mom_change_pct < 0 THEN quarterly_total_return_pct END)
107+
AS avg_quarterly_total_return_when_econ_declining,
97108

98109
-- Standard deviations
99110
STDDEV(econ_mom_change_pct) AS econ_change_volatility,
@@ -117,6 +128,7 @@ detailed_monthly_view AS (
117128
category,
118129
economic_category,
119130
econ_mom_change_pct,
131+
quarterly_total_return_pct,
120132
pct_change_q1_forward,
121133
pct_change_q2_forward,
122134
pct_change_q3_forward,
@@ -149,9 +161,15 @@ SELECT
149161
ROUND(corr_econ_q1_returns, 4) AS correlation_econ_vs_q1_returns,
150162
ROUND(corr_econ_q2_returns, 4) AS correlation_econ_vs_q2_returns,
151163
ROUND(corr_econ_q3_returns, 4) AS correlation_econ_vs_q3_returns,
164+
ROUND(corr_econ_quarterly_total_return, 4) AS correlation_econ_vs_quarterly_total_return,
152165
ROUND(avg_q1_return_when_econ_growing, 2) AS avg_q1_return_econ_up,
153166
ROUND(avg_q1_return_when_econ_declining, 2) AS avg_q1_return_econ_down,
154-
ROUND(avg_q1_return_when_econ_declining, 2) AS return_difference
167+
ROUND(avg_quarterly_total_return_when_econ_growing, 2) AS avg_quarterly_total_return_econ_up,
168+
ROUND(avg_quarterly_total_return_when_econ_declining, 2) AS avg_quarterly_total_return_econ_down,
169+
ROUND(
170+
COALESCE(avg_q1_return_when_econ_growing, 0) - COALESCE(avg_q1_return_when_econ_declining, 0),
171+
2
172+
) AS return_difference
155173
FROM correlation_analysis
156174
WHERE observation_count >= 10 -- Filter for meaningful sample sizes
157175

@@ -168,8 +186,11 @@ SELECT
168186
econ_change_quintile AS correlation_econ_vs_q1_returns,
169187
NULL AS correlation_econ_vs_q2_returns,
170188
NULL AS correlation_econ_vs_q3_returns,
189+
NULL AS correlation_econ_vs_quarterly_total_return,
171190
ROUND(AVG(pct_change_q1_forward), 2) AS avg_q1_return_econ_up,
172191
COUNT(*) AS avg_q1_return_econ_down,
192+
ROUND(AVG(quarterly_total_return_pct), 2) AS avg_quarterly_total_return_econ_up,
193+
NULL AS avg_quarterly_total_return_econ_down,
173194
ROUND(AVG(econ_mom_change_pct), 2) AS return_difference
174195
FROM detailed_monthly_view
175196
GROUP BY symbol, series_name, category, economic_category, econ_change_quintile

dbt_project/models/backtesting/leading_econ_return_indicator_snapshot.sql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,34 @@ economic_changes AS (
3434
pct_change_q2_forward,
3535
pct_change_q3_forward,
3636
LAG(value, 1) OVER (
37-
PARTITION BY snapshot_date, symbol, series_name
37+
PARTITION BY snapshot_date, symbol, bha.series_name
3838
ORDER BY month_date
3939
) AS prev_econ_value,
4040
CASE
4141
WHEN LAG(value, 1) OVER (
42-
PARTITION BY snapshot_date, symbol, series_name
42+
PARTITION BY snapshot_date, symbol, bha.series_name
4343
ORDER BY month_date
4444
) IS NOT NULL
4545
AND LAG(value, 1) OVER (
46-
PARTITION BY snapshot_date, symbol, series_name
46+
PARTITION BY snapshot_date, symbol, bha.series_name
4747
ORDER BY month_date
4848
) != 0
4949
THEN (
5050
(
5151
value
5252
- LAG(value, 1) OVER (
53-
PARTITION BY snapshot_date, symbol, series_name
53+
PARTITION BY snapshot_date, symbol, bha.series_name
5454
ORDER BY month_date
5555
)
5656
)
5757
/ LAG(value, 1) OVER (
58-
PARTITION BY snapshot_date, symbol, series_name
58+
PARTITION BY snapshot_date, symbol, bha.series_name
5959
ORDER BY month_date
6060
)
6161
) * 100
6262
END AS econ_mom_change_pct,
6363
AVG(value) OVER (
64-
PARTITION BY snapshot_date, symbol, series_name
64+
PARTITION BY snapshot_date, symbol, bha.series_name
6565
ORDER BY month_date
6666
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
6767
) AS econ_3mo_avg

dbt_project/models/markets/currency_analysis_return.sql

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ quarterly_data AS (
4141
year_val,
4242
year_month,
4343
month_date,
44+
month_val, -- Keep month_val for filtering
4445

4546
-- Average the monthly averages within each quarter
4647
avg_close,
@@ -123,31 +124,61 @@ quarterly_data AS (
123124
FROM monthly_averages
124125
),
125126

126-
with_forward_quarters AS (
127+
-- Get one row per quarter (last month of each quarter) for forward price calculations
128+
quarterly_lookup AS (
129+
SELECT DISTINCT
130+
symbol,
131+
exchange,
132+
year_val,
133+
quarter_num,
134+
year_quarter,
135+
quarterly_avg_close
136+
FROM quarterly_data
137+
WHERE month_val IN (3, 6, 9, 12) -- Last month of each quarter
138+
),
139+
140+
-- Calculate forward quarterly prices using quarterly data only
141+
quarterly_forward_prices AS (
127142
SELECT
128-
*,
129-
-- Forward-looking quarterly close prices for percent change calculations
143+
symbol,
144+
exchange,
145+
year_val,
146+
quarter_num,
147+
year_quarter,
148+
quarterly_avg_close,
130149
LEAD(quarterly_avg_close, 1) OVER (
131150
PARTITION BY symbol, exchange
132151
ORDER BY year_val, quarter_num
133152
) AS close_q1_forward,
134-
135153
LEAD(quarterly_avg_close, 2) OVER (
136154
PARTITION BY symbol, exchange
137155
ORDER BY year_val, quarter_num
138156
) AS close_q2_forward,
139-
140157
LEAD(quarterly_avg_close, 3) OVER (
141158
PARTITION BY symbol, exchange
142159
ORDER BY year_val, quarter_num
143160
) AS close_q3_forward,
144-
145161
LEAD(quarterly_avg_close, 4) OVER (
146162
PARTITION BY symbol, exchange
147163
ORDER BY year_val, quarter_num
148164
) AS close_q4_forward
165+
FROM quarterly_lookup
166+
),
149167

150-
FROM quarterly_data
168+
-- Join forward prices back to monthly data
169+
with_forward_quarters AS (
170+
SELECT
171+
qd.*,
172+
qfp.close_q1_forward,
173+
qfp.close_q2_forward,
174+
qfp.close_q3_forward,
175+
qfp.close_q4_forward
176+
FROM quarterly_data qd
177+
LEFT JOIN quarterly_forward_prices qfp
178+
ON qd.symbol = qfp.symbol
179+
AND qd.exchange = qfp.exchange
180+
AND qd.year_val = qfp.year_val
181+
AND qd.quarter_num = qfp.quarter_num
151182
)
152183

153184
SELECT
@@ -173,22 +204,30 @@ SELECT
173204
ROUND(quarterly_avg_low, 4) AS quarterly_avg_low,
174205
ROUND(quarterly_avg_volume, 0) AS quarterly_avg_volume,
175206

176-
-- Forward quarterly percentage changes
177-
ROUND(
178-
(close_q1_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2
179-
) AS pct_change_q1_forward,
180-
181-
ROUND(
182-
(close_q2_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2
183-
) AS pct_change_q2_forward,
184-
185-
ROUND(
186-
(close_q3_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2
187-
) AS pct_change_q3_forward,
188-
189-
ROUND(
190-
(close_q4_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2
191-
) AS pct_change_q4_forward
207+
-- Forward quarterly percentage changes (with NULL handling)
208+
CASE
209+
WHEN close_q1_forward IS NOT NULL AND quarterly_avg_close > 0
210+
THEN ROUND((close_q1_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2)
211+
ELSE NULL
212+
END AS pct_change_q1_forward,
213+
214+
CASE
215+
WHEN close_q2_forward IS NOT NULL AND quarterly_avg_close > 0
216+
THEN ROUND((close_q2_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2)
217+
ELSE NULL
218+
END AS pct_change_q2_forward,
219+
220+
CASE
221+
WHEN close_q3_forward IS NOT NULL AND quarterly_avg_close > 0
222+
THEN ROUND((close_q3_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2)
223+
ELSE NULL
224+
END AS pct_change_q3_forward,
225+
226+
CASE
227+
WHEN close_q4_forward IS NOT NULL AND quarterly_avg_close > 0
228+
THEN ROUND((close_q4_forward - quarterly_avg_close) / quarterly_avg_close * 100, 2)
229+
ELSE NULL
230+
END AS pct_change_q4_forward
192231

193232
FROM with_forward_quarters
194233
ORDER BY symbol, exchange, month_date

0 commit comments

Comments
 (0)