A python based SDK developed for interacting with Ostium, a Decentralized Perpetual Exchange for trading Crypto, RWA (Commodities, indices, Forex) and more.
Changelog
Track all notable changes, updates, and improvements to the Ostium Python SDK in our Changelog.
Ostium Python SDK
A python based SDK developed for interacting with Ostium v1 Trading Platform (https://ostium.app/)
Ostium is a decentralized perpetuals exchange on Arbitrum (Ethereum L2) with a focus on providing a seamless experience for traders for trading currencies, commodities, indices, crypto and more.
This SDK is designed to be used by developers who want to build applications on top of Ostium and automate their trading strategies.
Supported Operations
Basically you can perfrom any operation that is supported by the Ostium's web site in a programmatic way, via the SDK:
- Get list of feeds and their details
- Create a Trade/Order
- Close a Trade, Partial Close a trade, Set Take Profit, Set Stop Loss
- Add Colleteral, Remove Collateral
- Cancel an Order, Set Take Profit, Set Stop Loss, Set Entry Price
- Read Open Trades aka Positions
- Read Open Orders (Limit, Stop)
- Read Order History along with their details such as Pnl, etc.
- Get latest price of a feed
- Calculate fees such as funding rate, rollover fee, etc.
- Call testnet faucet to get testnet USDC tokens
- Read balance of your account, usdc and native token
To use the SDK you need to have a valid EVM private key for an account on either Arbitrum (mainnet) or Arbitrum Sepolia (testnet), depending on which network you plan to use and supply a RPC URL, see below for more details.
Installation
The SDK can be installed via pip:
pip install ostium-python-sdk
Running Tests
First, install the package with development dependencies:
pip install -e ".[dev]"
Running tests
Run specific tests
pytest -v tests/testtradeliquidation_price.py
pytest -v tests/test_funding.py
pytest -v tests/testtradegettpprice.py
pytest -v tests/testtradegetslprice.py
pytest -v tests/testcurrenttradeprofitp.py
pytest -v tests/testtopupwithcollateral.py
pytest -v tests/testtopupwithleverage.py
pytest -v tests/testremovecollateralwithcollateral.py
pytest -v tests/testremovecollateralfromleverage.py
pytest -v tests/testcurrenttotalprofitp.py
pytest -v tests/testcurrenttradeprofitraw.py
pytest -v tests/testcurrenttotalprofitraw.py
pytest -v tests/testgettradefundingfee.py
pytest -v tests/testgettraderolloverfee.py
pytest -v tests/testgettrade_value.py
pytest -v tests/testgetopening_fee.py
pytest -v tests/testgetpendingaccfunding_fees.py
pytest -v tests/testmaxleverage.py pytest -v tests/testovernightmax_leverage.py pytest -v tests/test_slippage.py pytest -v tests/testtargetfunding_rate.py
Run ALL tests
pytest
Requirements
Developed using:
python=3.8 SDK Instantiation
You can instantiate the SDK with the following parameters. Ostium Platform is deployed on Arbitrum. You can use the testnet or mainnet config via the NetworkConfig class, see below for an example.
from dotenv import load_dotenv
from ostiumpythonsdk import OstiumSDK, NetworkConfig
Load environment variables if using .env file
load_dotenv()
Get private key from environment variable
privatekey = os.getenv('PRIVATEKEY')
if not private_key:
raise ValueError("PRIVATE_KEY not found in .env file")
rpcurl = os.getenv('RPCURL') if not rpc_url: raise ValueError("RPC_URL not found in .env file")
Initialize SDK (default: verbose=False for quiet operation)
configTestnet = NetworkConfig.testnet()
sdk = OstiumSDK(configTestnet, privatekey, rpcurl)
For verbose mode with detailed logging:
sdk = OstiumSDK(configTestnet, privatekey, rpcurl, verbose=True)
NOTE: create a .env file with PRIVATEKEY and RPCURL to use the SDK. An RPC URL is required to use the SDK. You can get one by signing up for a free account at https://www.alchemy.com/ and creating an app.
NOTE: You can also use the SDK without providing a private key, in which case you will be limited to read only operations on the SDK.
PRIVATEKEY=yourprivatekeyhere
RPC_URL=https://arb-sepolia.g.alchemy.com/v2/...
#RPC_URL="https://arb-mainnet.g.alchemy.com/v2/...",
yourprivatekey_here should be a valid EVM private key for an account on either Arbitrum (mainnet) or Arbitrum Sepolia (testnet), depending on which network you plan to use.
Make sure to save it in a secure location, and that the .env file is not shared with anyone or committed to a public repository (make sure you add it to .gitignore if you are pushing your code).
Testnet and Fuacet to get USDC tokens
As you can see above, we show use case on testnet. In order to use Ostium on testnet, aka on Arbitrum Sepolia, you need to get testnet USDC tokens. You can do this by using the faucet which is also available on the SDK once instantiated in testnet config.
# Get current token amount from faucet
On testnet
sdk = OstiumSDK(NetworkConfig.testnet(), privatekey, rpcurl)
Check if tokens can be requested
if sdk.faucet.canrequesttokens(address):
# Get amount that will be received
amount = sdk.faucet.gettokenamount()
print(f"Will receive {amount} tokens")
# Request tokens
receipt = sdk.faucet.request_tokens()
print(f"Tokens requested successfully! TX: {receipt['transactionHash'].hex()}")
else:
nexttime = sdk.faucet.getnextrequesttime(address)
print(f"Cannot request tokens yet. Next request allowed at: {next_time}")
NOTE: You will also need gas aka ethereum or native token on Arbitrum Sepolia to even be able to request USDC tokens from the faucet or perform any write blockchain operation. You can get some native token for Arbitrum Sepolia for free at: https://www.alchemy.com/faucets/arbitrum-sepolia (or search for "arbitrum sepolia faucet")
The SDK contains the following classes:
OstiumSDK: The main class for interacting with the Ostium Platform.
NetworkConfig: The class for configuring the network.
Balance: The class for interacting with the account, fetching balance, etc. available viasdk.balance.
SubgraphClient: The class for interacting with the subgraph, getting pair details, open trades, open orders,etc. available viasdk.subgraph.
Price: The class for interacting with the price, fetching latest price, etc. available viasdk.price
Ostium: The class for interacting with the Ostium Smart contracts, opening trades, updating take profit and stop loss, closing trades, opening orders, etc. available viasdk.ostium.
Faucet: The class for interacting with the Faucet for getting testnet USDC tokens. available viasdk.faucet.
Basic Usage
The intraction with Ostium platform is denoted with pairid and tradeindex.
pairid: The id of the pair, available viasdk.subgraph.getpairs()tradeindex: The index of the trade for this trader on the pair, available viasdk.subgraph.getopen_trades()
List of available pairs (Mainnet)
- As of May 2025, the following pairs are available on the mainnet:
Usage Examples
Reading available pairs / feeds
from ostiumpythonsdk import OstiumSDK
from dotenv import load_dotenv
Load environment variables if using .env file
load_dotenv()
Get private key from environment variable
privatekey = os.getenv('PRIVATEKEY')
if not private_key:
raise ValueError("PRIVATE_KEY not found in .env file")
rpcurl = os.getenv('RPCURL') if not rpc_url: raise ValueError("RPC_URL not found in .env file")
Initialize SDK
config = NetworkConfig.testnet()
sdk = OstiumSDK(config, privatekey, rpcurl)
Or, initialize:
#
(1) mainnet:
#
config = NetworkConfig.mainnet()
sdk = OstiumSDK(config, privatekey, rpcurl)
#
(2) with explicit private key & rpc url, i.e: not read from env variables
sdk = OstiumSDK(
network="arbitrum",
privatekey="yourprivatekeyhere",
rpc_url="https://arb1.arbitrum.io/rpc...."
)
Get all available pairs
pairs = await sdk.subgraph.get_pairs()
print("\nPair Information:") print("----------------------------------------")
for pair in pairs: print("----------------------------------------") # Print all available fields in pair_details for key, value in pair.items(): print(f"{key}: {value}") print("----------------------------------------")
Opening a Trade, Reading Open Trades, Setting TP and SL, Closing a Trade
# Define trade parameters
trade_params = {
'collateral': 100, # USDC amount
'leverage': 10, # Leverage multiplier
'assettype': 0, # 0 for BTC, see pairdetails above for other asset types
'direction': True, # True for Long, False for Short
'order_type': 'MARKET' # 'MARKET', 'LIMIT', or 'STOP'
#'tp': 0, # Take Profit price - if not specified or Zero means no TP
#'sl': 0, # Stop Loss price - if not specified or Zero means no SL
}
try: sdk.ostium.setslippagepercentage(1) print(f"Slippage percentage set to: {sdk.ostium.getslippagepercentage()}%")
# Get latest price for BTC latestprice, , = await sdk.price.getprice("BTC", "USD") print(f"Latest price: {latest_price}") # Execute trade at current market price receipt = sdk.ostium.performtrade(tradeparams, atprice=latestprice) print(f"Trade successful! Transaction hash: {receipt['transactionHash'].hex()}")
# Wait for the transaction to be confirmed await asyncio.sleep(10)
# Get public address from private key account = Account.fromkey(privatekey) traderpublicaddress = account.address
# Get the trade details opentrades = await sdk.subgraph.getopentrades(traderpublic_address) for tradeindex, tradedata in enumerate(open_trades): print(f"Trade {tradeindex + 1}: {tradedata}\n")
if len(open_trades) == 0: print( "No open trades found. Maybe the trade failed? enough USDC and ETH in the account?") else: openedtrade = opentrades[len(open_trades) - 1] print(f"Opened trade: {opened_trade}\n")
sdk.ostium.update_tp( openedtrade['pair']['id'], openedtrade['index'], latest_price * 1.02) print(f"Trade Take Profit set to 2% above the current price!\n")
await asyncio.sleep(10)
sdk.ostium.update_sl( openedtrade['pair']['id'], openedtrade['index'], latest_price * 0.99) print(f"Trade Stop Loss set to 1% below the current price!\n")
await asyncio.sleep(10)
receipt = sdk.ostium.close_trade( openedtrade['pair']['id'], openedtrade['index']) print( f"Closed trade! Transaction hash: {receipt['transactionHash'].hex()}\n")
except Exception as e: print(f"Trade failed: {str(e)}")
NOTE: Use SDK method getopentrade_metrics every so often while trade is open to get the trade's metrics such as:
- Funding fee
- Roll over fee
- Unrealized Pnl and Pnl Percent
- Total Profit
- Liquidation Price
metrics = await sdk.getopentrademetrics(pairid, trade_index)
print(metrics)
Create a Short ETH Limit Order
This example shows how to create a short ETH limit order, 10% above the current ETHUSD price. So if price goes up 10% we order a Short ETH trade.
# Get private key from environment variable
privatekey = os.getenv('PRIVATEKEY')
if not private_key:
raise ValueError("PRIVATE_KEY not found in .env file")
rpcurl = os.getenv('RPCURL') if not rpc_url: raise ValueError("RPC_URL not found in .env file")
Initialize SDK
config = NetworkConfig.testnet()
sdk = OstiumSDK(config, privatekey, rpcurl)
Define trade parameters
order_params = {
'collateral': 10, # USDC amount
'leverage': 50, # Leverage multiplier
'asset_type': 1, # 1 for ETH
'direction': False, # True for Long, False for Short
'order_type': 'LIMIT' # 'MARKET', 'LIMIT', or 'STOP'
}
try: # Get latest price for ETH latestprice, , = await sdk.price.getprice("ETH", "USD") print(f"Latest price: {latest_price}") # Execute LIMIT trade order at 10% above the current price receipt = sdk.ostium.performtrade(orderparams, atprice=latestprice * 1.1) print( f"Order successful! Transaction hash: {receipt['transactionHash'].hex()}")
# Wait for the order to be confirmed await asyncio.sleep(10)
# Get public address from private key account = Account.fromkey(privatekey) traderpublicaddress = account.address
# Get the order details openorders = await sdk.subgraph.getorders(traderpublicaddress) for orderindex, orderdata in enumerate(open_orders): print(f"Order {orderindex + 1}: {orderdata}\n") limittype, , , , , , , pairIndex, index, , = getorderdetails(orderdata) print(f"You can cancellimitorder / updatelimitorder using pair_id: {pairIndex} and index: {index}\n") receipt = sdk.ostium.cancellimitorder(pairIndex, index) print( f"Limit Order cancelled! Transaction hash: {receipt['transactionHash'].hex()}")
if len(open_orders) == 0: print( "No open order found. Maybe the order failed? enough USDC and ETH in the account?") else: openedorder = openorders[len(open_orders) - 1] print(f"Opened order: {opened_order}\n")
except Exception as e: print(f"Order failed: {str(e)}")
NOTE: Similiarly you can create a Stop order, just use 'STOP' as the ordertype and make sure atprice is set to an acceptable stop loss price.
Example Usage Scripts
More examples can be found in the examples folder.
Get Testnet USDC from Faucet
To get testnet USDC tokens (only available on Arbitrum Sepolia testnet):
python examples/example-faucet-request.py
See example-faucet-request.py for an example of how to use the faucet to get testnet USDC tokens.
Read Block Number
To run the example:
python examples/example-read-block-number.py
See example-read-block-number.py for an example of how to use the SDK.
Read Positions
To run the example:
python examples/example-read-positions.py
See example-read-positions.py for an example of how to use the SDK.
Get Feed Prices
To open a trade you need the latest feed price.
See this example script on how to get the latest feed prices.
python examples/example-get-prices.py
See example-get-prices.py for an example of how to use the SDK.
Get Balance of an Address
See this example script on how to get the latest feed prices.
python examples/example-get-balance.py
See example-get-balance.py for an example of how to use the SDK.
Run an example from local install
pip uninstall ostium-python-sdk && pip install -e . && python examples/example-pairs-details.py