using Bitget_Server.Domain.Enums; using Bitget_Server.Domain.Models; namespace Bitget_Server.Application.Services; /// /// 기존 IndicatorProcess.Calculate전고점 / 전저고점 dictionary bookkeeping 이식. /// 단일 인스턴스로 보관되며 키는 "MarketName + Interval(Description)" 문자열이다. /// public class PriceLevelTracker { private readonly Dictionary> _levels = new(); public IReadOnlyDictionary> Levels => _levels; public void Clear() => _levels.Clear(); public bool ContainsKey(string key) => _levels.ContainsKey(key); public Dictionary GetOrCreate(string key) { if (_levels.TryGetValue(key, out var existing)) return existing; var dic = new Dictionary { { "전고가", 0 }, { "전저가", 0 }, { "전전고가", 0 }, { "전전저가", 0 }, { "전전전저가", 0 }, { "전전전고가", 0 }, { "전전전전저가", 0 }, { "전전전전고가", 0 }, { "tempHighVal", 0 }, { "tempLowVal", 0 }, { "tempHigh2Val", 0 }, { "tempLow2Val", 0 }, { "tempHigh3Val", 0 }, { "tempLow3Val", 0 }, { "tempHigh4Val", 0 }, { "tempLow4Val", 0 }, { "switchLowVal", 0 }, { "switchHighVal", 0 }, { "Type", 0 } }; _levels[key] = dic; return dic; } /// /// 기존 IndicatorProcess.Calculate전고점 이식. /// 전봉/전전봉/전전전봉의 이동평균(4일) 값으로 local minima/maxima 를 추적한다. /// public bool Calculate(string market, string intervalKey, MCandleTimeType type, double 전봉, double 전전봉, double 전전전봉, CandleData candleData) { var key = market + intervalKey; var 저고점 = GetOrCreate(key); var nowUnix = ((DateTimeOffset)candleData.Argument).ToUnixTimeSeconds(); // === 전저가 계산 === if (전봉 > 전전봉 && 전전봉 < 전전전봉 && 저고점["tempHighVal"] >= 저고점["tempLowVal"] && 저고점["tempLowVal"] != nowUnix && nowUnix - 저고점["tempHighVal"] >= 120 * (int)type) { 저고점["tempLow4Val"] = 저고점["tempLowVal"]; 저고점["tempLowVal"] = 저고점["tempLow2Val"]; 저고점["tempLow2Val"] = 저고점["tempLowVal"]; 저고점["tempLowVal"] = nowUnix; 저고점["switchLowVal"] = 저고점["전전전전저가"]; 저고점["전전전전저가"] = 저고점["전전저가"]; 저고점["전전전저가"] = 저고점["전전저가"]; 저고점["전전저가"] = 저고점["전저가"]; 저고점["전저가"] = 전전봉; 저고점["Type"] = 0; } else if (전봉 > 전전봉 && 전전봉 < 전전전봉 && 저고점["tempHighVal"] < 저고점["tempLowVal"] && 저고점["tempLowVal"] != nowUnix && nowUnix - 저고점["tempHighVal"] >= 120 * (int)type) { if (저고점["전저가"] > 전전봉) { 저고점["tempLowVal"] = nowUnix; 저고점["전저가"] = 전전봉; } 저고점["Type"] = 0; } else if (전봉 > 전전봉 && 전전봉 < 전전전봉 && 저고점["tempLowVal"] != nowUnix && nowUnix - 저고점["tempHighVal"] < 120 * (int)type) { // 이전 상태로 롤백 (High) 저고점["전고가"] = 저고점["전전고가"]; 저고점["전전고가"] = 저고점["전전전고가"]; 저고점["전전전고가"] = 저고점["전전전전고가"]; 저고점["Type"] = 0; 저고점["전전전전고가"] = 저고점["switchLowVal"]; 저고점["tempHighVal"] = 저고점["tempHigh2Val"]; 저고점["tempHigh2Val"] = 저고점["tempHighVal"]; 저고점["tempHighVal"] = 저고점["tempHigh4Val"]; if (저고점["전저가"] > 전전봉) 저고점["전저가"] = 전전봉; } // === 전고가 계산 === if (전전봉 > 전봉 && 전전봉 > 전전전봉 && 저고점["tempHighVal"] <= 저고점["tempLowVal"] && 저고점["tempHighVal"] != nowUnix && nowUnix - 저고점["tempLowVal"] >= 120 * (int)type) { 저고점["tempHigh4Val"] = 저고점["tempHighVal"]; 저고점["tempHighVal"] = 저고점["tempHigh2Val"]; 저고점["tempHigh2Val"] = 저고점["tempHighVal"]; 저고점["tempHighVal"] = nowUnix; 저고점["switchHighVal"] = 저고점["전전전전고가"]; 저고점["전전전전고가"] = 저고점["전전전고가"]; 저고점["전전전고가"] = 저고점["전전고가"]; 저고점["전전고가"] = 저고점["전고가"]; 저고점["Type"] = 1; 저고점["전고가"] = 전전봉; } else if (전전봉 > 전봉 && 전전봉 > 전전전봉 && 저고점["tempHighVal"] > 저고점["tempLowVal"] && 저고점["tempHighVal"] != nowUnix && nowUnix - 저고점["tempLowVal"] >= 120 * (int)type) { if (저고점["전고가"] < 전전봉) { 저고점["tempHighVal"] = nowUnix; 저고점["전고가"] = 전전봉; } } else if (전전봉 > 전봉 && 전전봉 > 전전전봉 && 저고점["tempHighVal"] != nowUnix && nowUnix - 저고점["tempLowVal"] < 120 * (int)type) { // 이전 상태로 롤백 (Low) 저고점["전저가"] = 저고점["전전저가"]; 저고점["전전저가"] = 저고점["전전전저가"]; 저고점["전전전저가"] = 저고점["전전전전저가"]; 저고점["전전전전저가"] = 저고점["switchHighVal"]; 저고점["Type"] = 1; 저고점["tempLowVal"] = 저고점["tempLow2Val"]; 저고점["tempLow2Val"] = 저고점["tempLowVal"]; 저고점["tempLowVal"] = 저고점["tempLow4Val"]; if (저고점["전고가"] < 전전봉) 저고점["전고가"] = 전전봉; } return 저고점["전전전저가"] != 0 && 저고점["전전전고가"] != 0; } }