StreamOrders RPC provides a bidirectional streaming interface for sending Add, Modify, and Cancel order requests and receiving responses.

Example Requests

Add Order

import os

import grpc
from port import port_pb2
from port import port_pb2_grpc
from common import common_pb2

API_KEY = os.getenv("QFEX_API_KEY")

def stream_orders(): # Attach API key metadata
    metadata = (("api-key", API_KEY),)
    channel = grpc.secure_channel("trade.pfex.io:443", grpc.ssl_channel_credentials())
    stub = port_pb2_grpc.PortServiceStub(channel)

    # Generator for sending requests
    def request_generator():
        # Add a limit buy order
        yield port_pb2.OrdersStreamRequest(
            add_order=port_pb2.AddOrderRequest(
                symbol="SP500-USD",
                side=common_pb2.OrderDirection.BUY,
                type=common_pb2.OrderType.LIMIT,
                time_in_force=common_pb2.OrderTimeInForce.GTC,
                price=530.50,
                quantity=0.1,
                client_order_id="order-id-123",
            )
        )

    # Bidirectional streaming call
    responses = stub.StreamOrders(request_generator(), metadata=metadata)
    for response in responses:
        print("Response:", response)

if __name__ == "__main__":
    stream_orders()

Cancel Order

You can cancel an order in two ways: 1. By order_id: Cancels the single order matching that unique identifier. 2. By client_order_id: Cancels all orders for your account that share the same client_order_id. Uniqueness is not enforced, so multiple orders may be cancelled at once.

import os

import grpc
from port import port_pb2
from port import port_pb2_grpc
from common import common_pb2

API_KEY = os.getenv("QFEX_API_KEY")

def stream_orders(): # Attach API key metadata
metadata = (("api-key", API_KEY),)
channel = grpc.secure_channel("trade.pfex.io:443", grpc.ssl_channel_credentials())
stub = port_pb2_grpc.PortServiceStub(channel)

    # Generator for sending requests
    def request_generator():
        # Cancenl an buy order
        yield port_pb2.OrdersStreamRequest(
            cancel_order=port_pb2.CancelOrderRequest(
                symbol="SP500-USD",
                client_order_id="order-id-123",
            )
        )

    # Bidirectional streaming call
    responses = stub.StreamOrders(request_generator(), metadata=metadata)
    for response in responses:
        print("Response:", response)

if **name** == "**main**":
stream_orders()

Modify Order

You can only modify orders by orderId.

This is to prevent modifications of inflight orders. If you must modify an order before receiving an ACK, cancel the order and re-add it.

You cannot modify an order that has been partially filled.

import os

import grpc
from port import port_pb2
from port import port_pb2_grpc
from common import common_pb2

API_KEY = os.getenv("QFEX_API_KEY")

def stream_orders(): # Attach API key metadata
metadata = (("api-key", API_KEY),)
channel = grpc.secure_channel("trade.pfex.io:443", grpc.ssl_channel_credentials())
stub = port_pb2_grpc.PortServiceStub(channel)

    # Generator for sending requests
    def request_generator():
        # Modify a buy order
        yield port_pb2.OrdersStreamRequest(
            modify_order=port_pb2.ModifyOrderRequest(
                symbol="SP500-USD",
                price=530.60,
                quantity=0.2,
                order_id="abc12345-12345-12345-12345",
            )
        )

    # Bidirectional streaming call
    responses = stub.StreamOrders(request_generator(), metadata=metadata)
    for response in responses:
        print("Response:", response)

if **name** == "**main**":
stream_orders()

Full Example Code

import os

import grpc
import port_pb2
import port_pb2_grpc
import common_pb2

API_KEY = os.getenv("QFEX_API_KEY")

def stream_orders(): # Attach API key metadata
metadata = (('api-key', API_KEY),)
channel = grpc.secure_channel('trade.pfex.io:443', grpc.ssl_channel_credentials())
stub = port_pb2_grpc.PortServiceStub(channel)

    # Generator for sending requests
    def request_generator():
        # Add a limit buy order
        yield port_pb2.OrdersStreamRequest(
            add_order=port_pb2.AddOrderRequest(
                symbol="SP500-USD",
                side=common_pb2.OrderDirection.BUY,
                type=common_pb2.OrderType.LIMIT,
                time_in_force=common_pb2.OrderTimeInForce.GTC,
                price=560.50,
                quantity=0.1,
                client_order_id="order-id-123"
            )
        )
        # Modify an existing order.
        yield port_pb2.OrdersStreamRequest(
            modify_order=port_pb2.ModifyOrderRequest(
                order_id="abc12345-12345-12345-12345", # Note, for modifies we must use the order_id not client_order_id
                symbol="SP500-USD",
                price=560.60,
                quantity=0.2
            )
        )
        # Cancel an existing order
        yield port_pb2.OrdersStreamRequest(
            cancel_order=port_pb2.CancelOrderRequest(
                client_order_id="order-id-123", # Note, for cancels we can use either the client_order_id or order_id
                symbol="SP500-USD"
            )
        )

    # Bidirectional streaming call
    responses = stub.StreamOrders(request_generator(), metadata=metadata)
    for response in responses:
        print("Response:", response)

if **name** == '**main**':
stream_orders()

Example Response

This response is for an Add Order request. For Modify and Cancel requests, the response will be the same but with the status field set to MODIFIED or CANCELLED respectively. If any field returns the default value, it will not be printed to console.

order_id: "510333ac-3f7b-4d88-934a-4396d48824cc"
symbol: "SP500-USD"
quantity: 0.1
status: ACK
price: 560.5
update_time {
  seconds: 1746908349
  nanos: 465551861
}
user_id: "abc12345-6e54-48c4-82e9-641e64bf185d"
client_order_id: "order-id-123"
quantity_remaining: 0.1