Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions examples/us_fundamental/workflow_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
qlib_init:
provider_uri: "~/.qlib/qlib_data/us_data"
region: us

market: &market sp500
benchmark: &benchmark ^GSPC

data_handler_config: &data_handler_config
start_time: "2018-01-01"
end_time: "2024-12-31"
fit_start_time: "2018-01-01"
fit_end_time: "2022-12-31"
instruments: *market
infer_processors:
- class: ProcessInf
kwargs: {}
- class: ZScoreNorm
kwargs: {}
- class: Fillna
kwargs: {}
learn_processors:
- class: DropnaLabel
- class: CSZScoreNorm
kwargs:
fields_group: label

data_loader_config: &data_loader_config
class: QlibDataLoader
kwargs:
config:
feature:
# ── Technical factors (Alpha158 US-tuned) ──────────────
# K-bar features
- ["($close-$open)/$open", "KMID"]
- ["($high-$low)/$open", "KLEN"]
- ["($close-$open)/($high-$low+1e-12)", "KMID2"]

# Price features (no VWAP)
- ["$open/$close", "OPEN0"]
- ["$high/$close", "HIGH0"]
- ["$low/$close", "LOW0"]

# Momentum (extended windows for US market)
- ["Ref($close, 5)/$close", "ROC5"]
- ["Ref($close, 10)/$close", "ROC10"]
- ["Ref($close, 20)/$close", "ROC20"]
- ["Ref($close, 60)/$close", "ROC60"]
- ["Ref($close, 120)/$close", "ROC120"]
- ["Ref($close, 250)/$close", "ROC250"]

# Moving averages
- ["Mean($close, 5)/$close", "MA5"]
- ["Mean($close, 10)/$close", "MA10"]
- ["Mean($close, 20)/$close", "MA20"]
- ["Mean($close, 60)/$close", "MA60"]
- ["Mean($close, 120)/$close", "MA120"]
- ["Mean($close, 250)/$close", "MA250"]

# Volatility
- ["Std($close, 5)/$close", "STD5"]
- ["Std($close, 20)/$close", "STD20"]
- ["Std($close, 60)/$close", "STD60"]
- ["Std($close, 250)/$close", "STD250"]

# 12-1 month momentum (Jegadeesh & Titman)
- ["Ref($close, 250)/$close - Ref($close, 20)/$close", "MOM_12_1"]

# Overnight gap
- ["$open / Ref($close, 1) - 1", "GAP"]

# ── Fundamental factors ────────────────────────────────
# Quality
- ["$roe", "ROE"]
- ["$roa", "ROA"]
- ["$gross_margin", "GMARGIN"]
- ["$accruals", "ACCRUALS"]

# Leverage
- ["$debt_to_equity", "DE_RATIO"]

# Growth
- ["$revenue_yoy", "REV_YOY"]
- ["$earnings_yoy", "EARN_YOY"]

# Value (price-relative)
- ["$netincome / ($close + 1e-12)", "EARN_YIELD"]
- ["$totalrevenue / ($close + 1e-12)", "SALES_YIELD"]
- ["$freecashflow / ($close + 1e-12)", "FCF_YIELD"]
- ["$stockholdersequity / ($close + 1e-12)", "BOOK_YIELD"]

label:
- ["Ref($close, -2)/Ref($close, -1) - 1", "LABEL0"]

task:
model:
class: LGBModel
module_path: qlib.contrib.model.gbdt
kwargs:
loss: mse
colsample_bytree: 0.8879
learning_rate: 0.05
subsample: 0.8789
lambda_l1: 205.6999
lambda_l2: 580.9768
max_depth: 8
num_leaves: 210
num_threads: 20
n_estimators: 1000
early_stopping_rounds: 50
verbose: -1
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: USAlphaFundamental
module_path: qlib.contrib.data.handler_us
kwargs: *data_handler_config
segments:
train: ["2018-01-01", "2021-12-31"]
valid: ["2022-01-01", "2022-12-31"]
test: ["2023-01-01", "2024-12-31"]
record:
- class: SignalRecord
module_path: qlib.workflow.record_temp
kwargs:
model: <MODEL>
dataset: <DATASET>
- class: SigAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
ana_long_short: false
ann_scaler: 252
- class: PortAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
config:
strategy:
class: TopkDropoutStrategy
module_path: qlib.contrib.strategy
kwargs:
signal: <PRED>
topk: 50
n_drop: 5
backtest:
start_time: "2023-01-01"
end_time: "2024-12-31"
account: 100000000
benchmark: *benchmark
exchange_kwargs:
limit_threshold: null # No price limits in US
deal_price: close
open_cost: 0.0005
close_cost: 0.0015
min_cost: 5
44 changes: 38 additions & 6 deletions examples/workflow_by_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from qlib.workflow import R
from qlib.workflow.record_temp import SignalRecord, PortAnaRecord, SigAnaRecord
from qlib.tests.data import GetData
from qlib.tests.config import CSI300_BENCH, CSI300_GBDT_TASK
from qlib.tests.config import CSI300_BENCH, CSI300_MARKET, GBDT_MODEL


if __name__ == "__main__":
Expand All @@ -22,8 +22,40 @@
GetData().qlib_data(target_dir=provider_uri, region=REG_CN, exists_skip=True)
qlib.init(provider_uri=provider_uri, region=REG_CN)

model = init_instance_by_config(CSI300_GBDT_TASK["model"])
dataset = init_instance_by_config(CSI300_GBDT_TASK["dataset"])
# ---------- 自定義:只預測 2017-01-01 起的連續 10 個交易日 ----------
# A 股 2017 年第一個交易日是 1/3(二),10 個交易日大約到 1/16(一)
# 設 test end 為 1/20 留點餘裕,實際只會取到有交易日的部分
TEST_START = "2017-01-01"
TEST_END = "2017-01-20"

task_config = {
"model": GBDT_MODEL,
"dataset": {
"class": "DatasetH",
"module_path": "qlib.data.dataset",
"kwargs": {
"handler": {
"class": "Alpha158",
"module_path": "qlib.contrib.data.handler",
"kwargs": {
"start_time": "2008-01-01",
"end_time": TEST_END,
"fit_start_time": "2008-01-01",
"fit_end_time": "2014-12-31",
"instruments": CSI300_MARKET,
},
},
"segments": {
"train": ("2008-01-01", "2014-12-31"),
"valid": ("2015-01-01", "2016-12-31"),
"test": (TEST_START, TEST_END),
},
},
},
}

model = init_instance_by_config(task_config["model"])
dataset = init_instance_by_config(task_config["dataset"])

port_analysis_config = {
"executor": {
Expand All @@ -44,8 +76,8 @@
},
},
"backtest": {
"start_time": "2017-01-01",
"end_time": "2020-08-01",
"start_time": TEST_START,
"end_time": TEST_END,
"account": 100000000,
"benchmark": CSI300_BENCH,
"exchange_kwargs": {
Expand All @@ -66,7 +98,7 @@

# start exp
with R.start(experiment_name="workflow"):
R.log_params(**flatten_dict(CSI300_GBDT_TASK))
R.log_params(**flatten_dict(task_config))
model.fit(dataset)
R.save_objects(**{"params.pkl": model})

Expand Down
Loading