0
# Broker Client
1
2
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.
3
4
## Core Client
5
6
### BrokerClient
7
8
```python { .api }
9
from alpaca.broker import BrokerClient
10
11
class BrokerClient(RESTClient):
12
def __init__(
13
self,
14
api_key: Optional[str] = None,
15
secret_key: Optional[str] = None,
16
oauth_token: Optional[str] = None,
17
use_basic_auth: bool = False,
18
raw_data: bool = False,
19
url_override: Optional[str] = None,
20
sandbox: bool = False,
21
) -> None:
22
"""
23
Initialize broker client for account management.
24
25
Args:
26
api_key: Broker API key
27
secret_key: Broker API secret key
28
oauth_token: OAuth token for user-on-behalf operations
29
use_basic_auth: Use basic authentication headers
30
raw_data: Return raw API responses instead of models
31
url_override: Override base URL for testing
32
sandbox: Use sandbox environment for testing
33
"""
34
```
35
36
#### Basic Setup
37
38
```python { .api }
39
# Production broker client
40
broker_client = BrokerClient(
41
api_key="your-broker-api-key",
42
secret_key="your-broker-secret-key",
43
use_basic_auth=True
44
)
45
46
# Sandbox broker client for testing
47
broker_client = BrokerClient(
48
api_key="sandbox-api-key",
49
secret_key="sandbox-secret-key",
50
use_basic_auth=True,
51
sandbox=True
52
)
53
54
# OAuth-based client for user-on-behalf operations
55
broker_client = BrokerClient(
56
oauth_token="user-oauth-token",
57
sandbox=True
58
)
59
```
60
61
## Account Management
62
63
### Account Creation
64
65
#### create_account()
66
67
```python { .api }
68
def create_account(
69
self,
70
account_data: CreateAccountRequest
71
) -> Union[Account, RawData]:
72
"""
73
Create a new customer brokerage account.
74
75
Args:
76
account_data: Account creation parameters including identity, contact, and disclosures
77
78
Returns:
79
Account: Created account with assigned ID and status
80
"""
81
```
82
83
#### CreateAccountRequest
84
85
```python { .api }
86
from alpaca.broker.requests import CreateAccountRequest
87
from alpaca.broker.models import Contact, Identity, Disclosures, TrustedContact
88
from datetime import date
89
90
class CreateAccountRequest(NonEmptyRequest):
91
def __init__(
92
self,
93
contact: Contact, # Required: Contact information
94
identity: Identity, # Required: Identity information
95
disclosures: Disclosures, # Required: Regulatory disclosures
96
agreements: List[AgreementType], # Required: Signed agreements
97
documents: Optional[List[AccountDocument]] = None, # Supporting documents
98
trusted_contact: Optional[TrustedContact] = None, # Trusted contact person
99
enabled_assets: Optional[List[AssetClass]] = None, # Tradeable asset classes
100
currency: Optional[str] = None, # Account currency (USD)
101
max_options_trading_level: Optional[int] = None # Options trading level (0-4)
102
):
103
```
104
105
### Core Account Models
106
107
#### Contact Model
108
109
```python { .api }
110
from alpaca.broker.models import Contact
111
112
class Contact:
113
"""Customer contact information."""
114
115
email_address: str # Email address
116
phone_number: str # Phone number with country code
117
street_address: List[str] # Street address lines
118
unit: Optional[str] # Apartment/unit number
119
city: str # City
120
state: str # State/province
121
postal_code: str # ZIP/postal code
122
country: Optional[str] # Country code (defaults to USA)
123
```
124
125
#### Identity Model
126
127
```python { .api }
128
from alpaca.broker.models import Identity
129
from alpaca.broker.enums import TaxIdType, EmploymentStatus, FundingSource
130
131
class Identity:
132
"""Customer identity information."""
133
134
given_name: str # First name
135
middle_name: Optional[str] # Middle name
136
family_name: str # Last name
137
date_of_birth: date # Date of birth
138
tax_id: Optional[str] # SSN/ITIN/EIN
139
tax_id_type: Optional[TaxIdType] # Type of tax ID
140
country_of_citizenship: Optional[str] # Citizenship country
141
country_of_birth: Optional[str] # Birth country
142
country_of_tax_residence: Optional[str] # Tax residence country
143
funding_source: Optional[List[FundingSource]] # Source of funds
144
annual_income_min: Optional[int] # Minimum annual income
145
annual_income_max: Optional[int] # Maximum annual income
146
liquid_net_worth_min: Optional[int] # Minimum liquid net worth
147
liquid_net_worth_max: Optional[int] # Maximum liquid net worth
148
total_net_worth_min: Optional[int] # Minimum total net worth
149
total_net_worth_max: Optional[int] # Maximum total net worth
150
employment_status: Optional[EmploymentStatus] # Employment status
151
employer_name: Optional[str] # Employer name
152
employer_address: Optional[str] # Employer address
153
employment_position: Optional[str] # Job title/position
154
```
155
156
#### Disclosures Model
157
158
```python { .api }
159
from alpaca.broker.models import Disclosures
160
161
class Disclosures:
162
"""Regulatory disclosure responses."""
163
164
is_control_person: bool # Control person of public company
165
is_affiliated_exchange_or_finra: bool # FINRA/exchange affiliation
166
is_politically_exposed: bool # Politically exposed person
167
immediate_family_exposed: bool # Family politically exposed
168
is_discretionary_investment: bool # Discretionary investment authority
169
employment_details: Optional[str] # Employment disclosure details
170
employer_details: Optional[str] # Employer disclosure details
171
investment_experience: Optional[str] # Investment experience level
172
investment_objectives: Optional[List[str]] # Investment objectives
173
source_of_funds: Optional[List[str]] # Source of funds details
174
```
175
176
**Account Creation Example:**
177
178
```python { .api }
179
from alpaca.broker.requests import CreateAccountRequest
180
from alpaca.broker.models import Contact, Identity, Disclosures
181
from alpaca.broker.enums import TaxIdType, EmploymentStatus, FundingSource, AgreementType
182
from datetime import date
183
184
# Create account request
185
account_request = CreateAccountRequest(
186
contact=Contact(
187
email_address="customer@example.com",
188
phone_number="+1-555-123-4567",
189
street_address=["123 Main Street"],
190
city="New York",
191
state="NY",
192
postal_code="10001"
193
),
194
195
identity=Identity(
196
given_name="John",
197
family_name="Doe",
198
date_of_birth=date(1990, 5, 15),
199
tax_id="123456789",
200
tax_id_type=TaxIdType.USA_SSN,
201
country_of_citizenship="USA",
202
annual_income_min=50000,
203
annual_income_max=75000,
204
liquid_net_worth_min=10000,
205
liquid_net_worth_max=25000,
206
employment_status=EmploymentStatus.EMPLOYED,
207
funding_source=[FundingSource.EMPLOYMENT_INCOME]
208
),
209
210
disclosures=Disclosures(
211
is_control_person=False,
212
is_affiliated_exchange_or_finra=False,
213
is_politically_exposed=False,
214
immediate_family_exposed=False,
215
is_discretionary_investment=False
216
),
217
218
agreements=[
219
AgreementType.ACCOUNT_AGREEMENT,
220
AgreementType.CUSTOMER_AGREEMENT
221
],
222
223
enabled_assets=[AssetClass.US_EQUITY],
224
max_options_trading_level=0 # No options trading
225
)
226
227
# Create the account
228
account = broker_client.create_account(account_request)
229
print(f"Account created: {account.id}")
230
print(f"Account number: {account.account_number}")
231
print(f"Status: {account.status}")
232
```
233
234
### Account Querying
235
236
#### list_accounts()
237
238
```python { .api }
239
def list_accounts(
240
self,
241
search_parameters: Optional[ListAccountsRequest] = None
242
) -> Union[List[Account], RawData]:
243
"""
244
List customer accounts with optional filtering.
245
246
Args:
247
search_parameters: Account filtering criteria
248
249
Returns:
250
List[Account]: List of accounts matching criteria
251
"""
252
```
253
254
#### get_account_by_id()
255
256
```python { .api }
257
def get_account_by_id(
258
self,
259
account_id: Union[UUID, str]
260
) -> Union[Account, RawData]:
261
"""
262
Get specific account by ID.
263
264
Args:
265
account_id: Account UUID
266
267
Returns:
268
Account: Account details
269
"""
270
```
271
272
#### ListAccountsRequest
273
274
```python { .api }
275
from alpaca.broker.requests import ListAccountsRequest
276
from alpaca.trading.enums import AccountStatus
277
from datetime import datetime
278
279
class ListAccountsRequest(NonEmptyRequest):
280
def __init__(
281
self,
282
query: Optional[str] = None, # Search query (name, email, etc.)
283
created_after: Optional[datetime] = None, # Created after timestamp
284
created_before: Optional[datetime] = None, # Created before timestamp
285
status: Optional[AccountStatus] = None, # Account status filter
286
sort: Optional[str] = None, # Sort field
287
entities: Optional[str] = None, # Additional entities to include
288
limit: Optional[int] = None, # Maximum accounts to return
289
page_token: Optional[str] = None # Pagination token
290
):
291
```
292
293
**Account Querying Examples:**
294
295
```python { .api }
296
# List all accounts
297
accounts = broker_client.list_accounts()
298
print(f"Total accounts: {len(accounts)}")
299
300
# Search for specific customer
301
search_results = broker_client.list_accounts(
302
ListAccountsRequest(
303
query="john.doe@example.com",
304
limit=10
305
)
306
)
307
308
# Filter by status and date
309
active_accounts = broker_client.list_accounts(
310
ListAccountsRequest(
311
status=AccountStatus.ACTIVE,
312
created_after=datetime.now() - timedelta(days=30),
313
sort="created_at"
314
)
315
)
316
317
# Get specific account
318
account = broker_client.get_account_by_id("account-uuid-here")
319
print(f"Account {account.account_number}: {account.status}")
320
```
321
322
### Account Updates
323
324
#### update_account()
325
326
```python { .api }
327
def update_account(
328
self,
329
account_id: Union[UUID, str],
330
account_data: UpdateAccountRequest,
331
) -> Union[Account, RawData]:
332
"""
333
Update existing account information.
334
335
Args:
336
account_id: Account UUID to update
337
account_data: Updated account fields
338
339
Returns:
340
Account: Updated account
341
"""
342
```
343
344
#### UpdateAccountRequest
345
346
```python { .api }
347
from alpaca.broker.requests import UpdateAccountRequest
348
349
class UpdateAccountRequest(NonEmptyRequest):
350
def __init__(
351
self,
352
contact: Optional[Contact] = None, # Updated contact info
353
identity: Optional[Identity] = None, # Updated identity info
354
disclosures: Optional[Disclosures] = None, # Updated disclosures
355
trusted_contact: Optional[TrustedContact] = None, # Updated trusted contact
356
enabled_assets: Optional[List[AssetClass]] = None, # Updated tradeable assets
357
max_options_trading_level: Optional[int] = None # Updated options level
358
):
359
```
360
361
**Account Update Examples:**
362
363
```python { .api }
364
# Update contact information
365
updated_contact = Contact(
366
email_address="newemail@example.com",
367
phone_number="+1-555-987-6543",
368
street_address=["456 New Street"],
369
city="San Francisco",
370
state="CA",
371
postal_code="94102"
372
)
373
374
update_request = UpdateAccountRequest(contact=updated_contact)
375
updated_account = broker_client.update_account(account_id, update_request)
376
377
# Enable options trading
378
options_update = UpdateAccountRequest(
379
max_options_trading_level=2, # Level 2 options
380
enabled_assets=[AssetClass.US_EQUITY, AssetClass.US_OPTION]
381
)
382
updated_account = broker_client.update_account(account_id, options_update)
383
```
384
385
## Funding Operations
386
387
### ACH Relationships
388
389
#### create_ach_relationship()
390
391
```python { .api }
392
def create_ach_relationship(
393
self,
394
account_id: Union[UUID, str],
395
ach_data: CreateACHRelationshipRequest,
396
) -> Union[ACHRelationship, RawData]:
397
"""
398
Create ACH bank relationship for transfers.
399
400
Args:
401
account_id: Customer account UUID
402
ach_data: ACH relationship parameters
403
404
Returns:
405
ACHRelationship: Created ACH relationship
406
"""
407
```
408
409
#### CreateACHRelationshipRequest
410
411
```python { .api }
412
from alpaca.broker.requests import CreateACHRelationshipRequest
413
from alpaca.broker.enums import BankAccountType
414
415
class CreateACHRelationshipRequest(NonEmptyRequest):
416
def __init__(
417
self,
418
account_owner_name: str, # Account owner name
419
bank_account_type: BankAccountType, # CHECKING or SAVINGS
420
bank_account_number: str, # Bank account number
421
bank_routing_number: str, # Bank routing number
422
nickname: Optional[str] = None # Relationship nickname
423
):
424
```
425
426
#### create_plaid_relationship()
427
428
```python { .api }
429
def create_plaid_relationship(
430
self,
431
account_id: Union[UUID, str],
432
plaid_data: CreatePlaidRelationshipRequest,
433
) -> Union[ACHRelationship, RawData]:
434
"""
435
Create ACH relationship via Plaid Link.
436
437
Args:
438
account_id: Customer account UUID
439
plaid_data: Plaid integration parameters
440
441
Returns:
442
ACHRelationship: Created ACH relationship via Plaid
443
"""
444
```
445
446
#### get_ach_relationships()
447
448
```python { .api }
449
def get_ach_relationships(
450
self,
451
account_id: Union[UUID, str]
452
) -> Union[List[ACHRelationship], RawData]:
453
"""
454
Get ACH relationships for account.
455
456
Args:
457
account_id: Customer account UUID
458
459
Returns:
460
List[ACHRelationship]: ACH relationships for the account
461
"""
462
```
463
464
#### delete_ach_relationship()
465
466
```python { .api }
467
def delete_ach_relationship(
468
self,
469
account_id: Union[UUID, str],
470
ach_relationship_id: Union[UUID, str],
471
) -> None:
472
"""
473
Delete ACH relationship.
474
475
Args:
476
account_id: Customer account UUID
477
ach_relationship_id: ACH relationship UUID to delete
478
"""
479
```
480
481
#### ACHRelationship Model
482
483
```python { .api }
484
from alpaca.broker.models import ACHRelationship
485
from alpaca.broker.enums import ACHRelationshipStatus, BankAccountType
486
487
class ACHRelationship:
488
"""ACH bank relationship for transfers."""
489
490
id: UUID # Relationship UUID
491
account_id: UUID # Customer account UUID
492
account_owner_name: str # Account owner name
493
bank_account_type: BankAccountType # CHECKING or SAVINGS
494
bank_account_number: str # Masked account number
495
bank_routing_number: str # Bank routing number
496
nickname: Optional[str] # Relationship nickname
497
status: ACHRelationshipStatus # Relationship status
498
created_at: datetime # Creation timestamp
499
```
500
501
**ACH Relationship Examples:**
502
503
```python { .api }
504
from alpaca.broker.enums import BankAccountType
505
506
# Create ACH relationship manually
507
ach_request = CreateACHRelationshipRequest(
508
account_owner_name="John Doe",
509
bank_account_type=BankAccountType.CHECKING,
510
bank_account_number="1234567890",
511
bank_routing_number="021000021", # Chase routing number
512
nickname="Primary Checking"
513
)
514
515
ach_relationship = broker_client.create_ach_relationship(account_id, ach_request)
516
print(f"ACH relationship created: {ach_relationship.id}")
517
print(f"Status: {ach_relationship.status}")
518
519
# List ACH relationships for account
520
relationships = broker_client.get_ach_relationships(account_id)
521
for rel in relationships:
522
print(f"{rel.nickname}: {rel.bank_account_type} ending in {rel.bank_account_number[-4:]}")
523
```
524
525
### Money Transfers
526
527
#### create_ach_transfer()
528
529
```python { .api }
530
def create_ach_transfer(
531
self,
532
account_id: Union[UUID, str],
533
transfer_data: CreateACHTransferRequest,
534
) -> Union[Transfer, RawData]:
535
"""
536
Create ACH transfer (deposit or withdrawal).
537
538
Args:
539
account_id: Customer account UUID
540
transfer_data: Transfer parameters
541
542
Returns:
543
Transfer: Created transfer with status
544
"""
545
```
546
547
#### CreateACHTransferRequest
548
549
```python { .api }
550
from alpaca.broker.requests import CreateACHTransferRequest
551
from alpaca.broker.enums import TransferDirection, TransferTiming
552
553
class CreateACHTransferRequest(NonEmptyRequest):
554
def __init__(
555
self,
556
relationship_id: Union[UUID, str], # ACH relationship UUID
557
amount: float, # Transfer amount
558
direction: TransferDirection, # INCOMING or OUTGOING
559
timing: Optional[TransferTiming] = None, # IMMEDIATE or NEXT_BUSINESS_DAY
560
fee_payment_method: Optional[str] = None # Fee payment method
561
):
562
```
563
564
#### get_transfers()
565
566
```python { .api }
567
def get_transfers(
568
self,
569
account_id: Union[UUID, str],
570
transfer_data: Optional[GetTransfersRequest] = None,
571
) -> Union[List[Transfer], RawData]:
572
"""
573
Get transfers for account with optional filtering.
574
575
Args:
576
account_id: Customer account UUID
577
transfer_data: Transfer query parameters
578
579
Returns:
580
List[Transfer]: Account transfers
581
"""
582
```
583
584
#### cancel_transfer()
585
586
```python { .api }
587
def cancel_transfer(
588
self,
589
account_id: Union[UUID, str],
590
transfer_id: Union[UUID, str],
591
) -> None:
592
"""
593
Cancel pending transfer.
594
595
Args:
596
account_id: Customer account UUID
597
transfer_id: Transfer UUID to cancel
598
"""
599
```
600
601
#### Transfer Model
602
603
```python { .api }
604
from alpaca.broker.models import Transfer
605
from alpaca.broker.enums import TransferDirection, TransferStatus, TransferType
606
607
class Transfer:
608
"""Money transfer information."""
609
610
id: UUID # Transfer UUID
611
account_id: UUID # Customer account UUID
612
relationship_id: UUID # ACH relationship UUID
613
amount: float # Transfer amount
614
direction: TransferDirection # INCOMING or OUTGOING
615
type: TransferType # ACH, WIRE, CHECK
616
status: TransferStatus # Transfer status
617
reason: Optional[str] # Transfer reason/description
618
requested_at: datetime # Request timestamp
619
effective_at: Optional[datetime] # Effective date
620
expires_at: Optional[datetime] # Expiration date
621
fee: Optional[float] # Transfer fee
622
additional_information: Optional[str] # Additional details
623
```
624
625
**Transfer Examples:**
626
627
```python { .api }
628
from alpaca.broker.enums import TransferDirection
629
630
# Deposit funds (incoming transfer)
631
deposit_request = CreateACHTransferRequest(
632
relationship_id=ach_relationship.id,
633
amount=5000.00,
634
direction=TransferDirection.INCOMING
635
)
636
637
deposit = broker_client.create_ach_transfer(account_id, deposit_request)
638
print(f"Deposit initiated: ${deposit.amount} (Status: {deposit.status})")
639
640
# Withdraw funds (outgoing transfer)
641
withdrawal_request = CreateACHTransferRequest(
642
relationship_id=ach_relationship.id,
643
amount=1000.00,
644
direction=TransferDirection.OUTGOING
645
)
646
647
withdrawal = broker_client.create_ach_transfer(account_id, withdrawal_request)
648
print(f"Withdrawal initiated: ${withdrawal.amount}")
649
650
# Get transfer history
651
transfers = broker_client.get_transfers(account_id)
652
for transfer in transfers:
653
direction_str = "Deposit" if transfer.direction == TransferDirection.INCOMING else "Withdrawal"
654
print(f"{direction_str}: ${transfer.amount} - {transfer.status} ({transfer.requested_at.date()})")
655
```
656
657
## Trading Operations
658
659
### Order Management for Broker Accounts
660
661
#### submit_order()
662
663
```python { .api }
664
def submit_order(
665
self,
666
account_id: Union[UUID, str],
667
order_data: OrderRequest,
668
) -> Union[Order, RawData]:
669
"""
670
Submit order for customer account.
671
672
Args:
673
account_id: Customer account UUID
674
order_data: Order parameters (same as trading client)
675
676
Returns:
677
Order: Submitted order
678
"""
679
```
680
681
#### get_orders_for_account()
682
683
```python { .api }
684
def get_orders_for_account(
685
self,
686
account_id: Union[UUID, str]
687
) -> Union[List[Order], RawData]:
688
"""
689
Get orders for specific customer account.
690
691
Args:
692
account_id: Customer account UUID
693
694
Returns:
695
List[Order]: Orders for the account
696
"""
697
```
698
699
**Broker Trading Examples:**
700
701
```python { .api }
702
from alpaca.trading.requests import MarketOrderRequest
703
from alpaca.trading.enums import OrderSide, TimeInForce
704
705
# Submit order for customer account
706
customer_order = MarketOrderRequest(
707
symbol="AAPL",
708
qty=100,
709
side=OrderSide.BUY,
710
time_in_force=TimeInForce.DAY
711
)
712
713
order = broker_client.submit_order(account_id, customer_order)
714
print(f"Order submitted for customer: {order.id}")
715
716
# Get customer's orders
717
customer_orders = broker_client.get_orders_for_account(account_id)
718
print(f"Customer has {len(customer_orders)} orders")
719
```
720
721
## Document Management
722
723
### Document Upload and Retrieval
724
725
#### upload_document()
726
727
```python { .api }
728
def upload_document(
729
self,
730
account_id: Union[UUID, str],
731
document_data: UploadDocumentRequest,
732
) -> Union[AccountDocument, RawData]:
733
"""
734
Upload document for account.
735
736
Args:
737
account_id: Customer account UUID
738
document_data: Document upload parameters
739
740
Returns:
741
AccountDocument: Uploaded document information
742
"""
743
```
744
745
#### get_documents()
746
747
```python { .api }
748
def get_documents(
749
self,
750
account_id: Union[UUID, str]
751
) -> Union[List[AccountDocument], RawData]:
752
"""
753
Get documents for account.
754
755
Args:
756
account_id: Customer account UUID
757
758
Returns:
759
List[AccountDocument]: Account documents
760
"""
761
```
762
763
#### download_document()
764
765
```python { .api }
766
def download_document(
767
self,
768
account_id: Union[UUID, str],
769
document_id: Union[UUID, str],
770
) -> bytes:
771
"""
772
Download document content.
773
774
Args:
775
account_id: Customer account UUID
776
document_id: Document UUID
777
778
Returns:
779
bytes: Document content
780
"""
781
```
782
783
### Trade Documents
784
785
#### get_trade_documents()
786
787
```python { .api }
788
def get_trade_documents(
789
self,
790
account_id: Union[UUID, str],
791
request: Optional[GetTradeDocumentsRequest] = None,
792
) -> Union[List[TradeDocument], RawData]:
793
"""
794
Get trade confirmation and statement documents.
795
796
Args:
797
account_id: Customer account UUID
798
request: Trade document filtering parameters
799
800
Returns:
801
List[TradeDocument]: Trade documents
802
"""
803
```
804
805
**Document Management Examples:**
806
807
```python { .api }
808
# Upload identity document
809
with open("customer_id.pdf", "rb") as f:
810
document_content = f.read()
811
812
upload_request = UploadDocumentRequest(
813
document_type="identity_verification",
814
content=base64.b64encode(document_content).decode(),
815
mime_type="application/pdf"
816
)
817
818
document = broker_client.upload_document(account_id, upload_request)
819
print(f"Document uploaded: {document.id}")
820
821
# Get all documents for account
822
documents = broker_client.get_documents(account_id)
823
for doc in documents:
824
print(f"{doc.document_type}: {doc.name} (uploaded: {doc.created_at})")
825
826
# Get trade confirmations
827
trade_docs = broker_client.get_trade_documents(account_id)
828
for doc in trade_docs:
829
print(f"Trade document: {doc.name} ({doc.date})")
830
```
831
832
## Journal Entries
833
834
Journal entries allow moving cash or securities between accounts.
835
836
### Cash Journals
837
838
#### create_journal()
839
840
```python { .api }
841
def create_journal(
842
self,
843
journal_data: CreateJournalRequest
844
) -> Union[Journal, RawData]:
845
"""
846
Create journal entry to move cash between accounts.
847
848
Args:
849
journal_data: Journal entry parameters
850
851
Returns:
852
Journal: Created journal entry
853
"""
854
```
855
856
#### CreateJournalRequest
857
858
```python { .api }
859
from alpaca.broker.requests import CreateJournalRequest
860
from alpaca.broker.enums import JournalEntryType
861
from datetime import date
862
863
class CreateJournalRequest(NonEmptyRequest):
864
def __init__(
865
self,
866
entry_type: JournalEntryType, # JNLC (cash) or JNLS (securities)
867
from_account: Union[UUID, str], # Source account UUID
868
to_account: Union[UUID, str], # Destination account UUID
869
amount: Optional[float] = None, # Cash amount (for JNLC)
870
symbol: Optional[str] = None, # Securities symbol (for JNLS)
871
qty: Optional[float] = None, # Securities quantity (for JNLS)
872
price: Optional[float] = None, # Securities price (for JNLS)
873
settle_date: Optional[date] = None, # Settlement date
874
description: Optional[str] = None # Journal description
875
):
876
```
877
878
### Batch Journals
879
880
#### create_batch_journal()
881
882
```python { .api }
883
def create_batch_journal(
884
self,
885
journal_data: CreateBatchJournalRequest
886
) -> Union[BatchJournalResponse, RawData]:
887
"""
888
Create multiple journal entries in a batch.
889
890
Args:
891
journal_data: Batch journal parameters
892
893
Returns:
894
BatchJournalResponse: Batch creation results
895
"""
896
```
897
898
#### get_journals()
899
900
```python { .api }
901
def get_journals(
902
self,
903
journal_data: Optional[GetJournalsRequest] = None
904
) -> Union[List[Journal], RawData]:
905
"""
906
Get journal entries with optional filtering.
907
908
Args:
909
journal_data: Journal query parameters
910
911
Returns:
912
List[Journal]: Journal entries
913
"""
914
```
915
916
#### Journal Model
917
918
```python { .api }
919
from alpaca.broker.models import Journal
920
from alpaca.broker.enums import JournalEntryType, JournalStatus
921
922
class Journal:
923
"""Journal entry for moving cash or securities between accounts."""
924
925
id: UUID # Journal UUID
926
entry_type: JournalEntryType # JNLC (cash) or JNLS (securities)
927
from_account: UUID # Source account UUID
928
to_account: UUID # Destination account UUID
929
status: JournalStatus # Journal status
930
settle_date: Optional[date] # Settlement date
931
system_date: Optional[date] # System processing date
932
net_amount: Optional[float] # Net cash amount
933
amount: Optional[float] # Gross amount
934
symbol: Optional[str] # Securities symbol
935
qty: Optional[float] # Securities quantity
936
price: Optional[float] # Securities price
937
description: Optional[str] # Description
938
created_at: datetime # Creation timestamp
939
```
940
941
**Journal Examples:**
942
943
```python { .api }
944
from alpaca.broker.enums import JournalEntryType
945
946
# Transfer cash between accounts
947
cash_journal = CreateJournalRequest(
948
entry_type=JournalEntryType.JNLC, # Cash journal
949
from_account="source-account-uuid",
950
to_account="destination-account-uuid",
951
amount=1000.00,
952
description="Customer cash transfer"
953
)
954
955
journal = broker_client.create_journal(cash_journal)
956
print(f"Cash journal created: {journal.id} (${journal.amount})")
957
958
# Transfer securities between accounts
959
securities_journal = CreateJournalRequest(
960
entry_type=JournalEntryType.JNLS, # Securities journal
961
from_account="source-account-uuid",
962
to_account="destination-account-uuid",
963
symbol="AAPL",
964
qty=100,
965
price=175.00,
966
description="AAPL share transfer"
967
)
968
969
securities_journal_entry = broker_client.create_journal(securities_journal)
970
print(f"Securities journal created: {securities_journal_entry.id}")
971
972
# Get journal history
973
journals = broker_client.get_journals()
974
for journal in journals:
975
if journal.entry_type == JournalEntryType.JNLC:
976
print(f"Cash: ${journal.amount} from {journal.from_account} to {journal.to_account}")
977
else:
978
print(f"Securities: {journal.qty} {journal.symbol} @ ${journal.price}")
979
```
980
981
## Portfolio Management & Rebalancing
982
983
### Portfolio Creation
984
985
#### create_portfolio()
986
987
```python { .api }
988
def create_portfolio(
989
self,
990
portfolio_data: CreatePortfolioRequest
991
) -> Union[Portfolio, RawData]:
992
"""
993
Create portfolio strategy for rebalancing.
994
995
Args:
996
portfolio_data: Portfolio creation parameters
997
998
Returns:
999
Portfolio: Created portfolio strategy
1000
"""
1001
```
1002
1003
#### CreatePortfolioRequest
1004
1005
```python { .api }
1006
from alpaca.broker.requests import CreatePortfolioRequest
1007
from alpaca.broker.enums import WeightType
1008
1009
class CreatePortfolioRequest(NonEmptyRequest):
1010
def __init__(
1011
self,
1012
name: str, # Portfolio name
1013
description: Optional[str] = None, # Portfolio description
1014
weights: Dict[str, float], # Asset allocation weights
1015
weight_type: WeightType = WeightType.PERCENT, # PERCENT or DOLLAR
1016
cooldown_days: Optional[int] = None, # Rebalancing cooldown period
1017
schedule: Optional[str] = None, # Rebalancing schedule
1018
max_accounts_per_day: Optional[int] = None # Max accounts to rebalance per day
1019
):
1020
```
1021
1022
#### get_portfolios()
1023
1024
```python { .api }
1025
def get_portfolios(
1026
self,
1027
request: Optional[GetPortfoliosRequest] = None
1028
) -> Union[List[Portfolio], RawData]:
1029
"""
1030
Get portfolio strategies with optional filtering.
1031
1032
Args:
1033
request: Portfolio query parameters
1034
1035
Returns:
1036
List[Portfolio]: Portfolio strategies
1037
"""
1038
```
1039
1040
### Account Subscriptions
1041
1042
#### create_subscription()
1043
1044
```python { .api }
1045
def create_subscription(
1046
self,
1047
subscription_data: CreateSubscriptionRequest
1048
) -> Union[Subscription, RawData]:
1049
"""
1050
Subscribe account to portfolio strategy.
1051
1052
Args:
1053
subscription_data: Subscription parameters
1054
1055
Returns:
1056
Subscription: Created subscription
1057
"""
1058
```
1059
1060
#### CreateSubscriptionRequest
1061
1062
```python { .api }
1063
from alpaca.broker.requests import CreateSubscriptionRequest
1064
1065
class CreateSubscriptionRequest(NonEmptyRequest):
1066
def __init__(
1067
self,
1068
account_id: Union[UUID, str], # Customer account UUID
1069
portfolio_id: Union[UUID, str], # Portfolio strategy UUID
1070
max_investment_amount: Optional[float] = None, # Maximum investment
1071
cash_percentage: Optional[float] = None # Cash allocation percentage
1072
):
1073
```
1074
1075
### Rebalancing Runs
1076
1077
#### create_run()
1078
1079
```python { .api }
1080
def create_run(
1081
self,
1082
run_data: CreateRunRequest
1083
) -> Union[RebalancingRun, RawData]:
1084
"""
1085
Execute portfolio rebalancing run.
1086
1087
Args:
1088
run_data: Rebalancing run parameters
1089
1090
Returns:
1091
RebalancingRun: Rebalancing execution results
1092
"""
1093
```
1094
1095
#### CreateRunRequest
1096
1097
```python { .api }
1098
from alpaca.broker.requests import CreateRunRequest
1099
from alpaca.broker.enums import RunType
1100
1101
class CreateRunRequest(NonEmptyRequest):
1102
def __init__(
1103
self,
1104
type: RunType, # FULL_REBALANCE or DRIFT_REBALANCE
1105
portfolio_id: Union[UUID, str], # Portfolio strategy UUID
1106
account_ids: Optional[List[Union[UUID, str]]] = None, # Specific accounts to rebalance
1107
notify: Optional[bool] = None, # Send notifications
1108
max_accounts_per_day: Optional[int] = None # Limit accounts per day
1109
):
1110
```
1111
1112
**Portfolio Management Examples:**
1113
1114
```python { .api }
1115
from alpaca.broker.enums import WeightType, RunType
1116
1117
# Create balanced portfolio strategy
1118
portfolio_request = CreatePortfolioRequest(
1119
name="Conservative Balanced",
1120
description="60% stocks, 40% bonds conservative allocation",
1121
weights={
1122
"SPY": 0.30, # S&P 500 ETF - 30%
1123
"VTI": 0.30, # Total Stock Market - 30%
1124
"BND": 0.25, # Bond ETF - 25%
1125
"VTEB": 0.15 # Municipal Bond ETF - 15%
1126
},
1127
weight_type=WeightType.PERCENT,
1128
cooldown_days=30 # Rebalance at most once per month
1129
)
1130
1131
portfolio = broker_client.create_portfolio(portfolio_request)
1132
print(f"Portfolio created: {portfolio.id} - {portfolio.name}")
1133
1134
# Subscribe customer account to portfolio
1135
subscription_request = CreateSubscriptionRequest(
1136
account_id="customer-account-uuid",
1137
portfolio_id=portfolio.id,
1138
max_investment_amount=50000.00, # Max $50k investment
1139
cash_percentage=0.05 # Keep 5% in cash
1140
)
1141
1142
subscription = broker_client.create_subscription(subscription_request)
1143
print(f"Account subscribed to portfolio: {subscription.id}")
1144
1145
# Execute rebalancing run
1146
run_request = CreateRunRequest(
1147
type=RunType.FULL_REBALANCE,
1148
portfolio_id=portfolio.id,
1149
account_ids=[subscription.account_id], # Rebalance specific account
1150
notify=True
1151
)
1152
1153
rebalancing_run = broker_client.create_run(run_request)
1154
print(f"Rebalancing run initiated: {rebalancing_run.id}")
1155
print(f"Status: {rebalancing_run.status}")
1156
```
1157
1158
## CIP (Customer Identification Program)
1159
1160
### KYC and Identity Verification
1161
1162
The broker client includes comprehensive KYC/AML functionality:
1163
1164
#### CIP Models
1165
1166
```python { .api }
1167
from alpaca.broker.models.cip import (
1168
CIPKYCInfo, CIPDocument, CIPPhoto, CIPIdentity,
1169
CIPWatchlist, CIPInfo
1170
)
1171
1172
class CIPInfo:
1173
"""Overall Customer Identification Program status."""
1174
1175
kyc: Optional[CIPKYCInfo] # KYC verification results
1176
identity: Optional[CIPIdentity] # Identity verification results
1177
watchlist: Optional[CIPWatchlist] # Watchlist screening results
1178
patriot_act: Optional[dict] # USA PATRIOT Act verification
1179
```
1180
1181
### Account Activities
1182
1183
#### get_account_activities()
1184
1185
```python { .api }
1186
def get_account_activities(
1187
self,
1188
account_id: Union[UUID, str],
1189
request: Optional[GetAccountActivitiesRequest] = None,
1190
) -> Union[List[BaseActivity], RawData]:
1191
"""
1192
Get account activities (trades, dividends, etc.).
1193
1194
Args:
1195
account_id: Customer account UUID
1196
request: Activity filtering parameters
1197
1198
Returns:
1199
List[BaseActivity]: Account activities
1200
"""
1201
```
1202
1203
## Error Handling
1204
1205
```python { .api }
1206
from alpaca.common.exceptions import APIError
1207
1208
try:
1209
# Create account that might fail validation
1210
account = broker_client.create_account(account_request)
1211
except APIError as e:
1212
if e.status_code == 400:
1213
print(f"Invalid account data: {e.message}")
1214
elif e.status_code == 409:
1215
print("Account already exists with this information")
1216
elif e.status_code == 422:
1217
print(f"Validation error: {e.message}")
1218
else:
1219
print(f"API error: {e.message} (status: {e.status_code})")
1220
except Exception as e:
1221
print(f"Unexpected error: {e}")
1222
```
1223
1224
## Complete Broker Integration Example
1225
1226
```python { .api }
1227
from datetime import date, datetime, timedelta
1228
from alpaca.broker import BrokerClient
1229
from alpaca.broker.requests import *
1230
from alpaca.broker.models import *
1231
from alpaca.broker.enums import *
1232
from alpaca.trading.requests import MarketOrderRequest
1233
from alpaca.trading.enums import OrderSide, TimeInForce
1234
1235
class BrokerPlatform:
1236
def __init__(self, api_key: str, secret_key: str, sandbox: bool = True):
1237
self.client = BrokerClient(
1238
api_key=api_key,
1239
secret_key=secret_key,
1240
use_basic_auth=True,
1241
sandbox=sandbox
1242
)
1243
1244
def onboard_customer(self, customer_info: dict) -> str:
1245
"""Complete customer onboarding workflow."""
1246
1247
print("š Starting customer onboarding...")
1248
1249
# Step 1: Create account
1250
account_request = CreateAccountRequest(
1251
contact=Contact(
1252
email_address=customer_info["email"],
1253
phone_number=customer_info["phone"],
1254
street_address=[customer_info["address"]],
1255
city=customer_info["city"],
1256
state=customer_info["state"],
1257
postal_code=customer_info["zip_code"]
1258
),
1259
1260
identity=Identity(
1261
given_name=customer_info["first_name"],
1262
family_name=customer_info["last_name"],
1263
date_of_birth=customer_info["date_of_birth"],
1264
tax_id=customer_info["ssn"],
1265
tax_id_type=TaxIdType.USA_SSN,
1266
annual_income_min=customer_info["income_min"],
1267
annual_income_max=customer_info["income_max"],
1268
employment_status=EmploymentStatus.EMPLOYED,
1269
funding_source=[FundingSource.EMPLOYMENT_INCOME]
1270
),
1271
1272
disclosures=Disclosures(
1273
is_control_person=False,
1274
is_affiliated_exchange_or_finra=False,
1275
is_politically_exposed=False,
1276
immediate_family_exposed=False,
1277
is_discretionary_investment=False
1278
),
1279
1280
agreements=[
1281
AgreementType.ACCOUNT_AGREEMENT,
1282
AgreementType.CUSTOMER_AGREEMENT
1283
],
1284
1285
enabled_assets=[AssetClass.US_EQUITY]
1286
)
1287
1288
account = self.client.create_account(account_request)
1289
print(f"ā Account created: {account.account_number}")
1290
1291
return str(account.id)
1292
1293
def setup_funding(self, account_id: str, bank_info: dict) -> str:
1294
"""Set up bank relationship and initial funding."""
1295
1296
print("š° Setting up funding...")
1297
1298
# Create ACH relationship
1299
ach_request = CreateACHRelationshipRequest(
1300
account_owner_name=bank_info["owner_name"],
1301
bank_account_type=BankAccountType.CHECKING,
1302
bank_account_number=bank_info["account_number"],
1303
bank_routing_number=bank_info["routing_number"],
1304
nickname="Primary Checking"
1305
)
1306
1307
ach_relationship = self.client.create_ach_relationship(account_id, ach_request)
1308
print(f"ā ACH relationship created: {ach_relationship.id}")
1309
1310
# Initial deposit
1311
if bank_info.get("initial_deposit", 0) > 0:
1312
deposit_request = CreateACHTransferRequest(
1313
relationship_id=ach_relationship.id,
1314
amount=bank_info["initial_deposit"],
1315
direction=TransferDirection.INCOMING
1316
)
1317
1318
deposit = self.client.create_ach_transfer(account_id, deposit_request)
1319
print(f"ā Initial deposit initiated: ${deposit.amount}")
1320
1321
return str(ach_relationship.id)
1322
1323
def create_portfolio_strategy(self, strategy_name: str, allocations: dict) -> str:
1324
"""Create rebalancing portfolio strategy."""
1325
1326
print(f"š Creating portfolio strategy: {strategy_name}")
1327
1328
portfolio_request = CreatePortfolioRequest(
1329
name=strategy_name,
1330
description=f"Automated {strategy_name} allocation",
1331
weights=allocations,
1332
weight_type=WeightType.PERCENT,
1333
cooldown_days=30
1334
)
1335
1336
portfolio = self.client.create_portfolio(portfolio_request)
1337
print(f"ā Portfolio strategy created: {portfolio.id}")
1338
1339
return str(portfolio.id)
1340
1341
def subscribe_to_portfolio(self, account_id: str, portfolio_id: str, max_investment: float) -> None:
1342
"""Subscribe customer to portfolio strategy."""
1343
1344
subscription_request = CreateSubscriptionRequest(
1345
account_id=account_id,
1346
portfolio_id=portfolio_id,
1347
max_investment_amount=max_investment,
1348
cash_percentage=0.05 # Keep 5% cash
1349
)
1350
1351
subscription = self.client.create_subscription(subscription_request)
1352
print(f"ā Account subscribed to portfolio: {subscription.id}")
1353
1354
def execute_trade(self, account_id: str, symbol: str, quantity: float, side: str) -> None:
1355
"""Execute trade for customer account."""
1356
1357
order_request = MarketOrderRequest(
1358
symbol=symbol,
1359
qty=quantity,
1360
side=OrderSide.BUY if side.upper() == "BUY" else OrderSide.SELL,
1361
time_in_force=TimeInForce.DAY
1362
)
1363
1364
order = self.client.submit_order(account_id, order_request)
1365
print(f"š Order submitted: {side} {quantity} {symbol} (ID: {order.id})")
1366
1367
def get_customer_summary(self, account_id: str) -> dict:
1368
"""Get comprehensive customer account summary."""
1369
1370
# Get account details
1371
account = self.client.get_account_by_id(account_id)
1372
1373
# Get funding relationships
1374
ach_relationships = self.client.get_ach_relationships(account_id)
1375
1376
# Get recent transfers
1377
transfers = self.client.get_transfers(account_id)
1378
recent_transfers = [t for t in transfers if t.requested_at > datetime.now() - timedelta(days=30)]
1379
1380
# Get orders
1381
orders = self.client.get_orders_for_account(account_id)
1382
1383
return {
1384
"account_number": account.account_number,
1385
"status": account.status,
1386
"ach_relationships": len(ach_relationships),
1387
"recent_transfers": len(recent_transfers),
1388
"total_orders": len(orders),
1389
"created_at": account.created_at
1390
}
1391
1392
# Example usage
1393
if __name__ == "__main__":
1394
platform = BrokerPlatform(
1395
api_key="sandbox-api-key",
1396
secret_key="sandbox-secret-key",
1397
sandbox=True
1398
)
1399
1400
# Customer onboarding
1401
customer_data = {
1402
"first_name": "Jane",
1403
"last_name": "Smith",
1404
"email": "jane.smith@example.com",
1405
"phone": "+1-555-123-4567",
1406
"address": "123 Investment St",
1407
"city": "New York",
1408
"state": "NY",
1409
"zip_code": "10001",
1410
"date_of_birth": date(1985, 3, 15),
1411
"ssn": "123456789",
1412
"income_min": 75000,
1413
"income_max": 100000
1414
}
1415
1416
account_id = platform.onboard_customer(customer_data)
1417
1418
# Set up funding
1419
bank_data = {
1420
"owner_name": "Jane Smith",
1421
"account_number": "1234567890",
1422
"routing_number": "021000021",
1423
"initial_deposit": 10000.00
1424
}
1425
1426
ach_id = platform.setup_funding(account_id, bank_data)
1427
1428
# Create portfolio strategy
1429
conservative_allocation = {
1430
"VTI": 0.40, # Total Stock Market - 40%
1431
"VXUS": 0.20, # International Stocks - 20%
1432
"BND": 0.30, # Bonds - 30%
1433
"VNQ": 0.10 # REITs - 10%
1434
}
1435
1436
portfolio_id = platform.create_portfolio_strategy(
1437
"Conservative Growth",
1438
conservative_allocation
1439
)
1440
1441
# Subscribe to portfolio
1442
platform.subscribe_to_portfolio(account_id, portfolio_id, 8000.00)
1443
1444
# Execute some trades
1445
platform.execute_trade(account_id, "AAPL", 10, "BUY")
1446
platform.execute_trade(account_id, "MSFT", 15, "BUY")
1447
1448
# Get summary
1449
summary = platform.get_customer_summary(account_id)
1450
print(f"\nš Customer Summary:")
1451
print(f"Account: {summary['account_number']}")
1452
print(f"Status: {summary['status']}")
1453
print(f"ACH Relationships: {summary['ach_relationships']}")
1454
print(f"Recent Transfers: {summary['recent_transfers']}")
1455
print(f"Total Orders: {summary['total_orders']}")
1456
print(f"Created: {summary['created_at'].date()}")
1457
```