Add new data structures and event handling classes for trading platform. Include base classes, value and bar structs, event arguments, emitters, listeners. Update ruleset for SonarLint.

This commit is contained in:
Miha Kralj
2024-07-25 17:42:09 -07:00
parent f7fd3fbf9f
commit 7dd938c368
86 changed files with 9367 additions and 9153 deletions
+284 -278
View File
@@ -1,278 +1,284 @@
using System;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverage_chart : Indicator {
#region Parameters
[InputParameter("MA1: Type:", 0, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA1type = 15;
[InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)]
private int MA1Period = 10;
[InputParameter("MA1: Data source:", 2, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA1DataSource = 3;
[InputParameter("MA2: Type:", 3, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA2type = 16;
[InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)]
private int MA2Period = 50;
[InputParameter("MA2: Data source:", 5, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA2DataSource = 8;
[InputParameter("Long trades", 6)]
private bool LongTrades = true;
[InputParameter("Short trades", 6)]
private bool ShortTrades = true;
#endregion Parameters
protected HistoricalData History;
private TBars bars;
///////
private TSeries MA1, MA2;
private CROSS_Series trades;
private COMPARE_Series overunder;
///////
public MovingAverage_chart() {
this.SeparateWindow = false;
this.Name = "MAs Crossover";
this.AddLineSeries("MA1", Color.LimeGreen, 2, LineStyle.Solid);
this.AddLineSeries("MA2", Color.OrangeRed, 2, LineStyle.Solid);
}
protected override void OnInit() {
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
this.Name = "MAs Cross: [ ";
switch (MA1type) {
case 0:
MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period);
this.Name += $"FWMA";
break;
case 8:
MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period);
MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : ";
switch (MA2type) {
case 0:
MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period);
this.Name += $"FWMA";
break;
case 8:
MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period);
MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]";
overunder = new(MA1, MA2);
trades = new(MA1, MA2);
}
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
this.GetPrice(PriceType.High),
this.GetPrice(PriceType.Low),
this.GetPrice(PriceType.Close),
this.GetPrice(PriceType.Volume), update);
this.SetValue(this.MA1[^1].v, lineIndex: 0);
this.SetValue(this.MA2[^1].v, lineIndex: 1);
if (trades[^1].v == 1) {
this.EndCloud(0, 1, Color.Empty);
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Green));
}
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
if (trades[^1].v == -1) {
this.EndCloud(0, 1, Color.Empty);
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Red));
}
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
}
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) {return;}
Graphics graphics = args.Graphics;
var mainWindow = this.CurrentChart.MainWindow;
int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left));
int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right)));
int historycount = HistoricalData.Count;
int ymax = mainWindow.ClientRectangle.Height;
int xmax = mainWindow.ClientRectangle.Width;
/*
for (int i = leftIndex; i <= rightIndex; i++) {
int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i)));
int width = this.CurrentChart.BarsWidth;
int height = (int)((equity[i+historycount].v) *proportion);
Brush bb = Brushes.DarkSlateGray;
bb = (overunder[i+historycount].v>0 && LongTrades)? Brushes.Green : bb;
bb = (overunder[i + historycount].v < 0 && ShortTrades) ? Brushes.Red : bb;
graphics.FillRectangle(bb, xi, ymax - height, width, height);
}
*/
}
}
using System;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverage_chart : Indicator {
#region Parameters
[InputParameter("MA1: Type:", 0, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA1type = 15;
[InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)]
private int MA1Period = 10;
[InputParameter("MA1: Data source:", 2, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA1DataSource = 3;
[InputParameter("MA2: Type:", 3, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA2type = 16;
[InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)]
private int MA2Period = 50;
[InputParameter("MA2: Data source:", 5, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA2DataSource = 8;
[InputParameter("Long trades", 6)]
private bool LongTrades = true;
[InputParameter("Short trades", 6)]
private bool ShortTrades = true;
#endregion Parameters
protected HistoricalData History;
private TBars bars;
///////
private TSeries MA1, MA2;
private CROSS_Series trades;
private COMPARE_Series overunder;
///////
public MovingAverage_chart() {
this.SeparateWindow = false;
this.Name = "MAs Crossover";
this.AddLineSeries("MA1", Color.LimeGreen, 2, LineStyle.Solid);
this.AddLineSeries("MA2", Color.OrangeRed, 2, LineStyle.Solid);
}
protected override void OnInit() {
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
this.Name = "MAs Cross: [ ";
switch (MA1type) {
case 0:
MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period);
this.Name += $"FWMA";
break;
case 8:
MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period);
MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : ";
switch (MA2type) {
case 0:
MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period);
this.Name += $"FWMA";
break;
case 8:
MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period);
MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]";
int maxKeep = Math.Max(Math.Max(this.MA1Period, this.MA2Period), 100);
MA1.Keep = maxKeep;
MA2.Keep = maxKeep;
trades.Keep = maxKeep;
overunder.Keep = maxKeep;
overunder = new(MA1, MA2);
trades = new(MA1, MA2);
}
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
this.GetPrice(PriceType.High),
this.GetPrice(PriceType.Low),
this.GetPrice(PriceType.Close),
this.GetPrice(PriceType.Volume), update);
this.SetValue(this.MA1[^1].v, lineIndex: 0);
this.SetValue(this.MA2[^1].v, lineIndex: 1);
if (trades[^1].v == 1) {
this.EndCloud(0, 1, Color.Empty);
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Green));
}
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
if (trades[^1].v == -1) {
this.EndCloud(0, 1, Color.Empty);
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Red));
}
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
}
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) {return;}
Graphics graphics = args.Graphics;
var mainWindow = this.CurrentChart.MainWindow;
int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left));
int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right)));
int historycount = HistoricalData.Count;
int ymax = mainWindow.ClientRectangle.Height;
int xmax = mainWindow.ClientRectangle.Width;
/*
for (int i = leftIndex; i <= rightIndex; i++) {
int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i)));
int width = this.CurrentChart.BarsWidth;
int height = (int)((equity[i+historycount].v) *proportion);
Brush bb = Brushes.DarkSlateGray;
bb = (overunder[i+historycount].v>0 && LongTrades)? Brushes.Green : bb;
bb = (overunder[i + historycount].v < 0 && ShortTrades) ? Brushes.Red : bb;
graphics.FillRectangle(bb, xi, ymax - height, width, height);
}
*/
}
}
+307 -298
View File
@@ -1,298 +1,307 @@
using System;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverageSlope_chart : Indicator {
#region Parameters
[InputParameter("MA1: Type:", 0, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA1type = 16;
[InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)]
private int MA1Period = 10;
[InputParameter("MA1: Data source:", 2, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA1DataSource = 3;
[InputParameter("MA2: Type:", 3, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA2type = 6;
[InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)]
private int MA2Period = 50;
[InputParameter("MA2: Data source:", 5, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA2DataSource = 8;
[InputParameter("Data required for slope calc:", 6, 2, 10, 1, 1)]
private int SlopePeriod = 3;
[InputParameter("Long trades", 7)]
private bool LongTrades = true;
[InputParameter("Short trades", 8)]
private bool ShortTrades;
#endregion Parameters
protected HistoricalData History;
private TBars bars;
///////
private TSeries MA1, MA2;
private SLOPE_Series sMA1, sMA2;
private CROSS_Series sig1, sig2;
private bool inLong, inShort;
///////
public MovingAverageSlope_chart() {
this.SeparateWindow = false;
this.Name = "Slopes convergence";
this.AddLineSeries("MA1", Color.DarkSlateGray, 2, LineStyle.Solid);
this.AddLineSeries("MA2", Color.DarkSlateGray, 2, LineStyle.Solid);
}
protected override void OnInit() {
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
this.Name = "Slopes convergence: [ ";
switch (MA1type) {
case 0:
MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period);
this.Name += $"FWMA";
break;
case 8:
MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period);
MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : ";
switch (MA2type) {
case 0:
MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period);
this.Name += $"FWMA";
break;
case 8:
MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period);
MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]";
sMA1 = new(MA1, SlopePeriod);
sMA2 = new(MA2, SlopePeriod);
sig1 = new(sMA1, 0);
sig2 = new(sMA2, 0);
}
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(),this.Open(), this.High(), this.Low(), this.Close(), this.Volume(), update);
this.SetValue(this.MA1[^1].v, lineIndex: 0);
this.SetValue(this.MA2[^1].v, lineIndex: 1);
Color s1Color= (this.sMA1[^1].v > 0)?Color.LimeGreen:Color.OrangeRed;
Color s2Color = (this.sMA2[^1].v > 0) ? Color.LimeGreen : Color.OrangeRed;
this.LinesSeries[0].SetMarker(0,s1Color);
this.LinesSeries[1].SetMarker(0,s2Color);
if (sig1[^1].v > 0 || sig2[^1].v > 0) {
if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0 && LongTrades)
{
inLong = true;
this.BeginCloud(0, 1, Color.FromArgb(127, Color.DarkGreen));
this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v)? 0 : 1 ].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
}
else {
this.EndCloud(0, 1, Color.Empty);
if (inShort)
{
this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow));
inShort = false;
}
}
}
if (sig1[^1].v < 0 || sig2[^1].v < 0) {
if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0 && ShortTrades)
{
inShort = true;
this.BeginCloud(0, 1, Color.FromArgb(100, Color.Red));
this.LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow));
}
else {
this.EndCloud(0, 1, Color.Empty);
if (inLong) {
LinesSeries[(this.MA1[^1].v > this.MA2[^1].v)?1:0].SetMarker(1, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
inLong = false;
}
}
}
}
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) {return;}
Graphics graphics = args.Graphics;
var mainWindow = this.CurrentChart.MainWindow;
int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left));
int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right)));
/*
int historycount = HistoricalData.Count;
int ymax = mainWindow.ClientRectangle.Height;
for (int i = leftIndex; i <= rightIndex; i++) {
int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i)));
int width = this.CurrentChart.BarsWidth;
int height = (int)((equity[i+historycount].v) *proportion);
Brush bb = Brushes.DarkSlateGray;
bb = (overunder[i+historycount].v>0 && LongTrades)? Brushes.Green : bb;
bb = (overunder[i + historycount].v < 0 && ShortTrades) ? Brushes.Red : bb;
graphics.FillRectangle(bb, xi, ymax - height, width, height);
}
*/
}
}
using System;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverageSlope_chart : Indicator {
#region Parameters
[InputParameter("MA1: Type:", 0, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA1type = 16;
[InputParameter("MA1: Smoothing period:", 1, 1, 999, 1, 1)]
private int MA1Period = 10;
[InputParameter("MA1: Data source:", 2, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA1DataSource = 3;
[InputParameter("MA2: Type:", 3, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MA2type = 6;
[InputParameter("MA2: Smoothing period:", 4, 1, 999, 1, 1)]
private int MA2Period = 50;
[InputParameter("MA2: Data source:", 5, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int MA2DataSource = 8;
[InputParameter("Data required for slope calc:", 6, 2, 10, 1, 1)]
private int SlopePeriod = 3;
[InputParameter("Long trades", 7)]
private bool LongTrades = true;
[InputParameter("Short trades", 8)]
private bool ShortTrades;
#endregion Parameters
protected HistoricalData History;
private TBars bars;
///////
private TSeries MA1, MA2;
private SLOPE_Series sMA1, sMA2;
private CROSS_Series sig1, sig2;
private bool inLong, inShort;
///////
public MovingAverageSlope_chart() {
this.SeparateWindow = false;
this.Name = "Slopes convergence";
this.AddLineSeries("MA1", Color.DarkSlateGray, 2, LineStyle.Solid);
this.AddLineSeries("MA2", Color.DarkSlateGray, 2, LineStyle.Solid);
}
protected override void OnInit() {
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
this.Name = "Slopes convergence: [ ";
switch (MA1type) {
case 0:
MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA1 = new EMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA1 = new WMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA1 = new T3_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA1 = new SMMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA1 = new TRIMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA1 = new DWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA1 = new FWMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period);
this.Name += $"FWMA";
break;
case 8:
MA1 = new DEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA1 = new TEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA1 = new ALMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA1 = new HMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA1 = new HEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA1Period);
MA1 = new MAMA_Series(source: bars.Select(this.MA1DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA1 = new KAMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA1 = new ZLEMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA1 = new JMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : ";
switch (MA2type) {
case 0:
MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMA";
break;
case 1:
MA2 = new EMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"EMA";
break;
case 2:
MA2 = new WMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"WMA";
break;
case 3:
MA2 = new T3_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"T3";
break;
case 4:
MA2 = new SMMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMMA";
break;
case 5:
MA2 = new TRIMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TRIMA";
break;
case 6:
MA2 = new DWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DWMA";
break;
case 7:
MA2 = new FWMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period);
this.Name += $"FWMA";
break;
case 8:
MA2 = new DEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"DEMA";
break;
case 9:
MA2 = new TEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"TEMA";
break;
case 10:
MA2 = new ALMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ALMA";
break;
case 11:
MA2 = new HMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HMA";
break;
case 12:
MA2 = new HEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"HEMA";
break;
case 13:
double factor = 1.015 * Math.Exp(-0.043 * (double)this.MA2Period);
MA2 = new MAMA_Series(source: bars.Select(this.MA2DataSource), fastlimit: factor, slowlimit: factor * 0.1, useNaN: false);
this.Name += $"MAMA";
break;
case 14:
MA2 = new KAMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"KAMA";
break;
case 15:
MA2 = new ZLEMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"ZLEMA";
break;
default:
MA2 = new JMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"JMA";
break;
}
this.Name += $"({MA2Period}:{TBars.SelectStr(this.MA2DataSource)}) ]";
sMA1 = new(MA1, SlopePeriod);
sMA2 = new(MA2, SlopePeriod);
sig1 = new(sMA1, 0);
sig2 = new(sMA2, 0);
int maxKeep = Math.Max(Math.Max(this.MA1Period, this.MA2Period), 100);
MA1.Keep = maxKeep;
MA2.Keep = maxKeep;
sMA1.Keep = maxKeep;
sMA2.Keep = maxKeep;
sig1.Keep = maxKeep;
sig2.Keep = maxKeep;
}
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(),this.Open(), this.High(), this.Low(), this.Close(), this.Volume(), update);
this.SetValue(this.MA1[^1].v, lineIndex: 0);
this.SetValue(this.MA2[^1].v, lineIndex: 1);
Color s1Color= (this.sMA1[^1].v > 0)?Color.LimeGreen:Color.OrangeRed;
Color s2Color = (this.sMA2[^1].v > 0) ? Color.LimeGreen : Color.OrangeRed;
this.LinesSeries[0].SetMarker(0,s1Color);
this.LinesSeries[1].SetMarker(0,s2Color);
if (sig1[^1].v > 0 || sig2[^1].v > 0) {
if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0 && LongTrades)
{
inLong = true;
this.BeginCloud(0, 1, Color.FromArgb(127, Color.DarkGreen));
this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v)? 0 : 1 ].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
}
else {
this.EndCloud(0, 1, Color.Empty);
if (inShort && this.Count > 1)
{
this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow));
inShort = false;
}
}
}
if (sig1[^1].v < 0 || sig2[^1].v < 0) {
if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0 && ShortTrades)
{
inShort = true;
this.BeginCloud(0, 1, Color.FromArgb(100, Color.Red));
this.LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow));
}
else {
this.EndCloud(0, 1, Color.Empty);
if (inLong && this.Count > 1) {
LinesSeries[(this.MA1[^1].v > this.MA2[^1].v)?1:0].SetMarker(1, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
inLong = false;
}
}
}
}
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) {return;}
Graphics graphics = args.Graphics;
var mainWindow = this.CurrentChart.MainWindow;
int leftIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left));
int rightIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right)));
/*
int historycount = HistoricalData.Count;
int ymax = mainWindow.ClientRectangle.Height;
for (int i = leftIndex; i <= rightIndex; i++) {
int xi = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - 1 - i)));
int width = this.CurrentChart.BarsWidth;
int height = (int)((equity[i+historycount].v) *proportion);
Brush bb = Brushes.DarkSlateGray;
bb = (overunder[i+historycount].v>0 && LongTrades)? Brushes.Green : bb;
bb = (overunder[i + historycount].v < 0 && ShortTrades) ? Brushes.Red : bb;
graphics.FillRectangle(bb, xi, ymax - height, width, height);
}
*/
}
}
+97 -96
View File
@@ -1,96 +1,97 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
using TradingPlatform.BusinessLayer.Chart;
namespace QuanTAlib;
public class JMA_chart : Indicator {
#region Parameters
[InputParameter("Data source", 0, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int DataSource = 3;
[InputParameter("Smoothing period", 1, 1, 999, 1, 1)]
private int Period = 9;
[InputParameter("Volatility short", 2, 3, 50, 1, 1)]
private int Vshort = 10;
[InputParameter("Volatility long", 3, 20, 500, 1, 1)]
private int Vlong = 65;
[InputParameter("Phase", 4, -100, 100, 1, 2)]
private double Jphase;
#endregion Parameters
///////
private JMA_Series indicator;
///////
protected TBars bars;
protected IChartWindow mainWindow;
protected Graphics graphics;
protected int firstOnScreenBarIndex, lastOnScreenBarIndex;
protected HistoricalData History;
protected int HistPeriod;
public JMA_chart() {
Name = "JMA - Jurik Moving Avg";
Description = "Jurik Moving Average description";
AddLineSeries(lineName: "JMA", lineColor: Color.Yellow, lineWidth: 3,lineStyle: LineStyle.Solid);
SeparateWindow = false;
HistPeriod = Period;
}
protected override void OnInit() {
base.OnInit();
bars = new();
var dur1 = this.HistoricalData.FromTime;
var dur = this.HistoricalData.Period.Duration.TotalSeconds * (HistPeriod * 4); //seconds of two periods
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
indicator = new(source: bars.Select(DataSource), period: Period, phase: Jphase, vshort: Vshort, vlong: Vlong, useNaN: true);
}
protected override void OnUpdate(UpdateArgs args) {
base.OnUpdate(args);
bars.Add(Time(), GetPrice(PriceType.Open),
GetPrice(PriceType.High),
GetPrice(PriceType.Low),
GetPrice(PriceType.Close),
GetPrice(PriceType.Volume),
update: !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar));
this.SetValue(indicator[^1].v, lineIndex: 0);
}
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) {
return;
}
graphics = args.Graphics;
mainWindow = this.CurrentChart.MainWindow;
DateTime leftTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left);
DateTime rightTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right);
firstOnScreenBarIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(leftTime);
lastOnScreenBarIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(rightTime));
}
}
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
using TradingPlatform.BusinessLayer.Chart;
namespace QuanTAlib;
public class JMA_chart : Indicator {
#region Parameters
[InputParameter("Data source", 0, variants: new object[]
{ "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
"OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
private int DataSource = 3;
[InputParameter("Smoothing period", 1, 1, 999, 1, 1)]
private int Period = 9;
[InputParameter("Volatility short", 2, 3, 50, 1, 1)]
private int Vshort = 10;
[InputParameter("Volatility long", 3, 20, 500, 1, 1)]
private int Vlong = 65;
[InputParameter("Phase", 4, -100, 100, 1, 2)]
private double Jphase;
#endregion Parameters
///////
private JMA_Series indicator;
///////
protected TBars bars;
protected IChartWindow mainWindow;
protected Graphics graphics;
protected int firstOnScreenBarIndex, lastOnScreenBarIndex;
protected HistoricalData History;
protected int HistPeriod;
public JMA_chart() {
Name = "JMA - Jurik Moving Avg";
Description = "Jurik Moving Average description";
AddLineSeries(lineName: "JMA", lineColor: Color.Yellow, lineWidth: 3,lineStyle: LineStyle.Solid);
SeparateWindow = false;
HistPeriod = Period;
}
protected override void OnInit() {
base.OnInit();
bars = new();
var dur1 = this.HistoricalData.FromTime;
var dur = this.HistoricalData.Period.Duration.TotalSeconds * (HistPeriod * 4); //seconds of two periods
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
indicator = new(source: bars.Select(DataSource), period: Period, phase: Jphase, vshort: Vshort, vlong: Vlong, useNaN: true);
indicator.Keep = Math.Max(Period, 100);
}
protected override void OnUpdate(UpdateArgs args) {
base.OnUpdate(args);
bars.Add(Time(), GetPrice(PriceType.Open),
GetPrice(PriceType.High),
GetPrice(PriceType.Low),
GetPrice(PriceType.Close),
GetPrice(PriceType.Volume),
update: !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar));
this.SetValue(indicator[^1].v, lineIndex: 0);
}
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) {
return;
}
graphics = args.Graphics;
mainWindow = this.CurrentChart.MainWindow;
DateTime leftTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left);
DateTime rightTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right);
firstOnScreenBarIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(leftTime);
lastOnScreenBarIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(rightTime));
}
}
+95 -95
View File
@@ -1,95 +1,95 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class TrailingStop_chart : Indicator {
#region Parameters
[InputParameter("Period", 0, 1, 100, 1, 1)]
protected int _period = 30;
[InputParameter("Factor", 1, 1, 100, 0.1, 1)]
protected double _factor = 10;
[InputParameter("Long TS", 2)]
private bool _LongTS = true;
[InputParameter("Short TS", 3)]
private bool _ShortTS = true;
#endregion Parameters
///////
private HistoricalData History;
private TBars bars;
private ATR_Series _atr;
private double _tslineL, _ratchetL, _tslineS, _ratchetS;
///////
public TrailingStop_chart() {
Name = $"ATR Trailing Stop";
AddLineSeries(lineName: "TrailingATR Long", lineColor: Color.Yellow, lineWidth: 1,lineStyle: LineStyle.Dot);
AddLineSeries(lineName: "Ratchet Long", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid);
AddLineSeries(lineName: "TrailingATR Short", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot);
AddLineSeries(lineName: "Ratchet Short", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid);
SeparateWindow = false;
}
protected override void OnInit() {
this.Name = $"Trailing Stop (ATR:{_period}, Mult:{_factor:f2})";
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
_atr = new(source: bars, _period, useNaN: true);
_ratchetL = Double.NegativeInfinity;
_ratchetS = Double.PositiveInfinity;
this.LinesSeries[0].Visible = _LongTS;
this.LinesSeries[1].Visible = _LongTS;
this.LinesSeries[2].Visible = _ShortTS;
this.LinesSeries[3].Visible = _ShortTS;
}
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
this.GetPrice(PriceType.High),
this.GetPrice(PriceType.Low),
this.GetPrice(PriceType.Close),
this.GetPrice(PriceType.Volume), update);
_tslineL = bars.High[^1].v - (_factor * _atr[^1].v);
_ratchetL = Math.Max(_tslineL,_ratchetL);
if (_ratchetL > bars.Low[^1].v) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
_ratchetL = _tslineL;
}
_tslineS = bars.High[^1].v + (_factor * _atr[^1].v);
_ratchetS = Math.Min(_tslineS, _ratchetS);
if (_ratchetS < bars.High[^1].v) {
this.LinesSeries[3].SetMarker(0, new IndicatorLineMarker(Color.Yellow, upperIcon: IndicatorLineMarkerIconType.UpArrow));
_ratchetS = _tslineS;
}
this.SetValue(_tslineL, lineIndex: 0);
this.SetValue(_ratchetL, lineIndex: 1);
this.SetValue(_tslineS, lineIndex: 2);
this.SetValue(_ratchetS, lineIndex: 3);
}
}
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class TrailingStop_chart : Indicator {
#region Parameters
[InputParameter("Period", 0, 1, 100, 1, 1)]
protected int _period = 30;
[InputParameter("Factor", 1, 1, 100, 0.1, 1)]
protected double _factor = 10;
[InputParameter("Long TS", 2)]
private bool _LongTS = true;
[InputParameter("Short TS", 3)]
private bool _ShortTS = true;
#endregion Parameters
///////
private HistoricalData History;
private TBars bars;
private ATR_Series _atr;
private double _tslineL, _ratchetL, _tslineS, _ratchetS;
///////
public TrailingStop_chart() {
Name = $"ATR Trailing Stop";
AddLineSeries(lineName: "TrailingATR Long", lineColor: Color.Yellow, lineWidth: 1,lineStyle: LineStyle.Dot);
AddLineSeries(lineName: "Ratchet Long", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid);
AddLineSeries(lineName: "TrailingATR Short", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot);
AddLineSeries(lineName: "Ratchet Short", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid);
SeparateWindow = false;
}
protected override void OnInit() {
this.Name = $"Trailing Stop (ATR:{_period}, Mult:{_factor:f2})";
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
_atr = new(source: bars, _period, useNaN: true);
_ratchetL = Double.NegativeInfinity;
_ratchetS = Double.PositiveInfinity;
this.LinesSeries[0].Visible = _LongTS;
this.LinesSeries[1].Visible = _LongTS;
this.LinesSeries[2].Visible = _ShortTS;
this.LinesSeries[3].Visible = _ShortTS;
}
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
this.GetPrice(PriceType.High),
this.GetPrice(PriceType.Low),
this.GetPrice(PriceType.Close),
this.GetPrice(PriceType.Volume), update);
_tslineL = bars.High[^1].v - (_factor * _atr[^1].v);
_ratchetL = Math.Max(_tslineL,_ratchetL);
if (_ratchetL > bars.Low[^1].v) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
_ratchetL = _tslineL;
}
_tslineS = bars.High[^1].v + (_factor * _atr[^1].v);
_ratchetS = Math.Min(_tslineS, _ratchetS);
if (_ratchetS < bars.High[^1].v) {
this.LinesSeries[3].SetMarker(0, new IndicatorLineMarker(Color.Yellow, upperIcon: IndicatorLineMarkerIconType.UpArrow));
_ratchetS = _tslineS;
}
this.SetValue(_tslineL, lineIndex: 0);
this.SetValue(_ratchetL, lineIndex: 1);
this.SetValue(_tslineS, lineIndex: 2);
this.SetValue(_ratchetS, lineIndex: 3);
}
}
+55 -55
View File
@@ -1,56 +1,56 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>preview</LangVersion>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Platforms>AnyCPU</Platforms>
<AlgoType>Indicator</AlgoType>
<AssemblyName>QuanTAlib_Indicators</AssemblyName>
<RootNamespace>QuanTAlib</RootNamespace>
<DebugType>embedded</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<Nullable>disable</Nullable>
<SignAssembly>False</SignAssembly>
<CodeAnalysisRuleSet>..\.sonarlint\mihakralj_quantalibcsharp.ruleset</CodeAnalysisRuleSet>
<AssemblyVersion>0.2.1.0</AssemblyVersion>
<FileVersion>0.2.1.0</FileVersion>
<InformationalVersion>0.2.1-dev.2+Branch.dev.Sha.cb5fe2dc86a78fe9358da810d17952c82299ed3d</InformationalVersion>
<Version>0.2.1-dev.2</Version>
<SuppressNETSdkWarningProperty>NETSDK1057</SuppressNETSdkWarningProperty>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
<NoWarn>NETSDK1057</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>True</Optimize>
<WarningLevel>3</WarningLevel>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<PlatformTarget>anycpu</PlatformTarget>
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>embedded</DebugType>
<Optimize>True</Optimize>
<WarningLevel>3</WarningLevel>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<PlatformTarget>anycpu</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles=".\bin\$(Configuration)\QuanTAlib_Indicators.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" />
</Target>
<ItemGroup>
<Compile Include="..\Calculations\**\*.cs" Exclude="..\Calculations\obj\**">
<Link>QuanTAlib\%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="TradingPlatform.BusinessLayer">
<HintPath>..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
</Reference>
</ItemGroup>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>preview</LangVersion>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Platforms>AnyCPU</Platforms>
<AlgoType>Indicator</AlgoType>
<AssemblyName>QuanTAlib_Indicators</AssemblyName>
<RootNamespace>QuanTAlib</RootNamespace>
<DebugType>embedded</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<Nullable>disable</Nullable>
<SignAssembly>False</SignAssembly>
<CodeAnalysisRuleSet>..\.sonarlint\mihakralj_quantalibcsharp.ruleset</CodeAnalysisRuleSet>
<AssemblyVersion>0.2.1.0</AssemblyVersion>
<FileVersion>0.2.1.0</FileVersion>
<InformationalVersion>0.2.1-dev.2+Branch.dev.Sha.cb5fe2dc86a78fe9358da810d17952c82299ed3d</InformationalVersion>
<Version>0.2.1-dev.2</Version>
<SuppressNETSdkWarningProperty>NETSDK1057</SuppressNETSdkWarningProperty>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
<NoWarn>NETSDK1057</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>True</Optimize>
<WarningLevel>3</WarningLevel>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<PlatformTarget>anycpu</PlatformTarget>
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>embedded</DebugType>
<Optimize>True</Optimize>
<WarningLevel>3</WarningLevel>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<PlatformTarget>anycpu</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles=".\bin\$(Configuration)\QuanTAlib_Indicators.dll" DestinationFolder="\Quantower\Settings\Scripts\Indicators\QuanTAlib" />
</Target>
<ItemGroup>
<Compile Include="..\Calculations\**\*.cs" Exclude="..\Calculations\obj\**">
<Link>QuanTAlib\%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="TradingPlatform.BusinessLayer">
<HintPath>..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
</Reference>
</ItemGroup>
</Project>