The Official Python SDK for Alpaca APIs providing access to trading, market data, and broker services
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The Broker Client provides comprehensive functionality for managing customer brokerage accounts, including account creation, KYC/AML compliance, funding operations, document management, and portfolio rebalancing. It's designed for broker-dealers and fintech platforms building investment services.
from alpaca.broker import BrokerClient
class BrokerClient(RESTClient):
def __init__(
self,
api_key: Optional[str] = None,
secret_key: Optional[str] = None,
oauth_token: Optional[str] = None,
use_basic_auth: bool = False,
raw_data: bool = False,
url_override: Optional[str] = None,
sandbox: bool = False,
) -> None:
"""
Initialize broker client for account management.
Args:
api_key: Broker API key
secret_key: Broker API secret key
oauth_token: OAuth token for user-on-behalf operations
use_basic_auth: Use basic authentication headers
raw_data: Return raw API responses instead of models
url_override: Override base URL for testing
sandbox: Use sandbox environment for testing
"""# Production broker client
broker_client = BrokerClient(
api_key="your-broker-api-key",
secret_key="your-broker-secret-key",
use_basic_auth=True
)
# Sandbox broker client for testing
broker_client = BrokerClient(
api_key="sandbox-api-key",
secret_key="sandbox-secret-key",
use_basic_auth=True,
sandbox=True
)
# OAuth-based client for user-on-behalf operations
broker_client = BrokerClient(
oauth_token="user-oauth-token",
sandbox=True
)def create_account(
self,
account_data: CreateAccountRequest
) -> Union[Account, RawData]:
"""
Create a new customer brokerage account.
Args:
account_data: Account creation parameters including identity, contact, and disclosures
Returns:
Account: Created account with assigned ID and status
"""from alpaca.broker.requests import CreateAccountRequest
from alpaca.broker.models import Contact, Identity, Disclosures, TrustedContact
from datetime import date
class CreateAccountRequest(NonEmptyRequest):
def __init__(
self,
contact: Contact, # Required: Contact information
identity: Identity, # Required: Identity information
disclosures: Disclosures, # Required: Regulatory disclosures
agreements: List[AgreementType], # Required: Signed agreements
documents: Optional[List[AccountDocument]] = None, # Supporting documents
trusted_contact: Optional[TrustedContact] = None, # Trusted contact person
enabled_assets: Optional[List[AssetClass]] = None, # Tradeable asset classes
currency: Optional[str] = None, # Account currency (USD)
max_options_trading_level: Optional[int] = None # Options trading level (0-4)
):from alpaca.broker.models import Contact
class Contact:
"""Customer contact information."""
email_address: str # Email address
phone_number: str # Phone number with country code
street_address: List[str] # Street address lines
unit: Optional[str] # Apartment/unit number
city: str # City
state: str # State/province
postal_code: str # ZIP/postal code
country: Optional[str] # Country code (defaults to USA)from alpaca.broker.models import Identity
from alpaca.broker.enums import TaxIdType, EmploymentStatus, FundingSource
class Identity:
"""Customer identity information."""
given_name: str # First name
middle_name: Optional[str] # Middle name
family_name: str # Last name
date_of_birth: date # Date of birth
tax_id: Optional[str] # SSN/ITIN/EIN
tax_id_type: Optional[TaxIdType] # Type of tax ID
country_of_citizenship: Optional[str] # Citizenship country
country_of_birth: Optional[str] # Birth country
country_of_tax_residence: Optional[str] # Tax residence country
funding_source: Optional[List[FundingSource]] # Source of funds
annual_income_min: Optional[int] # Minimum annual income
annual_income_max: Optional[int] # Maximum annual income
liquid_net_worth_min: Optional[int] # Minimum liquid net worth
liquid_net_worth_max: Optional[int] # Maximum liquid net worth
total_net_worth_min: Optional[int] # Minimum total net worth
total_net_worth_max: Optional[int] # Maximum total net worth
employment_status: Optional[EmploymentStatus] # Employment status
employer_name: Optional[str] # Employer name
employer_address: Optional[str] # Employer address
employment_position: Optional[str] # Job title/positionfrom alpaca.broker.models import Disclosures
class Disclosures:
"""Regulatory disclosure responses."""
is_control_person: bool # Control person of public company
is_affiliated_exchange_or_finra: bool # FINRA/exchange affiliation
is_politically_exposed: bool # Politically exposed person
immediate_family_exposed: bool # Family politically exposed
is_discretionary_investment: bool # Discretionary investment authority
employment_details: Optional[str] # Employment disclosure details
employer_details: Optional[str] # Employer disclosure details
investment_experience: Optional[str] # Investment experience level
investment_objectives: Optional[List[str]] # Investment objectives
source_of_funds: Optional[List[str]] # Source of funds detailsAccount Creation Example:
from alpaca.broker.requests import CreateAccountRequest
from alpaca.broker.models import Contact, Identity, Disclosures
from alpaca.broker.enums import TaxIdType, EmploymentStatus, FundingSource, AgreementType
from datetime import date
# Create account request
account_request = CreateAccountRequest(
contact=Contact(
email_address="customer@example.com",
phone_number="+1-555-123-4567",
street_address=["123 Main Street"],
city="New York",
state="NY",
postal_code="10001"
),
identity=Identity(
given_name="John",
family_name="Doe",
date_of_birth=date(1990, 5, 15),
tax_id="123456789",
tax_id_type=TaxIdType.USA_SSN,
country_of_citizenship="USA",
annual_income_min=50000,
annual_income_max=75000,
liquid_net_worth_min=10000,
liquid_net_worth_max=25000,
employment_status=EmploymentStatus.EMPLOYED,
funding_source=[FundingSource.EMPLOYMENT_INCOME]
),
disclosures=Disclosures(
is_control_person=False,
is_affiliated_exchange_or_finra=False,
is_politically_exposed=False,
immediate_family_exposed=False,
is_discretionary_investment=False
),
agreements=[
AgreementType.ACCOUNT_AGREEMENT,
AgreementType.CUSTOMER_AGREEMENT
],
enabled_assets=[AssetClass.US_EQUITY],
max_options_trading_level=0 # No options trading
)
# Create the account
account = broker_client.create_account(account_request)
print(f"Account created: {account.id}")
print(f"Account number: {account.account_number}")
print(f"Status: {account.status}")def list_accounts(
self,
search_parameters: Optional[ListAccountsRequest] = None
) -> Union[List[Account], RawData]:
"""
List customer accounts with optional filtering.
Args:
search_parameters: Account filtering criteria
Returns:
List[Account]: List of accounts matching criteria
"""def get_account_by_id(
self,
account_id: Union[UUID, str]
) -> Union[Account, RawData]:
"""
Get specific account by ID.
Args:
account_id: Account UUID
Returns:
Account: Account details
"""from alpaca.broker.requests import ListAccountsRequest
from alpaca.trading.enums import AccountStatus
from datetime import datetime
class ListAccountsRequest(NonEmptyRequest):
def __init__(
self,
query: Optional[str] = None, # Search query (name, email, etc.)
created_after: Optional[datetime] = None, # Created after timestamp
created_before: Optional[datetime] = None, # Created before timestamp
status: Optional[AccountStatus] = None, # Account status filter
sort: Optional[str] = None, # Sort field
entities: Optional[str] = None, # Additional entities to include
limit: Optional[int] = None, # Maximum accounts to return
page_token: Optional[str] = None # Pagination token
):Account Querying Examples:
# List all accounts
accounts = broker_client.list_accounts()
print(f"Total accounts: {len(accounts)}")
# Search for specific customer
search_results = broker_client.list_accounts(
ListAccountsRequest(
query="john.doe@example.com",
limit=10
)
)
# Filter by status and date
active_accounts = broker_client.list_accounts(
ListAccountsRequest(
status=AccountStatus.ACTIVE,
created_after=datetime.now() - timedelta(days=30),
sort="created_at"
)
)
# Get specific account
account = broker_client.get_account_by_id("account-uuid-here")
print(f"Account {account.account_number}: {account.status}")def update_account(
self,
account_id: Union[UUID, str],
account_data: UpdateAccountRequest,
) -> Union[Account, RawData]:
"""
Update existing account information.
Args:
account_id: Account UUID to update
account_data: Updated account fields
Returns:
Account: Updated account
"""from alpaca.broker.requests import UpdateAccountRequest
class UpdateAccountRequest(NonEmptyRequest):
def __init__(
self,
contact: Optional[Contact] = None, # Updated contact info
identity: Optional[Identity] = None, # Updated identity info
disclosures: Optional[Disclosures] = None, # Updated disclosures
trusted_contact: Optional[TrustedContact] = None, # Updated trusted contact
enabled_assets: Optional[List[AssetClass]] = None, # Updated tradeable assets
max_options_trading_level: Optional[int] = None # Updated options level
):Account Update Examples:
# Update contact information
updated_contact = Contact(
email_address="newemail@example.com",
phone_number="+1-555-987-6543",
street_address=["456 New Street"],
city="San Francisco",
state="CA",
postal_code="94102"
)
update_request = UpdateAccountRequest(contact=updated_contact)
updated_account = broker_client.update_account(account_id, update_request)
# Enable options trading
options_update = UpdateAccountRequest(
max_options_trading_level=2, # Level 2 options
enabled_assets=[AssetClass.US_EQUITY, AssetClass.US_OPTION]
)
updated_account = broker_client.update_account(account_id, options_update)def create_ach_relationship(
self,
account_id: Union[UUID, str],
ach_data: CreateACHRelationshipRequest,
) -> Union[ACHRelationship, RawData]:
"""
Create ACH bank relationship for transfers.
Args:
account_id: Customer account UUID
ach_data: ACH relationship parameters
Returns:
ACHRelationship: Created ACH relationship
"""from alpaca.broker.requests import CreateACHRelationshipRequest
from alpaca.broker.enums import BankAccountType
class CreateACHRelationshipRequest(NonEmptyRequest):
def __init__(
self,
account_owner_name: str, # Account owner name
bank_account_type: BankAccountType, # CHECKING or SAVINGS
bank_account_number: str, # Bank account number
bank_routing_number: str, # Bank routing number
nickname: Optional[str] = None # Relationship nickname
):def create_plaid_relationship(
self,
account_id: Union[UUID, str],
plaid_data: CreatePlaidRelationshipRequest,
) -> Union[ACHRelationship, RawData]:
"""
Create ACH relationship via Plaid Link.
Args:
account_id: Customer account UUID
plaid_data: Plaid integration parameters
Returns:
ACHRelationship: Created ACH relationship via Plaid
"""def get_ach_relationships(
self,
account_id: Union[UUID, str]
) -> Union[List[ACHRelationship], RawData]:
"""
Get ACH relationships for account.
Args:
account_id: Customer account UUID
Returns:
List[ACHRelationship]: ACH relationships for the account
"""def delete_ach_relationship(
self,
account_id: Union[UUID, str],
ach_relationship_id: Union[UUID, str],
) -> None:
"""
Delete ACH relationship.
Args:
account_id: Customer account UUID
ach_relationship_id: ACH relationship UUID to delete
"""from alpaca.broker.models import ACHRelationship
from alpaca.broker.enums import ACHRelationshipStatus, BankAccountType
class ACHRelationship:
"""ACH bank relationship for transfers."""
id: UUID # Relationship UUID
account_id: UUID # Customer account UUID
account_owner_name: str # Account owner name
bank_account_type: BankAccountType # CHECKING or SAVINGS
bank_account_number: str # Masked account number
bank_routing_number: str # Bank routing number
nickname: Optional[str] # Relationship nickname
status: ACHRelationshipStatus # Relationship status
created_at: datetime # Creation timestampACH Relationship Examples:
from alpaca.broker.enums import BankAccountType
# Create ACH relationship manually
ach_request = CreateACHRelationshipRequest(
account_owner_name="John Doe",
bank_account_type=BankAccountType.CHECKING,
bank_account_number="1234567890",
bank_routing_number="021000021", # Chase routing number
nickname="Primary Checking"
)
ach_relationship = broker_client.create_ach_relationship(account_id, ach_request)
print(f"ACH relationship created: {ach_relationship.id}")
print(f"Status: {ach_relationship.status}")
# List ACH relationships for account
relationships = broker_client.get_ach_relationships(account_id)
for rel in relationships:
print(f"{rel.nickname}: {rel.bank_account_type} ending in {rel.bank_account_number[-4:]}")def create_ach_transfer(
self,
account_id: Union[UUID, str],
transfer_data: CreateACHTransferRequest,
) -> Union[Transfer, RawData]:
"""
Create ACH transfer (deposit or withdrawal).
Args:
account_id: Customer account UUID
transfer_data: Transfer parameters
Returns:
Transfer: Created transfer with status
"""from alpaca.broker.requests import CreateACHTransferRequest
from alpaca.broker.enums import TransferDirection, TransferTiming
class CreateACHTransferRequest(NonEmptyRequest):
def __init__(
self,
relationship_id: Union[UUID, str], # ACH relationship UUID
amount: float, # Transfer amount
direction: TransferDirection, # INCOMING or OUTGOING
timing: Optional[TransferTiming] = None, # IMMEDIATE or NEXT_BUSINESS_DAY
fee_payment_method: Optional[str] = None # Fee payment method
):def get_transfers(
self,
account_id: Union[UUID, str],
transfer_data: Optional[GetTransfersRequest] = None,
) -> Union[List[Transfer], RawData]:
"""
Get transfers for account with optional filtering.
Args:
account_id: Customer account UUID
transfer_data: Transfer query parameters
Returns:
List[Transfer]: Account transfers
"""def cancel_transfer(
self,
account_id: Union[UUID, str],
transfer_id: Union[UUID, str],
) -> None:
"""
Cancel pending transfer.
Args:
account_id: Customer account UUID
transfer_id: Transfer UUID to cancel
"""from alpaca.broker.models import Transfer
from alpaca.broker.enums import TransferDirection, TransferStatus, TransferType
class Transfer:
"""Money transfer information."""
id: UUID # Transfer UUID
account_id: UUID # Customer account UUID
relationship_id: UUID # ACH relationship UUID
amount: float # Transfer amount
direction: TransferDirection # INCOMING or OUTGOING
type: TransferType # ACH, WIRE, CHECK
status: TransferStatus # Transfer status
reason: Optional[str] # Transfer reason/description
requested_at: datetime # Request timestamp
effective_at: Optional[datetime] # Effective date
expires_at: Optional[datetime] # Expiration date
fee: Optional[float] # Transfer fee
additional_information: Optional[str] # Additional detailsTransfer Examples:
from alpaca.broker.enums import TransferDirection
# Deposit funds (incoming transfer)
deposit_request = CreateACHTransferRequest(
relationship_id=ach_relationship.id,
amount=5000.00,
direction=TransferDirection.INCOMING
)
deposit = broker_client.create_ach_transfer(account_id, deposit_request)
print(f"Deposit initiated: ${deposit.amount} (Status: {deposit.status})")
# Withdraw funds (outgoing transfer)
withdrawal_request = CreateACHTransferRequest(
relationship_id=ach_relationship.id,
amount=1000.00,
direction=TransferDirection.OUTGOING
)
withdrawal = broker_client.create_ach_transfer(account_id, withdrawal_request)
print(f"Withdrawal initiated: ${withdrawal.amount}")
# Get transfer history
transfers = broker_client.get_transfers(account_id)
for transfer in transfers:
direction_str = "Deposit" if transfer.direction == TransferDirection.INCOMING else "Withdrawal"
print(f"{direction_str}: ${transfer.amount} - {transfer.status} ({transfer.requested_at.date()})")def submit_order(
self,
account_id: Union[UUID, str],
order_data: OrderRequest,
) -> Union[Order, RawData]:
"""
Submit order for customer account.
Args:
account_id: Customer account UUID
order_data: Order parameters (same as trading client)
Returns:
Order: Submitted order
"""def get_orders_for_account(
self,
account_id: Union[UUID, str]
) -> Union[List[Order], RawData]:
"""
Get orders for specific customer account.
Args:
account_id: Customer account UUID
Returns:
List[Order]: Orders for the account
"""Broker Trading Examples:
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
# Submit order for customer account
customer_order = MarketOrderRequest(
symbol="AAPL",
qty=100,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY
)
order = broker_client.submit_order(account_id, customer_order)
print(f"Order submitted for customer: {order.id}")
# Get customer's orders
customer_orders = broker_client.get_orders_for_account(account_id)
print(f"Customer has {len(customer_orders)} orders")def upload_document(
self,
account_id: Union[UUID, str],
document_data: UploadDocumentRequest,
) -> Union[AccountDocument, RawData]:
"""
Upload document for account.
Args:
account_id: Customer account UUID
document_data: Document upload parameters
Returns:
AccountDocument: Uploaded document information
"""def get_documents(
self,
account_id: Union[UUID, str]
) -> Union[List[AccountDocument], RawData]:
"""
Get documents for account.
Args:
account_id: Customer account UUID
Returns:
List[AccountDocument]: Account documents
"""def download_document(
self,
account_id: Union[UUID, str],
document_id: Union[UUID, str],
) -> bytes:
"""
Download document content.
Args:
account_id: Customer account UUID
document_id: Document UUID
Returns:
bytes: Document content
"""def get_trade_documents(
self,
account_id: Union[UUID, str],
request: Optional[GetTradeDocumentsRequest] = None,
) -> Union[List[TradeDocument], RawData]:
"""
Get trade confirmation and statement documents.
Args:
account_id: Customer account UUID
request: Trade document filtering parameters
Returns:
List[TradeDocument]: Trade documents
"""Document Management Examples:
# Upload identity document
with open("customer_id.pdf", "rb") as f:
document_content = f.read()
upload_request = UploadDocumentRequest(
document_type="identity_verification",
content=base64.b64encode(document_content).decode(),
mime_type="application/pdf"
)
document = broker_client.upload_document(account_id, upload_request)
print(f"Document uploaded: {document.id}")
# Get all documents for account
documents = broker_client.get_documents(account_id)
for doc in documents:
print(f"{doc.document_type}: {doc.name} (uploaded: {doc.created_at})")
# Get trade confirmations
trade_docs = broker_client.get_trade_documents(account_id)
for doc in trade_docs:
print(f"Trade document: {doc.name} ({doc.date})")Journal entries allow moving cash or securities between accounts.
def create_journal(
self,
journal_data: CreateJournalRequest
) -> Union[Journal, RawData]:
"""
Create journal entry to move cash between accounts.
Args:
journal_data: Journal entry parameters
Returns:
Journal: Created journal entry
"""from alpaca.broker.requests import CreateJournalRequest
from alpaca.broker.enums import JournalEntryType
from datetime import date
class CreateJournalRequest(NonEmptyRequest):
def __init__(
self,
entry_type: JournalEntryType, # JNLC (cash) or JNLS (securities)
from_account: Union[UUID, str], # Source account UUID
to_account: Union[UUID, str], # Destination account UUID
amount: Optional[float] = None, # Cash amount (for JNLC)
symbol: Optional[str] = None, # Securities symbol (for JNLS)
qty: Optional[float] = None, # Securities quantity (for JNLS)
price: Optional[float] = None, # Securities price (for JNLS)
settle_date: Optional[date] = None, # Settlement date
description: Optional[str] = None # Journal description
):def create_batch_journal(
self,
journal_data: CreateBatchJournalRequest
) -> Union[BatchJournalResponse, RawData]:
"""
Create multiple journal entries in a batch.
Args:
journal_data: Batch journal parameters
Returns:
BatchJournalResponse: Batch creation results
"""def get_journals(
self,
journal_data: Optional[GetJournalsRequest] = None
) -> Union[List[Journal], RawData]:
"""
Get journal entries with optional filtering.
Args:
journal_data: Journal query parameters
Returns:
List[Journal]: Journal entries
"""from alpaca.broker.models import Journal
from alpaca.broker.enums import JournalEntryType, JournalStatus
class Journal:
"""Journal entry for moving cash or securities between accounts."""
id: UUID # Journal UUID
entry_type: JournalEntryType # JNLC (cash) or JNLS (securities)
from_account: UUID # Source account UUID
to_account: UUID # Destination account UUID
status: JournalStatus # Journal status
settle_date: Optional[date] # Settlement date
system_date: Optional[date] # System processing date
net_amount: Optional[float] # Net cash amount
amount: Optional[float] # Gross amount
symbol: Optional[str] # Securities symbol
qty: Optional[float] # Securities quantity
price: Optional[float] # Securities price
description: Optional[str] # Description
created_at: datetime # Creation timestampJournal Examples:
from alpaca.broker.enums import JournalEntryType
# Transfer cash between accounts
cash_journal = CreateJournalRequest(
entry_type=JournalEntryType.JNLC, # Cash journal
from_account="source-account-uuid",
to_account="destination-account-uuid",
amount=1000.00,
description="Customer cash transfer"
)
journal = broker_client.create_journal(cash_journal)
print(f"Cash journal created: {journal.id} (${journal.amount})")
# Transfer securities between accounts
securities_journal = CreateJournalRequest(
entry_type=JournalEntryType.JNLS, # Securities journal
from_account="source-account-uuid",
to_account="destination-account-uuid",
symbol="AAPL",
qty=100,
price=175.00,
description="AAPL share transfer"
)
securities_journal_entry = broker_client.create_journal(securities_journal)
print(f"Securities journal created: {securities_journal_entry.id}")
# Get journal history
journals = broker_client.get_journals()
for journal in journals:
if journal.entry_type == JournalEntryType.JNLC:
print(f"Cash: ${journal.amount} from {journal.from_account} to {journal.to_account}")
else:
print(f"Securities: {journal.qty} {journal.symbol} @ ${journal.price}")def create_portfolio(
self,
portfolio_data: CreatePortfolioRequest
) -> Union[Portfolio, RawData]:
"""
Create portfolio strategy for rebalancing.
Args:
portfolio_data: Portfolio creation parameters
Returns:
Portfolio: Created portfolio strategy
"""from alpaca.broker.requests import CreatePortfolioRequest
from alpaca.broker.enums import WeightType
class CreatePortfolioRequest(NonEmptyRequest):
def __init__(
self,
name: str, # Portfolio name
description: Optional[str] = None, # Portfolio description
weights: Dict[str, float], # Asset allocation weights
weight_type: WeightType = WeightType.PERCENT, # PERCENT or DOLLAR
cooldown_days: Optional[int] = None, # Rebalancing cooldown period
schedule: Optional[str] = None, # Rebalancing schedule
max_accounts_per_day: Optional[int] = None # Max accounts to rebalance per day
):def get_portfolios(
self,
request: Optional[GetPortfoliosRequest] = None
) -> Union[List[Portfolio], RawData]:
"""
Get portfolio strategies with optional filtering.
Args:
request: Portfolio query parameters
Returns:
List[Portfolio]: Portfolio strategies
"""def create_subscription(
self,
subscription_data: CreateSubscriptionRequest
) -> Union[Subscription, RawData]:
"""
Subscribe account to portfolio strategy.
Args:
subscription_data: Subscription parameters
Returns:
Subscription: Created subscription
"""from alpaca.broker.requests import CreateSubscriptionRequest
class CreateSubscriptionRequest(NonEmptyRequest):
def __init__(
self,
account_id: Union[UUID, str], # Customer account UUID
portfolio_id: Union[UUID, str], # Portfolio strategy UUID
max_investment_amount: Optional[float] = None, # Maximum investment
cash_percentage: Optional[float] = None # Cash allocation percentage
):def create_run(
self,
run_data: CreateRunRequest
) -> Union[RebalancingRun, RawData]:
"""
Execute portfolio rebalancing run.
Args:
run_data: Rebalancing run parameters
Returns:
RebalancingRun: Rebalancing execution results
"""from alpaca.broker.requests import CreateRunRequest
from alpaca.broker.enums import RunType
class CreateRunRequest(NonEmptyRequest):
def __init__(
self,
type: RunType, # FULL_REBALANCE or DRIFT_REBALANCE
portfolio_id: Union[UUID, str], # Portfolio strategy UUID
account_ids: Optional[List[Union[UUID, str]]] = None, # Specific accounts to rebalance
notify: Optional[bool] = None, # Send notifications
max_accounts_per_day: Optional[int] = None # Limit accounts per day
):Portfolio Management Examples:
from alpaca.broker.enums import WeightType, RunType
# Create balanced portfolio strategy
portfolio_request = CreatePortfolioRequest(
name="Conservative Balanced",
description="60% stocks, 40% bonds conservative allocation",
weights={
"SPY": 0.30, # S&P 500 ETF - 30%
"VTI": 0.30, # Total Stock Market - 30%
"BND": 0.25, # Bond ETF - 25%
"VTEB": 0.15 # Municipal Bond ETF - 15%
},
weight_type=WeightType.PERCENT,
cooldown_days=30 # Rebalance at most once per month
)
portfolio = broker_client.create_portfolio(portfolio_request)
print(f"Portfolio created: {portfolio.id} - {portfolio.name}")
# Subscribe customer account to portfolio
subscription_request = CreateSubscriptionRequest(
account_id="customer-account-uuid",
portfolio_id=portfolio.id,
max_investment_amount=50000.00, # Max $50k investment
cash_percentage=0.05 # Keep 5% in cash
)
subscription = broker_client.create_subscription(subscription_request)
print(f"Account subscribed to portfolio: {subscription.id}")
# Execute rebalancing run
run_request = CreateRunRequest(
type=RunType.FULL_REBALANCE,
portfolio_id=portfolio.id,
account_ids=[subscription.account_id], # Rebalance specific account
notify=True
)
rebalancing_run = broker_client.create_run(run_request)
print(f"Rebalancing run initiated: {rebalancing_run.id}")
print(f"Status: {rebalancing_run.status}")The broker client includes comprehensive KYC/AML functionality:
from alpaca.broker.models.cip import (
CIPKYCInfo, CIPDocument, CIPPhoto, CIPIdentity,
CIPWatchlist, CIPInfo
)
class CIPInfo:
"""Overall Customer Identification Program status."""
kyc: Optional[CIPKYCInfo] # KYC verification results
identity: Optional[CIPIdentity] # Identity verification results
watchlist: Optional[CIPWatchlist] # Watchlist screening results
patriot_act: Optional[dict] # USA PATRIOT Act verificationdef get_account_activities(
self,
account_id: Union[UUID, str],
request: Optional[GetAccountActivitiesRequest] = None,
) -> Union[List[BaseActivity], RawData]:
"""
Get account activities (trades, dividends, etc.).
Args:
account_id: Customer account UUID
request: Activity filtering parameters
Returns:
List[BaseActivity]: Account activities
"""from alpaca.common.exceptions import APIError
try:
# Create account that might fail validation
account = broker_client.create_account(account_request)
except APIError as e:
if e.status_code == 400:
print(f"Invalid account data: {e.message}")
elif e.status_code == 409:
print("Account already exists with this information")
elif e.status_code == 422:
print(f"Validation error: {e.message}")
else:
print(f"API error: {e.message} (status: {e.status_code})")
except Exception as e:
print(f"Unexpected error: {e}")from datetime import date, datetime, timedelta
from alpaca.broker import BrokerClient
from alpaca.broker.requests import *
from alpaca.broker.models import *
from alpaca.broker.enums import *
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
class BrokerPlatform:
def __init__(self, api_key: str, secret_key: str, sandbox: bool = True):
self.client = BrokerClient(
api_key=api_key,
secret_key=secret_key,
use_basic_auth=True,
sandbox=sandbox
)
def onboard_customer(self, customer_info: dict) -> str:
"""Complete customer onboarding workflow."""
print("🚀 Starting customer onboarding...")
# Step 1: Create account
account_request = CreateAccountRequest(
contact=Contact(
email_address=customer_info["email"],
phone_number=customer_info["phone"],
street_address=[customer_info["address"]],
city=customer_info["city"],
state=customer_info["state"],
postal_code=customer_info["zip_code"]
),
identity=Identity(
given_name=customer_info["first_name"],
family_name=customer_info["last_name"],
date_of_birth=customer_info["date_of_birth"],
tax_id=customer_info["ssn"],
tax_id_type=TaxIdType.USA_SSN,
annual_income_min=customer_info["income_min"],
annual_income_max=customer_info["income_max"],
employment_status=EmploymentStatus.EMPLOYED,
funding_source=[FundingSource.EMPLOYMENT_INCOME]
),
disclosures=Disclosures(
is_control_person=False,
is_affiliated_exchange_or_finra=False,
is_politically_exposed=False,
immediate_family_exposed=False,
is_discretionary_investment=False
),
agreements=[
AgreementType.ACCOUNT_AGREEMENT,
AgreementType.CUSTOMER_AGREEMENT
],
enabled_assets=[AssetClass.US_EQUITY]
)
account = self.client.create_account(account_request)
print(f"✅ Account created: {account.account_number}")
return str(account.id)
def setup_funding(self, account_id: str, bank_info: dict) -> str:
"""Set up bank relationship and initial funding."""
print("💰 Setting up funding...")
# Create ACH relationship
ach_request = CreateACHRelationshipRequest(
account_owner_name=bank_info["owner_name"],
bank_account_type=BankAccountType.CHECKING,
bank_account_number=bank_info["account_number"],
bank_routing_number=bank_info["routing_number"],
nickname="Primary Checking"
)
ach_relationship = self.client.create_ach_relationship(account_id, ach_request)
print(f"✅ ACH relationship created: {ach_relationship.id}")
# Initial deposit
if bank_info.get("initial_deposit", 0) > 0:
deposit_request = CreateACHTransferRequest(
relationship_id=ach_relationship.id,
amount=bank_info["initial_deposit"],
direction=TransferDirection.INCOMING
)
deposit = self.client.create_ach_transfer(account_id, deposit_request)
print(f"✅ Initial deposit initiated: ${deposit.amount}")
return str(ach_relationship.id)
def create_portfolio_strategy(self, strategy_name: str, allocations: dict) -> str:
"""Create rebalancing portfolio strategy."""
print(f"📊 Creating portfolio strategy: {strategy_name}")
portfolio_request = CreatePortfolioRequest(
name=strategy_name,
description=f"Automated {strategy_name} allocation",
weights=allocations,
weight_type=WeightType.PERCENT,
cooldown_days=30
)
portfolio = self.client.create_portfolio(portfolio_request)
print(f"✅ Portfolio strategy created: {portfolio.id}")
return str(portfolio.id)
def subscribe_to_portfolio(self, account_id: str, portfolio_id: str, max_investment: float) -> None:
"""Subscribe customer to portfolio strategy."""
subscription_request = CreateSubscriptionRequest(
account_id=account_id,
portfolio_id=portfolio_id,
max_investment_amount=max_investment,
cash_percentage=0.05 # Keep 5% cash
)
subscription = self.client.create_subscription(subscription_request)
print(f"✅ Account subscribed to portfolio: {subscription.id}")
def execute_trade(self, account_id: str, symbol: str, quantity: float, side: str) -> None:
"""Execute trade for customer account."""
order_request = MarketOrderRequest(
symbol=symbol,
qty=quantity,
side=OrderSide.BUY if side.upper() == "BUY" else OrderSide.SELL,
time_in_force=TimeInForce.DAY
)
order = self.client.submit_order(account_id, order_request)
print(f"📈 Order submitted: {side} {quantity} {symbol} (ID: {order.id})")
def get_customer_summary(self, account_id: str) -> dict:
"""Get comprehensive customer account summary."""
# Get account details
account = self.client.get_account_by_id(account_id)
# Get funding relationships
ach_relationships = self.client.get_ach_relationships(account_id)
# Get recent transfers
transfers = self.client.get_transfers(account_id)
recent_transfers = [t for t in transfers if t.requested_at > datetime.now() - timedelta(days=30)]
# Get orders
orders = self.client.get_orders_for_account(account_id)
return {
"account_number": account.account_number,
"status": account.status,
"ach_relationships": len(ach_relationships),
"recent_transfers": len(recent_transfers),
"total_orders": len(orders),
"created_at": account.created_at
}
# Example usage
if __name__ == "__main__":
platform = BrokerPlatform(
api_key="sandbox-api-key",
secret_key="sandbox-secret-key",
sandbox=True
)
# Customer onboarding
customer_data = {
"first_name": "Jane",
"last_name": "Smith",
"email": "jane.smith@example.com",
"phone": "+1-555-123-4567",
"address": "123 Investment St",
"city": "New York",
"state": "NY",
"zip_code": "10001",
"date_of_birth": date(1985, 3, 15),
"ssn": "123456789",
"income_min": 75000,
"income_max": 100000
}
account_id = platform.onboard_customer(customer_data)
# Set up funding
bank_data = {
"owner_name": "Jane Smith",
"account_number": "1234567890",
"routing_number": "021000021",
"initial_deposit": 10000.00
}
ach_id = platform.setup_funding(account_id, bank_data)
# Create portfolio strategy
conservative_allocation = {
"VTI": 0.40, # Total Stock Market - 40%
"VXUS": 0.20, # International Stocks - 20%
"BND": 0.30, # Bonds - 30%
"VNQ": 0.10 # REITs - 10%
}
portfolio_id = platform.create_portfolio_strategy(
"Conservative Growth",
conservative_allocation
)
# Subscribe to portfolio
platform.subscribe_to_portfolio(account_id, portfolio_id, 8000.00)
# Execute some trades
platform.execute_trade(account_id, "AAPL", 10, "BUY")
platform.execute_trade(account_id, "MSFT", 15, "BUY")
# Get summary
summary = platform.get_customer_summary(account_id)
print(f"\n📋 Customer Summary:")
print(f"Account: {summary['account_number']}")
print(f"Status: {summary['status']}")
print(f"ACH Relationships: {summary['ach_relationships']}")
print(f"Recent Transfers: {summary['recent_transfers']}")
print(f"Total Orders: {summary['total_orders']}")
print(f"Created: {summary['created_at'].date()}")Install with Tessl CLI
npx tessl i tessl/pypi-alpaca-py