-
Notifications
You must be signed in to change notification settings - Fork 246
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
71bef73
commit 15e3568
Showing
11 changed files
with
2,314 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using Skender.Stock.Indicators; | ||
|
||
namespace Custom.Stock.Indicators; | ||
|
||
// Custom results class | ||
// This inherits many of the extension methods, like .RemoveWarmupPeriods() | ||
public class AtrWmaResult : ResultBase | ||
{ | ||
public decimal? AtrWma { get; set; } | ||
} | ||
|
||
public static class CustomIndicators | ||
{ | ||
// Custom ATR WMA calculation | ||
public static IEnumerable<AtrWmaResult> GetAtrWma<TQuote>( | ||
this IEnumerable<TQuote> quotes, | ||
int lookbackPeriods = 10) | ||
where TQuote : IQuote | ||
{ | ||
// sort quotes and convert to list | ||
List<TQuote> quotesList = quotes | ||
.OrderBy(x => x.Date) | ||
.ToList(); | ||
|
||
// initialize results | ||
List<AtrWmaResult> results = new(quotesList.Count); | ||
|
||
// perform pre-requisite calculations to get ATR values | ||
List<AtrResult> atrResults = quotes | ||
.GetAtr(lookbackPeriods) | ||
.ToList(); | ||
|
||
// roll through quotes | ||
for (int i = 0; i < quotesList.Count; i++) | ||
{ | ||
TQuote q = quotesList[i]; | ||
|
||
AtrWmaResult r = new() | ||
{ | ||
Date = q.Date | ||
}; | ||
|
||
// only do calculations after uncalculable periods | ||
if (i >= lookbackPeriods - 1) | ||
{ | ||
decimal? sumWma = 0; | ||
decimal? sumAtr = 0; | ||
|
||
for (int p = i - lookbackPeriods + 1; p <= i; p++) | ||
{ | ||
decimal close = quotesList[p].Close; | ||
decimal? atr = atrResults[p]?.Atr; | ||
|
||
sumWma += atr * close; | ||
sumAtr += atr; | ||
} | ||
|
||
r.AtrWma = sumWma / sumAtr; | ||
} | ||
|
||
// add record to results | ||
results.Add(r); | ||
} | ||
|
||
return results; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
docs/examples/CustomIndicators/CustomIndicatorsLibrary.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Skender.Stock.Indicators" Version="1.22.2" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
--- | ||
title: Custom Indicators | ||
permalink: /custom-indicators/ | ||
layout: default | ||
--- | ||
|
||
# {{ page.title }} | ||
|
||
At some point in your journey, you may want to create your own custom indicators. | ||
The following is an example of how you'd create your own. | ||
This example is also included in our [example usage code]({{site.baseurl}}/examples/#content). | ||
|
||
## STEP 1: Create the Results class | ||
|
||
Create your results class by extending the library `ResultBase` class. This will allow you to inherit many of the [utility functions]({{site.baseurl}}/utilities/#utilities-for-indicator-results), such as `RemoveWarmupPeriods()`. | ||
|
||
```csharp | ||
using Skender.Stock.Indicators; | ||
namespace Custom.Stock.Indicators; | ||
|
||
// custom results class | ||
public class AtrWmaResult : ResultBase | ||
{ | ||
// date property is inherited here, | ||
// so you only need to add custom items | ||
public decimal? AtrWma { get; set; } | ||
} | ||
``` | ||
|
||
## STEP 2: Create the your custom indicator | ||
|
||
Create your custom algorithm in the same style as our main library so the API functions identically. | ||
|
||
```csharp | ||
public static class CustomIndicators | ||
{ | ||
// Custom ATR WMA calculation | ||
public static IEnumerable<AtrWmaResult> GetAtrWma<TQuote>( | ||
this IEnumerable<TQuote> quotes, | ||
int lookbackPeriods = 10) | ||
where TQuote : IQuote | ||
{ | ||
// sort quotes and convert to list | ||
List<TQuote> quotesList = quotes | ||
.OrderBy(x => x.Date) | ||
.ToList(); | ||
|
||
// initialize results | ||
List<AtrWmaResult> results = new(quotesList.Count); | ||
|
||
// perform pre-requisite calculations to get ATR values | ||
List<AtrResult> atrResults = quotes | ||
.GetAtr(lookbackPeriods) | ||
.ToList(); | ||
|
||
// roll through quotes | ||
for (int i = 0; i < quotesList.Count; i++) | ||
{ | ||
TQuote q = quotesList[i]; | ||
|
||
AtrWmaResult r = new() | ||
{ | ||
Date = q.Date | ||
}; | ||
|
||
// only do calculations after uncalculable periods | ||
if (i >= lookbackPeriods - 1) | ||
{ | ||
decimal? sumWma = 0; | ||
decimal? sumAtr = 0; | ||
|
||
for (int p = i - lookbackPeriods + 1; p <= i; p++) | ||
{ | ||
decimal close = quotesList[p].Close; | ||
decimal? atr = atrResults[p]?.Atr; | ||
|
||
sumWma += atr * close; | ||
sumAtr += atr; | ||
} | ||
|
||
r.AtrWma = sumWma / sumAtr; | ||
} | ||
|
||
// add record to results | ||
results.Add(r); | ||
} | ||
|
||
return results; | ||
} | ||
} | ||
``` | ||
|
||
## STEP 3: Use your indicator just like the others | ||
|
||
```csharp | ||
using Skender.Stock.Indicators; | ||
using Custom.Stock.Indicators; // your custom library | ||
[..] | ||
|
||
// fetch historical quotes from your feed (your method) | ||
IEnumerable<Quote> quotes = GetHistoryFromFeed("MSFT"); | ||
|
||
// calculate 10-period ATR WMA | ||
IEnumerable<AtrWmaResult> results = quotes.GetAtrWma(10); | ||
|
||
// use results as needed for your use case (example only) | ||
foreach (AtrWmaResult r in results) | ||
{ | ||
Console.WriteLine($"ATR WMA on {r.Date:d} was ${r.AtrWma:N4}"); | ||
} | ||
``` | ||
|
||
```console | ||
ATR WMA on 4/19/2018 was $255.0590 | ||
ATR WMA on 4/20/2018 was $255.2015 | ||
ATR WMA on 4/23/2018 was $255.6135 | ||
ATR WMA on 4/24/2018 was $255.5105 | ||
ATR WMA on 4/25/2018 was $255.6570 | ||
ATR WMA on 4/26/2018 was $255.9705 | ||
.. | ||
``` |
24 changes: 24 additions & 0 deletions
24
docs/examples/CustomIndicatorsUsage/CustomIndicatorsUsage.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>disable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\CustomIndicators\CustomIndicatorsLibrary.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Update="quotes.data.json"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using Custom.Stock.Indicators; | ||
using Newtonsoft.Json; | ||
using Skender.Stock.Indicators; | ||
|
||
namespace ConsoleApp; | ||
|
||
// USE CUSTOM INDICATORS exactly the same as | ||
// other indicators in the library | ||
|
||
public class Program | ||
{ | ||
public static void Main() | ||
{ | ||
|
||
// fetch historical quotes from data provider | ||
IEnumerable<Quote> quotes = GetHistoryFromFeed(); | ||
|
||
// calculate 10-period custom AtrWma | ||
IEnumerable<AtrWmaResult> results = quotes.GetAtrWma(10); | ||
|
||
// show results | ||
Console.WriteLine("ATR WMA Results ---------------------------"); | ||
|
||
foreach (AtrWmaResult r in results.TakeLast(25)) | ||
// only showing last 25 records for brevity | ||
{ | ||
Console.WriteLine($"ATR WMA on {r.Date:u} was ${r.AtrWma:N3}"); | ||
} | ||
} | ||
|
||
|
||
private static IEnumerable<Quote> GetHistoryFromFeed() | ||
{ | ||
/************************************************************ | ||
We're mocking a data provider here by simply importing a | ||
JSON file, a similar format of many public APIs. | ||
This approach will vary widely depending on where you are | ||
getting your quote history. | ||
See https://github.com/DaveSkender/Stock.Indicators/discussions/579 | ||
for free or inexpensive market data providers and examples. | ||
The return type of IEnumerable<Quote> can also be List<Quote> | ||
or ICollection<Quote> or other IEnumerable compatible types. | ||
************************************************************/ | ||
|
||
string json = File.ReadAllText("quotes.data.json"); | ||
|
||
List<Quote> quotes = JsonConvert.DeserializeObject<IReadOnlyCollection<Quote>>(json) | ||
.OrderBy(x => x.Date) | ||
.ToList(); | ||
|
||
return quotes; | ||
} | ||
} |
Oops, something went wrong.