[](https://public.com/api)



# Public API Python SDK
A Python SDK for interacting with the Public Trading API, providing a simple and intuitive interface for trading operations, market data retrieval, and account management.
## Installation
### From PyPI
```bash
$ pip install publicdotcom-py
```
### Run locally
```bash
$ python3 -m venv .venv
$ source .venv/bin/activate
$ pip install .
$ pip install -e .
$ pip install -e ".[dev]" # for dev dependencies
$ # run example
$ python example.py
```
### Run tests
```bash
$ pytest
```
### Run examples
Inside of the examples folder are multiple python scripts showcasing specific ways to use the SDK. To run these Python files, first add your `API_SECRET_KEY` and `DEFAULT_ACCOUNT_NUMBER` to the `.env.example` file and change the filename to `.env`.
## Quick Start
```python
from public_api_sdk import PublicApiClient, PublicApiClientConfiguration
from public_api_sdk.auth_config import ApiKeyAuthConfig
# Initialize the client
client = PublicApiClient(
ApiKeyAuthConfig(api_secret_key="INSERT_API_SECRET_KEY"),
config=PublicApiClientConfiguration(
default_account_number="INSERT_ACCOUNT_NUMBER"
)
)
# Get accounts
accounts = client.get_accounts()
# Get a quote
from public_api_sdk import OrderInstrument, InstrumentType
quotes = client.get_quotes([
OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY)
])
```
## API Reference
### Client Configuration
The `PublicApiClient` is initialized with an API secret key create in your settings page at public.com and optional configuration. The SDK client will handle generation and refresh of access tokens:
```python
from public_api_sdk import PublicApiClient, PublicApiClientConfiguration
from public_api_sdk.auth_config import ApiKeyAuthConfig
config = PublicApiClientConfiguration(
default_account_number="INSERT_ACCOUNT_NUMBER", # Optional default account
)
client = PublicApiClient(
ApiKeyAuthConfig(api_secret_key="INSERT_API_SECRET_KEY"),
config=config
)
```
#### Default Account Number
The `default_account_number` configuration option simplifies API calls by eliminating the need to specify `account_id` in every method call. When set, any method that accepts an optional `account_id` parameter will automatically use the default account number if no account ID is explicitly provided.
```python
# With default_account_number configured
from public_api_sdk import OrderInstrument, InstrumentType
config = PublicApiClientConfiguration(
default_account_number="INSERT_ACCOUNT_NUMBER"
)
client = PublicApiClient(
ApiKeyAuthConfig(api_secret_key="INSERT_API_SECRET_KEY"),
config=config
)
instruments = [
OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY),
OrderInstrument(symbol="MSFT", type=InstrumentType.EQUITY)
]
# No need to specify account_id
portfolio = client.get_portfolio() # Uses default account number
quotes = client.get_quotes(instruments) # Uses default account number
# You can still override with a specific account
other_portfolio = client.get_portfolio(account_id="DIFFERENT123") # Uses "DIFFERENT123"
```
```python
# Without default_account_number
config = PublicApiClientConfiguration()
client = PublicApiClient(
ApiKeyAuthConfig(api_secret_key="INSERT_API_SECRET_KEY"),
config=config
)
# Must specify account_id for each call
portfolio = client.get_portfolio(account_id="INSERT_ACCOUNT_NUMBER") # Required
quotes = client.get_quotes(instruments, account_id="INSERT_ACCOUNT_NUMBER") # Required
```
This is particularly useful when working with a single account, as it reduces code repetition and makes the API calls cleaner.
### Account Management
#### Get Accounts
Retrieve all accounts associated with the authenticated user.
```python
accounts_response = client.get_accounts()
for account in accounts_response.accounts:
print(f"Account ID: {account.account_id}, Type: {account.account_type}")
```
#### Get Portfolio
Get a snapshot of account portfolio including positions, equity, and buying power.
```python
portfolio = client.get_portfolio(account_id="YOUR_ACCOUNT_NUMBER") # account_id optional if default set
print(f"Total equity: {portfolio.equity}")
print(f"Buying power: {portfolio.buying_power}")
```
#### Get Account History
Retrieve paginated account history with optional filtering.
```python
from public_api_sdk import HistoryRequest
history = client.get_history(
HistoryRequest(page_size=10),
account_id="YOUR_ACCOUNT"
)
```
### Market Data
#### Get Quotes
Retrieve real-time quotes for multiple instruments.
```python
from public_api_sdk import OrderInstrument, InstrumentType
quotes = client.get_quotes([
OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY),
OrderInstrument(symbol="GOOGL", type=InstrumentType.EQUITY)
])
for quote in quotes:
print(f"{quote.instrument.symbol}: ${quote.last}")
```
#### Get Instrument Details
Get detailed information about a specific instrument.
```python
instrument = client.get_instrument(
symbol="AAPL",
instrument_type=InstrumentType.EQUITY
)
print(f"Symbol: {instrument.instrument.symbol}")
print(f"Type: {instrument.instrument.type}")
print(f"Trading: {instrument.trading}")
print(f"Fractional Trading: {instrument.fractional_trading}")
print(f"Option Trading: {instrument.option_trading}")
print(f"Option Spread Trading: {instrument.option_spread_trading}")
```
#### Get All Instruments
Retrieve all available trading instruments with optional filtering.
```python
from public_api_sdk import InstrumentsRequest, InstrumentType, Trading
instruments = client.get_all_instruments(
InstrumentsRequest(
type_filter=[InstrumentType.EQUITY],
trading_filter=[Trading.BUY_AND_SELL],
)
)
```
### Options Trading
#### Get Option Expirations
Retrieve available option expiration dates for an underlying instrument.
```python
from public_api_sdk import OptionExpirationsRequest, OrderInstrument, InstrumentType
expirations = client.get_option_expirations(
OptionExpirationsRequest(
instrument=OrderInstrument(
symbol="AAPL",
type=InstrumentType.EQUITY
)
)
)
print(f"Available expirations: {expirations.expirations}")
```
#### Get Option Chain
Retrieve the option chain for a specific expiration date.
```python
from public_api_sdk import OptionChainRequest, InstrumentType
option_chain = client.get_option_chain(
OptionChainRequest(
instrument=OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY),
expiration_date=expirations.expirations[0]
)
)
```
#### Get Option Greeks
Get Greeks for a specific option contract (OSI format).
```python
greeks = client.get_option_greeks(
osi_option_symbol="AAPL260116C00270000"
)
print(f"Delta: {greeks.delta}, Gamma: {greeks.gamma}")
```
### Order Management
#### Preflight Calculations
##### Equity Preflight
Calculate estimated costs and impact before placing an equity order.
```python
from public_api_sdk import PreflightRequest, OrderSide, OrderType, TimeInForce, OrderInstrument, InstrumentType
from public_api_sdk import OrderExpirationRequest
from decimal import Decimal
preflight_request = PreflightRequest(
instrument=OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY),
order_side=OrderSide.BUY,
order_type=OrderType.LIMIT,
expiration=OrderExpirationRequest(time_in_force=TimeInForce.DAY),
quantity=10,
limit_price=Decimal("227.50")
)
preflight_response = client.perform_preflight_calculation(preflight_request)
print(f"Estimated commission: ${preflight_response.estimated_commission}")
print(f"Order value: ${preflight_response.order_value}")
```
##### Multi-Leg Preflight
Calculate estimated costs for complex multi-leg option strategies.
```python
preflight_multi = PreflightMultiLegRequest(
order_type=OrderType.LIMIT,
expiration=OrderExpirationRequest(
time_in_force=TimeInForce.GTD,
expiration_time=datetime(2025, 12, 1, tzinfo=timezone.utc)
),
quantity=1,
limit_price=Decimal("3.45"),
legs=[
OrderLegRequest(
instrument=LegInstrument(symbol="AAPL251024C00110000", type=LegInstrumentType.OPTION),
side=OrderSide.SELL,
open_close_indicator=OpenCloseIndicator.OPEN,
ratio_quantity=1
),
OrderLegRequest(
instrument=LegInstrument(symbol="AAPL251024C00120000", type=LegInstrumentType.OPTION),
side=OrderSide.BUY,
open_close_indicator=OpenCloseIndicator.OPEN,
ratio_quantity=1
)
]
)
# Calculate preflight to get strategy details and costs
preflight_result = client.perform_multi_leg_preflight_calculation(preflight_multi)
# Display results
print("\n" + "="*70)
print(f"Strategy: {preflight_result.strategy_name}")
print("="*70)
print(f"\nOrder Details:")
print(f" Order Type: {preflight_multi.order_type.value}")
print(f" Quantity: {preflight_multi.quantity}")
print(f" Limit Price: ${preflight_multi.limit_price}")
print(f"\nLegs:")
for i, leg in enumerate(preflight_multi.legs, 1):
print(f" {i}. {leg.side.value} {leg.instrument.symbol}")
cost = float(preflight_result.estimated_cost)
cost_label = "Debit (Cost)" if cost > 0 else "Credit"
print(f"\nCost Analysis:")
print(f" {cost_label}: ${abs(cost):.2f}")
print(f" Commission: ${preflight_result.estimated_commission}")
print(f" Buying Power Required: ${preflight_result.buying_power_requirement}")
print("\n" + "="*70)
```
#### Place Orders
##### Place Single-Leg Order
Submit a single-leg equity or option order.
```python
from public_api_sdk import OrderRequest, OrderInstrument, InstrumentType
import uuid
order_request = OrderRequest(
order_id=str(uuid.uuid4()),
instrument=OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY),
order_side=OrderSide.BUY,
order_type=OrderType.LIMIT,
expiration=OrderExpirationRequest(time_in_force=TimeInForce.DAY),
quantity=10,
limit_price=Decimal("227.50")
)
order_response = client.place_order(order_request)
print(f"Order placed with ID: {order_response.order_id}")
```
##### Place Multi-Leg Order
Submit a multi-leg option strategy order.
```python
from datetime import datetime, timezone
from public_api_sdk import MultilegOrderRequest
import uuid
multileg_order = MultilegOrderRequest(
order_id=str(uuid.uuid4()),
quantity=1,
type=OrderType.LIMIT,
limit_price=Decimal("3.45"),
expiration=OrderExpirationRequest(
time_in_force=TimeInForce.GTD,
expiration_time=datetime(2025, 10, 31, tzinfo=timezone.utc)
),
legs=[
OrderLegRequest(
instrument=LegInstrument(
symbol="AAPL251024C00110000",
type=LegInstrumentType.OPTION
),
side=OrderSide.SELL,
open_close_indicator=OpenCloseIndicator.OPEN,
ratio_quantity=1
),
OrderLegRequest(
instrument=LegInstrument(
symbol="AAPL251024C00120000",
type=LegInstrumentType.OPTION
),
side=OrderSide.BUY,
open_close_indicator=OpenCloseIndicator.OPEN,
ratio_quantity=1
)
]
)
multileg_response = client.place_multileg_order(multileg_order)
print(f"Multi-leg order placed: {multileg_response.order_id}")
```
#### Get Order Status
Retrieve the status and details of a specific order.
```python
order_details = client.get_order(
order_id="YOUR_ORDER_ID",
account_id="YOUR_ACCOUNT" # optional if default set
)
print(f"Order status: {order_details.status}")
```
#### Cancel Order
Submit an asynchronous request to cancel an order.
```python
client.cancel_order(
order_id="YOUR_ORDER_ID",
account_id="YOUR_ACCOUNT" # optional if default set
)
# Note: Check order status after to confirm cancellation
```
### Price Subscription
#### Basic Usage
```python
from public_api_sdk import (
PublicApiClient,
PublicApiClientConfiguration,
OrderInstrument,
InstrumentType,
PriceChange,
SubscriptionConfig,
)
# initialize client
config = PublicApiClientConfiguration(
default_account_number="YOUR_ACCOUNT"
)
client = PublicApiClient(
api_secret_key="YOUR_KEY",
config=config
)
# define callback
def on_price_change(price_change: PriceChange):
print(f"{price_change.instrument.symbol}: "
f"{price_change.old_quote.last} -> {price_change.new_quote.last}")
instruments = [
OrderInstrument(symbol="AAPL", type=InstrumentType.EQUITY),
OrderInstrument(symbol="GOOGL", type=InstrumentType.EQUITY),
]
subscription_id = client.subscribe_to_price_changes(
instruments=instruments,
callback=on_price_change,
config=SubscriptionConfig(polling_frequency_seconds=2.0)
)
# ...
# unsubscribe
client.unsubscribe(subscription_id)
```
#### Async Callbacks
```python
async def async_price_handler(price_change: PriceChange):
# Async processing
await process_price_change(price_change)
client.subscribe_to_price_changes(
instruments=instruments,
callback=async_price_handler # Async callbacks are automatically detected
)
```
#### Subscription Management
```python
# update polling frequency
client.set_polling_frequency(subscription_id, 5.0)
# get all active subscriptions
active = client.get_active_subscriptions()
# unsubscribe all
client.unsubscribe_all()
```
#### Custom Configuration
```python
config = SubscriptionConfig(
polling_frequency_seconds=1.0, # poll every second
retry_on_error=True, # retry on API errors
max_retries=5, # maximum retry attempts
exponential_backoff=True # use exponential backoff for retries
)
subscription_id = client.subscribe_to_price_changes(
instruments=instruments,
callback=on_price_change,
config=config
)
```
## Examples
### Complete Trading Workflow
See `example.py` for a complete trading workflow example that demonstrates:
- Getting accounts
- Retrieving quotes
- Performing preflight calculations
- Placing orders
- Checking order status
- Getting portfolio information
- Retrieving account history
### Options Trading Example
See `example_options.py` for a comprehensive options trading example that shows:
- Getting option expirations
- Retrieving option chains
- Getting option Greeks
- Performing multi-leg preflight calculations
- Placing multi-leg option orders
### Price Subscription
See `example_price_subscription.py` for complete examples including:
- Basic subscription usage
- Advanced async callbacks
- Multiple concurrent subscriptions
- Custom price alert system
## Error Handling
The SDK will raise exceptions for API errors. It's recommended to wrap API calls in try-except blocks:
```python
try:
order_response = client.place_order(order_request)
except Exception as e:
print(f"Error placing order: {e}")
finally:
client.close()
```
## Important Notes
- Order placement is asynchronous. Always use `get_order()` to verify order status.
- For accounts with a default account number configured, the `account_id` parameter is optional in most methods.
- The client manages token refresh automatically.
- Always call `client.close()` when done to clean up resources.
Raw data
{
"_id": null,
"home_page": null,
"name": "publicdotcom-py",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "api, sdk, trading, finance",
"author": null,
"author_email": "Public <api-support@public.com>",
"download_url": "https://files.pythonhosted.org/packages/94/e0/c66af9a4fe9c0ae5e6814526f54d00fdfda5aa2e2de83510edba2a4b9346/publicdotcom_py-0.1.3.tar.gz",
"platform": null,
"description": "[](https://public.com/api)\n\n\n\n\n\n# Public API Python SDK\n\nA Python SDK for interacting with the Public Trading API, providing a simple and intuitive interface for trading operations, market data retrieval, and account management.\n\n## Installation\n\n### From PyPI\n\n```bash\n$ pip install publicdotcom-py\n```\n\n### Run locally\n\n```bash\n$ python3 -m venv .venv\n$ source .venv/bin/activate\n$ pip install .\n\n$ pip install -e .\n$ pip install -e \".[dev]\" # for dev dependencies\n\n$ # run example\n$ python example.py\n```\n\n### Run tests\n\n```bash\n$ pytest\n```\n\n### Run examples\n\nInside of the examples folder are multiple python scripts showcasing specific ways to use the SDK. To run these Python files, first add your `API_SECRET_KEY` and `DEFAULT_ACCOUNT_NUMBER` to the `.env.example` file and change the filename to `.env`.\n\n## Quick Start\n\n```python\nfrom public_api_sdk import PublicApiClient, PublicApiClientConfiguration\nfrom public_api_sdk.auth_config import ApiKeyAuthConfig\n\n# Initialize the client\nclient = PublicApiClient(\n ApiKeyAuthConfig(api_secret_key=\"INSERT_API_SECRET_KEY\"),\n config=PublicApiClientConfiguration(\n default_account_number=\"INSERT_ACCOUNT_NUMBER\"\n )\n)\n\n# Get accounts\naccounts = client.get_accounts()\n\n# Get a quote\nfrom public_api_sdk import OrderInstrument, InstrumentType\n\nquotes = client.get_quotes([\n OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY)\n])\n```\n\n## API Reference\n\n### Client Configuration\n\nThe `PublicApiClient` is initialized with an API secret key create in your settings page at public.com and optional configuration. The SDK client will handle generation and refresh of access tokens:\n\n```python\nfrom public_api_sdk import PublicApiClient, PublicApiClientConfiguration\nfrom public_api_sdk.auth_config import ApiKeyAuthConfig\n\nconfig = PublicApiClientConfiguration(\n default_account_number=\"INSERT_ACCOUNT_NUMBER\", # Optional default account\n)\n\nclient = PublicApiClient(\n ApiKeyAuthConfig(api_secret_key=\"INSERT_API_SECRET_KEY\"),\n config=config\n )\n```\n\n#### Default Account Number\n\nThe `default_account_number` configuration option simplifies API calls by eliminating the need to specify `account_id` in every method call. When set, any method that accepts an optional `account_id` parameter will automatically use the default account number if no account ID is explicitly provided.\n\n```python\n# With default_account_number configured\nfrom public_api_sdk import OrderInstrument, InstrumentType\n\nconfig = PublicApiClientConfiguration(\n default_account_number=\"INSERT_ACCOUNT_NUMBER\"\n)\n\nclient = PublicApiClient(\n ApiKeyAuthConfig(api_secret_key=\"INSERT_API_SECRET_KEY\"), \n config=config\n )\n\ninstruments = [\n OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY),\n OrderInstrument(symbol=\"MSFT\", type=InstrumentType.EQUITY)\n]\n\n# No need to specify account_id\nportfolio = client.get_portfolio() # Uses default account number\nquotes = client.get_quotes(instruments) # Uses default account number\n\n# You can still override with a specific account\nother_portfolio = client.get_portfolio(account_id=\"DIFFERENT123\") # Uses \"DIFFERENT123\"\n```\n\n```python\n# Without default_account_number\nconfig = PublicApiClientConfiguration()\n\nclient = PublicApiClient(\n ApiKeyAuthConfig(api_secret_key=\"INSERT_API_SECRET_KEY\"), \n config=config\n )\n\n# Must specify account_id for each call\nportfolio = client.get_portfolio(account_id=\"INSERT_ACCOUNT_NUMBER\") # Required\nquotes = client.get_quotes(instruments, account_id=\"INSERT_ACCOUNT_NUMBER\") # Required\n```\n\nThis is particularly useful when working with a single account, as it reduces code repetition and makes the API calls cleaner.\n\n### Account Management\n\n#### Get Accounts\n\nRetrieve all accounts associated with the authenticated user.\n\n```python\naccounts_response = client.get_accounts()\nfor account in accounts_response.accounts:\n print(f\"Account ID: {account.account_id}, Type: {account.account_type}\")\n```\n\n#### Get Portfolio\n\nGet a snapshot of account portfolio including positions, equity, and buying power.\n\n```python\nportfolio = client.get_portfolio(account_id=\"YOUR_ACCOUNT_NUMBER\") # account_id optional if default set\nprint(f\"Total equity: {portfolio.equity}\")\nprint(f\"Buying power: {portfolio.buying_power}\")\n```\n\n#### Get Account History\n\nRetrieve paginated account history with optional filtering.\n\n```python\nfrom public_api_sdk import HistoryRequest\n\nhistory = client.get_history(\n HistoryRequest(page_size=10),\n account_id=\"YOUR_ACCOUNT\"\n)\n```\n\n### Market Data\n\n#### Get Quotes\n\nRetrieve real-time quotes for multiple instruments.\n\n```python\nfrom public_api_sdk import OrderInstrument, InstrumentType\n\nquotes = client.get_quotes([\n OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY),\n OrderInstrument(symbol=\"GOOGL\", type=InstrumentType.EQUITY)\n])\n\nfor quote in quotes:\n print(f\"{quote.instrument.symbol}: ${quote.last}\")\n```\n\n#### Get Instrument Details\n\nGet detailed information about a specific instrument.\n\n```python\ninstrument = client.get_instrument(\n symbol=\"AAPL\",\n instrument_type=InstrumentType.EQUITY\n)\n\nprint(f\"Symbol: {instrument.instrument.symbol}\")\nprint(f\"Type: {instrument.instrument.type}\")\nprint(f\"Trading: {instrument.trading}\")\nprint(f\"Fractional Trading: {instrument.fractional_trading}\")\nprint(f\"Option Trading: {instrument.option_trading}\")\nprint(f\"Option Spread Trading: {instrument.option_spread_trading}\")\n```\n\n#### Get All Instruments\n\nRetrieve all available trading instruments with optional filtering.\n\n```python\nfrom public_api_sdk import InstrumentsRequest, InstrumentType, Trading\n\ninstruments = client.get_all_instruments(\n InstrumentsRequest(\n type_filter=[InstrumentType.EQUITY],\n trading_filter=[Trading.BUY_AND_SELL],\n )\n)\n```\n\n### Options Trading\n\n#### Get Option Expirations\n\nRetrieve available option expiration dates for an underlying instrument.\n\n```python\nfrom public_api_sdk import OptionExpirationsRequest, OrderInstrument, InstrumentType\n\nexpirations = client.get_option_expirations(\n OptionExpirationsRequest(\n instrument=OrderInstrument(\n symbol=\"AAPL\", \n type=InstrumentType.EQUITY\n )\n )\n)\nprint(f\"Available expirations: {expirations.expirations}\")\n```\n\n#### Get Option Chain\n\nRetrieve the option chain for a specific expiration date.\n\n```python\nfrom public_api_sdk import OptionChainRequest, InstrumentType\n\noption_chain = client.get_option_chain(\n OptionChainRequest(\n instrument=OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY),\n expiration_date=expirations.expirations[0]\n )\n)\n```\n\n#### Get Option Greeks\n\nGet Greeks for a specific option contract (OSI format).\n\n```python\ngreeks = client.get_option_greeks(\n osi_option_symbol=\"AAPL260116C00270000\"\n)\nprint(f\"Delta: {greeks.delta}, Gamma: {greeks.gamma}\")\n```\n\n### Order Management\n\n#### Preflight Calculations\n\n##### Equity Preflight\n\nCalculate estimated costs and impact before placing an equity order.\n\n```python\nfrom public_api_sdk import PreflightRequest, OrderSide, OrderType, TimeInForce, OrderInstrument, InstrumentType\nfrom public_api_sdk import OrderExpirationRequest\nfrom decimal import Decimal\n\npreflight_request = PreflightRequest(\n instrument=OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY),\n order_side=OrderSide.BUY,\n order_type=OrderType.LIMIT,\n expiration=OrderExpirationRequest(time_in_force=TimeInForce.DAY),\n quantity=10,\n limit_price=Decimal(\"227.50\")\n)\n\npreflight_response = client.perform_preflight_calculation(preflight_request)\nprint(f\"Estimated commission: ${preflight_response.estimated_commission}\")\nprint(f\"Order value: ${preflight_response.order_value}\")\n```\n\n##### Multi-Leg Preflight\n\nCalculate estimated costs for complex multi-leg option strategies.\n\n```python\npreflight_multi = PreflightMultiLegRequest(\n order_type=OrderType.LIMIT,\n expiration=OrderExpirationRequest(\n time_in_force=TimeInForce.GTD,\n expiration_time=datetime(2025, 12, 1, tzinfo=timezone.utc)\n ),\n quantity=1,\n limit_price=Decimal(\"3.45\"),\n legs=[\n OrderLegRequest(\n instrument=LegInstrument(symbol=\"AAPL251024C00110000\", type=LegInstrumentType.OPTION),\n side=OrderSide.SELL,\n open_close_indicator=OpenCloseIndicator.OPEN,\n ratio_quantity=1\n ),\n OrderLegRequest(\n instrument=LegInstrument(symbol=\"AAPL251024C00120000\", type=LegInstrumentType.OPTION),\n side=OrderSide.BUY,\n open_close_indicator=OpenCloseIndicator.OPEN,\n ratio_quantity=1\n )\n ]\n)\n\n# Calculate preflight to get strategy details and costs\npreflight_result = client.perform_multi_leg_preflight_calculation(preflight_multi)\n\n# Display results\nprint(\"\\n\" + \"=\"*70)\nprint(f\"Strategy: {preflight_result.strategy_name}\")\nprint(\"=\"*70)\n\nprint(f\"\\nOrder Details:\")\nprint(f\" Order Type: {preflight_multi.order_type.value}\")\nprint(f\" Quantity: {preflight_multi.quantity}\")\nprint(f\" Limit Price: ${preflight_multi.limit_price}\")\n\nprint(f\"\\nLegs:\")\nfor i, leg in enumerate(preflight_multi.legs, 1):\n print(f\" {i}. {leg.side.value} {leg.instrument.symbol}\")\n\ncost = float(preflight_result.estimated_cost)\ncost_label = \"Debit (Cost)\" if cost > 0 else \"Credit\"\nprint(f\"\\nCost Analysis:\")\nprint(f\" {cost_label}: ${abs(cost):.2f}\")\nprint(f\" Commission: ${preflight_result.estimated_commission}\")\nprint(f\" Buying Power Required: ${preflight_result.buying_power_requirement}\")\n\nprint(\"\\n\" + \"=\"*70)\n```\n\n#### Place Orders\n\n##### Place Single-Leg Order\n\nSubmit a single-leg equity or option order.\n\n```python\nfrom public_api_sdk import OrderRequest, OrderInstrument, InstrumentType\nimport uuid\n\norder_request = OrderRequest(\n order_id=str(uuid.uuid4()),\n instrument=OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY),\n order_side=OrderSide.BUY,\n order_type=OrderType.LIMIT,\n expiration=OrderExpirationRequest(time_in_force=TimeInForce.DAY),\n quantity=10,\n limit_price=Decimal(\"227.50\")\n)\n\norder_response = client.place_order(order_request)\nprint(f\"Order placed with ID: {order_response.order_id}\")\n```\n\n##### Place Multi-Leg Order\n\nSubmit a multi-leg option strategy order.\n\n```python\nfrom datetime import datetime, timezone\nfrom public_api_sdk import MultilegOrderRequest\nimport uuid\n\nmultileg_order = MultilegOrderRequest(\n order_id=str(uuid.uuid4()),\n quantity=1,\n type=OrderType.LIMIT,\n limit_price=Decimal(\"3.45\"),\n expiration=OrderExpirationRequest(\n time_in_force=TimeInForce.GTD,\n expiration_time=datetime(2025, 10, 31, tzinfo=timezone.utc)\n ),\n legs=[\n OrderLegRequest(\n instrument=LegInstrument(\n symbol=\"AAPL251024C00110000\",\n type=LegInstrumentType.OPTION\n ),\n side=OrderSide.SELL,\n open_close_indicator=OpenCloseIndicator.OPEN,\n ratio_quantity=1\n ),\n OrderLegRequest(\n instrument=LegInstrument(\n symbol=\"AAPL251024C00120000\",\n type=LegInstrumentType.OPTION\n ),\n side=OrderSide.BUY,\n open_close_indicator=OpenCloseIndicator.OPEN,\n ratio_quantity=1\n )\n ]\n)\n\nmultileg_response = client.place_multileg_order(multileg_order)\nprint(f\"Multi-leg order placed: {multileg_response.order_id}\")\n```\n\n#### Get Order Status\n\nRetrieve the status and details of a specific order.\n\n```python\norder_details = client.get_order(\n order_id=\"YOUR_ORDER_ID\",\n account_id=\"YOUR_ACCOUNT\" # optional if default set\n)\nprint(f\"Order status: {order_details.status}\")\n```\n\n#### Cancel Order\n\nSubmit an asynchronous request to cancel an order.\n\n```python\nclient.cancel_order(\n order_id=\"YOUR_ORDER_ID\",\n account_id=\"YOUR_ACCOUNT\" # optional if default set\n)\n# Note: Check order status after to confirm cancellation\n```\n\n\n### Price Subscription\n\n#### Basic Usage\n\n```python\nfrom public_api_sdk import (\n PublicApiClient,\n PublicApiClientConfiguration,\n OrderInstrument,\n InstrumentType,\n PriceChange,\n SubscriptionConfig,\n)\n\n# initialize client\nconfig = PublicApiClientConfiguration(\n default_account_number=\"YOUR_ACCOUNT\"\n)\nclient = PublicApiClient(\n api_secret_key=\"YOUR_KEY\",\n config=config\n)\n\n# define callback\ndef on_price_change(price_change: PriceChange):\n print(f\"{price_change.instrument.symbol}: \"\n f\"{price_change.old_quote.last} -> {price_change.new_quote.last}\")\n\ninstruments = [\n OrderInstrument(symbol=\"AAPL\", type=InstrumentType.EQUITY),\n OrderInstrument(symbol=\"GOOGL\", type=InstrumentType.EQUITY),\n]\n\nsubscription_id = client.subscribe_to_price_changes(\n instruments=instruments,\n callback=on_price_change,\n config=SubscriptionConfig(polling_frequency_seconds=2.0)\n)\n\n# ...\n\n# unsubscribe\nclient.unsubscribe(subscription_id)\n```\n\n#### Async Callbacks\n\n```python\nasync def async_price_handler(price_change: PriceChange):\n # Async processing\n await process_price_change(price_change)\n\nclient.subscribe_to_price_changes(\n instruments=instruments,\n callback=async_price_handler # Async callbacks are automatically detected\n)\n```\n\n#### Subscription Management\n\n```python\n# update polling frequency\nclient.set_polling_frequency(subscription_id, 5.0)\n\n# get all active subscriptions\nactive = client.get_active_subscriptions()\n\n# unsubscribe all\nclient.unsubscribe_all()\n```\n\n#### Custom Configuration\n\n```python\nconfig = SubscriptionConfig(\n polling_frequency_seconds=1.0, # poll every second\n retry_on_error=True, # retry on API errors\n max_retries=5, # maximum retry attempts\n exponential_backoff=True # use exponential backoff for retries\n)\n\nsubscription_id = client.subscribe_to_price_changes(\n instruments=instruments,\n callback=on_price_change,\n config=config\n)\n```\n\n\n\n\n## Examples\n\n### Complete Trading Workflow\n\nSee `example.py` for a complete trading workflow example that demonstrates:\n- Getting accounts\n- Retrieving quotes\n- Performing preflight calculations\n- Placing orders\n- Checking order status\n- Getting portfolio information\n- Retrieving account history\n\n### Options Trading Example\n\nSee `example_options.py` for a comprehensive options trading example that shows:\n- Getting option expirations\n- Retrieving option chains\n- Getting option Greeks\n- Performing multi-leg preflight calculations\n- Placing multi-leg option orders\n\n### Price Subscription\n\nSee `example_price_subscription.py` for complete examples including:\n- Basic subscription usage\n- Advanced async callbacks\n- Multiple concurrent subscriptions\n- Custom price alert system\n\n\n## Error Handling\n\nThe SDK will raise exceptions for API errors. It's recommended to wrap API calls in try-except blocks:\n\n```python\ntry:\n order_response = client.place_order(order_request)\nexcept Exception as e:\n print(f\"Error placing order: {e}\")\nfinally:\n client.close()\n```\n\n## Important Notes\n\n- Order placement is asynchronous. Always use `get_order()` to verify order status.\n- For accounts with a default account number configured, the `account_id` parameter is optional in most methods.\n- The client manages token refresh automatically.\n- Always call `client.close()` when done to clean up resources.\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Python SDK for Public.com API",
"version": "0.1.3",
"project_urls": {
"Homepage": "https://public.com/api/docs",
"Issues": "https://github.com/PublicDotCom/publicdotcom-py/issues",
"Repository": "https://github.com/PublicDotCom/publicdotcom-py"
},
"split_keywords": [
"api",
" sdk",
" trading",
" finance"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "ee77ecf2b4ae83d6b6db028618aba1d2a171cdcbf62621256a9797ef2ffae90f",
"md5": "209eb754412e3865576c696044878aef",
"sha256": "02e9df47f86f9397f3061658ecafed83e602e27fedd45f07248d4128757e9f80"
},
"downloads": -1,
"filename": "publicdotcom_py-0.1.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "209eb754412e3865576c696044878aef",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 47156,
"upload_time": "2025-11-10T19:24:29",
"upload_time_iso_8601": "2025-11-10T19:24:29.465295Z",
"url": "https://files.pythonhosted.org/packages/ee/77/ecf2b4ae83d6b6db028618aba1d2a171cdcbf62621256a9797ef2ffae90f/publicdotcom_py-0.1.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "94e0c66af9a4fe9c0ae5e6814526f54d00fdfda5aa2e2de83510edba2a4b9346",
"md5": "60fafdf72b4f9cc933af420f081916ba",
"sha256": "100df7f8c9ff236e16757bfa700cf1227b96d1754a709baa2ae649f0f1f4bd83"
},
"downloads": -1,
"filename": "publicdotcom_py-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "60fafdf72b4f9cc933af420f081916ba",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 56899,
"upload_time": "2025-11-10T19:24:30",
"upload_time_iso_8601": "2025-11-10T19:24:30.527315Z",
"url": "https://files.pythonhosted.org/packages/94/e0/c66af9a4fe9c0ae5e6814526f54d00fdfda5aa2e2de83510edba2a4b9346/publicdotcom_py-0.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-10 19:24:30",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "PublicDotCom",
"github_project": "publicdotcom-py",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "publicdotcom-py"
}