using System.Collections.Generic; using System.Threading.Tasks; using QuantEngine.Core.Domain; using QuantEngine.Core.Interfaces; namespace QuantEngine.Application.Services { public class HistoryIngestionService { private readonly IPostgresqlHistoryStore _store; public HistoryIngestionService(IPostgresqlHistoryStore store) { _store = store; } public Task AppendDecisionAsync(IDictionary payload) => _store.AppendAsync("decision_result_history", payload); public Task AppendFactorOutputAsync(IDictionary payload) => _store.AppendAsync("factor_output_history", payload); public Task AppendMarketRawAsync(IDictionary payload) => _store.AppendAsync("market_raw_history", payload); public Task AppendGapAsync(IDictionary payload) => _store.AppendAsync("market_vs_engine_gap_history", payload); public Task AppendDecisionAsync( FinalDecisionResult decision, SellDecisionResult? sellDecision = null, TimingDecisionResult? timingDecision = null, string? instrumentId = null, string? sourceVersion = null, string? gate = null) { var payload = new Dictionary { ["decision_id"] = Guid.NewGuid().ToString("N"), ["decided_at"] = DateTimeOffset.UtcNow, ["instrument_id"] = instrumentId ?? string.Empty, ["action"] = decision.FinalAction, ["gate"] = gate ?? (string.IsNullOrWhiteSpace(sellDecision?.Validation) ? "PASS" : sellDecision.Validation), ["score"] = decision.PriorityScore, ["source_version"] = sourceVersion ?? decision.DecisionSource, ["provenance"] = new Dictionary { ["final_action"] = decision.FinalAction, ["action_priority"] = decision.ActionPriority, ["priority_score"] = decision.PriorityScore, ["decision_source"] = decision.DecisionSource, ["sell_action"] = sellDecision?.Action, ["sell_validation"] = sellDecision?.Validation, ["timing_action"] = timingDecision?.Action, ["timing_reason"] = timingDecision?.Reason } }; return _store.AppendAsync("decision_result_history", payload); } public Task AppendFactorOutputAsync( string factorId, string factorVersion, double outputValue, string outputGate, string? sourceVersion = null, DateTimeOffset? observedAt = null) { var payload = new Dictionary { ["factor_output_id"] = Guid.NewGuid().ToString("N"), ["observed_at"] = observedAt ?? DateTimeOffset.UtcNow, ["factor_id"] = factorId, ["factor_version"] = factorVersion, ["output_value"] = outputValue, ["output_gate"] = outputGate, ["source_version"] = sourceVersion ?? factorVersion, ["provenance"] = new Dictionary { ["factor_id"] = factorId, ["factor_version"] = factorVersion, ["output_value"] = outputValue, ["output_gate"] = outputGate, ["source_version"] = sourceVersion ?? factorVersion } }; return _store.AppendAsync("factor_output_history", payload); } } }