-
Notifications
You must be signed in to change notification settings - Fork 250
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
10 changed files
with
694 additions
and
8 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,20 @@ | ||
using System; | ||
|
||
namespace Skender.Stock.Indicators | ||
{ | ||
|
||
public class CorrResult | ||
{ | ||
public int Index { get; set; } | ||
public DateTime Date { get; set; } | ||
public decimal? Correlation { get; set; } | ||
|
||
// internal use only | ||
internal decimal PriceA { get; set; } | ||
internal decimal PriceB { get; set; } | ||
internal decimal PriceA2 => PriceA * PriceA; | ||
internal decimal PriceB2 => PriceB * PriceB; | ||
internal decimal PriceAB => PriceA * PriceB; | ||
} | ||
|
||
} |
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,63 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Skender.Stock.Indicators | ||
{ | ||
public static partial class Indicator | ||
{ | ||
// CORRELATION (e.g. BETA when used with Indices) | ||
public static IEnumerable<CorrResult> GetCorrelation(IEnumerable<Quote> historyA, IEnumerable<Quote> historyB, int lookbackPeriod) | ||
{ | ||
// clean quotes | ||
historyA = Cleaners.PrepareHistory(historyA); | ||
historyB = Cleaners.PrepareHistory(historyB); | ||
|
||
// initialize results | ||
List<CorrResult> results = new List<CorrResult>(); | ||
|
||
|
||
// roll through history for interim data | ||
foreach (Quote a in historyA) | ||
{ | ||
Quote b = historyB.Where(x => x.Date == a.Date).FirstOrDefault(); | ||
if (b == null) | ||
{ | ||
throw new BadHistoryException("Correlation requires matching dates in provided histories. {0} not found in historyB."); | ||
} | ||
|
||
CorrResult result = new CorrResult | ||
{ | ||
Index = (int)a.Index, | ||
Date = a.Date, | ||
PriceA = a.Close, | ||
PriceB = b.Close | ||
// other values calculated in class properties | ||
}; | ||
results.Add(result); | ||
} | ||
|
||
// compute correlation | ||
foreach (CorrResult r in results.Where(x => x.Index >= lookbackPeriod)) | ||
{ | ||
IEnumerable<CorrResult> period = results.Where(x => x.Index > (r.Index - lookbackPeriod) && x.Index <= r.Index); | ||
|
||
decimal avgA = period.Select(x => x.PriceA).Average(); | ||
decimal avgB = period.Select(x => x.PriceB).Average(); | ||
decimal avgA2 = period.Select(x => x.PriceA2).Average(); | ||
decimal avgB2 = period.Select(x => x.PriceB2).Average(); | ||
decimal avgAB = period.Select(x => x.PriceAB).Average(); | ||
|
||
decimal varianceA = avgA2 - avgA * avgA; | ||
decimal varianceB = avgB2 - avgB * avgB; | ||
decimal covariance = avgAB - avgA * avgB; | ||
|
||
r.Correlation = covariance / (decimal)Math.Sqrt((double)(varianceA * varianceB)); | ||
} | ||
|
||
return results; | ||
} | ||
|
||
} | ||
|
||
} |
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,53 @@ | ||
# Correlation Coefficient (e.g Beta) | ||
|
||
Correlation between two quote histories, based on Close price. This is `Beta` if one history represents the overall market. | ||
[More info ...](https://school.stockcharts.com/doku.php?id=technical_indicators:correlation_coeffici) | ||
|
||
``` C# | ||
// usage | ||
IEnumerable<CorrResult> results = Indicator.GetCorr(history, lookbackPeriod); | ||
``` | ||
|
||
## Parameters | ||
|
||
| name | type | notes | ||
| -- |-- |-- | ||
| `historyA` | 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`. The `A` history will be used to establish result length, so use the shorter history here. | ||
| `historyB` | 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`. Must at least the same date elements of `historyA`. Exception will be thrown if not matched. | ||
| `lookbackPeriod` | int | Number of periods (`N`) in the lookback period. | ||
|
||
## Response | ||
|
||
``` C# | ||
IEnumerable<CorrResult> | ||
``` | ||
|
||
The first `N-1` periods will have `null` values since there's not enough data to calculate. We always return the same number of elements as there are in the historical quotes. | ||
|
||
### CorrResult | ||
|
||
| name | type | notes | ||
| -- |-- |-- | ||
| `Index` | int | Sequence of dates | ||
| `Date` | DateTime | Date | ||
| `Corr` | decimal | Correlation based on `N` lookback periods | ||
|
||
## Example | ||
|
||
``` C# | ||
// fetch historical quotes from your favorite feed, in Quote format | ||
IEnumerable<Quote> historyTSLA = GetHistoryFromFeed("TSLA"); | ||
IEnumerable<Quote> historySPX = GetHistoryFromFeed("SPX"); | ||
|
||
// calculate 20-period Correlation | ||
IEnumerable<CorrResult> results = Indicator.GetCorr(historySPX,historyTSLA,20); | ||
|
||
// use results as needed | ||
DateTime evalDate = DateTime.Parse("12/31/2018"); | ||
CorrResult result = results.Where(x=>x.Date==evalDate).FirstOrDefault(); | ||
Console.WriteLine("CORR(SPX,TSLA,20) on {0} was ${1}", result.Date, result.Corr); | ||
``` | ||
|
||
``` text | ||
CORR(SPX,TSLA,20) on 12/31/2018 was 0.85 | ||
``` |
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
Oops, something went wrong.