feat: instrument analysis
This commit is contained in:
@@ -544,10 +544,11 @@ def _get_relevant_events(
|
|||||||
(SELECT GROUP_CONCAT(DISTINCT a.instrument)
|
(SELECT GROUP_CONCAT(DISTINCT a.instrument)
|
||||||
FROM causal_event_analyses a
|
FROM causal_event_analyses a
|
||||||
WHERE a.market_event_id = e.id) AS analyzed_instruments,
|
WHERE a.market_event_id = e.id) AS analyzed_instruments,
|
||||||
(SELECT a.template_id FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_template_id,
|
(SELECT a.template_id FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_template_id,
|
||||||
(SELECT a.id FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS analysis_id,
|
(SELECT a.id FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS analysis_id,
|
||||||
(SELECT a.prediction_json FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_prediction_json,
|
(SELECT a.prediction_json FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_prediction_json,
|
||||||
(SELECT a.actual_json FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_actual_json
|
(SELECT a.actual_json FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_actual_json,
|
||||||
|
(SELECT a.activation_score FROM causal_event_analyses a WHERE a.market_event_id = e.id ORDER BY a.id DESC LIMIT 1) AS cea_activation_score
|
||||||
FROM market_events e
|
FROM market_events e
|
||||||
ORDER BY e.start_date DESC
|
ORDER BY e.start_date DESC
|
||||||
""").fetchall()
|
""").fetchall()
|
||||||
@@ -556,8 +557,9 @@ def _get_relevant_events(
|
|||||||
# any collision with an e.* column named template_id
|
# any collision with an e.* column named template_id
|
||||||
all_events = [
|
all_events = [
|
||||||
{**dict(r), "template_id": r["cea_template_id"],
|
{**dict(r), "template_id": r["cea_template_id"],
|
||||||
"prediction_json": r["cea_prediction_json"],
|
"prediction_json": r["cea_prediction_json"],
|
||||||
"actual_json": r["cea_actual_json"]}
|
"actual_json": r["cea_actual_json"],
|
||||||
|
"activation_score": r["cea_activation_score"]}
|
||||||
for r in rows
|
for r in rows
|
||||||
]
|
]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -626,6 +628,7 @@ def _get_relevant_events(
|
|||||||
"absorption_pct": ev.get("absorption_pct"),
|
"absorption_pct": ev.get("absorption_pct"),
|
||||||
"prediction_json": ev.get("prediction_json") or None,
|
"prediction_json": ev.get("prediction_json") or None,
|
||||||
"actual_json": ev.get("actual_json") or None,
|
"actual_json": ev.get("actual_json") or None,
|
||||||
|
"activation_score": ev.get("activation_score"),
|
||||||
})
|
})
|
||||||
|
|
||||||
# Sort by start_date asc for timeline display, cap at 30
|
# Sort by start_date asc for timeline display, cap at 30
|
||||||
|
|||||||
@@ -42,8 +42,9 @@ interface SnapshotEvent {
|
|||||||
category: string; sub_type?: string; description: string; impact_score: number
|
category: string; sub_type?: string; description: string; impact_score: number
|
||||||
expected_value?: string | null; actual_value?: string | null
|
expected_value?: string | null; actual_value?: string | null
|
||||||
surprise_pct?: number | null; unit?: string | null; absorption_pct?: number | null
|
surprise_pct?: number | null; unit?: string | null; absorption_pct?: number | null
|
||||||
prediction_json?: string | null // JSON: {node_id: pips} from causal_event_analyses
|
prediction_json?: string | null // JSON: {node_id: pips} from causal_event_analyses
|
||||||
actual_json?: string | null // JSON: {instrument: pips} from causal_event_analyses
|
actual_json?: string | null // JSON: {instrument: pips} from causal_event_analyses
|
||||||
|
activation_score?: number | null // stored directional accuracy from causal_event_analyses
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RegimeSignals {
|
interface RegimeSignals {
|
||||||
@@ -704,6 +705,9 @@ function templateAbsorptionDays(tmpl: CausalTemplate): number {
|
|||||||
|
|
||||||
/** Score 0-100 measuring how well the graph predicted actual pips for an instrument. */
|
/** Score 0-100 measuring how well the graph predicted actual pips for an instrument. */
|
||||||
function comprehensionScore(ev: SnapshotEvent, tmpl: CausalTemplate, instrument: string): number | null {
|
function comprehensionScore(ev: SnapshotEvent, tmpl: CausalTemplate, instrument: string): number | null {
|
||||||
|
// Prefer the stored activation_score from causal_event_analyses (consistent with MarketEvents panel)
|
||||||
|
if (ev.activation_score != null) return Math.round(ev.activation_score * 100)
|
||||||
|
|
||||||
if (!ev.prediction_json || !ev.actual_json) return null
|
if (!ev.prediction_json || !ev.actual_json) return null
|
||||||
try {
|
try {
|
||||||
const preds: Record<string, number> = JSON.parse(ev.prediction_json)
|
const preds: Record<string, number> = JSON.parse(ev.prediction_json)
|
||||||
@@ -711,7 +715,6 @@ function comprehensionScore(ev: SnapshotEvent, tmpl: CausalTemplate, instrument:
|
|||||||
const actual = actuals[instrument] ?? actuals[instrument.toUpperCase()] ?? actuals[instrument.toLowerCase()]
|
const actual = actuals[instrument] ?? actuals[instrument.toUpperCase()] ?? actuals[instrument.toLowerCase()]
|
||||||
if (actual == null) return null
|
if (actual == null) return null
|
||||||
|
|
||||||
// Find the output node for this instrument (built-in templates use "output", auto-generated use "market_asset")
|
|
||||||
const outputNode = tmpl.graph_json.nodes.find(n =>
|
const outputNode = tmpl.graph_json.nodes.find(n =>
|
||||||
(n.type === 'market_asset' || n.type === 'output') && n.instrument?.toUpperCase() === instrument.toUpperCase()
|
(n.type === 'market_asset' || n.type === 'output') && n.instrument?.toUpperCase() === instrument.toUpperCase()
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user