snapkitty
developer-tools
python
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)).