Python 串接網路券商 IB 進行全自動美股程式交易
Python + A.I. 股市應用系列;串接券商更新帳務數據、下美股買賣委託單;Interactive Brokers 盈透證券

股仔與新創夥伴合作打造的美股資訊站 — FinGuider,歡迎前往體驗!
小小前言
最近被朋友笑稱是:
『最懶惰的投資人,沒有之一』
因為像是「要買賣哪些股票?」、「什麼時候買賣?」、「資金管理」這類的問題,我是透過 AI 以及量化交易策略去自動分析。
而「交易執行」的部份,我是透過程式串接網路券商去自動完成。
所以在整個美股投資的過程,就只有在入金的時候才需要親自出馬,特地跑一趟銀行去寫麻煩的電匯單,入金之後就沒我的事了!
就結果而言,朋友們的形容確實沒有半點毛病。但他們沒想到的是,要得到這樣「輕鬆」的投資生活之前,必須先付出難以衡量的成本與代價!購買高品質的數據資料;投入大量時間鑽研投資學、美股、AI、程式等等的知識;再花更多的時間與力氣編寫一段又一段的 code,經過無數次的除錯與優化,最終才形成一套完整的投資系統。
熬過了前面那一大段辛苦的付出,後面確實得到了更效率(更懶惰)的生活!一勞永逸,大概就是自己「學程式」的最大動力!
廢話講完,本文要分享什麼?
“幫助大家成為另一個輕鬆愜意的投資人”
如果我們把股市投資的過程簡單地拆成三個環節:
1. 資訊更新 ↙ 2. 投資決策 ↙ 3. 執行交易 ↖ back to 1. 資訊更新
那麼過去寫過的兩篇文章,分別介紹了如何寫程式去自動完成『1. 資訊更新』&『2. 投資決策』的相關內容:
剩下的『3. 執行交易』,希望透過本文內容,幫助大家掌握如何透過 Python 串接網路券商 IB 進行美股全自動程式交易
本文架構
- 前置作業 a) 下載 IB 的 Trader Workstation(簡稱 TWS) b) 開辦 IB 虛擬戶頭 c) 完成 TWS 的設定 d) 安裝 ib-insync 模組 e) 透過 Python 連線 TWS
- 透過 Python 了解 IB 戶頭裡的帳務資訊
- 將投資決策,透過 Python 送出委託單至 IB 進行下單
- 確認交易執行的狀況,對委託單進行修改
- 更新自己投資組合的帳面狀況
學會以上的內容,理論上足以開發自己的自動化程式交易。其他細節,例如:
Q. 為什麼選 IB — Interactive Brokers 盈透證券
Q. 如何開 IB 真實戶以及如何電匯入金
Q. 投資策略怎麼寫?怎麼回測?
Q. 一整套的自動化要怎麼在 Windows 上排程運作其實都是一些不錯的主題,但與本文主軸無關,再另找時間分享吧!
1. 前置作業
a) 下載 IB 的 Trader Workstation(簡稱 TWS)
☀ 前往 IB 的首頁
☀ 在 IB 首頁 Log In 的地方選擇 “Download Trader Workstation”

☀ 選擇最新版即可。下載安裝後,執行 TWS

b) 開辦 IB 虛擬戶頭
☀ 沒有開 IB 的真實帳戶也沒關係,執行 TWS 後會彈出一個登入視窗。點擊下方 “Try the demo”,就可以馬上無痛開辦一個虛擬 demo 帳戶

☀ 透過一個 email 無痛開通 demo 帳戶後,就可以啟動 TWS 囉!

☀ TWS 初始介面的版塊:

c) 完成 TWS 的設定
☀ 點擊 TWS 左上 File 選單中的 “Global Configuration”

☀ 在左選單中點選 “API” → “Settings”,並照著下圖完成設定,Socket port 以及 Master API client ID 內的參數可以修改

d) 安裝 ib-insync 模組
☀ 安裝 ib-insync 模組,這是一個完善的第三方 API,直接幫大家省下極大量的 coding 工作
pip install ib-insync* 如果是 python 3.6 以下的版本,需要再安裝 dataclasses,新版的 python 都不需要裝,已內含了!
pip install dataclassese) 透過 Python 連線 TWS
☀ TWS 必須「保持開啟」著的狀態,我們現在來試試連線吧!
# 匯入模組
from ib_insync import *util.startLoop() # 開啟 Socket 線程
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=123)☀ 在 Console 看到下圖的回傳文字,就表示連線成功囉!

2. 透過 Python 了解 IB 戶頭裡的帳務資訊
☀ 從 TWS 右上的 MONITOR 區塊,切換至 “Portfolio” 分頁後,點擊 “ACCOUNT” 打開這個 demo 帳號的戶頭帳務狀況

☀ 從 TWS 右上的 MONITOR 區塊,切換至 “Portfolio” 分頁後,點擊 “ACCOUNT” 打開這個 demo 帳號的戶頭帳務狀況

☀ 打開 “ACCOUNT” 後,右邊的每一個「+」號都可以展開該分類底下的詳細項目!這裡先介紹其中重要的 3 個項目:
- Cash = 現金,此帳戶有 1,037,875 USD
- Securities Gross Position Value = 持有中的資產的帳面價值,此 demo 是新開的還沒進行交易,目前自然就是 0 USD (註:如果有開期權戶,此項目還包含了期權的價值喔)
- Net Liquidation Value = 就是前兩項的加總,帳戶清算的總價值
☀ 接下來我們就來嘗試透過 Python 下指令取得這 3 個數字吧!
import pandas as pd# 先取得帳戶總覽,'DU228378'是我的 demo 帳號代碼,記得要改成你的 demo 帳號代碼,在 TWS 的右上方尋找
account_summary = ib.accountSummary(account='DU228378')
# 再透過 pandas 轉換為 DataFrame
account_summary_df = pd.DataFrame(account_summary).set_index('tag')♠ 取得 Cash 現金的數字
account_summary_df.loc['AvailableFunds']♠ 取得 Securities Gross Position Value 持有中資產的帳面價值
account_summary_df.loc['GrossPositionValue']♠ 取得 Net Liquidation Value 帳戶清算的總價值
account_summary_df.loc['NetLiquidation']☀ 如此就能輕鬆地掌握帳戶目前的狀況。不管是哪種交易策略,都一定會需要取得這些數字,來進行交易決策的判斷喔!
3. 將投資決策,透過 Python 送出委託單至 IB 進行下單交易
要成功送出委託單,我們要先定義﹝contract 合約﹞以及﹝order 委託單﹞這兩項變數。這裡透過幾個例子進行示範:
♦ 例1:「用市價買進 50 股 TSLA」 ♦ 例2:「用限價 370 買進 100 股 QQQ」
♦ 例1:「用市價買進 50 股 TSLA」# 定義 contract 合約
contract = Contract(
secType='STK', # 買進的是「股票」,就鍵入「STK」
symbol='TSLA', # 鍵入股票代碼
exchange='SMART', # SMART 指的是 TWS 的智能路由,
# 它會根據以下條件找出最佳的交易所
# 1.交易所成本最小化
# 2.執行機率最大化
currency='USD' # 鍵入貨幣單位
)# 定義 order 委託單
order = Order(
action='BUY', # 買進的話就是「BUY」,賣出/放空則是「SELL」
totalQuantity=50, # 這裡要鍵入的是「股」數喔!
orderType='MKT' # 例1下的是「市價單」,參數就是「MKT」
)# 向 TWS 發送委託單!
ib.placeOrder(contract, order)☀ 不到一秒,委託單就送出啦!Windows 右下角會彈出提示通知,這時回到 TWS,就能發現左下角的 ACTIVITY 區塊中,“Orders” 分頁內出現了我們剛剛設定的委託單

♦ 例2:「用限價 360 買進 100 股 QQQ」# 定義 contract 合約
contract = Contract(
secType='STK', # 買進「ETF」的話也是鍵入「STK」
symbol='QQQ', # 鍵入 ETF 代碼
exchange='SMART',
currency='USD'
)# 定義 order 委託單
order = Order(
action='BUY',
totalQuantity=100, # 這裡要鍵入的是「股」數喔!
orderType='LMT', # 例2下的是「限價單」,參數就是「LMT」
lmtPrice=370, # ★ 限價單會多一個參數,設定「掛單價格」★
)# 向 TWS 發送委託單!
ib.placeOrder(contract, order)
4. 確認交易執行的狀況,對委託單進行修改
☀ 先觀察一下 TWS。如果不是流動性太差的標的,基本上「市價單」執行成功的機會很高,我們就可以從右上 MONITOR 區塊的 “Portfolio” 中,看到帳面持股了!

☀ 而左下 ACTIVITY 區塊的 “Orders” 中,可以明顯看出兩筆委託單成交與否的差別。

☀ 切至 “Trades” 分頁,可以得到更詳細的成交資訊

看完了 TWS,接下來我們試試透過 Python API 來完成以下幾件事:
♦ 例3: 確認成交狀況 ♦ 例4: 掌握交易委託的資訊 ♦ 例5:「修改」一筆委託單 ♦ 例6:「取消」一筆委託單
♦ 例3: 確認成交狀況# 透過這個函數,可以確認交易執行的情況
ib.executions()備註:如果所有委託單都沒有成交,就會回傳一個空的 list
♦ 例4: 掌握交易委託的資訊# 透過這個函數,可以取得未執行完畢的交易委託
open_trades = ib.openTrades()檢視了一下 open_trades 會發現資訊量過多,各位針對自己所需去取值即可。這裡簡單做個示範,整理出一個記載重點資訊的 DataFrame
# 寫函數,從 open_trades 中的每一筆物件取值
def open_trade_info(trade_object):
return {
'orderId': trade_object.order.orderId,
'action': trade_object.order.action,
'totalQuantity': trade_object.order.totalQuantity,
'orderType': trade_object.order.orderType,
'lmtPrice': trade_object.order.lmtPrice,
'secType': trade_object.contract.secType,
'symbol': trade_object.contract.symbol
}# 整理成 DataFrame
open_trades_df = pd.DataFrame(list(map(lambda x: open_trade_info(x), open_trades)))
♦ 例5:「修改」一筆委託單
假設要修改剩下來的那筆委託單:
→ QQQ 買 80 股就好,不買 100 股了
→ 限價股價也從 370 改成 375 好了
以上要怎麼修改呢?# 首先我們需要辨識出要修的這筆委託單的專屬代號
loc_index = open_trades_df.index[open_trades_df.symbol == 'QQQ'][0]
modify_id = open_trades_df.loc[loc_index, 'orderId']# 跟前面一樣定義 contract 以及 order,但這次 order 裡要增加 orderId 這參數
contract = Contract(
secType='STK',
symbol='QQQ',
exchange='SMART',
currency='USD'
)
order = Order(
orderId=modify_id, # ★ 鍵入剛剛找到的專屬代號 ★
action='BUY',
totalQuantity=80, # 從 100 股修改成 80 股
orderType='LMT',
lmtPrice=375, # 從限價 370 修改成 375
)# 向 TWS 發送,就能對正在掛著的委託單進行修改了!
ib.placeOrder(contract, order)
♦ 例6:「取消」一筆委託單 假設要把一筆委託單取消掉,該怎麼做呢?
# 記得要定期更新 open_trades_df(見例4)# 一樣要先辨識出該筆委託單的專屬代號
cancel_id = open_trades_df# 定義 order 委託單,這次只要指出要取消委託單的專屬代號即可
order = Order(
orderId=cancel_id # ★ 鍵入該筆委託單的專屬代號 ★
)# 向 TWS 發送 cancelOrder,取消掉正在掛著的委託單!
ib.cancelOrder(order)
5. 更新自己投資組合的帳面狀況
大家可以先多練習下一些交易委託,讓投組豐富起來,再進行下一步驟喔!

☀ 投資組合豐富起來後,我們現在就來試試看透過 Python 獲取投資組合的資訊吧!
♦ 例7: 更新取得投資組合的資訊# 透過這個函數,可以輕鬆取得投資組合的資訊
portfolio_data = ib.portfolio()跟例4 非常相似,我們針對自己需求,將 portfolio_data 的資訊整理成 DataFrame# 寫函數,從 portfolio_data 中的每一筆物件取值
def portfolio_info(asset_object):
return {
'symbol': asset_object.contract.symbol,
'primaryExchange': asset_object.contract.primaryExchange,
'currency': asset_object.contract.currency,
'position': asset_object.position,
'marketPrice': asset_object.marketPrice,
'marketValue': asset_object.marketValue,
'averageCost': asset_object.averageCost,
'unrealizedPNL': asset_object.unrealizedPNL,
'realizedPNL': asset_object.realizedPNL
}# 整理成 DataFrame
portfolio_data_df = pd.DataFrame(list(map(lambda x: portfolio_info(x), portfolio_data)))
本文 END
以上的內容,是程式交易當中幾個關鍵的基礎環節,希望可以有效幫助大家無痛進入程式交易的領域。
熟悉基本後,可以進一步閱讀 TWS API 的設計規則,以及 ib-insync 模組的參數內容。
最後就可以結合自己的投資策略邏輯,開發出完善的自動化程式交易系統,享受更愜意的投資生活囉!
感謝各位看完這篇教學文!希望內容對你有幫助!☀
如果覺得文章還不錯,希望可以幫我一個小忙, 那就是按下『拍拍手』以及『分享』出去啦~ 感謝各位!♥






