coin_alerts/CoinWatch.cs

231 lines
7.8 KiB
C#

using BinanceExchange.API.Client;
using BinanceExchange.API.Enums;
using BinanceExchange.API.Models.Request;
using BinanceExchange.API.Models.Response;
using BinanceExchange.API.Models.WebSocket;
using BinanceExchange.API.Websockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace SignalsTest
{
public class CoinWatch
{
public bool kickstarted = false;
public string pair;
public int index;
public KlineInterval interval = KlineInterval.FifteenMinutes;
public List<KlineCandleStickResponse> candles = new List<KlineCandleStickResponse>();
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;
bool usingCache;
public CoinWatch(string pair, int index, KlineInterval _interval = KlineInterval.FifteenMinutes, bool useCache = false)
{
this.pair = pair;
this.index = index;
interval = _interval;
usingCache = useCache;
Init();
}
void Init()
{
if (usingCache)
{
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "/" + pair + ".txt"))
{
try
{
}
catch
{
}
}
}
// InitLivestream();
KeepUpdatingCandles();
// TestCallbacks();
}
async void TestCallbacks()
{
while (true)
{
await Task.Delay(1000);
PriceUpdated?.Invoke(this, new BinanceTradeData() { BestAskPrice = 0 });
}
}
async Task UpdateCandles()
{
candles = new List<KlineCandleStickResponse>();
int rounds = 1;
int candleLimit = 150;
int intervalInMinutes = Utils.GetMinutesForInterval(interval);
if (Utils.GetMinutesForInterval(interval) > 50)
{
rounds = 10;
}
for (int i = 0; i < rounds; i++)
{
DateTime startTime = DateTime.Now.AddMinutes(-intervalInMinutes * candleLimit * (rounds-i));
DateTime endTime = startTime.AddMinutes(intervalInMinutes * candleLimit);
GetKlinesCandlesticksRequest req = new GetKlinesCandlesticksRequest
{
Interval = interval,
Symbol = pair,
StartTime = startTime,
EndTime = endTime,
Limit = candleLimit
};
// Calculate and set the start time for this request
req.StartTime = req.EndTime.Value.AddMinutes(-intervalInMinutes * candleLimit);
Console.WriteLine($"Fetching kandles for {req.Symbol} (Round {i + 1}/{rounds}): {candles.Count} candles retrieved so far.");
var response = await Brian.Client.GetKlinesCandlesticks(req);
candles.AddRange(response);
// Update endTime for the next round
endTime = req.StartTime.Value;
// Respect the API rate limit
await Task.Delay(1500);
}
Console.WriteLine($"Completed fetching kandles. Total candles retrieved from {candles[0].OpenTime} to {candles[candles.Count-1].OpenTime}");
kickstarted = true;
Analyze(pair);
}
async void Analyze(string symbol)
{
int[] mas = new int[] { 7, 12, 25 };
reports = new List<TAReport>();
decimal max = 0;
decimal min = 100000000;
decimal maxVol = 0;
if(candles.Count < 100){return;}
for (int i = 0; i < candles.Count; i++)
{
TAReport report = TAReport.Generate(pair, Utils.GetMinutesForInterval(interval), candles, i, reports);
if (candles[i].Close > max)
{
max = candles[i].Close;
}
if (candles[i].Close < min)
{
min = candles[i].Close;
}
if (candles[i].Volume > maxVol)
{
maxVol = candles[i].Volume;
}
reports.Add(report);
}
string lineCalSMA = "SMA20";
if(interval!=KlineInterval.FifteenMinutes){
lineCalSMA= "SMA50";
}
resistancePoints = Confirmations.GetResistanceLevels(reports,SMA:lineCalSMA);
supportPoints = Confirmations.GetSupportiveLevels(reports, SMA:lineCalSMA);
Console.WriteLine($"Drawing chart for {reports.Count} candles, Coin: {symbol}, ceil:{max}, floor:{min}");
// Console.WriteLine("Picasso did his job");
// Console.WriteLine(reports[reports.Count-1].toJson());
bool isStSwitch = false;
for (int i = 0; i < 2; i++)
{
bool _isStSwitch = reports[reports.Count - 1 - i].STUp != reports[reports.Count - i - 2].STUp;
if (_isStSwitch)
{
isStSwitch = true;
break;
}
}
string triggers = "";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
triggers += "test";
}
// if(isStSwitch){
// triggers += "Switched SuperTrend\n";
// }
// if(reports[reports.Count-1].TGOR && !reports[reports.Count-2].TGOR){//Ignore if two in row
// triggers += "Price dropped\n";
// }
if (reports[reports.Count - 2].TWS > 1)
{
triggers += $"Three White Soldiers appeared";
}
if (reports[reports.Count - 2].TBC > 1)
{
triggers += $"Three Black Crows appeared";
}
if (triggers != "")
{
List<TAReport> limitedReports = new List<TAReport>(reports);
if(limitedReports.Count> 200){
limitedReports.RemoveRange(0,limitedReports.Count-150);
}
Picasso.DrawChart(limitedReports, symbol, interval);
string message = $"`{symbol}` [{Utils.GetMinutesForInterval(interval)}m] {triggers} \nCurrent price: {reports[reports.Count - 1].Close}";
Messenger.instance.ScheduleMessage(message, symbol, Utils.GetMinutesForInterval(interval).ToString());
}
}
async void KeepUpdatingCandles()
{
int delay = (index * 500);
await Task.Delay(delay);
UpdateCandles();
while (true)
{
await Task.Delay(60000 + delay);
Console.WriteLine($"Loop call, ({index}) , {DateTime.Now.Minute} = {DateTime.Now.Minute % Utils.GetMinutesForInterval(interval)} ");
if (DateTime.Now.Minute % Utils.GetMinutesForInterval(interval) == 0) { UpdateCandles(); }
}
}
void InitLivestream()
{
var manualWebsocket = new InstanceBinanceWebSocketClient(Brian.Client);
var socketId = manualWebsocket.ConnectToIndividualSymbolTickerWebSocket(pair, data =>
{
if (candles.Count > 0)
{
candles[candles.Count - 1].Close = data.BestAskPrice;
}
});
}
}
}