Skip to content

Commit

Permalink
extendable classes (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveSkender authored Dec 31, 2019
1 parent 1be4ae4 commit cd444ef
Show file tree
Hide file tree
Showing 34 changed files with 140 additions and 79 deletions.
11 changes: 6 additions & 5 deletions Indicators/BollingerBands/BollingerBands.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ namespace Skender.Stock.Indicators

public class BollingerBandsResult
{
public DateTime Date { get; internal set; }
public decimal? Sma { get; internal set; }
public decimal? UpperBand { get; internal set; }
public decimal? LowerBand { get; internal set; }
public bool? IsDiverging { get; internal set; }
public int Index { get; set; }
public DateTime Date { get; set; }
public decimal? Sma { get; set; }
public decimal? UpperBand { get; set; }
public decimal? LowerBand { get; set; }
public bool? IsDiverging { get; set; }
}

}
1 change: 1 addition & 0 deletions Indicators/BollingerBands/BollingerBands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static IEnumerable<BollingerBandsResult> GetBollingerBands(IEnumerable<Qu
{
BollingerBandsResult result = new BollingerBandsResult
{
Index = (int)h.Index,
Date = h.Date
};

Expand Down
3 changes: 2 additions & 1 deletion Indicators/BollingerBands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IEnumerable<BollingerBandsResult> results = Indicator.GetBollingerBands(history,

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`.
| `lookbackPeriod` | int | Number of periods (`N`) for the center line moving average
| `standardDeviation` | int | Width of bands. Standard deviations (`D`) from the moving average

Expand All @@ -28,6 +28,7 @@ The first `N-1` slow periods + signal period will have `null` values since there

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Sma` | decimal | Simple moving average (SMA) of Close price (center line)
| `UpperBand` | decimal | Upper line is `D` standard deviations above the SMA
Expand Down
5 changes: 3 additions & 2 deletions Indicators/Ema/Ema.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ namespace Skender.Stock.Indicators

public class EmaResult
{
public DateTime Date { get; internal set; }
public decimal? Ema { get; internal set; }
public int Index { get; set; }
public DateTime Date { get; set; }
public decimal? Ema { get; set; }
}

}
1 change: 1 addition & 0 deletions Indicators/Ema/Ema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static IEnumerable<EmaResult> GetEma(IEnumerable<Quote> history, int look

EmaResult result = new EmaResult
{
Index = (int)h.Index,
Date = h.Date
};

Expand Down
3 changes: 2 additions & 1 deletion Indicators/Ema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IEnumerable<EmaResult> results = Indicator.GetEma(history, lookbackPeriod);

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least 2×`N` periods of `history`. Since this uses a smoothing technique, we recommend you use at least 250 data points prior to the intended usage date for maximum precision.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least 2×`N` periods of `history`. Since this uses a smoothing technique, we recommend you use at least 250 data points prior to the intended usage date for maximum precision.
| `lookbackPeriod` | int | Number of periods (`N`) in the moving average.

## Response
Expand All @@ -27,6 +27,7 @@ The first `N-1` periods will have `null` values since there's not enough data to

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Ema` | decimal | Exponential moving average for `N` lookback period

Expand Down
30 changes: 30 additions & 0 deletions Indicators/GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Guide and Pro Tips

## Quote

Historical quotes should be of consistent time frequency (e.g. per minute, hour, day, etc.).

| name | type | notes
| -- |-- |--
| `Date` | DateTime | Date
| `Open` | decimal | Open price
| `High` | decimal | High price
| `Low` | decimal | Low price
| `Close` | decimal | Close price
| `Volume` | long | Volume

There is also an `Index` property that is set internally, so do not set that value. We set this to `public` visibility in case you want to use it in your own wrapper code. See **Cleaning History** section below if you want to return the `Index` values.

## Cleaning History

If you intend to use the same composed `IEnumerable<Quote> history` in multiple calls and want to have the same `Index` values mapped into results, we recommend you pre-clean it to initialize those index values. This will add the `Index` value and sort by `Date` provided; it will also perform basic checks for data quality.

You only need to do this if you want to use the `Index` value in your own wrapper software; otherwise, there is no need as `history` is cleaned on every call, internally. If you pre-clean, the provided `history` will be used as-is without additional cleaning. The original `Date` and composed `Index` is always returned in resultsets.

``` C#
// fetch historical quotes from your favorite feed, in Quote format
IEnumerable<Quote> history = GetHistoryFromFeed("SPY");

// preclean
history = Cleaners.PrepareHistory(history);
```
15 changes: 8 additions & 7 deletions Indicators/HeikinAshi/HeikinAshi.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ namespace Skender.Stock.Indicators

public class HeikinAshiResult
{
public DateTime Date { get; internal set; }
public decimal Open { get; internal set; }
public decimal High { get; internal set; }
public decimal Low { get; internal set; }
public decimal Close { get; internal set; }
public bool IsBullish { get; internal set; }
public decimal Weakness { get; internal set; }
public int Index { get; set; }
public DateTime Date { get; set; }
public decimal Open { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Close { get; set; }
public bool IsBullish { get; set; }
public decimal Weakness { get; set; }
}

}
1 change: 1 addition & 0 deletions Indicators/HeikinAshi/HeikinAshi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public static IEnumerable<HeikinAshiResult> GetHeikinAshi(IEnumerable<Quote> his

HeikinAshiResult result = new HeikinAshiResult
{
Index = (int)h.Index,
Date = h.Date,
Open = open,
High = high,
Expand Down
3 changes: 2 additions & 1 deletion Indicators/HeikinAshi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ IEnumerable<HeikinAshiResult> results = Indicator.GetHeikinAshi(history);

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc).
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc).

## Response

Expand All @@ -25,6 +25,7 @@ The first period will have `null` values since there's not enough data to calcul

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Open` | decimal | Modified open price
| `High` | decimal | Modified high price
Expand Down
6 changes: 3 additions & 3 deletions Indicators/Indicators.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>netcoreapp2.2;netcoreapp3.1;netstandard2.0;netstandard2.1;net462;net472;net48</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>0.0.3-preview</Version>
<Version>0.0.4-preview</Version>
<Authors>Dave Skender</Authors>
<Company></Company>
<Product>Stock Indicators</Product>
Expand All @@ -15,8 +15,8 @@
<PackageId>Skender.Stock.Indicators</PackageId>
<PackageReleaseNotes>This software is currently in active pre-release development.</PackageReleaseNotes>
<AssemblyName>Stock.Indicators</AssemblyName>
<AssemblyVersion>0.0.3.0</AssemblyVersion>
<FileVersion>0.0.3.0</FileVersion>
<AssemblyVersion>0.0.4.0</AssemblyVersion>
<FileVersion>0.0.4.0</FileVersion>
<Copyright>@2020 Dave Skender</Copyright>
<RootNamespace>Skender.Stock.Indicators</RootNamespace>
<LangVersion>8.0</LangVersion>
Expand Down
13 changes: 7 additions & 6 deletions Indicators/Macd/Macd.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ namespace Skender.Stock.Indicators

public class MacdResult
{
public DateTime Date { get; internal set; }
public decimal? Macd { get; internal set; }
public decimal? Signal { get; internal set; }
public decimal? Histogram { get; internal set; }
public bool? IsBullish { get; internal set; }
public bool? IsDiverging { get; internal set; }
public int Index { get; set; }
public DateTime Date { get; set; }
public decimal? Macd { get; set; }
public decimal? Signal { get; set; }
public decimal? Histogram { get; set; }
public bool? IsBullish { get; set; }
public bool? IsDiverging { get; set; }
}

}
1 change: 1 addition & 0 deletions Indicators/Macd/Macd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static IEnumerable<MacdResult> GetMacd(IEnumerable<Quote> history, int fa

MacdResult result = new MacdResult
{
Index = (int)h.Index,
Date = h.Date
};

Expand Down
3 changes: 2 additions & 1 deletion Indicators/Macd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IEnumerable<MacdResult> results = Indicator.GetMacd(history, fastPeriod, slowPer

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least slow period + signal period worth of `history`. Since this uses a smoothing technique, we recommend you use at least 250 data points prior to the intended usage date for maximum precision.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least slow period + signal period worth of `history`. Since this uses a smoothing technique, we recommend you use at least 250 data points prior to the intended usage date for maximum precision.
| `fastPeriod` | int | Number of periods (`N`) for the faster moving average.
| `slowPeriod` | int | Number of periods (`N`) for the slower moving average.
| `signalPeriod` | int | Number of periods (`N`) for the moving average of MACD.
Expand All @@ -29,6 +29,7 @@ The first `N-1` slow periods + signal period will have `null` values since there

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Macd` | decimal | The MACD line is the difference between slow and fast moving averages
| `Signal` | decimal | Moving average of the MACD line
Expand Down
9 changes: 5 additions & 4 deletions Indicators/ParabolicSar/ParabolicSar.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ namespace Skender.Stock.Indicators

public class ParabolicSarResult
{
public DateTime Date { get; internal set; }
public decimal? Sar { get; internal set; }
public bool? IsReversal { get; internal set; }
public bool? IsBullish { get; internal set; }
public int Index { get; set; }
public DateTime Date { get; set; }
public decimal? Sar { get; set; }
public bool? IsReversal { get; set; }
public bool? IsRising { get; set; }
}

}
3 changes: 2 additions & 1 deletion Indicators/ParabolicSar/ParabolicSar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static IEnumerable<ParabolicSarResult> GetParabolicSar(
{
ParabolicSarResult result = new ParabolicSarResult
{
Index = (int)h.Index,
Date = h.Date
};

Expand Down Expand Up @@ -109,7 +110,7 @@ public static IEnumerable<ParabolicSarResult> GetParabolicSar(
}
}

result.IsBullish = isRising;
result.IsRising = isRising;
priorSar = (decimal)result.Sar;

results.Add(result);
Expand Down
5 changes: 3 additions & 2 deletions Indicators/ParabolicSar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IEnumerable<ParabolicSarResult> results = Indicator.GetParabolicSar(history, acc

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). Provide sufficient history to capture prior trend reversals, before your usage period.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). Provide sufficient history to capture prior trend reversals, before your usage period.
| `accelerationStep` | decimal | Incremental step size
| `maxAccelerationFactor` | decimal | Maximimum step limit

Expand All @@ -30,10 +30,11 @@ The first period will have `null` values since there's not enough data to calcul

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Sar` | decimal | Stop and Reverse value
| `IsReversal` | bool | Indicates a trend reversal
| `IsBullish` | bool | Rising (true), Falling (false)
| `IsRising` | bool | Rising (true), Falling (false)

## Example

Expand Down
3 changes: 2 additions & 1 deletion Indicators/Rsi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ IEnumerable<RsiResult> results = Indicator.GetRsi(history, lookbackPeriod);

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`. Since this uses a smoothing technique, we recommend you use at least 250 data points prior to the intended usage date for maximum precision.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`. Since this uses a smoothing technique, we recommend you use at least 250 data points prior to the intended usage date for maximum precision.
| `lookbackPeriod` | int | Number of periods (`N`) in the lookback period.

## Response
Expand All @@ -28,6 +28,7 @@ The first `N-1` periods will have `null` values since there's not enough data to

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Rsi` | float | RSI over prior `N` lookback periods
| `IsIncreasing` | bool | Direction since last period (e.g. up or down)
Expand Down
8 changes: 4 additions & 4 deletions Indicators/Rsi/Rsi.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ namespace Skender.Stock.Indicators

public class RsiResult
{
public DateTime Date { get; internal set; }
internal int Index { get; set; }
public int Index { get; set; }
public DateTime Date { get; set; }
internal float Gain { get; set; } = 0;
internal float Loss { get; set; } = 0;
public float? Rsi { get; internal set; }
public bool? IsIncreasing { get; internal set; }
public float? Rsi { get; set; }
public bool? IsIncreasing { get; set; }
}

}
2 changes: 1 addition & 1 deletion Indicators/Rsi/Rsi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public static IEnumerable<RsiResult> GetRsi(IEnumerable<Quote> history, int look

RsiResult result = new RsiResult
{
Date = h.Date,
Index = (int)h.Index,
Date = h.Date,
Gain = (lastClose < h.Close) ? (float)(h.Close - lastClose) : 0,
Loss = (lastClose > h.Close) ? (float)(lastClose - h.Close) : 0
};
Expand Down
3 changes: 2 additions & 1 deletion Indicators/Sma/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IEnumerable<SmaResult> results = Indicator.GetSma(history, lookbackPeriod);

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`.
| `lookbackPeriod` | int | Number of periods (`N`) in the moving average.

## Response
Expand All @@ -27,6 +27,7 @@ The first `N-1` periods will have `null` values since there's not enough data to

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Sma` | decimal | Simple moving average for `N` lookback periods

Expand Down
5 changes: 3 additions & 2 deletions Indicators/Sma/Sma.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ namespace Skender.Stock.Indicators

public class SmaResult
{
public DateTime Date { get; internal set; }
public decimal? Sma { get; internal set; }
public int Index { get; set; }
public DateTime Date { get; set; }
public decimal? Sma { get; set; }
}

}
1 change: 1 addition & 0 deletions Indicators/Sma/Sma.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static IEnumerable<SmaResult> GetSma(IEnumerable<Quote> history, int look

SmaResult result = new SmaResult
{
Index = (int)h.Index,
Date = h.Date
};

Expand Down
3 changes: 2 additions & 1 deletion Indicators/Stoch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IEnumerable<StochResult> results = Indicator.GetStoch(history, lookbackPeriod, s

| name | type | notes
| -- |-- |--
| `history` | IEnumerable\<[Quote](../../README.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`.
| `history` | IEnumerable\<[Quote](../GUIDE.md#Quote)\> | Historical Quotes data should be at any consistent frequency (day, hour, minute, etc). You must supply at least `N` periods of `history`.
| `lookbackPeriod` | int | Number of periods (`N`) in the lookback period to calculate the Oscillator (%K)
| `signalPeriod` | int | Lookback period for the signal (%D)
| `smoothingPeriod` | int | Smoothes the Oscillator (%K). "Slow" stochastic uses 3, "Fast" stochastic uses 1. You can specify as needed here.
Expand All @@ -29,6 +29,7 @@ The first `N-1` periods will have `null` values since there's not enough data to

| name | type | notes
| -- |-- |--
| `Index` | int | Sequence of dates
| `Date` | DateTime | Date
| `Oscillator` | float | Oscillator over prior `N` lookback periods
| `Signal` | float | Simple moving average of Oscillator
Expand Down
Loading

0 comments on commit cd444ef

Please sign in to comment.