117 lines
3.3 KiB
C#
117 lines
3.3 KiB
C#
using Bitget_Server.Domain.Indicators;
|
|
|
|
namespace Bitget_Server.Application.Indicators;
|
|
|
|
[Serializable]
|
|
public class ImpulseMacdConditionSetup
|
|
{
|
|
private int lengthMA;
|
|
private int lengthSignal;
|
|
|
|
private List<double> srcList = new();
|
|
private List<double> highList = new();
|
|
private List<double> lowList = new();
|
|
private List<double> smmaHighList = new();
|
|
private List<double> smmaLowList = new();
|
|
private List<double> zlemaList = new();
|
|
private List<double> mdList = new();
|
|
private List<double> sbList = new();
|
|
private List<double> shList = new();
|
|
|
|
public ImpulseMacdConditionSetup(int lengthMA = 34, int lengthSignal = 12)
|
|
{
|
|
this.lengthMA = lengthMA;
|
|
this.lengthSignal = lengthSignal;
|
|
}
|
|
|
|
public ImpulseMacdData AddDataPoint(double high, double low, double close, bool flag)
|
|
{
|
|
double src = (high + low + close) / 3.0;
|
|
if (flag)
|
|
{
|
|
srcList.Add(src);
|
|
highList.Add(high);
|
|
lowList.Add(low);
|
|
}
|
|
else
|
|
{
|
|
srcList[srcList.Count - 1] = src;
|
|
highList[highList.Count - 1] = high;
|
|
lowList[lowList.Count - 1] = low;
|
|
}
|
|
|
|
double smmaHigh = CalculateSMMA(highList, smmaHighList, lengthMA);
|
|
double smmaLow = CalculateSMMA(lowList, smmaLowList, lengthMA);
|
|
double zlema = CalculateZLEMA(srcList, zlemaList, lengthMA);
|
|
|
|
double md = 0.0;
|
|
if (zlema > smmaHigh) md = zlema - smmaHigh;
|
|
else if (zlema < smmaLow) md = zlema - smmaLow;
|
|
|
|
if (flag) mdList.Add(md);
|
|
else mdList[mdList.Count - 1] = md;
|
|
|
|
double sb = mdList.Skip(mdList.Count - lengthSignal).Average();
|
|
double sh = md - sb;
|
|
|
|
if (flag)
|
|
{
|
|
sbList.Add(sb);
|
|
shList.Add(sh);
|
|
}
|
|
else
|
|
{
|
|
sbList[sbList.Count - 1] = sb;
|
|
shList[shList.Count - 1] = sh;
|
|
}
|
|
|
|
if (mdList.Count < lengthSignal) return null;
|
|
|
|
if (mdList.Count > 100) mdList.RemoveRange(0, 50);
|
|
if (sbList.Count > 100) sbList.RemoveRange(0, 50);
|
|
if (shList.Count > 100) shList.RemoveRange(0, 50);
|
|
|
|
return new ImpulseMacdData { MD = md, SH = sh, SB = sb };
|
|
}
|
|
|
|
private double CalculateSMMA(List<double> src, List<double> smmaList, int len)
|
|
{
|
|
if (src.Count < len) return src.Last();
|
|
|
|
double smma;
|
|
if (smmaList.Count == 0)
|
|
smma = src.Skip(src.Count - len).Average();
|
|
else
|
|
smma = (smmaList.Last() * (len - 1) + src.Last()) / len;
|
|
|
|
smmaList.Add(smma);
|
|
return smma;
|
|
}
|
|
|
|
private double CalculateZLEMA(List<double> src, List<double> zlemaList, int length)
|
|
{
|
|
if (src.Count < length * 2) return src.Last();
|
|
|
|
var ema1 = CalculateEMA(src, length);
|
|
var ema2 = CalculateEMA(ema1, length);
|
|
double d = ema1.Last() - ema2.Last();
|
|
double zlema = ema1.Last() + d;
|
|
zlemaList.Add(zlema);
|
|
return zlema;
|
|
}
|
|
|
|
private List<double> CalculateEMA(List<double> src, int length)
|
|
{
|
|
List<double> ema = new List<double>();
|
|
double k = 2.0 / (length + 1);
|
|
ema.Add(src.Take(length).Average());
|
|
|
|
for (int i = length; i < src.Count; i++)
|
|
{
|
|
double value = src[i] * k + ema.Last() * (1 - k);
|
|
ema.Add(value);
|
|
}
|
|
return ema;
|
|
}
|
|
}
|