PyPSX SDK
API-first trading infrastructure for the Pakistan Stock Exchange.
Installation
pip install pypsx
Try it in a notebook
One-liners — no client to construct
import pypsx
df = pypsx.download("OGDC", period="1y")
result = pypsx.backtest("dual_sma_momentum", "OGDC", period="1y", initial_cash=1_000_000)
quote = pypsx.get_quote("OGDC")
depth = pypsx.get_market_depth("OGDC")
These read PYPSX_API_KEY_ID/PYPSX_API_SECRET_KEY from the environment automatically. For order placement, positions, and account state, use TradingClient below.
Quick Start
Start with paper trading. It is the safety-first way to test your strategy, validate your order flow, and watch your dashboard update in real time before risking real capital.
import os
from dotenv import load_dotenv
from pypsx import TradingClient
load_dotenv()
client = TradingClient(
api_key=os.getenv("PYPSX_API_KEY_ID"),
secret_key=os.getenv("PYPSX_API_SECRET_KEY"),
paper=True,
)
account = client.get_account()
print(f"Connected! Current Balance: PKR {account.cash}")
order = client.place_manual_order(
symbol="OGDC",
side="BUY",
quantity=10,
order_type="MARKET",
)
print("Submitted:", order["order_id"], order["status"])
You can also load keys directly from environment variables:
from pypsx import TradingClient
client = TradingClient.from_env(paper=True)
Your First Trade
Step 1: Generate a paper key in the PyPSX dashboard.
Step 2: Copy the script above into my_bot.py.
Step 3: Set your own PYPSX_API_KEY_ID and PYPSX_API_SECRET_KEY in .env.
Step 4: Run python my_bot.py while the market is open.
Step 5: Watch orders, fills, and positions appear in the dashboard automatically.
The Power of PyPSX
PyPSX gives algorithmic traders a clean Python interface for the Pakistan Stock Exchange without exposing them to exchange plumbing.
Paper Trading
PyPSX currently operates in paper trading mode: simulated orders, no real
money. All requests go to https://paper-api.pypsx.com.
Real-Time Trading Experience
With PyPSX you can:
- Read positions, orders, and account state from Python
- Submit orders with a simple REST interface
- See fills reflected in the web dashboard without manual refresh
- Build bots around trading logic instead of exchange protocol handling
Developer's Promise
PyPSX handles the operational complexity of PSX integration, including request authentication, endpoint routing, and exchange connectivity. You focus on signal generation, risk rules, and execution logic. We handle the FIX-side complexity behind the API.
Authentication
How To Get Your Keys
- Sign in to the PyPSX dashboard.
- Open
Settings. - Select the account you want to trade.
- Click
Generate Paper KeyorGenerate Live Key. - Copy the
Public Key IDandSecret Key.
How The SDK Uses Them
Use the credentials directly in TradingClient(...):
from pypsx import TradingClient
client = TradingClient(
api_key=os.getenv("PYPSX_API_KEY_ID"),
secret_key=os.getenv("PYPSX_API_SECRET_KEY"),
paper=True,
)
Under the hood, the SDK automatically sends:
PYPSX-API-KEY-ID: <your-public-key-id>
PYPSX-API-SECRET-KEY: <your-secret-key>
If you are building against the API without the Python SDK, send those same headers yourself.
API Reference
| Method | What it does | Returns |
|---|---|---|
get_account(account_id=None) |
Account snapshot: cash, equity, buying_power, can_trade (attribute access supported) |
dict |
get_portfolio_valuation() |
Returns the latest equity, cash, positions value, and pricing snapshot | dict |
get_positions() |
Returns open positions for the selected paper trading account | list[dict] |
get_orders(limit=...) |
Returns recent orders and their current state | list[dict] |
place_manual_order(...) |
Submits a market or priced order through the selected environment | dict |
get_symbols() |
Fetches available market symbols | list[dict] |
get_intraday(symbol, days=...) |
Retrieves recent intraday market data for a symbol | list[dict] |
get_historical(symbol, start=..., end=...) |
Retrieves historical daily bars for strategy research and analysis | list[dict] |
get_historical_intraday(symbols, start=..., end=..., interval=...) |
Retrieves multi-interval OHLCV candles (1m/5m/15m/1h) | list[dict] |
get_portfolio(bot_id=None) |
Raw portfolio dict for the current bot/account scope | dict |
get_account_config(account_id=None) |
Account-level configuration | dict |
get_fundamentals(symbol) |
pe_ratio, dividend_yield, market_cap, free_float, etc. for a symbol |
dict |
get_dividends(symbol) |
Dividend history: year, amount, ex_date, payment_date, record_date |
list[dict] |
get_commission_rate() |
The account's commission rate percentage (cached after first call) | float |
add_funds(amount, account_id=None, bot_id=None) |
Add paper cash to an account | dict |
get_performance(bot_id=None, limit=100) |
Historical performance snapshots for a bot | dict |
get_trades(bot_id=None, limit=100) |
Executed trade history for a bot | dict |
get_logs(bot_id=None, limit=200) |
Bot run logs | dict |
list_bots() |
List all bots registered under the account | list[dict] |
create_bot(bot_id, bot_label=None, strategy_name=None, symbols=None, cycle_minutes=None) |
Register a new cloud bot | dict |
place_bracket_order(symbol, side, quantity, stop_loss_price, take_profit_price, entry_type="MARKET", ...) |
Entry order plus a linked stop-loss/take-profit exit pair | dict |
place_oco_order(symbol, quantity, stop_loss_price, take_profit_price, ...) |
Attach a linked stop-loss/take-profit pair to an existing position | dict |
place_stop_order(symbol, quantity, trigger_price, limit_price=None, ...) |
Standalone stop order | dict |
get_order_executions(since=None, limit=1000) |
Raw fill/execution records for the current bot scope | list[dict] |
close() |
Closes the underlying HTTP client cleanly | None |
Examples
Paper Trading
import os
from pypsx import TradingClient
client = TradingClient(
api_key=os.getenv("PYPSX_API_KEY_ID"),
secret_key=os.getenv("PYPSX_API_SECRET_KEY"),
paper=True,
)
valuation = client.get_portfolio_valuation()
positions = client.get_positions()
orders = client.get_orders(limit=25)
print("Equity:", valuation["equity"])
print("Positions:", len(positions))
print("Orders:", len(orders))
Simple Bot Pattern
from pypsx import TradingClient
SYMBOL = "OGDC"
client = TradingClient(
api_key="PK_xxxxxxxxxxxx",
secret_key="your_secret_key",
paper=True,
)
positions = client.get_positions()
already_holding = any(
position["symbol"] == SYMBOL and float(position["qty"]) > 0
for position in positions
)
if not already_holding:
client.place_manual_order(
symbol=SYMBOL,
side="BUY",
quantity=10,
order_type="MARKET",
)
Best Practices
- Use
.envfiles or a secrets manager for credentials. Do not hardcode production keys into source control. - Start every new strategy with
paper=True. - Treat paper trading as your pre-flight checklist before switching to live.
- Run execution scripts when the market is open so fills, liquidity, and dashboard feedback reflect real conditions.
- Add explicit guards in your code for position sizing, duplicate orders, and risk limits.
- Close clients cleanly with
client.close()in longer-running scripts or services.
Raw HTTP Example
If you are not using the SDK, this is the equivalent request format:
curl -X POST "https://paper-api.pypsx.com/orders" \
-H "Content-Type: application/json" \
-H "PYPSX-API-KEY-ID: $PYPSX_API_KEY_ID" \
-H "PYPSX-API-SECRET-KEY: $PYPSX_API_SECRET_KEY" \
-d "{\"symbol\":\"OGDC\",\"side\":\"BUY\",\"quantity\":10,\"order_type\":\"MARKET\",\"mode\":\"PAPER\",\"commission_rate\":0.02}"
Set commission_rate only when you want to override the default fee behavior for a specific order. The value is a percentage, so 0.02 means 0.02%.
Additional Examples
examples/pypsx_client_example.pyexamples/example_bot.py
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pypsx-2.5.0.tar.gz.
File metadata
- Download URL: pypsx-2.5.0.tar.gz
- Upload date:
- Size: 42.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d2e9ce1cf459f0a1762e82c9ec29894da0f37b43310370be1877a8bc3816d5c
|
|
| MD5 |
6109a39a6ed9344b70e91d91f7b7d2df
|
|
| BLAKE2b-256 |
4ddbfa6aaa0a5fbf2d327fc3717df64c2fc19ac08a031f90d68e231bef65872a
|
File details
Details for the file pypsx-2.5.0-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
385bc0d383af954a7cfe7fabf13c3be47d9e1d6168dbca195765f01d776278f1
|
|
| MD5 |
b73a0cf21b298b983f977b2e3c7a0de2
|
|
| BLAKE2b-256 |
b70e987fec2300c87bc15bdb55471f027300983bb58ca957e67f8c72d1e9c3ad
|
File details
Details for the file pypsx-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 26.2 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af4b1cf3e9537fb861c2624d9ca28a44747f91fb8993608bfa62edd948faaa5f
|
|
| MD5 |
faec51435d723f509b4de19acc290899
|
|
| BLAKE2b-256 |
1647d3b0911240341cd32e4a723db9fbeab93ec3a4c4f3c76523e1d4bb03a52c
|
File details
Details for the file pypsx-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 25.6 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19158799740f649d646f87131f2317aba08d19ec4c9221b59aa659ab715399cc
|
|
| MD5 |
70b1edc4bccf48c90244adee55d43490
|
|
| BLAKE2b-256 |
d3516f518495f9d7576c0a1a3d4ae634df59ee0293c33a5a43462bc34bd424df
|
File details
Details for the file pypsx-2.5.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d59cbb6eb6b0b93eaccebb0464ecdc8daa89b9d44204674e188dc087b217034
|
|
| MD5 |
bdd87310ece83223f83991dcfa989213
|
|
| BLAKE2b-256 |
fa945e523c339c36d675eae64629d2dcc97b9c54a38e716cab6f3ae5cd8a120e
|
File details
Details for the file pypsx-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 26.5 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fae436dad08deb2326cd1686c4dc2835f5a59bc27661f1f406cb2520ab7b8b3
|
|
| MD5 |
b0d5c952406eea953da6a0007badc3bd
|
|
| BLAKE2b-256 |
d9a0c44c0384d7791e98530c8abd402a9f0c0f5c54dc25675239ff52416c142e
|
File details
Details for the file pypsx-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 25.6 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cda8e33c59a1fbc51921d7979b69ecada0ea45e7105b3c953de2280e44709d52
|
|
| MD5 |
8dc0e47ecff9ee7871e0ed1f2c09bee4
|
|
| BLAKE2b-256 |
0ed8dca93e570ead22e5614b433f15bc7995397dde9962a6e5f1b1133d39a2ef
|
File details
Details for the file pypsx-2.5.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2fc88a6f632756d5cbd79b76dc2801587f512458404f5879a2f2c1b7265dda5c
|
|
| MD5 |
33aa52dcd41dc6e4866bd6cde22aa4cc
|
|
| BLAKE2b-256 |
052ae498614da055f4d6c1f21f39c0e3f3985e8329c0fb495f7c8ab2dc9747e9
|
File details
Details for the file pypsx-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 26.7 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
883355b97352c5d744436ae9b8cf576c8b52bfb74ea9c633aa0ba18c80b6ca1c
|
|
| MD5 |
f1b208f1fb192de3989aef6260471772
|
|
| BLAKE2b-256 |
c1c6695698ab0954c2c9c16bc47955d1d87b8227e05b698710cd001de8d42207
|
File details
Details for the file pypsx-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 25.9 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71ecf4d93f4d33a56f9f760e7cf1d6c834d6cd1e51cadc8acdc1713274e640e3
|
|
| MD5 |
db21fa216eca652cf2d85bca2194486b
|
|
| BLAKE2b-256 |
74fd2bd3a9d3cae7571384347f1e5ca890157cf274d3766f62b044a78825218c
|
File details
Details for the file pypsx-2.5.0-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df649693c572fcfede45167f9abff7494c3ea74f6ca149ca5302288239018271
|
|
| MD5 |
991188aaaa8e7b39a31d070492aec950
|
|
| BLAKE2b-256 |
05fff52d9f1c9b5984f13d6e95989b2dedc3d73a48bb8cde9915d24f251a4300
|
File details
Details for the file pypsx-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 24.0 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d519ff55b1b0b59a1f6551064ead9b4f95ce4deb7227c1b7b7aaada9d9ab0aa0
|
|
| MD5 |
91cc4046c791c9d40cb38ea2b68404e2
|
|
| BLAKE2b-256 |
0af3b13413a4f4efa0761692712587dfaee2f83897c678710e64852ef5114c10
|
File details
Details for the file pypsx-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 23.5 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef0b431f3398fbcf55d2988698ac18efa30045ee37abc678e824dff5e7ce419a
|
|
| MD5 |
15eae1f0e00561262242057fba297393
|
|
| BLAKE2b-256 |
69c79231f3f19cdc758988a1f83318bb378629e3a79d14d1b778608038e4a81c
|
File details
Details for the file pypsx-2.5.0-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a9df0e4719a0c9b1e0e37470d9aab7d730da77e003f49852e6b81966534be0d
|
|
| MD5 |
d64a3f9a4433a39bbdbaf16391e22764
|
|
| BLAKE2b-256 |
198a57b31b8756e604ef4f90f00b930e2c000f27a6bf51eac1fd66eb84891f65
|
File details
Details for the file pypsx-2.5.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 23.0 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8de69fa8b07448e655651dca8dfe02e587961b01a07692e89b1a8dc783e19111
|
|
| MD5 |
a497374a2f3543541c33e6cb5d68afef
|
|
| BLAKE2b-256 |
3b3f29273a42d9e588e10fe9f62622c870ad8c7111277effa2380641a01dfc93
|
File details
Details for the file pypsx-2.5.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pypsx-2.5.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 22.6 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4997b1ab2f7cc5e4e38de1d8a4db1233393980421a5aa231c6878fcea3cfa2ed
|
|
| MD5 |
c7b6448d7b4cf6ef95b60774817a1a93
|
|
| BLAKE2b-256 |
a7fcd80d576b5b0147b7270999349d371eacc9aef1ccba0abd370303ee5f2ea4
|