如果你接觸投資有一段時間,肯定聽過不少有關程式交易、量化交易的投資方法。對於那些對軟體、程式碼沒有任何研究的新手來說,一開始可能會覺得艱澀,但隨著近年來AI的崛起,投資策略能否更加自動化,或許將成為未來投資者們必須善用的工具。而程式交易一大優勢在於能有效克服「人性弱點」!本篇文章將透過程式交易的教學,帶大家一窺程式交易與人為交易的差別,從程式交易的基礎概念開始,逐漸入門,並掌握程式交易的使用技巧!
程式交易是什麼?和量化交易有何不同?
程式交易指的是在進行投資時,使用程式碼或自動運行工具來進行交易,這包含我們常做的任何投資流程,像是閱讀和尋找相關股票、進行基本面或技術面的分析、執行下單動作等等,所有流程都使用程式來自動化,這樣的方式就叫做「程式交易」。很
多人常常聽到「程式交易」、「量化交易」這2個名詞,這2者有什麼不同嗎?其實,程式交易和量化交易在本質上是相同的,都是使用程式下單或執行投資策略,以達到自動化投資的目的,僅僅是名詞上的不同而已。
程式交易的優點有哪些?3大關鍵優勢
程式交易不僅需要更進階的投資知識,相對來說入門門檻也複雜一點,那為什麼部分投資者會選擇程式交易呢?原因在於程式交易具有以下3個優勢,是主觀交易(人為交易)所無法取代的。
程式交易優點1 :24小時全自動交易
程式交易最大優勢就是「自動化」,電腦不會累、但人會累,透過程式交易可以大幅省下人工的時間,不需要時時刻刻坐在電腦前盯盤,也能夠做到一般交易者的交易行為,減少大量的時間成本。
程式交易優點2:可同時監控大量數據
不管你是基本面、籌碼面或技術面派,都一定需要看各種「數據」,像是財務報表 、法人進出或技術指標,這些數據若能透過程式交易即時監控,就能讓你24小時隨時監控,不錯過任何行情的變化。
程式交易優點3:回測做判斷
另外一個程式交易的優點,就是能夠執行「回測」。回測指的是運用相同的投資策略來計算過往績效,看該策略是不是能夠獲利,透過程式交易可以快速回測,運用數據及資料,以客觀的方式來評估該策略的可行性。
程式交易和人工交易有差嗎?表格比較大不同
前面有說過,程式交易是使用程式進行自動化交易,因此和人工交易(主動交易)上有差異,而除了下單工具的不同以外,在交易依據及交易時間上,更是有明顯的不同之處。
程式交易 人工交易(主動交易) 交易依據 僅依據程式設定的判斷標準,依照指標或數據進行交易。 根據人為的主觀判斷,可能有直覺、恐慌或貪婪等情感。 交易時間 24小時全天自動化交易 僅限空餘時間進行交易 交易工具 需使用軟體串API,部分下單軟體不一定支援 任何下單軟體、亦可向營業員掛單
程式交易常用5大入門策略
既然程式交易如此方便,是不是所有的判斷都可以仰賴程式交易?這個心態可是程式交易的大忌!程式交易的「程式」,還是經由人的主觀策略建立,好的策略在程式交易上有機會放大績效。若你目前沒有任何策略想法也沒關係,接下來將介紹5大常用程式交易策略,試著從中找到自己適合的交易策略吧!
1.趨勢策略(順勢交易):
什麼是趨勢呢?我們常見所謂的「熊市/牛市」等行情走勢,就是趨勢的一種;趨勢策略是指以各種技術指標,如EMA均線、MACD 、KDJ或WR威廉指標等,來判斷趨勢的走向,並「跟著」趨勢做交易,例如判斷是漲勢則做多、跌勢則做空。
2.動能策略:
動能策略指的是「汰弱留強」的策略,在該股市開始展現相當的潛力和動能時,立馬跟上的交易策略,這也是程式交易的優勢之一(能夠快速監控並掛單跟上),甚至還有「雙動能」的進階策略,常用指標是動力指標MTM、平均真實區間ATR及RSI指標。
3.逆勢策略:
前面提到的策略,基本上都是順勢交易,但採用逆勢策略的投資者也是大有人在。逆勢策略主要是「猜高或猜底」,預先判斷行情即將出現反轉所採取的策略。常見的指標有乖離率BIAS、拋物線指標SAR及樞紐點分析Pivot等。
4.籌碼策略:
籌碼是指法人及主力,包含外資、投信、自營商及大戶。籌碼策略是根據追蹤籌碼進出來進行策略的判斷和追蹤,程式交易的優勢在於能即時監控資金的流向,當大戶們都開始買進、賣出時,就開始掛單進行交易。常用指標為券資比、大戶持股數、法人買賣資訊等。
5.基本面策略:
可別以為程式交易就一定得鎖定技術面,很多時候重視基本面的價值投資學派,也會選擇程式交易來執行。基本面策略包含財報分析、總體經濟或產業指標等,都是程式可以參考的範圍。常用指標為現金流量表、資產負債表及毛利率等基本面指標。
程式交易適合用於哪些商品?
很多人會想問程式交易適合哪些商品,這時候要看程式交易的特性:
以程式做交易
講究掛單速度
因為這2個特性,程式交易若用在掛單速度緩慢、撮合量不高的平台上,就會無法展現程式交易的優勢,且因為要頻繁交易,對於「交易手續費」的要求也會比較高。
一般來說,程式交易適合市場量大的商品,例如美股、加密貨幣、原物料或黃金原油等商品,以期貨、外匯或差價合約的形式為主(點差較低、手續費較低),但若僅是將程式交易做為輔助用途,例如即時通知、偵測數據等等,那不論是哪種市場或商品,使用程式交易都有一定的幫助!
程式交易教學,實際案例演練及策略分享
了解程式交易的優點之後,該如何實際進行程式交易呢?接下來,我們就要進到程式交易教學的實際案例及演練!本次將以TQuant Lab 的 zipline-tej 中最基礎的4大函式進行介紹及實際案例操作,並套用買進持有策略(buy and hold),於回測第一天及最後一天進行買進賣出、計算績效。
台積電(2330)TSMC 買進持有策略
在這幾年內,台積電(2330)股價都是呈現長期上升的趨勢,且其佔了台股市值一半,吸引了許多投資人進行投資,本次範例將以最經典的買進持有策略,向您介紹 zipline 回測方法。包含組建 zipline 交易策略最基礎的4大函式 – initialize、handle_data、analyze 和 run_algorithm。
程式交易教學1-導入股價資料
在 zipline 中,我們使用 os 套件搭配 !zipline ingest 將股價資料導入到本地端。常用寫法為:
其中 -b 為 bundle 之涵義,bundle 為股票價量資訊的載體,tquant 則是 bundle 之名稱,可由使用者自定義。在 ingest 之前,需先使用 os 設定環境變數,以方便 zipline 接收使用者所欲抓取之資產標的與年份之要求。一般而言,針對環境變數之寫法如下:
os.environ[‘TEJAPI_BASE’] = “https://api.tej.com.tw” ==> 導航至 tej api 網域。
os.environ[‘TEJAPI_KEY’] = “your key” ==> 個人 api key 以驗證身分。
os.environ[‘mdate’] = “20170601 20230702” ==> 欲抓取資料之日期區間,前者為起始日,後者為終止日。
os.environ[‘ticker’] = ‘2330 IR0001’ ==> 所欲抓取股票之代碼。
程式交易教學2-Initialize 函式
initialize 為構建 zipline 交易策略的重要函式,會在回測開始前被呼叫一次,主要函式任務為設定回測環境,常用於設定滑價或手續費。分別可以使用以下函式:
設定滑價模式,zipline 共提供四種滑價計算方法,詳請請見後續教學-zipline slippage。
zipline.api.set_commission
設定手續費模式,zipline 共提供三種手續費計算方法,詳請請見後續教學-zipline commission。
常見的寫法如下:
def initialize(context): set_slippage(slippage.FixedSlippage()) set_commission(commission.PerShare(cost=0.00285))
除此之外,我們可以注意到 initialize 含有一個參數 context__,__context 為一個命名空間 (namespace),可以在儲存各種自定義變數後,在每次交易日中循環呼叫它。舉例來說,我們設置一個變數 「context.day = 0」 來計算交易日天數,並設置一個變數 「context.has_ordered = False」 來紀錄是否已經持有台積電股票。
def initialize(context): context.day = 0 context.has_ordered = False set_slippage(slippage.FixedSlippage()) set_commission(commission.PerShare(cost=0.00285))
程式交易教學3-Handle_data 函式
handle_data 為構建 zipline 交易策略的重要函式,會在回測開始後每天被呼叫,主要任務為設定交易策略、下單與紀錄交易資訊。
其中 handle_data 含有兩種參數 — context , data__。__context 與上述 initialize 介紹功能相同,這裡為了記錄交易天數與否持有台積電股票,我們設定為:
def handle_data(context, data):
# 每次交易日加 1 天。
context.day += 1
# 判別是否持有台積電,請注意我們在 initialize 設定 context.has_ordered 為 False。
if not context.has_ordered:
接著我們引入交易下單函式,下單函式共有六個不同種類,請見教材中以 zipline order 開頭之文件,這裡使用最基礎的下單函式:
zipline.api.order
買進或賣出 n 股的資產標的。
Parameters:
asset: zipline.assets.Asset 欲下單之資產,請注意資料型態為 zipline 獨有的 Asset 型態。
amount: int 欲下單股數。
limit_price: float , optional 限價。
stop_price: float , optional 停價。
加入下單函式 order(symbol(“2330”),其中 symbol(“2330”) 就是 zipline 中的 Asset 資料型態。之後,我們會將 context.has_ordered 調整成 True,此時下個交易日就不會再度下單,更改完程式如下:
def handle_data(context, data): context.day += 1 if not context.has_ordered: # 下單台積電股票一張 == 1000股 order(symbol(“2330”, 1000) # 設定 context.has_ordered 為 True 以避免下次交易日下單 context.has_ordered = True
最後為了記錄交易天數、是否持有部位與當日價格,我們使用 record 函式,其功能為記錄每個交易日的資訊並且在最終 run_algorithm 輸出的資料表中,以欄位型式加入所紀錄資訊。其程式編輯方式如下:
這裡我們紀錄當天交易天數 (context.day)、是否持有部位 (context.has_ordered) 與當天收盤價格 (data.current(symbol(“2330”), “close”)),其中上面所提到的 data 就是在 handle_data 中的 data__,__data 主要功能為保存每天股價的價量資料並且提供呼叫,於本實例我們欲紀錄當天收盤價,於是用到 data.current() 函式。
zipline.data.current
呼叫股票的當日價量資訊。
Parameters:
assets: zipline.asset.Asset 所欲呼叫的股票,請注意資料型態為 zipline 獨有的 Asset 型態。
fields: str 所欲呼叫的價量資訊,提供 ‘close’, ‘open’, ‘high’, ‘low’ 與 ‘volume’。
由於我們希望記錄台積電當日收盤價格,因此程式編輯如下:
def handle_data(context, data): context.day += 1 if not context.has_ordered: order(symbol(“2330”, 1000) context.has_ordered = True record( # 紀錄用 trade_days = context.day, has_ordered = context.has_ordered, TSMC = data.current(symbol(“2330”), “close”) )
程式交易教學4-Analyze 函式
analyze 主要用於回測後視覺化策略績效與風險,這裡我們以 matplotlib 繪製投組價值表與台積電股價走勢表。其中 analyze 有兩個參數 context 與 perf__,__context 就與上述相同,perf 就是最終 run_algorithm 輸出的資料表 — __results__。我們可以提取裡面特定欄位來繪製圖表。
程式交易教學5-Run_algorithm 函式
zipline.run_algorithm
進行策略回測。
Parameters:
start: pd.Timestamp or datetime 回測起始日期。
end: pd.Timestamp or datetime 回測結束日期。
initialize: callable 呼叫 initialize 函式以用於回測。
capital_base: int 初始資金額度。
handle_data: callable , optional 呼叫 handle_data 函式以用於回測。
before_trading_start: callable , optional 呼叫 before_trading_start 函式以用於回測。
analyze: callable , optional 呼叫 analyze 函式以用於回測。
data_frequency: {“daily”, “minute”} , optional 設置交易頻率。
bundle: str , optional 設置回測用的 bundle。
trading_calendar: TradingCalendar , optional 設置交易日曆。
benchmark_returns: pd.Series , optional 設置指標報酬率。
treasury_returns: pd.Series , optional 設置無風險利率。
Returns:
Perf: pd.DataFrame , 內建欄位有:
benchmark_return: 當日的benchmark報酬率,若是由set_benchmark()設定,則計算方式為(當日benchmark收盤價 / 前一日benchmark收盤價) – 1。
benchmark_period_return: 累積的benchmark日報酬率。計算方式:np.nancumprod(1 + benchmark_return Series) – 1。
treasury_return: 當日的treasury報酬率,直接由TEJ API提供。
treasury_period_return: 累積的treasury日報酬率。計算方式:np.nancumprod(1 + treasury_return Series) – 1。
benchmark_volatility: benchmark日報酬率的年化波動率,至少需有兩期的報酬率才進行計算。計算方式:(benchmark_return Series).expanding(2).std(ddof=1) * np.sqrt(252)
orders:顯示下單紀錄 每一筆下單用一個字典的方式呈現,其中:
id:虛擬單號。
dt:下單時間。
reason:None, Hold, or Reject(目前不適用)
created:建立時間。
amount:
下單股數。
若>0表示買進或回補,<0表示賣出或放空。
若有發股票股利或股票分割的情形,除權日當天會更新之前未成交訂單的amount(new_amount = old_amount / ratio,其中ratio = 1/僅除權調整係數)。
filled:成交股數。
註:Order execution – 當演算法在某一天下單時,該訂單會在下一個交易日成交,以避免lookahead bias。
commission:該筆交易傭金。
stop:停損價,若有發股票股利或股票分割的情形,除權日當天會更新之前未成交訂單的stop price(new_stop = old_stop * ratio,其中ratio = 1/僅除權調整係數)。
limit:限價價,若有發股票股利或股票分割的情形,除權日當天會更新之前未成交訂單的limit price(new_limit = old_limit * ratio,其中ratio = 1/僅除權調整係數)。
stop_reached:
對於buy stop order,若現價>=stop price,則顯示True否則False。
對於sell stop order,若現價<=stop price,則顯示True否則False。
limit_reached:
對於buy limit order,若現價<=limit price,則顯示True否則False。
對於sell limit order,若現價>=limit price,則顯示True否則False。
sid(asset):下單的標的。
status:若=0表示OPEN(未完全成交),=1表示FILLED(完全成交),=2表示CANCEL(已取消)。
transactions:顯示交易紀錄
amount:下單股數。
dt : 交易時間。
price:成交價(為調整前收盤價,不調整股息、分割、股票股利)。
order_id:單號,可與orders中的id比對。
sid(asset):下單的標的。
commission:一律為None。傭金資料已經在’orders’底下。
positions:顯示持有部位
sid(asset):下單的標的。
amount:該標的總持有股數。除權日當天amount會進行調整(old_amount / ratio = new_amount,其中ratio = 1/僅除權調整係數)。
last_sale_price:標的最近一筆的收盤價。
cost_basis:每股平均成本(含commissions)。
計算方法為:sum(成交價 * (1+commission) * 股數) / 總股數
除權日當天cost_basis會進行調整(old_cost_basis * ratio = new_cost_basis,其中ratio = 1/僅除權調整係數)。
對於買進或回補來說,commissions會造成cost_basis增加;對於賣出或放空來說,commissions會造成cost_basis減少。
longs_count:
當日帳上有幾檔長部位股票。可與positions比較。
shorts_count:
當日帳上有幾檔短部位股票。可與positions比較。
long_exposure(long_value):
當日帳上長部位的市值。
可與positions比較。
當投資標的為股票時long_exposure和long_value兩欄位數值一致。
計算方式為sum(持有股數 * 收盤價) = sum(amount * last_sale_price),where amount > 0。
short_exposure(short_value):
當日帳上短部位的市值。
可與positions比較。
當投資標的為股票時short_exposure和short_value兩欄位數值一致。
計算方式為sum(持有股數 * 收盤價) = sum(amount * last_sale_price),where amount < 0。
short_exposure必然 <= 0。
ending_exposure(ending_value):
當日結束時帳上部位的淨市值。
計算方式:long_exposure + short_exposure
starting_exposure(starting_value):
當日開始時帳上部位的淨市值。
為前一日的ending_exposure。
gross_leverage(leverage):
Gross leverage is the sum of long and short leverage exposure per share divided by net asset value(portfolio_value)。
計算方式:(long_exposure – short_exposure)/portfolio_value
net_leverage:
Net leverage is the net leverage exposure per share divided by net asset value(portfolio_value)。
計算方式:(long_exposure + short_exposure)/portfolio_value
capital_used:
當天的cash flow。>0表示流入,<0表示流出。
計算方式:
-1 * sum(transaction.price * transaction.amount) – sum(order.commission) + sum(earn_dividends) + sum(leftover_cash)
註:
earn_dividends:會於pay_date當天配發。
leftover_cash:分割、股票股利等原因導致股數變動時,若有<1股(fractional_share_count)無法分配的情況時則返回現金。
leftover_cash範例:
若現在持有100股(amount),ratio=3。
新的amount理論上是100/3=33.333,然而不滿一股的部分需轉換成現金 (return cash)。
所以新的amount會是33,剩餘的0.333股(33.333-33)就是fractional_share_count。
由於ratio=3代表該公司股數有發生變動,所以每股平均成本 (cost basis)需調整=原cost basis * 原amount / 新amount 後四捨五入到小數第二位。
所以退回現金(return cash)=(fractional_share_count) * (新cost basis) 再四捨五入到小數第二位
ending_cash:
當日結束時帳上持有現金。
計算方式:starting_cash+capital_used
starting_cash:
當日開始時帳上持有現金。
為前一日的ending_cash+sum(earn_dividends),若無前一日則為capital_base。
pnl:
當日投資組合損益。
計算方式:(ending_exposure + ending_cash) – (starting_exposure + starting_cash)。
returns:
當日報酬率。
計算方式:(當日portfolio_value) / (前一日portfolio_value) – 1。
存在尾差。
portfolio_value:
即net asset value,當日投資組合總價值。
計算方式:(ending_exposure + ending_cash)
algorithm_period_return:
投資組合累積日報酬率。
計算方式:( 1 + 前一日的algorithm_period_return) * ( 1 + 當日returns) – 1。
存在尾差。
algo_volatility:
投資組合日報酬率的年化波動率,至少需有兩期的報酬率才進行計算。
利用empyrical套件計算: empyrical.annual_volatility(returnsSeries, period=’daily’, alpha=2.0, annualization=None)。
具體來說,empyrical套件的計算方式為:returnsSeries.std(ddof=1) * (252 ** (1 / 2)),std為樣本標準差。
用完整returns資料,則會回傳最後一日algo_volatility,若扣掉最後一日returns,則回傳倒數第二日,以此類推。
excess_return:
投資組合累積超額日報酬(相對於benchmark_period_return)。
計算方式為:(algorithm_period_return – benchmark_period_return)。
max_drawdown:
投資組合累積報酬率從過去的峰值下跌的最大跌幅百分比。
利用empyrical套件計算:empyrical.max_drawdown(returns Series)。
具體來說,empyrical套件的計算方式為:
cumulative_returns:先計算過去每一日的累積報酬。
previous_peaks:計算過去累積報酬率的最大值。
daily_drawdown:計算每日回撤 = (cumulative_returns – previous_peaks) / previous_peaks
max_drawdown:過去每一日的daily_drawdown取極小值。
sharpe:
年化夏普比率,衡量每承擔1單位風險,可以獲取多少的報酬。
利用empyrical套件計算:empyrical.sharpe_ratio(returns Series, risk_free=0)。
具體來說,empyrical套件的計算方式為: np.mean(returns Series) / np.std(returns Series,ddof=1) * np.sqrt(252)
sortino:
年化索提諾比率,衡量承擔單位下方風險,可以獲取多少的報酬。
利用empyrical套件計算:empyrical.sortino_ratio(returns Series, required_return=0)。
具體來說,empyrical套件的計算方式為:
計算downside_risk:np.sqrt(np.nanmean(np.square(downside_return))) * np.sqrt(252),其中downside_return將returns Series中>0的數值替換成0。
計算mean_return:np.nanmean(returns Series)
計算sortino_ratio = mean_return / downside_risk * 252。
存在尾差。
alpha:
年化alpha,衡量投資組合創造超額報酬的能力。
利用empyrical套件計算:empyrical.alpha_beta_aligned(returns=returnsSeries, factor_returns=benchmark_return Series,risk_free=0.0)
具體來說,empyrical套件的計算方式為:
計算alpha_series:returns Series – (當日beta * benchmark_return Series)
計算平均alpha:nanmean(alpha_series)
計算年化alpha:(平均alpha + 1) ^ 252 -1
beta:
衡量投資組合相對於整體市場的波動性。
利用empyrical套件計算:empyrical.alpha_beta_aligned(returns=returnsSeries, factor_returns=benchmark_return Series,risk_free=0.0)
具體來說,empyrical套件的計算方式為: Cov(benchmark_return Series, returns Series) / Var(benchmark_return Series)
我們可以發現之前使用 order 紀錄的 trade_days, has_ordered 與 TSMC 確實以欄位型式記錄在 results 表中。
results[[‘trade_days’,’has_ordered’,’TSMC’]]
如何選擇適合自己的程式交易及回測平台?
當進行程式交易時,除了考慮市場和商品外,選擇合適的平台和工具,才能夠讓程式交易的績效最大化!程式交易平台,應該具備高效且穩定的交易環境,並提供精確的「回測功能」,才能讓交易策略更加靈活,優化時也會比較順手。
為什麼「回測」如此重要呢?原因在於交易策略的擬定,通常來自於過往數據的表現,也因此回測是否準確,就是交易策略是否穩定的重要指標。一個優秀的回測引擎,應該能夠模擬真實的交易環境,包括考慮滑點、手續費和其他交易成本,這樣才能提供可靠的結果,協助交易者隨時優化它的策略。
舉例來說,目前市面上的回測平台或回測套件,可能缺乏較完善的回測系統,例如手續費跟滑價沒有較詳細的設定,導致回測結果不夠精確,會使得投資人可能做出錯誤的交易;亦或是太過簡陋,投資人缺乏資訊去判斷自己的策略是否出現錯誤或bug。而TQuant Lab這套回測系統,不僅擁有精確的手續費跟滑價設定,更能藉由參數避開特定事件,從而做出策略調整,例如漲跌停、發放股票股利等等設定。
選擇 TQuant Lab 的4大優點!程式交易推薦回測系統
TEJ 採用 Quantopian 公司所提供的 Zipline 套件,修改成符合台灣金融市場交易的回測引擎。經過多年的發展,這套回測引擎已成為國際常用的量化平台基礎回測架構。由 TEJ 專業量化分析團隊維護,並不定時推出專屬的新功能,使其能同時回測股票與 ETF 等多種商品。在回測過程中,日誌會自動顯示投資組合每日持有股票的各項紀錄,包含現金股利、股票股利等資訊,貼合市場真實情境。
TEJ 採用 Quantopian 所提供的 Pipeline 套件,進行擴充和維護,能夠篩選和獲取特定金融數據來建構投資因子,使使用者能設計專屬的投資策略。系統自動平移一期資料,確保在建構策略時不會用到未來資料,避免前視偏誤。內建多種計算函式,如 zscore、SimpleMovingAverage、pearsonr、BollingerBands 等,方便您構建專屬的投資指標。此外,系統還能視覺化產出流程圖,讓您了解策略的計算過程。
TEJ 團隊在 Alphalens 因子分析工具的基礎上,修改並適配台灣金融市場的版本,提供多種多樣的因子研究分析。報酬率分析功能讓使用者輕鬆組建多空對沖投組來檢驗因子效力;資訊分析功能則能觀察因子是否具有預測未來股票報酬的能力。此外,週轉率分析功能能檢驗因子的換股頻率,評估其是否會導致過高的交易成本。
Pyfolio 是一款強大的策略績效分析工具,讓使用者能快速掌握策略的優缺點。只需一鍵即可生成完整的績效指標,並同時產出各種視覺化報表。該工具能解析策略在過去歷史中遭遇重大金融事件時的表現,檢查其穩健性。此外,Pyfolio 還能分析投資組合中流動性較差的股票,幫助找出可能面臨的流動性風險。
Zipline-tej 的事件驅動型回測能高度模擬真實市場的進出情況,提供多種動態與靜態滑價模型,如固定點滑價成本和成交量驅動的動態滑價成本。此外,還包含台灣市場獨有的手續費成本模型及成交訂單遞延機制。搭配 TEJ 資料庫提供的交易日註記,避免在漲跌停時仍能順利買進的回測前視偏誤,確保回測結果更加真實可靠。
【TQuant Lab回測系統】解決你的量化金融痛點
全方位提供交易回測所需工具
延伸閱讀:
找不到好的金融數據來源?一文搞懂取得高品質數據的關鍵!
量化交易時代來臨:如何藉由好的投資資料打造投資策略?
TQuant Lab KD 指標策略,探索股價反轉時機?