mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-15 00:58:04 +00:00
New version merge
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using TradingPlatform.BusinessLayer.Chart;
|
||||
using QuanTAlib;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public abstract class AbstractIndicatorBase : Indicator
|
||||
{
|
||||
|
||||
[InputParameter("Data source", sortIndex: 18, variants: new object[]{
|
||||
"Close", PriceType.Close,
|
||||
"Open", PriceType.Open,
|
||||
"High", PriceType.High,
|
||||
"Low", PriceType.Low,
|
||||
"Typical", PriceType.Typical,
|
||||
"Median", PriceType.Median,
|
||||
"Weighted", PriceType.Weighted
|
||||
})]
|
||||
public PriceType SourcePrice { get; set; } = PriceType.Close;
|
||||
|
||||
[InputParameter(name: "Line smoothing", sortIndex: 19, minimum: 0.0, maximum: 1.0, increment: 0.1, decimalPlaces: 2)]
|
||||
public double Tension = 0.2;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 20)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
|
||||
// LineSeries.LineSeries(string, Color, int, LineStyle)'
|
||||
|
||||
protected LineSeries? Series;
|
||||
protected abstract AbstractBase MovingAverage { get; }
|
||||
|
||||
protected AbstractIndicatorBase() : base()
|
||||
{
|
||||
OnBackGround = true;
|
||||
SeparateWindow = false;
|
||||
Series = new(name: $"Name", color: Color.Orange, width: 2, style: LineStyle.Solid);
|
||||
AddLineSeries(Series);
|
||||
|
||||
InitIndicator();
|
||||
}
|
||||
|
||||
protected virtual void InitIndicator()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
InitIndicator();
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
base.OnUpdate(args);
|
||||
bool isNew = this.HistoricalData.Aggregation.GetPeriod == Period.TICK1
|
||||
? args.Reason == UpdateReason.NewTick || args.Reason == UpdateReason.HistoricalBar
|
||||
: args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar;
|
||||
double price = GetPrice(SourcePrice);
|
||||
|
||||
TValue input = new TValue(Time(), price, isNew);
|
||||
TValue result = MovingAverage.Calc(input);
|
||||
|
||||
Series!.SetMarker(0, Color.Transparent);
|
||||
Series.SetValue(result.Value);
|
||||
|
||||
}
|
||||
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
List<Point> allPoints = new List<Point>();
|
||||
if (CurrentChart == null) return;
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
var mainWindow = CurrentChart.MainWindow;
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
|
||||
gr.SetClip(clientRect);
|
||||
DateTime leftTime = new[] { converter.GetTime(clientRect.Left), Time(this.Count - 1) }.Max();
|
||||
DateTime rightTime = new[] { converter.GetTime(clientRect.Right), Time(0) }.Min();
|
||||
|
||||
int leftIndex = (int)HistoricalData.GetIndexByTime(leftTime.Ticks) + 1;
|
||||
int rightIndex = (int)HistoricalData.GetIndexByTime(rightTime.Ticks);
|
||||
|
||||
for (int i = rightIndex; i < leftIndex; i++)
|
||||
{
|
||||
int barX = (int)converter.GetChartX(Time(i));
|
||||
int barY = (int)converter.GetChartY(Series![i]);
|
||||
int halfBarWidth = CurrentChart.BarsWidth / 2;
|
||||
Point point = new Point(barX + halfBarWidth, barY);
|
||||
allPoints.Add(point);
|
||||
}
|
||||
|
||||
if (allPoints.Count > 1)
|
||||
{
|
||||
DrawSmoothCombinedCurve(gr, allPoints, this.Count - MovingAverage.WarmupPeriod - rightIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSmoothCombinedCurve(Graphics gr, List<Point> allPoints, int hotCount)
|
||||
{
|
||||
if (allPoints.Count < 2) return;
|
||||
|
||||
using (Pen defaultPen = new(Series!.Color, Series.Width) { DashStyle = ConvertLineStyleToDashStyle(Series.Style) })
|
||||
using (Pen coldPen = new(Series!.Color, Series.Width) { DashStyle = DashStyle.Dot })
|
||||
{
|
||||
// Draw the hot part
|
||||
if (hotCount > 0)
|
||||
{
|
||||
var hotPoints = allPoints.Take(Math.Min(hotCount + 1, allPoints.Count)).ToArray();
|
||||
gr.DrawCurve(defaultPen, hotPoints, 0, hotPoints.Length - 1, (float)Tension);
|
||||
}
|
||||
|
||||
// Draw the cold part
|
||||
if (ShowColdValues && hotCount < allPoints.Count)
|
||||
{
|
||||
var coldPoints = allPoints.Skip(Math.Max(0, hotCount)).ToArray();
|
||||
gr.DrawCurve(coldPen, coldPoints, 0, coldPoints.Length - 1, (float)Tension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawText(Graphics gr, string text, Rectangle clientRect)
|
||||
{
|
||||
Font font = new Font("Inter", 8);
|
||||
SizeF textSize = gr.MeasureString(text, font);
|
||||
RectangleF textRect = new RectangleF(clientRect.Left + 5,
|
||||
clientRect.Bottom - textSize.Height - 10,
|
||||
textSize.Width + 10, textSize.Height + 10);
|
||||
gr.FillRectangle(SystemBrushes.ControlDarkDark, textRect);
|
||||
gr.DrawString(text, font, Brushes.White, new PointF(textRect.X + 6, textRect.Y + 5));
|
||||
}
|
||||
|
||||
private DashStyle ConvertLineStyleToDashStyle(LineStyle lineStyle)
|
||||
{
|
||||
return lineStyle switch
|
||||
{
|
||||
LineStyle.Solid => DashStyle.Solid,
|
||||
LineStyle.Dash => DashStyle.Dash,
|
||||
LineStyle.Dot => DashStyle.Dot,
|
||||
LineStyle.DashDot => DashStyle.DashDot,
|
||||
_ => DashStyle.Solid,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class AlmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Offset", sortIndex: 5)]
|
||||
public double Offset = 0.85;
|
||||
|
||||
[InputParameter("Sigma", sortIndex: 6)]
|
||||
public double Sigma = 6.0;
|
||||
private Alma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"ALMA {Period} : {Offset:F2} : {Sigma:F0} : {SourceName}";
|
||||
|
||||
public AlmaIndicator() : base()
|
||||
{
|
||||
Name = "ALMA - Arnaud Legoux Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Alma(period: Period, offset: Offset, sigma: Sigma);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AlgoType>Indicator</AlgoType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.Interactive.Formatting" Version="1.0.0-beta.21459.1" />
|
||||
<Compile Include="..\..\lib\**\*.cs" Exclude="..\..\lib\obj\**">
|
||||
<Link>lib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
|
||||
<Copy SourceFiles="$(OutputPath)\Averages.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Averages" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class DemaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
private Dema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"DEMA {Period} : {SourceName}";
|
||||
|
||||
public DemaIndicator() : base()
|
||||
{
|
||||
Name = "DEMA - Double Exponential Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Dema(period: Period);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class DsmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Dsma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"DSMA {Period} : {SourceName}";
|
||||
|
||||
public DsmaIndicator() : base()
|
||||
{
|
||||
Name = "DSMA - Deviation Scaled Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Dsma(Period);
|
||||
MinHistoryDepths = ma.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class DwmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Dwma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"DWMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public DwmaIndicator() : base()
|
||||
{
|
||||
Name = "DWMA - Double Weighted Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Dwma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class EmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Use SMA for warmup", sortIndex: 5)]
|
||||
public bool UseSma { get; set; } = false;
|
||||
|
||||
private Ema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"EMA {Period} : {SourceName}";
|
||||
|
||||
public EmaIndicator() : base()
|
||||
{
|
||||
Name = "EMA - Exponential Moving Average";
|
||||
Description = "Exponential Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Ema(period: Period, useSma: UseSma);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class EpmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Epma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"EPMA {Period} : {SourceName}";
|
||||
|
||||
public EpmaIndicator() : base()
|
||||
{
|
||||
Name = "EPMA - Endpoint Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Epma(period: Period);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class FramaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Frama? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"FRAMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public FramaIndicator() : base()
|
||||
{
|
||||
Name = "FRAMA - Fractal Adaptive Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Frama(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class FwmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Fwma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"FWMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public FwmaIndicator() : base()
|
||||
{
|
||||
Name = "FWMA - Fibonacci-Weighted Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Fwma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class GmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Gma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"GMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public GmaIndicator() : base()
|
||||
{
|
||||
Name = "GMA - Gaussian-Weighted Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Gma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class HmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Hma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"HMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public HmaIndicator() : base()
|
||||
{
|
||||
Name = "HMA - Hull Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Hma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class HtitIndicator : IndicatorBase
|
||||
{
|
||||
private Htit? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"HTIT : {SourceName}";
|
||||
|
||||
public HtitIndicator() : base()
|
||||
{
|
||||
Name = "HTIT - Hilbert Transform Instantaneous Trendline";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Htit();
|
||||
MinHistoryDepths = ma.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class HwmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("nA - smoothed series", sortIndex: 5, minimum: 0.0, maximum: 1.0, increment: 0.1, decimalPlaces: 2)]
|
||||
public double nA { get; set; } = 0.18;
|
||||
|
||||
[InputParameter("nB - assess the trend (from 0 to 1)", sortIndex: 6, minimum: 0.0, maximum: 1.0, increment: 0.1, decimalPlaces: 2)]
|
||||
public double nB { get; set; } = 0.1;
|
||||
|
||||
[InputParameter("nC - assess seasonality (from 0 to 1)", sortIndex: 7, minimum: 0.0, maximum: 1.0, increment: 0.1, decimalPlaces: 2)]
|
||||
public double nC { get; set; } = 0.1;
|
||||
|
||||
private Hwma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"HWMA {nA:F2} : {nB:F2} : {nC:F2} : {SourceName}";
|
||||
|
||||
|
||||
public HwmaIndicator() : base()
|
||||
{
|
||||
Name = "HWMA - Holt-Winter Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
//nA = 2 / (1 + (double)Period);
|
||||
//nB = 1 / (double)Period;
|
||||
//nC = 1 / (double)Period;
|
||||
ma = new Hwma(nA: nA, nB: nB, nC: nC);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class JmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 2, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Phase", sortIndex: 2, -100, 100, 1, 0)]
|
||||
public int Phase { get; set; } = 0;
|
||||
private Jma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"JMA {Period} : {Phase} : {SourceName}";
|
||||
|
||||
|
||||
public JmaIndicator() : base()
|
||||
{
|
||||
Name = "JMA - Jurik Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Jma(period: Period, phase: (double)Phase);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class KamaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Fast", sortIndex: 2, 1, 2000, 1, 0)]
|
||||
public int Fast { get; set; } = 2;
|
||||
[InputParameter("Slow", sortIndex: 3, 1, 2000, 1, 0)]
|
||||
public int Slow { get; set; } = 30;
|
||||
private Kama? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"KAMA {Period} : {Fast} : {Slow} : {SourceName}";
|
||||
|
||||
|
||||
public KamaIndicator() : base()
|
||||
{
|
||||
Name = "KAMA - Kaufman's Adaptive Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Kama(Period, Fast, Slow);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class LtmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Gamma", sortIndex: 1, 0, 1, 0.01, 2)]
|
||||
public double Gamma { get; set; } = 0.10;
|
||||
|
||||
private Ltma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"Laguerre {Gamma:F2} : {SourceName}";
|
||||
|
||||
public LtmaIndicator() : base()
|
||||
{
|
||||
Name = "LTMA - Laguerre Transform Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Ltma(gamma: Gamma);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MaafIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 39;
|
||||
|
||||
[InputParameter("Threshold", sortIndex: 5, minimum: 0, maximum: 1, increment: 0.001, decimalPlaces:3)]
|
||||
public double Threshold = 0.002;
|
||||
|
||||
private Maaf? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MAAF {Period} : {Threshold:F2} : {SourceName}";
|
||||
|
||||
public MaafIndicator() : base()
|
||||
{
|
||||
Name = "MAAF - Median-Average Adaptive Filter";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Maaf(Period: Period, Threshold: Threshold);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MamaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Fast limit", sortIndex: 2, 0, 1, 0.01, 2)]
|
||||
public double Fast { get; set; } = 0.4;
|
||||
[InputParameter("Slow limit", sortIndex: 3, 0, 1, 0.01, 2)]
|
||||
public double Slow { get; set; } = 0.04;
|
||||
private Mama? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MAMA : {Fast} : {Slow} : {SourceName}";
|
||||
|
||||
|
||||
public MamaIndicator() : base()
|
||||
{
|
||||
Name = "MAMA - MESA Adaptive Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Mama(Fast, Slow);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MgdiIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("k Factor", sortIndex: 2, minimum: 0.0, maximum: 1.0, increment: 0.1, decimalPlaces: 2)]
|
||||
public double kfactor { get; set; } = 0.6;
|
||||
|
||||
|
||||
private Mgdi? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MGDI {Period} : {kfactor:F2} : {SourceName}";
|
||||
|
||||
|
||||
public MgdiIndicator() : base()
|
||||
{
|
||||
Name = "MGDI - McGinley Dynamic Index";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Mgdi(period: Period, kFactor: kfactor);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Mma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MMA {Period} : {SourceName}";
|
||||
|
||||
public MmaIndicator() : base()
|
||||
{
|
||||
Name = "MMA - Modified Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Mma(period: Period);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class QemaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("alpha 1", sortIndex: 1, minimum: 0.01, maximum: 1.0, increment: 0.01, decimalPlaces: 2)]
|
||||
public double k1 { get; set; } = 0.2;
|
||||
|
||||
[InputParameter("alpha 2", sortIndex: 2, minimum: 0.01, maximum: 1.0, increment: 0.01, decimalPlaces: 2)]
|
||||
public double k2 { get; set; } = 0.3;
|
||||
[InputParameter("alpha 3", sortIndex: 3, minimum: 0.01, maximum: 1.0, increment: 0.01, decimalPlaces: 2)]
|
||||
public double k3 { get; set; } = 0.4;
|
||||
[InputParameter("alpha 4", sortIndex: 4, minimum: 0.01, maximum: 1.0, increment: 0.01, decimalPlaces: 2)]
|
||||
public double k4 { get; set; } = 0.5;
|
||||
private Qema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"QEMA {k1:F2} : {k2:F2} : {k3:F2} : {k4:F2} :{SourceName}";
|
||||
|
||||
public QemaIndicator() : base()
|
||||
{
|
||||
Name = "QEMA - Quad Exponential Moving Average";
|
||||
Description = "Quad Exponential Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Qema(k1, k2, k3, k4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class RemaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Regularization Factor", sortIndex: 2, minimum: 0, maximum: 2.5, increment: 0.1, decimalPlaces: 1)]
|
||||
public double Lambda { get; set; } = 0.5;
|
||||
|
||||
private Rema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"REMA {Period} : {Lambda:F2} : {SourceName}";
|
||||
|
||||
public RemaIndicator() : base()
|
||||
{
|
||||
Name = "REMA - Regularized Exponential Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Rema(period: Period, lambda: Lambda);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class RmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Rma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"RMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public RmaIndicator() : base()
|
||||
{
|
||||
Name = "RMA - wildeR Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Rma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class SinemaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Sinema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"SINEMA {Period} : {SourceName}";
|
||||
|
||||
public SinemaIndicator() : base()
|
||||
{
|
||||
Name = "SINEMA - Sine-Weighted Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Sinema(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class SmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Sma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"SMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public SmaIndicator() : base()
|
||||
{
|
||||
Name = "SMA - Simple Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Sma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class SmmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Smma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"SMMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public SmmaIndicator() : base()
|
||||
{
|
||||
Name = "SMMA - Smoothed Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Smma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class T3Indicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Vfactor", sortIndex: 2, 0, 1, 0.01, 2)]
|
||||
public double Vfactor { get; set; } = 0.62;
|
||||
|
||||
[InputParameter("Use SMA for warmup", sortIndex: 3)]
|
||||
public bool UseSma { get; set; } = false;
|
||||
|
||||
private T3? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"T3 {Period} : {Vfactor:F2} : {SourceName}";
|
||||
|
||||
public T3Indicator() : base()
|
||||
{
|
||||
Name = "T3 - Tillson T3 Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new T3(period: Period, vfactor: Vfactor, useSma: UseSma);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class TemaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Tema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"TEMA {Period} : {SourceName}";
|
||||
|
||||
public TemaIndicator() : base()
|
||||
{
|
||||
Name = "TEMA - Triple Exponential Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Tema(period: Period);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class TrimaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Trima? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"TRIMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public TrimaIndicator() : base()
|
||||
{
|
||||
Name = "TRIMA - Triangular Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Trima(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class VidyaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Short Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
[InputParameter("Long Period", sortIndex: 2, 1, 2000, 1, 0)]
|
||||
public int LPeriod { get; set; } = 40;
|
||||
[InputParameter("Alpha", sortIndex: 3, 0, 1, 0.1, 1)]
|
||||
public double Alpha { get; set; } = 0.4;
|
||||
|
||||
private Vidya? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"VIDYA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public VidyaIndicator() : base()
|
||||
{
|
||||
Name = "VIDYA - Variable Index Dynamic Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Vidya(Period, LPeriod, Alpha);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class WmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Wma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"WMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public WmaIndicator() : base()
|
||||
{
|
||||
Name = "WMA - Weighted Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Wma(Period);
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class ZlemaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Zlema? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"ZLEMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public ZlemaIndicator() : base()
|
||||
{
|
||||
Name = "ZLEMA - Weighted Moving Average";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Zlema(Period);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using TradingPlatform.BusinessLayer.Chart;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Drawing.Drawing2D;
|
||||
using QuanTAlib;
|
||||
using System.Collections;
|
||||
using TradingPlatform.BusinessLayer.TimeSync;
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public abstract class IndicatorBase : Indicator, IWatchlistIndicator
|
||||
{
|
||||
|
||||
[InputParameter("Data source", sortIndex: 17, variants: [
|
||||
"Open", 1,
|
||||
"High", 2,
|
||||
"Low", 3,
|
||||
"Close", 4,
|
||||
"HL/2 (Median)", 5,
|
||||
"OC/2 (Midpoint)", 6,
|
||||
"OHL/3 (Mean)", 7,
|
||||
"HLC/3 (Typical)", 8,
|
||||
"OHLC/4 (Average)", 9,
|
||||
"HLCC/4 (Weighted)", 10
|
||||
])]
|
||||
public int Source { get; set; } = 4;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 20)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
public int MinHistoryDepths;
|
||||
|
||||
// LineSeries.LineSeries(string, Color, int, LineStyle)'
|
||||
|
||||
protected LineSeries? Series;
|
||||
protected string SourceName;
|
||||
protected abstract AbstractBase QuanTAlib { get; }
|
||||
|
||||
int IWatchlistIndicator.MinHistoryDepths => 0;
|
||||
|
||||
protected IndicatorBase() : base()
|
||||
{
|
||||
OnBackGround = true;
|
||||
SeparateWindow = false;
|
||||
SourceName = GetName(Source);
|
||||
Series = new(name: $"{Name}", color: Color.Yellow, width: 2, style: LineStyle.Solid);
|
||||
|
||||
AddLineSeries(Series);
|
||||
InitIndicator();
|
||||
}
|
||||
|
||||
protected virtual void InitIndicator()
|
||||
{
|
||||
SourceName = GetName(Source);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
InitIndicator();
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TBar bar = new(Time: Time(),
|
||||
Open: GetPrice(PriceType.Open),
|
||||
High: GetPrice(PriceType.High),
|
||||
Low: GetPrice(PriceType.Low),
|
||||
Close: GetPrice(PriceType.Close),
|
||||
Volume: GetPrice(PriceType.Volume),
|
||||
IsNew: args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
|
||||
|
||||
double price = Source switch
|
||||
{
|
||||
1 => bar.Open,
|
||||
2 => bar.High,
|
||||
3 => bar.Low,
|
||||
4 => bar.Close,
|
||||
5 => bar.HL2,
|
||||
6 => bar.OC2,
|
||||
7 => bar.OHL3,
|
||||
8 => bar.HLC3,
|
||||
9 => bar.OHLC4,
|
||||
10 => bar.HLCC4,
|
||||
_ => bar.Close
|
||||
};
|
||||
|
||||
TValue input = new TValue(bar.Time, price, bar.IsNew);
|
||||
TValue result = QuanTAlib.Calc(input);
|
||||
Series!.SetValue(result.Value);
|
||||
Series!.SetMarker(0, Color.Transparent);
|
||||
|
||||
}
|
||||
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
List<Point> allPoints = new List<Point>();
|
||||
if (CurrentChart == null) return;
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
var mainWindow = this.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
|
||||
gr.SetClip(clientRect);
|
||||
DateTime leftTime = new[] { converter.GetTime(clientRect.Left), Time(this.Count - 1) }.Max();
|
||||
DateTime rightTime = new[] { converter.GetTime(clientRect.Right), Time(0) }.Min();
|
||||
|
||||
int leftIndex = (int)HistoricalData.GetIndexByTime(leftTime.Ticks) + 1;
|
||||
int rightIndex = (int)HistoricalData.GetIndexByTime(rightTime.Ticks);
|
||||
|
||||
for (int i = rightIndex; i < leftIndex; i++)
|
||||
{
|
||||
int barX = (int)converter.GetChartX(Time(i));
|
||||
int barY = (int)converter.GetChartY(Series![i]);
|
||||
int halfBarWidth = CurrentChart.BarsWidth / 2;
|
||||
Point point = new Point(barX + halfBarWidth, barY);
|
||||
allPoints.Add(point);
|
||||
}
|
||||
|
||||
if (allPoints.Count > 1)
|
||||
{
|
||||
DrawSmoothCombinedCurve(gr, allPoints, this.Count - QuanTAlib.WarmupPeriod - rightIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSmoothCombinedCurve(Graphics gr, List<Point> allPoints, int hotCount)
|
||||
{
|
||||
if (allPoints.Count < 2) return;
|
||||
|
||||
using (Pen defaultPen = new(Series!.Color, Series.Width) { DashStyle = ConvertLineStyleToDashStyle(Series.Style) })
|
||||
using (Pen coldPen = new(Series!.Color, Series.Width) { DashStyle = DashStyle.Dot })
|
||||
{
|
||||
// Draw the hot part
|
||||
if (hotCount > 0)
|
||||
{
|
||||
var hotPoints = allPoints.Take(Math.Min(hotCount + 1, allPoints.Count)).ToArray();
|
||||
gr.DrawCurve(defaultPen, hotPoints, 0, hotPoints.Length - 1, (float)0.2);
|
||||
}
|
||||
|
||||
// Draw the cold part
|
||||
if (ShowColdValues && hotCount < allPoints.Count)
|
||||
{
|
||||
var coldPoints = allPoints.Skip(Math.Max(0, hotCount)).ToArray();
|
||||
gr.DrawCurve(coldPen, coldPoints, 0, coldPoints.Length - 1, (float)0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
private DashStyle ConvertLineStyleToDashStyle(LineStyle lineStyle)
|
||||
{
|
||||
return lineStyle switch
|
||||
{
|
||||
LineStyle.Solid => DashStyle.Solid,
|
||||
LineStyle.Dash => DashStyle.Dash,
|
||||
LineStyle.Dot => DashStyle.Dot,
|
||||
LineStyle.DashDot => DashStyle.DashDot,
|
||||
_ => DashStyle.Solid,
|
||||
};
|
||||
}
|
||||
protected void DrawText(Graphics gr, string text, Rectangle clientRect)
|
||||
{
|
||||
Font font = new Font("Inter", 8);
|
||||
SizeF textSize = gr.MeasureString(text, font);
|
||||
RectangleF textRect = new RectangleF(clientRect.Left + 5,
|
||||
clientRect.Bottom - textSize.Height - 10,
|
||||
textSize.Width + 10, textSize.Height + 10);
|
||||
gr.FillRectangle(SystemBrushes.ControlDarkDark, textRect);
|
||||
gr.DrawString(text, font, Brushes.White, new PointF(textRect.X + 6, textRect.Y + 5));
|
||||
}
|
||||
protected string GetName(int pType)
|
||||
{
|
||||
return pType switch
|
||||
{
|
||||
1 => "Open",
|
||||
2 => "High",
|
||||
3 => "Low",
|
||||
4 => "Close",
|
||||
5 => "Median",
|
||||
6 => "Midpoint",
|
||||
7 => "Mean",
|
||||
8 => "Typical",
|
||||
9 => "Average",
|
||||
10 => "Weighted",
|
||||
_ => "N/A"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class EntropyIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 2, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 50;
|
||||
|
||||
private Entropy? entropy;
|
||||
protected override AbstractBase QuanTAlib => entropy!;
|
||||
public override string ShortName => $"ENTROPY {Period} : {SourceName}";
|
||||
|
||||
public EntropyIndicator() : base()
|
||||
{
|
||||
Name = "ENTROPY - Entropy";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
entropy = new(Period);
|
||||
MinHistoryDepths = entropy.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class KurtosisIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 4, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 20;
|
||||
|
||||
private Kurtosis? kurtosis;
|
||||
protected override AbstractBase QuanTAlib => kurtosis!;
|
||||
public override string ShortName => $"KURTOSIS {Period} : {SourceName}";
|
||||
|
||||
public KurtosisIndicator() : base()
|
||||
{
|
||||
Name = "KURTOSIS - Relative Flatness";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
kurtosis = new(Period);
|
||||
MinHistoryDepths = kurtosis.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MaxIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 50;
|
||||
|
||||
[InputParameter("Decay to mean", sortIndex: 1, minimum: 0.00, maximum: 100.0, increment: 0.01, decimalPlaces: 2)]
|
||||
public double Decay { get; set; } = 0.1;
|
||||
|
||||
private Max? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MAX {Period} : {Decay:F2} : {SourceName}";
|
||||
|
||||
public MaxIndicator() : base()
|
||||
{
|
||||
Name = "MAX - Maximum value (with decay) ";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
ma = new Max(Period, Decay);
|
||||
MinHistoryDepths = ma.WarmupPeriod;
|
||||
Source = 2;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MedianIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 50;
|
||||
|
||||
private Median? med;
|
||||
protected override AbstractBase QuanTAlib => med!;
|
||||
public override string ShortName => $"MEDIAN {Period} : {SourceName}";
|
||||
public MedianIndicator() : base()
|
||||
{
|
||||
Name = "MEDIAN - Median historical value";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
med = new Median(Period);
|
||||
MinHistoryDepths = med.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class MinIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 50;
|
||||
|
||||
[InputParameter("Decay to mean", sortIndex: 1, minimum: 0.00, maximum: 100.0, increment: 0.01, decimalPlaces: 2)]
|
||||
public double Decay { get; set; } = 0.1;
|
||||
|
||||
private Min? mi;
|
||||
protected override AbstractBase QuanTAlib => mi!;
|
||||
public override string ShortName => $"MIN {Period} : {Decay:F2} : {SourceName}";
|
||||
public MinIndicator() : base()
|
||||
{
|
||||
Name = "MIN - Minimum value (with decay)";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
mi = new Min(Period, Decay);
|
||||
MinHistoryDepths = mi.WarmupPeriod;
|
||||
Source = 3;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class ModeIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 50;
|
||||
|
||||
private Mode? mode;
|
||||
protected override AbstractBase QuanTAlib => mode!;
|
||||
public override string ShortName => $"MODE {Period} : {SourceName}";
|
||||
public ModeIndicator() : base()
|
||||
{
|
||||
Name = "MODE - Most frequent historical value";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
mode = new Mode(Period);
|
||||
MinHistoryDepths = mode.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
public class PercentileIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 2, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 20;
|
||||
|
||||
[InputParameter("Percent", sortIndex: 2, 0, 100, 1, 0)]
|
||||
public double Percent { get; set; } = 50;
|
||||
|
||||
private Percentile? percentile;
|
||||
protected override AbstractBase QuanTAlib => percentile!;
|
||||
public override string ShortName => $"PERCENTILE {Period} {Percent:F0}% : {SourceName}";
|
||||
|
||||
public PercentileIndicator() : base()
|
||||
{
|
||||
Name = "PERCENTILE - n-th Percentile ";
|
||||
SeparateWindow = false;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
percentile = new(Period, Percent);
|
||||
MinHistoryDepths = percentile.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class SkewIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 3, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 20;
|
||||
|
||||
private Skew? skew;
|
||||
protected override AbstractBase QuanTAlib => skew!;
|
||||
public override string ShortName => $"SKEW {Period} : {SourceName}";
|
||||
|
||||
public SkewIndicator() : base()
|
||||
{
|
||||
Name = "SKEW - Skewness";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
skew = new(Period);
|
||||
MinHistoryDepths = skew.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AlgoType>Indicator</AlgoType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.Interactive.Formatting" Version="1.0.0-beta.21459.1" />
|
||||
<Compile Include="..\..\lib\**\*.cs" Exclude="..\..\lib\obj\**">
|
||||
<Link>lib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
|
||||
<Copy SourceFiles="$(OutputPath)\Statistics.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Statistics" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class StddevIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 20;
|
||||
|
||||
[InputParameter("Population", sortIndex: 2)]
|
||||
public bool IsPopulation { get; set; } = false;
|
||||
|
||||
private Stddev? stddev;
|
||||
protected override AbstractBase QuanTAlib => stddev!;
|
||||
public override string ShortName => $"STDDEV {Period} : {SourceName}";
|
||||
public StddevIndicator() : base()
|
||||
{
|
||||
Name = "STDDEV - Standard Deviation";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
stddev = new(Period, IsPopulation);
|
||||
MinHistoryDepths = stddev.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class VarianceIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, minimum: 2, maximum: 2000, increment: 1, decimalPlaces: 0)]
|
||||
public int Period { get; set; } = 20;
|
||||
|
||||
[InputParameter("Population", sortIndex: 2)]
|
||||
public bool IsPopulation { get; set; } = false;
|
||||
|
||||
private Variance? variance;
|
||||
protected override AbstractBase QuanTAlib => variance!;
|
||||
public override string ShortName => $"VAR {Period} : {SourceName}";
|
||||
public VarianceIndicator() : base()
|
||||
{
|
||||
Name = "VAR - Variance";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
SeparateWindow = true;
|
||||
variance = new(Period, IsPopulation);
|
||||
MinHistoryDepths = variance.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
|
||||
public class ZScoreIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 2, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 20;
|
||||
|
||||
private Zscore? zScore;
|
||||
protected override AbstractBase QuanTAlib => zScore!;
|
||||
public override string ShortName => $"ZSCORE {Period} : {SourceName}";
|
||||
|
||||
public ZScoreIndicator() : base()
|
||||
{
|
||||
Name = "ZSCORE - Standard Score";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
zScore = new(Period);
|
||||
MinHistoryDepths = zScore.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using TradingPlatform.BusinessLayer.Chart;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Drawing.Drawing2D;
|
||||
using QuanTAlib;
|
||||
using System.Collections;
|
||||
using TradingPlatform.BusinessLayer.TimeSync;
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public abstract class IndicatorBase : Indicator, IWatchlistIndicator
|
||||
{
|
||||
|
||||
[InputParameter("Data source", sortIndex: 17, variants: [
|
||||
"Open", 1,
|
||||
"High", 2,
|
||||
"Low", 3,
|
||||
"Close", 4,
|
||||
"HL/2 (Median)", 5,
|
||||
"OC/2 (Midpoint)", 6,
|
||||
"OHL/3 (Mean)", 7,
|
||||
"HLC/3 (Typical)", 8,
|
||||
"OHLC/4 (Average)", 9,
|
||||
"HLCC/4 (Weighted)", 10
|
||||
])]
|
||||
public int Source { get; set; } = 4;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 20)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
public int MinHistoryDepths;
|
||||
|
||||
// LineSeries.LineSeries(string, Color, int, LineStyle)'
|
||||
|
||||
protected LineSeries? Series;
|
||||
protected string SourceName;
|
||||
protected abstract AbstractBase QuanTAlib { get; }
|
||||
|
||||
int IWatchlistIndicator.MinHistoryDepths => 0;
|
||||
|
||||
protected IndicatorBase() : base()
|
||||
{
|
||||
OnBackGround = true;
|
||||
SeparateWindow = false;
|
||||
SourceName = GetName(Source);
|
||||
Series = new(name: $"{Name}", color: Color.RoyalBlue, width: 2, style: LineStyle.Solid);
|
||||
|
||||
AddLineSeries(Series);
|
||||
InitIndicator();
|
||||
}
|
||||
|
||||
protected virtual void InitIndicator()
|
||||
{
|
||||
SourceName = GetName(Source);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
InitIndicator();
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TBar bar = new(Time: Time(),
|
||||
Open: GetPrice(PriceType.Open),
|
||||
High: GetPrice(PriceType.High),
|
||||
Low: GetPrice(PriceType.Low),
|
||||
Close: GetPrice(PriceType.Close),
|
||||
Volume: GetPrice(PriceType.Volume),
|
||||
IsNew: args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
|
||||
|
||||
double price = Source switch
|
||||
{
|
||||
1 => bar.Open,
|
||||
2 => bar.High,
|
||||
3 => bar.Low,
|
||||
4 => bar.Close,
|
||||
5 => bar.HL2,
|
||||
6 => bar.OC2,
|
||||
7 => bar.OHL3,
|
||||
8 => bar.HLC3,
|
||||
9 => bar.OHLC4,
|
||||
10 => bar.HLCC4,
|
||||
_ => bar.Close
|
||||
};
|
||||
|
||||
TValue input = new TValue(bar.Time, price, bar.IsNew);
|
||||
TValue result = QuanTAlib.Calc(input);
|
||||
Series!.SetValue(result.Value);
|
||||
Series!.SetMarker(0, Color.Transparent);
|
||||
|
||||
}
|
||||
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
List<Point> allPoints = new List<Point>();
|
||||
if (CurrentChart == null) return;
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
|
||||
var mainWindow = this.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
|
||||
gr.SetClip(clientRect);
|
||||
DateTime leftTime = new[] { converter.GetTime(clientRect.Left), Time(this.Count - 1) }.Max();
|
||||
DateTime rightTime = new[] { converter.GetTime(clientRect.Right), Time(0) }.Min();
|
||||
|
||||
int leftIndex = (int)HistoricalData.GetIndexByTime(leftTime.Ticks) + 1;
|
||||
int rightIndex = (int)HistoricalData.GetIndexByTime(rightTime.Ticks);
|
||||
|
||||
for (int i = rightIndex; i < leftIndex; i++)
|
||||
{
|
||||
int barX = (int)converter.GetChartX(Time(i));
|
||||
int barY = (int)converter.GetChartY(Series![i]);
|
||||
int halfBarWidth = CurrentChart.BarsWidth / 2;
|
||||
Point point = new Point(barX + halfBarWidth, barY);
|
||||
allPoints.Add(point);
|
||||
}
|
||||
|
||||
if (allPoints.Count > 1)
|
||||
{
|
||||
DrawSmoothCombinedCurve(gr, allPoints, this.Count - QuanTAlib.WarmupPeriod - rightIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSmoothCombinedCurve(Graphics gr, List<Point> allPoints, int hotCount)
|
||||
{
|
||||
if (allPoints.Count < 2) return;
|
||||
|
||||
using (Pen defaultPen = new(Series!.Color, Series.Width) { DashStyle = ConvertLineStyleToDashStyle(Series.Style) })
|
||||
using (Pen coldPen = new(Series!.Color, Series.Width) { DashStyle = DashStyle.Dot })
|
||||
{
|
||||
// Draw the hot part
|
||||
if (hotCount > 0)
|
||||
{
|
||||
var hotPoints = allPoints.Take(Math.Min(hotCount + 1, allPoints.Count)).ToArray();
|
||||
gr.DrawCurve(defaultPen, hotPoints, 0, hotPoints.Length - 1, (float)0.1);
|
||||
}
|
||||
|
||||
// Draw the cold part
|
||||
if (ShowColdValues && hotCount < allPoints.Count)
|
||||
{
|
||||
var coldPoints = allPoints.Skip(Math.Max(0, hotCount)).ToArray();
|
||||
gr.DrawCurve(coldPen, coldPoints, 0, coldPoints.Length - 1, (float)0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
private DashStyle ConvertLineStyleToDashStyle(LineStyle lineStyle)
|
||||
{
|
||||
return lineStyle switch
|
||||
{
|
||||
LineStyle.Solid => DashStyle.Solid,
|
||||
LineStyle.Dash => DashStyle.Dash,
|
||||
LineStyle.Dot => DashStyle.Dot,
|
||||
LineStyle.DashDot => DashStyle.DashDot,
|
||||
_ => DashStyle.Solid,
|
||||
};
|
||||
}
|
||||
protected void DrawText(Graphics gr, string text, Rectangle clientRect)
|
||||
{
|
||||
Font font = new Font("Inter", 8);
|
||||
SizeF textSize = gr.MeasureString(text, font);
|
||||
RectangleF textRect = new RectangleF(clientRect.Left + 5,
|
||||
clientRect.Bottom - textSize.Height - 10,
|
||||
textSize.Width + 10, textSize.Height + 10);
|
||||
gr.FillRectangle(SystemBrushes.ControlDarkDark, textRect);
|
||||
gr.DrawString(text, font, Brushes.White, new PointF(textRect.X + 6, textRect.Y + 5));
|
||||
}
|
||||
protected string GetName(int pType)
|
||||
{
|
||||
return pType switch
|
||||
{
|
||||
1 => "Open",
|
||||
2 => "High",
|
||||
3 => "Low",
|
||||
4 => "Close",
|
||||
5 => "Median",
|
||||
6 => "Midpoint",
|
||||
7 => "Mean",
|
||||
8 => "Typical",
|
||||
9 => "Average",
|
||||
10 => "Weighted",
|
||||
_ => "N/A"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user