feat(dotnet): migrate core formulas, deploy tools, and blazor admin web app to .NET 10
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Has been cancelled
Quant Engine CI/CD Pipeline / validate-core (pull_request) Has been cancelled
Quant Engine CI/CD Pipeline / validate-ui-and-storage (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Has been cancelled
Quant Engine CI/CD Pipeline / validate-core (pull_request) Has been cancelled
Quant Engine CI/CD Pipeline / validate-ui-and-storage (pull_request) Has been cancelled
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (pull_request) Has been cancelled
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantEngine.Core.Domain
|
||||
{
|
||||
public class SellPriceSanityResult
|
||||
{
|
||||
public string SellPriceSanityStatus { get; set; } = "PASS";
|
||||
public List<string> SellPriceSanityIssues { get; set; } = new List<string>();
|
||||
public bool HtsAllowed { get; set; } = true;
|
||||
public bool ShadowLedger { get; set; }
|
||||
public string Ticker { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public static class SellPriceSanityChecker
|
||||
{
|
||||
public static SellPriceSanityResult CheckSellPriceSanity(
|
||||
double sellLimitPrice,
|
||||
double? stopLossPrice,
|
||||
double prevClose,
|
||||
string ticker = "")
|
||||
{
|
||||
var issues = new List<string>();
|
||||
string status = "PASS";
|
||||
|
||||
if (stopLossPrice.HasValue && sellLimitPrice < stopLossPrice.Value)
|
||||
{
|
||||
issues.Add($"INVALID_PRICE_INVERSION: sell={sellLimitPrice:N0} < stop={stopLossPrice.Value:N0}");
|
||||
status = "INVALID_PRICE_INVERSION";
|
||||
}
|
||||
|
||||
double upperLimit = prevClose * 1.30;
|
||||
if (sellLimitPrice > upperLimit)
|
||||
{
|
||||
issues.Add($"INVALID_UNREALISTIC_PRICE: sell={sellLimitPrice:N0} > prev_close*1.30={upperLimit:N0}");
|
||||
if (status == "PASS")
|
||||
{
|
||||
status = "INVALID_UNREALISTIC_PRICE";
|
||||
}
|
||||
}
|
||||
|
||||
int tickUnit = KrxTickNormalizer.GetTickUnit(sellLimitPrice);
|
||||
if (sellLimitPrice % tickUnit != 0)
|
||||
{
|
||||
double corrected = KrxTickNormalizer.NormalizeTick(sellLimitPrice);
|
||||
issues.Add($"INVALID_TICK: sell={sellLimitPrice:N0} 호가단위={tickUnit}원 → 정규화={corrected:N0}");
|
||||
if (status == "PASS")
|
||||
{
|
||||
status = "INVALID_TICK";
|
||||
}
|
||||
}
|
||||
|
||||
return new SellPriceSanityResult
|
||||
{
|
||||
SellPriceSanityStatus = status,
|
||||
SellPriceSanityIssues = issues,
|
||||
HtsAllowed = status == "PASS",
|
||||
ShadowLedger = status != "PASS",
|
||||
Ticker = ticker
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user