Skip to content

Commit

Permalink
refactor: abstract stream types, use record struct types (incomplete)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveSkender committed Jun 22, 2024
1 parent a8fa2e2 commit 6c8b30c
Show file tree
Hide file tree
Showing 208 changed files with 2,257 additions and 3,094 deletions.
16 changes: 1 addition & 15 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,9 @@ max_line_length = 150
trim_trailing_whitespace = true
insert_final_newline = true

[*.{csproj,props,targets}]
indent_style = space
indent_size = 2

[*.yml]
indent_style = space
indent_size = 2

[*.{cs,vb}]
tab_width = 4
indent_size = 4
end_of_line = lf

#### Naming styles ####

Expand Down Expand Up @@ -70,11 +61,6 @@ dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_code_quality_unused_parameters = all:suggestion

dotnet_sort_system_directives_first = true
Expand All @@ -87,7 +73,7 @@ dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_prefer_collection_expression = true:suggestion
dotnet_style_prefer_collection_expression = false:suggestion

[*.cs]
# ref: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/csharp-formatting-options
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ IEnumerable<SmaResult> results = quotes.GetSma(20);
// find result on a specific date
DateTime lookupDate = [..] // the date you want to find
SmaResult result = results.Find(lookupDate);

// throws 'InvalidOperationException' when not found
```

### Remove warmup periods
Expand Down
43 changes: 24 additions & 19 deletions src/_common/Candles/Candles.Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,39 @@ namespace Skender.Stock.Indicators;

// CANDLESTICK MODELS

public record CandleProperties : Quote
public record struct CandleProperties : IQuote, IReusableResult
{
// base quote properties
public DateTime Timestamp { get; set; }
public decimal Open { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Close { get; set; }
public decimal Volume { get; set; }

readonly double IReusableResult.Value
=> (double)Close;

// raw sizes
public decimal? Size => High - Low;
public decimal? Body => (Open > Close) ? (Open - Close) : (Close - Open);
public decimal? UpperWick => High - (Open > Close ? Open : Close);
public decimal? LowerWick => (Open > Close ? Close : Open) - Low;
public readonly decimal? Size => High - Low;
public readonly decimal? Body => (Open > Close) ? (Open - Close) : (Close - Open);
public readonly decimal? UpperWick => High - (Open > Close ? Open : Close);
public readonly decimal? LowerWick => (Open > Close ? Close : Open) - Low;

// percent sizes
public double? BodyPct => (Size != 0) ? (double?)(Body / Size) : 1;
public double? UpperWickPct => (Size != 0) ? (double?)(UpperWick / Size) : 1;
public double? LowerWickPct => (Size != 0) ? (double?)(LowerWick / Size) : 1;
public readonly double? BodyPct => (Size != 0) ? (double?)(Body / Size) : 1;
public readonly double? UpperWickPct => (Size != 0) ? (double?)(UpperWick / Size) : 1;
public readonly double? LowerWickPct => (Size != 0) ? (double?)(LowerWick / Size) : 1;

// directional info
public bool IsBullish => Close > Open;
public bool IsBearish => Close < Open;
public readonly bool IsBullish => Close > Open;
public readonly bool IsBearish => Close < Open;
}

public record class CandleResult : IResult
public record struct CandleResult : IResult
{
public CandleResult(DateTime date, Match match)
{
Timestamp = date;
Match = match;
}

public DateTime Timestamp { get; private set; }
public DateTime Timestamp { get; set; }
public decimal? Price { get; set; }
public Match Match { get; set; }
public CandleProperties Candle { get; set; } = new CandleProperties();
public CandleProperties Candle { get; set; }
}
34 changes: 9 additions & 25 deletions src/_common/Candles/Candles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,20 @@ public static CandleProperties ToCandle<TQuote>(
// convert/sort quotes into candles list
public static IEnumerable<CandleProperties> ToCandles<TQuote>(
this IEnumerable<TQuote> quotes)
where TQuote : IQuote
{
List<CandleProperties> candlesList =
[
.. quotes
where TQuote : IQuote => quotes
.Select(x => x.ToCandle())
.OrderBy(x => x.Timestamp)
];

// validate
return candlesList;
}
.ToList();

// convert/sort quotes into candle results
internal static List<CandleResult> ToCandleResults<TQuote>(
this IEnumerable<TQuote> quotes)
where TQuote : IQuote
{
List<CandleResult> candlesList =
[
.. quotes
.Select(x => new CandleResult(
x.Timestamp,
Match.None) {
Candle = x.ToCandle()
where TQuote : IQuote => quotes
.Select(q => new CandleResult() {
Timestamp = q.Timestamp,
Match = Match.None,
Candle = q.ToCandle()
})
.OrderBy(x => x.Timestamp)
];

// validate
return candlesList;
}
.OrderBy(c => c.Timestamp)
.ToList();
}
19 changes: 19 additions & 0 deletions src/_common/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ namespace Skender.Stock.Indicators;
// SHARED ENUMERATIONS
// note: indicator unique ENUMS specified in indicator models

/// <summary>
/// Part or value of a quote candle
/// </summary>
public enum CandlePart
{
Open,
Expand All @@ -17,12 +20,18 @@ public enum CandlePart
OHLC4
}

/// <summary>
/// Candle close or high/low wick values
/// </summary>
public enum EndType
{
Close = 0,
HighLow = 1
}

/// <summary>
/// Candlestick pattern matching type
/// </summary>
public enum Match
{
BullConfirmed = 200,
Expand All @@ -35,6 +44,9 @@ public enum Match
BearConfirmed = -200
}

/// <summary>
/// Moving average type
/// </summary>
public enum MaType
{
ALMA,
Expand All @@ -50,6 +62,10 @@ public enum MaType
WMA
}

/// <summary>
/// Period size. Usually referring to the
/// time period represented in a quote candle.
/// </summary>
public enum PeriodSize
{
Month,
Expand All @@ -66,6 +82,9 @@ public enum PeriodSize
OneMinute
}

/// <summary>
/// The action taken on the cache (outcome)
/// </summary>
public enum Act
{
AddNew,
Expand Down
File renamed without changes.
21 changes: 16 additions & 5 deletions src/_common/Generics/Seek.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,29 @@ namespace Skender.Stock.Indicators;
public static class Seeking
{
// FIND SERIES by DATE
/// <include file='./info.xml' path='info/type[@name="FindSeries"]/*' />
///
/// <summary> Finds time series values on a specific date.
/// <para>
/// See <see href="https://dotnet.StockIndicators.dev/utilities/#find-indicator-result-by-date?utm_source=library&amp;utm_medium=inline-help&amp;utm_campaign=embedded">documentation</see> for more information.
/// </para>
/// </summary>
/// <typeparam name="TSeries">Any series type.</typeparam>
/// <param name="series">Time series to evaluate.</param>
/// <param name="lookupDate">Exact date to lookup.</param>
/// <returns>First record in the series on the date specified.</returns>
/// <exception cref="InvalidOperationException">
/// Sequence contains no matching element
/// </exception>
public static TSeries? Find<TSeries>(
this IEnumerable<TSeries> series,
DateTime lookupDate)
where TSeries : ISeries => series
.FirstOrDefault(x => x.Timestamp == lookupDate);
.First(x => x.Timestamp == lookupDate);

// TODO: add TryFind(), like TryParse() since struct won't allow null return types.
// May just use this (above) with a try/catch and `bool` primary return type.

// FIND INDEX by DATE
/// <include file='./info.xml' path='info/type[@name="FindIndex"]/*' />
///
public static int FindIndex<TSeries>(
this List<TSeries> series,
DateTime lookupDate)
Expand All @@ -25,7 +37,6 @@ public static int FindIndex<TSeries>(

// FIND INDEX by DATE
/// <include file='./info.xml' path='info/type[@name="FindIndexChain"]/*' />
///
public static int FindIndex(
this List<(DateTime Timestamp, double Value)> tuple,
DateTime lookupDate)
Expand Down
14 changes: 1 addition & 13 deletions src/_common/Generics/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@

<info>

<type name="FindSeries">
<summary> Finds time series values on a specific date.
<para>
See <see href="https://dotnet.StockIndicators.dev/utilities/#find-indicator-result-by-date?utm_source=library&amp;utm_medium=inline-help&amp;utm_campaign=embedded">documentation</see> for more information.
</para>
</summary>
<typeparam name="TSeries">Any series type.</typeparam>
<param name="series">Time series to evaluate.</param>
<param name="lookupDate">Exact date to lookup.</param>
<returns>First record in the series on the date specified.</returns>
</type>

<type name="FindIndex">
<summary>
Finds time series index on a specific date.
Expand Down Expand Up @@ -53,4 +41,4 @@
<exception cref="ArgumentOutOfRangeException">Invalid parameter value provided.</exception>
</type>

</info>
</info>
Loading

0 comments on commit 6c8b30c

Please sign in to comment.