refactor(dotnet): normalize formula service inputs
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 17s
Validators (Pushes and Pull Requests) / validate-core (push) Has been cancelled

This commit is contained in:
2026-07-13 01:28:05 +09:00
parent e745cfb0ae
commit cb814b8aa2
2 changed files with 77 additions and 12 deletions
@@ -16,14 +16,14 @@ namespace QuantEngine.Application.Services
_learningService = learningService;
}
public TimingDecisionResult ComputeTimingDecision(Dictionary<string, object> ctx)
=> FormulaEngine.ComputeTimingDecision(ctx);
public TimingDecisionResult ComputeTimingDecision(Dictionary<string, object> ctx)
=> FormulaEngine.ComputeTimingDecision(RequireContext(ctx));
public SellDecisionResult ComputeSellDecision(Dictionary<string, object> ctx)
=> FormulaEngine.ComputeSellDecision(ctx);
public SellDecisionResult ComputeSellDecision(Dictionary<string, object> ctx)
=> FormulaEngine.ComputeSellDecision(RequireContext(ctx));
public FinalDecisionResult ComputeFinalDecision(Dictionary<string, object> ctx)
=> FormulaEngine.ComputeFinalDecision(ctx);
public FinalDecisionResult ComputeFinalDecision(Dictionary<string, object> ctx)
=> FormulaEngine.ComputeFinalDecision(RequireContext(ctx));
public async Task<Guid> ComputeAndRecordFinalDecisionAsync(
Dictionary<string, object> ctx,
@@ -32,17 +32,18 @@ namespace QuantEngine.Application.Services
string sourceVersion,
IEnumerable<FactorEvidenceInput> factorEvidence)
{
var decision = ComputeFinalDecision(ctx);
var normalizedContext = RequireContext(ctx);
var decision = ComputeFinalDecision(normalizedContext);
return await _learningService.RecordDecisionAsync(
decisionKey,
RequireValue(decisionKey, nameof(decisionKey)),
DateTimeOffset.UtcNow,
instrumentId,
RequireValue(instrumentId, nameof(instrumentId)),
decision.FinalAction,
"PASS",
Convert.ToDecimal(decision.PriorityScore),
sourceVersion,
RequireValue(sourceVersion, nameof(sourceVersion)),
factorEvidence,
new { context_keys = ctx.Keys.OrderBy(key => key).ToArray() },
new { context_keys = normalizedContext.Keys.OrderBy(key => key).ToArray() },
new { formula = "FormulaEngine.ComputeFinalDecision", source_version = sourceVersion });
}
@@ -59,6 +60,22 @@ namespace QuantEngine.Application.Services
=> FormulaEngine.ComputeCashRecoveryOptimizer(sellCandidates, cashShortfallMinKrw);
public Task<int> AppendFormulaRunAsync(string formulaName, Dictionary<string, object?> payload)
=> _historyStore.AppendAsync($"formula_{formulaName}_history", payload);
=> _historyStore.AppendAsync($"formula_{RequireValue(formulaName, nameof(formulaName))}_history", payload);
private static Dictionary<string, object> RequireContext(Dictionary<string, object> ctx)
{
ArgumentNullException.ThrowIfNull(ctx);
return ctx;
}
private static string RequireValue(string value, string parameterName)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("Value is required.", parameterName);
}
return value.Trim();
}
}
}