coin_alerts/Indicators.cs
2025-01-13 11:21:07 +05:30

200 lines
7.0 KiB
C#

using BinanceExchange.API.Models.Response;
public static class Indicators
{
public static decimal getSMA(List<KlineCandleStickResponse> responses, int curIndex, int interval, int startIndex = 0)
{
// curIndex = Math.Clamp(curIndex,0, responses.Count);
// decimal total = 0;
// for(int i=curIndex-interval; i < curIndex; i++){
// total += responses[i].Close;
// }
// // decimal length = (curIndex-startIndex); if(length <= 0){length=1;}
// // decimal N = (length / (decimal)interval);
// Console.WriteLine($"SMA Cacl ({interval}) : {total}/{interval} = {total/interval}");
// return total / interval;
decimal total = 0;
for (int x = (curIndex > 1500) ? 1500 : 0; x < interval; x++)
{
total += (curIndex - x >= 0) ? responses[curIndex - x].Close : (decimal)0;
}
return total / (decimal)interval;
}
public static decimal getSMA(List<decimal> responses, int curIndex, int interval, int startIndex = 0)
{
decimal total = 0;
for (int x = (curIndex > 1500) ? 1500 : 0; x < interval; x++)
{
total += (curIndex - x >= 0) ? responses[curIndex - x] : (decimal)0;
}
return total / (decimal)interval;
}
public static decimal getEMA(List<KlineCandleStickResponse> responses, int curIndex, int startIndex, int periods, decimal? prevEma = null)
{
if (curIndex < 1) { return 0; }
if (startIndex - curIndex > 1500) { return 0; }; if (curIndex >= responses.Count) { return 0; };
// decimal N = (decimal)curIndex / (decimal)periods;
decimal multiplier = (decimal)2 / ((decimal)(periods + 1));
decimal firstHalf = responses[curIndex].Close * multiplier; //First half of the equation
decimal secondHalf = getEMA(responses, curIndex - 1, startIndex, periods) * (1 - multiplier); //Second half of the equation
// decimal secondHalf = (prevEma ?? getSMA(responses, curIndex-1, periods)) * (1- multiplier); //Second half of the equation
return firstHalf + secondHalf;
}
public static decimal getEMA(List<decimal> responses, int curIndex, int startIndex, int periods)
{
if (curIndex < 1) { return 0; }
if (startIndex - curIndex > 1500) { return 0; };
if (curIndex >= responses.Count) { return 0; };
// decimal N = (decimal)curIndex / (decimal)periods;
decimal multiplier = (decimal)2 / ((decimal)(periods + 1));
decimal firstHalf = responses[curIndex] * multiplier; //First half of the equation
decimal secondHalf = getEMA(responses, curIndex - 1, startIndex, periods) * (1 - multiplier); //Second half of the equation
// decimal secondHalf = (prevEma ?? getSMA(responses, curIndex-1, periods)) * (1- multiplier); //Second half of the equation
return firstHalf + secondHalf;
}
public static decimal getMACD(List<KlineCandleStickResponse> responses, int shortPeriod, int longPeriod, int curIndex)
{
return getEMA(responses, curIndex, curIndex, shortPeriod) - getEMA(responses, curIndex, curIndex, longPeriod);
}
public static decimal getATR(List<KlineCandleStickResponse> responses, int period, int curIndex, List<decimal> prevATRs)
{
if (curIndex <= 0 || curIndex > responses.Count) { return 0; }
if (curIndex >= responses.Count) { return 0; };
decimal TR = responses[curIndex].High - responses[curIndex].Low;
if (curIndex > 1)
{
decimal tr2 = responses[curIndex].High - responses[curIndex - 1].Close;
decimal tr3 = responses[curIndex].Low - responses[curIndex - 1].Close;
if (tr2 > TR)
{
TR = tr2;
}
if (tr3 > TR)
{
TR = tr3;
}
}
if (curIndex < period)
{
//get just the TR
return TR;
}
decimal prevATR = 0;
if (prevATRs.Count > 0)
{
// int start = curIndex - period;
// for (int i = start; i < curIndex; i++)
// {
// prevATR += prevATRs[i];
// }
// prevATR = (prevATR) / (decimal)(curIndex-start);
prevATR = prevATRs[curIndex - 1];
}
decimal ATR = (decimal)((prevATR * (decimal)(period - 1)) + TR) / (decimal)period;
return ATR;
}
public static decimal getRSI(List<KlineCandleStickResponse> responses, int index, int period = 14){
decimal avgGain = 0;
decimal avgLoss =0;
if(index < 2){return 0;}
int length = 0;
for(int i=index; i > index - period && i > 0; i--){
length++;
avgGain += responses[i].Close - responses[i-1].Close;
avgLoss += responses[i-1].Close - responses[i].Close;
}
if(length <=0){return 0;}
avgGain /= length;
avgLoss /= length;
decimal f =(1.0m+(avgGain/(avgLoss==0 ? 1: avgLoss))); //Avoiding dividing by 0
if(f<=0){return 0;}
return 100.0m - (100.0m/f);
}
public static bool didMACDLineCrossSignalLine(decimal[] MACDs, decimal[] Signals, int index, int period = 7, decimal threshold = (decimal)0.1)
{
int counter = 0;
if (index >= MACDs.Length || index >= Signals.Length) { return false; }
if (index - period < 0) { return false; };
for (int i = index; i > index - period; i--)
{
if (MACDs[i] < Signals[i])
{
counter++;
}
}
bool wasMACDUnder = counter > ((float)period / 2f);
return wasMACDUnder && MACDs[index] > Signals[index];
}
public static decimal getAvgDiff(List<KlineCandleStickResponse> responses, int i)
{
decimal avgDiff = 0;
if (i > 10)
{
for (int k = 1; k < 6; k++)
{
avgDiff += responses[i - k].Close;
}
avgDiff = avgDiff / (decimal)5;
avgDiff = responses[i].Close - avgDiff;
}
return avgDiff;
}
public static decimal getStochastic(List<KlineCandleStickResponse> responses, int i, int length = 14){
if(i < 20){
return 0;
}
decimal highest = 0;
decimal lowest = 1000000000000000;
for(int k =0; k < length; k++){
if(responses[i-k].Low < lowest){
lowest = responses[i-k].Low;
}
if(responses[i-k].High > highest){
highest = responses[i-k].High;
}
}
decimal topHalf = responses[i].Close - lowest;
decimal botHalf = highest - lowest;
return (topHalf /botHalf) * 100;
}
public static decimal getStochasticMA(List<KlineCandleStickResponse> responses, int i, int length = 14, int period = 3){
decimal total = 0;
for(int k =0; k < period; k++){
total += getStochastic(responses, i-k);
}
return total / period;
}
}