Skip to content

Commit

Permalink
Merge pull request #138 from alpacahq/corp-act
Browse files Browse the repository at this point in the history
Corporate Actions
  • Loading branch information
haxdds authored Jul 27, 2022
2 parents 1d26f84 + d22ca1c commit 5943a8d
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 36 deletions.
43 changes: 43 additions & 0 deletions alpaca/broker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
Watchlist,
Calendar,
Clock,
CorporateActionAnnouncement,
)
from alpaca.trading.models import (
BaseActivity,
Expand All @@ -69,6 +70,7 @@
GetAssetsRequest,
GetOrdersRequest,
GetOrderByIdRequest,
GetCorporateAnnouncementsRequest,
)
from alpaca.trading.enums import (
ActivityType,
Expand Down Expand Up @@ -1530,3 +1532,44 @@ def cancel_order_for_account_by_id(
# TODO: Should ideally return some information about the order's cancel status (Issue #78)
# TODO: Currently no way to retrieve status details for empty responses with base REST implementation
self.delete(f"/trading/accounts/{account_id}/orders/{order_id}")

# ############################## CORPORATE ACTIONS ################################# #

def get_corporate_annoucements(
self, filter: GetCorporateAnnouncementsRequest
) -> List[CorporateActionAnnouncement]:
"""
Returns corporate action announcements data given specified search criteria.
Args:
filter (GetCorporateAnnouncementsRequest): The parameters to filter the search by.
Returns:
List[CorporateActionAnnouncement]: The resulting announcements from the search.
"""
params = filter.to_request_fields() if filter else {}

if "ca_types" in params and type(params["ca_types"]) is List:
params["ca_types"] = ",".join(params["ca_types"])

response = self.get("/corporate_actions/announcements", params)

return parse_obj_as(List[CorporateActionAnnouncement], response)

def get_corporate_announcment_by_id(
self, corporate_announcment_id: Union[UUID, str]
) -> CorporateActionAnnouncement:
"""
Returns a specific corporate action announcement.
Args:
corporate_announcment_id: The id of the desired corporate action announcement
Returns:
CorporateActionAnnouncement: The corporate action queried.
"""
corporate_announcment_id = validate_uuid_id_param(
corporate_announcment_id, "corporate_announcment_id"
)

response = self.get(
f"/corporate_actions/announcements/{corporate_announcment_id}"
)

return CorporateActionAnnouncement(**response)
47 changes: 44 additions & 3 deletions alpaca/trading/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
CancelOrderResponse,
CreateWatchlistRequest,
UpdateWatchlistRequest,
GetCorporateAnnouncementsRequest,
)

from alpaca.trading.models import (
Expand All @@ -28,6 +29,7 @@
Clock,
Calendar,
TradeAccount,
CorporateActionAnnouncement,
)


Expand Down Expand Up @@ -336,9 +338,7 @@ def get_calendar(
List[Calendar]: A list of Calendar objects representing the market days.
"""

result = self.get(
"/calendar", filters.to_request_fields() if filters is not None else {}
)
result = self.get("/calendar", filters.to_request_fields() if filters else {})

return parse_obj_as(List[Calendar], result)

Expand Down Expand Up @@ -498,3 +498,44 @@ def remove_asset_from_watchlist_by_id(
result = self.delete(f"/watchlists/{watchlist_id}/{symbol}")

return Watchlist(**result)

# ############################## CORPORATE ACTIONS ################################# #

def get_corporate_annoucements(
self, filter: GetCorporateAnnouncementsRequest
) -> List[CorporateActionAnnouncement]:
"""
Returns corporate action announcements data given specified search criteria.
Args:
filter (GetCorporateAnnouncementsRequest): The parameters to filter the search by.
Returns:
List[CorporateActionAnnouncement]: The resulting announcements from the search.
"""
params = filter.to_request_fields() if filter else {}

if "ca_types" in params and type(params["ca_types"]) is List:
params["ca_types"] = ",".join(params["ca_types"])

response = self.get("/corporate_actions/announcements", params)

return parse_obj_as(List[CorporateActionAnnouncement], response)

def get_corporate_announcment_by_id(
self, corporate_announcment_id: Union[UUID, str]
) -> CorporateActionAnnouncement:
"""
Returns a specific corporate action announcement.
Args:
corporate_announcment_id: The id of the desired corporate action announcement
Returns:
CorporateActionAnnouncement: The corporate action queried.
"""
corporate_announcment_id = validate_uuid_id_param(
corporate_announcment_id, "corporate_announcment_id"
)

response = self.get(
f"/corporate_actions/announcements/{corporate_announcment_id}"
)

return CorporateActionAnnouncement(**response)
8 changes: 8 additions & 0 deletions alpaca/trading/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,11 @@ class AccountStatus(str, Enum):
SIGNED_UP = "SIGNED_UP"
SUBMISSION_FAILED = "SUBMISSION_FAILED"
SUBMITTED = "SUBMITTED"


class CorporateActionDateType(str, Enum):

DECLARATION_DATE = "declaration_date"
EX_DATE = "ex_date"
RECORD_DATE = "record_date"
PAYABLE_DATE = "payable_date"
2 changes: 1 addition & 1 deletion alpaca/trading/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ class CorporateActionAnnouncement(BaseModel):
initiating_original_cusip: str
target_symbol: str
target_original_cusip: str
declaration_date: date
declaration_date: Optional[date]
ex_date: date
record_date: date
payable_date: date
Expand Down
41 changes: 40 additions & 1 deletion alpaca/trading/requests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import date, datetime
from datetime import date, datetime, timedelta
from typing import Optional, Any, List
from uuid import UUID

Expand All @@ -16,6 +16,8 @@
OrderSide,
OrderClass,
OrderStatus,
CorporateActionType,
CorporateActionDateType,
)


Expand Down Expand Up @@ -426,3 +428,40 @@ def root_validator(cls, values: dict) -> dict:
raise ValueError("Both trail_percent and trail_price cannot be set.")

return values


class GetCorporateAnnouncementsRequest(NonEmptyRequest):
"""
Contains parameters for querying corporate action data.
Attributes:
ca_types (List[CorporateActionType]): A list of corporate action types.
since (date): The start (inclusive) of the date range when searching corporate action announcements.
The date range is limited to 90 days.
until (date): The end (inclusive) of the date range when searching corporate action announcements.
The date range is limited to 90 days.
symbol (Optional[str]): The symbol of the company initiating the announcement.
cusip (Optional[str]): The CUSIP of the company initiating the announcement.
date_type (Optional[CorporateActionDateType]): The date type for the announcement.
"""

ca_types: List[CorporateActionType]
since: date
until: date
symbol: Optional[str]
cusip: Optional[str]
date_type: Optional[CorporateActionDateType]

@root_validator()
def root_validator(cls, values: dict) -> dict:

since = values.get("since")
until = values.get("until")

if (
since is not None
and until is not None
and (until - since) > timedelta(days=90)
):
raise ValueError("The date range is limited to 90 days.")

return values
18 changes: 18 additions & 0 deletions docs/api_reference/broker/corporate-actions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
=================
Corporate Actions
=================

The corporate actions endpoints allow you to retrieve data for splits, mergers, and other
corporate events.

Get Corporate Actions
---------------------

.. automethod:: alpaca.broker.client.BrokerClient.get_corporate_annoucements



Get Corporate Action By ID
---------------------------

.. automethod:: alpaca.broker.client.BrokerClient.get_corporate_announcment_by_id
1 change: 1 addition & 0 deletions docs/api_reference/broker_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Contents
broker/account_activities
broker/calendar
broker/clock
broker/corporate-actions
broker/documents
broker/funding
broker/journals
Expand Down
18 changes: 18 additions & 0 deletions docs/api_reference/trading/corporate-actions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
=================
Corporate Actions
=================

The corporate actions endpoints allow you to retrieve data for splits, mergers, and other
corporate events.

Get Corporate Actions
---------------------

.. automethod:: alpaca.trading.client.TradingClient.get_corporate_annoucements



Get Corporate Action By ID
---------------------------

.. automethod:: alpaca.trading.client.TradingClient.get_corporate_announcment_by_id
30 changes: 18 additions & 12 deletions docs/api_reference/trading/enums.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,6 @@ AccountStatus
.. autoenum:: alpaca.trading.enums.AccountStatus


CorporateActionType
-------------------

.. autoenum:: alpaca.trading.enums.CorporateActionType


CorporateActionSubType
----------------------

.. autoenum:: alpaca.trading.enums.CorporateActionSubType



ActivityType
------------
Expand All @@ -95,6 +83,24 @@ NonTradeActivityStatus



CorporateActionType
-------------------

.. autoenum:: alpaca.trading.enums.CorporateActionType


CorporateActionSubType
----------------------

.. autoenum:: alpaca.trading.enums.CorporateActionSubType


CorporateActionDateType
-----------------------

.. autoenum:: alpaca.trading.enums.CorporateActionDateType





13 changes: 7 additions & 6 deletions docs/api_reference/trading/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ PortfolioHistory
.. autoclass:: alpaca.trading.models.PortfolioHistory


CorporateActionAnnouncement
---------------------------

.. autoclass:: alpaca.trading.models.CorporateActionAnnouncement


ClosePositionResponse
---------------------

Expand All @@ -80,3 +74,10 @@ FailedClosePositionDetails

.. autoclass:: alpaca.trading.models.FailedClosePositionDetails


CorporateActionAnnouncement
---------------------------

.. autoclass:: alpaca.trading.models.CorporateActionAnnouncement


3 changes: 3 additions & 0 deletions docs/api_reference/trading/requests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ CancelOrderResponse
.. autoclass:: alpaca.trading.requests.CancelOrderResponse


GetCorporateAnnouncementsRequest
--------------------------------

.. autoclass:: alpaca.trading.requests.GetCorporateAnnouncementsRequest



Expand Down
1 change: 1 addition & 0 deletions docs/api_reference/trading_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Contents
trading/watchlists
trading/calendar
trading/clock
trading/corporate-actions
trading/models
trading/requests
trading/enums
Expand Down
26 changes: 13 additions & 13 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,26 +83,26 @@ Some examples of request models corresponding to methods:
* ``GetOrdersRequest`` for ``TradingClient.get_orders()``
* ``CryptoLatestOrderbookRequest`` for ``CryptoHistoricalDataClient.get_crypto_latest_orderbook()``

**Usage Example**
**Request Models Usage Example**

To submit an order, you will need to provide a ``MarketOrderRequest`` object.
To get historical bar data for crypto, you will need to provide a CryptoBarsRequest object.

.. code-block:: python
from alpaca.trading.client import TradingClient
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
from alpaca.data.historical import CryptoHistoricalDataClient
from alpaca.data.requests import CryptoBarsRequest
from alpaca.data.timeframe import TimeFrame
client = TradingClient('api-key', 'secret-key')
# no keys required for crypto data
client = CryptoHistoricalDataClient()
request_params = MarketOrderRequest(
symbol="SPY",
qty=3,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY
)
request_params = CryptoBarsRequest(
symbol_or_symbols=["BTC/USD", "ETH/USD"],
timeframe=TimeFrame.Day,
start="2022-07-01"
)
client.submit_order(order_data=request_params)
bars = client.get_crypto_bars(request_params)
Data Validation
^^^^^^^^^^^^^^^
Expand Down
Loading

0 comments on commit 5943a8d

Please sign in to comment.