multiple timeframe sup

This commit is contained in:
Sewmina 2025-01-14 22:55:18 +05:30
parent 27594f73e1
commit bf83a4b912
9 changed files with 146 additions and 74 deletions

0
.editorconfig Normal file
View File

2
.gitignore vendored
View File

@ -400,5 +400,7 @@ FodyWeavers.xsd
*.sln.iml *.sln.iml
*.png *.png
Charts/*
Secrets.cs Secrets.cs
.aider*

View File

@ -1,4 +1,5 @@
using BinanceExchange.API.Client; using BinanceExchange.API.Client;
using BinanceExchange.API.Enums;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -11,14 +12,49 @@ namespace SignalsTest
{ {
private static BinanceClient m_client; private static BinanceClient m_client;
public static BinanceClient Client { get { if(m_client == null) public static BinanceClient Client
{
get
{
if (m_client == null)
{ {
m_client = new BinanceClient(new ClientConfiguration() m_client = new BinanceClient(new ClientConfiguration()
{ {
ApiKey = Secrets.BINANCE_API_PK, ApiKey = Secrets.BINANCE_API_PK,
SecretKey = Secrets.BINANCE_API_SK, SecretKey = Secrets.BINANCE_API_SK,
}); });
} return m_client; }
} } return m_client;
}
}
public static List<CoinWatch> watches = new List<CoinWatch>();
public static CoinWatch GetCoinWatch(string symbol, KlineInterval interval){
foreach(CoinWatch watch in watches){
if(watch.pair == symbol && watch.interval == interval){
return watch;
}
}
return watches[0];
}
public static CoinWatch GetCoinWatchLongest(string symbol){
CoinWatch match = watches[0];
foreach(CoinWatch watch in watches){
if(watch.pair == symbol){
if(match.pair != watch.pair){
match = watch;
}
if(Utils.GetMinutesForInterval(match.interval) < Utils.GetMinutesForInterval(watch.interval)){
match = watch;
}
}
}
return match;
}
} }
} }

View File

@ -24,6 +24,9 @@ namespace SignalsTest
public KlineInterval interval = KlineInterval.FifteenMinutes; public KlineInterval interval = KlineInterval.FifteenMinutes;
public List<KlineCandleStickResponse> candles=new List<KlineCandleStickResponse>(); public List<KlineCandleStickResponse> candles=new List<KlineCandleStickResponse>();
public List<TAReport> reports = new List<TAReport>(); public List<TAReport> reports = new List<TAReport>();
public List<decimal> resistancePoints = new List<decimal>();
public List<decimal> supportPoints = new List<decimal>();
public event EventHandler<BinanceTradeData> PriceUpdated; public event EventHandler<BinanceTradeData> PriceUpdated;
bool usingCache; bool usingCache;
public CoinWatch(string pair,int index, KlineInterval _interval = KlineInterval.FifteenMinutes , bool useCache=false) public CoinWatch(string pair,int index, KlineInterval _interval = KlineInterval.FifteenMinutes , bool useCache=false)
@ -98,6 +101,10 @@ namespace SignalsTest
reports.Add(report); reports.Add(report);
} }
resistancePoints =Confirmations.GetResistanceLevels(reports);
supportPoints = Confirmations.GetSupportiveLevels(reports);
Console.WriteLine($"Drawing chart for {reports.Count} candles, Coin: {symbol}, ceil:{max}, floor:{min}"); Console.WriteLine($"Drawing chart for {reports.Count} candles, Coin: {symbol}, ceil:{max}, floor:{min}");
// Console.WriteLine("Picasso did his job"); // Console.WriteLine("Picasso did his job");
@ -133,10 +140,10 @@ namespace SignalsTest
} }
if(triggers!= ""){ if(triggers!= ""){
Picasso.DrawChart(reports, max ,min, maxVol, symbol); Picasso.DrawChart(reports, max ,min, maxVol, symbol, interval);
string message = $"`{symbol}` {triggers} \nCurrent price: {reports[reports.Count-1].Close}"; string message = $"`{symbol}` [{Utils.GetMinutesForInterval(interval)}m] {triggers} \nCurrent price: {reports[reports.Count-1].Close}";
Messenger.instance.ScheduleMessage(message, symbol); Messenger.instance.ScheduleMessage(message, symbol, Utils.GetMinutesForInterval(interval).ToString());
} }
} }

View File

@ -1,39 +1,41 @@
using BinanceExchange.API.Enums;
public static class CoinsList{ public static class CoinsList{
public static List<string> symbols= [ public static Dictionary<string, List<KlineInterval>> symbols = new Dictionary<string, List<KlineInterval>> {
"BTCUSDT", { "BTCUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ADAUSDT", { "ADAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"AIXBTUSDT", { "AIXBTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"XRPUSDT", { "XRPUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"XLMUSDT", { "XLMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"SOLUSDT", { "SOLUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"AVAXUSDT", { "AVAXUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ENAUSDT", { "ENAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"HIVEUSDT", { "HIVEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"STEEMUSDT", { "STEEMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"MOVEUSDT", { "MOVEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"DOGEUSDT", { "DOGEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"PEPEUSDT", { "PEPEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ACTUSDT", { "ACTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"STGUSDT", { "STGUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ONEUSDT", { "ONEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"LINKUSDT", { "LINKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ARUSDT", { "ARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"RUNEUSDT", { "RUNEUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"USUALUSDT", { "USUALUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ZKUSDT", { "ZKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"JUPUSDT", { "JUPUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"LUNAUSDT", { "LUNAUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"DUSKUSDT", { "DUSKUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"SUIUSDT", { "SUIUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"INJUSDT", { "INJUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"FILUSDT", { "FILUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"GRTUSDT", { "GRTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"HBARUSDT", { "HBARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"CFXUSDT", { "CFXUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"TLMUSDT", { "TLMUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"NEARUSDT", { "NEARUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"FORTHUSDT", { "FORTHUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"ETHUSDT", { "ETHUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] },
"PNUTUSDT" { "PNUTUSDT", [KlineInterval.FifteenMinutes, KlineInterval.OneHour] }
]; };
} }

7
CustomTypes.cs Normal file
View File

@ -0,0 +1,7 @@
public class MessageQueueItem{
public string symbol;
public string interval;
public string filename=>"Charts/"+symbol+interval+".png";
public string text;
}

View File

@ -23,10 +23,14 @@ namespace SignalsTest
public const string chatId = "@doralockscryptosignals"; public const string chatId = "@doralockscryptosignals";
public const string chatId_test = "@SignalTestPrivate"; public const string chatId_test = "@SignalTestPrivate";
public Dictionary<string,string> messagesSchedule = new Dictionary<string, string>(); public List<MessageQueueItem> messagesSchedule = new List<MessageQueueItem>();
public void ScheduleMessage(string text, string filename=""){ public void ScheduleMessage(string text, string symbol="", string interval=""){
messagesSchedule.Add(text,filename); messagesSchedule.Add(new MessageQueueItem(){
symbol = symbol,
interval=interval,
text=text
});
} }
public async void InitializeScheduler(){ public async void InitializeScheduler(){
@ -39,25 +43,26 @@ namespace SignalsTest
continue; continue;
} }
string message = messagesSchedule.Keys.ElementAt(0); MessageQueueItem queueItem = messagesSchedule[0];
string filename = messagesSchedule[message]; string message = queueItem.text;
string filename = queueItem.filename;
string symbol = queueItem.symbol;
try{ try{
if(filename.Length < 2){ if(symbol.Length < 2){
await botClient.SendTextMessageAsync(_chatId, message); await botClient.SendTextMessageAsync(_chatId, message);
}else{ }else{
FileStream fsSource = new FileStream($"{filename}.png", FileMode.Open, FileAccess.Read); FileStream fsSource = new FileStream(filename, FileMode.Open, FileAccess.Read);
InputFile photo = InputFile.FromStream(fsSource); InputFile photo = InputFile.FromStream(fsSource);
string url = $"https://www.tradingview.com/chart/?symbol=BINANCE%3A{filename}"; string url = $"https://www.tradingview.com/chart/?symbol=BINANCE%3A{symbol}";
// string formattedMessage = message.Replace($"`{filename}`", $"`{filename}`[Trading View]({url})"); // string formattedMessage = message.Replace($"`{filename}`", $"`{filename}`[Trading View]({url})");
string formattedMessage = message.Replace( string formattedMessage = message.Replace(
$"`{filename}`", $"`{symbol}`",
$"<a href=\"{url}\">{filename}</a>" $"<a href=\"{url}\">{symbol}</a>"
); );
await botClient.SendPhotoAsync(_chatId, photo,caption: formattedMessage,parseMode: ParseMode.Html); await botClient.SendPhotoAsync(_chatId, photo,caption: formattedMessage,parseMode: ParseMode.Html);
} }
messagesSchedule.Remove(message); messagesSchedule.Remove(queueItem);
}catch(Exception e){ }catch(Exception e){
Console.WriteLine($"Error occured while sending {message} to {filename}"); Console.WriteLine($"Error occured while sending {message} to {filename}");
Console.WriteLine(e.ToString()); Console.WriteLine(e.ToString());

View File

@ -8,12 +8,13 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Diagnostics; using System.Diagnostics;
using BinanceExchange.API.Enums;
public class Picasso{ public class Picasso{
public static void DrawChart(List<TAReport> reports, decimal max, decimal min, decimal volMax, string filename="test"){ public static void DrawChart(List<TAReport> reports, decimal max, decimal min, decimal volMax, string filename="test", KlineInterval interval = KlineInterval.FifteenMinutes){
// float height = (float)Math.Ceiling(max - min) * 2f; // float height = (float)Math.Ceiling(max - min) * 2f;
// float width = ((float)height / 9f) * 16f; // float width = ((float)height / 9f) * 16f;
decimal heightRange = max-min; decimal heightRange = max-min;
@ -125,15 +126,16 @@ public class Picasso{
#endregion #endregion
#region LINES #region LINES
List<decimal> resistancePoints = Confirmations.GetResistanceLevels(reports);
foreach(decimal point in resistancePoints){ CoinWatch longestWatch = Brian.GetCoinWatchLongest(filename);
foreach(decimal point in longestWatch.resistancePoints){
float yVal = ((float)(point-min) * heightMultiplier) + candlesOffset; float yVal = ((float)(point-min) * heightMultiplier) + candlesOffset;
// Console.WriteLine($"{filename} res at {yVal/height}"); // Console.WriteLine($"{filename} res at {yVal/height}");
img.Mutate(ctx=> ctx.DrawLine(Color.Red,1f, [new PointF(0, yVal), new PointF(width, yVal)])); img.Mutate(ctx=> ctx.DrawLine(Color.Red,1f, [new PointF(0, yVal), new PointF(width, yVal)]));
} }
List<decimal> supPoints = Confirmations.GetSupportiveLevels(reports); foreach(decimal point in longestWatch.supportPoints){
foreach(decimal point in supPoints){
float yVal = ((float)(point-min) * heightMultiplier) + candlesOffset; float yVal = ((float)(point-min) * heightMultiplier) + candlesOffset;
// Console.WriteLine($"{filename} sup at {yVal/height}"); // Console.WriteLine($"{filename} sup at {yVal/height}");
img.Mutate(ctx=> ctx.DrawLine(Color.Green,1f, [new PointF(0, yVal), new PointF(width, yVal)])); img.Mutate(ctx=> ctx.DrawLine(Color.Green,1f, [new PointF(0, yVal), new PointF(width, yVal)]));
@ -150,7 +152,6 @@ public class Picasso{
IPath stochFast = GetPath(reports, "Stochastic", widthMultiplier, (float)volumeHeightMultiplier/100f, 0, 0); IPath stochFast = GetPath(reports, "Stochastic", widthMultiplier, (float)volumeHeightMultiplier/100f, 0, 0);
IPath stochK3 = GetPath(reports, "StochasticK3", widthMultiplier, (float)volumeHeightMultiplier/100f, 0, 0); IPath stochK3 = GetPath(reports, "StochasticK3", widthMultiplier, (float)volumeHeightMultiplier/100f, 0, 0);
IPath stPath = GetPath(reports, "ST", widthMultiplier,(float)heightMultiplier, (float)min, candlesOffset); IPath stPath = GetPath(reports, "ST", widthMultiplier,(float)heightMultiplier, (float)min, candlesOffset);
#endregion #endregion
//NewChart //NewChart
@ -161,6 +162,7 @@ public class Picasso{
throw new Exception($"Couldn't find font {TextFont}"); throw new Exception($"Couldn't find font {TextFont}");
var font = fontFamily.CreateFont(TextFontSize, FontStyle.Regular); var font = fontFamily.CreateFont(TextFontSize, FontStyle.Regular);
int intervalInMins = Utils.GetMinutesForInterval(interval);
img.Mutate(ctx => ctx.Draw(Color.Yellow, 2, sma20Path). img.Mutate(ctx => ctx.Draw(Color.Yellow, 2, sma20Path).
Draw(Color.Purple, 2, sma50Path). Draw(Color.Purple, 2, sma50Path).
@ -169,9 +171,9 @@ public class Picasso{
Draw(Color.Cyan, 3,stochFast). Draw(Color.Cyan, 3,stochFast).
Draw(Color.Orange, 3, stochK3). Draw(Color.Orange, 3, stochK3).
Flip(FlipMode.Vertical). Flip(FlipMode.Vertical).
DrawText(filename, font,new Color(Rgba32.ParseHex("#FFFFFF")), new PointF(10,10))); DrawText($"{filename}- {intervalInMins}m", font,new Color(Rgba32.ParseHex("#FFFFFF")), new PointF(10,10)));
img.Save($"{filename}.png"); img.Save($"Charts/{filename}{intervalInMins}.png");
} }
} }

View File

@ -1,20 +1,31 @@
using BinanceExchange.API.Models.WebSocket; using BinanceExchange.API.Enums;
using BinanceExchange.API.Models.WebSocket;
using SignalsTest; using SignalsTest;
class Program class Program
{ {
static ManualResetEvent _quitEvent = new ManualResetEvent(false); static ManualResetEvent _quitEvent = new ManualResetEvent(false);
static List<CoinWatch> watches = new List<CoinWatch>();
private static void Main(string[] args) private static void Main(string[] args)
{ {
Console.WriteLine("Initializing Messiah"); Console.WriteLine("Initializing Messiah");
Messenger.instance.ScheduleMessage("Rebooted bot"); Messenger.instance.ScheduleMessage("Rebooted bot");
for (int i=0; i < CoinsList.symbols.Count; i++){ // for (int i=0; i < CoinsList.symbols.Count; i++){
CoinWatch btcWatch = new CoinWatch(CoinsList.symbols[i], i); // CoinWatch btcWatch = new CoinWatch(CoinsList.symbols[i], i);
btcWatch.PriceUpdated += CoinWatch_OnPriceUpdate; // btcWatch.PriceUpdated += CoinWatch_OnPriceUpdate;
watches.Add(btcWatch); // watches.Add(btcWatch);
// }
Brian.watches = new List<CoinWatch>();
int i=0;
foreach(KeyValuePair<string, List<KlineInterval>> symbol in CoinsList.symbols){
foreach(KlineInterval interval in symbol.Value){
CoinWatch btcWatch = new CoinWatch(symbol.Key, i, interval);
btcWatch.PriceUpdated += CoinWatch_OnPriceUpdate;
Brian.watches.Add(btcWatch);
i++;
}
} }
CheckSuccess(); CheckSuccess();
_quitEvent.WaitOne(); _quitEvent.WaitOne();
@ -22,17 +33,17 @@ class Program
async static void CheckSuccess(){ async static void CheckSuccess(){
await Task.Delay(120000); await Task.Delay(160000);
List<string> failedList = new List<string>(); List<string> failedList = new List<string>();
string commasList = ""; string commasList = "";
foreach(CoinWatch coin in watches){ foreach(CoinWatch coin in Brian.watches){
if(!coin.kickstarted){ if(!coin.kickstarted){
failedList.Add(coin.pair); failedList.Add(coin.pair);
commasList += coin.pair + ", "; commasList += $"{coin.pair}[{coin.interval}]" + ", ";
} }
} }
string msg = $"Reboot complete: {failedList.Count} Failed out of {watches.Count}. Failed list: \n{commasList}"; string msg = $"Reboot complete: {failedList.Count} Failed out of {Brian.watches.Count}. Failed list: \n{commasList}";
Console.WriteLine(msg); Console.WriteLine(msg);
Messenger.instance.ScheduleMessage(msg); Messenger.instance.ScheduleMessage(msg);
} }