Home > OS >  How can I fill the IEnumerable class of skender.stock.indicators?
How can I fill the IEnumerable class of skender.stock.indicators?

Time:10-08

I have this DataTable:

index date open high low close volume
1 01/03/17 $212.61 $213.35 $211.52 $212.80 96,708,880
2 01/04/17 $213.16 $214.22 $213.15 $214.06 83,348,752
3 01/05/17 $213.77 $214.06 $213.02 $213.89 82,961,968

I'm trying to use the Skender.stocks library

https://daveskender.github.io/Stock.Indicators/guide/

The sample in the page only says:

IEnumerable<Quote> quotes = Mycustomfunction();

How can I use a DataTable in a function or cast to return a IEnumerable<Quote>?

CodePudding user response:

You will need to:

  1. Iterate over the DataTable rows
  2. Create a new instance of a Quote
  3. Input the values from the row into the respective property
  4. Add the Quote to a List(Of Quote)

The list would be your IEnumerable from that point.

Here is an example:

Dim quotes As New List(Of Quote)()
For Each row As DataRow In MyDataTable.Rows
    quotes.Add(New Quote() With {
        .Date = Convert.ToDateTime(row.Item("Date")),
        .Open = Convert.ToDecimal(row.Item("Open")),
        .High = Convert.ToDecimal(row.Item("High")),
        .Low = Convert.ToDecimal(row.Item("Low")),
        .Close = Convert.ToDecimal(row.Item("Close")),
        .Volume = Convert.ToDecimal(row.Item("Volume"))
    })
Next

Live Demo: https://dotnetfiddle.net/LgguWG

This is a quick and dirty method if you know that each row will have a value for every column and every column can be converted to its respective data type.

If you wanted to refine it a bit more, you could setup conditional statements attempting to convert the values prior to setting the property of the Quote being added to the collection.

CodePudding user response:

An option is to derive your own Quote class and add a constructor which gets its property values from a DataRow

private class MyQuote : Quote
{
    public MyQuote(DataRow dr)
    {
        this.Date = (DateTime)dr["date"];
        this.Open = (decimal)dr["open"];
        this.High = (decimal)dr["high"];
        this.Low = (decimal)dr["low"];
        this.Close = (decimal)dr["close"];
        this.Volume = (decimal)dr["volume"];
    }
}

or implementing the Interface

private class MyQuote : IQuote
{
    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 decimal Volume { get; set; }
    public MyQuote(DataRow dr)
    {
        this.Date = (DateTime)dr["date"];
        this.Open = (decimal)dr["open"];
        this.High = (decimal)dr["high"];
        this.Low = (decimal)dr["low"];
        this.Close = (decimal)dr["close"];
        this.Volume = (decimal)dr["volume"];
    }
}

Then you can use some LINQ to get it from the DataTable (same for derived class and interface)

var quotes = dt.Select().Select(r => new MyQuote(r));

CodePudding user response:

Many, many thanks to David!!, the complete code in c # for if someone else needs it is like this:

Populate the datatable....

using Skender.Stock.Indicators;




void makedt ()
    {
        dt = new DataTable();
        dt.Clear();
        dt.Columns.Add("Date");
        dt.Columns.Add("Open");
        dt.Columns.Add("High");
        dt.Columns.Add("Low");
        dt.Columns.Add("Close");
        dt.Columns.Add("Volume");

        DataRow _ravi = dt.NewRow();
        _ravi["Date"] = DateTime.Now;
        _ravi["Open"] = "500";
        _ravi["High"] = "500";
        _ravi["Low"] = "500";
        _ravi["Close"] = "500";
        _ravi["Volume"] = "500";
        dt.Rows.Add(_ravi);
        //_ravi.Delete();

        _ravi = dt.NewRow();
        _ravi["Date"] = DateTime.Now;
        _ravi["Open"] = "600";
        _ravi["High"] = "600";
        _ravi["Low"] = "600";
        _ravi["Close"] = "600";
        _ravi["Volume"] = "600";
        dt.Rows.Add(_ravi);
        //_ravi.Delete();

        _ravi = dt.NewRow();
        _ravi["Date"] = DateTime.Now;
        _ravi["Open"] = "700";
        _ravi["High"] = "700";
        _ravi["Low"] = "700";
        _ravi["Close"] = "700";
        _ravi["Volume"] = "700";
        dt.Rows.Add(_ravi);
        //_ravi.Delete();

        _ravi = dt.NewRow();
        _ravi["Date"] = DateTime.Now;
        _ravi["Open"] = "800";
        _ravi["High"] = "800";
        _ravi["Low"] = "800";
        _ravi["Close"] = "800";
        _ravi["Volume"] = "800";
        dt.Rows.Add(_ravi);
        //_ravi.Delete();

        _ravi = dt.NewRow();
        _ravi["Date"] = DateTime.Now;
        _ravi["Open"] = "900";
        _ravi["High"] = "900";
        _ravi["Low"] = "900";
        _ravi["Close"] = "900";
        _ravi["Volume"] = "900";
        dt.Rows.Add(_ravi);
        //_ravi.Delete();
    }

running the procedure......

void method()
    {
        
        List<Quote> _quotes = new List<Quote>();
        foreach (DataRow row in dt.Rows)
            _quotes.Add(new Quote()
            {
                Date = Convert.ToDateTime(row["Date"]),
                Open = Convert.ToDecimal(row["Open"]),
                High = Convert.ToDecimal(row["High"]),
                Low = Convert.ToDecimal(row["Low"]),
                Close = Convert.ToDecimal(row["Close"]),
                Volume = Convert.ToDecimal(row["Volume"])
            });

        string s = "";
        foreach (var quote in _quotes)
        {
            s = s   quote.Date.ToString()   quote.Open.ToString()   quote.High.ToString()   quote.Low.ToString()   quote.Close.ToString();
        } // this for if only for check values

        IEnumerable<Quote> quotes = _quotes;
        IEnumerable<SmaResult> results = quotes.GetSma(2);


    }
  • Related