Files
QuantEngineByItz/src/dotnet/QuantEngine.Core/Domain/ProfitLockCalculator.cs
T
kjh2064 2ba8def9bb
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
feat(dotnet): migrate core formulas, deploy tools, and blazor admin web app to .NET 10
2026-06-25 15:52:10 +09:00

67 lines
2.3 KiB
C#

using System;
namespace QuantEngine.Core.Domain
{
public class ProfitLockResult
{
public string RatchetStage { get; set; } = "NORMAL";
public double? AutoTrailingStop { get; set; }
public string TpLadderAction { get; set; } = "적용 안함";
public bool ApexSuperActive { get; set; }
}
public static class ProfitLockCalculator
{
public static string ClassifyProfitLockStage(double profitPct)
{
if (profitPct >= 60) return "APEX_SUPER";
if (profitPct >= 40) return "APEX_TRAILING";
if (profitPct >= 30) return "PROFIT_LOCK_30";
if (profitPct >= 20) return "PROFIT_LOCK_20";
if (profitPct >= 10) return "PROFIT_LOCK_10";
if (profitPct >= 0) return "BREAKEVEN_RATCHET";
return "NORMAL";
}
public static ProfitLockResult ComputeTrailingStop(
double profitPct,
double highestClose,
double atr20,
double? ratchetStop,
double averageCost)
{
string stage = ClassifyProfitLockStage(profitPct);
double baseStop = ratchetStop ?? averageCost;
double? trailingStop = null;
string tpAction = "적용 안함";
if (stage == "APEX_SUPER")
{
double raw = highestClose - 1.2 * atr20;
trailingStop = KrxTickNormalizer.NormalizeTick(Math.Max(baseStop, raw));
tpAction = "강제 10% 익절 권고";
}
else if (stage == "APEX_TRAILING")
{
double raw = highestClose - 1.5 * atr20;
trailingStop = KrxTickNormalizer.NormalizeTick(Math.Max(baseStop, raw));
tpAction = "부분익절 검토";
}
else if (stage == "PROFIT_LOCK_30" || stage == "PROFIT_LOCK_20")
{
double raw = highestClose - 2.0 * atr20;
trailingStop = KrxTickNormalizer.NormalizeTick(Math.Max(baseStop, raw));
tpAction = "래칫 유지";
}
return new ProfitLockResult
{
RatchetStage = stage,
AutoTrailingStop = trailingStop,
TpLadderAction = tpAction,
ApexSuperActive = stage == "APEX_SUPER"
};
}
}
}