coin_alerts/Picasso.cs
2025-01-09 13:40:55 +05:30

118 lines
5.5 KiB
C#

using SignalsTest;
using System;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Newtonsoft.Json;
public class Picasso{
public static void DrawChart(List<TAReport> reports, decimal max, decimal min, decimal volMax, string filename="test"){
// float height = (float)Math.Ceiling(max - min) * 2f;
// float width = ((float)height / 9f) * 16f;
decimal heightRange = max-min;
float height=1080;
float width = 1920;
float widthMultiplier = width / (float)reports.Count;
float heightMultiplier = (height/ (float)heightRange) * 0.6f;
float candlesOffset = 0.3f * height;
float volumeSize = 0.2f * height;
using (Image img = new Image<Rgba32>((int)width + 100, (int)height)){
//Draw Candles
for(int i=0; i < reports.Count; i++){
// img.Mutate(ctx=> ctx.DrawLine()))
PointF[] points = new PointF[2];
float openVal1 = (float)(reports[i].candle.Open - min) * heightMultiplier;
float closeVal1 = (float)(reports[i].candle.Close - min)* heightMultiplier;
points[0] =new PointF(i * widthMultiplier, openVal1 + candlesOffset);
points[1] =new PointF(i * widthMultiplier, closeVal1+ candlesOffset);
PointF[] rangePoints = new PointF[2];
float highVal = (float)(reports[i].candle.High-min)* heightMultiplier;
float lowVal = (float)(reports[i].candle.Low-min)* heightMultiplier;
rangePoints[0] = new PointF(i * widthMultiplier, highVal+ candlesOffset);
rangePoints[1] = new PointF(i * widthMultiplier, lowVal+ candlesOffset);
PointF[] volumePoints = new PointF[2];
volumePoints[0] = new PointF(i * widthMultiplier, 0);
volumePoints[1] = new PointF(i * widthMultiplier, ((float)reports[i].candle.Volume / (float)volMax) * volumeSize);
Color candleColor = reports[i].candle.Close > reports[i].candle.Open ? Color.Green : Color.Red;
img.Mutate(ctx=> ctx.
DrawLine(candleColor, 10, points).
DrawLine(candleColor, 3, rangePoints).
DrawLine(candleColor, 10, volumePoints)
);
if(reports[i].TGOR){
PointF[] tgorPoints = new PointF[2];
tgorPoints[0] = new PointF(i * widthMultiplier, lowVal+ candlesOffset);
tgorPoints[1] = new PointF(i * widthMultiplier, lowVal- 15+ candlesOffset);
img.Mutate(ctx=>ctx.DrawLine(Color.Blue, 15, tgorPoints));
}
}
// Console.WriteLine("Getting paths");
// object t = GetPropByName(reports[reports.Count- 1], "SMA7");
// Console.WriteLine(t);
// Console.WriteLine(float.Parse(t.ToString()));
//Overlay
IPath sma7Path = GetPath(reports, "SMA7", widthMultiplier,(float)heightMultiplier, (float)min, candlesOffset);
IPath sma25Path = GetPath(reports, "SMA25", widthMultiplier,(float)heightMultiplier, (float)min, candlesOffset);
IPath stPath = GetPath(reports, "ST", widthMultiplier,(float)heightMultiplier, (float)min, candlesOffset);
//NewChart
FontFamily fontFamily;
float TextFontSize = 64f;
string TextFont = "Noto Sans Mono";
if (!SystemFonts.TryGet(TextFont, out fontFamily))
throw new Exception($"Couldn't find font {TextFont}");
var font = fontFamily.CreateFont(TextFontSize, FontStyle.Regular);
img.Mutate(ctx => ctx.Draw(Color.Yellow, 2, sma7Path).
Draw(Color.Purple, 2, sma25Path).
Draw(Color.Green, 3, stPath).
Flip(FlipMode.Vertical).
DrawText(filename, font,new Color(Rgba32.ParseHex("#000000FF")), new PointF(10,10)));
img.Save($"{filename}.png");
}
}
static IPath GetPath(List<TAReport> reports, string propName, float widthMultiplier,float heightMultiplier, float min, float offset =0){
PathBuilder builder = new PathBuilder();
builder.SetOrigin(new PointF(0,0));
for(int i=0; i < reports.Count; i++){
float newVal = float.Parse(GetPropByName(reports[i],propName).ToString() ?? "0");
// Console.WriteLine( newVal);
float prevVal = i > 0 ? float.Parse(GetPropByName(reports[i-1],propName).ToString() ?? "0") : 0;
// Console.WriteLine( prevVal);
float preValY =( prevVal - min) * heightMultiplier ;
float newValY=(newVal - min) * heightMultiplier;
PointF prevPoint = new PointF((i-1)* widthMultiplier, (preValY) +offset);
PointF newPoint = new PointF(i * widthMultiplier, (newValY) + offset);
// Console.WriteLine(newValY);
builder.AddLine(prevPoint, newPoint);
}
return builder.Build();
}
static object GetPropByName(TAReport report, string propName){
string json = report.toJson();
Dictionary<string,string> dic = JsonConvert.DeserializeObject<Dictionary<string,string>>(json) ?? new Dictionary<string, string>();
// Console.WriteLine(dic[propName]);
return dic[propName];
}
}