下單系統
分析完元富證券的下單系統 Python API 之後,我們就可以基於自己的需求,開發一個下單系統。
在大多數的情境下,我們只會單獨操作一個證券帳戶,所以我們目前的實作是基於單一帳號的情境。
我們不推薦任何股票,所有關於證券戶內的股票資訊都會以馬賽克處理。
登入帳號
你可以直接把帳號密碼寫在類別的輸入中,也可以參考我們的寫法:使用一個 yaml 檔案來儲存帳號資訊。
參數檔案中,必須有帳號密碼和帳號號碼,這樣才能順利登入元富證券的帳號。
from autotraderx import load_yaml
from autotraderx.masterlink import Trader
# Load account infos
cfg = load_yaml(DIR / "account.yaml")
# Login account
account = Trader(
    user=cfg["user"],
    password=cfg["password"],
    account_number=str(cfg["account_number"]),
    is_sim=False,
    is_force=True,
    is_event=False,
)
account.login()
# Do something
account.stop()
查詢庫存
登入帳號,呼叫 get_inventory 函數,就可以查詢目前的庫存狀況。
查詢結果會直接顯示在命令列中,我們可以看到目前的庫存狀況,如果要取得資訊做進一步地使用,可以直接使用回傳值。
data = account.get_inventory()

其中,data 的輸出格式為一個字典,內容像是:
{
    '2002': {
        '股票': '中鋼',
        '融券庫存(張)': '0',
        '融資庫存(張)': '0',
        '集保庫存(張)': '1',
        '零股庫存(股)': '0'
    },
    '2330': {
        '股票': '台積電',
        '融券庫存(張)': '0',
        '融資庫存(張)': '0',
        '集保庫存(張)': '1',
        '零股庫存(股)': '0'
    },
    # ...以下省略
}
如果不需要顯示在命令列,可以在初始化 Trader 時,設定 verbose 參數為 False。
account = Trader(
    verbose=False
)
查詢委託資訊
登入帳號,呼叫 get_order_report 函數,就可以查詢目前的所有委託資訊。
查詢結果會直接顯示在命令列中,我們可以看到目前的所有委託資訊,如果要取得資訊做進一步地使用,可以直接使用回傳值。

data = account.get_order_report()
其中,data 的輸出格式為 List[Dict],內容像是:
[
    {
        '委託價': '13.95',
        '委託方式(價格)': '限價單',
        '委託方式(效期)': '當日有效',
        '委託時間': '08:31:32.032000',
        '委託書號': 'i0040',
        '委託量': '4000',
        '成交價': '',
        '成交時間': '',
        '成交量': '',
        '狀態': '',
        '股票': '馬賽克',
        '股票代號': '馬賽克',
        '訊息': '',
        '買賣別': 'Sell',
        '類型': '委託訂單'
    },
    # ...以下省略
]
查詢成交資訊
登入帳號,呼叫 get_trade_report 函數,就可以查詢目前的所有成交資訊。
查詢結果會直接顯示在命令列中,我們可以看到目前的所有成交資訊,如果要取得資訊做進一步地使用,可以直接使用回傳值。

data = account.get_trade_report()
其中,data 的輸出格式為 List[Dict],內容像是:
[
    {
        '委託價': '13.95',
        '委託方式(價格)': '限價單',
        '委託方式(效期)': '當日有效',
        '委託時間': '08:31:32.032000',
        '委託書號': 'i0040',
        '委託量': '4000',
        '成交價': '',
        '成交時間': '09:00:11.609000',
        '成交量': '4000',
        '狀態': '111)全部成交',
        '股票': '馬賽克',
        '股票代號': '馬賽克',
        '訊息': '',
        '買賣別': 'Sell',
        '類型': '委託訂單'
    },
    # ...以下省略
]
下單定義型別
在下單的過程中,元富證券定義了幾個常數,我們需要先了解這些常數的意義。
OrderType
# 委託方式(效期)
class OrderType(str, Enum):
    # 當日有效
    ROD = "R"
    # 立即成交,否則取消
    IOC = "I"
    # 立即全部成交,否則取消
    FOK = "F"
PriceType
# 委託方式(價格)
class PriceType(str, Enum):
    # 限價單
    LMT = "L"
    # 市價單
    MKT = "M"
TradingType
# 委託別
class TradingType(str, Enum):
    # 集保
    CUSTODY = "G"
TradingUnit
# 交易單位
class TradingUnit(int,Enum):
    COMMON = 1000
    ODD = 1
TradingSession
# 交易時段
class TradingSession(str, Enum):
    # 普通
    NORMAL = "N"
    # 盤後
    FIXED_NORMAL = "F"
    # 盤中零股
    ODD = "R"
    # 盤後零股
    FIXED_ODD = "L"
Side
# 買賣別
class Side(str, Enum):
    # 買進
    Buy = "B"
    # 賣出
    Sell = "S"
下單買進
登入帳號,呼叫 buy 函數,就可以下買進單。
例如,買進台積電(股票代號:2330) 1 張,價格為 500 元。
預設下單方式:
- 價格類型:OrderType.KMT, 限價單
 - 委託類型:PriceType.ROD, 當日有效
 - 交易時段:TradingSession.NORMAL, 一般交易時段
 - 交易單位:TradingUnit.COMMON, 一般交易單位
 
account.buy(symbol="2330", qty=1, price=500)
下單賣出
登入帳號,呼叫 sell 函數,就可以下賣出單。
例如,賣出台積電(股票代號:2330) 1 張,價格為 500 元。
預設下單方式:
- 價格類型:OrderType.KMT, 限價單
 - 委託類型:PriceType.ROD, 當日有效
 - 交易時段:TradingSession.NORMAL, 一般交易時段
 - 交易單位:TradingUnit.COMMON, 一般交易單位
 
account.sell(symbol="2330", qty=1, price=500)
自定義下單方式
登入帳號,呼叫 set_order 函數,就可以下自定義單。
以下展示了 set_order 函數的定義,依照你的需求,自行設定下單方式。
 def set_order(
        self,
        symbol: str,    # 股票代號
        side: Side,     # 買賣別
        qty: int,       # 委託股數
        price: float,   # 委託價格
        order_type: OrderType = OrderType.ROD,  # 委託類型
        price_type: PriceType = PriceType.MKT,  # 價格類型
        trading_session: TradingSession = TradingSession.NORMAL,  # 交易時段
        trading_unit: TradingUnit = TradingUnit.COMMON,  # 交易單位
    ):
        self.api.ReqBasic(symbol)
        order = Order(
            tradingSession=trading_session,
            side=side,
            symbol=symbol,
            priceType=price_type,
            price=str(price),
            tradingUnit=trading_unit,
            qty=str(qty),
            orderType=order_type,
            tradingAccount=self.account_number,
            userDef=''
        )
        rc = self.api.NewOrder(order)
        if rc == RCode.OK:
            print(u'已送出委託')
        else:
            print(u'下單失敗! 請再次執行程式,依據回報資料修正輸入')
在 set_order 函數中,若要買進 1 張,則 qty 參數應該為 1000。
例如:買進台積電(股票代號:2330) 1 張,價格為 500 元,委託類型為立即全部成交,價格類型為市價單。
account.set_order(
    symbol="2330",
    side=Side.Buy,
    qty=1000,
    price=500,
    order_type=OrderType.FOK,
    price_type=PriceType.MKT
)
改價
必須先找到要改價的「委託單號」,然後呼叫 change_price 函數,就可以改價。
例如,台積電(股票代號:2330)改價,新價格為 600 元。
account.change_price(order_number="i0041", mod_price=600)
改量
必須先找到要改量的「委託單號」,然後呼叫 change_qty 函數,就可以改量。
例如,台積電(股票代號:2330)改量,從 1 張改為 2 張。
account.change_qty(order_number="i0041", mod_qty=2000)
刪單
使用改量的方式,將「委託量」改為 0,就是刪單。
其他功能
原始的 API 還有查詢資券餘額的功能,由於我們目前手邊的帳號沒有開通相關權限,所以我們暫時無法針對這些功能進行開發測試。
此外,我們沒有在元富證券的 API 中找到「查詢帳戶庫存成交價的資訊」,於是嘗試從程式碼下去追蹤,我們發現最後的資料填充層被封裝在 .dll 檔案內,如果要取得這些資料,還要再對 .dll 進行反編譯後,再進行資料的解析......,這個工作量對於我們來說有點大!
總之,我們目前無法提供「計算庫存均價」的服務,祈禱未來元富證券可以把這個功能開放出來。
如果你知道該如何取得「庫存均價」,也就是「每張庫存的成交價」的資訊,拜託告訴我們!🙏 🙏 🙏