diff --git a/BitgetApi/IndicatorConditionSetup/SMABandConditionSetup.cs b/BitgetApi/IndicatorConditionSetup/SMABandConditionSetup.cs index 856c15f..a96f23c 100644 --- a/BitgetApi/IndicatorConditionSetup/SMABandConditionSetup.cs +++ b/BitgetApi/IndicatorConditionSetup/SMABandConditionSetup.cs @@ -1,4 +1,5 @@ using BitgetAPI.Data; +using DevExpress.XtraBars.ViewInfo; using System; using System.Collections.Generic; using System.Linq; @@ -13,32 +14,27 @@ namespace BitgetApi.IndicatorConditionSetup { private readonly int rangeLookback = 12; private readonly double rangeThresholdPercent = 0.6; - private readonly int recentTouchLookback = 5; - private readonly int recentTouch2Lookback = 15; public bool Calculate(List candles, SMABandType type) { - var close = candles.Select(t => t.Close).ToList(); - close.RemoveAt(close.Count - 1); + var close = candles.Select(t => t.Close).ToList(); - var high = candles.Select(t=>t.High).ToList(); - high.RemoveAt(high.Count - 1); + var high = candles.Select(t=>t.High).ToList(); - var low = candles.Select(t => t.Low).ToList(); - low.RemoveAt(low.Count - 1); + var low = candles.Select(t => t.Low).ToList(); - var open = candles.Select(t => t.Open).ToList(); - open.RemoveAt(open.Count - 1); + var open = candles.Select(t => t.Open).ToList(); int i = close.Count - 1; - if (close.Count < 20 || high.Count < 20 || low.Count < 20 || open.Count < 20) + if (close.Count < 100 || high.Count < 100 || low.Count < 100 || open.Count < 100) return false; // SMA4 관련 double sma4 = Sma4(close, i); double prevSma4 = Sma4(close, i - 1); double prev2Sma4 = Sma4(close, i - 2); + double prev3Sma4 = Sma4(close, i - 2); // 밴드 계산 double sma4High = Highest(close, i, 12); @@ -52,26 +48,39 @@ namespace BitgetApi.IndicatorConditionSetup double prev2Sma4High = Highest(close, i - 2, 12); double prev2Sma4Low = Lowest(close, i - 2, 12); double prev2Sma4Middle = SMA(close, i - 2, 12); + + double prev3Sma4High = Highest(close, i - 3, 12); + double prev3Sma4Low = Lowest(close, i - 3, 12); + double prev3Sma4Middle = SMA(close, i - 3, 12); + bool isSideways = IsSideways(high, low, i); - // 조건 판단 - bool isLongRecentTouch = IsRecentTouch(close, i, recentTouchLookback, "low"); - bool isShortRecentTouch = IsRecentTouch(close, i, recentTouchLookback, "high"); - bool isShort2RecentTouch = IsMiddleBreakout(close, i, recentTouch2Lookback, true); - bool isLong2RecentTouch = IsMiddleBreakout(close, i, recentTouch2Lookback, false); + //구름떼 + double conversionLine = (high.Skip(i - 8).Take(9).Max() + low.Skip(i - 8).Take(9).Min()) / 2.0; + double baseLine = (high.Skip(i - 25).Take(26).Max() + low.Skip(i - 25).Take(26).Min()) / 2.0; + double leadingSpan1 = (conversionLine + baseLine) / 2.0; + double leadingSpan2 = (high.Skip(i - 51).Take(52).Max() + low.Skip(i - 51).Take(52).Min()) / 2.0; + + double cloudTopNow = Math.Max(leadingSpan1, leadingSpan2); + double cloudBottomNow = Math.Min(leadingSpan1, leadingSpan2); + + bool isSma4BelowCloud = sma4 < cloudBottomNow; + bool isSma4AboveCloud = sma4 > cloudTopNow; + bool greenCandle = open[i] < close[i]; bool redCandle = open[i] > close[i]; // 진입/청산 조건 - bool rawNewLong = (isSideways && !isLongRecentTouch && isLong2RecentTouch && sma4 == sma4High && prevSma4 < sma4 && prevSma4 == prevSma4High && prev2Sma4 < prev2Sma4High && greenCandle) - || (isSideways && isLong2RecentTouch && sma4 > sma4Middle && prevSma4 < prevSma4Middle && prevSma4 < sma4 && (sma4Middle - prevSma4Middle) > (prevSma4Middle - SMA(close, i - 2, 12)) && greenCandle); + bool rawNewLong = isSideways && isSma4AboveCloud && (sma4 == sma4High && prevSma4 <= prevSma4High && prev2Sma4 <= prev2Sma4High) && (sma4 >= prevSma4 && prevSma4 >= prev2Sma4 && prev2Sma4 >= prev3Sma4); - bool rawLongSell = close[i] < sma4Middle || (prevSma4High == prevSma4 && sma4High > sma4); + bool rawLongSell = (sma4 <= prevSma4 && prevSma4 <= prev2Sma4 && prev2Sma4 <= prev3Sma4 && sma4 == sma4Low); - bool rawNewShort = (sma4 == sma4Low && prevSma4 > sma4 && prevSma4 > prevSma4Low && open[i] > close[i] && ((sma4Middle - prevSma4Middle) < (prevSma4Middle - prev2Sma4Middle))); - - bool rawShortSell = close[i] > sma4Middle || (sma4High == sma4 && prevSma4High > prevSma4) || (prev2Sma4Low == prev2Sma4 && prevSma4Low < prevSma4); + + bool rawNewShort = isSideways && isSma4BelowCloud && (sma4 == sma4Low && prevSma4 >= prevSma4Low && prev2Sma4 >= prev2Sma4Low) && (sma4 <= prevSma4 && prevSma4 <= prev2Sma4 && prev2Sma4 <= prev3Sma4); + + + bool rawShortSell = (sma4 >= prevSma4 && prevSma4 >= prev2Sma4 && prev2Sma4 >= prev3Sma4 && sma4 == sma4High); // === 시그널 계산 === if (type == SMABandType.LongBuy) @@ -129,32 +138,5 @@ namespace BitgetApi.IndicatorConditionSetup double range = highestHigh - lowestLow; return range > (highestHigh * rangeThresholdPercent / 100.0); } - - private bool IsRecentTouch(List close, int currentIndex, int lookback, string type) - { - for (int j = currentIndex - lookback + 1; j <= currentIndex; j++) - { - double sma4 = Sma4(close, j); - double band = (type == "low") ? Lowest(close, j, 12) : Highest(close, j, 12); - double prevSma4 = Sma4(close, j - 1); - double prevBand = (type == "low") ? Lowest(close, j - 1, 12) : Highest(close, j - 1, 12); - - if (sma4 >= band && prevSma4 == prevBand) - return true; - } - return false; - } - - private bool IsMiddleBreakout(List close, int currentIndex, int lookback, bool above) - { - for (int j = currentIndex - lookback + 1; j <= currentIndex; j++) - { - double sma4 = Sma4(close, j); - double middle = SMA(close, j, 12); - if (above && sma4 > middle) return true; - if (!above && sma4 < middle) return true; - } - return false; - } } }