Order (Single Strategy)
Broker Integration - Taiwan Market
The live order execution system currently integrates with Taiwan-based brokers (E.SUN Securities, Sinopac Securities, Masterlink Securities, and Fubon Securities). For US market trading, please use your broker's native API. The position calculation and portfolio management features of FinLab can still be used to generate target positions for any market.
Execute Trading Strategy
The current trading system requires finlab>=0.3.0.dev1. Before placing orders, please make sure you have the latest version installed.
First, run your strategy before the next trading day opens:
Calculate Share Quantities
Next, display the current positions:
| stock_id | entry_date | exit_date | entry_sig_date | exit_sig_date | position | period | entry_index | exit_index | return | entry_price | exit_price | mae | gmfe | bmfe | mdd | pdays | next_weights |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1416 | 2021-10-01 | NaT | 2021-09-30 | 2022-06-30 | 0.510197 | 159.0 | 3566.0 | -1.0 | -3.539823e-02 | 10.60 | NaN | -0.053097 | 0.070796 | 0.070796 | -0.115702 | 37.0 | 0.060665 |
| 1453 | 2021-10-01 | NaT | 2021-09-30 | 2022-06-30 | 0.510197 | 159.0 | 3566.0 | -1.0 | 2.348165e+00 | 8.43 | NaN | -0.086763 | 2.403782 | 0.245829 | -0.624585 | 60.0 | 0.171264 |
| 1524 | 2022-04-01 | NaT | 2022-03-31 | 2022-06-30 | 0.611632 | 39.0 | 3686.0 | -1.0 | -3.330669e-16 | 10.60 | NaN | -0.476658 | 0.015152 | 0.000000 | -0.476658 | 2.0 | 0.122168 |
| 2543 | 2021-10-01 | NaT | 2021-09-30 | NaT | 0.510197 | 159.0 | 3566.0 | -1.0 | 1.073232e-01 | 7.46 | NaN | -0.063131 | 0.363636 | 0.008838 | -0.268519 | 44.0 | 0.070298 |
| 2701 | 2022-04-01 | NaT | 2022-03-31 | 2022-06-30 | 0.611632 | 39.0 | 3686.0 | -1.0 | -3.330669e-16 | 12.05 | NaN | -0.025105 | 0.029289 | 0.029289 | -0.052846 | 18.0 | 0.063107 |
Once confirmed, calculate the number of lots (1 lot = 1000 shares in Taiwan) for each stock:
from finlab.online.order_executor import Position
# total fund
fund = 1000000
position = Position.from_report(report, fund)
print(position)
The Position above indicates that your account should hold 1 lot of 2330 (TSMC), using cash settlement.
Advanced Position Adjustments
Odd Lot Trading
To use odd lot positions, simply modify the code as follows:
# Round lots
position = Position.from_report(report, fund)
# Odd lots
position = Position.from_report(report, fund, odd_lot=True)
Custom Position Quantities
The above method uses Position.from_report to construct positions, but you can also build positions intuitively:
[{'stock_id': '2330', 'quantity': 1, 'order_condition': <OrderCondition.CASH: 1>}
{'stock_id': '1101', 'quantity': 1.001, 'order_condition': <OrderCondition.CASH: 1>}]
Position Addition/Subtraction
Position objects support addition and subtraction:
# Remove 1 lot of 2330
new_position = position - Position({'2330': 1})
# Add 1 lot of 1101
new_position = position + Position({'1101': 1})
Multi-Strategy Position Aggregation
If you have multiple positions, you can aggregate them:
from finlab import backtest
from finlab.online.order_executor import Position
report1 = backtest.sim(...)
report2 = backtest.sim(...)
position1 = Position.from_report(report1, 1000000) # Strategy fund: 1 million
position2 = Position.from_report(report2, 1000000) # Strategy fund: 1 million
total_position = position1 + position2
Placing Orders
1. Install Broker API
Currently supports E.SUN Securities, Sinopac Securities, Masterlink Securities, and Fubon Securities trading systems. Choose one:
2. Connect to Brokerage Account
Currently supports E.SUN Securities, Sinopac Securities, Masterlink Securities, and Fubon Securities trading systems. You can set the account credentials as environment variables. You only need to configure for the broker you use; no need to connect multiple brokers simultaneously.
Choose your broker
- First, follow the config tutorial to obtain the config file.
- Then log in to the E.SUN Securities API to get the market data Token.
from finlab.online.esun_account import EsunAccount
import os
os.environ['ESUN_CONFIG_PATH'] = 'path to config.ini.example'
os.environ['ESUN_MARKET_API_KEY'] = 'E.SUN market API Token'
os.environ['ESUN_ACCOUNT_PASSWORD'] = 'E.SUN account password'
os.environ['ESUN_CERT_PASSWORD'] = 'E.SUN certificate password'
acc = EsunAccount()
Legacy Fugle environment variables (still supported)
from finlab.online.fugle_account import FugleAccount
import os
os.environ['FUGLE_CONFIG_PATH'] = 'path to config.ini.example'
os.environ['FUGLE_MARKET_API_KEY'] = 'market API Token'
os.environ['FUGLE_ACCOUNT_PASSWORD'] = 'account password'
os.environ['FUGLE_CERT_PASSWORD'] = 'certificate password'
acc = FugleAccount()
If you encounter error codes during trading, check the E.SUN Securities documentation for the cause. If you are unfamiliar with FinLab Package trading, it is also recommended to practice with the broker's tutorial first.
-
Please obtain the certificate first:
- Windows certificate download
- MacOS certificate: Currently Sinopac supports MacOS for trading but does not support obtaining certificates on MacOS. You can first use a Windows machine to obtain the certificate, then use it on MacOS.
import os
from finlab.online.sinopac_account import SinopacAccount
os.environ['SHIOAJI_API_KEY'] = 'Sinopac API_KEY'
os.environ['SHIOAJI_SECRET_KEY'] = 'Sinopac SECRET_KEY'
os.environ['SHIOAJI_CERT_PERSON_ID']= 'National ID number'
os.environ['SHIOAJI_CERT_PATH']= 'Sinopac certificate path'
os.environ['SHIOAJI_CERT_PASSWORD'] = 'Sinopac certificate password' # defaults to National ID
acc = SinopacAccount()
Refer to the Masterlink Securities tutorial to obtain the certificate, place it in the appropriate path, install the required packages, and then run:
import os
from finlab.online.masterlink_account import MasterlinkAccount
os.environ['MASTERLINK_NATIONAL_ID'] = 'National ID number'
os.environ['MASTERLINK_ACCOUNT'] = 'Trading account'
os.environ['MASTERLINK_ACCOUNT_PASS'] = 'Password'
os.environ['MASTERLINK_CERT_PATH'] = 'Masterlink certificate path'
os.environ['MASTERLINK_CERT_PASS'] = 'Masterlink certificate password' # defaults to National ID
acc = MasterlinkAccount()
Setup is now complete!
Refer to the Fubon Securities tutorial to obtain the certificate, place it in the appropriate path, install the required packages, and then run:
import os
from fubon_account import FubonAccount
# Set environment variables
import os
os.environ['FUBON_NATIONAL_ID'] = "A123456789"
os.environ['FUBON_ACCOUNT_PASS'] = "your_password"
os.environ['FUBON_CERT_PATH'] = "/path/to/cert.pfx"
account = FubonAccount()
Setup is now complete!
3. Batch Order Execution
Finally, use OrderExecutor to adjust the brokerage account's positions according to the target position.
from finlab.online.order_executor import OrderExecutor
# Order Executor
order_executer = OrderExecutor(position , account=acc)
If the position contains "full-delivery stocks", "disposition stocks", or "alert stocks", you must pre-deposit funds at your brokerage account first.
After completing the deposit based onshow_alerting_stocks results, proceed with order execution:
# Preview orders (view-only mode, no actual orders placed)
order_executer.create_orders(view_only=True)
# Execute orders (will actually place orders; test during market close for first-time use)
# Default: uses the latest transaction price as the limit price
order_executer.create_orders()
# Update limit price (use the latest transaction price as new limit price)
order_executer.update_order_price()
# Cancel all pending orders
order_executer.cancel_orders()
View Account Positions
For any supported broker account, you can check positions as follows:
# Choose your broker (pick one)
# Sinopac
from finlab.online.sinopac_account import SinopacAccount
acc = SinopacAccount()
# E.SUN Securities
from finlab.online.esun_account import EsunAccount
acc = EsunAccount()
# Or use the legacy name (still supported)
# from finlab.online.fugle_account import FugleAccount
# acc = FugleAccount()
print(acc.get_position())
[{'stock_id': '2330', 'quantity': 1, 'order_condition': <OrderCondition.CASH: 1>}
{'stock_id': '1101', 'quantity': 1.001, 'order_condition': <OrderCondition.CASH: 1>}]
Common Errors and Solutions
Important Risk Warning
Live trading involves real money. Errors can lead to financial losses!
Check before placing orders:
1. Test on a simulated account for at least 1 week
2. Initial capital should not exceed 10-20% of total funds
3. Use view_only=True to preview orders
4. Monitor positions and order status daily
5. Set stop-loss mechanisms to avoid large single-trade losses
Error 1: Account Connection Failure
Symptom: acc = SinopacAccount() or acc = EsunAccount() throws a connection error
from finlab.online.sinopac_account import SinopacAccount
acc = SinopacAccount()
# ConnectionError: Unable to connect to broker API
Causes: - Environment variables not correctly set (API KEY, certificate path, etc.) - Certificate file does not exist or path is wrong - Certificate password is incorrect - Network connection issue or broker API service is down
Solution:
import os
from finlab.online.sinopac_account import SinopacAccount
# Step 1: Check if environment variables are set
required_env_vars = [
'SHIOAJI_API_KEY',
'SHIOAJI_SECRET_KEY',
'SHIOAJI_CERT_PERSON_ID',
'SHIOAJI_CERT_PATH',
'SHIOAJI_CERT_PASSWORD'
]
print("=== Environment Variable Check ===")
for var in required_env_vars:
value = os.environ.get(var)
if value:
# Hide sensitive information
if 'KEY' in var or 'PASSWORD' in var:
print(f"{var}: {'*' * 8} (set)")
else:
print(f"{var}: {value}")
else:
print(f"{var}: NOT SET")
# Step 2: Check if certificate file exists
cert_path = os.environ.get('SHIOAJI_CERT_PATH')
if cert_path and os.path.exists(cert_path):
print(f"\nCertificate file exists: {cert_path}")
else:
print(f"\nCertificate file not found: {cert_path}")
print("Please verify the certificate path is correct")
exit(1)
# Step 3: Attempt connection and catch errors
try:
acc = SinopacAccount()
print("\nAccount connected successfully")
except FileNotFoundError as e:
print(f"\nCertificate file error: {e}")
print("Check SHIOAJI_CERT_PATH")
except PermissionError as e:
print(f"\nCertificate permission error: {e}")
print("Check certificate password (SHIOAJI_CERT_PASSWORD)")
except ConnectionError as e:
print(f"\nNetwork connection error: {e}")
print("Possible causes:")
print("1. Unstable network connection")
print("2. Broker API service temporarily unavailable")
print("3. Incorrect API KEY or SECRET KEY")
except Exception as e:
print(f"\nUnknown error: {e}")
print("Check all environment variables are correctly set")
Error 2: Pre-Order Safety Check Failure
Symptom: Insufficient funds, too many holdings, or single stock weight too high
Solution: Implement multi-layer safety checks
from finlab.online.order_executor import OrderExecutor, Position
from finlab.online.sinopac_account import SinopacAccount
# Use example
try:
acc = SinopacAccount()
position = Position.from_report(report, fund=1000000)
# Execute order
order_executor = OrderExecutor(position, account=acc)
# Preview first (no actual orders)
print("\n=== Preview Orders ===")
order_executor.create_orders(view_only=True)
# After confirmation, execute orders
# order_executor.create_orders() # Uncomment to actually place orders
except ValueError as e:
print(f"\n{e}")
print("\nPlease fix the issue before placing orders")
except Exception as e:
print(f"\nUnexpected error: {e}")
Error 3: Orders Rejected
Symptom: After executing create_orders(), some or all orders are rejected by the broker
Common rejection reasons:
- Disposition stocks not pre-deposited
- Stock suspended from trading
- Locked at price limit (up or down)
- Odd lot trading outside of allowed hours
- Insufficient account permissions
Error 4: Odd Lot Order Failure
Symptom: Using odd_lot=True but orders fail
Causes: - Odd lot trading hour restrictions (intraday: 09:00-13:40, after-hours: 14:00-14:30) - Some brokers do not support odd lot API trading - Insufficient odd lot trading volume
Live Trading Best Practices
1. Test with a Simulated Account
# Most brokers offer simulated accounts; test for 1-2 weeks
# Confirm all workflows are working before using real funds
2. Set Up Daily Scheduling
import schedule
import time
def daily_rebalance():
"""Auto-rebalance after market close"""
try:
# 1. Run strategy
report = backtest.sim(position, resample='M')
# 2. Calculate positions
position = Position.from_report(report, fund=1000000)
# 3. Execute orders
order_executor = OrderExecutor(position, account=acc)
order_executor.create_orders()
print(f"{datetime.now()} - Orders completed")
except Exception as e:
print(f"{datetime.now()} - Order failed: {e}")
# Send notification (LINE/Email)
# Execute daily at 14:00 (after market close)
schedule.every().day.at("14:00").do(daily_rebalance)
while True:
schedule.run_pending()
time.sleep(60)
3. Log All Trades
import json
from datetime import datetime
def log_trade(position, orders, status):
"""Record trade log"""
log_entry = {
'timestamp': datetime.now().isoformat(),
'position': position,
'orders': orders,
'status': status
}
with open('trade_log.json', 'a') as f:
f.write(json.dumps(log_entry, ensure_ascii=False) + '\n')
Reference Resources
- API Reference - online - Complete OrderExecutor parameter documentation
- Live Trading Tutorial (Multi-Strategy) - Multi-strategy portfolio trading
- Risk Management Guide - Live trading risk controls
- Complete Strategy Development Workflow - From backtesting to live trading
- FAQ - More troubleshooting
Final Reminder
Always test thoroughly on a simulated account before using real funds!
Recommended testing checklist: - Account connection is stable and error-free - Order workflow executes completely - Position calculations are correct (match expectations) - Capital controls work normally (no overspending) - Exception handling mechanisms are effective - Runs continuously for 1-2 weeks without issues
Only consider using real funds after all items above are confirmed!