refactor(dotnet): normalize factor input dates
This commit is contained in:
@@ -125,5 +125,28 @@ namespace QuantEngine.Core.Tests
|
|||||||
Assert.Equal(expectedMom20, outputs.Momentum20D, 5);
|
Assert.Equal(expectedMom20, outputs.Momentum20D, 5);
|
||||||
Assert.Equal(1.0, outputs.Beta60D);
|
Assert.Equal(1.0, outputs.Beta60D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CalculateFactors_DuplicateDates_UsesLastOccurrencePerDate()
|
||||||
|
{
|
||||||
|
var stock = CreateMockBars("005930", 100.0, 1.0, 130);
|
||||||
|
var index = CreateMockBars("KOSPI", 2000.0, 0.0, 130);
|
||||||
|
|
||||||
|
var duplicateDate = stock[129].TradeDate;
|
||||||
|
stock.Add(new PriceHistoryDailyRecord(
|
||||||
|
"005930",
|
||||||
|
duplicateDate,
|
||||||
|
1000m,
|
||||||
|
1002m,
|
||||||
|
998m,
|
||||||
|
1001m,
|
||||||
|
100000,
|
||||||
|
"TEST_SOURCE"));
|
||||||
|
|
||||||
|
var outputs = FactorCalculator.CalculateFactors(stock, index);
|
||||||
|
|
||||||
|
Assert.True(outputs.Momentum20D > 0);
|
||||||
|
Assert.True(outputs.Atr20Pct > 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ namespace QuantEngine.Core.Domain
|
|||||||
return new FactorOutputs(0, 0, 0, 0, 0, 1.0, 0);
|
return new FactorOutputs(0, 0, 0, 0, 0, 1.0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sortedStock = stockBars.OrderBy(b => b.TradeDate).ToList();
|
var sortedStock = NormalizeBars(stockBars);
|
||||||
var sortedIndex = indexBars?.OrderBy(b => b.TradeDate).ToList() ?? new List<PriceHistoryDailyRecord>();
|
var sortedIndex = NormalizeBars(indexBars);
|
||||||
return new FactorOutputs(
|
return new FactorOutputs(
|
||||||
CalculateMomentum(sortedStock, 20),
|
CalculateMomentum(sortedStock, 20),
|
||||||
CalculateMomentum(sortedStock, 60),
|
CalculateMomentum(sortedStock, 60),
|
||||||
@@ -38,6 +38,20 @@ namespace QuantEngine.Core.Domain
|
|||||||
CalculateRs20D(sortedStock, sortedIndex));
|
CalculateRs20D(sortedStock, sortedIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<PriceHistoryDailyRecord> NormalizeBars(List<PriceHistoryDailyRecord>? bars)
|
||||||
|
{
|
||||||
|
if (bars == null || bars.Count == 0)
|
||||||
|
{
|
||||||
|
return new List<PriceHistoryDailyRecord>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bars
|
||||||
|
.OrderBy(b => b.TradeDate)
|
||||||
|
.GroupBy(b => b.TradeDate)
|
||||||
|
.Select(g => g.Last())
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
private static double CalculateMomentum(List<PriceHistoryDailyRecord> bars, int period)
|
private static double CalculateMomentum(List<PriceHistoryDailyRecord> bars, int period)
|
||||||
{
|
{
|
||||||
if (bars.Count <= period) return 0.0;
|
if (bars.Count <= period) return 0.0;
|
||||||
|
|||||||
Reference in New Issue
Block a user