diff --git a/README.md b/README.md index ab8196cc..595fc7bd 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ TODO: Add badges. -# News +# ๐Ÿ“ฐ News | ๐Ÿ—ž๏ธNews | ๐Ÿ“Description | | -- | ------ | | First release | RDAgent are release on Github | -# Introduction +# ๐ŸŒŸ Introduction ![](docs/_static/scen.jpg) @@ -31,15 +31,62 @@ We have a quick ๐ŸŽฅdemo for one use case of RDAgent. # โšกQuick start You can try our demo by running the following command: -```bash -# TODO: -# prepare environment -# installation -# App entrance -``` +### ๐Ÿ Create a Conda Environment +- Create a new conda environment with Python (3.10 and 3.11 are well tested in our CI): + ```sh + conda create -n rdagent python=3.10 + ``` +- Activate the environment: + ```sh + conda activate rdagent + ``` + +### ๐Ÿ› ๏ธ Run Make Files +TODO: `pip install rdagent` in the future. + +- **Navigate to the directory containing the MakeFile** and set up the development environment: + ```sh + make dev + ``` + +### ๐Ÿ“ฆ Install Pytorch +TODO: use docker in quick start intead. + +- Install Pytorch and related libraries: + ```sh + pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu + pip3 install torch_geometric + ``` + +### โš™๏ธ Environment Configuration +- Place the `.env` file in the same directory as the `.env.example` file. + - TOOD: please refer to ... for the detailed explanation of the `.env` + - TODO: simplify `.env.example` only keep OpenAI or Azure Azure OpenAI +- Export each variable in the `.env` file: + ```sh + export $(grep -v '^#' .env | xargs) + ``` +### ๐Ÿš€ Run the Application +TODO: run the front-page demo. The [๐ŸŽฅdemo]() is implemented by the above commands. +- Run the factor extraction and implementation application based on financial reports: + ```sh + python rdagent/app/qlib_rd_loop/factor_from_report_sh.py + ``` + +- Run the self-loop factor extraction and implementation application: + ```sh + python rdagent/app/qlib_rd_loop/factor.py + ``` + +- Run the self-loop model extraction and implementation application: + ```sh + python rdagent/app/qlib_rd_loop/model.py + ``` + + # Scenarios We have applied RD-Agent to multiple valuable data-driven industrial scenarios.. @@ -60,9 +107,9 @@ Here is our supported scenarios | Scenario/Target | Model Implementation | Data Building | | -- | -- | -- | -| ๐Ÿ’นFinance | Iteratively Proposing Ideas & Evolving | - Auto reports reading & implementation
- Iteratively Proposing Ideas & Evolving | -| ๐ŸฉบMedical | Iteratively Proposing Ideas & Evolving | - | -| General | Auto paper reading & implementation | - | +| ๐Ÿ’น Finance | Iteratively Proposing Ideas & Evolving | - Auto reports reading & implementation
- Iteratively Proposing Ideas & Evolving | +| ๐Ÿฉบ Medical | Iteratively Proposing Ideas & Evolving | - | +| ๐Ÿญ General | Auto paper reading & implementation | - | Different scenarios vary in entrance and configuration. Please check the detailed setup tutorial in the scenarios documents. diff --git a/docs/installation.rst b/docs/installation.rst index 90a3f1a0..b4852be3 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -13,3 +13,27 @@ Configuration ============= Quick configuration + + + + +Azure OpenAI +------------ + + + +USE_AZURE_TOKEN_PROVIDER +~~~~~~~~~~~~~~~~~~~~~~~~ + +### โ˜๏ธ Azure Configuration +- Install Azure CLI: + ```sh + curl -L https://aka.ms/InstallAzureCli | bash + ``` +- Log in to Azure: + ```sh + az login --use-device-code + ``` + +- `exit` and re-login to your environment (this step may not be necessary). + diff --git a/docs/scenarios_and_quickstart.rst b/docs/scenarios_and_quickstart.rst index cdc613b6..e264cb24 100644 --- a/docs/scenarios_and_quickstart.rst +++ b/docs/scenarios_and_quickstart.rst @@ -5,29 +5,107 @@ Scenarios and Quick Start Scenario lists ========================= -TODO: Copy the content in the README.md +.. list-table:: + :header-rows: 1 + * - Scenario/Target + - Model Implementation + - Data Building + * - ๐Ÿ’น Finance + - Iteratively Proposing Ideas & Evolving + - Auto reports reading & implementation + Iteratively Proposing Ideas & Evolving + * - ๐Ÿฉบ Medical + - Iteratively Proposing Ideas & Evolving + - + * - ๐Ÿญ General + - Auto paper reading & implementation + - Scnarios' demo & quick start ========================= Scen1 ----- +๐Ÿค– Knowledge-Based Hypothesis Generation and Iteration Scen1 Intro ~~~~~~~~~~~ +In this scenario, our model autonomously generates and tests hypotheses using a knowledge base. The process involves: + +- **๐Ÿ” Hypothesis Generation**: The model proposes new hypotheses. +- **๐Ÿ“ Factor Creation**: Write and define new factors. +- **โœ… Factor Validation**: Validate the factors quantitatively. +- **๐Ÿ“ˆ Backtesting with Qlib**: + + - **Dataset**: CSI300 + - **Model**: LGBModel + - **Factors**: Alpha158 + + - **Data Split**: + + - **Train**: 2008-01-01 to 2014-12-31 + - **Valid**: 2015-01-01 to 2016-12-31 + - **Test**: 2017-01-01 to 2020-08-01 +- **๐Ÿ”„ Feedback Analysis**: Analyze backtest results. +- **๐Ÿ”ง Hypothesis Refinement**: Refine hypotheses based on feedback and repeat. Scen1 Demo ~~~~~~~~~~ +.. TODO Scen1 Quick Start ~~~~~~~~~~~~~~~~~ +To quickly start the factor extraction process, run the following command in your terminal within the 'rdagent' virtual environment: +.. code-block:: sh + python rdagent/app/qlib_rd_loop/factor.py Usage of modules -================ +~~~~~~~~~~~~~~~~~ TODO: Show some examples: + +Scen2: +----- +๐Ÿ“„ Research Report-Based Factor Extraction + +Scen2 Intro +~~~~~~~~~~~ +In this scenario, factors and hypotheses are extracted from research reports. The process includes: + +- **๐Ÿ” Factor Extraction**: Extract relevant factors from research reports. +- **๐Ÿ“ Factor Creation**: Define these extracted factors. +- **โœ… Factor Validation**: Validate the extracted factors. +- **๐Ÿ“ˆ Backtesting with Qlib**: + + - **Dataset**: CSI300 + - **Model**: LGBModel + - **Factors**: Alpha158 + + - **Data Split**: + + - **Train**: 2008-01-01 to 2014-12-31 + - **Valid**: 2015-01-01 to 2016-12-31 + - **Test**: 2017-01-01 to 2020-08-01 +- **๐Ÿ”„ Feedback Analysis**: Analyze backtest results. +- **๐Ÿ”ง Hypothesis Refinement**: Refine hypotheses based on feedback and continue the cycle. + +Scen2 Demo +~~~~~~~~~~ +.. TODO + +Scen2 Quick Start +~~~~~~~~~~~~~~~~~ + +To quickly start the factor extraction process, run the following command in your terminal within the 'rdagent' virtual environment: + +.. code-block:: sh + + python rdagent/app/qlib_rd_loop/factor_from_report_sh.py + + +Usage of modules +~~~~~~~~~~~~~~~~~ +TODO: Show some examples: \ No newline at end of file diff --git a/rdagent/app/qlib_rd_loop/conf.py b/rdagent/app/qlib_rd_loop/conf.py index 60d63dbb..cf618866 100644 --- a/rdagent/app/qlib_rd_loop/conf.py +++ b/rdagent/app/qlib_rd_loop/conf.py @@ -1,39 +1,43 @@ -from pathlib import Path - -from pydantic_settings import BaseSettings +from rdagent.components.workflow.conf import BasePropSetting -class PropSetting(BaseSettings): +class ModelBasePropSetting(BasePropSetting): class Config: - env_prefix = "QLIB_" # Use MODEL_CODER_ as prefix for environment variables + env_prefix = "QLIB_MODEL_" # Use MODEL_CODER_ as prefix for environment variables protected_namespaces = () # Add 'model_' to the protected namespaces - factor_scen: str = "rdagent.scenarios.qlib.experiment.factor_experiment.QlibFactorScenario" - factor_hypothesis_gen: str = "rdagent.scenarios.qlib.proposal.factor_proposal.QlibFactorHypothesisGen" - factor_hypothesis2experiment: str = ( - "rdagent.scenarios.qlib.proposal.factor_proposal.QlibFactorHypothesis2Experiment" - ) - factor_coder: str = "rdagent.scenarios.qlib.developer.factor_coder.QlibFactorCoSTEER" - factor_runner: str = "rdagent.scenarios.qlib.developer.factor_runner.QlibFactorRunner" - factor_summarizer: str = "rdagent.scenarios.qlib.developer.feedback.QlibFactorHypothesisExperiment2Feedback" - - # TODO: model part is not finished yet - model_scen: str = "rdagent.scenarios.qlib.experiment.model_experiment.QlibModelScenario" - model_hypothesis_gen: str = "rdagent.scenarios.qlib.proposal.model_proposal.QlibModelHypothesisGen" - model_hypothesis2experiment: str = "rdagent.scenarios.qlib.proposal.model_proposal.QlibModelHypothesis2Experiment" - model_coder: str = "rdagent.scenarios.qlib.developer.model_coder.QlibModelCoSTEER" - model_runner: str = "rdagent.scenarios.qlib.developer.model_runner.QlibModelRunner" - model_summarizer: str = "rdagent.scenarios.qlib.developer.feedback.QlibModelHypothesisExperiment2Feedback" + scen: str = "rdagent.scenarios.qlib.experiment.model_experiment.QlibModelScenario" + hypothesis_gen: str = "rdagent.scenarios.qlib.proposal.model_proposal.QlibModelHypothesisGen" + hypothesis2experiment: str = "rdagent.scenarios.qlib.proposal.model_proposal.QlibModelHypothesis2Experiment" + coder: str = "rdagent.scenarios.qlib.developer.model_coder.QlibModelCoSTEER" + runner: str = "rdagent.scenarios.qlib.developer.model_runner.QlibModelRunner" + summarizer: str = "rdagent.scenarios.qlib.developer.feedback.QlibModelHypothesisExperiment2Feedback" evolving_n: int = 10 - py_bin: str = "/usr/bin/python" - local_qlib_folder: Path = Path("/home/rdagent/qlib") +class FactorBasePropSetting(BasePropSetting): + class Config: + env_prefix = "QLIB_FACTOR_" # Use MODEL_CODER_ as prefix for environment variables + protected_namespaces = () # Add 'model_' to the protected namespaces + + # 1) override base settings + # TODO: model part is not finished yet + scen: str = "rdagent.scenarios.qlib.experiment.factor_experiment.QlibFactorScenario" + hypothesis_gen: str = "rdagent.scenarios.qlib.proposal.factor_proposal.QlibFactorHypothesisGen" + hypothesis2experiment: str = "rdagent.scenarios.qlib.proposal.factor_proposal.QlibFactorHypothesis2Experiment" + coder: str = "rdagent.scenarios.qlib.developer.factor_coder.QlibFactorCoSTEER" + runner: str = "rdagent.scenarios.qlib.developer.factor_runner.QlibFactorRunner" + summarizer: str = "rdagent.scenarios.qlib.developer.feedback.QlibFactorHypothesisExperiment2Feedback" + + evolving_n: int = 10 + + # 2) sub task specific: origin_report_path: str = "data/report_origin" local_report_path: str = "data/report" report_result_json_file_path: str = "git_ignore_folder/res_dict.json" progress_file_path: str = "git_ignore_folder/progress.pkl" -PROP_SETTING = PropSetting() +FACTOR_PROP_SETTING = FactorBasePropSetting() +MODEL_PROP_SETTING = ModelBasePropSetting() diff --git a/rdagent/app/qlib_rd_loop/factor_w_sc.py b/rdagent/app/qlib_rd_loop/factor_w_sc.py new file mode 100644 index 00000000..1e6f8220 --- /dev/null +++ b/rdagent/app/qlib_rd_loop/factor_w_sc.py @@ -0,0 +1,38 @@ +""" +Factor workflow with session control +""" + +import fire + +from rdagent.app.qlib_rd_loop.conf import FACTOR_PROP_SETTING +from rdagent.components.workflow.rd_loop import RDLoop +from rdagent.core.exception import FactorEmptyError + + +class FactorRDLoop(RDLoop): + skip_loop_error = (FactorEmptyError,) + + +def main(path=None, step_n=None): + """ + You can continue running session by + + .. code-block:: python + + dotenv run -- python rdagent/app/qlib_rd_loop/factor_w_sc.py $LOG_PATH/__session__/1/0_propose --step_n 1 # `step_n` is a optional paramter + + """ + if path is None: + model_loop = FactorRDLoop(FACTOR_PROP_SETTING) + else: + model_loop = FactorRDLoop.load(path) + model_loop.run(step_n=step_n) + + +if __name__ == "__main__": + fire.Fire(main) + + + +if __name__ == "__main__": + fire.Fire(main) diff --git a/rdagent/app/qlib_rd_loop/model_w_sc.py b/rdagent/app/qlib_rd_loop/model_w_sc.py index c5fca4c3..59e89b67 100644 --- a/rdagent/app/qlib_rd_loop/model_w_sc.py +++ b/rdagent/app/qlib_rd_loop/model_w_sc.py @@ -1,70 +1,16 @@ """ Model workflow with session control -It is from `rdagent/app/qlib_rd_loop/model.py` and try to replace `rdagent/app/qlib_rd_loop/RDAgent.py` """ import fire -from typing import Any -from rdagent.app.qlib_rd_loop.conf import PROP_SETTING -from rdagent.core.developer import Developer + +from rdagent.app.qlib_rd_loop.conf import MODEL_PROP_SETTING +from rdagent.components.workflow.rd_loop import RDLoop from rdagent.core.exception import ModelEmptyError -from rdagent.core.proposal import ( - Hypothesis2Experiment, - HypothesisExperiment2Feedback, - HypothesisGen, - Trace, -) -from rdagent.core.scenario import Scenario -from rdagent.core.utils import import_class -from rdagent.log import rdagent_logger as logger -from rdagent.utils.workflow import LoopMeta, LoopBase -class ModelLoop(LoopBase, metaclass=LoopMeta): - # TODO: supporting customized loop control like catching `ModelEmptyError` - - def __init__(self): - scen: Scenario = import_class(PROP_SETTING.model_scen)() - - self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.model_hypothesis_gen)(scen) - - self.hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.model_hypothesis2experiment)() - - self.qlib_model_coder: Developer = import_class(PROP_SETTING.model_coder)(scen) - self.qlib_model_runner: Developer = import_class(PROP_SETTING.model_runner)(scen) - - self.qlib_model_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.model_summarizer)(scen) - self.trace = Trace(scen=scen) - super().__init__() - - def propose(self, prev_out: dict[str, Any]): - with logger.tag("r"): # research - hypothesis = self.hypothesis_gen.gen(self.trace) - logger.log_object(hypothesis, tag="hypothesis generation") - return hypothesis - - def exp_gen(self, prev_out: dict[str, Any]): - with logger.tag("r"): # research - exp = self.hypothesis2experiment.convert(prev_out["propose"], self.trace) - logger.log_object(exp.sub_tasks, tag="experiment generation") - return exp - - def coding(self, prev_out: dict[str, Any]): - with logger.tag("d"): # develop - exp = self.qlib_model_coder.develop(prev_out["exp_gen"]) - logger.log_object(exp.sub_workspace_list, tag="model coder result") - return exp - - def running(self, prev_out: dict[str, Any]): - with logger.tag("ef"): # evaluate and feedback - exp = self.qlib_model_runner.develop(prev_out["coding"]) - logger.log_object(exp, tag="model runner result") - return exp - - def feedback(self, prev_out: dict[str, Any]): - feedback = self.qlib_model_summarizer.generate_feedback(prev_out["running"], prev_out["propose"], self.trace) - logger.log_object(feedback, tag="feedback") - self.trace.hist.append((prev_out["propose"],prev_out["running"] , feedback)) +class ModelRDLoop(RDLoop): + skip_loop_error = (ModelEmptyError,) def main(path=None, step_n=None): @@ -77,9 +23,9 @@ def main(path=None, step_n=None): """ if path is None: - model_loop = ModelLoop() + model_loop = ModelRDLoop(MODEL_PROP_SETTING) else: - model_loop = ModelLoop.load(path) + model_loop = ModelRDLoop.load(path) model_loop.run(step_n=step_n) diff --git a/rdagent/components/workflow/rd_loop.py b/rdagent/components/workflow/rd_loop.py index 69a73d5d..d1a40017 100644 --- a/rdagent/components/workflow/rd_loop.py +++ b/rdagent/components/workflow/rd_loop.py @@ -60,5 +60,6 @@ class RDLoop(LoopBase, metaclass=LoopMeta): def feedback(self, prev_out: dict[str, Any]): feedback = self.summarizer.generate_feedback(prev_out["running"], prev_out["propose"], self.trace) - logger.log_object(feedback, tag="feedback") + with logger.tag("ef"): # evaluate and feedback + logger.log_object(feedback, tag="feedback") self.trace.hist.append((prev_out["propose"],prev_out["running"] , feedback)) diff --git a/rdagent/scenarios/qlib/experiment/factor_experiment.py b/rdagent/scenarios/qlib/experiment/factor_experiment.py index b4821eb4..09e166d5 100644 --- a/rdagent/scenarios/qlib/experiment/factor_experiment.py +++ b/rdagent/scenarios/qlib/experiment/factor_experiment.py @@ -39,6 +39,10 @@ class QlibFactorScenario(Scenario): @property def simulator(self) -> str: return prompt_dict["qlib_factor_simulator"] + + @property + def rich_style_description(self)->str: + return "Below is QlibFactor Evolving Automatic R&D Demo." def get_scenario_all_desc(self) -> str: return f"""Background of the scenario: diff --git a/rdagent/scenarios/qlib/experiment/factor_template/read_exp_res.py b/rdagent/scenarios/qlib/experiment/factor_template/read_exp_res.py index 19930248..d08e3b4c 100644 --- a/rdagent/scenarios/qlib/experiment/factor_template/read_exp_res.py +++ b/rdagent/scenarios/qlib/experiment/factor_template/read_exp_res.py @@ -43,3 +43,6 @@ else: metrics.to_csv(output_path) print(f"Output has been saved to {output_path}") + + ret_data_frame = latest_recorder.load_object("portfolio_analysis/report_normal_1day.pkl") + ret_data_frame.to_pickle("ret.pkl") \ No newline at end of file diff --git a/rdagent/scenarios/qlib/experiment/workspace.py b/rdagent/scenarios/qlib/experiment/workspace.py index 00871440..f3e16e11 100644 --- a/rdagent/scenarios/qlib/experiment/workspace.py +++ b/rdagent/scenarios/qlib/experiment/workspace.py @@ -31,7 +31,7 @@ class QlibFBWorkspace(FBWorkspace): ) ret_df = pd.read_pickle(self.workspace_path / "ret.pkl") - logger.log_object(ret_df, tag="returns") # TODO: tag + logger.log_object(ret_df, tag="Quantitative Backtesting Chart") csv_path = self.workspace_path / "qlib_res.csv" diff --git a/rdagent/scenarios/qlib/prompts.yaml b/rdagent/scenarios/qlib/prompts.yaml index 19814df6..139ebd57 100644 --- a/rdagent/scenarios/qlib/prompts.yaml +++ b/rdagent/scenarios/qlib/prompts.yaml @@ -59,7 +59,7 @@ factor_hypothesis_specification: |- - "Filter stocks by market capitalization before calculating the factors." factor_hypothesis_specification: |- - Additional Specifications: + Specifications: - Hypotheses should grow and evolve based on the previous hypothesis. If there is no previous hypothesis, start with something simple. - Gradually build upon previous hypotheses and feedback. - Ensure that the hypothesis focuses on the creation and selection of factors in quantitative finance. @@ -94,7 +94,7 @@ factor_hypothesis_specification: |- - "Investigate the impact of an earnings surprise factor calculated from recent earnings announcements." - "Develop a composite factor integrating ESG (Environmental, Social, Governance) scores with traditional financial metrics." - Detailed Workflow: + Detailed Workflow: (These are just examples for the format, do not be constrained by these examples) 1. Initial Hypothesis: - Begin with a simple factor, such as "Include a momentum factor based on the last 12 months' returns." @@ -110,8 +110,11 @@ factor_hypothesis_specification: |- 5. Advanced Hypotheses: - Explore sophisticated combinations or new types of factors, e.g., "Develop a composite factor integrating ESG scores with traditional financial metrics." - Remember: If a hypothesis achieves the desired results, start a new direction while preserving the effective factors from previous hypotheses. New evaluations should combine the newly proposed factors with previously successful factors that surpassed SOTA. - + Important Note: + - If a hypothesis achieves the desired results, start a new direction while preserving the effective factors from previous hypotheses. + - New evaluations should combine the newly proposed factors with previously successful factors that surpassed SOTA. + - If the previous hypothesis factor exceeds SOTA, you can write another factor in the same direction, otherwise, explore new directions. + - The final maintained SOTA is the continuous accumulation of factors that surpass each iteration. factor_experiment_output_format: |- The output should follow JSON format. The schema is as follows: