refactor(dotnet): structure pipeline orchestration steps
This commit is contained in:
@@ -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);
|
errMsg = "REFERENCE IMPLEMENTATION ONLY";
|
||||||
await Task.Delay(5);
|
|
||||||
}
|
}
|
||||||
else if (step == "routing_decision")
|
|
||||||
{
|
|
||||||
// Step 2: Real computed routing decision logic
|
|
||||||
var ctx = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
["entryModeGate"] = "PASS",
|
|
||||||
["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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user