publicdotcom-py


Namepublicdotcom-py JSON
Version 0.1.3 PyPI version JSON
download
home_pageNone
SummaryPython SDK for Public.com API
upload_time2025-11-10 19:24:30
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseApache-2.0
keywords api sdk trading finance
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Public API Python SDK](banner.png)](https://public.com/api)

![Version](https://img.shields.io/badge/version-0.1.3-brightgreen?style=flat-square)
![Python](https://img.shields.io/badge/python-3.8%2B-blue?style=flat-square)
![License](https://img.shields.io/badge/license-Apache%202.0-green?style=flat-square)

# 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": "[![Public API Python SDK](banner.png)](https://public.com/api)\n\n![Version](https://img.shields.io/badge/version-0.1.3-brightgreen?style=flat-square)\n![Python](https://img.shields.io/badge/python-3.8%2B-blue?style=flat-square)\n![License](https://img.shields.io/badge/license-Apache%202.0-green?style=flat-square)\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"
}
        
Elapsed time: 2.65036s