Files
BitGet_API/BitgetApi/IndicatorConditionSetup/SMABandConditionSetup.cs
2025-05-27 13:13:16 +09:00

174 lines
7.7 KiB
C#

using BitgetAPI.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static BitgetAPI.CommonProperty;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
namespace BitgetApi.IndicatorConditionSetup
{
public class SMABandConditionSetup
{
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<CandleData> candles, SMABandType type)
{
var close = candles.Select(t => t.Close).ToList();
close.RemoveAt(close.Count - 1);
var high = candles.Select(t=>t.High).ToList();
high.RemoveAt(high.Count - 1);
var low = candles.Select(t => t.Low).ToList();
low.RemoveAt(low.Count - 1);
var open = candles.Select(t => t.Open).ToList();
open.RemoveAt(open.Count - 1);
int i = close.Count - 1; // 최신 데이터 기준
double sma4 = Avg(close[i], close[i - 1], close[i - 2], close[i - 3]);
double prevSma4 = Avg(close[i - 4], close[i - 1], close[i - 2], close[i - 3]);
double prev2Sma4 = Avg(close[i - 4], close[i - 5], close[i - 2], close[i - 3]);
double prev3Sma4 = Avg(close[i - 4], close[i - 5], close[i - 6], close[i - 3]);
double sma4High = Highest(close, i, 12, useSma4: true);
double sma4Middle = SMA(close, i, 12, useSma4: true);
double sma4Low = Lowest(close, i, 12, useSma4: true);
double prevSma4High = Highest(close, i - 1, 12, useSma4: true);
double prevSma4Middle = SMA(close, i - 1, 12, useSma4: true);
double prevSma4Low = Lowest(close, i - 1, 12, useSma4: true);
double prev2Sma4High = Highest(close, i - 2, 12, useSma4: true);
double prev2Sma4Middle = SMA(close, i - 2, 12, useSma4: true);
double prev2Sma4Low = Lowest(close, i - 2, 12, useSma4: true);
double highestHigh = high.Skip(i - rangeLookback).Take(rangeLookback).Max();
double lowestLow = low.Skip(i - rangeLookback).Take(rangeLookback).Min();
double priceRange = highestHigh - lowestLow;
bool isSideways = priceRange > (highestHigh * rangeThresholdPercent / 100.0);
bool isLongRecentTouch = false;
for (int j = i - recentTouchLookback + 1; j <= i; j++)
{
double sma4_j = Avg(close[j], close[j - 1], close[j - 2], close[j - 3]);
double sma4Low_j = Lowest(close, j, 12, useSma4: true);
double prevSma4_j = Avg(close[j - 4], close[j - 1], close[j - 2], close[j - 3]);
double prevSma4Low_j = Lowest(close, j - 1, 12, useSma4: true);
if (sma4_j >= sma4Low_j && prevSma4_j == prevSma4Low_j)
{
isLongRecentTouch = true;
break;
}
}
bool isShortRecentTouch = false;
for (int j = i - recentTouchLookback + 1; j <= i; j++)
{
double sma4_j = Avg(close[j], close[j - 1], close[j - 2], close[j - 3]);
double sma4High_j = Highest(close, j, 12, useSma4: true);
double prevSma4_j = Avg(close[j - 4], close[j - 1], close[j - 2], close[j - 3]);
double prevSma4High_j = Highest(close, j - 1, 12, useSma4: true);
if (sma4_j <= sma4High_j && prevSma4_j == prevSma4High_j)
{
isShortRecentTouch = true;
break;
}
}
bool isShort2RecentTouch = false;
for (int j = i - recentTouch2Lookback + 1; j <= i; j++)
{
double sma4_j = Avg(close[j], close[j - 1], close[j - 2], close[j - 3]);
double sma4Middle_j = SMA(close, j, 12, useSma4: true);
if (sma4_j > sma4Middle_j)
{
isShort2RecentTouch = true;
break;
}
}
bool isLong2RecentTouch = false;
for (int j = i - recentTouch2Lookback + 1; j <= i; j++)
{
double sma4_j = Avg(close[j], close[j - 1], close[j - 2], close[j - 3]);
double sma4Middle_j = SMA(close, j, 12, useSma4: true);
if (sma4_j < sma4Middle_j)
{
isLong2RecentTouch = true;
break;
}
}
bool rawNewLong = (isSideways && ! isLongRecentTouch && isLong2RecentTouch && sma4 == sma4High && prevSma4<sma4 && prevSma4 < prevSma4High && open[open.Count - 1]<close[close.Count - 1] && ((sma4Middle -prevSma4Middle) > (prevSma4Middle - prev2Sma4Middle))) &&(isSideways && isLong2RecentTouch && sma4 > sma4Middle && prevSma4 < prevSma4Middle && prevSma4 < sma4 &&((sma4Middle - prevSma4Middle) > (prevSma4Middle - prev2Sma4Middle) && open[open.Count - 1] < close[close.Count - 1]));
bool rawLongSell = close[close.Count - 1] < sma4Middle || prevSma4High == prevSma4 && sma4High > sma4;
bool rawNewShort = (! isShortRecentTouch && isShort2RecentTouch && sma4 == sma4Low && prevSma4 > sma4 && prevSma4 > prevSma4Low && open[open.Count - 1] > close[close.Count - 1] &&((sma4Middle - prevSma4Middle) < (prevSma4Middle - prev2Sma4Middle))) || (isShort2RecentTouch && sma4 == sma4Low && prevSma4 == prevSma4Low && prevSma4 > sma4 && open[open.Count - 1] > close[close.Count - 1] &&((sma4Middle - prevSma4Middle) < (prevSma4Middle - prev2Sma4Middle)));
bool rawShortSell = rawShortSell = close[close.Count - 1] > sma4Middle || (sma4High == sma4 && prevSma4High > prevSma4) || (prev2Sma4Low == prev2Sma4 && prevSma4Low < prevSma4);
// === 시그널 계산 ===
if (type == SMABandType.LongBuy)
{
return rawNewLong;
}
else if (type == SMABandType.ShortBuy)
{
return rawNewShort;
}
else if (type == SMABandType.LongSell)
{
return rawLongSell;
}
else if (type == SMABandType.ShortSell)
{
return rawShortSell;
}
return false;
}
private double Avg(params double[] values) => values.Average();
private double SMA(List<double> source, int currentIndex, int period, bool useSma4)
{
var values = new List<double>();
for (int i = currentIndex - period + 1; i <= currentIndex; i++)
{
double sma4 = Avg(source[i], source[i - 1], source[i - 2], source[i - 3]);
values.Add(sma4);
}
return values.Average();
}
private double Highest(List<double> source, int currentIndex, int period, bool useSma4)
{
var values = new List<double>();
for (int i = currentIndex - period + 1; i <= currentIndex; i++)
{
double sma4 = Avg(source[i], source[i - 1], source[i - 2], source[i - 3]);
values.Add(sma4);
}
return values.Max();
}
private double Lowest(List<double> source, int currentIndex, int period, bool useSma4)
{
var values = new List<double>();
for (int i = currentIndex - period + 1; i <= currentIndex; i++)
{
double sma4 = Avg(source[i], source[i - 1], source[i - 2], source[i - 3]);
values.Add(sma4);
}
return values.Min();
}
}
}