Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/main/java/dev/sorn/fmp4j/FmpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import dev.sorn.fmp4j.cfg.FmpConfig;
import dev.sorn.fmp4j.cfg.FmpConfigImpl;
import dev.sorn.fmp4j.clients.FmpBulkClient;
import dev.sorn.fmp4j.clients.FmpCalendarClient;
import dev.sorn.fmp4j.clients.FmpChartClient;
import dev.sorn.fmp4j.clients.FmpCompanyClient;
Expand All @@ -23,6 +24,7 @@ public class FmpClient {
protected final FmpHttpClient fmpHttpClient;

// Alphabetical order
protected final FmpBulkClient fmpBulkClient;
protected final FmpCalendarClient fmpCalendarClient;
protected final FmpChartClient fmpChartClient;
protected final FmpCompanyClient fmpCompanyClient;
Expand All @@ -46,6 +48,7 @@ public FmpClient(FmpConfig fmpConfig, FmpHttpClient fmpHttpClient) {
fmpHttpClient,

// Alphabetical order
new FmpBulkClient(fmpConfig, fmpHttpClient),
new FmpCalendarClient(fmpConfig, fmpHttpClient),
new FmpChartClient(fmpConfig, fmpHttpClient),
new FmpCompanyClient(fmpConfig, fmpHttpClient),
Expand All @@ -65,6 +68,7 @@ public FmpClient(
FmpHttpClient fmpHttpClient,

// Alphabetical order
FmpBulkClient fmpBulkClient,
FmpCalendarClient fmpCalendarClient,
FmpChartClient fmpChartClient,
FmpCompanyClient fmpCompanyClient,
Expand All @@ -77,15 +81,18 @@ public FmpClient(
FmpSearchClient fmpSearchClient,
FmpSecFilingsSearchClient fmpSecFilingsSearchClient,
FmpStatementClient fmpStatementClient) {
FmpEtfClient fmpEtfClient1;
// Alphabetical order
this.fmpConfig = fmpConfig;
this.fmpHttpClient = fmpHttpClient;
this.fmpBulkClient = fmpBulkClient;
this.fmpCalendarClient = fmpCalendarClient;
this.fmpChartClient = fmpChartClient;
this.fmpCompanyClient = fmpCompanyClient;
this.fmpDirectoryClient = fmpDirectoryClient;
this.fmpEtfClient = fmpEtfClient;
this.fmpEarningsCallTranscriptClient = fmpEarningsCallTranscriptClient;
fmpEtfClient1 = fmpEtfClient;
this.fmpEtfClient = fmpEtfClient1;
this.fmpEconomicsClient = fmpEconomicsClient;
this.fmpNewsClient = fmpNewsClient;
this.fmpQuoteClient = fmpQuoteClient;
Expand All @@ -94,6 +101,10 @@ public FmpClient(
this.fmpStatementClient = fmpStatementClient;
}

public FmpBulkClient bulk() {
return fmpBulkClient;
}

public FmpCalendarClient calendar() {
return fmpCalendarClient;
}
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/dev/sorn/fmp4j/clients/FmpBulkClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.sorn.fmp4j.clients;

import dev.sorn.fmp4j.cfg.FmpConfig;
import dev.sorn.fmp4j.http.FmpHttpClient;
import dev.sorn.fmp4j.models.FmpCashFlowStatementGrowth;
import dev.sorn.fmp4j.services.FmpCashFlowStatementGrowthBulkService;
import dev.sorn.fmp4j.services.FmpService;
import dev.sorn.fmp4j.types.FmpPeriod;
import dev.sorn.fmp4j.types.FmpYear;

public class FmpBulkClient {
private final FmpService<FmpCashFlowStatementGrowth[]> cashFlowStatementGrowthService;

public FmpBulkClient(FmpConfig fmpConfig, FmpHttpClient fmpHttpClient) {
this.cashFlowStatementGrowthService = new FmpCashFlowStatementGrowthBulkService(fmpConfig, fmpHttpClient);
}

public synchronized FmpCashFlowStatementGrowth[] cashFlowStatementGrowth(FmpYear year, FmpPeriod period) {
cashFlowStatementGrowthService.param("year", year);
cashFlowStatementGrowthService.param("period", period);
return cashFlowStatementGrowthService.download();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.sorn.fmp4j.services;

import static dev.sorn.fmp4j.json.FmpJsonUtils.typeRef;

import dev.sorn.fmp4j.cfg.FmpConfig;
import dev.sorn.fmp4j.http.FmpHttpClient;
import dev.sorn.fmp4j.models.FmpCashFlowStatementGrowth;
import java.util.Set;

public class FmpCashFlowStatementGrowthBulkService extends FmpService<FmpCashFlowStatementGrowth[]> {
public FmpCashFlowStatementGrowthBulkService(FmpConfig cfg, FmpHttpClient http) {
super(cfg, http, typeRef(FmpCashFlowStatementGrowth[].class));
}

@Override
protected String relativeUrl() {
return "/v4/cash-flow-statement-growth-bulk";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fmp4j only works with /stable/, not /vX/

Docs for stable (note: it returns CSV, not JSON).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, will be fixed soon.

}

@Override
protected Set<String> requiredParams() {
return Set.of("year", "period");
}

@Override
protected Set<String> optionalParams() {
return Set.of();
}
}
18 changes: 18 additions & 0 deletions src/test/java/dev/sorn/fmp4j/FmpClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import static dev.sorn.fmp4j.types.FmpPeriod.period;
import static dev.sorn.fmp4j.types.FmpStructure.FLAT;
import static dev.sorn.fmp4j.types.FmpSymbol.symbol;
import static dev.sorn.fmp4j.types.FmpYear.year;
import static java.lang.String.format;
import static java.lang.String.join;
import static java.lang.System.setProperty;
Expand Down Expand Up @@ -133,6 +134,23 @@ void searchByIsin() {
assertValidResult(result, 3, FmpSearchByIsin.class);
}

@Test
void cashFlowStatementGrowthBulk() {
var year = year("2025");
var period = period("quarter");
var typeRef = typeRef(FmpCashFlowStatementGrowth[].class);
var endpoint = "v4/cash-flow-statement-growth-bulk";
var uri = buildUri(endpoint);
var headers = defaultHeaders();
var params = buildParams(Map.of("year", year, "period", period));
var file = format("stable/cash-flow-statement-growth-bulk/?year=%s&period=%s.json", year, period);

mockHttpGet(uri, headers, params, file, typeRef);
var result = fmpClient.bulk().cashFlowStatementGrowth(year, period);

assertValidResult(result, 2, FmpCashFlowStatementGrowth.class);
}

@Test
void searchByName() {
// given
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package dev.sorn.fmp4j.services;

import static dev.sorn.fmp4j.HttpClientStub.httpClientStub;
import static dev.sorn.fmp4j.TestUtils.assertAllFieldsNonNull;
import static dev.sorn.fmp4j.TestUtils.jsonTestResource;
import static dev.sorn.fmp4j.json.FmpJsonDeserializerImpl.FMP_JSON_DESERIALIZER;
import static dev.sorn.fmp4j.types.FmpPeriod.period;
import static dev.sorn.fmp4j.types.FmpYear.year;
import static java.util.stream.IntStream.range;
import static org.junit.jupiter.api.Assertions.assertEquals;

import dev.sorn.fmp4j.HttpClientStub;
import dev.sorn.fmp4j.cfg.FmpConfigImpl;
import dev.sorn.fmp4j.http.FmpHttpClient;
import dev.sorn.fmp4j.http.FmpHttpClientImpl;
import dev.sorn.fmp4j.models.FmpCashFlowStatementGrowth;
import java.util.Set;
import org.junit.jupiter.api.Test;

class FmpCashFlowStatementGrowthBulkServiceTest {
private final HttpClientStub httpStub = httpClientStub();
private final FmpHttpClient http = new FmpHttpClientImpl(httpStub, FMP_JSON_DESERIALIZER);
private final FmpService<FmpCashFlowStatementGrowth[]> service =
new FmpCashFlowStatementGrowthBulkService(new FmpConfigImpl(), http);

@Test
void relative_url() {
// when
var relativeUrl = service.relativeUrl();

// then
assertEquals("/v4/cash-flow-statement-growth-bulk", relativeUrl);
}

@Test
void required_params() {
// when
var params = service.requiredParams();

// then
assertEquals(Set.of("year", "period"), params);
}

@Test
void optional_params() {
// when
var params = service.optionalParams();

// then
assertEquals(Set.of(), params);
}

@Test
void successful_download() {
// given
var year = year("2025");
var period = period("quarter");
service.param("year", year);
service.param("period", period);
httpStub.configureResponse()
.body(jsonTestResource("stable/cash-flow-statement-growth-bulk/?year=%s&period=%s.json", year, period))
.statusCode(200)
.apply();

// when
var result = service.download();

// then
assertEquals(2, result.length);
range(0, result.length).forEach(i -> assertAllFieldsNonNull(result[i]));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
[
{
"symbol": "AAPL",
"date": "2025-06-28",
"fiscalYear": "2025",
"period": "Q3",
"reportedCurrency": "USD",
"growthNetIncome": -0.054317998385795,
"growthDepreciationAndAmortization": 0.06350995866215708,
"growthDeferredIncomeTax": 0,
"growthStockBasedCompensation": -0.017978921264724116,
"growthChangeInWorkingCapital": 3.652374366067312,
"growthAccountsReceivables": -2.1114327062228653,
"growthInventory": -0.432348367029549,
"growthAccountsPayables": 0.5115340980713475,
"growthOtherWorkingCapital": 4.545270498256664,
"growthOtherNonCashItems": -89.5,
"growthNetCashProvidedByOperatingActivites": 0.16345190380761523,
"growthInvestmentsInPropertyPlantAndEquipment": -0.12732009117551285,
"growthAcquisitionsNet": 0,
"growthPurchasesOfInvestments": 0.18502690724912946,
"growthSalesMaturitiesOfInvestments": 0.13665099692008428,
"growthOtherInvestingActivites": -9.625,
"growthNetCashUsedForInvestingActivites": 0.7391155296537538,
"growthDebtRepayment": -1.9816398390342052,
"growthCommonStockIssued": 0,
"growthCommonStockRepurchased": 0.186230596957294,
"growthDividendsPaid": -0.04976051091005854,
"growthOtherFinancingActivites": 7.0030674846625764,
"growthNetCashUsedProvidedByFinancingActivities": 0.1438667861821692,
"growthEffectOfForexChangesOnCash": 0,
"growthNetChangeInCash": 4.793635938231165,
"growthCashAtEndOfPeriod": 0.287870179674739,
"growthCashAtBeginningOfPeriod": -0.0705303805406119,
"growthOperatingCashFlow": 0.16345190380761523,
"growthCapitalExpenditure": -0.12732009117551285,
"growthFreeCashFlow": 0.1687658637038456,
"growthNetDebtIssuance": -2.8135245901639343,
"growthLongTermNetDebtIssuance": -0.891,
"growthShortTermNetDebtIssuance": -0.018360160965794767,
"growthNetStockIssuance": 0.186230596957294,
"growthPreferredDividendsPaid": -0.04976051091005854,
"growthIncomeTaxesPaid": -0.5665285451197053,
"growthInterestPaid": 0
},
{
"symbol": "AAPL",
"date": "2025-03-29",
"fiscalYear": "2025",
"period": "Q2",
"reportedCurrency": "USD",
"growthNetIncome": -0.3179190751445087,
"growthDepreciationAndAmortization": -0.13603896103896104,
"growthDeferredIncomeTax": 0,
"growthStockBasedCompensation": -0.018259281801582473,
"growthChangeInWorkingCapital": 0.39481026785714285,
"growthAccountsReceivables": 0.4304302824190448,
"growthInventory": 1.9906976744186047,
"growthAccountsPayables": -0.18917703492729726,
"growthOtherWorkingCapital": 0.1960394249027941,
"growthOtherNonCashItems": 0.8964659034345446,
"growthNetCashProvidedByOperatingActivites": -0.19986637715049274,
"growthInvestmentsInPropertyPlantAndEquipment": -0.0445578231292517,
"growthAcquisitionsNet": 0,
"growthPurchasesOfInvestments": -0.03167864141084259,
"growthSalesMaturitiesOfInvestments": -0.3659489182383473,
"growthOtherInvestingActivites": 0.9469320066334992,
"growthNetCashUsedForInvestingActivites": -0.7021037581699346,
"growthDebtRepayment": 0.499496475327291,
"growthCommonStockIssued": 0,
"growthCommonStockRepurchased": -0.09709395916292468,
"growthDividendsPaid": 0.0254149377593361,
"growthOtherFinancingActivites": 0.8897158322056834,
"growthNetCashUsedProvidedByFinancingActivities": 0.2632648396027533,
"growthEffectOfForexChangesOnCash": 0,
"growthNetChangeInCash": -7.002808988764045,
"growthCashAtEndOfPeriod": -0.0705303805406119,
"growthCashAtBeginningOfPeriod": 0.011889256253548409,
"growthOperatingCashFlow": -0.19986637715049274,
"growthCapitalExpenditure": -0.0445578231292517,
"growthFreeCashFlow": -0.06145749353918026,
"growthNetDebtIssuance": -0.5714828897338403,
"growthLongTermNetDebtIssuance": 0.499496475327291,
"growthShortTermNetDebtIssuance": -0.04017094017094017,
"growthNetStockIssuance": -0.09709395916292468,
"growthPreferredDividendsPaid": 0.0254149377593361,
"growthIncomeTaxesPaid": 0.34269662921348315,
"growthInterestPaid": -0.30952380952380953
}
]