Yahoo & Alphavantage feeds

This commit is contained in:
Miha Kralj
2022-11-10 15:36:34 -08:00
5 changed files with 87 additions and 85 deletions
+8 -2
View File
@@ -36,6 +36,12 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
public TSeries OHLC4 => this._ohlc4; public TSeries OHLC4 => this._ohlc4;
public TSeries HLCC4 => this._hlcc4; 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<this.Count; i++) { outBars.Add(this[i]); }
return outBars;
}
public TSeries Select(int source) public TSeries Select(int source)
{ {
return source switch return source switch
@@ -69,8 +75,8 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
}; };
} }
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); => 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) public void Add(DateTime t, decimal o, decimal h, decimal l, decimal c, decimal v, bool update = false)
+7
View File
@@ -40,6 +40,13 @@ public class TSeries : System.Collections.Generic.List<(DateTime t, double v)>
public int Length => this.Count; 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<this.Count; i++) { outSeries.Add(this[i]); }
return outSeries;
}
// add/update one (t,v) tuple to/at the end of the list // add/update one (t,v) tuple to/at the end of the list
public void Add((DateTime t, double v) TValue, bool update = false) public void Add((DateTime t, double v) TValue, bool update = false)
{ {
+13 -80
View File
@@ -3,86 +3,32 @@ using System;
using System.Text.Json; using System.Text.Json;
/* <summary> /* <summary>
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 Get API key at https://www.alphavantage.co/support/#api-key
Parameters: Parameters:
Symbol: stock ("AAPL"), crypto ("BTC") or forex pair (divided by dash: "USD-EUR") Symbol: stock ("AAPL"),
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
APIkey: unique Alphavantage API key APIkey: unique Alphavantage API key
Usage:
Alphavantage_Feed ticker = new("MSFT", APIkey:"xxxxxxx");
</summary> */ </summary> */
public class Alphavantage_Feed : TBars public class Alphavantage_Feed : TBars
{ {
public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1} 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(); System.Net.Http.HttpClient client = new();
JsonElement json = 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<JsonDocument>(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;
}
} string req = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED" + "&symbol=" + Symbol + "&apikey=" + APIkey;
if (json.ValueKind == JsonValueKind.Undefined) var msg = client.GetStringAsync(req).Result;
{ var jres = JsonSerializer.Deserialize<JsonDocument>(msg).RootElement;
string req = "https://www.alphavantage.co/query?function=TIME_SERIES" + GetInterval(Interval) + "&symbol=" + Symbol + "&outputsize=" + outputsize + "&apikey=" + APIkey; jres.TryGetProperty("Time Series (Daily)", out json);
var msg = client.GetStringAsync(req).Result;
var jres = JsonSerializer.Deserialize<JsonDocument>(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<JsonDocument>(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)); }
}
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) 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 "3b. low (USD)": l = Convert.ToDouble(val.Value.ToString()); break;
case "4. close": c = 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 "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 "5. volume": v = Convert.ToDouble(val.Value.ToString()); break;
case "6. 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); 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"
};
} }
+2 -2
View File
@@ -20,10 +20,10 @@ GBM - Geometric Brownian Motion is a random simulator of market movement, return
public class GBM_Feed : TBars public class GBM_Feed : TBars
{ {
static double seed; private double seed;
readonly double drift, volatility; readonly double drift, volatility;
public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0) { 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; volatility = Volatility*0.01;
drift = Drift*0.01; drift = Drift*0.01;
for (int i = 0; i <Bars; i++) { for (int i = 0; i <Bars; i++) {
+56
View File
@@ -0,0 +1,56 @@
namespace QuanTAlib;
using System;
using System.Text.Json;
/* <summary>
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);
</summary> */
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<JsonDocument>(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<datetime.GetArrayLength(); i++) {
DateTime d = DateTimeOffset.FromUnixTimeSeconds(long.Parse(datetime[i].GetRawText())).DateTime;
double o = Math.Round(double.Parse(open[i].GetRawText()),3);
double h = Math.Round(double.Parse(high[i].GetRawText()),3);
double l = Math.Round(double.Parse(low[i].GetRawText()),3);
double c = Math.Round(double.Parse(close[i].GetRawText()),3);
double v = Math.Round(double.Parse(volume[i].GetRawText()),3);
base.Add(d, o, h, l, c, v);
}
}
}