Skip to content

Commit

Permalink
Feature/exercise for account with commission (#517)
Browse files Browse the repository at this point in the history
* feat: Exercise an Options Position with Commission

* update project dependencies
  • Loading branch information
matebudai authored Oct 24, 2024
1 parent 8b5b683 commit a8ee1a0
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 24 deletions.
39 changes: 38 additions & 1 deletion alpaca/broker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
CreateBankTransferRequest,
CreateBatchJournalRequest,
CreateJournalRequest,
CreateOptionExerciseRequest,
CreatePlaidRelationshipRequest,
CreatePortfolioRequest,
CreateReverseBatchJournalRequest,
Expand Down Expand Up @@ -58,7 +59,11 @@
from alpaca.common.enums import BaseURL, PaginationType
from alpaca.common.exceptions import APIError
from alpaca.common.rest import HTTPResult, RESTClient
from alpaca.common.utils import validate_symbol_or_asset_id, validate_uuid_id_param
from alpaca.common.utils import (
validate_symbol_or_asset_id,
validate_uuid_id_param,
validate_symbol_or_contract_id,
)
from alpaca.trading.enums import ActivityType
from alpaca.trading.models import AccountConfiguration as TradeAccountConfiguration
from alpaca.trading.models import (
Expand Down Expand Up @@ -2320,3 +2325,35 @@ def cancel_run_by_id(self, run_id: Union[UUID, str]) -> None:
run_id = validate_uuid_id_param(run_id)

self.delete(f"/rebalancing/runs/{run_id}")

def exercise_options_position_for_account_by_id(
self,
symbol_or_contract_id: Union[UUID, str],
account_id: Union[UUID, str],
commission: Optional[float] = None,
) -> None:
"""
This endpoint enables the correspondent to exercise a held option contract for an account, converting it into the underlying asset based on the specified terms.
All available held shares of this option contract will be exercised.
By default, Alpaca will automatically exercise in-the-money (ITM) contracts at expiry.
Exercise requests will be processed immediately once received. Exercise requests submitted outside market hours will be rejected.
To cancel an exercise request or to submit a Do-not-exercise (DNE) instruction, please contact our support team.
Args:
account_id (Union[UUID, str]): The Account id you wish to retrieve CIPInfo for
symbol_or_contract_id (Union[UUID, str]): Option contract symbol or ID.
commission (Optional[float]): The dollar value commission you want to charge the end user.
Returns:
None
"""

account_id = validate_uuid_id_param(account_id)
symbol_or_contract_id = validate_symbol_or_contract_id(symbol_or_contract_id)
req = CreateOptionExerciseRequest(commission=commission)

params = req.to_request_fields()
self.post(
f"/trading/accounts/{account_id}/positions/{symbol_or_contract_id}/exercise",
params,
)
4 changes: 4 additions & 0 deletions alpaca/broker/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1124,3 +1124,7 @@ class GetRunsRequest(NonEmptyRequest):
account_id: Optional[UUID] = None
type: Optional[RunType] = None
limit: Optional[int] = None


class CreateOptionExerciseRequest(NonEmptyRequest):
commission: Optional[float] = None
46 changes: 23 additions & 23 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions tests/broker/broker_client/test_accounts_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,3 +940,25 @@ def test_update_trade_configuration_for_account_validates_id(
account_id=334,
config=config,
)


def test_exercise_options_position_with_symbol_and_commission(
reqmock, client: BrokerClient
) -> None:
account_id = "5fc0795e-1f16-40cc-aa90-ede67c39d7a9"
symbol_or_contract_id = "SPY240304P00480000"

reqmock.post(
f"/v1/trading/accounts/{account_id}/positions/{symbol_or_contract_id}/exercise",
status_code=204,
)

res = client.exercise_options_position_for_account_by_id(
symbol_or_contract_id=symbol_or_contract_id,
account_id=account_id,
commission=0.55,
)

assert reqmock.called_once
assert reqmock.request_history[0].qs == {}
assert res is None

0 comments on commit a8ee1a0

Please sign in to comment.