refactor(dotnet): normalize factor computation outputs
This commit is contained in:
@@ -42,6 +42,10 @@ public sealed class FactorComputationService
|
|||||||
FactorOutputs outputs,
|
FactorOutputs outputs,
|
||||||
DateTimeOffset? observedAt = null)
|
DateTimeOffset? observedAt = null)
|
||||||
{
|
{
|
||||||
|
ticker = RequireValue(ticker, nameof(ticker));
|
||||||
|
sourceVersion = RequireValue(sourceVersion, nameof(sourceVersion));
|
||||||
|
ArgumentNullException.ThrowIfNull(outputs);
|
||||||
|
|
||||||
var when = observedAt ?? DateTimeOffset.UtcNow;
|
var when = observedAt ?? DateTimeOffset.UtcNow;
|
||||||
await _history.AppendFactorOutputAsync("momentum_20d", sourceVersion, outputs.Momentum20D, "PASS", sourceVersion, when);
|
await _history.AppendFactorOutputAsync("momentum_20d", sourceVersion, outputs.Momentum20D, "PASS", sourceVersion, when);
|
||||||
await _history.AppendFactorOutputAsync("momentum_60d", sourceVersion, outputs.Momentum60D, "PASS", sourceVersion, when);
|
await _history.AppendFactorOutputAsync("momentum_60d", sourceVersion, outputs.Momentum60D, "PASS", sourceVersion, when);
|
||||||
@@ -52,4 +56,14 @@ public sealed class FactorComputationService
|
|||||||
await _history.AppendFactorOutputAsync("rs_20d", sourceVersion, outputs.Rs20D, "PASS", sourceVersion, when);
|
await _history.AppendFactorOutputAsync("rs_20d", sourceVersion, outputs.Rs20D, "PASS", sourceVersion, when);
|
||||||
_auditTrail.Append("factor_audit", ticker, new FactorComputationAudit(ticker, 0, 0, "PERSISTED", when, sourceVersion));
|
_auditTrail.Append("factor_audit", ticker, new FactorComputationAudit(ticker, 0, 0, "PERSISTED", when, sourceVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string RequireValue(string value, string parameterName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Value is required.", parameterName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.Trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,16 @@ public class FactorComputationServiceTests
|
|||||||
storeMock.Verify(s => s.AppendAsync("factor_output_history", It.IsAny<IDictionary<string, object?>>()), Times.Exactly(7));
|
storeMock.Verify(s => s.AppendAsync("factor_output_history", It.IsAny<IDictionary<string, object?>>()), Times.Exactly(7));
|
||||||
auditTrailMock.Verify(a => a.Append("factor_audit", "005930", It.IsAny<FactorComputationAudit>()), Times.Once);
|
auditTrailMock.Verify(a => a.Append("factor_audit", "005930", It.IsAny<FactorComputationAudit>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AppendFactorOutputsAsync_RejectsBlankTicker()
|
||||||
|
{
|
||||||
|
var storeMock = new Mock<IPostgresqlHistoryStore>();
|
||||||
|
var auditTrailMock = new Mock<IRuntimeAuditTrailService>();
|
||||||
|
var history = new HistoryIngestionService(storeMock.Object);
|
||||||
|
var service = new FactorComputationService(history, auditTrailMock.Object);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() =>
|
||||||
|
service.AppendFactorOutputsAsync(" ", "v1", new FactorOutputs(1, 2, 3, 4, 5, 6, 7)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user