藍酬股的智慧:霍華.羅斯曼的審慎致富之道

前言

霍華.羅斯曼(Howard Rothman)為華爾街知名投資機構「遠見投資顧問公司」(Vision Investment Advisor, VIA)之首席投資分析師,其主導的「藍酬股成長操作帳戶」(Blue Chip Growth Account)自1997年成立以來,至2001年為止累積報酬率高達49.27%,表現為同期標準普爾500指數(S&P500)的兩倍以上,並在各年度中皆穩定優於大盤。

截至2002年12月,羅斯曼已擔任遠見投資顧問公司總裁,並曾擔任國家折扣券商協會(the National Introducing Brokers Association)主席及創始會員。他自1990年起被推薦進入國家期貨協會(the National Futures Association)董事會,連任三屆,並積極參與期貨產業協會的法律與合規委員會,具備深厚的專業背景與業界影響力。

羅斯曼的投資核心理念在於「於正確時機買進並長期持有優質個股」(”buy right and hold tight”、”buy strong and hold long”)。他強調,選擇財務穩健、獲利穩定成長的公司,並於適當價格買入後耐心持有,無須頻繁調整持股,即可獲得長期優異報酬。這種簡潔而堅定的投資哲學,不僅體現出他的實務智慧,也為本次策略回測提供了明確且具有歷史驗證的依據。

策略邏輯

本策略核心精神承襲霍華.羅斯曼強調的投資哲學——選擇基本面穩健、具成長潛力的優質公司,並於適當時機進場佈局,長期持有以追求穩定報酬。為此,我們設計一套具體且嚴謹的篩選機制,從全市場中挑選具備穩定獲利能力與成長潛力的個股,條件如下:

  1. 總市值 ≧ 市場平均值:確保標的公司具一定規模,排除過小型或波動性過高的股票。
  2. 最近一季流動比率 ≧ 市場平均值:反映企業短期償債能力,避免選入財務體質不穩的公司。
  3. 近四季股東權益報酬率(ROE)≧ 市場平均值:挑選資金運用效率較高、具持續獲利能力的企業。
  4. 近五年自由現金流量均為正值:確保公司具備穩定的現金流,能支應營運與未來投資。
  5. 近四季營收成長率大於 6%:濾除營收成長過慢或過於劇烈的企業,聚焦於穩健成長型公司。
  6. 近四季盈餘成長率大於 8%:優先挑選獲利穩定成長的公司,並排除成長異常或可能來自一次性因素的企業。

透過上述多重條件交叉篩選,我們期望能精準鎖定具備「規模穩健、財務健康、成長動能明確」的企業,建立一組具長期投資價值的股票池,作為後續回測與策略建構的基礎。

資料前處理

通過使用 TQuant 提供的 get_nuiverse 以及 get_histiort_data 函數來獲取需要的股票財務資料,並進行上述篩選標準的計算。

程式碼範例展示

import pandas as pd
import numpy as np
import tejapi
import os
import json
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Arial'
tej_key = 'Your key'
tejapi.ApiConfig.api_key = tej_key
os.environ['TEJAPI_BASE'] = "https://api.tej.com.tw"
os.environ['TEJAPI_KEY'] = tej_key




from zipline.sources.TEJ_Api_Data import get_universe
import TejToolAPI
from zipline.data.run_ingest import simple_ingest
from zipline.api import set_slippage, set_commission, set_benchmark,  symbol,  record, order_target_percent
from zipline.finance import commission, slippage
from zipline import run_algorithm


start_date = '2010-01-01'; end_date = '2025-04-21'


pool = get_universe(start = start_date,
                     end = end_date,
                     mkt_bd_e = ['TSE', 'OTC'],
                     stktp_e = 'Common Stock',
                     main_ind_e = 'General Industry')


columns = ['coid','roi', 'mktcap', 'r501', 'r104', 'cscfo', 'cscfi', 'r401', 'r405']


start_dt = pd.Timestamp(start_date, tz = 'UTC')
end_dt = pd.Timestamp(end_date, tz = "UTC")


data_use = TejToolAPI.get_history_data(start = start_dt,
                                   end = end_dt,
                                   ticker = pool,
                                   fin_type = 'Q', # 為單季資料
                                   columns = columns,
                                   transfer_to_chinese = False)

data_use['Avg_Market_Cap_Per_Day'] = data_use.groupby('mdate')['Market_Cap_Dollars'].transform('mean')
data_use['Avg_Current_Ratio_Per_Day'] = data_use.groupby('mdate')['Current_Ratio_Q'].transform('mean')
data_use['Avg_Return_Rate_on_Equity_Per_Day'] = data_use.groupby('mdate')['Return_Rate_on_Equity_A_percent_Q'].transform('mean')
data_use['Free_Cash_Flow'] = data_use['Cash_Flow_from_Operating_Activities_Q'] - data_use['Cash_Flow_from_Investing_Activities_Q']


# 確保資料依公司與時間排序
data_use = data_use.sort_values(['coid', 'mdate'])
# 使用 rolling() 計算近四季平均 ROE(min_periods=4 確保要有滿4筆才計算)
data_use['Avg_ROE_4Q'] = data_use.groupby('coid')['Return_Rate_on_Equity_A_percent_Q'] \
                                .transform(lambda x: x.rolling(window=252, min_periods=252).mean())


# 使用 rolling() 計算近四季平均營收成長率
data_use['Avg_Sales_Growth_4Q'] = data_use.groupby('coid')['Sales_Growth_Rate_Q'] \
                                         .transform(lambda x: x.rolling(window=252, min_periods=252).mean())


data_use['Avg_NI_Growth_4Q'] = data_use.groupby('coid')['Net_Income_Growth_Rate_Q'] \
                                         .transform(lambda x: x.rolling(window=252, min_periods=252).mean())


# 計算過去1260日(5年)的最小值是否大於0
data_use['FCF_Positive_5Y'] = data_use.groupby('coid')['Free_Cash_Flow'] \
                                     .transform(lambda x: x.rolling(window=1260, min_periods=1260).mean() > 0)
def compute_stock(date, data):
   df = data[data['mdate'] == pd.to_datetime(date)].reset_index(drop = True)


   set_1 = set(df[df['Market_Cap_Dollars'] >= df['Avg_Market_Cap_Per_Day']]['coid'])


   set_2 = set(df[df['Current_Ratio_Q'] >= df['Avg_Current_Ratio_Per_Day']]['coid'])


   set_3 = set(df[df['Avg_ROE_4Q'] >= df['Avg_Return_Rate_on_Equity_Per_Day']]['coid'])


   set_4 = set(df[df['FCF_Positive_5Y']]['coid'])


   set_5 = set(df[(df['Avg_Sales_Growth_4Q'] > 0.06)]['coid'])


   set_6 = set(df[(df['Avg_NI_Growth_4Q'] > 0.08)]['coid'])


   tickers = list(set_1 & set_2 &  set_3 & set_4 & set_5 & set_6)
   return tickers

回測流程操作細節

為使投資策略能更貼近真實市場操作,本策略設計以 120 日為一輪的再平衡週期。選擇較長的持有期間主要考量到:企業基本面如營收、盈餘與現金流等財務指標,其變動多數具有一定的滯後性與穩定性,股價需一段時間才能完整反映其內在價值。因此,相較於短期交易策略,採用 120 天(約 6 個交易月)的持有期能更有效捕捉基本面因素對股價的中長期驅動力。

具體流程為:
每 120 個交易日重新進行一次股票池篩選,依據最新財務數據更新篩選結果,並同步汰換不符合標準的個股,納入新符合條件之標的。此作法可兼顧基本面變化與交易成本控制,達成策略穩定性與實務執行的平衡。同時為了確保回測時的槓桿使用是穩健的以貼近真實世界,我們在交易邏輯有另外設計一個槓桿檢查機制,當回測時的槓桿率超過1.2 時,進行股票部位的再調整使其回到 1.0。

回測程式碼展示

pools = pool + ['IR0001']


start_ingest = start_date.replace('-', '')
end_ingest = end_date.replace('-', '')


print(f'開始匯入回測資料')
simple_ingest(name = 'tquant' , tickers = pools , start_date = start_ingest , end_date = end_ingest)
print(f'結束匯入回測資料')


​​def initialize(context, re = 120):
   set_slippage(slippage.VolumeShareSlippage(volume_limit=1, price_impact=0.01))
   set_commission(commission.Custom_TW_Commission())
   set_benchmark(symbol('IR0001'))


   context.i = 0
   context.state = False
   context.order_tickers = []
   context.last_tickers = []
   context.rebalance = re




def handle_data_1(context, data):
   # 避免前視偏誤,在篩選股票下一交易日下單
   if context.state == True:


       for i in context.last_tickers:
           if i not in context.order_tickers:
               order_target_percent(symbol(i), 0)




       for i in context.order_tickers:
           order_target_percent(symbol(i), 1 / len(context.order_tickers))


           curr = data.current(symbol(i), 'price')
           record(price = curr, days = context.i)


       print(f"下單日期:{data.current_dt.date()}, 擇股股票數量:{len(context.order_tickers)}, Leverage: {context.account.leverage}")




       context.last_tickers = context.order_tickers.copy()
       context.state = False


   backtest_date = data.current_dt.date()


   if context.i % context.rebalance == 0:
       context.state = True
       context.order_tickers = compute_stock(date = backtest_date, data = data_use)




   record(Leverage = context.account.leverage)
   if context.account.leverage > 1.2:
       print(f'{data.current_dt.date()}: Over Leverage, Leverage: {context.account.leverage}')
       for i in context.order_tickers:
           order_target_percent(symbol(i), 1 / len(context.order_tickers))


   context.i += 1


   record(ticker_num = len(context.order_tickers))


def analyze(context, perf):
       fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(18, 10), sharex=False)
       plt.style.use('ggplot')
       axes[0].plot(perf.index, perf['algorithm_period_return'], label = 'Strategy')
       axes[0].plot(perf.index, perf['benchmark_period_return'], label = 'Benchmark')
       axes[0].set_title(f"Backtest_Results")
       axes[0].legend()


       axes[1].plot(perf.index, perf['Leverage'], label = 'Leverage')
       axes[1].set_title(f"Leverage")
       axes[1].legend


       axes[2].plot(perf.index, perf['ticker_num'], label = 'Ticker_number')
       axes[2].set_title(f'Ticker Number')
       axes[2].legend()




       plt.tight_layout()
       plt.show()
results = run_algorithm(
           start = pd.Timestamp('2019-01-01', tz = 'utc'),
           end = pd.Timestamp(end_date, tz = 'utc'),
           initialize = initialize,
           handle_data = handle_data_1,
           analyze = analyze,
           bundle = 'tquant',
           capital_base = 1e5)

績效圖表與分析

審慎致富投資法

上圖展示了策略的累積報酬率、槓桿使用率以及持倉的股票數量。從槓桿率的線圖來看,策略回測結果並沒有使用到過高的槓桿,也沒有過多的現金儲備造成侵蝕整體報酬率的情況。以投資的股票數量來看,每次篩選股票出的股票數平均是在 10 支股票左右,這顯示出策略的嚴謹程度是中,不會因篩選條件過於嚴格而篩選掉所有股票,同時也不會因篩選條件過於鬆散,而造成下單股票數量過多造成績效貼近大盤。

從累積報酬率的線圖來看,策略跑贏大盤的時機點主要處於 2020年初 – 2022 年初以及 2023 年初 – 2024 5、6月,這兩個時期剛好對應到大盤的主要上漲期間。與此同時在 2022 – 2023 年初的時期以及 2024 年中至今的這兩個時期則是容易輸給大盤的漲幅(兩條線的距離靠近),對應到大盤進入熊市或是盤整格局。因此我們認為此策略是根據價值投資的概念去做選股,因此在牛市時期較容易出現價格反應公司價值的狀況,而熊市時期的情緒面容易影響股票的短期價格,造成價值投資在此時期的效果大大減半。

審慎致富投資法

從上圖可以看出 2022 至 2024 年初的期間是整體策略最大的回撤期間,顯示出此策略仰賴整體市場的狀態,而非能夠在不同的市場情況都能夠賺取超額報酬,因此需要視市場情況來盼對是否使用此策略。

績效指標 / 策略大盤(Benchmark)霍華.羅斯曼投資策略
年化報酬率14.5%19.43%
累積報酬率126.97%193%
年化波動度17.08%26.43%
夏普值0.880.8
卡瑪比率0.550.46
期間最大回撤– 26.295%– 41.937%
註:卡瑪比率計算方式為年化波動度除以期間最大回撤,用以衡量「報酬率對虧損」的比值,此指標的數值越高越好。

在本研究中,將霍華.羅斯曼(Howard Rothman)投資策略與大盤表現進行比較,發現其在報酬能力上具有明顯優勢。該策略的年化報酬率為 19.43%,顯著高於大盤的 14.5%,累積報酬亦高達 193%,優於大盤的 126.97%。然而,其風險指標亦相對較高,年化波動度達 26.43%(大盤為 17.08%),最大回撤亦來到 -41.94%,低於大盤的 -26.30%,主要是篩選條件較嚴導致成分股數較低,使得整體投組分散性不佳。最終也使夏普值略低(0.80 vs 0.88),表示風險調整後的效益未能優於大盤,但整體而言,該策略在絕對報酬表現上仍展現出強勁的潛力。

完整程式碼連結


歡迎投資朋友參考,之後也會持續介紹使用 TEJ 資料庫來建構各式指標,並回測指標績效,所以歡迎對各種交易回測有興趣的讀者,選購 TQuant Lab 的相關方案,用高品質的資料庫,建構出適合自己的交易策略。
溫馨提醒,本次分析僅供參考,不代表任何商品或投資上的建議。

【TQuant Lab 回測系統】解決你的量化金融痛點

全方位提供交易回測所需工具

延伸閱讀

從景氣燈號到資產輪動:一套避開熊市的量化策略

麥克.墨菲高科技股投資風險評估法則

查爾士.布蘭帝 價值型選股法則:打造安全邊際的投資組合

相關連結

返回總覽頁
Procesing