Skip to content

非阻塞模式範例

首先,讓我們來了解什麼是「Blocking」?如果一個函數需要等待某些操作完成才能繼續執行,那麼它就是一個「blocking」函數。無論你是進行 I/O 或是 CPU 相關任務,每個函數都是 blocking 的,因為任何操作都需要花費一定的時間。如果一個函數正在執行需要大量 CPU 運算的任務,那麼它會阻止該函數返回;同樣地,如果一個函數正在試圖從數據庫中取得某些資料,它會一直等待結果返回,直到結果返回為止才繼續執行。

相反,當執行非阻塞(non-blocking)操作時,它永遠不會等待操作完成。如果嘗試在短時間內發送大量請求,非阻塞模式非常有用。為了讓您了解阻塞和非阻塞模式之間的區別,我們提供了一些比較的例子。

Shioaji提供 Blocking 和 Non-Blocking 模式,只需設定 timeout 的值即可。timeout預設為5000(毫秒),表示函數最多等待5秒。

非阻塞模式下單

PlaceOrder 函數中設置 timeout = 0

In

IContract contract = _api.Contracts.Stocks["TSE"]["2890"];
var stockOrder = new StockOrder()
{
    price = 16.4,
    quantity = 1,
    action = Action.Buy,
    price_type = StockPriceType.LMT,
    order_type = StockOrderType.ROD,
    order_lot = StockOrderLot.Common,
    first_sell = StockFirstSell.No,
    custom_field = "914"
};
var trade = new Trade();
trade = _api.PlaceOrder(
                contract:contract, 
                order:stockOrder, 
                timeout:0, 
                cb:order_cb
            );
Console.WriteLine(trade);

Out

{
    contract={
        security_type=STK, 
        code=2890, 
        symbol=TSE2890, 
        exchange=TSE, 
        limit_up=19.1, 
        limit_down=15.7, 
        reference=17.4, 
        margin_trading_balance=0, 
        short_selling_balance=0, 
        update_date=2022/09/26, 
        category=17, 
        day_trade=Yes, 
        name=永豐金,
    }, 
    order={
        action=Buy, 
        price=15.7, 
        quantity=1, 
        price_type=LMT, 
        order_type=ROD, 
        order_lot=Common, 
        order_cond=Cash, 
        first_sell=false, 
        account={
            account_type=S, 
            person_id=PERSON_ID, 
            broker_id=BROKER_ID, 
            account_id=ACCOUNT_ID, 
            signed=True, 
            username=USERNAME,
            }, 
        custom_field=test, 
        ca=,
    }, 
    status={
        status=Inactive, 
        order_ts=0, 
        modified_ts=0, 
        modified_price=0, 
        deal_quantity=0, 
        cancel_quantity=0,
    },
}

在非阻塞模式中取得的Trade物件,因為委託單仍在傳輸中還未送至交易所,所以會缺少一些資訊。在Order物件中沒有idseqnoOrderStatus物件中沒有 idstatus_codeorder_datetimeDealsstatus顯示為Inactive。在非阻塞模式中要取得上述提到的資訊可利用委託回報非阻塞模式下單回調兩種方式。

委託回報

Out

OrderState.StockOrder {
    "operation": {
        "op_type": "New",
        "op_code": "00",
        "op_msg": ""
    },
    "order": {
        "id": "8bbe0c24",
        "seqno": "612978",
        "ordno": "IB919",
        "account": {
            "account_type": "S",
            "person_id": "",
            "broker_id": "",
            "account_id": "",
            "signed": true
        },
        "action": "Buy",
        "price": 15.7,
        "quantity": 1,
        "order_type": "ROD",
        "price_type": "LMT",
        "order_cond": "Cash",
        "order_lot": "Common",
        "custom_field": "914"
    },
    "status": {
        "id": "8bbe0c24",
        "exchange_ts": 1664152597,
        "modified_price": 0,
        "cancel_quantity": 0,
        "order_quantity": 1,
        "web_id": "137"
    },
    "contract": {
        "security_type": "STK",
        "exchange": "TSE",
        "code": "2890",
        "symbol": "",
        "name": "",
        "currency": "TWD"
    }
}

非阻塞模式下單回調

In

private static void PlaceOrder(Shioaji _api)
{
    IContract contract = _api.Contracts.Stocks["TSE"]["2890"];
    var stockOrder = new StockOrder()
    {
        price = 15.7,
        quantity = 1,
        action = Action.Buy,
        price_type = StockPriceType.LMT,
        order_type = StockOrderType.ROD,
        order_lot = StockOrderLot.Common,
        first_sell = StockFirstSell.No,
        custom_field = "test"
    };
    var trade = _api.PlaceOrder(
                        contract:contract, 
                        order:stockOrder, 
                        timeout:0, 
                        cb:order_cb // only work in non-blocking mode
                    );
}

private static void order_cb(Trade trade) 
{
    Console.WriteLine($"MY_ORDER_CB: {trade}");
}

Out: place order callback

MY_ORDER_CB: {
    contract={
        security_type=STK, 
        code=2890, 
        symbol=TSE2890, 
        exchange=TSE, 
        limit_up=19.1, 
        limit_down=15.7, 
        reference=17.4, 
        margin_trading_balance=0, 
        short_selling_balance=0, 
        update_date=2022/09/26, 
        category=17, 
        day_trade=Yes, 
        name=永豐金,
    }, 
    order={
        action=Buy, 
        price=15.7, 
        quantity=1, 
        price_type=LMT, 
        order_type=ROD, 
        order_lot=Common, 
        order_cond=Cash, 
        first_sell=false, 
        id=8bbe0c24, 
        seqno=612978, 
        ordno=IB919, 
        account={
            account_type=S, 
            person_id=PERSON_ID, 
            broker_id=BROKER_ID, 
            account_id=ACCOUNT_ID, 
            signed=True, 
            username=USERNAME,
        }, 
        custom_field=test, 
        ca=,
    }, 
    status={
        id=8bbe0c24, 
        status=PendingSubmit, 
        status_code=0, 
        order_ts=1664152597, 
        msg=委託成功, 
        modified_ts=0, 
        modified_price=0, 
        deal_quantity=0, 
        cancel_quantity=0,
    },
}

支援非等待模式的函數

- PlaceOrder
- UpdateOrder
- CancelOrder
- UpdateStatus