diff --git a/Source/Basics/TBars.cs b/Source/Basics/TBars.cs index 81a6db25..849ca182 100644 --- a/Source/Basics/TBars.cs +++ b/Source/Basics/TBars.cs @@ -36,6 +36,12 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub public TSeries OHLC4 => this._ohlc4; public TSeries HLCC4 => this._hlcc4; + public TBars Tail(int count=10) { + TBars outBars = new(); + if (count > this.Count) { count = this.Count; } + for (int i = this.Count-count; i "Weighted", }; } + - public void - Add((DateTime t, double o, double h, double l, double c, double v) i, bool update = false) + public void Add((DateTime t, double o, double h, double l, double c, double v) i, bool update = false) => Add(i.t, i.o, i.h, i.l, i.c, i.v, update); public void Add(DateTime t, decimal o, decimal h, decimal l, decimal c, decimal v, bool update = false) diff --git a/Source/Basics/TSeries.cs b/Source/Basics/TSeries.cs index 586c31af..af9b8da7 100644 --- a/Source/Basics/TSeries.cs +++ b/Source/Basics/TSeries.cs @@ -40,6 +40,13 @@ public class TSeries : System.Collections.Generic.List<(DateTime t, double v)> public int Length => this.Count; + public TSeries Tail(int count=10) { + TSeries outSeries = new(); + if (count > this.Count) { count = this.Count; } + for (int i = this.Count-count; i -Alphavantage - Free API to collect quotes for stock, Forex and crypto. It requires a (free) API key +Alphavantage - Free API to collect 100 recent daily quotes. It requires a (free) API key Get API key at https://www.alphavantage.co/support/#api-key Parameters: - Symbol: stock ("AAPL"), crypto ("BTC") or forex pair (divided by dash: "USD-EUR") - Extended: if true, return 2,000 rows. if false, return 100 rows - Interval: enum with options of Month, Week, Day, Hour, Min30, Min15, Min5, Min1 + Symbol: stock ("AAPL"), APIkey: unique Alphavantage API key + Usage: + Alphavantage_Feed ticker = new("MSFT", APIkey:"xxxxxxx"); */ public class Alphavantage_Feed : TBars { public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1} - public Alphavantage_Feed(string Symbol = "IBM", bool Extended = false, Interval Interval = Interval.Day, string APIkey = "demo") + public Alphavantage_Feed(string Symbol = "IBM", string APIkey = "demo") { - - string outputsize = "compact"; - if (Extended) { outputsize = "full"; } System.Net.Http.HttpClient client = new(); JsonElement json = new(); - var tokens = Symbol.Split('-'); - if (tokens.Length > 1) - { - string req = "https://www.alphavantage.co/query?function=FX" + GetInterval(Interval) + "&from_symbol=" + tokens[0] + "&to_symbol=" + tokens[1] + "&outputsize=" + outputsize + "&apikey=" + APIkey; - var msg = client.GetStringAsync(req).Result; - var jres = JsonSerializer.Deserialize(msg).RootElement; - switch (Interval) - { - case Interval.Month: jres.TryGetProperty("Time Series FX (Monthly)", out json); break; - case Interval.Week: jres.TryGetProperty("Time Series FX (Weekly)", out json); break; - case Interval.Day: jres.TryGetProperty("Time Series FX (Daily)", out json); break; - case Interval.Hour: jres.TryGetProperty("Time Series FX (60min)", out json); break; - case Interval.Min30: jres.TryGetProperty("Time Series FX (30min)", out json); break; - case Interval.Min15: jres.TryGetProperty("Time Series FX (15min)", out json); break; - case Interval.Min5: jres.TryGetProperty("Time Series FX (5min)", out json); break; - case Interval.Min1: jres.TryGetProperty("Time Series FX (1min)", out json); break; - } - - } - if (json.ValueKind == JsonValueKind.Undefined) - { - string req = "https://www.alphavantage.co/query?function=TIME_SERIES" + GetInterval(Interval) + "&symbol=" + Symbol + "&outputsize=" + outputsize + "&apikey=" + APIkey; - var msg = client.GetStringAsync(req).Result; - var jres = JsonSerializer.Deserialize(msg).RootElement; - switch (Interval) - { - case Interval.Month: jres.TryGetProperty("Monthly Time Series", out json); break; - case Interval.Week: jres.TryGetProperty("Weekly Time Series", out json); break; - case Interval.Day: jres.TryGetProperty("Time Series (Daily)", out json); break; - case Interval.Hour: jres.TryGetProperty("Time Series (60min)", out json); break; - case Interval.Min30: jres.TryGetProperty("Time Series (30min)", out json); break; - case Interval.Min15: jres.TryGetProperty("Time Series (15min)", out json); break; - case Interval.Min5: jres.TryGetProperty("Time Series (5min)", out json); break; - case Interval.Min1: jres.TryGetProperty("Time Series (1min)", out json); break; - } - } - if (json.ValueKind == JsonValueKind.Undefined) - { - string req; - if ((int)Interval < 3) { req = "https://www.alphavantage.co/query?function=DIGITAL_CURRENCY" + GetInterval(Interval) + "&symbol=" + Symbol + "&market=USD&&outputsize=" + outputsize + "&apikey=" + APIkey; } - else { req = "https://www.alphavantage.co/query?function=CRYPTO" + GetInterval(Interval) + "&symbol=" + Symbol + "&market=USD&&outputsize=" + outputsize + "&apikey=" + APIkey; } - var msg = client.GetStringAsync(req).Result; - var jres = JsonSerializer.Deserialize(msg).RootElement; - switch (Interval) - { - case Interval.Month: jres.TryGetProperty("Time Series (Digital Currency Monthly)", out json); break; - case Interval.Week: jres.TryGetProperty("Time Series (Digital Currency Weekly)", out json); break; - case Interval.Day: jres.TryGetProperty("Time Series (Digital Currency Daily)", out json); break; - case Interval.Hour: jres.TryGetProperty("Time Series Crypto (60min)", out json); break; - case Interval.Min30: jres.TryGetProperty("Time Series Crypto (30min)", out json); break; - case Interval.Min15: jres.TryGetProperty("Time Series Crypto (15min)", out json); break; - case Interval.Min5: jres.TryGetProperty("Time Series Crypto (5min)", out json); break; - case Interval.Min1: jres.TryGetProperty("Time Series Crypto (1min)", out json); break; - } - } - if (json.ValueKind != JsonValueKind.Undefined) - { - foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); } - } + string req = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED" + "&symbol=" + Symbol + "&apikey=" + APIkey; + var msg = client.GetStringAsync(req).Result; + var jres = JsonSerializer.Deserialize(msg).RootElement; + jres.TryGetProperty("Time Series (Daily)", out json); + + if (json.ValueKind == JsonValueKind.Undefined) {throw new InvalidOperationException("Stock symbol "+Symbol+" not found"); } + foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); } + base.Reverse(); } private static (DateTime t, double o, double h, double l, double c, double v) GetOHLC(JsonProperty json) { @@ -101,25 +47,12 @@ public class Alphavantage_Feed : TBars case "3b. low (USD)": l = Convert.ToDouble(val.Value.ToString()); break; case "4. close": c = Convert.ToDouble(val.Value.ToString()); break; case "4b. close (USD)": c = Convert.ToDouble(val.Value.ToString()); break; - case "5. adjusted close": c = Convert.ToDouble(val.Value.ToString()); break; + //case "5. adjusted close": c = Convert.ToDouble(val.Value.ToString()); break; case "5. volume": v = Convert.ToDouble(val.Value.ToString()); break; case "6. volume": v = Convert.ToDouble(val.Value.ToString()); break; } } return (date, o, h, l, c, v); } - - private static string GetInterval(Interval interval = Interval.Day) => interval switch - { - Interval.Month => "_MONTHLY", - Interval.Week => "_WEEKLY", - Interval.Day => "_DAILY_ADJUSTED", - Interval.Hour => "_INTRADAY&interval=60min", - Interval.Min30 => "_INTRADAY&interval=30min", - Interval.Min15 => "_INTRADAY&interval=15min", - Interval.Min5 => "_INTRADAY&interval=5min", - Interval.Min1 => "_INTRADAY&interval=1min", - _ => "_DAILY" - }; } diff --git a/Source/Feeds/GBM_Feed.cs b/Source/Feeds/GBM_Feed.cs index d54ffe9b..dbc9559e 100644 --- a/Source/Feeds/GBM_Feed.cs +++ b/Source/Feeds/GBM_Feed.cs @@ -20,10 +20,10 @@ GBM - Geometric Brownian Motion is a random simulator of market movement, return public class GBM_Feed : TBars { - static double seed; + private double seed; readonly double drift, volatility; public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0) { - seed = Seed; + this.seed = Seed; volatility = Volatility*0.01; drift = Drift*0.01; for (int i = 0; i +Yahoo Finance - Free API feed to collect daily market quotes + Parameters: + Symbol: stock symbol (default: "IBM") + Period: number of days of collected history (default: 252) + Usage: + Yahoo_Feed ticker = new("MSFT", 20); + + */ + +public class Yahoo_Feed : TBars +{ + private static string requestUrl; + + public Yahoo_Feed(string Symbol = "IBM", int Period = 252) { + requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+ + Symbol+"?interval=1d&period1="+ + (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+ + (int)new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); + System.Net.Http.HttpClient client = new(); + var msg = client.GetStringAsync(requestUrl).Result; + var jresult = JsonSerializer.Deserialize(msg).RootElement; + JsonElement json = new(); + JsonElement datetime = new(); + JsonElement open = new(); + JsonElement high = new(); + JsonElement low = new(); + JsonElement close = new(); + JsonElement volume = new(); + + jresult.TryGetProperty("chart",out json); + json.TryGetProperty("result",out json); + json[0].TryGetProperty("timestamp",out datetime); + json[0].TryGetProperty("indicators",out json); + json.TryGetProperty("quote",out json); + json[0].TryGetProperty("open",out open); + json[0].TryGetProperty("high",out high); + json[0].TryGetProperty("low",out low); + json[0].TryGetProperty("close",out close); + json[0].TryGetProperty("volume",out volume); + + for (int i=0; i