# -*- coding: utf-8 -*-
"""排名法多因子策略:營收動能 40% + ROE 30% + 價格動能 30%,流動性過濾後取前 20 名。

對應文章:https://finlab.finance/blog/ai-agent-quant-trading-guide
先完成 https://finlab.finance/setup 的 AI 輔助設定流程；再執行本檔。

投資警語:本程式僅供量化研究與教學用途,過去績效不代表未來表現,
不構成任何投資建議;實際交易前請自行評估風險、滑價與交易容量。
"""
from finlab import data
from finlab.backtest import sim

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

# 因子對齊:月營收與 ROE 依公布時點向後填值到日頻,避免用到未來資料
rev_d = revenue_yoy.reindex(close.index, method="ffill")
roe_d = roe.reindex(close.index, method="ffill")

# 三個因子各自做全市場百分位排名(0~1,越高越好)
rev_rank = rev_d.rank(axis=1, pct=True)
roe_rank = roe_d.rank(axis=1, pct=True)
mom_rank = close.pct_change(60).rank(axis=1, pct=True)  # 60 個交易日(約一季)動能

# 加權綜合分數:營收 40% + ROE 30% + 動能 30%
composite = rev_rank * 0.4 + roe_rank * 0.3 + mom_rank * 0.3

# 流動性過濾:近 20 日平均成交金額 > 1,000 萬
amount20 = (close * volume).rolling(20).mean()
liquid = amount20 > 10_000_000

# 每月選綜合分數最高的前 20 檔,等權重買入
position = composite.where(liquid & close.notna()).is_largest(20)

# 回測:每月再平衡(finlab 預設內扣手續費 0.1425% 與賣出證交稅 0.3%)
report = sim(position, resample="M", upload=False, name="排名法多因子策略")
print(report.get_stats())

# 目前選股清單
latest = position[position.any(axis=1)].iloc[-1]
print(sorted(latest[latest].index.tolist()))
