feat: wire normalized learning store into dotnet
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// =============================================================================
|
||||
// QuantEngine Database Schema (DBML)
|
||||
// DbUp 마이그레이션(V1~V3)과 1:1 동기화 — 마이그레이션 추가 시 이 파일도 반드시 갱신
|
||||
// DbUp 마이그레이션(V1~V5)과 1:1 동기화 — 마이그레이션 추가 시 이 파일도 반드시 갱신
|
||||
// (CLAUDE.md 규칙: schema 변경 → DBML + 문서 동기화)
|
||||
//
|
||||
// 참고: Hangfire 스키마는 Hangfire.PostgreSql 라이브러리가 자동 생성
|
||||
@@ -277,6 +277,12 @@ TableGroup "engine_history" {
|
||||
factor_output_history
|
||||
decision_result_history
|
||||
market_vs_engine_gap_history
|
||||
source_observation
|
||||
factor_definition
|
||||
factor_observation
|
||||
decision_event
|
||||
decision_factor_evidence
|
||||
outcome_evaluation
|
||||
}
|
||||
|
||||
Table engine_history.market_raw_history {
|
||||
@@ -375,6 +381,88 @@ Table engine_history.market_vs_engine_gap_history {
|
||||
Note: "시장 데이터 vs 엔진 계산 갭 분석 이력"
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Schema: engine_history (V5 normalized learning history)
|
||||
// =============================================================================
|
||||
|
||||
Table engine_history.source_observation {
|
||||
observation_id UUID [pk]
|
||||
observed_at TIMESTAMPTZ [not null]
|
||||
instrument_id TEXT [not null]
|
||||
source_name TEXT [not null]
|
||||
source_version TEXT [not null]
|
||||
payload JSONB [not null]
|
||||
provenance JSONB [not null, default: "'{}'::jsonb"]
|
||||
created_at TIMESTAMPTZ [not null, default: "NOW()"]
|
||||
}
|
||||
|
||||
Table engine_history.factor_definition {
|
||||
factor_id TEXT [not null]
|
||||
factor_version TEXT [not null]
|
||||
formula_id TEXT [not null]
|
||||
effective_from TIMESTAMPTZ [not null]
|
||||
effective_to TIMESTAMPTZ
|
||||
definition JSONB [not null, default: "'{}'::jsonb"]
|
||||
provenance JSONB [not null, default: "'{}'::jsonb"]
|
||||
|
||||
indexes {
|
||||
(factor_id, factor_version) [pk]
|
||||
}
|
||||
}
|
||||
|
||||
Table engine_history.factor_observation {
|
||||
factor_observation_id UUID [pk]
|
||||
observation_id UUID [not null]
|
||||
factor_id TEXT [not null]
|
||||
factor_version TEXT [not null]
|
||||
observed_at TIMESTAMPTZ [not null]
|
||||
numeric_value NUMERIC
|
||||
text_value TEXT
|
||||
gate TEXT [not null]
|
||||
provenance JSONB [not null, default: "'{}'::jsonb"]
|
||||
}
|
||||
|
||||
Table engine_history.decision_event {
|
||||
decision_id UUID [pk]
|
||||
decision_key TEXT [not null, unique]
|
||||
decided_at TIMESTAMPTZ [not null]
|
||||
instrument_id TEXT [not null]
|
||||
action TEXT [not null]
|
||||
gate TEXT [not null]
|
||||
score NUMERIC
|
||||
source_version TEXT [not null]
|
||||
trace JSONB [not null, default: "'{}'::jsonb"]
|
||||
provenance JSONB [not null, default: "'{}'::jsonb"]
|
||||
created_at TIMESTAMPTZ [not null, default: "NOW()"]
|
||||
}
|
||||
|
||||
Table engine_history.decision_factor_evidence {
|
||||
decision_id UUID [not null]
|
||||
factor_observation_id UUID [not null]
|
||||
role TEXT [not null]
|
||||
|
||||
indexes {
|
||||
(decision_id, factor_observation_id) [pk]
|
||||
}
|
||||
}
|
||||
|
||||
Table engine_history.outcome_evaluation {
|
||||
evaluation_id UUID [pk]
|
||||
decision_id UUID [not null]
|
||||
horizon_days INT [not null]
|
||||
evaluated_at TIMESTAMPTZ [not null]
|
||||
realized_return NUMERIC
|
||||
benchmark_return NUMERIC
|
||||
excess_return NUMERIC
|
||||
outcome_class TEXT [not null]
|
||||
evaluation_gate TEXT [not null]
|
||||
provenance JSONB [not null, default: "'{}'::jsonb"]
|
||||
|
||||
indexes {
|
||||
(decision_id, horizon_days) [unique]
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Relationships (Logical, not enforced as FKs in DDL)
|
||||
// =============================================================================
|
||||
@@ -390,3 +478,9 @@ Ref: quantengine.kis_collection_errors.run_id > quantengine.kis_collection_runs.
|
||||
Ref: quantengine.workspace_session.username > quantengine.workspace_account.username {
|
||||
// logical relationship: session belongs to a user
|
||||
}
|
||||
|
||||
Ref: engine_history.factor_observation.observation_id > engine_history.source_observation.observation_id
|
||||
Ref: engine_history.factor_observation.(factor_id, factor_version) > engine_history.factor_definition.(factor_id, factor_version)
|
||||
Ref: engine_history.decision_factor_evidence.decision_id > engine_history.decision_event.decision_id
|
||||
Ref: engine_history.decision_factor_evidence.factor_observation_id > engine_history.factor_observation.factor_observation_id
|
||||
Ref: engine_history.outcome_evaluation.decision_id > engine_history.decision_event.decision_id
|
||||
|
||||
Reference in New Issue
Block a user