Skip to content

Latest commit

 

History

History
270 lines (216 loc) · 16.7 KB

README.md

File metadata and controls

270 lines (216 loc) · 16.7 KB

Logo

GitHub Repository Maven Central Javadocs GitHub

Overview

This library is a Java client implementation of the Alpaca API. Alpaca lets you trade with algorithms, connect with apps, and build services all with a commission-free trading API for stocks, crypto, and options. This library uses the Alpaca OpenAPI Specifications to generate clients for the REST API with the OkHttp library, but implements the websocket and SSE streaming interface using a custom implementation with the OkHttp library. This library is community developed and if you have any questions, please ask them on Github Discussions, the Alpaca Slack #dev-alpaca-java channel, or on the Alpaca Forums. This library strives to provide the complete Alpaca API as a Java client implementation, so open a new issue or new pull request if you find something missing.

Give this repository a star ⭐ if it helped you build a trading algorithm in Java!

Gradle and Maven Integration

If you are using Gradle as your build tool, add the following dependency to your build.gradle file:

implementation group: "net.jacobpeterson.alpaca", name: "alpaca-java", version: "10.0.1"

If you are using Maven as your build tool, add the following dependency to your pom.xml file:

<dependency>
    <groupId>net.jacobpeterson.alpaca</groupId>
    <artifactId>alpaca-java</artifactId>
    <version>10.0.1</version>
</dependency>

Note that you don't have to use the Maven Central artifacts. Instead, you can clone this repository, build this project, and install the artifacts to your local Maven repository as shown in the Building section.

Logger

For logging, this library uses SLF4j which serves as an interface for various logging frameworks. This enables you to use whatever logging framework you would like. However, if you do not add a logging framework as a dependency in your project, the console will output a message stating that SLF4j is defaulting to a no-operation (NOP) logger implementation. To enable logging, add a logging framework of your choice as a dependency to your project such as Logback, Log4j 2, SLF4j-simple, or Apache Commons Logging.

BigDecimal vs. Double

It is generally considered bad practice to represent currency values in floating-point data types such as float or double because it can lead to rounding errors and precision loss in calculations. However, using floating-point data types can have significant performance benefits compared to using arbitrary-precision number data types, especially in a quantitative finance and algorithmic trading environment. Because of this, alpaca-java uses the Double data type (the double boxed type) when using the Market Data APIs and the BigDecimal data type when using the Trading or Broker APIs. The thinking behind this is that exact decimal quantities are important when placing real trades with real money, but less important when performing calculations of financial indicators. The best solution would be to use the TA4j Num interface so that you can decide what data type to use based on your use case, but that is on the TODO list for now. By the way, using BigDecimal wouldn't matter if Alpaca used floating-point data types in their internal systems or in their REST APIs, but the fact that they use String data types in some of the REST API JSON responses and their Trading and Broker OpenAPI specifications don't use the double data type, this leads me to believe that using BigDecimal does actually matter.

Examples

Note that the examples below are not exhaustive. Refer to the Javadoc for all classes and method signatures.

AlpacaAPI is the main class used to interface with the various Alpaca API endpoints. If you are using the Trading or Market Data APIs for a single Alpaca account or if you are using the Broker API, you will generally only need one instance of this class. However, if you are using the Trading API with OAuth to act on behalf of an Alpaca account, this class is optimized so that it can be instantiated quickly, especially when an existing OkHttpClient is given in the constructor. Additionally, all API endpoint instances are instantiated lazily. This class is thread-safe.

The Alpaca API documentation is located here and the AlpacaAPI Javadoc is located here.

Example usage:

Use this code if you are using the Trading or Market Data APIs for a single Alpaca account:

final String keyID = "<your_key_id>";
final String secretKey = "<your_secret_key>";
final TraderAPIEndpointType endpointType = TraderAPIEndpointType.PAPER; // or 'LIVE'
final MarketDataWebsocketSourceType sourceType = MarketDataWebsocketSourceType.IEX; // or 'SIP'
final AlpacaAPI alpacaAPI = new AlpacaAPI(keyID, secretKey, endpointType, sourceType);

Use this code if you are using the Trading API with OAuth to act on behalf of an Alpaca account:

final String oAuthToken = "<an_oauth_token>";
final TraderAPIEndpointType endpointType = TraderAPIEndpointType.PAPER; // or 'LIVE'
final AlpacaAPI alpacaAPI = new AlpacaAPI(oAuthToken, endpointType);

Use this code if you are using the Broker API:

final String brokerAPIKey = "<your_broker_api_key>";
final String brokerAPISecret = "<your_broker_api_secret>";
final BrokerAPIEndpointType endpointType = BrokerAPIEndpointType.SANDBOX; // or 'PRODUCTION'
final AlpacaAPI alpacaAPI = new AlpacaAPI(brokerAPIKey, brokerAPISecret, endpointType);

Note that this library uses OkHttp as its HTTP client library which creates background threads to service requests via a connection pool. These threads persist even if the main thread exits, so if you want to destroy these threads when you're done using AlpacaAPI, use alpacaAPI.closeOkHttpClient();.

The Trader API is used for placing trades, updating account details, getting open positions, and more. Refer to the Javadoc for a list of all available method signatures.

Example usage:

// Place a market order to buy one share of Apple
final Order openingOrder = alpacaAPI.trader().orders()
        .postOrder(new PostOrderRequest()
                .symbol("AAPL")
                .qty("1")
                .side(OrderSide.BUY)
                .type(OrderType.MARKET)
                .timeInForce(TimeInForce.GTC));
System.out.println("Opening Apple order: " + openingOrder);

// Wait for massive gains
Thread.sleep(10_000);

// Close the Apple position
final Order closingOrder = alpacaAPI.trader().positions()
        .deleteOpenPosition("AAPL", null, new BigDecimal("100"));
System.out.println("Closing Apple order: " + openingOrder);

// Wait for closing trade to fill
Thread.sleep(10_000);

// Print out PnL
final String openFillPrice = alpacaAPI.trader().orders()
        .getOrderByOrderID(UUID.fromString(openingOrder.getId()), false)
        .getFilledAvgPrice();
final String closeFillPrice = alpacaAPI.trader().orders()
        .getOrderByOrderID(UUID.fromString(closingOrder.getId()), false)
        .getFilledAvgPrice();
System.out.println("PnL from Apple trade: " +
        new BigDecimal(closeFillPrice).subtract(new BigDecimal(openFillPrice)));

The Market Data API is used for getting market data for stocks, cryptocurrencies, options, and more. Refer to the Javadoc for a list of all available method signatures.

Example usage:

// Print out the latest Tesla trade
final StockTrade latestTSLATrade = alpacaAPI.marketData().stock()
        .stockLatestTradeSingle("TSLA", StockFeed.IEX, null).getTrade();
System.out.printf("Latest TSLA trade: price=%s, size=%s\n",
        latestTSLATrade.getP(), latestTSLATrade.getS());

// Print out the highest Bitcoin ask price on the order book
final CryptoOrderbook latestBitcoinOrderBooks = alpacaAPI.marketData().crypto()
        .cryptoLatestOrderbooks(CryptoLoc.US, "BTC/USD").getOrderbooks().get("BTC/USD");
final Double highestBitcoinAskPrice = latestBitcoinOrderBooks.getA().stream()
        .map(CryptoOrderbookEntry::getP)
        .max(Double::compare)
        .orElse(null);
System.out.println("Bitcoin highest ask price: " + highestBitcoinAskPrice);

// Print out the latest Microsoft option trade
final String latestMSFTOptionTrade = alpacaAPI.marketData().option()
        .optionChain("MSFT").getSnapshots().entrySet().stream()
        .filter(entry -> entry.getValue().getLatestTrade() != null)
        .map(entry -> Map.entry(entry.getKey(), entry.getValue().getLatestTrade()))
        .max(Comparator.comparing(entry -> entry.getValue().getT()))
        .map(entry -> String.format("ticker=%s, time=%s, price=%s",
                entry.getKey(), entry.getValue().getT(), entry.getValue().getP()))
        .orElse(null);
System.out.println("Latest Microsoft option trade: " + latestMSFTOptionTrade);

The Broker API is used for creating new Alpaca accounts for your end users, funding their accounts, placing trades, and more. Refer to the Javadoc for a list of all available method signatures.

Example usage:

// Listen to the trade events (SSE) and print them out
final SSERequest sseRequest = alpacaAPI.broker().events()
        .subscribeToTradeV2(null, null, null, null, new SSEListenerAdapter<>());

// Wait for SSE channel to be ready
Thread.sleep(2000);

// Buy one share of GME for an account
alpacaAPI.broker().trading()
        .createOrderForAccount(UUID.fromString("<some_account_uuid>"),
                new CreateOrderRequest()
                        .symbol("GME")
                        .qty(BigDecimal.ONE)
                        .side(OrderSide.SELL)
                        .timeInForce(TimeInForce.GTC)
                        .type(OrderType.MARKET));

// Wait to be filled
Thread.sleep(2000);

// Close the SSE stream and the OkHttpClient to exit cleanly
sseRequest.close();
alpacaAPI.closeOkHttpClient();

The Updates Stream is used for listening to trade updates in realtime. Refer to the Javadoc for a list of all available method signatures.

Example usage:

// Connect to the 'updates' stream and wait until it's authorized
alpacaAPI.updatesStream().connect();
if (!alpacaAPI.updatesStream().waitForAuthorization(5, TimeUnit.SECONDS)) {
    throw new RuntimeException();
}

// Print out trade updates
alpacaAPI.updatesStream().setListener(System.out::println);
alpacaAPI.updatesStream().subscribeToTradeUpdates(true);

// Place a trade
alpacaAPI.trader().orders().postOrder(new PostOrderRequest()
        .symbol("AAPL")
        .qty("1")
        .side(OrderSide.BUY)
        .type(OrderType.MARKET)
        .timeInForce(TimeInForce.GTC));

// Wait a few seconds
Thread.sleep(5000);

// Close the trade
alpacaAPI.trader().positions().deleteAllOpenPositions(true);

// Wait a few seconds
Thread.sleep(5000);

// Disconnect the 'updates' stream and exit cleanly
alpacaAPI.updatesStream().disconnect();
alpacaAPI.closeOkHttpClient();

The Market Data Stream is used for listening to stock market data, crypto market data, and news data in realtime. Refer to the Javadocs (stock, crypto, news) for a list of all available method signatures.

Example usage:

// Connect to the 'stock market data' stream and wait until it's authorized
alpacaAPI.stockMarketDataStream().connect();
if (!alpacaAPI.stockMarketDataStream().waitForAuthorization(5, TimeUnit.SECONDS)) {
    throw new RuntimeException();
}

// Print out trade messages
alpacaAPI.stockMarketDataStream().setListener(new StockMarketDataListenerAdapter() {
    @Override
    public void onTrade(StockTradeMessage trade) {
        System.out.println("Received trade: " + trade);
    }
});

// Subscribe to AAPL trades
alpacaAPI.stockMarketDataStream().setTradeSubscriptions(Set.of("AAPL"));
System.out.println("Subscribed to Apple trades.");

// Wait a few seconds
Thread.sleep(5000);

// Unsubscribe from AAPL and subscribe to TSLA and MSFT
alpacaAPI.stockMarketDataStream().setTradeSubscriptions(Set.of("TSLA", "MSFT"));
System.out.println("Subscribed to Tesla and Microsoft trades.");

// Wait a few seconds
Thread.sleep(5000);

// Disconnect the 'stock market data' stream and exit cleanly
alpacaAPI.stockMarketDataStream().disconnect();
alpacaAPI.closeOkHttpClient();

Building

To build this project yourself, clone this repository and run:

./gradlew build

To install the built artifacts to your local Maven repository on your machine (the ~/.m2/ directory), run:

./gradlew publishToMavenLocal

TODO

  • Implement better reconnect logic for Websockets and SSE streaming.
  • Implement Unit Testing for REST API and Websocket streaming (both live and mocked).
  • Use TA4j Num interface instead of Double or BigDecimal for number data types so that users can use either Double or BigDecimal for performance or precision in price data.

Contributing

Contributions are welcome!

Do the following before starting your pull request:

  1. Create a new branch in your forked repository for your feature or bug fix instead of committing directly to the master branch in your fork.
  2. Use the dev branch as the base branch in your pull request.