File size: 4,772 Bytes
8f5564f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | % βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
% MARKETSCOPE β Correlation Breakdown Detection (Deterministic)
%
% Detects when historically correlated assets diverge.
% Outputs scenario bands, not predictions.
%
% Training_Gate: Human_Review_Required
% Audit_Spec: 4b565498-9afc-4782-af4a-c6b11a5d0058
% βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
:- module(correlation, [
correlation_breakdown/3,
check_all_pairs/2,
pair_status/3
]).
:- use_module(library(http/json)).
% ββ Correlation Breakdown Detection βββββββββββββββββββββββββββββββββββββββββββ
%% correlation_breakdown(+AssetA, +AssetB, -Window)
% Detects when rolling correlation drops below threshold.
% Window is the lookback period in days.
correlation_breakdown(AssetA, AssetB, Window) :-
rolling_corr(AssetA, AssetB, Window, Corr),
historical_avg_corr(AssetA, AssetB, Avg),
Corr < 0.3,
Avg > 0.7.
%% correlation_breakdown(+AssetA, +AssetB, -Window, -Details)
% Extended version with detailed breakdown information.
correlation_breakdown(AssetA, AssetB, Window, Details) :-
rolling_corr(AssetA, AssetB, Window, CurrentCorr),
historical_avg_corr(AssetA, AssetB, HistoricalAvg),
deviation(Deviation, CurrentCorr, HistoricalAvg),
( CurrentCorr < 0.3,
HistoricalAvg > 0.7
-> Details = _{
asset_a: AssetA,
asset_b: AssetB,
window_days: Window,
current_corr: CurrentCorr,
historical_avg: HistoricalAvg,
deviation: Deviation,
alert: true,
message: 'CORRELATION BREAKDOWN DETECTED'
}
; Details = _{
asset_a: AssetA,
asset_b: AssetB,
window_days: Window,
current_corr: CurrentCorr,
historical_avg: HistoricalAvg,
deviation: Deviation,
alert: false,
message: 'Correlation within normal range'
}
).
% ββ Multi-Pair Analysis ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
%% check_all_pairs(+Pairs, -Alerts)
% Checks all asset pairs for correlation breakdowns.
check_all_pairs(Pairs, Alerts) :-
maplist(check_pair, Pairs, Results),
include(has_alert, Results, Alerts).
%% check_pair(+Pair, -Result)
% Checks a single pair.
check_pair(AssetA-AssetB, Result) :-
( correlation_breakdown(AssetA, AssetB, 20, Details)
-> Result = Details
; Result = _{
asset_a: AssetA,
asset_b: AssetB,
alert: false,
message: 'No breakdown detected'
}
).
%% pair_status(+AssetA, +AssetB, -Status)
% Returns current correlation status.
pair_status(AssetA, AssetB, Status) :-
rolling_corr(AssetA, AssetB, 20, Current),
historical_avg_corr(AssetA, AssetB, Historical),
( Current < 0.3, Historical > 0.7
-> Status = breakdown
; Current < 0.5
-> Status = weakening
; Status = normal
).
% ββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
%% deviation(-Deviation, +Current, +Historical)
% Computes absolute deviation.
deviation(D, Current, Historical) :-
D is abs(Current - Historical).
%% has_alert(+Details)
% Checks if a result contains an alert.
has_alert(Details) :-
get_dict(alert, Details, true).
% ββ Data Sources (Stubs β replaced at runtime) βββββββββββββββββββββββββββββββ
:- dynamic rolling_corr/4, historical_avg_corr/3.
%% set_rolling_corr(+AssetA, +AssetB, +Window, +Corr)
set_rolling_corr(AssetA, AssetB, Window, Corr) :-
retractall(rolling_corr(AssetA, AssetB, Window, _)),
assert(rolling_corr(AssetA, AssetB, Window, Corr)).
%% set_historical_avg(+AssetA, +AssetB, +Avg)
set_historical_avg(AssetA, AssetB, Avg) :-
retractall(historical_avg_corr(AssetA, AssetB, _)),
assert(historical_avg_corr(AssetA, AssetB, Avg)).
|