All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mainstringargs.alpaca.AlpacaAPI Maven / Gradle / Ivy

There is a newer version: 5.0.13
Show newest version
package io.github.mainstringargs.alpaca;

import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.gson.reflect.TypeToken;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import io.github.mainstringargs.alpaca.domain.Account;
import io.github.mainstringargs.alpaca.domain.Asset;
import io.github.mainstringargs.alpaca.domain.Bar;
import io.github.mainstringargs.alpaca.domain.Calendar;
import io.github.mainstringargs.alpaca.domain.Clock;
import io.github.mainstringargs.alpaca.domain.Order;
import io.github.mainstringargs.alpaca.domain.Position;
import io.github.mainstringargs.alpaca.enums.AssetStatus;
import io.github.mainstringargs.alpaca.enums.BarsTimeFrame;
import io.github.mainstringargs.alpaca.enums.Direction;
import io.github.mainstringargs.alpaca.enums.OrderSide;
import io.github.mainstringargs.alpaca.enums.OrderStatus;
import io.github.mainstringargs.alpaca.enums.OrderTimeInForce;
import io.github.mainstringargs.alpaca.enums.OrderType;
import io.github.mainstringargs.alpaca.properties.AlpacaProperties;
import io.github.mainstringargs.alpaca.rest.AlpacaRequest;
import io.github.mainstringargs.alpaca.rest.accounts.GetAccountRequestBuilder;
import io.github.mainstringargs.alpaca.rest.assets.GetAssetBySymbolRequestBuilder;
import io.github.mainstringargs.alpaca.rest.assets.GetAssetsRequestBuilder;
import io.github.mainstringargs.alpaca.rest.bars.GetBarsRequestBuilder;
import io.github.mainstringargs.alpaca.rest.calendar.GetCalendarRequestBuilder;
import io.github.mainstringargs.alpaca.rest.clock.GetClockRequestBuilder;
import io.github.mainstringargs.alpaca.rest.exceptions.AlpacaAPIException;
import io.github.mainstringargs.alpaca.rest.orders.DeleteOrderRequestBuilder;
import io.github.mainstringargs.alpaca.rest.orders.GetListOfOrdersRequestBuilder;
import io.github.mainstringargs.alpaca.rest.orders.GetOrderByClientIdRequestBuilder;
import io.github.mainstringargs.alpaca.rest.orders.GetOrderRequestBuilder;
import io.github.mainstringargs.alpaca.rest.orders.PostOrderRequestBuilder;
import io.github.mainstringargs.alpaca.rest.positions.GetOpenPositionBySymbolRequestBuilder;
import io.github.mainstringargs.alpaca.rest.positions.GetOpenPositionsRequestBuilder;
import io.github.mainstringargs.alpaca.websocket.AlpacaStreamListener;
import io.github.mainstringargs.alpaca.websocket.AlpacaWebsocketClient;

/**
 * The Class AlpacaAPI.
 */
public class AlpacaAPI {

  /** The key id. */
  private String keyId;

  /** The secret. */
  private String secret;

  /** The base account url. */
  private String baseAccountUrl;

  /** The alpaca request. */
  private AlpacaRequest alpacaRequest;

  /** The base data url. */
  private String baseDataUrl;
  
  /** The logger. */
  private static Logger LOGGER = LogManager.getLogger(AlpacaAPI.class);

  private AlpacaWebsocketClient alpacaWebSocketClient;

  /**
   * Instantiates a new Alpaca API using properties specified in alpaca.properties file (or relevant
   * defaults)
   */
  public AlpacaAPI() {

    keyId = AlpacaProperties.KEY_ID_VALUE;
    secret = AlpacaProperties.SECRET_VALUE;
    baseAccountUrl = AlpacaProperties.BASE_ACCOUNT_URL_VALUE;
    baseDataUrl = AlpacaProperties.BASE_DATA_URL_VALUE;
    
    LOGGER.info("AlpacaAPI is using the following properties: \nkeyId: " + keyId + "\nsecret: "
        + secret + "\nbaseAccountUrl: " + baseAccountUrl + "\nbaseDataUrl: " + baseDataUrl);
 
    
    alpacaRequest = new AlpacaRequest(keyId, secret);
    alpacaWebSocketClient = new AlpacaWebsocketClient(keyId, secret, baseAccountUrl);

  }

  /**
   * Instantiates a new Alpaca API using the specified keyId, secret, baseAccountUrl, and baseDataUrl.
   *
   * @param keyId the key id
   * @param secret the secret
   * @param baseAccountUrl the base account url
   * @param baseDataUrl the base data url
   */
  public AlpacaAPI(String keyId, String secret, String baseAccountUrl, String baseDataUrl) {
    this.keyId = keyId;
    this.secret = secret;
    this.baseAccountUrl = baseAccountUrl;
    this.baseDataUrl = baseDataUrl;
    
    LOGGER.info("AlpacaAPI is using the following properties: \nkeyId: " + keyId + "\nsecret: "
        + secret + "\nbaseAccountUrl: " + baseAccountUrl + "\nbaseDataUrl: " + baseDataUrl);
    
    alpacaRequest = new AlpacaRequest(keyId, secret);


  }

  /**
   * Instantiates a new Alpaca API using the specified keyId, secret, and baseAccountUrl.
   *
   * @param keyId the key id
   * @param secret the secret
   * @param baseAccountUrl the base account url
   */
  public AlpacaAPI(String keyId, String secret, String baseAccountUrl) {
    this.keyId = keyId;
    this.secret = secret;
    this.baseAccountUrl = baseAccountUrl;
    baseDataUrl = AlpacaProperties.BASE_DATA_URL_VALUE;
    
    LOGGER.info("AlpacaAPI is using the following properties: \nkeyId: " + keyId + "\nsecret: "
        + secret + "\nbaseAccountUrl: " + baseAccountUrl + "\nbaseDataUrl: " + baseDataUrl);
    
    alpacaRequest = new AlpacaRequest(keyId, secret);


  }

  /**
   * Gets the account.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/account/#get-the-account
   *
   * @return the account
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Account getAccount() throws AlpacaAPIException {
    GetAccountRequestBuilder urlBuilder = new GetAccountRequestBuilder(baseAccountUrl);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }

    Account account = alpacaRequest.getResponseObject(response, Account.class);

    return account;
  }


  /**
   * Gets the orders using the following API defaults:
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/orders/#get-a-list-of-orders
   *
   * Status: Open 
   * Limit: 50 
   * Direction: Descending
   *
   * @return the orders
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getOrders() throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetListOfOrdersRequestBuilder urlBuilder = new GetListOfOrdersRequestBuilder(baseAccountUrl);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    List orders = alpacaRequest.getResponseObject(response, listType);

    return orders;
  }

  /**
   * Gets the orders.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/orders/#get-a-list-of-orders
   *
   * @param status the status (Open if null)
   * @param limit the limit (50 if null)
   * @param after the after
   * @param until the until
   * @param direction the direction (Descending if null)
   * @return the orders
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getOrders(OrderStatus status, Integer limit, LocalDateTime after,
      LocalDateTime until, Direction direction) throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetListOfOrdersRequestBuilder urlBuilder = new GetListOfOrdersRequestBuilder(baseAccountUrl);

    urlBuilder.status(status).limit(limit).after(after).until(until).direction(direction);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    List orders = alpacaRequest.getResponseObject(response, listType);

    return orders;
  }

  /**
   * Request/Submits new order.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/orders/#request-a-new-order
   *
   * @param symbol the symbol or asset_id (required)
   * @param quantity the quantity (required)
   * @param side the side (required)
   * @param type the type (required)
   * @param timeInForce the time in force (required)
   * @param limitPrice the limit price (required if Limit or Stop Limit)
   * @param stopPrice the stop price (required if Stop or Stop Limit)
   * @param clientOrderId the client order id (optional)
   * @return the order
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Order requestNewOrder(String symbol, Integer quantity, OrderSide side, OrderType type,
      OrderTimeInForce timeInForce, Double limitPrice, Double stopPrice, String clientOrderId)
      throws AlpacaAPIException {

    Type objectType = new TypeToken() {}.getType();

    PostOrderRequestBuilder urlBuilder = new PostOrderRequestBuilder(baseAccountUrl);

    urlBuilder.symbol(symbol).quantity(quantity).side(side).type(type).timeInForce(timeInForce)
        .limitPrice(limitPrice).stopPrice(stopPrice).clientOrderId(clientOrderId);

    HttpResponse response = alpacaRequest.invokePost(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Order order = alpacaRequest.getResponseObject(response, objectType);

    return order;
  }

  /**
   * Gets the order.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/orders/#get-an-order
   *
   * @param orderId the order id (required)
   * @return the order
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Order getOrder(String orderId) throws AlpacaAPIException {
    Type objectType = new TypeToken() {}.getType();

    GetOrderRequestBuilder urlBuilder = new GetOrderRequestBuilder(baseAccountUrl);

    urlBuilder.orderId(orderId);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Order order = alpacaRequest.getResponseObject(response, objectType);

    return order;
  }

  /**
   * Gets the order by client id.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/orders/#get-an-order-by-client-order-id
   *
   * @param clientOrderId the client order id (required)
   * @return the order by client id
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Order getOrderByClientId(String clientOrderId) throws AlpacaAPIException {
    Type objectType = new TypeToken() {}.getType();

    GetOrderByClientIdRequestBuilder urlBuilder =
        new GetOrderByClientIdRequestBuilder(baseAccountUrl);

    urlBuilder.ordersByClientOrderId(clientOrderId);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Order order = alpacaRequest.getResponseObject(response, objectType);

    return order;
  }

  /**
   * Cancel order.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/orders/#cancel-an-order
   *
   * @param orderId the order id (required)
   * @return true, if successful
   * @throws AlpacaAPIException the alpaca API exception
   */
  public boolean cancelOrder(String orderId) throws AlpacaAPIException {
    DeleteOrderRequestBuilder urlBuilder = new DeleteOrderRequestBuilder(baseAccountUrl);

    urlBuilder.orderId(orderId);

    HttpResponse response = alpacaRequest.invokeDelete(urlBuilder);

    if ((response.getStatus() != 200 && response.getStatus() != 204)) {
      throw new AlpacaAPIException(response);
    }


    return response.getStatus() == 200 || response.getStatus() == 204;
  }

  /**
   * Gets the open positions.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/positions/#get-open-positions
   *
   * @return the open positions
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getOpenPositions() throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetOpenPositionsRequestBuilder urlBuilder = new GetOpenPositionsRequestBuilder(baseAccountUrl);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    List positions = alpacaRequest.getResponseObject(response, listType);

    return positions;
  }


  /**
   * Gets the open position by symbol.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/positions/#get-an-open-position
   *
   * @param symbol the symbol or asset_id (required)
   * @return the open position by symbol
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Position getOpenPositionBySymbol(String symbol) throws AlpacaAPIException {
    Type listType = new TypeToken() {}.getType();

    GetOpenPositionBySymbolRequestBuilder urlBuilder =
        new GetOpenPositionBySymbolRequestBuilder(baseAccountUrl);

    urlBuilder.symbol(symbol);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Position position = alpacaRequest.getResponseObject(response, listType);

    return position;
  }

  /**
   * Gets the assets using the following API defaults:
   * 
   * Status: Active
   * Asset Class: us_equity
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/assets/#get-assets
   *
   * @return the assets
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getAssets() throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetAssetsRequestBuilder urlBuilder = new GetAssetsRequestBuilder(baseAccountUrl);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    List assets = alpacaRequest.getResponseObject(response, listType);

    return assets;
  }


  /**
   * Gets the assets.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/assets/#get-assets
   *
   * @param assetStatus the asset status (Active if null)
   * @param assetClass the asset class (us_equity if null)
   * @return the assets
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getAssets(AssetStatus assetStatus, String assetClass)
      throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetAssetsRequestBuilder urlBuilder = new GetAssetsRequestBuilder(baseAccountUrl);

    urlBuilder.status(assetStatus).assetClass(assetClass);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    List assets = alpacaRequest.getResponseObject(response, listType);

    return assets;
  }

  /**
   * Gets the asset by symbol or asset_id.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/assets/#get-an-asset
   *
   * @param symbol the symbol (required)
   * @return the asset by symbol
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Asset getAssetBySymbol(String symbol) throws AlpacaAPIException {
    Type listType = new TypeToken() {}.getType();

    GetAssetBySymbolRequestBuilder urlBuilder = new GetAssetBySymbolRequestBuilder(baseAccountUrl);

    urlBuilder.symbol(symbol);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Asset asset = alpacaRequest.getResponseObject(response, listType);

    return asset;
  }

  /**
   * Gets the calendar.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/calendar/#get-the-calendar
   *
   * @return the calendar
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getCalendar() throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetCalendarRequestBuilder urlBuilder = new GetCalendarRequestBuilder(baseAccountUrl);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }

    List calendar = alpacaRequest.getResponseObject(response, listType);

    return calendar;
  }

  /**
   * Gets the calendar.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/calendar/#get-the-calendar
   *
   * @param start the start
   * @param end the end
   * @return the calendar
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getCalendar(LocalDate start, LocalDate end) throws AlpacaAPIException {
    Type listType = new TypeToken>() {}.getType();

    GetCalendarRequestBuilder urlBuilder = new GetCalendarRequestBuilder(baseAccountUrl);

    urlBuilder.start(start).end(end);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    List calendar = alpacaRequest.getResponseObject(response, listType);

    return calendar;
  }

  /**
   * Gets the clock.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/clock/#get-the-clock
   *
   * @return the clock
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Clock getClock() throws AlpacaAPIException {
    GetClockRequestBuilder urlBuilder = new GetClockRequestBuilder(baseAccountUrl);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Clock clock = alpacaRequest.getResponseObject(response, Clock.class);

    return clock;
  }


  /**
   * Gets the bars.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/market-data/bars/#get-a-list-of-bars
   *
   * @param timeframe the timeframe (required)
   * @param symbols One or more (max 200) symbol names (required)
   * @param limit The maximum number of bars to be returned for each symbol. It can be between 1 and 1000. Default is 100 if parameter is unspecified or 0. (100 if null)
   * @param start Filter bars equal to or after this time. Cannot be used with after.
   * @param end Filter bars equal to or before this time. Cannot be used with until.
   * @param after Filter bars after this time. Cannot be used with start.
   * @param until Filter bars before this time. Cannot be used with end.
   * @return the bars
   * @throws AlpacaAPIException the alpaca API exception
   */
  public Map> getBars(BarsTimeFrame timeframe, String[] symbols, Integer limit,
      LocalDateTime start, LocalDateTime end, LocalDateTime after, LocalDateTime until)
      throws AlpacaAPIException {
    GetBarsRequestBuilder urlBuilder = new GetBarsRequestBuilder(baseDataUrl);
    urlBuilder.timeframe(timeframe).symbols(symbols).limit(limit).start(start).end(end).after(after)
        .until(until);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Type mapType = new TypeToken>>() {}.getType();

    Map> bars = alpacaRequest.getResponseObject(response, mapType);

    return bars;
  }

  /**
   * Gets the bars.
   * 
   * @see https://docs.alpaca.markets/api-documentation/web-api/market-data/bars/#get-a-list-of-bars
   *
   * @param timeframe the timeframe (required)
   * @param symbol One symbol name (required)
   * @param limit The maximum number of bars to be returned for each symbol. It can be between 1 and
   *        1000. Default is 100 if parameter is unspecified or 0. (100 if null)
   * @param start Filter bars equal to or after this time. Cannot be used with after.
   * @param end Filter bars equal to or before this time. Cannot be used with until.
   * @param after Filter bars after this time. Cannot be used with start.
   * @param until Filter bars before this time. Cannot be used with end.
   * @return the bars
   * @throws AlpacaAPIException the alpaca API exception
   */
  public List getBars(BarsTimeFrame timeframe, String symbol, Integer limit,
      LocalDateTime start, LocalDateTime end, LocalDateTime after, LocalDateTime until)
      throws AlpacaAPIException {
    GetBarsRequestBuilder urlBuilder = new GetBarsRequestBuilder(baseDataUrl);
    urlBuilder.timeframe(timeframe).symbols(symbol).limit(limit).start(start).end(end).after(after)
        .until(until);

    HttpResponse response = alpacaRequest.invokeGet(urlBuilder);

    if (response.getStatus() != 200) {
      throw new AlpacaAPIException(response);
    }


    Type mapType = new TypeToken>>() {}.getType();

    Map> bars = alpacaRequest.getResponseObject(response, mapType);

    return bars.get(symbol);
  }
  
  /**
   * Adds the alpaca stream listener.
   *
   * @param streamListener the stream listener
   */
  public void addAlpacaStreamListener(AlpacaStreamListener streamListener) {
    alpacaWebSocketClient.addListener(streamListener);
  }
  
  /**
   * Removes the alpaca stream listener.
   *
   * @param streamListener the stream listener
   */
  public void removeAlpacaStreamListener(AlpacaStreamListener streamListener) {
    alpacaWebSocketClient.removeListener(streamListener);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy