Update file paths for QuanTAlib packages in main_automation.yml

This commit is contained in:
Miha Kralj
2023-04-12 12:23:12 -07:00
parent badea98dc0
commit b99d451ea8
22 changed files with 403 additions and 253 deletions
+8
View File
@@ -0,0 +1,8 @@
# Top-most EditorConfig file
root = true
[*.{cs,vb}]
# Suppress S3776 (Cognitive Complexity)
dotnet_diagnostic.S3776.severity = none
# Suppress CA1416 (Platform Compatibility)
dotnet_diagnostic.CA1416.severity = none
+53 -50
View File
@@ -10,13 +10,21 @@ on:
jobs:
build_test:
runs-on: windows-latest
#runs-on: windows-latest
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
############## Install tools
- name: Create Quantower folder at root
run: |
sudo mkdir -p /Quantower/
sudo chmod -R 777 /Quantower
- name: Install .NET
uses: actions/setup-dotnet@v3
with:
@@ -34,31 +42,14 @@ jobs:
uses: gittools/actions/gitversion/execute@v0
with:
useConfigFile: true
configFilePath: /a/QuanTAlib/QuanTAlib/GitVersion.yml
#configFilePath: GitVersion.yml
updateAssemblyInfo: true
- name: Display GitVersion variables (without prefix)
run: |
echo "Major: ${{ steps.gitversion.outputs.major }}"
echo "Minor: ${{ steps.gitversion.outputs.minor }}"
echo "Patch: ${{ steps.gitversion.outputs.patch }}"
echo "PreReleaseTag: ${{ steps.gitversion.outputs.preReleaseTag }}"
echo "PreReleaseTagWithDash: ${{ steps.gitversion.outputs.preReleaseTagWithDash }}"
echo "PreReleaseLabel: ${{ steps.gitversion.outputs.preReleaseLabel }}"
echo "PreReleaseNumber: ${{ steps.gitversion.outputs.preReleaseNumber }}"
echo "WeightedPreReleaseNumber: ${{ steps.gitversion.outputs.weightedPreReleaseNumber }}"
echo "FullBuildMetaData: ${{ steps.gitversion.outputs.fullBuildMetaData }}"
echo "MajorMinorPatch: ${{ steps.gitversion.outputs.majorMinorPatch }}"
echo "SemVer: ${{ steps.gitversion.outputs.semVer }}"
echo "AssemblySemVer: ${{ steps.gitversion.outputs.assemblySemVer }}"
echo "AssemblySemFileVer: ${{ steps.gitversion.outputs.assemblySemFileVer }}"
echo "FullSemVer: ${{ steps.gitversion.outputs.fullSemVer }}"
echo "InformationalVersion: ${{ steps.gitversion.outputs.informationalVersion }}"
- name: Install JDK11 for Sonar Scanner
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: 1.11
java-version: 11
distribution: 'zulu'
- name: Install JetBrains
run: dotnet tool install JetBrains.dotCover.GlobalTool --global
@@ -74,42 +65,52 @@ jobs:
run: dotnet sonarscanner begin /o:"mihakralj" /k:"mihakralj_QuanTAlib"
/d:sonar.login="${{ secrets.SONAR_TOKEN }}"
/d:sonar.host.url="https://sonarcloud.io"
/d:sonar.cs.dotcover.reportsPaths=./coveragereport.html
/d:sonar.cs.dotcover.reportsPaths=./dotcover.xml
############# Build and test
- name: Build Main branch of QuanTAlib DLL
if: ${{ github.ref != 'refs/heads/dev' }}
run: dotnet build ./Calculations/Calculations.csproj --verbosity detailed --configuration Release --nologo -p:PackageVersion=${{ steps.gitversion.outputs.MajorMinorPatch }}
run: dotnet build ./Calculations/Calculations.csproj --configuration Release --nologo -p:PackageVersion=${{ steps.gitversion.outputs.MajorMinorPatch }}
- name: Build dev branch of QuanTAlib DLL
if: ${{ github.ref == 'refs/heads/dev' }}
run: dotnet build ./Calculations/Calculations.csproj --verbosity detailed --configuration Release --nologo -p:PackageVersion=${{ steps.gitversion.outputs.FullSemVer }}
run: dotnet build ./Calculations/Calculations.csproj --configuration Release --nologo -p:PackageVersion=${{ steps.gitversion.outputs.FullSemVer }}
- name: Build Indicators DLL
run: dotnet build ./Indicators/Indicators.csproj --verbosity detailed --configuration Release --nologo
run: dotnet build ./Indicators/Indicators.csproj --configuration Release --nologo
- name: Build Strategies DLL
run: dotnet build ./Strategies/Strategies.csproj --verbosity detailed --configuration Release --nologo
run: dotnet build ./Strategies/Strategies.csproj --configuration Release --nologo
- name: DotCover Test XML
run: dotnet dotcover test ./Tests/Tests.csproj --verbosity minimal --dcReportType=DetailedXML --dcoutput=./coveragereport.xml
- name: DotCover Test
run: dotnet dotcover test Tests/Tests.csproj --dcReportType=DetailedXML --dcReportType=HTML --dcoutput=dotcover.xml --dcoutput=dotcover.html
- name: Coverlet Test
run: dotnet test -p:CollectCoverage=true --collect:"XPlat Code Coverage" --results-directory "./"
- name: Upload coverage reports to Codecov
############## Report to Sonar/CodeCov/Codacy
- name: Move coverage report to project root
run: |
report=$(find . -name '*coverage.cobertura.xml' | head -1)
mv "$report" ./coverage.cobertura.xml
- name: Upload to Codacy
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: "*cover*.xml"
- name: Upload to Codecov
uses: codecov/codecov-action@v3
with:
files: ./coveragereport.xml
files: cover*
verbose: true
- name: Sonar reporter
- name: Upload to Sonar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: dotnet sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
- name: Codacy coverage reporter
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: ./coveragereport.xml
############## Publish dev release
- name: Publish dev release assets
if: ${{ github.ref == 'refs/heads/dev' }}
@@ -120,18 +121,20 @@ jobs:
prerelease: true
overwrite: true
release_name: ${{ steps.gitversion.outputs.SemVer }}
tag_name: ${{ steps.gitversion.outputs.SemVer }}
tag_name: prerelease
release_config: |
.\Calculations\bin\Release\net6.0\QuanTAlib.dll
.\Indicators\bin\Release\QuanTAlib_Indicators.dll
.\Strategies\bin\Release\QuanTAlib_Strategies.dll
Calculations/bin/Release/net6.0/QuanTAlib.dll
Indicators/bin/Release/QuanTAlib_Indicators.dll
Strategies/bin/Release/QuanTAlib_Strategies.dll
- name: Push package to myget.org
run: dotnet nuget push '.\Calculations\bin\Release\QuanTAlib.*.nupkg'
run: dotnet nuget push 'Calculations/bin/Release/QuanTAlib.*.nupkg'
--api-key ${{ secrets.MYGET_DEPLOY_KEY_QUANTALIB }}
--source https://www.myget.org/F/quantalib/api/v2/package
--skip-duplicate
############## Publish main release
- name: Publish main release assets
if: ${{ github.ref == 'refs/heads/main' }}
uses: SourceSprint/upload-multiple-releases@1.0.7
@@ -141,15 +144,15 @@ jobs:
prerelease: false
overwrite: true
release_name: ${{ steps.gitversion.outputs.MajorMinorPatch }}
tag_name: ${{ steps.gitversion.outputs.MajorMinorPatch }}
tag_name: latest
release_config: |
.\Calculations\bin\Release\net6.0\QuanTAlib.dll
.\Indicators\bin\Release\QuanTAlib_Indicators.dll
.\Strategies\bin\Release\QuanTAlib_Strategies.dll
Calculations/bin/Release/net6.0/QuanTAlib.dll
Indicators/bin/Release/QuanTAlib_Indicators.dll
Strategies/bin/Release/QuanTAlib_Strategies.dll
- name: Push package to nuget.org
if: ${{ github.ref == 'refs/heads/main' }}
run: dotnet nuget push '.\Calculations\bin\Release\QuanTAlib.*.nupkg'
run: dotnet nuget push 'Calculations/bin/Release/QuanTAlib.*.nupkg'
--api-key ${{ secrets.NUGET_DEPLOY_KEY_QUANTLIB }}
--source https://api.nuget.org/v3/index.json
--skip-duplicate
+4 -3
View File
@@ -1,6 +1,7 @@
namespace QuanTAlib;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
/* <summary>
@@ -18,9 +19,9 @@ public class TSeries : List<(DateTime t, double v)> {
public static implicit operator (DateTime t, double v)(TSeries l) => l[^1];
public static implicit operator double(TSeries l) => l[^1].v;
public static implicit operator DateTime(TSeries l) => l[^1].t;
public List<DateTime> t => this.Select(item => item.t).ToList();
public List<double> v => this.Select(item => item.v).ToList();
public int Length => this.Count;
public ReadOnlyCollection<DateTime> t => this.Select(item => item.t).ToList().AsReadOnly();
public ReadOnlyCollection<double> v => this.Select(item => item.v).ToList().AsReadOnly();
public int Length => Count;
public TSeries Tail(int count = 10) {
var tailSeries = new TSeries();
+2 -1
View File
@@ -34,6 +34,7 @@
<AssemblyVersion>0.2.1.0</AssemblyVersion>
<FileVersion>0.2.1.0</FileVersion>
<InformationalVersion>0.2.1-dev.2+Branch.dev.Sha.cb5fe2dc86a78fe9358da810d17952c82299ed3d</InformationalVersion>
<SuppressNETSdkWarningProperty>NETSDK1057</SuppressNETSdkWarningProperty>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
@@ -60,7 +61,7 @@
<AdditionalFiles Include="..\.sonarlint\mihakralj_quantalib\CSharp\SonarLint.xml" Link="SonarLint.xml" />
</ItemGroup>
<ItemGroup>
<None Include="..\Docs\readme.md">
<None Include="..\docs\readme.md">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
+1 -1
View File
@@ -15,7 +15,7 @@ DECAY:
</summary> */
public class DECAY_Series : Single_TSeries_Indicator {
private bool _exp;
private readonly bool _exp;
private double _pdecay, _ppdecay;
private readonly double _dfactor;
+10 -8
View File
@@ -21,12 +21,14 @@ Sources:
public class LINREG_Series : Single_TSeries_Indicator
{
public readonly TSeries Intercept = new();
public readonly TSeries RSquared = new();
public readonly TSeries StdDev = new();
private readonly TSeries p_Intercept = new();
private readonly TSeries p_RSquared = new();
private readonly TSeries p_StdDev = new();
private readonly System.Collections.Generic.List<double> _buffer = new();
public LINREG_Series(TSeries source, int period, bool useNaN = false)
public TSeries Intercept => p_Intercept;
public TSeries RSquared => p_RSquared;
public TSeries StdDev => p_StdDev;
public LINREG_Series(TSeries source, int period, bool useNaN = false)
: base(source, period, useNaN)
{
if (this._data.Count > 0) { base.Add(this._data); }
@@ -80,12 +82,12 @@ public class LINREG_Series : Single_TSeries_Indicator
base.Add(ret, update, _NaN);
ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
Intercept.Add(ret, update);
p_Intercept.Add(ret, update);
ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _StdDev);
StdDev.Add(ret, update);
p_StdDev.Add(ret, update);
ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _RSquared);
RSquared.Add(ret, update);
p_RSquared.Add(ret, update);
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ Sources:
https://phemex.com/academy/what-is-arnaud-legoux-moving-averages
https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/
TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma)
Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma)
</summary> */
+3 -3
View File
@@ -41,7 +41,7 @@ public class DEMA_Series : Single_TSeries_Indicator
_lastsum = _lastlastsum;
_lastema1 = _lastlastema1;
_lastema2 = _lastlastema2;
}
}
else {
_lastlastsum = _lastsum;
_lastlastema1 = _lastema1;
@@ -67,8 +67,8 @@ public class DEMA_Series : Single_TSeries_Indicator
}
_dema = 2*_ema1 - _ema2;
_lastema1 = _ema1;
_lastema2 = _ema2;
_lastema1 = Double.IsNaN(_ema1)?_lastema1:_ema1;
_lastema2 = Double.IsNaN(_ema2)?_lastema2:_ema2;
base.Add((TValue.t, _dema), update, _NaN);
}
+5 -7
View File
@@ -9,24 +9,22 @@ DWMA: Double Weighted Moving Average
</summary> */
public class DWMA_Series : Single_TSeries_Indicator {
private readonly System.Collections.Generic.List<double> _buffer1 = new();
private readonly System.Collections.Generic.List<double> _weights = new();
public DWMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
for (int i = 0; i < this._p; i++) {
double _weight = (i + 1) * (i + 1);
this._weights.Add(_weight);
}
if (base._data.Count > 0) { base.Add(base._data); }
}
private readonly System.Collections.Generic.List<double> _buffer1 = new();
private readonly System.Collections.Generic.List<double> _weights = new();
public override void Add((System.DateTime t, double v) TValue, bool update) {
Add_Replace_Trim(_buffer1, TValue.v, _p, update);
double _wma1 = 0;
double _wsum = 0;
double _wma1 = 0, _wsum = 0;
for (int i = 0; i < _buffer1.Count; i++) {
_wma1 += _buffer1[i] * this._weights[i];
_wsum += this._weights[i];
_wma1 += _buffer1[i] * _weights[i];
_wsum += _weights[i];
}
_wma1 /= _wsum;
+1 -1
View File
@@ -60,7 +60,7 @@ public class EMA_Series : Single_TSeries_Indicator {
else {
_ema = _k * (TValue.v - _lastema) + _lastema;
}
_lastema = _ema;
_lastema = Double.IsNaN(_ema)?_lastema:_ema;
base.Add((TValue.t, _ema), update, _NaN);
}
+4 -2
View File
@@ -27,13 +27,14 @@ public class JMA_Series : Single_TSeries_Indicator {
public TSeries mma1 { get; }
public TSeries mma2 { get; }
private double upperBand, lowerBand, vsum, Kv, del1, del2;
private double upperBand, lowerBand, vsum, Kv;
private double prev_ma1, prev_det0, prev_det1, prev_vsum, prev_jma;
private double p_upperBand, p_lowerBand, p_Kv, p_prev_ma1, p_prev_det0, p_prev_det1, p_prev_vsum, p_prev_jma;
private readonly int _voltyS, _voltyL;
public JMA_Series(TSeries source, int period, double phase = 0.0, int vshort = 10, int vlong = 65, bool useNaN = false) : base(source, period, useNaN) {
upperBand = lowerBand = prev_ma1 = prev_det0 = prev_det1 = prev_vsum = prev_jma = Kv = del1 = del2 = 0.0;
upperBand = lowerBand = prev_ma1 = prev_det0 = prev_det1 = prev_vsum = prev_jma = Kv = 0.0;
Kv = 0;
pr = (phase * 0.01) + 1.5;
@@ -48,6 +49,7 @@ public class JMA_Series : Single_TSeries_Indicator {
}
public override void Add((System.DateTime t, double v) TValue, bool update) {
double del1 = 0.0, del2 = 0.0;
if (this.Count == 0) { prev_ma1 = prev_jma = TValue.v; }
if (update) {
upperBand = p_upperBand;
+1 -1
View File
@@ -33,7 +33,7 @@ public class MAMA_Series : Single_TSeries_Indicator
public override void Add((System.DateTime t, double v) TValue, bool update)
{
if (!update) {
// roll forward (oldx = x)
pr.io = pr.i6; pr.i6 = pr.i5; pr.i5 = pr.i4; pr.i4 = pr.i3; pr.i3 = pr.i2; pr.i2 = pr.i1; pr.i1 = pr.i;
+1 -11
View File
@@ -13,16 +13,6 @@ Sources:
https://technicalindicators.net/indicators-technical-analysis/150-t3-moving-average
http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/
Calculation:
Volume Factor is typically 0.7 (but also 0.618);
Ema1 = Ema (Close);
Ema2 = Ema (Ema1);
Ema3 = Ema (Ema2);
Ema4 = Ema (Ema3);
Ema5 = Ema (Ema4);
Ema6 = Ema (Ema5);
T3 = (a*a*a) * Ema6 + (3*a*a + 3*a*a*a) * Ema5 + (6*a*a 3*a 3*a*a*a) * Ema4 + (1 + 3*a + a*a*a + 3*a*a) * Ema3
</summary> */
public class T3_Series : Single_TSeries_Indicator {
private readonly double _k, _k1m, _c1, _c2, _c3, _c4;
@@ -35,7 +25,7 @@ public class T3_Series : Single_TSeries_Indicator {
private double _lastema1, _lastema2, _lastema3, _lastema4, _lastema5, _lastema6;
private double _llastema1, _llastema2, _llastema3, _llastema4, _llastema5, _llastema6;
private bool _useSMA;
private readonly bool _useSMA;
public T3_Series(TSeries source, int period, double vfactor = 0.7, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN) {
double _a = vfactor; //0.7; //0.618
+1 -8
View File
@@ -9,13 +9,6 @@ TRIX: Triple Exponential Average
has become a popular technical analysis tool to aid chartists in spotting diversions
and directional cues in stock trading patterns.
Calculation:
Ema1 = Ema (Close);
Ema2 = Ema (Ema1);
Ema3 = Ema (Ema2);
TRIX = (Ema3-Ema3[1]) / Ema3[1]
Sources:
https://www.investopedia.com/terms/t/trix.asp
@@ -29,7 +22,7 @@ public class TRIX_Series : Single_TSeries_Indicator
private double _lastema1, _lastema2, _lastema3;
private double _llastema1, _llastema2, _llastema3;
private bool _useSMA;
private readonly bool _useSMA;
public TRIX_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN)
{
+1 -33
View File
@@ -6,7 +6,7 @@ ADO: Chaikin Accumulation/Distribution Oscillator
ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
and fast (3-day) EMA(ADL):
Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
Chaikin A/D Oscillator is defined as 3-day EMA of ADL minus 10-day EMA of ADL
Sources:
https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
@@ -53,35 +53,3 @@ public class ADOSC_Series : Single_TBars_Indicator
}
}
/*
public class ADOSC_Series : Single_TBars_Indicator
{
private readonly ADL_Series _TSadl;
private readonly EMA_Series _TSslow;
private readonly EMA_Series _TSfast;
private readonly SUB_Series _TSado;
public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
{
_TSadl = new(source: source, useNaN: false);
_TSslow = new(source: _TSadl, period: 10, useNaN: false);
_TSfast = new(source: _TSadl, period: 3, useNaN: false);
_TSado = new(_TSfast, _TSslow);
if (source.Count > 0)
{ base.Add(_TSado); }
Console.WriteLine(base.Count);
}
public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
{
if (update)
{ _TSadl.Add(TBar, true); }
double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
var result = (TBar.t, _ado);
base.Add(result, update);
}
}
*/
+265 -121
View File
@@ -1,136 +1,280 @@
using System;
using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverage_chart : Indicator
{
#region Parameters
[InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
private int Period = 10;
[InputParameter("Data source", 1, 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("Moving Average Type", 2, variants: new object[]
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, "FMA", 7, "DEMA", 8, "TEMA", 9,
"ALMA", 10, "HMA", 11, "HEMA", 12, "MAMA", 13, "KAMA", 14, "ZLEMA", 15, "JMA", 16})]
private int MAtype = 1;
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, "FMA", 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 = false;
#endregion Parameters
protected HistoricalData History;
private TBars bars ;
private TBars bars;
///////
private TSeries indicator;
///////
///////
private TSeries MA1, MA2;
private CROSS_Series trades;
private COMPARE_Series overunder;
private EQUITY_Series equity;
///////
public MovingAverage_chart()
{
this.SeparateWindow = false;
this.Name = "Flexible Moving Average";
this.AddLineSeries("MA", Color.Yellow, 3, 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]);
}
switch (MAtype) {
case 0:
indicator = new SMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Simple Moving Average - SMA";
break;
case 1:
indicator = new EMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Exponential Moving Average - EMA";
break;
case 2:
indicator = new WMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Weighted Moving Average - WMA";
break;
case 3:
indicator = new T3_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Tillson T3 Moving Average - T3";
break;
case 4:
indicator = new SMMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Smoothed Moving Average - SMMA";
break;
case 5:
indicator = new TRIMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Triangular Moving Average - TRIMA";
break;
case 6:
indicator = new DWMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Double Weighted Moving Average - DWMA";
break;
case 7:
indicator = new FMA_Series(source: bars.Select(this.DataSource), period: this.Period);
this.Name = $"Fibonacci Moving Average - FMA";
break;
case 8:
indicator = new DEMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Double Exponential Moving Average - DEMA";
break;
case 9:
indicator = new TEMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Triple Exponential Moving Average - TEMA";
break;
case 10:
indicator = new ALMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Arnaud Legoux Moving Average - ALMA";
break;
case 11:
indicator = new HMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Hull Moving Average - HMA";
break;
case 12:
indicator = new HEMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Hull-Exponential Moving Average - HEMA";
break;
case 13:
double factor= 1.015 * Math.Exp(-0.043 * (double)this.Period);
indicator = new MAMA_Series(source: bars.Select(this.DataSource),
fastlimit: factor, slowlimit: factor*0.1,
useNaN: false);
this.Name = $"MESA Adaptive Moving Average - MAMA";
break;
case 14:
indicator = new KAMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Kaufman's Adaptive Moving Average - KAMA";
break;
case 15:
indicator = new ZLEMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Zero Lag Exponential Moving Average - ZLEMA";
break;
default:
indicator = new JMA_Series(source: bars.Select(this.DataSource), period: this.Period, useNaN: false);
this.Name = $"Jurik Moving Average - JMA";
break;
}
this.Name = this.Name + $" ({Period}:{TBars.SelectStr(this.DataSource)})";
public MovingAverage_chart() {
this.SeparateWindow = false;
this.Name = "2MA Crossover";
this.AddLineSeries("MA1", Color.SeaGreen, 3, LineStyle.Solid);
this.AddLineSeries("MA2", Color.OrangeRed, 3, LineStyle.Solid);
}
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.indicator[this.indicator.Count - 1].v);
}
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 = "Crossover[ ";
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 FMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period);
this.Name += $"FMA";
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 FMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period);
this.Name += $"FMA";
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);
equity = new(trades,prices: bars.Open,Long:LongTrades,Short:ShortTrades,Warmup:MA1Period+MA2Period);
}
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.SeaGreen, upperIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Green));
}
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
if (trades[^1].v == -1) {
this.EndCloud(0, 1, Color.Empty);
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Red));
}
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.SeaGreen, upperIcon: 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 ymin = ymax - (int)(ymax / 4);
double eqmin = equity.v.Min();
double eqmax = equity.v.Max();
double proportion = (ymax-ymin) / (eqmax-eqmin);
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);
}
}
}
+1
View File
@@ -16,6 +16,7 @@
<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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>True</Optimize>
+1
View File
@@ -16,6 +16,7 @@
<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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>True</Optimize>
+2 -1
View File
@@ -8,13 +8,14 @@ public class Update
[Fact]
public void Add_Test()
{
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries a = new() { Double.NaN, 0, 1, 2, 3, 4 };
ALMA_Series c = new(a, 4);
Assert.Equal(6, c.Count);
a.Add(5);
Assert.Equal(a.Count, c.Count);
a.Add(10, update: true);
Assert.Equal(a.Count, c.Count);
Assert.Equal(0, a[1].v);
}
[Fact]
+32
View File
@@ -0,0 +1,32 @@
using Xunit;
using System;
using QuanTAlib;
namespace MovingAvg;
public class DWMA_Test
{
[Fact]
public void Add_Test()
{
TSeries a = new() { Double.NaN, 0, 1, 2, 3, 4 };
DWMA_Series c = new(a, 3);
Assert.Equal(6, c.Count);
a.Add(5);
Assert.Equal(a.Count, c.Count);
a.Add(0, update: true);
Assert.Equal(a.Count, c.Count);
Assert.Equal(0, a[1].v);
}
[Fact]
public void Edge_Test()
{
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
DWMA_Series c = new(a, 3);
Assert.Equal(a.Count, c.Count);
a.Add(double.NaN);
Assert.Equal(a.Count, c.Count);
a.Add(double.PositiveInfinity);
Assert.Equal(a.Count, c.Count);
}
}
+2 -1
View File
@@ -8,13 +8,14 @@ public class EMA_Test
[Fact]
public void Add_Test()
{
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries a = new() { Double.NaN, 0, 1, 2, 3, 4 };
EMA_Series c = new(a, 3);
Assert.Equal(6, c.Count);
a.Add(5);
Assert.Equal(a.Count, c.Count);
a.Add(0, update: true);
Assert.Equal(a.Count, c.Count);
Assert.Equal(0, a[1].v);
}
[Fact]
+4
View File
@@ -12,6 +12,10 @@
<Version>0.2.1-dev.2</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Python.Included" Version="3.11.2" />
<PackageReference Include="pythonnet" Version="3.1.0-preview2023-03-04" />
<PackageReference Include="xunit" Version="2.4.2" />