134 lines
3.9 KiB
C#
134 lines
3.9 KiB
C#
using BitgetApi.IndicatorData;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
|
|
namespace BitgetAPI.IndicatorConditionSetup
|
|
{
|
|
[Serializable]
|
|
public class ImpulseMacdConditionSetup
|
|
{
|
|
private int lengthMA;
|
|
private int lengthSignal;
|
|
|
|
private List<double> srcList = new List<double>();
|
|
private List<double> highList = new List<double>();
|
|
private List<double> lowList = new List<double>();
|
|
private List<double> smmaHighList = new List<double>();
|
|
private List<double> smmaLowList = new List<double>();
|
|
private List<double> zlemaList = new List<double>();
|
|
private List<double> mdList = new List<double>();
|
|
private List<double> sbList = new List<double>();
|
|
private List<double> shList = new List<double>();
|
|
|
|
public ImpulseMacdConditionSetup(int lengthMA = 26, 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;
|
|
}
|
|
|
|
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;
|
|
|
|
mdList.Add(md);
|
|
|
|
if (mdList.Count < lengthSignal)
|
|
return null;
|
|
|
|
double sb = mdList.Skip(mdList.Count - lengthSignal).Average();
|
|
double sh = md - sb;
|
|
|
|
sbList.Add(sb);
|
|
shList.Add(sh);
|
|
|
|
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;
|
|
}
|
|
}
|
|
} |