AlanQ 是一個量化交易回測框架,提供從資料管理、因子開發、回測執行到績效評估的完整功能。
本專案參考 阿布量化交易系統 (abu) 的教學書籍與開源框架,實作並學習量化交易相關概念與建立回測系統。
- Python 3.8 或更高版本
- Clone或下載專案
git clone https://github.com/Alan-Cheng/q-trade.git
cd q-trade- 建立虛擬環境(建議)
python -m venv venv- 啟動虛擬環境
- macOS/Linux:
source venv/bin/activate- Windows:
venv\Scripts\activate- 安裝依賴套件
pip install -r requirements.txt專案所需的套件已列於 requirements.txt,包含:
pandas: 資料處理numpy: 數值計算matplotlib: 圖表繪製mplfinance: 金融圖表繪製yfinance: 股票資料下載scipy: 科學計算bokeh: 互動式視覺化seaborn: 統計圖表jupyter: Jupyter Notebook 環境ipykernel: Jupyter 核心ta-lib: 技術分析指標庫statsmodels: 統計分析(用於回歸工具)scikit-learn: 機器學習工具requests: HTTP 請求庫
alanq/
├── backtest/ # 回測引擎
├── data/ # 資料管理
├── factors/ # 交易因子
│ ├── selection/ # 選股因子
│ └── timing/ # 時機因子(買入/賣出)
├── positions/ # 倉位管理
├── optimization/ # 因子優化
├── performance/ # 績效評估
│ ├── basic/ # 基本績效指標
│ └── detail/ # 詳細績效指標
├── slippage/ # 滑價模型
├── benchmark/ # 基準計算
└── util/ # 工具函數
下圖展示了各模組之間的依賴關係和數據流向:
graph TD
A[data/StockDataManager] --> B[factors/selection<br/>選股因子]
A --> C[factors/timing<br/>時機因子]
B --> D[backtest/selection_backtester<br/>選股回測器]
D --> E[選中的股票列表]
E --> F[backtest/timing_backtester<br/>時機回測器]
C --> F
G[slippage/<br/>滑價模型] --> F
H[positions/<br/>倉位管理] --> F
F --> I[optimization/<br/>因子優化器]
I --> F
F --> J[performance/<br/>績效評估]
K[benchmark/<br/>基準計算] --> J
style A fill:#e1f5ff
style D fill:#fff4e1
style F fill:#fff4e1
style I fill:#ffe1f5
style J fill:#e1ffe1
-
資料層 (
data/)StockDataManager提供股票資料給所有需要資料的模組
-
因子層 (
factors/)selection/: 選股因子,用於篩選股票timing/: 時機因子,用於判斷買賣時機
-
回測層 (
backtest/)selection_backtester: 使用選股因子進行股票篩選,輸出選中的股票列表timing_backtester: 使用時機因子、滑價模型、倉位管理進行回測- 接收
selection_backtester輸出的選中股票列表
-
優化層 (
optimization/)- 因子優化器使用
timing_backtester進行參數優化
- 因子優化器使用
-
評估層 (
performance/,benchmark/)- 績效評估模組分析回測結果
- 基準計算模組提供對比基準
功能: 負責下載、儲存和管理股票 K 線資料
主要類別: StockDataManager
輸入:
symbols(list): 股票代碼列表,例如["TSLA", "AAPL"]start_date(str, optional): 資料起始日期,格式為"YYYY-MM-DD"。如果為None,則下載該股票所有可用的歷史資料(通常從股票上市日期或 yfinance 有資料的最早日期開始,約為 5-10 年前)end_date(str, optional): 資料結束日期,格式為"YYYY-MM-DD"。如果為None,則下載到最新日期
輸出:
stock_data(dict): 股票資料字典,格式為{股票代號: DataFrame}- DataFrame 包含欄位:
Open,High,Low,Close,Volume
注意事項:
- 如果
start_date為None,yfinance 會下載該股票所有可用的歷史資料,資料量可能很大,下載時間較長 - 建議明確指定
start_date以控制資料範圍和提升下載效率
主要方法:
get_kl_pd(symbol): 取得指定股票的 K 線 DataFrameget_stock_data(): 取得所有股票資料字典get_stock_data_by_symbol(symbol): 取得單一股票資料get_stock_data_by_symbols(symbols): 取得多檔股票資料
功能: 判斷股票是否符合選股條件
基類: StockPickerBase
輸入:
kl_pd(pd.DataFrame): 股票的 K 線資料target_symbol(str): 股票代碼
輸出:
bool:True表示選中,False表示不選中
實作範例:
RegressAngleFactor: 基於回歸角度的選股因子
基類:
BaseBuyFactor: 買入因子基類BaseSellFactor: 賣出因子基類
輸入:
df(pd.DataFrame): 價格資料,必須包含Open,High,Low,Close欄位- 其他參數依因子而定(例如
xd,atr_multiplier等)
輸出:
np.ndarray: 訊號陣列- 買入因子:
1= 買入訊號,NaN= 無操作 - 賣出因子:
0= 賣出訊號,NaN= 無操作
- 買入因子:
實作範例:
BreakoutFactor: 突破買入因子ATRStopSellFactor: ATR 停損賣出因子RiskStopSellFactor: 風險停損賣出因子CloseATRStopSellFactor: 收盤價 ATR 停損賣出因子
功能: 執行選股回測,篩選符合條件的股票
主要類別: StockPickerWorker
輸入:
data_manager:StockDataManager實例stock_pickers(list): 選股因子配置列表,格式:[ {"class": RegressAngleFactor, "angle_threshold": 30}, ... ]
輸出:
choice_symbols(list): 被選中的股票代號列表factor_results_df(pd.DataFrame): 詳細的因子篩選結果,包含:- 各因子的通過/失敗狀態
- 最終選中結果
功能: 單檔股票時機回測引擎
timing_backtester.py 的 MultiStockBacktester,即使只回測單一股票也可以使用(只需傳入包含單一股票的字典)。
主要類別: Backtester
輸入:
df(pd.DataFrame): 價格資料,index 為日期,至少包含Close欄位buy_factors(list): 買入因子配置列表[{"class": BreakoutFactor, "xd": 60}, ...]sell_factors(list): 賣出因子配置列表[{"class": ATRStopSellFactor, "atr_multiplier": 2.0}, ...]initial_capital(float): 初始資金,預設 1,000,000slippage_factors(list, optional): 滑價因子配置列表
輸出:
result(pd.DataFrame): 回測結果,包含:strategy_equity: 策略權益曲線position: 持倉股數- 各因子訊號欄位
trades(pd.DataFrame): 交易紀錄,包含:entry_date,exit_date: 進出場日期entry_price,exit_price: 進出場價格shares: 股數return_pct: 報酬率pnl: 盈虧金額
stats(dict): 績效統計,包含:策略_總報酬率,策略_年化報酬率策略_Sharpe,策略_最大回撤等
canceled_trades(pd.DataFrame, optional): 被滑價取消的交易紀錄(如果有滑價模型)
功能: 多股票時機回測引擎,支援倉位管理
主要類別: MultiStockBacktester
輸入:
stock_data(dict): 股票資料字典,格式{股票代號: DataFrame}buy_factors(list, optional): 全局買入因子配置sell_factors(list, optional): 全局賣出因子配置strategy_config(dict, optional): 客製化策略字典{ "TSLA": { "buy_factors": [...], "sell_factors": [...] } }initial_capital(float): 初始資金,預設 1,000,000position_manager(BasePositionManager, optional): 倉位管理器slippage_factors(list, optional): 滑價因子配置列表enable_full_rate_factor(bool): 是否啟用滿倉模擬(將收益放大為同全倉投入收益)
輸出:
stock_results(dict): 回測結果字典,包含:equity_curve: 策略權益曲線raw_equity_curve: 實際資金曲線(未調整)cash_curve: 現金曲線benchmark_equity: 基準權益曲線
trades(pd.DataFrame): 所有股票的交易紀錄stats(dict): 績效統計,包含策略和基準的各項指標canceled_trades(pd.DataFrame, optional): 被滑價取消的交易紀錄
功能: 計算每次交易應該買入的股數
基類: BasePositionManager
輸入:
current_price(float): 當前價格available_capital(float): 可用資金**kwargs: 其他參數,可能包含:total_capital: 總資金current_holdings: 當前持倉股票數量atr: ATR 值(用於風險基礎倉位)returns: 歷史報酬率(用於波動率倉位)
輸出:
float: 應該買入的股數(可以是小數)
實作範例:
EqualWeightPositionManager: 等權重倉位管理FixedRatioPositionManager: 固定比例倉位管理RiskBasePositionManager: 風險基礎倉位管理VolatilityPositionManager: 波動率倉位管理KellyPositionManager: 凱利公式倉位管理
功能: 模擬實際交易中的滑價和撤單情況
基類: BaseSlippage
輸入:
df(pd.DataFrame): 整個價格資料(用於前置計算)action(str):"buy"或"sell",指定應用於買入或賣出- 其他參數依模型而定
方法:
set_current_data(row): 在回測每日迴圈中被呼叫,傳入當天數據fit_price(): 計算滑價後的成交價格
輸出:
float: 滑價後的成交價格- 買入撤單: 回傳
np.inf - 賣出撤單: 回傳
0或-np.inf
- 買入撤單: 回傳
實作範例:
SlippageOpenGap: 開盤大跌滑價模型- 參數:
open_down_rate(float): 開盤跌幅閾值,預設 0.07
- 參數:
功能: 計算和顯示各種績效指標
主要類別: PerformanceMetrics
輸入:
trades(pd.DataFrame): 交易紀錄 DataFramestats(dict, optional): 基本統計字典equity_curve(pd.Series, optional): 權益曲線initial_capital(float, optional): 初始資金basic_metrics(list, optional): 基本指標配置列表detailed_metrics(list, optional): 詳細指標配置列表
輸出:
stats(dict): 基本績效指標,包含:策略_總報酬率,策略_年化報酬率策略_年化波動率,策略_Sharpe策略_最大回撤,策略_最終權益
detailed_stats(dict): 詳細績效指標,包含:總交易次數,獲利交易次數,虧損交易次數勝率,平均獲利,平均虧損盈虧比,淨獲利最大單筆獲利,最大單筆虧損平均持倉天數,平均報酬率最大連續獲利次數,最大連續虧損次數
主要方法:
show_summary(): 顯示績效摘要show_by_symbol(): 按股票分組顯示績效plot_equity_curve(): 繪製權益曲線圖plot_drawdown(): 繪製回撤曲線圖plot_trade_distribution(): 繪製交易盈虧分佈圖plot_monthly_returns(): 繪製月度報酬圖get_metrics_dataframe(): 取得所有指標的 DataFrame
基類: BaseBasicMetric
實作範例:
TotalReturnMetric: 總報酬率AnnualReturnMetric: 年化報酬率VolatilityMetric: 年化波動率SharpeMetric: Sharpe 比率MaxDrawdownMetric: 最大回撤FinalEquityMetric: 最終權益
基類: BaseDetailedMetric
實作範例:
TotalTradesMetric: 總交易次數WinRateMetric: 勝率WinningTradesMetric: 獲利交易次數LosingTradesMetric: 虧損交易次數ProfitLossRatioMetric: 盈虧比AvgProfitMetric: 平均獲利AvgLossMetric: 平均虧損NetProfitMetric: 淨獲利MaxSingleProfitMetric: 最大單筆獲利MaxSingleLossMetric: 最大單筆虧損AvgHoldingDaysMetric: 平均持倉天數AvgReturnMetric: 平均報酬率MaxConsecutiveWinsMetric: 最大連續獲利次數MaxConsecutiveLossesMetric: 最大連續虧損次數
功能: 自動化測試不同因子組合,找出最佳參數配置
功能: 單股票因子優化器
主要類別: FactorOptimizer
輸入:
df(pd.DataFrame): 股票價格資料parameter_space(ParameterSpace): 參數空間定義initial_capital(float): 初始資金,預設 1,000,000slippage_factors(list, optional): 滑價因子列表n_jobs(int): 並行處理進程數,-1表示使用所有 CPU 核心metric_weights(dict or list, optional): 績效指標權重配置- 可以是字典:
{'策略_總報酬率': 0.3, '策略_Sharpe': 0.2, ...} - 或指標類別列表:
[{"class": TotalReturnMetric, "weight": 3}, ...]
- 可以是字典:
basic_metrics(list, optional): 基本指標列表detailed_metrics(list, optional): 詳細指標列表
輸出:
best_config(dict): 最佳配置字典,包含:buy_factors: 最佳買入因子配置sell_factors: 最佳賣出因子配置總得分: 總得分
results_df(pd.DataFrame): 所有組合的結果 DataFrame,包含:總得分: 總得分(排序依據)買入因子,賣出因子: 因子配置- 各項績效指標和單項得分
主要方法:
optimize(): 執行優化get_top_n(n): 取得前 N 名結果save_results(filepath): 儲存結果到 CSV
功能: 多股票因子優化器
主要類別: MultiStockFactorOptimizer
輸入:
stock_data(dict): 股票資料字典parameter_space(ParameterSpace): 參數空間定義initial_capital(float): 初始資金slippage_factors(list, optional): 滑價因子列表position_manager(BasePositionManager, optional): 倉位管理器enable_full_rate_factor(bool): 是否啟用滿倉模擬n_jobs(int): 並行處理進程數metric_weights(dict or list, optional): 績效指標權重配置basic_metrics(list, optional): 基本指標列表detailed_metrics(list, optional): 詳細指標列表
輸出: 與 FactorOptimizer 相同
功能: 定義參數空間,生成所有因子組合
主要類別: ParameterSpace
輸入: 因子配置列表,例如:
ParameterSpace(
buy_factors=[
[{"class": BreakoutFactor, "xd": xd} for xd in [20, 40, 60]],
...
],
sell_factors=[
[{"class": ATRStopSellFactor, "atr_multiplier": mult} for mult in [1.5, 2.0, 2.5]],
...
]
)輸出:
combinations(list): 所有因子組合列表
功能: 定義可用的績效指標和評分方法
主要內容:
AVAILABLE_METRICS(dict): 可用指標字典,定義各指標的:key: 指標鍵名source: 資料來源(stats或detailed_stats)higher_is_better: 是否越大越好
功能: 計算基準績效(Buy & Hold 策略)
主要類別: Benchmark
靜態方法:
-
compute_log_ret(df): 計算對數報酬率- 輸入:
df(pd.DataFrame) - 單股票價格資料 - 輸出:
pd.Series- 對數報酬率序列
- 輸入:
-
compute_equity_curve(df, initial_capital): 計算基準權益曲線- 輸入:
df(pd.DataFrame) - 單股票價格資料initial_capital(float) - 初始資金
- 輸出:
pd.Series- 基準權益曲線
- 輸入:
-
compute_single_stock_benchmark(df, initial_capital): 計算完整基準績效- 輸入: 同上
- 輸出:
dict- 包含equity_curve,log_ret,stats
-
compute_multi_stock_equity_curve(stock_data, initial_capital): 計算多股票基準權益曲線(平均分散)- 輸入:
stock_data(dict) - 股票資料字典initial_capital(float) - 初始資金
- 輸出:
pd.Series- 基準權益曲線
- 輸入:
-
compute_multi_stock_benchmark(stock_data, initial_capital): 計算完整多股票基準績效- 輸入: 同上
- 輸出:
dict- 包含equity_curve,log_ret,stats
compute_performance_stats(equity_curve, initial_capital, log_ret=None): 計算基準績效指標- 輸入:
equity_curve(pd.Series) - 基準權益曲線initial_capital(float) - 初始資金log_ret(pd.Series, optional) - 對數報酬率
- 輸出:
dict- 包含:總報酬率,年化報酬率年化波動率,Sharpe最大回撤
- 輸入:
功能: 計算標準化後的股價趨勢角度
主要類別: RegressionUtil
靜態方法:
calc_regress_deg(data, symbol=None, show=False): 計算趨勢角度- 輸入:
data(pd.Series): 價格序列symbol(str, optional): 股票代號(用於顯示)show(bool): 是否顯示圖表
- 輸出:
float- 趨勢角度(度數)
- 輸入:
裝飾器:
reversed_result(func): 如果self.reversed為True,則翻轉fit_pick的布林返回值
from alanq.data.data_manager import StockDataManager
# ~~from alanq.backtest.timing_backtester_single import Backtester~~ # 已棄用
from alanq.backtest.timing_backtester import MultiStockBacktester # 推薦使用
from alanq.factors.timing.breakout_factor import BreakoutFactor
from alanq.factors.timing.atr_stop_sell_factor import ATRStopSellFactor
# 1. 下載資料
data_manager = StockDataManager(
symbols=["TSLA"],
start_date="2020-01-01",
end_date="2023-12-31"
)
stock_data = data_manager.get_stock_data()
# 2. 設定因子
buy_factors = [
{"class": BreakoutFactor, "xd": 60}
]
sell_factors = [
{"class": ATRStopSellFactor, "atr_multiplier": 2.0}
]
# 3. 執行回測(使用 MultiStockBacktester,即使只有單一股票)
backtester = MultiStockBacktester(
stock_data=stock_data, # 傳入字典格式
buy_factors=buy_factors,
sell_factors=sell_factors,
initial_capital=1_000_000
)
stock_results, trades, stats = backtester.run(show_plot=True)
# 4. 查看結果
print(stats)
print(trades.head())from alanq.backtest.timing_backtester import MultiStockBacktester
from alanq.positions.equal_weight_position import EqualWeightPositionManager
# 1. 準備多股票資料
data_manager = StockDataManager(
symbols=["TSLA", "AAPL", "MSFT"],
start_date="2020-01-01",
end_date="2023-12-31"
)
stock_data = data_manager.get_stock_data()
# 2. 設定倉位管理
position_manager = EqualWeightPositionManager(max_stocks=5)
# 3. 執行多股票回測
backtester = MultiStockBacktester(
stock_data=stock_data,
buy_factors=buy_factors,
sell_factors=sell_factors,
initial_capital=1_000_000,
position_manager=position_manager
)
stock_results, trades, stats = backtester.run(show_plot=True)from alanq.optimization.factor_optimizer import FactorOptimizer
from alanq.optimization.parameter_space import ParameterSpace
# 1. 定義參數空間
parameter_space = ParameterSpace(
buy_factors=[
[{"class": BreakoutFactor, "xd": xd} for xd in [20, 40, 60, 80]]
],
sell_factors=[
[{"class": ATRStopSellFactor, "atr_multiplier": mult}
for mult in [1.5, 2.0, 2.5, 3.0]]
]
)
# 2. 執行優化
optimizer = FactorOptimizer(
df=df,
parameter_space=parameter_space,
initial_capital=1_000_000,
n_jobs=-1 # 使用所有 CPU 核心
)
best_config, results_df = optimizer.optimize()
# 3. 查看最佳配置
print(f"最佳配置: {best_config}")
print(f"前 10 名結果:")
print(optimizer.get_top_n(10))from alanq.performance.performance_metrics import PerformanceMetrics
# 計算績效指標
metrics = PerformanceMetrics(
trades=trades,
stats=stats,
equity_curve=result['strategy_equity'],
initial_capital=1_000_000
)
# 顯示摘要
metrics.show_summary()
# 繪製圖表
metrics.plot_equity_curve()
metrics.plot_drawdown()
metrics.plot_trade_distribution()本專案也包含機器學習相關的應用範例,詳見 notebooks/CH10-監督與非監督機器學習.ipynb。
主要依賴套件:
pandas: 資料處理numpy: 數值計算matplotlib: 圖表繪製yfinance: 股票資料下載statsmodels: 統計分析(用於回歸工具)
- 資料格式: 所有價格資料的 DataFrame 必須包含
Open,High,Low,Close欄位,且 index 為日期 - 因子配置: 因子配置必須包含
"class"鍵,指定因子類別 - 滑價模型: 滑價模型必須指定
action參數("buy"或"sell") - 並行處理: 優化器支援多進程並行處理,可大幅提升效率
- 滿倉模擬: 多股票回測器支援
enable_full_rate_factor選項,可將收益放大為同全倉投入收益,便於與基準比較




