Skip to content

Backtest results stay the same regardless of model usedΒ #1930

Closed
@kyleluc

Description

@kyleluc

πŸ› Bug Report

I noticed that when I switch between different models (e.g., LGBModel, XGBModel, DNNModel), the backtest results remain exactly the same β€” including cumulative return, daily return, and other portfolio metrics.

πŸ“„ Code Snippet

Here is the simplified version of my model training code and backtesting code:
model training code:
each time when training,I just modify the task[model] param and experiment_name

data_handler_config = {
    "freq":"day", #1min
    "start_time": "2020-01-01",
    "end_time": "2025-03-31",
    "fit_start_time": "2020-01-01",
    "fit_end_time": "2025-03-30",
    "instruments": ["BTC","ETH","BNB","NEO","ONG"]
}
lgb_model={
        "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,
        },
    }
d_ensemble_model={
        "class": "DEnsembleModel",
        "module_path": "qlib.contrib.model.double_ensemble",
        "kwargs": {
            "model_class": "LGBModel",
            "n_estimators": 5,
            "decay": 0.9,
        }
    }
xgb_model={
        "class": "XGBModel",
        "module_path": "qlib.contrib.model.xgboost"
    }
task = {
    "model": xgb_model, #this is the 1st param I changed when training
    "dataset": {
        "class": "DatasetH",
        "module_path": "qlib.data.dataset",
        "kwargs": {
            "handler": {
                "class": "Alpha158",
                "module_path": "qlib.contrib.data.handler",
                "kwargs": data_handler_config,
            },
            "segments": {
                "train": ("2020-01-01", "2023-12-31"),
                "valid": ("2024-01-01", "2024-12-31"),
                "test": ("2025-01-01", "2025-03-30"),
            },
        },
    },
}

# model initialization
model = init_instance_by_config(task["model"])
dataset = init_instance_by_config(task["dataset"])

# start exp to train model, this is the 2nd param I changed when training
with R.start(experiment_name="xgb_exp_3"):
    R.log_params(**flatten_dict(task))
    model.fit(dataset)
    R.save_objects(trained_model=model)
    R.save_objects(trained_dataset=dataset)
    rid = R.get_recorder().id
    print(f"rid of xgb_exp_3 = {rid}")

backtesting code:
It's always the same,except the experiment_name param

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": {
            "model": model,
            "dataset": dataset,
            "topk": 50,
            "n_drop": 5,
        },
    },
    "backtest": {
        "start_time": "2025-01-01",
        "end_time": "2025-03-30",
        "account": 100000000,
        "benchmark": benchmark,
        "exchange_kwargs": {
            "limit_threshold": 0.99,
            "deal_price": "close",
            "open_cost": 0.0005,
            "close_cost": 0.0005,
            "min_cost": 1,
        },
    },
}

with R.start(experiment_name="xgb_backtest"):
    recorder = R.get_recorder(recorder_id=rid, experiment_name="xgb_exp")
    model = recorder.load_object("trained_model")

    recorder = R.get_recorder()
    sr = SignalRecord(model, dataset, recorder)
    sr.generate()

    par = PortAnaRecord(recorder, port_analysis_config, "day")
    par.generate()

this is the result I've got everytime:

'The following are analysis results of benchmark return(1day).'
                       risk
mean              -0.001070
std                0.026967
annualized_return -0.254626
information_ratio -0.612033
max_drawdown      -0.280937
'The following are analysis results of the excess return without cost(1day).'
                       risk
mean              -0.000667
std                0.022932
annualized_return -0.158777
information_ratio -0.448802
max_drawdown      -0.148111
'The following are analysis results of the excess return with cost(1day).'
                       risk
mean              -0.001136
std                0.022926
annualized_return -0.270377
information_ratio -0.764456
max_drawdown      -0.164187
'The following are analysis results of indicators(1day).'
     value
ffr    1.0
pa     0.0
pos    0.0

Expected Behavior

I expect backtest results to vary when I change the underlying model.

Screenshot

Environment

Note: User could run cd scripts && python collect_info.py all under project directory to get system information
and paste them here directly.

  • Qlib version: 0.9.6
  • Python version: 3.8.10
  • OS (Windows, Linux, MacOS): windows10
  • Commit number (optional, please provide it if you are using the dev version):

Additional Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions