mirror of
https://github.com/microsoft/qlib.git
synced 2026-11-11 21:41:06 +08:00
* Update test_qlib_from_source.yml * add ipynb format check to workflow * test ipynb CI * modify nbqa check path * add pylint flake8 mypy check to ipynb * check ipynb with black and pylint * reformat .ipynb files * format line length nbqa black . -l 120 * update nbqa .ipynb format CI * format old ipynb files * add nbconvert check to CI * adjust CI order to avoid repeating download data
29 KiB
29 KiB
In [ ]:
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.In [ ]:
from pprint import pprint
from pathlib import Path
import pandas as pdIn [ ]:
MARKET = "csi300"
BENCHMARK = "SH000300"
EXP_NAME = "tutorial_exp"In [ ]:
from qlib.tests.data import GetData
GetData().qlib_data(exists_skip=True)In [ ]:
import qlib
qlib.init()In [ ]:
from qlib.data import D
print(D.calendar(start_time="2010-01-01", end_time="2017-12-31", freq="day")[:2]) # calendar dataIn [ ]:
df = D.features(
["SH601216"],
["$open", "$high", "$low", "$close", "$factor"],
start_time="2020-05-01",
end_time="2020-05-31",
)In [ ]:
import plotly.graph_objects as go
fig = go.Figure(
data=[
go.Candlestick(
x=df.index.get_level_values("datetime"),
open=df["$open"],
high=df["$high"],
low=df["$low"],
close=df["$close"],
)
]
)
fig.show()In [ ]:
import plotly.graph_objects as go
fig = go.Figure(
data=[
go.Candlestick(
x=df.index.get_level_values("datetime"),
open=df["$open"] / df["$factor"],
high=df["$high"] / df["$factor"],
low=df["$low"] / df["$factor"],
close=df["$close"] / df["$factor"],
)
]
)
fig.show()In [ ]:
# dynamic universe
universe = D.list_instruments(D.instruments("csi100"), start_time="2010-01-01", end_time="2020-12-31")
pprint(universe)In [ ]:
print(len(universe))In [ ]:
df = D.features(D.instruments("csi100"), ["$close"], start_time="2010-01-01", end_time="2020-12-31")
df.groupby("datetime").size().plot()In [ ]:
p = Path("~/.qlib/qlib_data/cn_data/financial").expanduser()In [ ]:
if not p.exists():
!cd ../../scripts/data_collector/pit/ && pip install -r requirements.txt
!cd ../../scripts/data_collector/pit/ && python collector.py download_data --source_dir ~/.qlib/stock_data/source/pit --start 2000-01-01 --end 2020-01-01 --interval quarterly --symbol_regex "^(600519|000725).*"
!cd ../../scripts/data_collector/pit/ && python collector.py normalize_data --interval quarterly --source_dir ~/.qlib/stock_data/source/pit --normalize_dir ~/.qlib/stock_data/source/pit_normalized
!cd ../../scripts/ && python dump_pit.py dump --csv_path ~/.qlib/stock_data/source/pit_normalized --qlib_dir ~/.qlib/qlib_data/cn_data --interval quarterlyIn [ ]:
instruments = ["sh600519"]
data = D.features(
instruments,
["P($$roewa_q)"],
start_time="2019-01-01",
end_time="2019-07-19",
freq="day",
)In [ ]:
data.tail(15)In [ ]:
D.features(
["sh600519"],
["(EMA($close, 12) - EMA($close, 26))/$close - EMA((EMA($close, 12) - EMA($close, 26))/$close, 9)/$close"],
)In [ ]:
from qlib.data.dataset.loader import QlibDataLoaderIn [ ]:
qdl = QlibDataLoader(config=(["$close / Ref($close, 10)"], ["RET10"]))In [ ]:
qdl.load(instruments=["sh600519"], start_time="20190101", end_time="20191231")In [ ]:
df = qdl.load(instruments=["sh600519"], start_time="20190101", end_time="20191231")In [ ]:
df.isna().sum()In [ ]:
df.plot(kind="hist")In [ ]:
from qlib.data.dataset.handler import DataHandlerLP
from qlib.data.dataset.processor import ZScoreNorm, FillnaIn [ ]:
# NOTE: normally, the training & validation time range will be `fit_start_time` , `fit_end_time`
# however,all the components are decomposed, so the training & validation time range is unknown when preprocessing.
dh = DataHandlerLP(
instruments=["sh600519"],
start_time="20170101",
end_time="20191231",
infer_processors=[
ZScoreNorm(fit_start_time="20170101", fit_end_time="20181231"),
Fillna(),
],
data_loader=qdl,
)In [ ]:
df = dh.fetch()In [ ]:
dfIn [ ]:
df.isna().sum()In [ ]:
df.plot(kind="hist")In [ ]:
from qlib.data.dataset import DatasetH, TSDatasetHIn [ ]:
ds = DatasetH(dh, segments={"train": ("20180101", "20181231"), "valid": ("20190101", "20191231")})In [ ]:
ds.prepare("train")In [ ]:
ds.prepare("valid")In [ ]:
ds = TSDatasetH(
step_len=10,
handler=dh,
segments={"train": ("20180101", "20181231"), "valid": ("20190101", "20191231")},
)
train_sampler = ds.prepare("train")In [ ]:
train_samplerIn [ ]:
train_sampler[0] # Retrieving the first exampleIn [ ]:
train_sampler["2018-01-08", "sh600519"] # get the time series by <'timestamp', 'instrument_id'> indexIn [ ]:
handler_kwargs = {
"start_time": "2008-01-01",
"end_time": "2020-08-01",
"fit_start_time": "2008-01-01",
"fit_end_time": "2014-12-31",
"instruments": MARKET,
}
handler_conf = {
"class": "Alpha158",
"module_path": "qlib.contrib.data.handler",
"kwargs": handler_kwargs,
}
pprint(handler_conf)In [ ]:
from qlib.utils import init_instance_by_configIn [ ]:
hd = init_instance_by_config(handler_conf)In [ ]:
from qlib.contrib.data.handler import Alpha158
hd = Alpha158(**handler_kwargs)In [ ]:
df = hd.fetch()In [ ]:
dfIn [ ]:
hd.data_loaderIn [ ]:
hd.data_loader.fieldsIn [ ]:
hd.learn_processorsIn [ ]:
hd.infer_processorsIn [ ]:
hd.process_type # appending typeIn [ ]:
hd.fetch(col_set="label", data_key=hd.DK_L)In [ ]:
hd.fetch(col_set="label", data_key=hd.DK_I)In [ ]:
dataset_conf = {
"class": "DatasetH",
"module_path": "qlib.data.dataset",
"kwargs": {
"handler": hd,
"segments": {
"train": ("2008-01-01", "2014-12-31"),
"valid": ("2015-01-01", "2016-12-31"),
"test": ("2017-01-01", "2020-08-01"),
},
},
}In [ ]:
dataset = init_instance_by_config(dataset_conf)In [ ]:
from qlib.workflow import R
from qlib.workflow.record_temp import SignalRecord, PortAnaRecord, SigAnaRecordIn [ ]:
model = init_instance_by_config(
{
"class": "LGBModel",
"module_path": "qlib.contrib.model.gbdt",
"kwargs": {
"loss": "mse",
"colsample_bytree": 0.8879,
"learning_rate": 0.0421,
"subsample": 0.8789,
"lambda_l1": 205.6999,
"lambda_l2": 580.9768,
"max_depth": 8,
"num_leaves": 210,
"num_threads": 20,
},
}
)In [ ]:
# start exp to train model
with R.start(experiment_name=EXP_NAME):
model.fit(dataset)
R.save_objects(trained_model=model)
rec = R.get_recorder()
rid = rec.id # save the record id
# Inference and saving signal
sr = SignalRecord(model, dataset, rec)
sr.generate()In [ ]:
###################################
# prediction, backtest & analysis
###################################
port_analysis_config = {
"executor": {
"class": "SimulatorExecutor",
"module_path": "qlib.backtest.executor",
"kwargs": {
"time_per_step": "day",
"generate_portfolio_metrics": True,
},
},
"strategy": {
"class": "TopkDropoutStrategy",
"module_path": "qlib.contrib.strategy.signal_strategy",
"kwargs": {
"signal": "<PRED>",
"topk": 50,
"n_drop": 5,
},
},
"backtest": {
"start_time": "2017-01-01",
"end_time": "2020-08-01",
"account": 100000000,
"benchmark": BENCHMARK,
"exchange_kwargs": {
"freq": "day",
"limit_threshold": 0.095,
"deal_price": "close",
"open_cost": 0.0005,
"close_cost": 0.0015,
"min_cost": 5,
},
},
}
# backtest and analysis
with R.start(experiment_name=EXP_NAME, recorder_id=rid, resume=True):
# signal-based analysis
rec = R.get_recorder()
sar = SigAnaRecord(rec)
sar.generate()
# portfolio-based analysis: backtest
par = PortAnaRecord(rec, port_analysis_config, "day")
par.generate()In [ ]:
# load recorder
recorder = R.get_recorder(recorder_id=rid, experiment_name=EXP_NAME)In [ ]:
# load previous results
pred_df = recorder.load_object("pred.pkl")
report_normal_df = recorder.load_object("portfolio_analysis/report_normal_1day.pkl")
positions = recorder.load_object("portfolio_analysis/positions_normal_1day.pkl")
analysis_df = recorder.load_object("portfolio_analysis/port_analysis_1day.pkl")In [ ]:
# Previous Model can be loaded. but it is not used.
loaded_model = recorder.load_object("trained_model")
loaded_modelIn [ ]:
from qlib.contrib.report import analysis_model, analysis_positionIn [ ]:
analysis_position.report_graph(report_normal_df)In [ ]:
analysis_position.risk_analysis_graph(analysis_df, report_normal_df)Warning:
Output truncated. This notebook contains too many cells to display efficiently.