Giter VIP home page Giter VIP logo

ooples / ooplesfinance.stockindicators Goto Github PK

View Code? Open in Web Editor NEW
185.0 12.0 48.0 2.16 MB

Largest C# stock indicator library with over 750 to choose from and easiest to use with abilities such as making an indicator out of any other indicator or using any moving average with any indicator.

License: Apache License 2.0

C# 100.00%
indicator stock finance technical-analysis technical-indicators indicators backtesting nuget nuget-package stock-analysis

ooplesfinance.stockindicators's Introduction

Nuget Nuget (with prereleases) GitHub

.Net Stock Indicator Library

This is a stock indicator library that is completely open source (Apache 2.0 license) and very easy to use. Current version contains 763 stock indicators and I will add more as I get requests for them!

How to use this library

Here is an example to show how easy it is to create indicators using other indicators

var stockData = new StockData(openPrices, highPrices, lowPrices, closePrices, volumes);
var results = stockData.CalculateRelativeStrengthIndex().CalculateMovingAverageConvergenceDivergence();

Here is a simple example calculating default bollinger bands to get you started using the Alpaca C# Api

using Alpaca.Markets;
using OoplesFinance.StockIndicators.Models;
using static OoplesFinance.StockIndicators.Calculations;

const string paperApiKey = "REPLACEME";
const string paperApiSecret = "REPLACEME";
const string symbol = "AAPL";
var startDate = new DateTime(2021, 01, 01);
var endDate = new DateTime(2021, 12, 31);

var client = Environments.Paper.GetAlpacaDataClient(new SecretKey(paperApiKey, paperApiSecret));
var bars = (await client.ListHistoricalBarsAsync(new HistoricalBarsRequest(symbol, startDate, endDate, BarTimeFrame.Day)).ConfigureAwait(false)).Items;
var stockData = new StockData(bars.Select(x => x.Open), bars.Select(x => x.High), bars.Select(x => x.Low), bars.Select(x => x.Close), bars.Select(x => x.Volume), bars.Select(x => x.TimeUtc));

var results = stockData.CalculateBollingerBands();
var upperBandList = results.OutputValues["UpperBand"];
var middleBandList = results.OutputValues["MiddleBand"];
var lowerBandList = results.OutputValues["LowerBand"];

Here is a more advanced example showing how to calculate bollinger bands with full customization and using a custom input of high rather than the default close

var stockData = new StockData(bars.Select(x => x.Open), bars.Select(x => x.High), bars.Select(x => x.Low), 
bars.Select(x => x.Close), bars.Select(x => x.Volume), bars.Select(x => x.TimeUtc), InputName.High);

var results = stockData.CalculateBollingerBands(MovingAvgType.EhlersMesaAdaptiveMovingAverage, 15, 2.5m);
var upperBandList = results.OutputValues["UpperBand"];
var middleBandList = results.OutputValues["MiddleBand"];
var lowerBandList = results.OutputValues["LowerBand"];

It is extremely important to remember that if you use the same data source to calculate different indicators without using the chaining method then you need to clear the data in between each call. We have a great example for this below:

var stockData = new StockData(bars.Select(x => x.Open), bars.Select(x => x.High), bars.Select(x => x.Low), 
bars.Select(x => x.Close), bars.Select(x => x.Volume), bars.Select(x => x.TimeUtc), InputName.High);

var sma = stockData.CalculateSimpleMovingAverage(14);

// if you don't perform this clear method in between then your ema result will be calculated using the sma results
stockData.Clear();

var ema = stockData.CalculateExponentialMovingAverage(14);

For more detailed Alpaca examples then check out my more advanced Alpaca example code

Support This Project

BTC: 36DRmZefJNW82q9pHY1kWYSZhLUWQkpgGq

ETH: 0x7D6e58754476189ffF736B63b6159D2647f74f34

USDC: 0x587Ae0709f45b970992bdD772bF693141D95CAED

DOGE: DF1nsK1nLASzmwHNAfNengBGS4w7bNyJ1e

SHIB: 0xCDe2355212764218355c9393FbE121Ae49B43382

Paypal: https://www.paypal.me/cheatcountry

Patreon: https://patreon.com/cheatcountry

Support or Contact

Email me at [email protected] for any help or support or to let me know of ways to further improve this library.

ooplesfinance.stockindicators's People

Contributors

dependabot[bot] avatar olegra avatar ooples avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ooplesfinance.stockindicators's Issues

Keltner channel calculation appears to differ significantly from Trading View for the same input

While testing I noticed a significant difference in the Keltner Channel calculation that is produced by this library when compared to what I see displayed in Trading View using what appears to be the same input and was hoping to get some clarity on why that may be.

An example of this is AAPL on 2023-01-27. The Keltner upper band in Trading View is 144.91. The Keltner Channel Upper Band produced by this library is 152.8937. The default inputs used by the CalculateKeltnerChannels method seems to the same as the input used in Trading View.

Please let me know if you need any more info.

image

Suggestions for possible improvements

Hi Franklin,

Thank you for this collection of indicators!
Here are some suggestions which you may decide to apply:

  1. Design each indicator as a simple function
    This kind of design should be considered because of multiple reasons:
  • Imagine having an infinite stream of data, this will allow to save memory and maybe even increase performance.
  • Having simple functions allows composition
  • Having simple functions allows easy testing and rewriting to different language.
    Please let me give you quick example of simple SMA in Java that covers all three points above:
public static class SMA implements Function<BigDecimal, BigDecimal> { 
   private final var buffer = new LinkedList<>()
   private final int length
   private var sum = BigDecimal.ZERO

   SMA(int length) {
     this.length = length
   }

   @Override
   BigDecimal apply(BigDecimal currentValue) {
        if (buffer.size() == length) {
            sum -= buffer.removeFirst()
         }
        sum += currentValue
        buffer.addLast(currentValue)
        // at the end calculated SMA should be rounded to SOURCE scale
        return roundValue(sum / buffer.size(), currentValue)
  }
}

So it is basically a function, that accepts decimal value and produces new one. It has some minimal internal state like a self buffer etc. Usage is quite simple, it can be applied now to any datasource, streaming or not. RSI from SMA will look like this:

var datasource = candlesticks.map(c -> c.close)
     .map(new SMA(3).then(new RSI(14)))

I think you may improve your code in this way if you agree.
2. Rounding of values is a problem now. You used 4 decimals by default in any calculation, but I think this is not correct.
Whenever you know the scale you should use it. For example any moving average should use scale of original sourced value. RSI should/may use just 2 decimals. SMA from RSI should have the same 2 decimals for calculated value.
3. I tried to use some cryptocurrency candlestick data and many indicators failed to generate any useful data, I even couldnt find simple signal for RSI with StrongSell/StrongBuy values, which is weird.

The most important part is point with number 1, I do not have much experience with C# to help you with that. Please let me know what do you think.

New Indicator Suggestion: Market Meanness Index

Request to add this very interesting volatility index, based on a fundamental principle of statistics.

The author is a seasoned pro trader and claims it beats most other trend indicators in backtesting.

Only requires half-a-dozen lines of straightforward code. Would do it myself, but new to both C# and Git so a pull request would be a bit of a learning curve. If you can manage to add this in the midst of your new parenthood it would be appreciated!

Explanation here, along with code in C:

https://financial-hacker.com/the-market-meanness-index/

Thanks for all your hard work producing this comprehensive library!

StackOverflowException in new release 1.0.37

If you run the following code on any data:

stockData.CalculateRelativeStrengthIndex();

There will be an StackOverflowException. I tracked it down to the following lines:

    /// <summary>
    /// Adds the rounded.
    /// </summary>
    /// <param name="list">The list.</param>
    /// <param name="value">The value.</param>
    public static void AddRounded(this List<decimal> list, decimal value)
    {
        list.AddRounded(Math.Round(value, 4));
    }

This must be:

    /// <summary>
    /// Adds the rounded.
    /// </summary>
    /// <param name="list">The list.</param>
    /// <param name="value">The value.</param>
    public static void AddRounded(this List<decimal> list, decimal value)
    {
        list.Add(Math.Round(value, 4));
    }

Missing includes in OoplesFinance.StockIndicators.csproj

OoplesFinance.StockIndicators.csproj contains references to a missing Images folder, reference to C:\Users\cheat\Downloads\Favicon.jpg and <PackageIcon>Favicon.jpg</PackageIcon>. After removing these I could get it to build. Overall StockIndicators.csproj could use some cleaning up.

This is really an impressive project BTW! Where do the indicator implementations come from? Did you write all 510 of them by hand?

License?

Can't find any mention of the open source license anywhere.
Sorry if I missed it.

System.InvalidOperationException: 'Sequence contains no elements'

Hello!

I wanted to try out this awesome library. Testing the first indicator, Bollinger Bands like this i get the following error:

System.InvalidOperationException: 'Sequence contains no elements'

Stacktrace:

   at System.Linq.ThrowHelper.ThrowNoElementsException()
   at System.Linq.Enumerable.Average(IEnumerable`1 source)
   at OoplesFinance.StockIndicators.Calculations.CalculateSimpleMovingAverage(StockData stockData, Int32 length)
   at OoplesFinance.StockIndicators.Helpers.CalculationsHelper.GetMovingAverageList(StockData stockData, MovingAvgType movingAvgType, Int32 length, List`1 customValuesList)
   at OoplesFinance.StockIndicators.Calculations.CalculateBollingerBands(StockData stockData, MovingAvgType maType, Int32 length, Decimal stdDevMult)
   at OoplesFinance.StockIndicators.Calculations.CalculateBollingerBands(StockData stockData)
   at antihodl2core.LearnDataGenerator.SkenderMinutes.Run() in F:\src\antihodl2\antihodl2core\LearnDataGenerator\SkenderMinutes.cs:line 104
   at antihodl2core.Form1.<learningDataGenerator_Click>d__7.MoveNext() in F:\src\antihodl2\antihodl2core\Form1.cs:line 69

Not sure what could be missing here.

image

image

Supertrend returning same values

Hi.
Thank you for this great library.

I'm trying to use your library in my project and I installed using nuget.

I'm trying to calculate the Supertrend indicator but it's returning all same values - all items in the OutputList contains same values)
Can you please provide sample code to calculate the Supertrend indicator?

Here's my code snippet:

StockData stockData = new StockData(quotes.Select(x => x.ToTickerData()));
var st = stockData.CalculateSuperTrend(maType: MovingAvgType.ExponentialMovingAverage, length: 10, atrMult: 3.0);

CalculateNegativeVolumeIndex, CalculatePositiveVolumeIndex alwas return array of zeros

double nvi = currentVolume >= prevVolume ? prevNvi : prevNvi + (prevNvi * pctChg);

The problem is here:

double prevNvi = nviList.LastOrDefault();
double nvi = currentVolume >= prevVolume ? prevNvi : prevNvi + (prevNvi * pctChg);
nviList.AddRounded(nvi);

because prevNvi is initialized as 0 and therefore nvi also assigned 0 and on next iteration prevNvi again assigned 0 and so on.
solution: prevNvi should never be assigned 0.

CalculateInsyncIndex throws the following exception

Greetings Franklin,

This code

var bars = stockHistoryDaily[@"RELIANCE"];
var stockData = new StockData(bars.Select(x => x.Open), bars.Select(x => x.High), bars.Select(x => x.Low), bars.Select(x => x.Close), bars.Select(x => x.Volume), bars.Select(x => x.DateTime));
var insyncResults = stockData.CalculateInsyncIndex();
var insyncIndex = insyncResults.OutputValues["Iidx"];

produces this exception

OoplesFinance.StockIndicators.Exceptions.CalculationException: Calculations based off of BollingerBands can't be completed because this indicator doesn't have a single output.
   at OoplesFinance.StockIndicators.Helpers.CalculationsHelper.GetInputValuesList(StockData stockData)
   at OoplesFinance.StockIndicators.Calculations.CalculateDetrendedPriceOscillator(StockData stockData, MovingAvgType maType, Int32 length)
   at OoplesFinance.StockIndicators.Calculations.CalculateInsyncIndex(StockData stockData, MovingAvgType maType, Int32 fastLength, Int32 slowLength, Int32 signalLength, Int32 emoLength, Int32 mfiLength, Int32 bbLength, Int32 cciLength, Int32 dpoLength, Int32 rocLength, Int32 rsiLength, Int32 stochLength, Int32 stochKLength, Int32 stochDLength, Int32 smaLength, Double stdDevMult, Double divisor)
   at Program.<Main>$(String[] args) in 

in method CalculateDetrendedPriceOscillator at line CalculationsHelper.GetInputValuesList(stockData).inputList;

      this StockData stockData,
      MovingAvgType maType = MovingAvgType.SimpleMovingAverage,
      int length = 20)
    {
      List<double> doubleList = new List<double>();
      List<Signal> signalList = new List<Signal>();
      List<double> inputList = CalculationsHelper.GetInputValuesList(stockData).inputList;
      int num1 = MathHelper.MinOrMax(checked ((int) Math.Ceiling(unchecked ((double) length / 2.0 + 1.0))));
      List<double> movingAverageList = CalculationsHelper.GetMovingAverageList(stockData, maType, length, inputList);
      int index = 0;

It is called by this code

      List<double> customValuesList5 = stockData1.CalculateBollingerBands(length: length, stdDevMult: stdDevMult1).CustomValuesList;
      List<double> customValuesList6 = stockData.CalculateDetrendedPriceOscillator(length: dpoLength).CustomValuesList;
      List<double> customValuesList7 = stockData.CalculateRateOfChange(rocLength).CustomValuesList;

I am trying out your excellent humongous library. :-)

New Indicator : TDI

Hello,

Firstly, thanks for your big Indicator Collection :)

Is there a way you can add TDI ( Traders Dynamic Index ) to your lib?

TDI is a combination of the RSI, BA and MA.

Example From Tradingview > https://www.tradingview.com/script/9Ltwsixb-TDI-Traders-Dynamic-Index-Goldminds/

//
// @author LazyBear
// If you use this code in its orignal/modified form, do drop me a note. 
// 
// Modified by Bromley

study("TDI - Traders Dynamic Index [Goldminds]", shorttitle="TDIGM")

rsiPeriod = input(11, minval = 1, title = "RSI Period")
bandLength = input(31, minval = 1, title = "Band Length")
lengthrsipl = input(1, minval = 0, title = "Fast MA on RSI")
lengthtradesl = input(9, minval = 1, title = "Slow MA on RSI")

src = close                                                             // Source of Calculations (Close of Bar)
r = rsi(src, rsiPeriod)                                                 // RSI of Close
ma = sma(r, bandLength)                                                 // Moving Average of RSI [current]
offs = (1.6185 * stdev(r, bandLength))                                  // Offset
up = ma + offs                                                          // Upper Bands
dn = ma - offs                                                          // Lower Bands
mid = (up + dn) / 2                                                     // Average of Upper and Lower Bands
fastMA = sma(r, lengthrsipl)                                            // Moving Average of RSI 2 bars back
slowMA = sma(r, lengthtradesl)                                          // Moving Average of RSI 7 bars back

hline(30)                                                               // Oversold
hline(50)                                                               // Midline
hline(70)                                                               // Overbought

upl = plot(up, "Upper Band", color = blue)                              // Upper Band
dnl = plot(dn, "Lower Band", color = blue)                              // Lower Band
midl = plot(mid, "Middle of Bands", color = orange, linewidth = 2)      // Middle of Bands

plot(slowMA, "Slow MA", color=green, linewidth=2)                       // Plot Slow MA
plot(fastMA, "Fast MA", color=red, linewidth=2)                         // Plot Fast MA

fill(upl, midl, red, transp=90)                                         // Fill Upper Half Red
fill(midl, dnl, green, transp=90)                                       // Fill Lower Half Green

Rsi calculation wrong?

Hello,

If i use this:

        var rsi = stockData.CalculateRelativeStrengthIndex();

The result are always strange, i only get these numbers: 100 + 50 (60% only 50) and a range from 30 to 50, but nothing between 50.01 to 99.99 and 0 to 29.99, why?

Input parameters for SqueezeMomentumIndicator

First of all, thank you for this great library :)

I'm considering using SqueezeMomentumIndicator in your library.

In the LazyBear's implementation, there are some input parameters to calculate Bollinger Bands and Keltner Channels,
but your implementation is missing those parameters.

Are those parameters not relevant to the output of the indicator?

I really appreciate any advise you can provide.

calculating indicators on the same data set

I would like to be able to create X number of indicators on the same input data. As per documentation I am using the recomended approach by invoking stockData.Clear();, however, this method seems to be cleaning up the values of the previous outputted collection in some cases (bug?).

Consider following example:

            var results = stockData.CalculateBollingerBands();
            var line2 = results.OutputValues["UpperBand"];
            var line3 = results.OutputValues["MiddleBand"];
            var line4 = results.OutputValues["LowerBand"];

            stockData.Clear();
            var results2 = stockData.CalculateMovingAverageV3();
            var line5 = results2.OutputValues["Mav3"];

            stockData.Clear();
            var results3 = stockData.CalculateSimpleMovingAverage();
            var line6 = results3.OutputValues["Sma"];

            stockData.Clear();
  • upon invoke of stockData.Clear(); on the BollingerBands results - the values in collection line2 , line3, line4 are not being cleaned up
  • upon invoke of the method 2nd and 3rd times - both the line5 and line6 are affected by the cleaned up as well..

Why the results of the BollingerBands calculation are not being cleaned, while the rest are?

I do think that there is some kind of bug there, since the behavior is expected to be the same for all scenarios.. Proof:

Video002.mp4

I would like to be able to calculate multiple indicators on the same data set. If the behavior is intended, then how to achieve my goal? (Cloning the resulting list seems to be the temporary solution)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.