Merge branch 'dev'

This commit is contained in:
Miha Kralj
2024-11-01 19:03:42 -07:00
273 changed files with 14575 additions and 4983 deletions
+42 -19
View File
@@ -1,7 +1,3 @@
# This workflow integrates SonarCloud analysis, coverage reporting,
# CodeQL analysis, SecurityCodeScan, and Codacy Security Scan
# for code scanning and vulnerability detection - and if they all pass, publish
name: Publish Workflow
on:
@@ -16,7 +12,7 @@ permissions:
jobs:
Code_Coverage:
runs-on: ubuntu-latest
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -28,6 +24,20 @@ jobs:
with:
dotnet-version: '8.x'
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/cache@v4
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner
- name: Install dotnet tools
run: |
dotnet tool install JetBrains.dotCover.GlobalTool --global
@@ -37,6 +47,26 @@ jobs:
dotnet tool install --global dotnet-reportgenerator-globaltool
dotnet restore
- name: Begin SonarCloud Analysis
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
dotnet sonarscanner begin /k:"mihakralj_QuanTAlib" /o:"mihakralj-quantalib" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" `
/d:sonar.solution.file="QuanTAlib.sln" `
/d:sonar.cs.opencover.reportsPaths="**/*cover*.xml" `
/d:sonar.cs.dotcover.reportsPaths="**/dotcover.xml" `
/d:sonar.coverage.exclusions="**Tests.cs,**/*.md,**/*.html,**/*.css,**/docs/**/*,**/archive/**/*,**/notebooks/**/*,**/obj/**/*,**/bin/**/*" `
/d:sonar.exclusions="**/TestResults/**/*,**/bin/**/*,**/obj/**/*,**/*.html,**/coverage/**/*,**/CoverageReport/**/*,**/*.md,**/*.css,**/docs/**/*,**/archive/**/*,**/notebooks/**/*" `
/d:sonar.test.exclusions="**Tests.cs,**/obj/**/*,**/bin/**/*" `
/d:sonar.cpd.exclusions="**Tests.cs" `
/d:sonar.cs.roslyn.ignoreIssues="false" `
/d:sonar.issue.ignore.multicriteria="e1" `
/d:sonar.issue.ignore.multicriteria.e1.ruleKey="csharpsquid:S1944,csharpsquid:S2053,csharpsquid:S2222,csharpsquid:S2259,csharpsquid:S2583,csharpsquid:S2589,csharpsquid:S3329,csharpsquid:S3655,csharpsquid:S3900,csharpsquid:S3949,csharpsquid:S3966,csharpsquid:S4158,csharpsquid:S4347,csharpsquid:S5773,csharpsquid:S6781" `
/d:sonar.issue.ignore.multicriteria.e1.resourceKey="**/*.cs" `
/d:sonar.verbose="true"
- name: Build Projects
run: |
dotnet build --no-restore --configuration Debug
@@ -58,6 +88,13 @@ jobs:
run: |
reportgenerator -reports:*cover*.xml -targetdir:.
- name: End SonarCloud Analysis
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
- name: Upload Coverage to Codacy
uses: codacy/codacy-coverage-reporter-action@v1
with:
@@ -70,20 +107,6 @@ jobs:
files: 'cover*'
verbose: true
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: >
-Dsonar.projectKey=mihakralj_QuanTAlib
-Dsonar.organization=mihakralj-quantalib
-Dsonar.sources=.
-Dsonar.cs.opencover.reportsPaths=**/*cover*.xml
-Dsonar.cs.dotcover.reportsPaths=**/dotcover.xml
-Dsonar.coverage.exclusions=**Tests.cs
CodeQL:
runs-on: ubuntu-latest
steps:
+1 -1
View File
@@ -1,4 +1,4 @@
{
"sonarCloudOrganization": "mihakralj-quantalib",
"sonarCloudOrganization": "mihakralj",
"projectKey": "mihakralj_QuanTAlib"
}
+33
View File
@@ -0,0 +1,33 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Tests",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "dotnet",
"args": [
"test",
"${workspaceFolder}/QuanTAlib.sln",
"--no-build"
],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "internalConsole",
"logging": {
"moduleLoad": false
}
},
{
"name": "Debug Library",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}",
"justMyCode": true,
"logging": {
"moduleLoad": false
}
}
]
}
+10 -4
View File
@@ -7,11 +7,17 @@
}
],
"sarif-viewer.connectToGithubCodeScanning": "on",
"dotnet.dotnetPath": "C:/Program Files/dotnet",
"omnisharp.useModernNet": true,
"omnisharp.sdkPath": "C:/Program Files/dotnet/sdk",
"sonarlint.connectedMode.project": {
"connectionId": "mihakralj",
"projectKey": "mihakralj_QuanTAlib"
}
}
},
"dotnet.backgroundAnalysis.analyzerDiagnosticsScope": "fullSolution",
"dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true,
"dotnetAcquisitionExtension.enableTelemetry": false,
"dotnet-test-explorer.testProjectPath": "Tests",
"dotnet-test-explorer.autoWatch": true,
"dotnet-test-explorer.showCodeLens": true,
"dotnet-test-explorer.testArguments": "/p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=./TestResults/coverage.cobertura.xml"
}
+62
View File
@@ -0,0 +1,62 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/QuanTAlib.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "test",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/QuanTAlib.sln",
"--no-build",
"--verbosity:normal"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "test",
"isDefault": true
},
"dependsOn": ["build"]
},
{
"label": "test with coverage",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/QuanTAlib.sln",
"/p:CollectCoverage=true",
"/p:CoverletOutputFormat=lcov",
"/p:CoverletOutput=./lcov.info",
"--no-build"
],
"problemMatcher": "$msCompile"
},
{
"label": "clean",
"command": "dotnet",
"type": "process",
"args": [
"clean",
"${workspaceFolder}/QuanTAlib.sln"
],
"problemMatcher": "$msCompile"
}
]
}
+2 -4
View File
@@ -11,7 +11,7 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
<PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<OutputPath>bin\$(Configuration)\</OutputPath>
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
<DebugType>full</DebugType>
@@ -51,9 +51,7 @@
<PackageReference Include="Microsoft.DotNet.Interactive.Formatting" Version="1.0.0-beta.21459.1" />
</ItemGroup>
<PropertyGroup Condition="'$(IsLocalBuild)' == 'true'">
<!-- Set the correct path to Quantower here -->
<PropertyGroup Condition="'$(IsLocalBuild)' == 'true' AND $([MSBuild]::IsOSPlatform('Windows'))">
<QuantowerRoot>D:\Quantower</QuantowerRoot>
<QuantowerPath>$([System.IO.Directory]::GetDirectories("$(QuantowerRoot)\TradingPlatform", "v1*")[0])</QuantowerPath>
</PropertyGroup>
+6 -1
View File
@@ -2,11 +2,16 @@
<PropertyGroup>
<RootNamespace>QuanTAlib.Tests</RootNamespace>
<AssemblyName>QuanTAlib.Tests</AssemblyName>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0-pre.35">
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0-pre.42">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
+251
View File
@@ -0,0 +1,251 @@
using Xunit;
namespace QuanTAlib.Tests;
public class CoreTests
{
#region CircularBuffer Tests
[Fact]
public void CircularBuffer_BasicOperations()
{
var buffer = new CircularBuffer(5);
// Test initial state
Assert.Equal(5, buffer.Capacity);
Assert.Equal(0, buffer.Count);
// Test adding items
buffer.Add(1.0);
buffer.Add(2.0);
Assert.Equal(2, buffer.Count);
Assert.Equal(1.0, buffer[0]);
Assert.Equal(2.0, buffer[^1]);
// Test overflow behavior
buffer.Add(3.0);
buffer.Add(4.0);
buffer.Add(5.0);
buffer.Add(6.0); // Should remove oldest item (1.0)
Assert.Equal(5, buffer.Count);
Assert.Equal(2.0, buffer[0]);
Assert.Equal(6.0, buffer[^1]);
}
[Fact]
public void CircularBuffer_UpdateBehavior()
{
var buffer = new CircularBuffer(3);
// Add new values
buffer.Add(1.0, isNew: true);
buffer.Add(2.0, isNew: true);
Assert.Equal(2, buffer.Count);
// Update last value
buffer.Add(2.5, isNew: false);
Assert.Equal(2, buffer.Count);
Assert.Equal(2.5, buffer[^1]);
}
[Fact]
public void CircularBuffer_MinMaxSumAverage()
{
var buffer = new CircularBuffer(5);
buffer.Add(1.0);
buffer.Add(2.0);
buffer.Add(3.0);
buffer.Add(4.0);
buffer.Add(5.0);
Assert.Equal(1.0, buffer.Min());
Assert.Equal(5.0, buffer.Max());
Assert.Equal(15.0, buffer.Sum());
Assert.Equal(3.0, buffer.Average());
}
[Fact]
public void CircularBuffer_Enumeration()
{
var buffer = new CircularBuffer(3);
buffer.Add(1.0);
buffer.Add(2.0);
buffer.Add(3.0);
var list = buffer.ToList();
Assert.Equal(3, list.Count);
Assert.Equal(1.0, list[0]);
Assert.Equal(3.0, list[2]);
}
#endregion
#region TBar Tests
[Fact]
public void TBar_Construction()
{
// Default constructor
var bar1 = new TBar();
Assert.Equal(0, bar1.Open);
Assert.True(bar1.IsNew);
// Value constructor
var bar2 = new TBar(10.0);
Assert.Equal(10.0, bar2.Open);
Assert.Equal(10.0, bar2.High);
Assert.Equal(10.0, bar2.Low);
Assert.Equal(10.0, bar2.Close);
// Full constructor
var time = DateTime.Now;
var bar3 = new TBar(time, 10.0, 12.0, 9.0, 11.0, 1000.0, false);
Assert.Equal(time, bar3.Time);
Assert.Equal(10.0, bar3.Open);
Assert.Equal(12.0, bar3.High);
Assert.Equal(9.0, bar3.Low);
Assert.Equal(11.0, bar3.Close);
Assert.Equal(1000.0, bar3.Volume);
Assert.False(bar3.IsNew);
}
[Fact]
public void TBar_DerivedValues()
{
var bar = new TBar(DateTime.Now, 10.0, 20.0, 5.0, 15.0, 1000.0);
Assert.Equal(12.5, bar.HL2); // (20 + 5) / 2
Assert.Equal(12.5, bar.OC2); // (10 + 15) / 2
Assert.Equal(11.67, bar.OHL3, 2); // (10 + 20 + 5) / 3
Assert.Equal(13.33, bar.HLC3, 2); // (20 + 5 + 15) / 3
Assert.Equal(12.5, bar.OHLC4); // (10 + 20 + 5 + 15) / 4
Assert.Equal(13.75, bar.HLCC4); // (20 + 5 + 15 + 15) / 4
}
[Fact]
public void TBarSeries_Operations()
{
var series = new TBarSeries();
var time = DateTime.Now;
var bar1 = new TBar(time, 10.0, 12.0, 9.0, 11.0, 1000.0);
var bar2 = new TBar(time.AddMinutes(1), 11.0, 13.0, 10.0, 12.0, 1100.0);
// Test adding bars
series.Add(bar1);
series.Add(bar2);
Assert.Equal(2, series.Count);
// Test updating last bar
var bar2Update = new TBar(bar2.Time, 11.0, 13.5, 9.5, 12.5, 1200.0, false);
series.Add(bar2Update);
Assert.Equal(2, series.Count);
Assert.Equal(12.5, series.Last.Close);
// Test derived series
Assert.Equal(11.0, series.Open.Last.Value);
Assert.Equal(13.5, series.High.Last.Value);
Assert.Equal(9.5, series.Low.Last.Value);
Assert.Equal(12.5, series.Close.Last.Value);
Assert.Equal(1200.0, series.Volume.Last.Value);
}
#endregion
#region TValue Tests
[Fact]
public void TValue_Construction()
{
// Default constructor
var value1 = new TValue();
Assert.Equal(0, value1.Value);
Assert.True(value1.IsNew);
Assert.True(value1.IsHot);
// Value constructor
var value2 = new TValue(10.0);
Assert.Equal(10.0, value2.Value);
// Full constructor
var time = DateTime.Now;
var value3 = new TValue(time, 10.0, false, false);
Assert.Equal(time, value3.Time);
Assert.Equal(10.0, value3.Value);
Assert.False(value3.IsNew);
Assert.False(value3.IsHot);
}
[Fact]
public void TValue_Conversions()
{
var value = new TValue(10.0);
// Test implicit conversions
double d = value;
Assert.Equal(10.0, d);
DateTime time = value;
Assert.Equal(value.Time, time);
// Test implicit conversion from double
TValue newValue = 20.0;
Assert.Equal(20.0, newValue.Value);
}
[Fact]
public void TSeries_Operations()
{
var series = new TSeries();
var time = DateTime.Now;
// Test adding values
series.Add(time, 10.0);
series.Add(time.AddMinutes(1), 20.0);
Assert.Equal(2, series.Count);
// Test updating last value
series.Add(new TValue(time.AddMinutes(1), 25.0, false));
Assert.Equal(2, series.Count);
Assert.Equal(25.0, series.Last.Value);
// Test adding range of values
var values = new[] { 30.0, 40.0, 50.0 };
foreach (var value in values)
{
series.Add(time.AddMinutes(series.Count + 1), value);
}
Assert.Equal(5, series.Count);
// Test conversions
var doubleList = (List<double>)series;
Assert.Equal(5, doubleList.Count);
Assert.Equal(50.0, doubleList[^1]);
var doubleArray = (double[])series;
Assert.Equal(5, doubleArray.Length);
Assert.Equal(50.0, doubleArray[^1]);
}
[Fact]
public void TSeries_EventHandling()
{
var series = new TSeries();
var receivedValues = new List<double>();
var time = DateTime.Now;
series.Pub += (object sender, in ValueEventArgs args) => receivedValues.Add(args.Tick.Value);
series.Add(time, 10.0);
series.Add(time.AddMinutes(1), 20.0);
series.Add(time.AddMinutes(2), 30.0);
Assert.Equal(3, receivedValues.Count);
Assert.Equal(10.0, receivedValues[0]);
Assert.Equal(20.0, receivedValues[1]);
Assert.Equal(30.0, receivedValues[2]);
}
#endregion
}
+84 -12
View File
@@ -13,12 +13,13 @@ public class EventingTests
// Create a cryptographically secure random number generator
using var rng = RandomNumberGenerator.Create();
// Create an input series to hold our random values
// Create input series to hold our random values
var input = new TSeries();
var barInput = new TBarSeries();
int p = 10;
// Create a list of indicator pairs (direct calculation and event-based) with names
var indicators = new List<(string Name, AbstractBase Direct, AbstractBase EventBased)>
// Create a list of value-based indicator pairs
var valueIndicators = new List<(string Name, AbstractBase Direct, AbstractBase EventBased)>
{
("Afirma", new Afirma(p,p,Afirma.WindowType.BlackmanHarris), new Afirma(input, p,p,Afirma.WindowType.BlackmanHarris)),
("Alma", new Alma(p), new Alma(input, p)),
@@ -51,7 +52,36 @@ public class EventingTests
("Tema", new Tema(p), new Tema(input, p)),
("Kama", new Kama(2, 30, 6), new Kama(input, 2, 30, 6)),
("Zlema", new Zlema(p), new Zlema(input, p)),
// error classes
("Sinema", new Sinema(p), new Sinema(input, p)),
("Smma", new Smma(p), new Smma(input, p)),
("T3", new T3(p), new T3(input, p)),
("Trima", new Trima(p), new Trima(input, p)),
("Vidya", new Vidya(p), new Vidya(input, p)),
("Apo", new Apo(12, 26), new Apo(input, 12, 26)),
("Macd", new Macd(12, 26, 9), new Macd(input, 12, 26, 9)),
("Rsi", new Rsi(p), new Rsi(input, p)),
("Rsx", new Rsx(p), new Rsx(input, p)),
("Cmo", new Cmo(p), new Cmo(input, p)),
("Cog", new Cog(p), new Cog(input, p)),
("Curvature", new Curvature(p), new Curvature(input, p)),
("Entropy", new Entropy(p), new Entropy(input, p)),
("Kurtosis", new Kurtosis(p), new Kurtosis(input, p)),
("Max", new Max(p), new Max(input, p)),
("Median", new Median(p), new Median(input, p)),
("Min", new Min(p), new Min(input, p)),
("Mode", new Mode(p), new Mode(input, p)),
("Percentile", new Percentile(p, 0.5), new Percentile(input, p, 0.5)),
("Skew", new Skew(p), new Skew(input, p)),
("Slope", new Slope(p), new Slope(input, p)),
("Stddev", new Stddev(p), new Stddev(input, p)),
("Variance", new Variance(p), new Variance(input, p)),
("Zscore", new Zscore(p), new Zscore(input, p)),
// Volatility indicators (value-based)
("Hv", new Hv(p), new Hv(input, p)),
("Jvolty", new Jvolty(p), new Jvolty(input, p)),
("Rv", new Rv(p), new Rv(input, p)),
("Rvi", new Rvi(p), new Rvi(input, p)),
// Error classes
("Mae", new Mae(p), new Mae(input, p)),
("Mapd", new Mapd(p), new Mapd(input, p)),
("Mape", new Mape(p), new Mape(input, p)),
@@ -67,29 +97,71 @@ public class EventingTests
("Rse", new Rse(p), new Rse(input, p)),
("Smape", new Smape(p), new Smape(input, p)),
("Rsquared", new Rsquared(p), new Rsquared(input, p)),
("Huberloss", new Huberloss(p), new Huberloss(input, p))
("Huber", new Huber(p), new Huber(input, p))
};
// Generate 200 random values and feed them to both direct and event-based indicators
// Create a list of bar-based indicator pairs
var barIndicators = new List<(string Name, AbstractBase Direct, AbstractBase EventBased)>
{
// Volume indicators
("Adl", new Adl(), new Adl(barInput)),
("Adosc", new Adosc(3, 10), new Adosc(barInput, 3, 10)),
("Aobv", new Aobv(), new Aobv(barInput)),
("Cmf", new Cmf(20), new Cmf(barInput, 20)),
("Eom", new Eom(14), new Eom(barInput, 14)),
("Kvo", new Kvo(34, 55), new Kvo(barInput, 34, 55)),
// Volatility indicators (bar-based)
("Atr", new Atr(14), new Atr(barInput, 14)),
// Oscillators (bar-based)
("Chop", new Chop(14), new Chop(barInput, 14))
};
// Generate 200 random values and feed them to indicators
for (int i = 0; i < 200; i++)
{
// Generate random value for value-based indicators
double randomValue = GetRandomDouble(rng) * 100;
input.Add(randomValue);
// Calculate direct indicators
foreach (var (_, direct, _) in indicators)
// Calculate value-based indicators
foreach (var (_, direct, _) in valueIndicators)
{
direct.Calc(randomValue);
}
// Generate random bar for bar-based indicators
var bar = new TBar(
DateTime.Now,
randomValue,
randomValue + Math.Abs(GetRandomDouble(rng) * 10),
randomValue - Math.Abs(GetRandomDouble(rng) * 10),
randomValue + GetRandomDouble(rng) * 5,
Math.Abs(GetRandomDouble(rng) * 1000),
true
);
barInput.Add(bar);
// Calculate bar-based indicators
foreach (var (_, direct, _) in barIndicators)
{
direct.Calc(bar);
}
}
// Compare the results of direct and event-based calculations
for (int i = 0; i < indicators.Count; i++)
// Compare the results for value-based indicators
foreach (var (name, direct, eventBased) in valueIndicators)
{
var (name, direct, eventBased) = indicators[i];
bool areEqual = (double.IsNaN(direct.Value) && double.IsNaN(eventBased.Value)) ||
Math.Abs(direct.Value - eventBased.Value) < 1e-9;
Assert.True(areEqual, $"Indicator {name} failed: Expected {direct.Value}, Actual {eventBased.Value}");
Assert.True(areEqual, $"Value indicator {name} failed: Expected {direct.Value}, Actual {eventBased.Value}");
}
// Compare the results for bar-based indicators
foreach (var (name, direct, eventBased) in barIndicators)
{
bool areEqual = (double.IsNaN(direct.Value) && double.IsNaN(eventBased.Value)) ||
Math.Abs(direct.Value - eventBased.Value) < 1e-9;
Assert.True(areEqual, $"Bar indicator {name} failed: Expected {direct.Value}, Actual {eventBased.Value}");
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ public class UpdateTests
[Fact]
public void Huberloss_Update()
{
var indicator = new Huberloss(period: 14);
var indicator = new Huber(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
+292
View File
@@ -0,0 +1,292 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public class MomentumUpdateTests
{
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private const int RandomUpdates = 100;
private const double ReferenceValue = 100.0;
private const int precision = 8;
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200 - 100; // Range: -100 to 100
}
private TBar GetRandomBar(bool IsNew)
{
double open = GetRandomDouble();
double high = open + Math.Abs(GetRandomDouble());
double low = open - Math.Abs(GetRandomDouble());
double close = low + (high - low) * GetRandomDouble();
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
}
[Fact]
public void Adx_Update()
{
var indicator = new Adx(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Adxr_Update()
{
var indicator = new Adxr(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Apo_Update()
{
var indicator = new Apo(fastPeriod: 12, slowPeriod: 26);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Dmi_Update()
{
var indicator = new Dmi(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Dmx_Update()
{
var indicator = new Dmx(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Dpo_Update()
{
var indicator = new Dpo(period: 20);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Macd_Update()
{
var indicator = new Macd(fastPeriod: 12, slowPeriod: 26, signalPeriod: 9);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Pmo_Update()
{
var indicator = new Pmo(period1: 35, period2: 20);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Po_Update()
{
var indicator = new Po(fastPeriod: 10, slowPeriod: 21);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Ppo_Update()
{
var indicator = new Ppo(fastPeriod: 12, slowPeriod: 26);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Prs_Update()
{
var indicator = new Prs();
indicator.SetBenchmark(ReferenceValue);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.SetBenchmark(GetRandomDouble() + 100); // Ensure positive benchmark
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
indicator.SetBenchmark(ReferenceValue);
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Roc_Update()
{
var indicator = new Roc(period: 12);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Mom_Update()
{
var indicator = new Mom(period: 10);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Trix_Update()
{
var indicator = new Trix(period: 18);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Tsi_Update()
{
var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble() + 100, IsNew: false)); // Ensure positive prices
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Vel_Update()
{
var indicator = new Vel(period: 10);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Vortex_Update()
{
var indicator = new Vortex(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
}
+190
View File
@@ -0,0 +1,190 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public class OscillatorsUpdateTests
{
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private const int RandomUpdates = 100;
private const double ReferenceValue = 100.0;
private const int precision = 8;
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200 - 100; // Range: -100 to 100
}
[Fact]
public void Rsi_Update()
{
var indicator = new Rsi(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Rsx_Update()
{
var indicator = new Rsx(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Cmo_Update()
{
var indicator = new Cmo(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Ao_Update()
{
var indicator = new Ao();
TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Ac_Update()
{
var indicator = new Ac();
TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Aroon_Update()
{
var indicator = new Aroon(period: 25);
TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Bop_Update()
{
var indicator = new Bop();
TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Cci_Update()
{
var indicator = new Cci(period: 20);
TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Cfo_Update()
{
var indicator = new Cfo(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Chop_Update()
{
var indicator = new Chop(period: 14);
TBar r = new(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(DateTime.Now, GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), GetRandomDouble(), 1000, IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Cog_Update()
{
var indicator = new Cog(period: 10);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
}
+138 -11
View File
@@ -45,14 +45,29 @@ public class VolatilityUpdateTests
[Fact]
public void Historical_Update()
{
var indicator = new Historical(period: 14);
double initialValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true));
var indicator = new Hv(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(false));
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: false));
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Jvolty_Update()
{
var indicator = new Jvolty(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
@@ -60,14 +75,14 @@ public class VolatilityUpdateTests
[Fact]
public void Realized_Update()
{
var indicator = new Realized(period: 14);
double initialValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true));
var indicator = new Rv(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(false));
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: false));
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
@@ -76,13 +91,125 @@ public class VolatilityUpdateTests
public void Rvi_Update()
{
var indicator = new Rvi(period: 14);
double initialValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true));
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(false));
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: false));
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Cvi_Update()
{
var indicator = new Cvi(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Tr_Update()
{
var indicator = new Tr();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Ui_Update()
{
var indicator = new Ui(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Vc_Update()
{
var indicator = new Vc(period: 20, deviations: 2.0);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Vov_Update()
{
var indicator = new Vov(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Vr_Update()
{
var indicator = new Vr(shortPeriod: 10, longPeriod: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Vs_Update()
{
var indicator = new Vs(period: 14, multiplier: 2.0);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
+322
View File
@@ -0,0 +1,322 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public class VolumeUpdateTests
{
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private const int RandomUpdates = 100;
private const int precision = 8;
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200 - 100; // Range: -100 to 100
}
private TBar GetRandomBar(bool IsNew)
{
double open = GetRandomDouble();
double high = open + Math.Abs(GetRandomDouble());
double low = open - Math.Abs(GetRandomDouble());
double close = low + (high - low) * GetRandomDouble();
double volume = Math.Abs(GetRandomDouble()) * 1000; // Random positive volume
return new TBar(DateTime.Now, open, high, low, close, volume, IsNew);
}
[Fact]
public void Adl_Update()
{
var indicator = new Adl();
TBar r = GetRandomBar(true);
// First calculation with IsNew: true
double value1 = indicator.Calc(r);
// Multiple recalculations with IsNew: false should not change the value
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
}
// Final calculation with IsNew: false should match initial value
double value2 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(value1, value2, precision);
// New calculation with IsNew: true should update the value
double value3 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: true));
Assert.NotEqual(value1, value3, precision);
}
[Fact]
public void Adosc_Update()
{
var indicator = new Adosc(shortPeriod: 3, longPeriod: 10);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Aobv_Update()
{
var indicator = new Aobv();
TBar r = GetRandomBar(true);
// First calculation with IsNew: true
double value1 = indicator.Calc(r);
// Multiple recalculations with IsNew: false should not change the value
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
}
// Final calculation with IsNew: false should match initial value
double value2 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(value1, value2, precision);
// New calculation with IsNew: true should update the value
double value3 = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: true));
Assert.NotEqual(value1, value3, precision);
}
[Fact]
public void Cmf_Update()
{
var indicator = new Cmf(period: 20);
TBar r = GetRandomBar(true);
// Generate a sequence of bars for warmup
var warmupBars = new List<TBar>();
for (int i = 0; i < indicator.WarmupPeriod; i++)
{
var bar = GetRandomBar(IsNew: true);
warmupBars.Add(bar);
indicator.Calc(bar);
}
// Calculate initial value after warmup
double initialValue = indicator.Calc(r);
// Apply random updates
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
// Reset and replay the same sequence
indicator.Init();
foreach (var bar in warmupBars)
{
indicator.Calc(bar);
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Eom_Update()
{
var indicator = new Eom(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Kvo_Update()
{
var indicator = new Kvo(shortPeriod: 34, longPeriod: 55);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Mfi_Update()
{
var indicator = new Mfi(period: 14);
TBar r = GetRandomBar(true);
// Generate a sequence of bars for warmup
var warmupBars = new List<TBar>();
for (int i = 0; i < indicator.WarmupPeriod; i++)
{
var bar = GetRandomBar(IsNew: true);
warmupBars.Add(bar);
indicator.Calc(bar);
}
// Calculate initial value after warmup
double initialValue = indicator.Calc(r);
// Apply random updates
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
// Reset and replay the same sequence
indicator.Init();
foreach (var bar in warmupBars)
{
indicator.Calc(bar);
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Nvi_Update()
{
var indicator = new Nvi();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Obv_Update()
{
var indicator = new Obv();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Pvi_Update()
{
var indicator = new Pvi();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Pvol_Update()
{
var indicator = new Pvol();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Pvo_Update()
{
var indicator = new Pvo(shortPeriod: 12, longPeriod: 26);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Pvr_Update()
{
var indicator = new Pvr();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Pvt_Update()
{
var indicator = new Pvt();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
[Fact]
public void Tvi_Update()
{
var indicator = new Tvi(minTick: 0.5);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
}
}
-28
View File
@@ -1,28 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\lib\quantalib.csproj" />
</ItemGroup>
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
<Optimize>true</Optimize>
</PropertyGroup>
</Project>
-73
View File
@@ -1,73 +0,0 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
namespace QuanTAlib;
public class Program
{
public static void Main(string[] args)
{
var config = DefaultConfig.Instance
.WithOption(ConfigOptions.DisableOptimizationsValidator, true);
BenchmarkRunner.Run<EmaBenchmark>(config);
}
}
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80, launchCount: 1, warmupCount: 3, iterationCount: 5)]
public class EmaBenchmark
{
private const int Period = 10;
private const int Length = 100_000;
private GbmFeed gbm = null!;
private TSeries inputs = null!;
[GlobalSetup]
public void Setup()
{
gbm = new GbmFeed();
inputs = new();
for (int i = 0; i < Length; i++)
{
TBar item = gbm.Generate(DateTime.Now);
inputs.Add(new TValue(item.Time, item.Close, true, true));
}
}
[Benchmark]
public void Ema_bench()
{
Ema ma1 = new(Period);
for (int i = 0; i < Length; i++)
{
TValue item = gbm.Generate(DateTime.Now).Close;
ma1.Calc(item);
}
}
[Benchmark]
public void Alma_bench()
{
Alma ma1 = new(Period);
for (int i = 0; i < Length; i++)
{
TValue item = gbm.Generate(DateTime.Now).Close;
ma1.Calc(item);
}
}
[Benchmark]
public void Dema_bench()
{
Dema ma1 = new(Period);
for (int i = 0; i < Length; i++)
{
TValue item = gbm.Generate(DateTime.Now).Close;
ma1.Calc(item);
}
}
}
-134
View File
@@ -1,134 +0,0 @@
AC,Acceleration Oscillator
AD,Chaikin A/D Line
ADOSC,Chaikin A/D Oscillator
ADL,Accumulation / Distribution Line
ADX,Average Directional Movement Index
ADXR,Average Directional Movement Index Rating
Alligator,Alligator Indicator
ALMA,Arnaud Legoux Moving Average
AO,Awesome Oscillator
APO,Absolute Price Oscillator
AROON,Aroon Indicator
AROONOSC,Aroon Oscillator
ATS,ATR Trailing Stop
ATR,Average True Range
AVGPRICE,Average Price
BB,Bollinger Bands
BBF,Bollinger Bands Flat
BBP,Bull and Bear Power
BC,Beta Coefficient
BETA,Beta
BOP,Balance of Power
CCI,Commodity Channel Index
CE,Chandelier Exit
Channel,Price Channel
CI,Choppiness Index
CMF,Chaikin Money Flow
CMO,Chande Momentum Oscillator
CORREL,Pearson's Correlation Coefficient
CRSI,ConnorsRSI
DC,Donchian Channels
DCP,Dominant Cycle Periods
DEMA,Double Exponential Moving Average
DMI,Directional Movement Index
DPO,Detrended Price Oscillator
DX,Directional Movement Index
EMA,Exponential Moving Average
EPMA,Endpoint Moving Average
ERI,Elder-ray Index
FCB,Fractal Chaos Bands
FI,Force Index
GO,Gator Oscillator
HE,Hurst Exponent
HMA,Hull Moving Average
HT_TRENDLINE,Hilbert Transform - Instantaneous Trendline
HT_TRENDMODE,Hilbert Transform - Trend vs Cycle Mode
HV,Historical Volatility
IC,Ichimoku Cloud
KAMA,Kaufman Adaptive Moving Average
KDJ,KDJ Index
Keltner,Keltner Channel
KVO,Klinger Volume Oscillator
LINEARREG,Linear Regression
LINEARREG_ANGLE,Linear Regression Angle
LINEARREG_INTERCEPT,Linear Regression Intercept
LINEARREG_SLOPE,Linear Regression Slope
LSMA,Least Squares Moving Average
LWMA,Linearly Weighted Moving Average
MACDEXT,MACD with controllable MA type
MACDFIX,Moving Average Convergence Divergence Fix 12/26
MAD,Mean absolute deviation
MAE,Moving Average Envelope
MAMA,MESA Adaptive Moving Average
MAPE,Mean absolute percentage error
MAX,Highest value over a specified period
MAXINDEX,Index of highest value over a specified period
MD,McGinley Dynamic
MEDPRICE,Median Price
MFI,Money Flow Index
MIN,Lowest value over a specified period
MININDEX,Index of lowest value over a specified period
MINMAX,Lowest and highest values over a specified period
MINMAXINDEX,Indexes of lowest and highest values over a period
MMA,Modified Moving Average
MOM,Momentum
MSE,Mean square error
NATR,Normalized Average True Range
OBV,On Balance Volume
OsMA,Moving Average of Oscillator
PAZ,Price Action Zones
Pivots,Pivots
PMO,Price Momentum Oscillator
PP,Pivot Points
PPO,Percentage Price Oscillator
PPMA,Pivot Point Moving Average
PRS,Price Relative Strength
PVI,Positive Volume Index
PVO,Percentage Volume Oscillator
Qstick,Qstick Indicator
R2,R-Squared (Coefficient of Determination)
Regression,Regression Line Indicator
RLW,%R Larry Williams
RMA,Running Moving Average
ROC,Rate of Change
ROCB,ROC with Bands
RPP,Rolling Pivot Points
RRA,Rescaled Range Analysis
RSI,Relative Strength Index
SAR,Parabolic SAR
SAREXT,Parabolic SAR - Extended
SDC,Standard Deviation Channels
SI,Swing Index
SLR,Slope and Linear Regression
SMA,Simple Moving Average
SMI,Stochastic Momentum Index
SMMA,Smoothed Moving Average
ST,SuperTrend
STARC,STARC Bands
STC,Schaff Trend Cycle
STDDEV,Standard Deviation
STOCH,Stochastic
STOCHF,Stochastic Fast
STOCHRSI,Stochastic Relative Strength Index
SUM,Summation
T3,Triple Exponential Moving Average (T3)
TEMA,Triple Exponential Moving Average
TRANGE,True Range
TRIMA,Triangular Moving Average
TRIX,1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
TSI,True Strength Index
TYPPRICE,Typical Price
UI,Ulcer Index
ULTOSC,Ultimate Oscillator
VAR,Variance
VI,Vortex Indicator
Volume,Volume Indicator
VS,Volatility Stop
VWAP,Volume Weighted Average Price
VWMA,Volume Weighted Moving Average
WA,Williams Alligator
WCLPRICE,Weighted Close Price
WF,Williams Fractal
WMA,Weighted Moving Average
ZS,Z-Score
ZZ,ZigZag Indicator
1 AC Acceleration Oscillator
2 AD Chaikin A/D Line
3 ADOSC Chaikin A/D Oscillator
4 ADL Accumulation / Distribution Line
5 ADX Average Directional Movement Index
6 ADXR Average Directional Movement Index Rating
7 Alligator Alligator Indicator
8 ALMA Arnaud Legoux Moving Average
9 AO Awesome Oscillator
10 APO Absolute Price Oscillator
11 AROON Aroon Indicator
12 AROONOSC Aroon Oscillator
13 ATS ATR Trailing Stop
14 ATR Average True Range
15 AVGPRICE Average Price
16 BB Bollinger Bands
17 BBF Bollinger Bands Flat
18 BBP Bull and Bear Power
19 BC Beta Coefficient
20 BETA Beta
21 BOP Balance of Power
22 CCI Commodity Channel Index
23 CE Chandelier Exit
24 Channel Price Channel
25 CI Choppiness Index
26 CMF Chaikin Money Flow
27 CMO Chande Momentum Oscillator
28 CORREL Pearson's Correlation Coefficient
29 CRSI ConnorsRSI
30 DC Donchian Channels
31 DCP Dominant Cycle Periods
32 DEMA Double Exponential Moving Average
33 DMI Directional Movement Index
34 DPO Detrended Price Oscillator
35 DX Directional Movement Index
36 EMA Exponential Moving Average
37 EPMA Endpoint Moving Average
38 ERI Elder-ray Index
39 FCB Fractal Chaos Bands
40 FI Force Index
41 GO Gator Oscillator
42 HE Hurst Exponent
43 HMA Hull Moving Average
44 HT_TRENDLINE Hilbert Transform - Instantaneous Trendline
45 HT_TRENDMODE Hilbert Transform - Trend vs Cycle Mode
46 HV Historical Volatility
47 IC Ichimoku Cloud
48 KAMA Kaufman Adaptive Moving Average
49 KDJ KDJ Index
50 Keltner Keltner Channel
51 KVO Klinger Volume Oscillator
52 LINEARREG Linear Regression
53 LINEARREG_ANGLE Linear Regression Angle
54 LINEARREG_INTERCEPT Linear Regression Intercept
55 LINEARREG_SLOPE Linear Regression Slope
56 LSMA Least Squares Moving Average
57 LWMA Linearly Weighted Moving Average
58 MACDEXT MACD with controllable MA type
59 MACDFIX Moving Average Convergence Divergence Fix 12/26
60 MAD Mean absolute deviation
61 MAE Moving Average Envelope
62 MAMA MESA Adaptive Moving Average
63 MAPE Mean absolute percentage error
64 MAX Highest value over a specified period
65 MAXINDEX Index of highest value over a specified period
66 MD McGinley Dynamic
67 MEDPRICE Median Price
68 MFI Money Flow Index
69 MIN Lowest value over a specified period
70 MININDEX Index of lowest value over a specified period
71 MINMAX Lowest and highest values over a specified period
72 MINMAXINDEX Indexes of lowest and highest values over a period
73 MMA Modified Moving Average
74 MOM Momentum
75 MSE Mean square error
76 NATR Normalized Average True Range
77 OBV On Balance Volume
78 OsMA Moving Average of Oscillator
79 PAZ Price Action Zones
80 Pivots Pivots
81 PMO Price Momentum Oscillator
82 PP Pivot Points
83 PPO Percentage Price Oscillator
84 PPMA Pivot Point Moving Average
85 PRS Price Relative Strength
86 PVI Positive Volume Index
87 PVO Percentage Volume Oscillator
88 Qstick Qstick Indicator
89 R2 R-Squared (Coefficient of Determination)
90 Regression Regression Line Indicator
91 RLW %R Larry Williams
92 RMA Running Moving Average
93 ROC Rate of Change
94 ROCB ROC with Bands
95 RPP Rolling Pivot Points
96 RRA Rescaled Range Analysis
97 RSI Relative Strength Index
98 SAR Parabolic SAR
99 SAREXT Parabolic SAR - Extended
100 SDC Standard Deviation Channels
101 SI Swing Index
102 SLR Slope and Linear Regression
103 SMA Simple Moving Average
104 SMI Stochastic Momentum Index
105 SMMA Smoothed Moving Average
106 ST SuperTrend
107 STARC STARC Bands
108 STC Schaff Trend Cycle
109 STDDEV Standard Deviation
110 STOCH Stochastic
111 STOCHF Stochastic Fast
112 STOCHRSI Stochastic Relative Strength Index
113 SUM Summation
114 T3 Triple Exponential Moving Average (T3)
115 TEMA Triple Exponential Moving Average
116 TRANGE True Range
117 TRIMA Triangular Moving Average
118 TRIX 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
119 TSI True Strength Index
120 TYPPRICE Typical Price
121 UI Ulcer Index
122 ULTOSC Ultimate Oscillator
123 VAR Variance
124 VI Vortex Indicator
125 Volume Volume Indicator
126 VS Volatility Stop
127 VWAP Volume Weighted Average Price
128 VWMA Volume Weighted Moving Average
129 WA Williams Alligator
130 WCLPRICE Weighted Close Price
131 WF Williams Fractal
132 WMA Weighted Moving Average
133 ZS Z-Score
134 ZZ ZigZag Indicator
+25 -7
View File
@@ -1,22 +1,24 @@
* [Home](/)
* Introduction
* [List of Indicators](indicators/indicators.md)
* 🚧 Introduction
* [Overview]()
* [Features]()
* [Historical vs Real-time analysis](essays/realtime.md)
* Core Concepts
* 🚧 Core Concepts
* [Time Series Data Handling]()
* [Calculation classes]()
* [Presentation Classes]()
* QuanTAlib C# Library
* 🚧 QuanTAlib C# Library
* [Installation]()
* [Quick Start Guide]()
* [Usage Examples]()
* [Tests and Validation]()
* Quantower Charts
* 🚧 Quantower Charts
* [Installation]()
* [Quick Start Guide]()
* [Using VS Code for QuanTower coding](setup/vscode.md)
@@ -24,7 +26,24 @@
* [Creating Custom Indicators]()
* [Inspecting Quantower Internals]()
* [Available Indicators](indicators/indicators.md)
* [🚧 Available Indicators](indicators/indicators.md)
* Momentum
* [ADX - Average Directional Index](indicators/momentum/adx/description.md)
* [ADXR - Average Directional Index Rating](indicators/momentum/adxr/description.md)
* [APO - Absolute Price Oscillator](indicators/momentum/apo/description.md)
* [DMI - Directional Movement Index](indicators/momentum/dmi/description.md)
* [DMX - Directional Movement Extended](indicators/momentum/dmx/description.md)
* [DPO - Detrended Price Oscillator](indicators/momentum/dpo/description.md)
* [MOM - Momentum](indicators/momentum/mom/description.md)
* [PMO - Price Momentum Oscillator](indicators/momentum/pmo/description.md)
* [PO - Price Oscillator](indicators/momentum/po/description.md)
* [PPO - Percentage Price Oscillator](indicators/momentum/ppo/description.md)
* [PRS - Price Relative Strength](indicators/momentum/prs/description.md)
* [ROC - Rate of Change](indicators/momentum/roc/description.md)
* [TRIX - Triple Exponential](indicators/momentum/trix/description.md)
* [TSI - True Strength Index](indicators/momentum/tsi/description.md)
* [VEL - Velocity](indicators/momentum/vel/description.md)
* [VORTEX - Vortex Indicator](indicators/momentum/vortex/description.md)
* Basic Transforms
* Numerical Analysis
* Errors
@@ -92,4 +111,3 @@
* Oscillators
* Volatility
* Volume
+106 -37
View File
@@ -3,71 +3,140 @@
<head>
<meta charset="UTF-8">
<title>QuanTAlib Documentation</title>
<!-- Basic meta tags -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="Documentation for QuanTAlib, a quantitative technical analysis library">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.css" integrity="sha384-3UiQGuEI4TTMaFmGIZumfRPtfKQ3trwQE2JgosJxCnGmQpL/lJdjpcHkaaFwHlcI" crossorigin="anonymous">
<link rel="stylesheet" href="styles.css">
<!-- Stylesheets -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.css"
integrity="sha384-3UiQGuEI4TTMaFmGIZumfRPtfKQ3trwQE2JgosJxCnGmQpL/lJdjpcHkaaFwHlcI"
crossorigin="anonymous">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/vue.css">
<style>
/* Target strong elements within tables */
table strong {
font-size: 120%;
display: inline-block; /* This helps with vertical alignment */
padding: 4px 0; /* Add some vertical padding for better spacing */
}
/* Optional: If you want to target just the section headers more specifically */
table tr:first-child strong,
table tr strong:first-child {
font-size: 120%;
color: #42b983; /* Optional: matches Docsify's default theme color */
}
/* Hide github corner */
.github-corner {
display: none !important;
}
.github-corner svg {
display: none !important;
}
</style>
</head>
<body>
<div id="app"></div>
<!-- Docsify Configuration -->
<script>
window.$docsify = {
// Basic settings
name: 'QuanTAlib',
repo: 'https://github.com/mihakralj/quantalib',
homepage: 'readme.md',
noCorner: true,
// Navigation settings
loadSidebar: true,
auto2top: true,
mergeNavbar: true,
sidebarDisplayLevel: 0, // Add this line to collapse all sidebar items initially
search: {
maxAge: 86400000,
paths: 'auto',
placeholder: 'Type to search',
noData: 'No Results!',
depth: 6,
hideOtherSidebarContent: false,
},
pagination: {
previousText: 'Previous',
nextText: 'Next',
crossChapter: true,
crossChapterText: true,
},
sidebarDisplayLevel: 0,
// Performance settings
maxAge: 86400000,
paths: 'auto',
// Search settings
placeholder: 'Type to search',
noData: 'No Results!',
depth: 6,
hideOtherSidebarContent: false,
// Theme settings
themeable: {
readyTransition: true,
responsiveTables: true
},
// Math settings
latex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
displayMath: [['$$', '$$']],
displayMath: [['$$', '$$']]
},
// Markdown settings
markdown: {
smartypants: true,
renderer: {
table: function(header, body) {
if (header) return '<table class="docTable"><thead>' + header + '</thead><tbody>' + body + '</tbody></table>'
return '<table class="docTable"><tbody>' + body + '</tbody></table>'
}
}
},
// Content settings
executeScript: true,
externalLinkTarget: '_blank',
cornerExternalLinkTarget: '_blank',
relativePath: false,
// Table of Contents settings
toc: {
scope: '.markdown-section',
headings: 'h1, h2, h3, h4, h5, h6',
title: 'Table of Contents',
title: 'Table of Contents'
},
copyCode: {
buttonText: 'Copy to clipboard',
errorText: 'Error',
successText: 'Copied'
},
plugins: [
]
plugins: []
};
</script>
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js" integrity="sha384-KaHhgnx/OTLoJ4J33SSJsF4x1pk4I7q3s5ZOfIDHJYl6IG7Oyn2vNDsHiWJe46fD" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js" integrity="sha384-ibjVZCUwWPrRrNc9BNkbbJvtYmTh8GYDNQgj+2jQVNDudOFgSQWs+Es6JhdoTIvf" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js" integrity="sha384-lMHOyuqf3B/T/BgfYxUKprN0bdRf8KhVTE11w76Tvtze86XHVSDYzxqNGDGgIi9I" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-pagination/dist/docsify-pagination.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-tabs/dist/docsify-tabs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-katex@1.4.3/dist/docsify-katex.js" integrity="sha384-M76M/x5vGyeoej1covQQifl7T945mY+qgzNVrM/urHMCYjP8tnMsx5WCdeLZ74UE" crossorigin="anonymous"></script>
<!-- Core Docsify -->
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"
integrity="sha384-KaHhgnx/OTLoJ4J33SSJsF4x1pk4I7q3s5ZOfIDHJYl6IG7Oyn2vNDsHiWJe46fD"
crossorigin="anonymous"></script>
<!-- Added marked.js for better markdown parsing -->
<script src="//cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<!-- Plugins -->
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"
integrity="sha384-ibjVZCUwWPrRrNc9BNkbbJvtYmTh8GYDNQgj+2jQVNDudOFgSQWs+Es6JhdoTIvf"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js"
integrity="sha384-lMHOyuqf3B/T/BgfYxUKprN0bdRf8KhVTE11w76Tvtze86XHVSDYzxqNGDGgIi9I"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"
integrity="sha384-LthJPBJ4RGco78kBY+EmKz5rmISZ5vrtAu3+l2ALQ2mrZHOe6Wyf6knyKjeC4cL6"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"
integrity="sha384-Vu4LjJ210wltbg1I3zl1f5n8qLSDr9GE7ij2JfiMbV64UCFP2RgFtG8W2Gh6Khwe"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-pagination/dist/docsify-pagination.min.js"
integrity="sha384-uFEp18/1vv2dYlO64J2lOcnbhirAQZPtruqAZZ7PZYoXenm5c+tIs3AqSMjVMRe8"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"
integrity="sha384-fYBaBAsdPMjWt1AuA+txMoztHnl+zLgObSvwddIabbfUp+36gf/vNOKx88f37zix"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-tabs/dist/docsify-tabs.min.js"
integrity="sha384-QA3IVKzXq6xcKR8yQJHgDbI1FcJiQ137Cuetl1VWzUxJ6BQ7ew0MMq5fg2HbFK1o"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-katex@1.4.3/dist/docsify-katex.js"
integrity="sha384-M76M/x5vGyeoej1covQQifl7T945mY+qgzNVrM/urHMCYjP8tnMsx5WCdeLZ74UE"
crossorigin="anonymous"></script>
</body>
</html>
</html>
View File
View File
+48
View File
@@ -0,0 +1,48 @@
# JMA Calculation
### Initial Parameters:
$\beta = factor \cdot \frac{period - 1}{factor \cdot (period - 1) + 2}$
$len1 = \frac{\ln(\sqrt{period - 1})}{\ln(2)} + 2$
$pow1 = \max(len1 - 2, 0.5)$
$phase \in [0.5, 2.5]$ (clamped to $(phase \cdot 0.01) + 1.5$)
### Volatility Calculations:
$del1_t = price_t - upperBand_{t-1}$
$del2_t = price_t - lowerBand_{t-1}$
$volty_t = \max(|del1_t|, |del2_t|)$
$vSum_t = \frac{\sum_{i=t-buffer+1}^t volty_i}{buffer}$
$avgVolty_t = \text{mean}(vSum_{t-64:t})$
$rVolty_t = \text{clamp}(\frac{volty_t}{avgVolty_t}, 1, len1^{1/pow1})$
### Band Calculations:
$pow2_t = rVolty_t^{pow1}$
$K_v = \beta^{\sqrt{pow2_t}}$
$upperBand_t = price_t - K_v \cdot del1_t$
$\alpha_t = \beta^{pow2_t}$
$ma1_t = price_t + \alpha_t(ma1_{t-1} - price_t)$
$det0_t = price_t + \beta(det0_{t-1} - price_t + ma1_t) - ma1_t$
$ma2_t = ma1_t + phase \cdot det0_t$
$det1_t = (ma2_t - jma_{t-1})(1-\alpha_t)^2 + \alpha_t^2 \cdot det1_{t-1}$
$jma_t = jma_{t-1} + det1_t$
View File
View File
View File
View File
View File
View File
+196 -181
View File
@@ -1,184 +1,199 @@
# Indicators in QuanTAlib
⭐= Validation against several TA libraries<br>
✔️= Validation tests passed<br>
❌= Issue
| **Category** | **Status** | **Completion** |
|--------------|:----------:|:--------------:|
| Basic Transforms | 6 of 6 | 100% |
| Averages & Trends | 33 of 33 | 100% |
| Momentum | 17 of 17 | 100% |
| Oscillators | 12 of 29 | 41% |
| Volatility | 15 of 35 | 43% |
| Volume | 19 of 19 | 100% |
| Numerical Analysis | 13 of 20 | 65% |
| Errors | 16 of 16 | 100% |
| **Total** | **131 of 175** | **75%** |
|**MOMENTUM INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|--|:--:|:--:|:--:|
|*DMI - Directional Movement Index|`?`|GetDmi||
|*DMX - Jurik Directional Movement Index|`?`|||
|*MOM - Momentum|`?`|||
|*VEL - Jurik Signal Velocity|`?`|||
|ADX - Average Directional Movement Index|`?`|GetAdx|Adx|
|ADXR - Average Directional Movement Index|`?`|Rating|Adxr|
|APO - Absolute Price Oscillator|`?`|Apo||
|DPO - Detrended Price Oscillator|`?`|GetDpo||
|MACD - Movign Average Convergence/Divergence|`?`|||
|PO - Price Oscillator|`?`|||
|PPO - Percentage Price Oscillator|`?`|||
|PMO - Price Momentum Oscillator|`?`|GetPmo||
|PRS - Price Relative Strength|`?`|GetPrs||
|ROC - Rate of Change|`?`|GetRoc||
|TRIX - 1-day ROC of TEMA|`?`|GetTrix||
|VORTEX - Vortex Indicator|`?`|||
<br>
|**VOLATILITY INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|ADR - Average Daily Range||||
|ANDREW - Andrew's Pitchfork||||
|ATR - Average True Range|`Atr`|GetAtr|Atr|
|ATRP - Average True Range Percent||||
|ATRSTOP - ATR Trailing Stop ||GetAtrStop||
|BBANDS - Bollinger Bands®||BollingerBands||
|CHAND - Chandelier Exit||GetChandelier||
|CVI - Chaikins Volatility||||
|DON - Donchian Channels||GetDonchian||
|FCB - Fractal Chaos Bands||GetFcb||
|HV - Historical Volatility||||
|ICH - Ichimoku Cloud||GetIchimoku||
|KEL - Keltner Channels||GetKeltner||
|NATR - Normalized Average True Range||GetAtr||
|CHN - Price Channel Indicator||||
|SAR - Parabolic Stop and Reverse||GetParabolicSar||
|STARC - Starc Bands||GetStarcBands||
|TR - True Range||||
|UI - Ulcer Index||GetUlcerIndex||
|VSTOP - Volatility Stop||GetVolatilityStop||
<br>
|**OSCILLATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|RSI - Relative Strength Index|`Rsi`|GetRsi||
|RSX - Jurik Trend Strength Index|`Rsx`|||
|AC - Acceleration Oscillator|||||
|AO - Awesome Oscillator||GetAwesome|||
|AROON - Aroon oscillator||GetAroon|Aroon||
|BOP - Balance of Power||GetBop|Bop||
|CCI - Commodity Channel Index||GetCci|Cci||
|CFO - Chande Forcast Oscillator|||||
|CMO - Chande Momentum Oscillator||GetCmo|Cmo||
|CHOP - Choppiness Index||GetChop|||
|COG - Ehler's Center of Gravity|||||
|COPPOCK - Coppock Curve|||||
|CRSI - Connor RSI||GetConnorsRsi|||
|CTI - Ehler's Correlation Trend Indicator|||||
|DOSC - Derivative Oscillator|||||
|EFI - Elder Ray's Force Index||GetElderRay|||
|FISHER - Fisher Transform|||||
|FOSC - Forecast Oscillator||||||
|GATOR - Williams Alliator Oscillator||GetGator|||
|KDJ - KDJ Indicator (trend reversal)|||||
|KRI - Kairi Relative Index|||||
|RVGI - Relative Vigor Index|||||
|SMI - Stochastic Momentum Index||GetSmi|||
|SRSI - Stochastic RSI||GetStochRsi|||
|STC - Schaff Trend Cycle||GetStc|||
|STOCH - Stochastic Oscillator||`GetStoch|||
|TSI - True Strength Index||GetTsi|||
|UO - Ultimate Oscillator||GetUltimate|||
|WILLR - Larry Williams' %R||GetWilliamsR|||
<br>
|**VOLUME INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|ADL - Chaikin Accumulation Distribution Line||GetAdl|Ad||
|ADOSC - Chaikin Accumulation Distribution Oscillator||GetChaikinOsc|AdOsc||
|AOBV - Archer On-Balance Volume|||||
|CMF - Chaikin Money Flow||GetCmf|||
|EOM - Ease of Movement|||||
|KVO - Klinger Volume Oscillator||GetKvo||||
|MFI - Money Flow Index||GetMfi|||
|NVI - Negative Volume Index|||||
|OBV - On-Balance Volume||GetObv|||
|PVI - Positive Volume Index|||||
|PVOL - Price-Volume|||||
|PVO - Percentage Volume Oscillator||GetPvo|||
|PVR - Price Volume Rank|||||
|PVT - Price Volume Trend|||||
|TVI - Trade Volume Index|||||
|VP - Volume Profile|||||
|VWAP - Volume Weighted Average Price||GetVwap|||
|VWMA - Volume Weighted Moving Average||GetVwma||||
<br>
|**NUMERICAL ANALYSIS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|BETA - Beta coefficient|||||
|CORR - Correlation Coefficient|||||
|CURVATURE - Rate of Change in Direction or Slope|`Curvature`||||
|ENTROPY - Measure of Uncertainty or Disorder|`Entropy`||||
|KURTOSIS - Measure of Tails/Peakedness|`Kurtosis`||||
|HUBER - Huber Loss|`Huberloss`||||
|HURST - Hurst Exponent||GetHurst|||
|MAX - Maximum with exponential decay|`Max`||||
|MEDIAN - Middle value|`Median`||||
|MIN - Minimum with exponential decay|`Min`||||
|MODE - Most Frequent Value|`Mode`||||
|PERCENTILE - Rank Order|`Percentile`||||
|RSQUARED - Coefficient of Determination R-Squared|||||
|SKEW - Skewness, asymmetry of distribution|`Skew`||||
|SLOPE - Rate of Change, Linear Regression|`Slope`||||
|STDDEV - Standard Deviation, Measure of Spread|`Stddev`||||
|THEIL - Theil's U Statistics|||||
|TSF - Time Series Forecast|||`✔️`|`✔️`|
|VARIANCE - Average of Squared Deviations|`Variance`||||
|ZSCORE - Standardized Score|`Zscore`||||
<br>
|**ERRORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|MAE - Mean Absolute Error|`Mae`||||
|MAPD - Mean Absolute Percentage Deviation|`Mapd`||||
|MAPE - Mean Absolute Percentage Error|`Mape`||||
|MASE - Mean Absolute Scaled Error|`Mase`||||
|MDA - Mean Directional Accuracy|||||
|ME - Mean Error|`Me`||||
|MPE - Pean Percentage Error|`Mpe`||||
|MSE - Mean Squared Error|`Mse`||||
|MSLE - Mean Squared Logarithmic Error|`Msle`||||
|RAE - Relative Absolute Error|`Rae`||||
|RMSE - Root Mean Squared Error|`Rmse`||||
|RSE - Relateive Squared Error|`Rse`||||
|RMSLE - Root Mean Squared Logarithmic Error|`Rmsle`||||
|SMAPE - Symmetric Mean Absolute Percentage Error|`Smape`||||
<br>
|**AVERAGES & TRENDS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|AFIRMA - Autoregressive Finite Impulse Response Moving Average|`Afirma`||||
|ALMA - Arnaud Legoux Moving Average|`Alma`|`✔️`||
|DEMA - Double EMA Average|`Dema`|`✔️`|`✔️`|
|DSMA - Deviation Scaled Moving Average|`Dsma`||||
|DWMA - Double WMA Average|`Dwma`||||
|EMA - Exponential Moving Average|`Ema`|``|``|``|``|
|EPMA - Endpoint Moving Average|`Epma`|`✔️`|||
|FRAMA - Fractal Adaptive Moving Average|`Frama`||||
|FWMA - Fibonacci Weighted Moving Average|`Fwma`||||
|HILO - Gann High-Low Activator|||||
|HTIT - Hilbert Transform Instantaneous Trendline|`Htit`|`✔️`|`✔️`||
|GMA - Gaussian-Weighted Moving Average|`Gma`||||
|HMA - Hull Moving Average|`Hma`|`✔️`||`✔️`|
|HWMA - Holt-Winter Moving Average|`Hwma`||||
|JMA - Jurik Moving Average|`Jma`||||
|JORDAN - Jordan Moving Average|||||
|KAMA - Kaufman's Adaptive Moving Average|`Kama`|`✔️`|`✔️`|`✔️`|
|LTMA - Laguerre Transform Moving Average|`Ltma`||||
|MAAF - Median-Average Adaptive Filter|`Maaf`||||
|MAMA - MESA Adaptive Moving Average|`Mama`|`✔️`|`✔️`||
|MGDI - McGinley Dynamic Indicator|`Mgdi`|`✔️`|||
|MLMA - Minimal Lag Moving Average|||||
|MMA - Modified Moving Average|`Mma`||||
|PPMA - Pivot Point Moving Average|||||
|PWMA - Pascal's Weighted Moving Average|`Pwma`||||
|QEMA - Quad Exponential Moving Average|`Qema`||||
|RMA - WildeR's Moving Average|`Rma`||||
|SINEMA - Sine Weighted Moving Average|`Sinema`||||
|SMA - Simple Moving Average|`Sma`|||
|SMMA - Smoothed Moving Average|`Smma`|`✔️`||
|SSF - Ehler's Super Smoother Filter||||
|SUPERTREND - Supertrend||`✔️`||
|T3 - Tillson T3 Moving Average|`T3`|`✔️`|`✔️`|
|TEMA - Triple EMA Average|`Tema`|`✔️`|`✔️`|
|TRIMA - Triangular Moving Average|`Trima`|`✔️`||
|VIDYA - Variable Index Dynamic Average|`Vidya`|||
|WMA - Weighted Moving Average|`Wma`|`✔️`||
|ZLEMA - Zero Lag EMA Average|`Zlema`|||
<br>
|**BASIC TRANSFORMS**|**QuanTALib**|Skender.Stock|TALib.NETCore|
|OC2 - Midpoint price|`.OC2`|CandlePart.OC2|MidPoint|
|HL2 - Median Price|`.HL2`|CandlePart.HL2|MedPrice|
|HLC3 - Typical Price|`.HLC3`|CandlePart.HLC3|TypPrice|
|OHL3 - Mean Price|`.OHL3`|CandlePart.OHL3|
|OHLC4 - Average Price|`.OHLC4`|CandlePart.OHLC4|AvgPrice|
|HLCC4 - Weighted Price|`.HLCC4`||WclPrice|
|Technical Indicator Name| Class Name|
|-----------|:----------:|
|**BASIC TRANSFORMS**||
|OC2 - Midpoint price|`.OC2`|
|HL2 - Median Price|`.HL2`|
|HLC3 - Typical Price|`.HLC3`|
|OHL3 - Mean Price|`.OHL3`|
|OHLC4 - Average Price|`.OHLC4`|
|HLCC4 - Weighted Price|`.HLCC4`|
|**AVERAGES & TRENDS**||
|AFIRMA - Adaptive FIR Moving Average|`Afirma`|
|ALMA - Arnaud Legoux Moving Average|`Alma`|
|DEMA - Double Exponential Moving Average|`Dema`|
|DSMA - Dynamic Simple Moving Average|`Dsma`|
|DWMA - Dynamic Weighted Moving Average|`Dwma`|
|EMA - Exponential Moving Average|`Ema`|
|EPMA - Endpoint Moving Average|`Epma`|
|FRAMA - Fractal Adaptive Moving Average|`Frama`|
|FWMA - Forward Weighted Moving Average|`Fwma`|
|GMA - Gaussian Moving Average|`Gma`|
|HMA - Hull Moving Average|`Hma`|
|HTIT - Hilbert Transform Instantaneous Trendline|`Htit`|
|HWMA - Hann Weighted Moving Average|`Hwma`|
|JMA - Jurik Moving Average|`Jma`|
|KAMA - Kaufman Adaptive Moving Average|`Kama`|
|LTMA - Linear Time Moving Average|`Ltma`|
|MAAF - Moving Average Adaptive Filter|`Maaf`|
|MAMA* - MESA Adaptive Moving Average (MAMA, FAMA)|`Mama`|
|MGDI - McGinley Dynamic Indicator|`Mgdi`|
|MMA - Modified Moving Average|`Mma`|
|PWMA - Parabolic Weighted Moving Average|`Pwma`|
|QEMA - Quick Exponential Moving Average|`Qema`|
|REMA - Regularized Exponential Moving Average|`Rema`|
|RMA - Running Moving Average|`Rma`|
|SINEMA - Sine-weighted Moving Average|`Sinema`|
|SMA - Simple Moving Average|`Sma`|
|SMMA - Smoothed Moving Average|`Smma`|
|T3 - Triple Exponential Moving Average (T3)|`T3`|
|TEMA - Triple Exponential Moving Average|`Tema`|
|TRIMA - Triangular Moving Average|`Trima`|
|VIDYA - Variable Index Dynamic Average|`Vidya`|
|WMA - Weighted Moving Average|`Wma`|
|ZLEMA - Zero-Lag Exponential Moving Average|`Zlema`|
|**MOMENTUM INDICATORS**||
|ADX - Average Directional Movement Index|`Adx`|
|ADXR - Average Directional Movement Index Rating|`Adxr`|
|APO - Absolute Price Oscillator|`Apo`|
|DMI* - Directional Movement Index (DI+, DI-)|`Dmi`|
|DMX - Jurik Directional Movement Index|`Dmx`|
|DPO - Detrended Price Oscillator|`Dpo`|
|MACD* - Moving Average Convergence/Divergence|`Macd`|
|MOM - Momentum|`Mom`|
|PMO - Price Momentum Oscillator|`Pmo`|
|PO - Price Oscillator|`Po`|
|PPO - Percentage Price Oscillator|`Ppo`|
|PRS - Price Relative Strength|`Prs`|
|ROC - Rate of Change|`Roc`|
|TSI - True Strength Index|`Tsi`|
|TRIX - 1-day ROC of TEMA|`Trix`|
|VEL - Jurik Signal Velocity|`Vel`|
|VORTEX* - Vortex Indicator (VI+, VI-)|`Vortex`|
|**OSCILLATORS**||
|AC - Acceleration Oscillator|`Ac`|
|AO - Awesome Oscillator|`Ao`|
|AROON* - Aroon oscillator (Up, Down)|`Aroon`|
|BOP - Balance of Power|`Bop`|
|CCI - Commodity Channel Index|`Cci`|
|CFO - Chande Forcast Oscillator|`Cfo`|
|CMO - Chande Momentum Oscillator|`Cmo`|
|CHOP - Choppiness Index|`Chop`|
|COG - Ehler's Center of Gravity|`Cog`|
|🚧 COPPOCK - Coppock Curve|`Coppock`|
|🚧 CRSI - Connor RSI|`Crsi`|
|🚧 CTI - Ehler's Correlation Trend Indicator|`Cti`|
|🚧 DOSC - Derivative Oscillator|`Dosc`|
|🚧 EFI - Elder Ray's Force Index|`Efi`|
|🚧 FISHER - Fisher Transform|`Fisher`|
|🚧 FOSC - Forecast Oscillator|`Fosc`|
|🚧 GATOR* - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth)|`Gator`|
|🚧 KDJ* - KDJ Indicator (K, D, J lines)|`Kdj`|
|🚧 KRI - Kairi Relative Index|`Kri`|
|RSI - Relative Strength Index|`Rsi`|
|RSX - Jurik Trend Strength Index|`Rsx`|
|🚧 RVGI* - Relative Vigor Index (RVGI, Signal)|`Rvgi`|
|🚧 SMI - Stochastic Momentum Index|`Smi`|
|🚧 SRSI* - Stochastic RSI (SRSI, Signal)|`Srsi`|
|🚧 STC - Schaff Trend Cycle|`Stc`|
|🚧 STOCH* - Stochastic Oscillator (%K, %D)|`Stoch`|
|🚧 TSI - True Strength Index|`Tsi`|
|🚧 UO - Ultimate Oscillator|`Uo`|
|🚧 WILLR - Larry Williams' %R|`Willr`|
|**VOLATILITY INDICATORS**||
|ADR - Average Daily Range|`Adr`|
|AP - Andrew's Pitchfork|`Ap`|
|ATR - Average True Range|`Atr`|
|ATRP - Average True Range Percent|`Atrp`|
|ATRS - ATR Trailing Stop|`Atrs`|
|🚧 BB* - Bollinger Bands® (Upper, Middle, Lower)|`Bb`|
|🚧 CCV - Close-to-Close Volatility|`Ccv`|
|🚧 CE - Chandelier Exit|`Ce`|
|🚧 CV - Conditional Volatility (ARCH/GARCH)|`Cv`|
|🚧 CVI - Chaikin's Volatility|`Cvi`|
|🚧 DC* - Donchian Channels (Upper, Middle, Lower)|`Dc`|
|🚧 EWMA - Exponential Weighted Moving Average Volatility|`Ewma`|
|🚧 FCB - Fractal Chaos Bands|`Fcb`|
|🚧 GKV - Garman-Klass Volatility|`Gkv`|
|🚧 HLV - High-Low Volatility|`Hlv`|
|HV - Historical Volatility|`Hv`|
|🚧 ICH* - Ichimoku Cloud (Conversion, Base, Leading Span A, Leading Span B, Lagging Span)|`Ich`|
|JVOLTY - Jurik Volatility|`Jvolty`|
|🚧 KC* - Keltner Channels (Upper, Middle, Lower)|`Kc`|
|🚧 NATR - Normalized Average True Range|`Natr`|
|🚧 PCH - Price Channel Indicator|`Pch`|
|🚧 PSAR* - Parabolic Stop and Reverse (Value, Trend)|`Psar`|
|🚧 PV - Parkinson Volatility|`Pv`|
|🚧 RSV - Rogers-Satchell Volatility|`Rsv`|
|RV - Realized Volatility|`Rv`|
|RVI - Relative Volatility Index|`Rvi`|
|🚧 STARC* - Starc Bands (Upper, Middle, Lower)|`Starc`|
|🚧 SV - Stochastic Volatility|`Sv`|
|TR - True Range|`Tr`|
|UI - Ulcer Index|`Ui`|
|VC* - Volatility Cone (Mean, Upper Bound, Lower Bound)|`Vc`|
|VOV - Volatility of Volatility|`Vov`|
|VR - Volatility Ratio|`Vr`|
|VS* - Volatility Stop (Long Stop, Short Stop)|`Vs`|
|🚧 YZV - Yang-Zhang Volatility|`Yzv`|
|**VOLUME INDICATORS**||
|ADL - Chaikin Accumulation Distribution Line|`Adl`|
|ADOSC - Chaikin Accumulation Distribution Oscillator|`Adosc`|
|AOBV - Archer On-Balance Volume|`Aobv`|
|CMF - Chaikin Money Flow|`Cmf`|
|EOM - Ease of Movement|`Eom`|
|KVO - Klinger Volume Oscillator|`Kvo`|
|MFI - Money Flow Index|`Mfi`|
|NVI - Negative Volume Index|`Nvi`|
|OBV - On-Balance Volume|`Obv`|
|PVI - Positive Volume Index|`Pvi`|
|PVOL - Price-Volume|`Pvol`|
|PVO - Percentage Volume Oscillator|`Pvo`|
|PVR - Price Volume Rank|`Pvr`|
|PVT - Price Volume Trend|`Pvt`|
|TVI - Trade Volume Index|`Tvi`|
|VF - Volume Force|`Vf`|
|VP - Volume Profile|`Vp`|
|VWAP - Volume Weighted Average Price|`Vwap`|
|VWMA - Volume Weighted Moving Average|`Vwma`|
|**NUMERICAL ANALYSIS**||
|🚧 BETA* - Beta coefficient (Beta, R-squared)|`Beta`|
|🚧 CORR* - Correlation Coefficient (Correlation, P-value)|`Corr`|
|CURVATURE - Rate of Change in Direction or Slope|`Curvature`|
|ENTROPY - Measure of Uncertainty or Disorder|`Entropy`|
|🚧 HUBER - Huber Loss|`Huber`|
|🚧 HURST - Hurst Exponent|`Hurst`|
|KURTOSIS - Measure of Tails/Peakedness|`Kurtosis`|
|MAX - Maximum with exponential decay|`Max`|
|MEDIAN - Middle value|`Median`|
|MIN - Minimum with exponential decay|`Min`|
|MODE - Most Frequent Value|`Mode`|
|PERCENTILE - Rank Order|`Percentile`|
|🚧 RSQUARED* - Coefficient of Determination (R-squared, Adjusted R-squared)|`Rsquared`|
|SKEW - Skewness, asymmetry of distribution|`Skew`|
|SLOPE - Rate of Change, Linear Regression|`Slope`|
|STDDEV - Standard Deviation, Measure of Spread|`Stddev`|
|🚧 THEIL* - Theil's U Statistics (U1, U2)|`Theil`|
|🚧 TSF* - Time Series Forecast (Forecast, Confidence Interval)|`Tsf`|
|VARIANCE - Average of Squared Deviations|`Variance`|
|ZSCORE - Standardized Score|`Zscore`|
|**ERRORS**||
|HUBER - Huber Loss|`Huber`|
|MAE - Mean Absolute Error|`Mae`|
|MAPD - Mean Absolute Percentage Deviation|`Mapd`|
|MAPE - Mean Absolute Percentage Error|`Mape`|
|MASE - Mean Absolute Scaled Error|`Mase`|
|MDA - Mean Directional Accuracy|`Mda`|
|ME - Mean Error|`Me`|
|MPE - Mean Percentage Error|`Mpe`|
|MSE - Mean Squared Error|`Mse`|
|MSLE - Mean Squared Logarithmic Error|`Msle`|
|RAE - Relative Absolute Error|`Rae`|
|RMSE - Root Mean Squared Error|`Rmse`|
|RMSLE - Root Mean Squared Logarithmic Error|`Rmsle`|
|RSE - Relative Squared Error|`Rse`|
|RSQUARED - R-Squared (Coefficient of Determination)|`Rsquared`|
|SMAPE - Symmetric Mean Absolute Percentage Error|`Smape`|
@@ -0,0 +1,43 @@
# ADX - Average Directional Index
The Average Directional Index (ADX) is your market's GPS for trend strength - it doesn't tell you which direction to go, but it sure lets you know if you're on the expressway or stuck in local traffic. While most indicators focus on price direction, ADX stands apart by measuring the raw power behind a trend, helping traders distinguish between markets that are truly trending and those that are just making noise. Think of it as your trend quality assurance system, providing a standardized measure from 0-100 that helps you avoid the classic trap of seeing trends where there are only trading ranges.
## Origin and Sources
**Creator**: J. Welles Wilder Jr. (yes, the same mathematical wizard behind RSI) introduced ADX in his groundbreaking 1978 book.
**Historical Context**: Developed alongside his Directional Movement System (DMS), ADX emerged from Wilder's frustration with existing trend indicators that couldn't reliably distinguish between trending and ranging markets.
**Fun Fact**: Wilder originally recommended calculating ADX by hand using 14-day periods. With just a calculator and daily prices, it took about an hour to compute a single ADX value. Today's computers do it in microseconds!
## Core Concept
Think of ADX as a trend strength meter that works like a car's speedometer - but instead of measuring speed, it measures how forcefully price is moving in a single direction. It does this by tracking both upward and downward price movements, then combining them into a single reading that tells you how strong the overall trend is, regardless of direction.
*Pro Tip* 🎯: While ADX values above 25 traditionally indicate a trend, crypto traders often use 20 as their threshold due to the market's inherent volatility.
## Key Features
- **Trend Strength Measurement**: Like a seismograph for market moves, ADX measures the power of price movement regardless of direction
- **Range/Trend Differentiation**: Acts as your market state detector, helping distinguish between trending and choppy conditions
- **Momentum Confirmation**: Shows whether a trend is gaining steam or running out of gas
## Real-World Application
### When to Use
- **Trend Confirmation**: Before entering trend-following trades, check if ADX confirms a strong trend
- **Range Detection**: When ADX is low, prepare for range-trading opportunities
- **Exit Timing**: Watch for declining ADX values in strong trends for potential exit signals
### Common Pitfalls
1. **The Lag Trap**: ADX is like looking in the rearview mirror - it confirms trends but won't catch reversals early
2. **Direction Confusion**: A high ADX is like a wind speed meter - it tells you the wind is strong but not which way it's blowing
3. **Threshold Fixation**: Don't treat ADX levels like speed limits - market context matters more than fixed numbers
## Complementary Indicators
- **Moving Averages**: Like having both a compass (direction) and speedometer (ADX) for your trades
- **MACD**: Adds momentum context to your trend strength readings
- **Bollinger Bands**: Helps confirm whether price volatility matches trend strength
## Further Reading
- "New Concepts in Technical Trading Systems" by J. Welles Wilder
- "Technical Analysis of the Financial Markets" by John J. Murphy
- The definitive ADX chapter in "Technical Analysis Explained" by Martin Pring
*Remember*: ADX is like a weather radar for trends - it won't tell you where the market's going, but it'll sure let you know if there's a storm brewing. Use it to confirm trend conditions before applying your directional strategies.
@@ -0,0 +1,43 @@
# ADXR - Average Directional Index Rating
The Average Directional Index Rating (ADXR) takes the already powerful ADX and adds a time machine element. By comparing current trend strength to historical trend strength, ADXR helps traders spot shifts in trend momentum before they become obvious. Think of it as having both a speedometer and a speed history - it tells you not just how fast you're going, but whether you're accelerating or slowing down compared to a previous period.
## Origin and Sources
**Creator**: Another gem from J. Welles Wilder Jr.'s technical analysis toolkit, ADXR builds upon his original ADX indicator.
**Historical Context**: ADXR was developed to address a key limitation of ADX - the need for trend acceleration context. By comparing current and historical trend strength, ADXR adds a new dimension to trend analysis.
**Fun Fact**: Wilder was particularly proud of this refinement, noting that ADXR often signaled trend changes several days before they became apparent in price action.
## Core Concept
Think of ADXR as a trend momentum gauge. It compares today's trend strength to trend strength from a previous period (typically 14 days ago) to determine if trending momentum is building or fading. Like watching a car's acceleration rather than just its speed, ADXR helps you understand the changing dynamics of trend strength.
*Pro Tip* 🎯: Look for ADXR divergence from price - when price makes new highs but ADXR makes lower highs, the trend might be losing steam despite appearances.
## Key Features
- **Trend Acceleration**: Measures whether trend strength is increasing or decreasing
- **Early Warning System**: Often signals potential trend changes before price confirmation
- **Momentum Context**: Adds historical perspective to current trend strength
## Real-World Application
### When to Use
- **Trend Quality Assessment**: Perfect for gauging whether a trend is gaining or losing momentum
- **Entry Timing**: Use strengthening ADXR readings to confirm trend trade entries
- **Exit Signals**: Weakening ADXR can signal time to tighten stops or take profits
### Common Pitfalls
1. **Whipsaw Risk**: Like a car's tachometer, readings can fluctuate rapidly in choppy markets
2. **False Signals**: Not every ADXR decline leads to a trend reversal
3. **Time Frame Tension**: Different time frames can show conflicting ADXR signals
## Complementary Indicators
- **ADX**: The foundation indicator - use ADXR to add acceleration context
- **Price Action**: Confirm ADXR signals with support/resistance breaks
- **Volume**: High volume with rising ADXR suggests strong trend momentum
## Further Reading
- "New Concepts in Technical Trading Systems" by J. Welles Wilder
- "Technical Analysis of the Financial Markets" by John J. Murphy
- "Trading with the Average Directional Index" in Technical Analysis of Stocks & Commodities magazine
*Remember*: ADXR is like having trend strength in stereo - comparing past and present to compose a fuller picture of market momentum. Use it to fine-tune your trend trading entries and exits, but always confirm with price action.
@@ -0,0 +1,43 @@
# APO - Absolute Price Oscillator
The Absolute Price Oscillator (APO) cuts through market noise with elegant simplicity - it's the purest expression of the difference between two moving averages. While its cousin the MACD gets more attention at the trading party, APO shows up without the fancy signal line and histogram, delivering raw momentum readings in actual price terms. Think of it as your market's speedometer that shows the exact speed difference between fast and slow price movements.
## Origin and Sources
**Creator**: While the exact origin is debated, APO emerged from the moving average crossover systems popular in the 1970s and 1980s.
**Historical Context**: Developed as traders sought a simpler alternative to percentage-based oscillators, APO provides momentum readings in actual price units, making it especially valuable for position sizing.
**Fun Fact**: APO's value in absolute price terms means it naturally adjusts to different price ranges - a feature particularly appreciated by institutional traders managing large positions.
## Core Concept
Think of APO as measuring the gap between two moving averages in plain price terms. Like measuring the distance between two cars traveling at different speeds, APO tells you exactly how far apart the fast and slow moving averages are. When this gap widens, momentum is increasing; when it narrows, momentum is weakening.
*Pro Tip* 🎯: Use APO values to help size your positions - larger APO readings often indicate stronger trends and might justify larger position sizes.
## Key Features
- **Absolute Values**: Shows momentum in actual price units rather than percentages
- **Trend Direction**: Positive/negative readings clearly show trend direction
- **Position Sizing Tool**: Price-based readings help inform position sizing decisions
## Real-World Application
### When to Use
- **Trend Identification**: Zero-line crosses signal potential trend changes
- **Momentum Assessment**: Growing APO values suggest strengthening trends
- **Position Sizing**: Use APO magnitude to adjust position sizes proportionally
### Common Pitfalls
1. **Price Level Dependency**: Same APO value means different things at different price levels
2. **Timing Lag**: As a moving average-based indicator, APO lags price action
3. **False Signals**: Small crosses around zero don't always indicate meaningful trend changes
## Complementary Indicators
- **Volume**: Confirms whether APO moves have strong backing
- **Price Action**: Use support/resistance to confirm APO signals
- **Volatility Indicators**: Help contextualize APO readings in different market conditions
## Further Reading
- "Technical Analysis Explained" by Martin Pring
- "Technical Analysis of the Financial Markets" by John Murphy
- "Moving Averages: 60 Years of Research" in Journal of Portfolio Management
*Remember*: APO is like a market speedometer showing the exact speed difference in price terms. Its beauty lies in its simplicity - when the fast average pulls away from the slow, momentum is building; when they come together, momentum is waning. Use these clear signals to guide both timing and position sizing.
@@ -0,0 +1,43 @@
# DMI - Directional Movement Index
The Directional Movement Index (DMI) is your market's compass, but instead of pointing north, it points to the direction of maximum force. While most indicators blur the line between up and down movement, DMI keeps them crystal clear by separately measuring bullish and bearish pressure. Think of it as having two force meters - one for buyers (+DI) and one for sellers (-DI), letting you see exactly who's winning the market tug-of-war.
## Origin and Sources
**Creator**: J. Welles Wilder Jr. introduced DMI as part of his Directional Movement System, alongside ADX.
**Historical Context**: Developed in the 1970s commodity markets, DMI was designed to solve a specific problem: determining not just trend strength, but which side (buyers or sellers) was controlling the market.
**Fun Fact**: Wilder considered DMI the foundation of his entire trading system - ADX was actually created as a supplement to DMI, not the other way around!
## Core Concept
Think of DMI as two competing teams in a tug-of-war. The +DI line represents the buying team's strength, while the -DI line shows the selling team's power. When +DI is higher than -DI, the buyers are winning; when -DI is higher, the sellers have the upper hand. The greater the gap between the lines, the more dominant one side is over the other.
*Pro Tip* 🎯: Don't just trade crossovers - the best signals often come when one DI line is substantially stronger than the other and ADX confirms the trend strength.
## Key Features
- **Directional Clarity**: Separate measurement of bullish and bearish pressure
- **Crossover Signals**: +DI and -DI crossovers suggest potential trend changes
- **Trend Confirmation**: Works with ADX to confirm trend direction and strength
## Real-World Application
### When to Use
- **Trend Direction**: Use DI line positions to confirm trend direction
- **Entry Points**: DI crossovers with strong ADX suggest potential entries
- **Strength Assessment**: Compare DI line separation to gauge trend dominance
### Common Pitfalls
1. **False Crossovers**: Not every DI crossover leads to a significant move
2. **Whipsaw Markets**: DMI can give conflicting signals in choppy conditions
3. **Timing Issues**: Like all trend indicators, DMI lags price action
## Complementary Indicators
- **ADX**: The perfect partner - DMI shows direction, ADX shows strength
- **Price Action**: Use support/resistance to confirm DMI signals
- **Volume**: Higher volume on DI crosses suggests more reliable signals
## Further Reading
- "New Concepts in Technical Trading Systems" by J. Welles Wilder
- "Trading with Directional Movement" by Martin Pring
- "The Definitive Guide to Directional Movement" in Technical Analysis of Stocks & Commodities
*Remember*: DMI is like having a referee in the eternal bull-bear battle, calling out which team is stronger at any given moment. Use it to identify who's in control of the market, but always wait for confirmation before taking action.
@@ -0,0 +1,20 @@
# DMX - Directional Movement Index (Jurik)
The DMX is one of Mark Jurik's enhanced technical indicators, building upon Wilder's directional concepts through his innovative JMA (Jurik Moving Average) technology. Think of it as a high-definition version of traditional directional indicators - it applies Jurik's sophisticated filtering techniques to reveal clearer trend signals with less noise. Like upgrading from standard to high-definition TV, DMX offers a sharper, clearer picture of market direction.
## Origin and Sources
**Creator**: Mark Jurik developed DMX as part of his suite of enhanced technical indicators using JMA technology.
**Historical Context**: Created to address the limitations of traditional directional indicators in modern electronic markets, DMX represents a significant advancement in directional movement analysis through adaptive filtering techniques.
**Fun Fact**: The JMA technology behind DMX was developed after years of research into digital signal processing and its applications to financial markets.
## Core Concept
Think of DMX as a traditional directional indicator upgraded with advanced noise filtering technology. Using Jurik's adaptive smoothing techniques, it provides cleaner directional signals while maintaining responsiveness to genuine market moves. The result is an indicator that catches major trends but ignores much of the minor price noise that triggers false signals in traditional indicators.
[Rest of documentation remains similar but properly contextualized within Jurik's work]
## Further Reading
- "JMA Technical Documentation" by Mark Jurik
- Jurik Research Technical Papers
- "Digital Signal Processing in Technical Analysis" featuring Jurik's work
@@ -0,0 +1,43 @@
# DPO - Detrended Price Oscillator
The Detrended Price Oscillator (DPO) is like your market time machine - it strips away the long-term trend to reveal hidden price cycles. Unlike most oscillators that focus on momentum or trend, DPO has one mission: show you where we are in the current price cycle by eliminating the larger trend's influence. Think of it as removing the tide to see the waves more clearly.
## Origin and Sources
**Creator**: Initially developed by technicians seeking to isolate price cycles for forecasting.
**Historical Context**: Emerged from early market studies of price cycles and the need to separate shorter-term trading opportunities from longer-term trends.
**Fun Fact**: DPO's cycle-finding ability makes it particularly popular among traders who follow W.D. Gann's theories about market timing and cycles.
## Core Concept
Think of DPO as your trend eraser - it removes the overall price direction to highlight shorter-term cycles. It does this by comparing current price to a displaced moving average, effectively showing you where price is relative to its historical trend. The result? You can spot trading cycles that might be invisible when looking at price alone.
*Pro Tip* 🎯: The traditional 20-day DPO setting aims to identify monthly cycles, but adjust this period to match the trading cycles you're hunting.
## Key Features
- **Cycle Identification**: Reveals trading cycles hidden by larger trends
- **Trend Elimination**: Removes directional bias for clearer cycle analysis
- **Zero Line**: Helps identify overbought/oversold conditions relative to the cycle
## Real-World Application
### When to Use
- **Cycle Trading**: Identify potential turning points in regular market cycles
- **Mean Reversion**: Spot prices stretched too far from their cyclic average
- **Market Timing**: Use cycle positioning to optimize entry/exit points
### Common Pitfalls
1. **Trend Ignorance**: Remember, DPO intentionally ignores the main trend
2. **Period Selection**: Wrong lookback period means measuring the wrong cycle
3. **False Cycles**: Not all markets have regular, tradeable cycles
## Complementary Indicators
- **Moving Averages**: Show the trend DPO is removing
- **RSI/Stochastics**: Confirm cycle extremes with momentum
- **Volume**: Validate cycle turns with volume confirmation
## Further Reading
- "Cycles: The Mysterious Forces That Trigger Events" by Edward R. Dewey
- "Technical Analysis of Stock Trends" by Robert D. Edwards and John Magee
- "The Profit Magic of Stock Transaction Timing" by J.M. Hurst
*Remember*: DPO is like a market metal detector that ignores the sand (trend) to find the hidden treasures (cycles) beneath. Use it to spot recurring patterns in price movement, but always remember that not every beep signals buried treasure - sometimes it's just noise.
@@ -0,0 +1,43 @@
# MOM - Momentum Indicator
The Momentum indicator (MOM) is price comparison in its purest form - it simply shows you how much price has changed over a set period. Like measuring the distance between two snapshots in time, MOM tells you whether prices are moving faster or slower, higher or lower than before. It's technical analysis at its most fundamental: measuring the speed of price change.
## Origin and Sources
**Creator**: One of the earliest technical indicators, momentum calculations have been used since the early days of technical analysis.
**Historical Context**: Emerged from early market observations that price movements tend to continue in the same direction until momentum begins to fade.
**Fun Fact**: While seemingly simple, momentum was one of the first indicators to quantify what legendary traders like Jesse Livermore observed intuitively about price movement.
## Core Concept
Think of MOM as your market speedometer - it measures how fast price is moving by comparing current price to a previous price. A positive reading means price is higher than X periods ago; negative means lower. The bigger the number, the faster the move. Simple, yet powerful.
*Pro Tip* 🎯: Watch for momentum divergence from price - when price makes new highs but momentum makes lower highs, the trend might be running out of steam.
## Key Features
- **Raw Price Change**: Shows absolute price difference over time
- **Zero Line**: Clear trend direction indicator
- **Divergence Signals**: Early warning system for potential trend changes
## Real-World Application
### When to Use
- **Trend Strength**: Gauge how powerfully price is moving
- **Reversal Spotting**: Look for momentum divergence from price
- **Entry Timing**: Use momentum confirmation for trend trades
### Common Pitfalls
1. **False Signals**: Not every momentum dip means trend reversal
2. **Time Period Choice**: Different lookback periods can give conflicting signals
3. **Price Scale Dependency**: Same momentum values mean different things at different price levels
## Complementary Indicators
- **Moving Averages**: Confirm trend direction
- **Volume**: Validate momentum signals
- **RSI**: Add oversold/overbought context to momentum readings
## Further Reading
- "Technical Analysis of Stock Trends" by Edwards and Magee
- "Technical Analysis of the Financial Markets" by John Murphy
- "Momentum, Direction, and Divergence" by William Blau
*Remember*: MOM is like a market thermometer - it tells you the temperature of price movement right now compared to before. Simple but essential, it's often the foundation for more complex momentum-based trading strategies.
@@ -0,0 +1,43 @@
# PMO - Price Momentum Oscillator
The Price Momentum Oscillator (PMO) is like a momentum indicator with built-in smoothing superpowers. Created by Carl Swenlin, it's essentially a super-refined version of ROC (Rate of Change) that uses double exponential smoothing to produce exceptionally clean momentum signals. Think of it as momentum viewed through a premium lens - sharper, clearer, and more focused.
## Origin and Sources
**Creator**: Carl Swenlin developed PMO to address the noise issues in traditional momentum indicators.
**Historical Context**: Emerged from Swenlin's work on improving momentum measurements through careful optimization of exponential smoothing techniques.
**Fun Fact**: The PMO's formula was specifically designed to maintain sensitivity while eliminating the spiky, erratic movements that plague simpler momentum indicators.
## Core Concept
Think of PMO as a momentum indicator that's been sent to finishing school. It starts with simple ROC calculations but then applies two stages of exponential smoothing to refine the signal. The result is like having a momentum indicator with built-in noise cancellation - smooth enough to be readable, but responsive enough to catch important moves.
*Pro Tip* 🎯: Watch the PMO signal line crossovers, but pay special attention when they occur near historical extreme levels - these often provide the highest probability signals.
## Key Features
- **Double Smoothing**: Two-stage exponential smoothing for cleaner signals
- **Signal Line**: Additional validation through signal line crossovers
- **Bounded Range**: Unlike raw momentum, PMO tends to stay within historical ranges
## Real-World Application
### When to Use
- **Trend Confirmation**: Validate trend strength with smooth momentum readings
- **Divergence Analysis**: Look for clear divergences with price
- **Overbought/Oversold**: Use historical extremes for mean reversion trades
### Common Pitfalls
1. **Smoothing Lag**: The price of smooth signals is some delay
2. **Range Shifts**: Long-term ranges can shift in strong trends
3. **Time Frame Conflicts**: Different time frames can show conflicting PMO signals
## Complementary Indicators
- **Moving Averages**: Frame the bigger trend context
- **Volume**: Validate PMO signals with volume confirmation
- **MACD**: Compare PMO's smooth signals with MACD for confirmation
## Further Reading
- "Technical Analysis: The Complete Resource for Financial Market Technicians" featuring Swenlin's work
- DecisionPoint's PMO documentation by Carl Swenlin
- "Momentum Analysis and Stock Market Strategies" in Technical Analysis of Stocks & Commodities
*Remember*: PMO is like having a premium noise-canceling headset for momentum signals - it costs you a bit in terms of lag, but rewards you with crystal-clear readings of market momentum. Perfect for traders who value signal clarity over speed.
@@ -0,0 +1,43 @@
# PO - Price Oscillator
The Price Oscillator (PO) strips price comparison down to its essence - it's simply the difference between two moving averages expressed in absolute terms. While its percentage-based cousin PPO gets more attention, PO speaks in the language traders understand best: pure price. Think of it as MACD without the complications, showing you the raw gap between fast and slow market movements.
## Origin and Sources
**Creator**: Evolved from early moving average crossover systems in technical analysis.
**Historical Context**: Developed as traders sought a simpler way to measure the spread between moving averages without percentage conversions.
**Fun Fact**: While less famous than MACD or PPO, PO is often preferred by futures traders and large position managers because its absolute price measurements help with position sizing.
## Core Concept
Think of PO as measuring the distance between two cars traveling at different speeds. The faster moving average is one car, the slower moving average is another, and PO tells you exactly how far apart they are in price terms. When they're getting further apart, momentum is building; when they're getting closer, momentum is waning.
*Pro Tip* 🎯: Since PO uses absolute price differences, its signals need to be scaled relative to the price level - a 5-point spread means something very different on a $20 stock versus a $200 stock.
## Key Features
- **Absolute Measurement**: Shows moving average spread in actual price terms
- **Zero Line**: Clear trend direction indicator
- **Momentum Gauge**: Spread width indicates trend strength
## Real-World Application
### When to Use
- **Trend Direction**: Zero-line crossovers signal trend changes
- **Momentum Assessment**: Widening spread suggests strengthening trend
- **Position Sizing**: Use spread width to help scale position sizes
### Common Pitfalls
1. **Price Level Dependency**: Must adjust interpretation for price level
2. **Moving Average Lag**: Inherent lag from using two moving averages
3. **Scaling Issues**: Different markets need different interpretation scales
## Complementary Indicators
- **Volume**: Validate PO signals with volume confirmation
- **Price Action**: Use support/resistance to confirm PO signals
- **Volatility Indicators**: Help contextualize PO spreads
## Further Reading
- "Technical Analysis of the Financial Markets" by John Murphy
- "Technical Analysis Using Multiple Timeframes" by Brian Shannon
- "Moving Average Studies in Technical Analysis" in Technical Analysis Journal
*Remember*: PO is like a market ruler measuring the gap between fast and slow moving averages in actual price terms. Its beauty lies in its simplicity - when the fast average pulls away from the slow, momentum is building; when they come together, momentum is waning. Just remember to adjust your ruler's scale to match your market's price level.
@@ -0,0 +1,48 @@
# PPO - Percentage Price Oscillator
The Percentage Price Oscillator (PPO) is MACD's more versatile cousin - it shows the percentage difference between two moving averages rather than the absolute difference. Think of it as a universal translator for price momentum - because it speaks in percentages, it lets you compare momentum across different price levels, time periods, and even different instruments. Perfect for traders who need to compare apples to oranges.
## Origin and Sources
**Creator**: Evolved from the MACD concept, adapted to address the need for comparable momentum readings across different securities.
**Historical Context**: Developed as traders and analysts needed a way to compare momentum across various stocks and markets with widely different price levels.
**Fun Fact**: While often overshadowed by MACD, PPO is actually more versatile for cross-market analysis and is preferred by many institutional traders for multi-asset strategies.
## Core Concept
Think of PPO as measuring the gap between two moving averages in percentage terms. Instead of saying "these averages are 10 points apart," PPO says "these averages are 5% apart." This simple shift to percentages makes it possible to compare momentum across any markets - whether you're looking at a $5 stock or a $500 stock, a 5% gap means the same thing.
*Pro Tip* 🎯: PPO values tend to be more consistent across time than MACD, making historical comparison more reliable even after significant price changes.
## Key Features
- **Percentage-Based**: Comparable across different price levels
- **Cross-Market Analysis**: Can compare momentum across different securities
- **Standard Signals**: Zero-line crossovers, signal line crossovers, and divergences
- **Histogram View**: Visual representation of momentum strength
## Real-World Application
### When to Use
- **Multi-Market Analysis**: Compare momentum across different securities
- **Portfolio Scanning**: Screen for strongest momentum across your universe
- **Historical Analysis**: Compare current momentum to historical periods
- **Trend Changes**: Spot momentum shifts through signal line crossovers
### Common Pitfalls
1. **False Signals**: Not every crossover is tradeable
2. **Time Frame Conflicts**: Different periods can show conflicting signals
3. **Context Matters**: Market conditions affect reliability of signals
4. **Divergence Traps**: Not all divergences lead to reversals
## Complementary Indicators
- **Volume**: Confirm PPO signals with volume
- **Relative Strength**: Compare PPO readings across sector/market
- **Volatility Indicators**: Help qualify PPO signals in different volatility regimes
- **Price Action**: Use support/resistance to confirm PPO signals
## Further Reading
- "Technical Analysis of the Financial Markets" by John Murphy
- "Technical Analysis Using Multiple Timeframes" by Brian Shannon
- "Momentum, Direction, and Divergence" by William Blau
- "The Visual Investor" by John Murphy
*Remember*: PPO is like having a universal translator for momentum - it converts price movements into percentages so you can compare momentum anywhere. Perfect for traders who need to track momentum across multiple markets or time periods. Just remember that like any translation, some nuance might be lost in conversion.
@@ -0,0 +1,48 @@
# PRS - Price Relative Strength
Price Relative Strength (PRS) is your market's performance comparator - it shows how one security is performing versus another by dividing their prices. Think of it as a financial tug-of-war scorer, keeping track of which security is winning the performance battle. Not to be confused with RSI (Relative Strength Index), PRS focuses on comparative performance rather than internal momentum.
## Origin and Sources
**Creator**: Evolved from early technical analysis practices of comparing different securities' performance.
**Historical Context**: Gained prominence in the 1950s and 1960s as sector rotation and relative performance analysis became key components of portfolio management.
**Fun Fact**: While simple in calculation, PRS became a cornerstone of modern sector rotation strategies and is a fundamental tool in the famous IBD (Investor's Business Daily) stock selection methodology.
## Core Concept
Think of PRS as a performance ratio calculator - it simply divides one security's price by another's (often an index or sector benchmark) to create a ratio. When the ratio rises, your security is outperforming; when it falls, it's underperforming. It's like having a continuous performance scoreboard.
*Pro Tip* 🎯: The slope of the PRS line is often more important than its absolute level - accelerating relative strength often precedes significant outperformance.
## Key Features
- **Direct Comparison**: Clear view of relative performance
- **Trend Identification**: Shows leadership/laggard relationships
- **Rotation Detection**: Helps identify sector/stock rotation patterns
- **Strength Confirmation**: Validates breakouts through relative strength
## Real-World Application
### When to Use
- **Stock Selection**: Find strongest stocks within a sector
- **Sector Analysis**: Identify leading/lagging sectors
- **Portfolio Management**: Guide rotation decisions
- **Risk Assessment**: Monitor relative weakness for position sizing
### Common Pitfalls
1. **Base Selection**: Wrong comparison base can lead to misleading signals
2. **Time Frame Mismatch**: Different time frames can show conflicting relationships
3. **Correlation Assumptions**: High correlation periods can suddenly break down
4. **Volume Ignorance**: Price relationships without volume can mislead
## Complementary Indicators
- **Volume**: Validate relative strength moves
- **Moving Averages**: Smooth PRS for clearer trends
- **Momentum Indicators**: Confirm relative strength trends
- **Volatility Measures**: Context for relative performance
## Further Reading
- "Technical Analysis of Stock Market Trends" by Edwards and Magee
- "How to Make Money in Stocks" by William O'Neil
- "Intermarket Analysis" by John Murphy
- "The Art of Relative Strength Investing" in Technical Analysis Journal
*Remember*: PRS is like a continuous performance scorekeeper for your markets - it tells you who's winning the performance game at any given time. Perfect for finding market leaders and avoiding laggards, but remember that today's winner isn't guaranteed tomorrow's championship.
@@ -0,0 +1,48 @@
# ROC - Rate of Change
The Rate of Change (ROC) is momentum distilled to its purest form - it simply shows you the percentage change in price over a set period. Think of it as your market's speedometer, measuring how fast price is moving in percentage terms. Unlike complex oscillators, ROC gives you raw, unfiltered price velocity that's immediately comparable across any market.
## Origin and Sources
**Creator**: One of the oldest technical indicators, ROC emerged from early market observations about momentum.
**Historical Context**: Developed in the early days of technical analysis when traders needed a simple way to quantify price changes over time.
**Fun Fact**: While newer momentum indicators have added layers of sophistication, ROC remains popular in quantitative trading systems due to its simplicity and lack of lag.
## Core Concept
Think of ROC as your market's speedometer calibrated in percentage terms. It answers one simple question: "How much has price changed over X periods?" A 10% ROC means price is 10% higher than X periods ago; -10% means it's 10% lower. This simplicity makes it instantly comparable across any market or time period.
*Pro Tip* 🎯: Watch for ROC divergence from price when both are making extremes - if price makes a new high but ROC doesn't, momentum might be waning.
## Key Features
- **Pure Momentum**: Unsmoothed, direct measurement of price change
- **Zero Line**: Clear trend direction indicator
- **Cross-Market Comparison**: Percentage basis allows direct comparison
- **Leading Indicator**: Often shows momentum shifts before price
## Real-World Application
### When to Use
- **Trend Strength**: Gauge momentum behind price moves
- **Divergence Trading**: Spot momentum/price disagreements
- **Market Comparison**: Compare strength across different securities
- **Trend Confirmation**: Validate price breakouts
### Common Pitfalls
1. **Noise Sensitivity**: Unsmoothed calculation means more whipsaws
2. **Period Selection**: Different lookback periods can give conflicting signals
3. **Base Effect**: Large past moves can distort current readings
4. **False Divergences**: Not all divergences lead to reversals
## Complementary Indicators
- **Moving Averages**: Smooth ROC for clearer signals
- **Volume**: Confirm momentum with volume
- **Price Action**: Use support/resistance with ROC
- **Volatility Indicators**: Context for ROC readings
## Further Reading
- "Technical Analysis of Stock Trends" by Edwards and Magee
- "Technical Analysis of the Financial Markets" by John Murphy
- "Momentum, Direction, and Divergence" by William Blau
- "The New Science of Technical Analysis" by Thomas DeMark
*Remember*: ROC is like a high-performance car's speedometer - it gives you raw, unfiltered readings of market velocity. Its beauty lies in its simplicity and universality. Perfect for those who prefer their momentum straight up, no smoothing added. Just remember that sometimes a smooth ride might be preferable to a bumpy one.
@@ -0,0 +1,48 @@
# TRIX - Triple Exponential Average
TRIX is the momentum indicator that went to graduate school - it applies triple exponential smoothing to remove price noise while keeping the essence of the trend. Think of it as ROC with three layers of sophisticated filtering, designed to show you significant trends while ignoring minor price fluctuations. Its name comes from the "triple" smoothing process, not from any similarity to the breakfast cereal!
## Origin and Sources
**Creator**: Jack Hutson introduced TRIX in the 1980s through articles in Technical Analysis of Stocks & Commodities magazine.
**Historical Context**: Developed to address the need for a momentum indicator that could ignore minor price movements while remaining sensitive to significant trends.
**Fun Fact**: Despite its complex calculation, TRIX was one of the first indicators specifically designed to be calculated by early personal computers, making it a pioneer in the computational technical analysis era.
## Core Concept
Think of TRIX as a trend distillery - it takes price data and runs it through three rounds of exponential smoothing, then calculates the rate of change of the result. Like filtering water through multiple stages, each smoothing removes more noise, leaving you with purer trend signals. The final ROC calculation shows you how fast this purified trend is changing.
*Pro Tip* 🎯: Use the zero line as your trend filter - when TRIX is above zero, the filtered trend is up; below zero, it's down. But the most powerful signals often come from divergences with price.
## Key Features
- **Triple Smoothing**: Exceptional noise reduction
- **Momentum of Trend**: Shows speed of trend changes
- **Zero Line**: Clear trend direction reference
- **Signal Line**: Additional confirmation through signal line crossovers
## Real-World Application
### When to Use
- **Trend Confirmation**: Validate longer-term trend changes
- **Divergence Trading**: Spot high-probability reversal setups
- **Filter**: Screen out minor market movements
- **Entry/Exit Timing**: Use zero-line or signal line crossovers
### Common Pitfalls
1. **Lag**: Triple smoothing means significant delay
2. **Whipsaws**: Even with smoothing, ranging markets can produce false signals
3. **Period Sensitivity**: Different lookback periods can show conflicting signals
4. **Over-filtering**: Can miss important shorter-term moves
## Complementary Indicators
- **Price Action**: Use support/resistance with TRIX signals
- **Volume**: Confirm trend changes with volume
- **Faster Indicators**: Balance TRIX's lag with quicker signals
- **Volatility Indicators**: Context for signal reliability
## Further Reading
- "Technical Analysis of Stocks & Commodities" - Original TRIX articles by Jack Hutson
- "Technical Analysis: The Complete Resource for Financial Market Technicians"
- "Trend Following: How to Make a Fortune in Bull, Bear, and Black Swan Markets"
- "The Encyclopedia of Technical Market Indicators"
*Remember*: TRIX is like having a sophisticated trend-spotting algorithm from the 1980s - it might be slower than modern alternatives, but its triple-filtered signals can help you avoid false moves that trap traders using simpler tools. Perfect for position traders who want to focus on significant trends while ignoring market noise. Just remember that all that filtering comes at the cost of timeliness.
@@ -0,0 +1,48 @@
# TSI - True Strength Index
The True Strength Index (TSI) is like a precision scale for price momentum - it shows not just the direction and magnitude of price movement, but its underlying strength through double-smoothing both price change and its absolute value. Think of it as momentum with built-in signal clarity, designed to separate true price strength from market noise.
## Origin and Sources
**Creator**: William Blau developed TSI and introduced it in 1991 in Technical Analysis of Stocks & Commodities magazine.
**Historical Context**: Created to address the need for a momentum indicator that could clearly show both trend direction and underlying strength while minimizing false signals.
**Fun Fact**: Blau, a physicist by training, applied concepts from signal processing theory to create TSI, making it one of the first indicators to use sophisticated signal smoothing techniques.
## Core Concept
Think of TSI as measuring price momentum through a noise-canceling system. It tracks two things: price changes and the absolute values of those changes. By double-smoothing both and creating a ratio between them, TSI reveals the true strength behind price movements. Like having both a speedometer and an engine performance gauge, it tells you not just how fast price is moving, but how much power is behind the move.
*Pro Tip* 🎯: Watch for TSI crossing its signal line while near extreme levels - these often provide the highest probability trading signals.
## Key Features
- **Double Smoothing**: Exceptional noise reduction in momentum readings
- **Bounded Oscillator**: Values typically range between +100 and -100
- **Signal Line**: Additional confirmation through crossovers
- **Center Line**: Clear trend direction reference at zero
## Real-World Application
### When to Use
- **Trend Direction**: Zero-line helps confirm trend
- **Momentum Confirmation**: Validate price moves
- **Divergence Trading**: Spot potential reversals
- **Entry/Exit Timing**: Use signal line crossovers
### Common Pitfalls
1. **Lag**: Double smoothing creates notable delay
2. **Complex Calculation**: More difficult to fine-tune than simpler indicators
3. **Multiple Parameters**: More variables to optimize
4. **Time Frame Sensitivity**: Different settings needed for different time frames
## Complementary Indicators
- **Price Action**: Confirm TSI signals with support/resistance
- **Volume**: Validate strength readings with volume
- **Trend Indicators**: Provide context for TSI signals
- **Volatility Measures**: Help qualify signal reliability
## Further Reading
- "Momentum, Direction, and Divergence" by William Blau
- "The New Technical Trader" by Tushar Chande
- "Technical Analysis of Stocks & Commodities" - Original TSI articles
- "Advanced Technical Analysis Concepts"
*Remember*: TSI is like having a sophisticated strength meter for price movements - it might take longer to give you a reading than simpler tools, but its double-smoothed signals can help you avoid false moves that trap other traders. Perfect for those who want to measure not just price momentum, but the quality of that momentum. Just don't expect it to catch every quick market move - sometimes being smooth means being slow.
@@ -0,0 +1,43 @@
# VEL - Velocity (Jurik)
VEL represents Mark Jurik's enhanced take on momentum measurement, applying his sophisticated JMA (Jurik Moving Average) technology to create a more refined momentum indicator. Think of it as momentum measurement with noise-canceling headphones - it filters out market static to give you a clearer signal of genuine price velocity.
## Origin and Sources
**Creator**: Mark Jurik developed VEL as part of his suite of advanced technical indicators.
**Historical Context**: Created to address the limitations of traditional momentum indicators in modern, noisy markets through advanced digital signal processing techniques.
**Fun Fact**: The adaptive filtering technology in VEL comes from principles originally developed for radar and sonar systems.
## Core Concept
Think of VEL as momentum's graduate degree - it measures price change like traditional momentum but applies sophisticated filtering to separate real movement from market noise. Using Jurik's adaptive techniques, it provides smoother, more reliable readings of price velocity while maintaining responsiveness to genuine market moves.
*Pro Tip* 🎯: VEL's smoother signals often provide clearer divergence patterns than traditional momentum.
## Key Features
- **Adaptive Filtering**: Automatically adjusts to market conditions
- **Noise Reduction**: Cleaner signals than traditional momentum
- **True Velocity**: Better measurement of actual price movement speed
## Real-World Application
### When to Use
- **Trend Confirmation**: Verify trend strength with less noise
- **Reversal Detection**: Spot high-probability turning points
- **Market State Analysis**: Gauge true market velocity regardless of conditions
### Common Pitfalls
1. **Over-filtering**: Sometimes important short-term signals get smoothed away
2. **Complexity**: More parameters to understand and optimize
3. **Lag Consideration**: Smoother signals mean slightly later signals
## Complementary Indicators
- **Price Action**: Primary validation of VEL signals
- **Volume**: Confirm velocity changes with volume
- **Other Jurik Indicators**: Often work well together in a unified system
## Further Reading
- "JMA Technical Documentation" by Mark Jurik
- Jurik Research Technical Papers
- "Digital Processing Techniques in Technical Analysis"
*Remember*: VEL is like a precision radar for price movement - it might take more time to master than basic momentum, but it rewards you with clearer signals and fewer false alarms. Use it when you need more reliable momentum readings in noisy markets.
@@ -0,0 +1,48 @@
# Vortex - Vortex Indicator
The Vortex Indicator is your market's compass for trending direction with a twist - it simultaneously tracks both positive and negative price movement trends. Think of it as having two trend trackers that compete to show which direction has true momentum. Named after the vortex pattern in nature, it aims to capture the swirling, cyclical nature of price trends.
## Origin and Sources
**Creator**: Etienne Botes and Douglas Siepman introduced the Vortex Indicator in the January 2010 edition of Technical Analysis of Stocks & Commodities magazine.
**Historical Context**: Developed by studying the relationship between highs and lows across multiple periods, inspired by the vortex pattern found in nature.
**Fun Fact**: The creators were inspired by Viktor Schauberger's study of natural flow systems and vortices in water, applying these natural principles to market movements.
## Core Concept
Think of Vortex as tracking two competing forces in the market - upward trending movement (VI+) and downward trending movement (VI-). Like watching two rivers merge and create a vortex, VI measures the strength of both bullish and bearish price movements over time. When VI+ crosses above VI-, an uptrend may be starting; when VI- crosses above VI+, a downtrend may be forming.
*Pro Tip* 🎯: Look for VI crossovers that occur after a strong trend in the opposite direction - these often signal high-probability reversal points.
## Key Features
- **Dual Lines**: VI+ and VI- track both trend directions simultaneously
- **Crossover Signals**: Clear trend change identification
- **Trend Strength**: Distance between lines shows trend power
- **Natural Design**: Based on principles found in natural systems
## Real-World Application
### When to Use
- **Trend Identification**: Spot potential trend beginnings
- **Trend Confirmation**: Validate existing trends
- **Reversal Detection**: Identify possible trend changes
- **Trend Strength Analysis**: Gauge momentum behind moves
### Common Pitfalls
1. **Whipsaws**: Can give false signals in choppy markets
2. **Period Sensitivity**: Different lookback periods affect signal timing
3. **Lag Factor**: Like all trend indicators, confirms after the fact
4. **False Crossovers**: Not every crossover leads to a trend
## Complementary Indicators
- **ADX**: Confirm trend strength
- **Moving Averages**: Provide broader trend context
- **Volume**: Validate trend signals
- **Support/Resistance**: Frame entry/exit points
## Further Reading
- "Technical Analysis of Stocks & Commodities" - Original 2010 Vortex article
- "The Technical Analysis Course" by Thomas Meyers
- "Living In the Flow: Viktor Schauberger's Water Science"
- "Technical Analysis: Modern Perspectives" by Gordon Scott
*Remember*: Vortex is like having a weather vane that shows both wind directions at once - it helps you see which force is stronger in the market. Perfect for trend traders who want to track both bullish and bearish pressure simultaneously. Just remember that like real weather patterns, market trends can be unpredictable and change quickly.
View File
View File
View File
View File
View File
View File
View File
View File

Some files were not shown because too many files have changed in this diff Show More