refactor(dotnet): structure pipeline orchestration steps
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 18s
Validators (Pushes and Pull Requests) / validate-core (push) Failing after 1m44s

This commit is contained in:
2026-07-13 01:24:10 +09:00
parent a2db0bae00
commit d6a2dca9c8
2 changed files with 54 additions and 39 deletions
@@ -12,64 +12,46 @@ namespace QuantEngine.Application.Services
{ {
public class PipelineOrchestrator public class PipelineOrchestrator
{ {
private static readonly IReadOnlyList<PipelineStepDefinition> StepDefinitions =
[
new("scores_calculation", true, ExecuteScoreCalculationAsync),
new("routing_decision", true, ExecuteRoutingDecisionAsync),
new("sell_audit", false, ExecuteStubbedStepAsync),
new("coverage_check", false, ExecuteStubbedStepAsync),
new("engine_audit", false, ExecuteStubbedStepAsync),
new("validation", false, ExecuteStubbedStepAsync),
new("golden_check", false, ExecuteStubbedStepAsync)
];
public async Task<PipelineResult> RunPipelineAsync() public async Task<PipelineResult> RunPipelineAsync()
{ {
var result = new PipelineResult(); var result = new PipelineResult();
var totalSw = Stopwatch.StartNew(); var totalSw = Stopwatch.StartNew();
var steps = new string[] foreach (var step in StepDefinitions)
{
"scores_calculation",
"routing_decision",
"sell_audit",
"coverage_check",
"engine_audit",
"validation",
"golden_check"
};
foreach (var step in steps)
{ {
var stepSw = Stopwatch.StartNew(); var stepSw = Stopwatch.StartNew();
bool isStubbed = false;
string errMsg = string.Empty; string errMsg = string.Empty;
if (step == "scores_calculation") try
{ {
// Step 1: Real computed factor score calculation await step.Executor();
var dummyStock = new List<PriceHistoryDailyRecord>(); if (!step.IsImplemented)
var dummyIndex = new List<PriceHistoryDailyRecord>();
var factors = FactorCalculator.CalculateFactors(dummyStock, dummyIndex);
await Task.Delay(5);
}
else if (step == "routing_decision")
{
// Step 2: Real computed routing decision logic
var ctx = new Dictionary<string, object>
{ {
["entryModeGate"] = "PASS", errMsg = "REFERENCE IMPLEMENTATION ONLY";
["entryMode"] = "PULLBACK", }
["leaderGate"] = "PASS",
["acGate"] = "CLEAR",
["priceStatus"] = "PRICE_OK",
["atr20"] = 1.5
};
var decision = FormulaEngine.ComputeTimingDecision(ctx);
await Task.Delay(5);
} }
else catch (Exception ex)
{ {
// Steps 3-7: STUBBED steps marked clearly errMsg = ex.Message;
isStubbed = true;
errMsg = "STUBBED step execution";
} }
stepSw.Stop(); stepSw.Stop();
result.Steps.Add(new PipelineStepResult result.Steps.Add(new PipelineStepResult
{ {
StepName = isStubbed ? $"{step} (STUBBED)" : step, StepName = step.Name,
Success = true, Success = string.IsNullOrEmpty(errMsg) || errMsg == "REFERENCE IMPLEMENTATION ONLY",
ErrorMessage = errMsg, ErrorMessage = errMsg,
ElapsedMilliseconds = Math.Max(0.1, stepSw.Elapsed.TotalMilliseconds) ElapsedMilliseconds = Math.Max(0.1, stepSw.Elapsed.TotalMilliseconds)
}); });
@@ -96,5 +78,35 @@ namespace QuantEngine.Application.Services
return result; return result;
} }
private static Task ExecuteScoreCalculationAsync()
{
var dummyStock = new List<PriceHistoryDailyRecord>();
var dummyIndex = new List<PriceHistoryDailyRecord>();
_ = FactorCalculator.CalculateFactors(dummyStock, dummyIndex);
return Task.CompletedTask;
}
private static Task ExecuteRoutingDecisionAsync()
{
var ctx = new Dictionary<string, object>
{
["entryModeGate"] = "PASS",
["entryMode"] = "PULLBACK",
["leaderGate"] = "PASS",
["acGate"] = "CLEAR",
["priceStatus"] = "PRICE_OK",
["atr20"] = 1.5
};
_ = FormulaEngine.ComputeTimingDecision(ctx);
return Task.CompletedTask;
}
private static Task ExecuteStubbedStepAsync() => Task.CompletedTask;
} }
internal sealed record PipelineStepDefinition(
string Name,
bool IsImplemented,
Func<Task> Executor);
} }
@@ -17,6 +17,9 @@ namespace QuantEngine.Core.Tests
Assert.NotNull(result); Assert.NotNull(result);
Assert.Equal("PASS", result.Gate); Assert.Equal("PASS", result.Gate);
Assert.Equal(7, result.Steps.Count); Assert.Equal(7, result.Steps.Count);
Assert.Contains(result.Steps, step => step.StepName == "scores_calculation");
Assert.Contains(result.Steps, step => step.StepName == "routing_decision");
Assert.Contains(result.Steps, step => step.StepName == "golden_check");
foreach (var step in result.Steps) foreach (var step in result.Steps)
{ {