# -*- coding: utf-8 -*-
"""月營收成長動能 三因子 — finlab 台股真實回測(可重現,含樣本外驗證)。

對應文章:https://finlab.finance/blog/hermes-agent-finlab-walk-forward
回測區間:2018-01-01 ~ 2026-06-09(全站 canonical 快照日)
基準:0050 含息(etl:adj_close 還原價買進持有)
成本:finlab sim() 台股預設(手續費 0.1425%、賣出證交稅 0.3%),未另設滑價

walk-forward:把 2018–2021 當研究段、2022 之後當樣本外(策略沒見過的資料)分開檢視,
避免「整段 in-sample 挑到漂亮參數」的錯覺。

執行:
  cd ~/Documents/finlab && UV_ENV_FILE=.env uv run --with finlab python strategy.py

本程式僅供量化研究與教學,過去績效不代表未來表現,不構成任何投資建議。
"""
import finlab
from finlab import data
from finlab.backtest import sim

finlab.login()

# 1) 載入資料
close = data.get("price:收盤價")
volume = data.get("price:成交股數")
revenue_yoy = data.get("monthly_revenue:去年同月增減(%)").reindex(close.index, method="ffill")
roe = data.get("fundamental_features:ROE稅後").index_str_to_date()
roe = roe.reindex(close.index, method="ffill")

# 2) 健康成長股票池:年增 10%~200% 且最近 3 個月都正成長(排除暴衝與衰退)
healthy_growth = (revenue_yoy > 10) & (revenue_yoy < 200) & ((revenue_yoy > 0).rolling(3).sum() == 3)

# 3) 三個因子:營收成長 + 價格動能 + 品質
rank_revenue = revenue_yoy.where(healthy_growth).rank(axis=1, pct=True)
rank_momentum = close.pct_change(60).where(healthy_growth).rank(axis=1, pct=True)
rank_quality = roe.where(healthy_growth).rank(axis=1, pct=True)
score = rank_revenue + rank_momentum + rank_quality

# 4) 取前 20 名,分數平方加權,每月再平衡(每月 10 號營收公布後資料自動更新)
top20 = score.rank(axis=1, ascending=False) <= 20
weight = (score[top20].fillna(0)) ** 2
weight = weight.div(weight.sum(axis=1), axis=0)

report = sim(weight, resample="M", name="月營收成長動能")
report.display()
