diff --git a/FinancialModelingPrepApi/Abstractions/Fund/IFundProvider.cs b/FinancialModelingPrepApi/Abstractions/Fund/IFundProvider.cs new file mode 100644 index 0000000..e69ad62 --- /dev/null +++ b/FinancialModelingPrepApi/Abstractions/Fund/IFundProvider.cs @@ -0,0 +1,13 @@ +using MatthiWare.FinancialModelingPrep.Model; +using MatthiWare.FinancialModelingPrep.Model.Fund; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MatthiWare.FinancialModelingPrep.Abstractions.Fund +{ + public interface IFundProvider + { + public Task>> GetETFStockExposureAsync(string symbol); + + } +} diff --git a/FinancialModelingPrepApi/Abstractions/IFinancialModelingPrepApiClient.cs b/FinancialModelingPrepApi/Abstractions/IFinancialModelingPrepApiClient.cs index a93205c..6db3f66 100644 --- a/FinancialModelingPrepApi/Abstractions/IFinancialModelingPrepApiClient.cs +++ b/FinancialModelingPrepApi/Abstractions/IFinancialModelingPrepApiClient.cs @@ -1,6 +1,7 @@ using MatthiWare.FinancialModelingPrep.Abstractions.AdvancedData; using MatthiWare.FinancialModelingPrep.Abstractions.Calendars; using MatthiWare.FinancialModelingPrep.Abstractions.CompanyValuation; +using MatthiWare.FinancialModelingPrep.Abstractions.Fund; using MatthiWare.FinancialModelingPrep.Abstractions.InstitutionalFund; using MatthiWare.FinancialModelingPrep.Abstractions.MarketIndexes; using MatthiWare.FinancialModelingPrep.Abstractions.Statistics; @@ -54,5 +55,15 @@ public interface IFinancialModelingPrepApiClient /// Statistic Related Endpoint are grouped here (Estimates) /// IStockStatisticsProvider StockStatistics { get; } + + /// + /// Cryptomarket related enpoints + /// + ICryptoMarketProvider Crypto { get; } + + /// + /// ETF/Mutual Fund related enpoints + /// + IFundProvider Fund { get; } } } diff --git a/FinancialModelingPrepApi/Core/FinancialModelingPrepApiClient.cs b/FinancialModelingPrepApi/Core/FinancialModelingPrepApiClient.cs index 1e21b11..aa9ce52 100644 --- a/FinancialModelingPrepApi/Core/FinancialModelingPrepApiClient.cs +++ b/FinancialModelingPrepApi/Core/FinancialModelingPrepApiClient.cs @@ -1,6 +1,7 @@ using MatthiWare.FinancialModelingPrep.Abstractions.AdvancedData; using MatthiWare.FinancialModelingPrep.Abstractions.Calendars; using MatthiWare.FinancialModelingPrep.Abstractions.CompanyValuation; +using MatthiWare.FinancialModelingPrep.Abstractions.Fund; using MatthiWare.FinancialModelingPrep.Abstractions.InstitutionalFund; using MatthiWare.FinancialModelingPrep.Abstractions.MarketIndexes; using MatthiWare.FinancialModelingPrep.Abstractions.Statistics; @@ -33,8 +34,15 @@ public class FinancialModelingPrepApiClient : IFinancialModelingPrepApiClient /// public IStockMarketProvider StockMarket { get; } + /// public IStockStatisticsProvider StockStatistics { get; } + /// + public ICryptoMarketProvider Crypto { get; } + + /// + public IFundProvider Fund { get; } + /// public FinancialModelingPrepApiClient(ICompanyValuationProvider companyValuation, IMarketIndexesProvider marketIndexes, @@ -43,7 +51,9 @@ public FinancialModelingPrepApiClient(ICompanyValuationProvider companyValuation IInstitutionalFundProvider institutionalFund, IStockTimeSeriesProvider stockTimeSeries, IStockMarketProvider stockMarket, - IStockStatisticsProvider stockStatistics) + IStockStatisticsProvider stockStatistics, + ICryptoMarketProvider cryptoMarket, + IFundProvider fund) { CompanyValuation = companyValuation; MarketIndexes = marketIndexes; @@ -53,6 +63,8 @@ public FinancialModelingPrepApiClient(ICompanyValuationProvider companyValuation StockTimeSeries = stockTimeSeries; StockMarket = stockMarket; StockStatistics = stockStatistics; + Crypto = cryptoMarket; + Fund = fund; } } } diff --git a/FinancialModelingPrepApi/Core/Fund/FundProvider.cs b/FinancialModelingPrepApi/Core/Fund/FundProvider.cs new file mode 100644 index 0000000..9be0626 --- /dev/null +++ b/FinancialModelingPrepApi/Core/Fund/FundProvider.cs @@ -0,0 +1,34 @@ +using MatthiWare.FinancialModelingPrep.Abstractions.Fund; +using MatthiWare.FinancialModelingPrep.Core.Http; +using MatthiWare.FinancialModelingPrep.Model; +using MatthiWare.FinancialModelingPrep.Model.Fund; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Threading.Tasks; + +namespace MatthiWare.FinancialModelingPrep.Core.Fund +{ + public class FundProvider : IFundProvider + { + private readonly FinancialModelingPrepHttpClient client; + + public FundProvider(FinancialModelingPrepHttpClient client) + { + this.client = client ?? throw new System.ArgumentNullException(nameof(client)); + } + + public Task>> GetETFStockExposureAsync(string symbol) + { + const string url = "[version]/etf-stock-exposure/[symbol]"; + + var pathParams = new NameValueCollection() + { + { "version", ApiVersion.v3.ToString() }, + { "symbol", symbol } + }; + + return client.GetJsonAsync>(url, pathParams, null); + } + } +} diff --git a/FinancialModelingPrepApi/DependencyInjectionExtensions.cs b/FinancialModelingPrepApi/DependencyInjectionExtensions.cs index 5dd545c..4311c27 100644 --- a/FinancialModelingPrepApi/DependencyInjectionExtensions.cs +++ b/FinancialModelingPrepApi/DependencyInjectionExtensions.cs @@ -1,6 +1,7 @@ using MatthiWare.FinancialModelingPrep.Abstractions.AdvancedData; using MatthiWare.FinancialModelingPrep.Abstractions.Calendars; using MatthiWare.FinancialModelingPrep.Abstractions.CompanyValuation; +using MatthiWare.FinancialModelingPrep.Abstractions.Fund; using MatthiWare.FinancialModelingPrep.Abstractions.Http; using MatthiWare.FinancialModelingPrep.Abstractions.InstitutionalFund; using MatthiWare.FinancialModelingPrep.Abstractions.MarketIndexes; @@ -11,6 +12,7 @@ using MatthiWare.FinancialModelingPrep.Core.AdvancedData; using MatthiWare.FinancialModelingPrep.Core.Calendars; using MatthiWare.FinancialModelingPrep.Core.CompanyValuation; +using MatthiWare.FinancialModelingPrep.Core.Fund; using MatthiWare.FinancialModelingPrep.Core.Http; using MatthiWare.FinancialModelingPrep.Core.InstitutionalFund; using MatthiWare.FinancialModelingPrep.Core.MarketIndexes; @@ -51,6 +53,7 @@ public static void AddFinancialModelingPrepApiClient(this IServiceCollection ser services.TryAddTransient(); services.TryAddTransient(); services.TryAddTransient(); + services.TryAddTransient(); } } } diff --git a/FinancialModelingPrepApi/Model/Fund/ETFStockExposureResponse.cs b/FinancialModelingPrepApi/Model/Fund/ETFStockExposureResponse.cs new file mode 100644 index 0000000..2bb656e --- /dev/null +++ b/FinancialModelingPrepApi/Model/Fund/ETFStockExposureResponse.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; + +namespace MatthiWare.FinancialModelingPrep.Model.Fund +{ + public class ETFStockExposureResponse + { + [JsonPropertyName("etfSymbol")] + public string EtfSymbol { get; set; } + + [JsonPropertyName("assetExposure")] + public string AssetExposure { get; set; } + + [JsonPropertyName("sharesNumber")] + public int SharesNumber { get; set; } + + [JsonPropertyName("weightPercentage")] + public double WeightPercentage { get; set; } + + [JsonPropertyName("marketValue")] + public double MarketValue { get; set; } + } +} diff --git a/Tests/ClientFactoryTests.cs b/Tests/ClientFactoryTests.cs index f217a1a..203d70b 100644 --- a/Tests/ClientFactoryTests.cs +++ b/Tests/ClientFactoryTests.cs @@ -53,5 +53,17 @@ public void API_Contains_StockMarket_Provider() { Assert.NotNull(api.StockMarket); } + + [Fact] + public void API_Contains_CryptoMarket_Provider() + { + Assert.NotNull(api.Crypto); + } + + [Fact] + public void API_Contains_Fund_Provider() + { + Assert.NotNull(api.Fund); + } } } diff --git a/Tests/CompanyValuation/CompanyValuationTests.cs b/Tests/CompanyValuation/CompanyValuationTests.cs index c747670..53caa15 100644 --- a/Tests/CompanyValuation/CompanyValuationTests.cs +++ b/Tests/CompanyValuation/CompanyValuationTests.cs @@ -46,7 +46,7 @@ public async Task GetCompanyProfileTests(string symbol) [Theory] [InlineData("AAPL", false)] [InlineData("BST", true, Skip = "IsFund returns incorrect result")] - public async Task GetCompanyProfile_IsFund_Tests(string symbol, bool isFund) + public async Task GetCompanyProfile_IsFund_Tests(string symbol, bool isFund) { var result = await api.GetCompanyProfileAsync(symbol); diff --git a/Tests/Fund/FundTests.cs b/Tests/Fund/FundTests.cs new file mode 100644 index 0000000..7523b90 --- /dev/null +++ b/Tests/Fund/FundTests.cs @@ -0,0 +1,31 @@ +using MatthiWare.FinancialModelingPrep.Abstractions.Fund; +using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Tests.CompanyValuation +{ + public class FundTests : TestingBase + { + private readonly IFundProvider api; + + public FundTests(ITestOutputHelper testOutput) : base(testOutput) + { + api = ServiceProvider.GetRequiredService(); + } + + [Theory] + [InlineData("AAPL")] + [InlineData("AGS.BR")] + [InlineData("O")] + [InlineData("LGEN.L")] + public async Task GetETFStockExposureAsyncTest(string symbol) + { + var result = await api.GetETFStockExposureAsync(symbol); + + result.AssertNoErrors(); + Assert.NotEmpty(result.Data); + } + } +}