vwap added

This commit is contained in:
Sewmina 2025-03-18 12:34:30 +05:30
parent 3219c51be3
commit 2007117dee
6 changed files with 220 additions and 57 deletions

View File

@ -78,6 +78,8 @@ namespace SignalsTest
if (Utils.GetMinutesForInterval(interval) > 50)
{
rounds = 10;
}else if(Utils.GetMinutesForInterval(interval) > 5){
rounds = 5;
}
for (int i = 0; i < rounds; i++)
@ -148,6 +150,11 @@ namespace SignalsTest
resistancePoints = Confirmations.GetResistanceLevels(reports,SMA:lineCalSMA);
supportPoints = Confirmations.GetSupportiveLevels(reports, SMA:lineCalSMA);
for(int i=0; i < reports.Count;i++){
reports[i].isBullFlag = Confirmations.IsBullFlag(reports, i);
reports[i].RelativeVolumeIndex = Confirmations.GetRelativeVolumeIndex(reports,i);
}
Console.WriteLine($"Drawing chart for {reports.Count} candles, Coin: {symbol}, ceil:{max}, floor:{min}");
// Console.WriteLine("Picasso did his job");
@ -192,7 +199,9 @@ namespace SignalsTest
if(reports[reports.Count-2].isInverseHammer){
triggers+=$"Inverse Hammer candle appeared\n";
}
// if(reports[reports.Count-2].isBullFlag){
// triggers+=$"Possible Bull Flag\n";
// }
if (triggers != "")
{
List<TAReport> limitedReports = new List<TAReport>(reports);

View File

@ -5,37 +5,37 @@ public static class CoinsList{
{ "BTCUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ADAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "AIXBTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "XRPUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "XLMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "SOLUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "AVAXUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ENAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "HIVEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "STEEMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "MOVEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "DOGEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "PEPEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ACTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "STGUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ONEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "LINKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "RUNEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "USUALUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ZKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "JUPUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "LUNAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "DUSKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "SUIUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "INJUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "FILUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "GRTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "HBARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "CFXUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "TLMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "NEARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "FORTHUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "ETHUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
{ "PNUTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] }
// { "XRPUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "XLMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "SOLUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "AVAXUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "ENAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "HIVEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "STEEMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "MOVEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "DOGEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "PEPEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "ACTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "STGUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "ONEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "LINKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "ARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "RUNEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "USUALUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "ZKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "JUPUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "LUNAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "DUSKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "SUIUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "INJUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "FILUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "GRTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "HBARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "CFXUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "TLMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "NEARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "FORTHUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "ETHUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] },
// { "PNUTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour, KlineInterval.OneDay, KlineInterval.OneWeek] }
};
}

View File

@ -156,4 +156,59 @@ public static class Confirmations
return formattedResistances;
}
public static float GetRelativeVolumeIndex(List<TAReport> reports, int currentIndex){
decimal totalVolume = 0;
foreach(TAReport report in reports){
totalVolume+=report.candle.Volume;
}
float avgVol = (float)totalVolume/(float)reports.Count;
return (float)reports[currentIndex].candle.Volume / avgVol;
}
public static bool IsBullFlag(List<TAReport> reports, int currentIndex, int lookbackPeriod = 20)
{
if (currentIndex < lookbackPeriod) return false;
// Find the flagpole
decimal highestPoint = 0;
decimal lowestPoint = decimal.MaxValue;
int highestPointIndex = 0;
// Look for a sharp upward move (flagpole)
for (int i = currentIndex - lookbackPeriod; i <= currentIndex; i++)
{
if (reports[i].candle.High > highestPoint)
{
highestPoint = reports[i].candle.High;
highestPointIndex = i;
}
if (reports[i].candle.Low < lowestPoint)
{
lowestPoint = reports[i].candle.Low;
}
}
// Calculate flagpole height
decimal flagpoleHeight = highestPoint - lowestPoint;
if (flagpoleHeight / lowestPoint < 0.03m) return false; // Minimum 3% move
// Check for consolidation pattern after flagpole
decimal upperTrendStart = highestPoint;
decimal lowerTrendStart = reports[highestPointIndex].candle.Low;
decimal upperTrendEnd = reports[currentIndex].candle.High;
decimal lowerTrendEnd = reports[currentIndex].candle.Low;
// Verify parallel downward sloping trend lines
bool isDownwardSloping = upperTrendEnd < upperTrendStart && lowerTrendEnd < lowerTrendStart;
bool isParallel = Math.Abs((upperTrendEnd - upperTrendStart) - (lowerTrendEnd - lowerTrendStart)) / flagpoleHeight < 0.2m;
// Volume should typically decrease during flag formation
bool isVolumeDecreasing = reports[currentIndex].candle.Volume < reports[highestPointIndex].candle.Volume;
return isDownwardSloping && isParallel && isVolumeDecreasing;
}
}

View File

@ -1,4 +1,5 @@
using BinanceExchange.API.Models.Response;
using System.Diagnostics;
using BinanceExchange.API.Models.Response;
public static class Indicators
{
@ -114,24 +115,75 @@ public static class Indicators
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;
public static decimal getVwapWeekly(List<KlineCandleStickResponse> responses, int index){
if(index < 15){return 0;}
decimal f =(1.0m+(avgGain/(avgLoss==0 ? 1: avgLoss))); //Avoiding dividing by 0
if(f<=0){return 0;}
return 100.0m - (100.0m/f);
decimal cumPrice = 0;
decimal cumVolume = 0;
for(int i=index; i > 0; i--){
decimal typicalPrice = (responses[i].High + responses[i].Low + responses[i].Close) / 3;
cumPrice += typicalPrice * responses[i].Volume;
cumVolume += responses[i].Volume;
if(responses[i].CloseTime.DayOfWeek == DayOfWeek.Sunday && responses[i].CloseTime.Hour == 23 && responses[i].CloseTime.Minute == 59){
break;
}
}
return cumPrice/ cumVolume;
}
public static decimal getVwapMonthly(List<KlineCandleStickResponse> responses, int index){
if(index < 15){return 0;}
decimal cumPrice = 0;
decimal cumVolume = 0;
for(int i=index; i > 0; i--){
decimal typicalPrice = (responses[i].High + responses[i].Low + responses[i].Close) / 3;
cumPrice += typicalPrice * responses[i].Volume;
cumVolume += responses[i].Volume;
if(responses[i].CloseTime.Date.Day == 1 && responses[i].OpenTime.Hour == 0 && responses[i].OpenTime.Minute == 0){
break;
}
}
return cumPrice/ cumVolume;
}
public static decimal getRSI(List<KlineCandleStickResponse> responses, int index, int period = 14)
{
decimal avgGain = 0;
decimal avgLoss = 0;
if (index < period)
{
return 0;
}
for (int i = index; i > index - period; i--)
{
decimal change = responses[i].Close - responses[i - 1].Close;
if (change > 0)
{
avgGain += change;
}
else
{
avgLoss += Math.Abs(change);
}
}
avgGain /= period;
avgLoss /= period;
if (avgLoss == 0)
{
return 100; // If there's no loss, RSI is 100
}
decimal rs = avgGain / avgLoss;
decimal rsi = 100 - (100 / (1 + rs));
return rsi;
}
public static bool didMACDLineCrossSignalLine(decimal[] MACDs, decimal[] Signals, int index, int period = 7, decimal threshold = (decimal)0.1)
{

View File

@ -76,12 +76,15 @@ public class Picasso{
volumePoints[0] = new PointF(i * widthMultiplier, height);
volumePoints[1] = new PointF(i * widthMultiplier, height - ((float)reports[i].candle.Volume / (float)volMax) * volumeHeightMultiplier);
Color candleColor = reports[i].candle.Close > reports[i].candle.Open ? Color.Green : Color.Red;
Color candleColor = reports[i].candle.Close > reports[i].candle.Open ? Color.Green : Color.Red; // Traditional Bar
Color rsiColor = reports[i].RSI50 > 50 ? Color.Green : Color.Red; // RSI Bar
// Console.WriteLine(reports[i].RSI);
img.Mutate(ctx=> ctx.
DrawLine(candleColor, 10, points).
DrawLine(candleColor, 3, rangePoints).
DrawLine(candleColor, 10, volumePoints)
DrawLine(candleColor, 10, points).
DrawLine(rsiColor, 8, points).
DrawLine(candleColor, (reports[i].RelativeVolumeIndex > 1 ? 12: 5), volumePoints)
);
#endregion
@ -156,6 +159,34 @@ public class Picasso{
PointF squarePosition = new PointF(i * widthMultiplier - squareSize/2, highVal + 50);
img.Mutate(ctx => ctx.Fill(Color.White, new RectangleF(squarePosition, new SizeF(squareSize, squareSize))));
}
// if (reports[i].isBullFlag)
// {
// // Draw a flag symbol
// float flagWidth = 10f;
// float flagHeight = 15f;
// float poleHeight = 25f;
// // Position flag below the candle
// PointF flagBasePosition = new PointF(i * widthMultiplier, lowVal + 10);
// // Draw flag pole
// img.Mutate(ctx => ctx.DrawLine(
// Color.White,
// 1f,
// new PointF(flagBasePosition.X, flagBasePosition.Y),
// new PointF(flagBasePosition.X, flagBasePosition.Y - poleHeight)
// ));
// // Draw flag triangle
// PointF[] flagPoints = new PointF[] {
// new PointF(flagBasePosition.X, flagBasePosition.Y - poleHeight),
// new PointF(flagBasePosition.X + flagWidth, flagBasePosition.Y - poleHeight + flagHeight/2),
// new PointF(flagBasePosition.X, flagBasePosition.Y - poleHeight + flagHeight)
// };
// img.Mutate(ctx => ctx.DrawPolygon(Color.White, 1f, flagPoints));
// }
}
// Console.WriteLine("Getting paths");
// object t = GetPropByName(reports[reports.Count- 1], "SMA7");
@ -201,6 +232,8 @@ public class Picasso{
IPath sma20Path = GetPath(reports, "SMA20", widthMultiplier, (float)heightMultiplier, (float)min, candlesOffset);
IPath sma50Path = GetPath(reports, "SMA50", widthMultiplier, (float)heightMultiplier, (float)min, candlesOffset);
IPath sma200Path = GetPath(reports, "SMA200", widthMultiplier, (float)heightMultiplier, (float)min, candlesOffset);
IPath vWapWeeklyPath = GetPath(reports, (Utils.GetMinutesForInterval(interval) > 60? "VwapMonthly" : "VwapWeekly") , widthMultiplier, (float)heightMultiplier, (float)min, candlesOffset);
IPath stochFast = GetPath(reports, "Stochastic", widthMultiplier, (float)volumeHeightMultiplier/100f, 0);
IPath stochK3 = GetPath(reports, "StochasticK3", widthMultiplier, (float)volumeHeightMultiplier/100f, 0);
@ -212,10 +245,12 @@ public class Picasso{
int intervalInMins = Utils.GetMinutesForInterval(interval);
string intervalText = intervalInMins > (60 * 23) ? $"{intervalInMins/(60*24)}D" : $"{intervalInMins}m";
img.Mutate(ctx => ctx.Draw(Color.Yellow, 2, sma20Path).
Draw(Color.Purple, 2, sma50Path).
Draw(Color.Cyan, 2, sma200Path).
Draw(Color.Green, 3, stPath).
img.Mutate(ctx => ctx.
// Draw(Color.Yellow, 2, sma20Path).
// Draw(Color.Purple, 2, sma50Path).
// Draw(Color.Cyan, 2, sma200Path).
Draw(Color.DarkRed,5, vWapWeeklyPath).
// Draw(Color.Green, 3, stPath).
Draw(Color.Cyan, 3,stochFast).
Draw(Color.Orange, 3, stochK3).
DrawText($"{filename}- {intervalText}", titleFont,new Color(Rgba32.ParseHex("#FFFFFF")), new PointF(10,10)));

View File

@ -33,19 +33,27 @@ namespace SignalsTest
public decimal ATR10;
public decimal AVGDiff = 0;
public decimal VwapWeekly=0;
public decimal VwapMonthly = 0;
public decimal STHigh;
public decimal STLow;
public decimal ST;
public decimal RSI = 0;
public decimal RSI50 = 0;
public int TWS =0;
public int TBC = 0;
public bool isHammer,isInverseHammer = false;
public bool isBullFlag =false;
public decimal Stochastic = 0;
public decimal StochasticK3 = 0;
public float RelativeVolumeIndex = 0;
public bool STUp = false;
public bool TGOR=false;
@ -79,6 +87,7 @@ namespace SignalsTest
report.MACD = Indicators.getMACD(response, 12, 26, index);
report.RSI = Indicators.getRSI(response, index);
report.RSI50 = Indicators.getRSI(response, index, 50);
if (history == null)
{
@ -100,6 +109,9 @@ namespace SignalsTest
report.ATR10 = Indicators.getATR(response, 10, index, ATR10History);
report.ATR14 = Indicators.getATR(response, 14, index, ATR14History);
report.VwapWeekly = Indicators.getVwapWeekly(response, index);
report.VwapMonthly = Indicators.getVwapMonthly(response, index);
// SuperTrend Multiplier
decimal multiplier = 3;