Finance Quant Agent¶
🥇The First Data-Centric Quant Multi-Agent Framework RD-Agent(Q)¶
R&D-Agent for Quantitative Finance, in short RD-Agent(Q), is the first data-centric, multi-agent framework designed to automate the full-stack research and development of quantitative strategies via coordinated factor-model co-optimization.
You can learn more details about RD-Agent(Q) through the paper.
⚡ Quick Start¶
Before you start, please make sure you have installed RD-Agent and configured the environment for RD-Agent correctly. If you want to know how to install and configure the RD-Agent, please refer to the documentation.
Then, you can run the framework by running the following command:
🐍 Create a Conda Environment
Create a new conda environment with Python (3.10 and 3.11 are well tested in our CI):
conda create -n rdagent python=3.10
Activate the environment:
conda activate rdagent
📦 Install the RDAgent
You can install the RDAgent package from PyPI:
pip install rdagent
🚀 Run the Application
You can directly run the application by using the following command:
rdagent fin_quant
🛠️ Usage of modules¶
Env Config
The following environment variables can be set in the .env file to customize the application’s behavior:
- pydantic settings rdagent.app.qlib_rd_loop.conf.QuantBasePropSetting¶
Show JSON schema
{ "title": "QuantBasePropSetting", "type": "object", "properties": { "scen": { "default": "rdagent.scenarios.qlib.experiment.quant_experiment.QlibQuantScenario", "title": "Scen", "type": "string" }, "knowledge_base": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Knowledge Base" }, "knowledge_base_path": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Knowledge Base Path" }, "hypothesis_gen": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Hypothesis Gen" }, "interactor": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Interactor" }, "hypothesis2experiment": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Hypothesis2Experiment" }, "coder": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Coder" }, "runner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Runner" }, "summarizer": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Summarizer" }, "evolving_n": { "default": 10, "title": "Evolving N", "type": "integer" }, "quant_hypothesis_gen": { "default": "rdagent.scenarios.qlib.proposal.quant_proposal.QlibQuantHypothesisGen", "title": "Quant Hypothesis Gen", "type": "string" }, "model_hypothesis2experiment": { "default": "rdagent.scenarios.qlib.proposal.model_proposal.QlibModelHypothesis2Experiment", "title": "Model Hypothesis2Experiment", "type": "string" }, "model_coder": { "default": "rdagent.scenarios.qlib.developer.model_coder.QlibModelCoSTEER", "title": "Model Coder", "type": "string" }, "model_runner": { "default": "rdagent.scenarios.qlib.developer.model_runner.QlibModelRunner", "title": "Model Runner", "type": "string" }, "model_summarizer": { "default": "rdagent.scenarios.qlib.developer.feedback.QlibModelExperiment2Feedback", "title": "Model Summarizer", "type": "string" }, "factor_hypothesis2experiment": { "default": "rdagent.scenarios.qlib.proposal.factor_proposal.QlibFactorHypothesis2Experiment", "title": "Factor Hypothesis2Experiment", "type": "string" }, "factor_coder": { "default": "rdagent.scenarios.qlib.developer.factor_coder.QlibFactorCoSTEER", "title": "Factor Coder", "type": "string" }, "factor_runner": { "default": "rdagent.scenarios.qlib.developer.factor_runner.QlibFactorRunner", "title": "Factor Runner", "type": "string" }, "factor_summarizer": { "default": "rdagent.scenarios.qlib.developer.feedback.QlibFactorExperiment2Feedback", "title": "Factor Summarizer", "type": "string" }, "action_selection": { "default": "bandit", "title": "Action Selection", "type": "string" }, "train_start": { "default": "2008-01-01", "title": "Train Start", "type": "string" }, "train_end": { "default": "2014-12-31", "title": "Train End", "type": "string" }, "valid_start": { "default": "2015-01-01", "title": "Valid Start", "type": "string" }, "valid_end": { "default": "2016-12-31", "title": "Valid End", "type": "string" }, "test_start": { "default": "2017-01-01", "title": "Test Start", "type": "string" }, "test_end": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": "2020-08-01", "title": "Test End" } }, "additionalProperties": false }
- Config:
env_prefix: str = QLIB_QUANT_
protected_namespaces: tuple = ()
- field action_selection: str = 'bandit'¶
Action selection strategy: ‘bandit’ for bandit-based selection, ‘llm’ for LLM-based selection, ‘random’ for random selection
- field evolving_n: int = 10¶
Number of evolutions
- field factor_coder: str = 'rdagent.scenarios.qlib.developer.factor_coder.QlibFactorCoSTEER'¶
Coder class
- field factor_hypothesis2experiment: str = 'rdagent.scenarios.qlib.proposal.factor_proposal.QlibFactorHypothesis2Experiment'¶
Hypothesis to experiment class
- field factor_runner: str = 'rdagent.scenarios.qlib.developer.factor_runner.QlibFactorRunner'¶
Runner class
- field factor_summarizer: str = 'rdagent.scenarios.qlib.developer.feedback.QlibFactorExperiment2Feedback'¶
Summarizer class
- field model_coder: str = 'rdagent.scenarios.qlib.developer.model_coder.QlibModelCoSTEER'¶
Coder class
- field model_hypothesis2experiment: str = 'rdagent.scenarios.qlib.proposal.model_proposal.QlibModelHypothesis2Experiment'¶
Hypothesis to experiment class
- field model_runner: str = 'rdagent.scenarios.qlib.developer.model_runner.QlibModelRunner'¶
Runner class
- field model_summarizer: str = 'rdagent.scenarios.qlib.developer.feedback.QlibModelExperiment2Feedback'¶
Summarizer class
- field quant_hypothesis_gen: str = 'rdagent.scenarios.qlib.proposal.quant_proposal.QlibQuantHypothesisGen'¶
Hypothesis generation class
- field scen: str = 'rdagent.scenarios.qlib.experiment.quant_experiment.QlibQuantScenario'¶
Scenario class for Qlib Model
- field test_end: str | None = '2020-08-01'¶
End date of the test / backtest segment
- field test_start: str = '2017-01-01'¶
Start date of the test / backtest segment
- field train_end: str = '2014-12-31'¶
End date of the training segment
- field train_start: str = '2008-01-01'¶
Start date of the training segment
- field valid_end: str = '2016-12-31'¶
End date of the validation segment
- field valid_start: str = '2015-01-01'¶
Start date of the validation segment
- Qlib Configuration
- The .yaml files in both the model_template and factor_template directories contain some configurations for running the corresponding models or factors within the Qlib framework. Below is an overview of their contents and roles:
- General Settings:
provider_uri: Specifies the local Qlib data path, set to ~/.qlib/qlib_data/cn_data.
market: Configured to csi300, representing the CSI 300 index constituents.
benchmark: Set to SH000300, used for backtesting evaluation.
- Data Handling:
start_time and end_time: Define the full data range, from 2008-01-01 to 2022-08-01.
fit_start_time: The start date for fitting the model, set to 2008-01-01.
fit_end_time: The end date for fitting the model, set to 2014-12-31.
features and labels: Generated via a nested data loader combining Alpha158DL (for engineered features such as RESI5, WVMA5, RSQR5, KLEN, etc.) and a StaticDataLoader that loads precomputed factor files (combined_factors_df.parquet).
normalization: The pipeline includes RobustZScoreNorm (with clipping) and Fillna for inference, and DropnaLabel with CSZScoreNorm for training.
- Training Configuration:
Model: Uses GeneralPTNN, a PyTorch-based neural network model.
- Dataset Splits:
train: 2008-01-01 to 2014-12-31
valid: 2015-01-01 to 2016-12-31
test: 2017-01-01 to 2020-08-01
- Default Hyperparameters (can be overridden by command-line arguments):
n_epochs: 100
lr: 2e-4
early_stop: 10
batch_size: 256
weight_decay: 0.0
metric: loss
loss: mse
n_jobs: 20
GPU: 0 (uses GPU 0 if available)
- Backtesting and Evaluation:
strategy: TopkDropoutStrategy, which selects the top 50 stocks and randomly drops 5 to introduce exploration.
backtest period: 2017-01-01 to 2020-08-01
initial capital: 100,000,000
cost configuration: Includes open/close costs, minimum transaction costs, and slippage control.
- Recording and Analysis:
SignalRecord: Logs predicted signals.
SigAnaRecord: Performs signal analysis without long-short separation.
PortAnaRecord: Conducts portfolio analysis using the configured strategy and backtest settings.