mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-13 15:56:57 +08:00
Initial interface for discussion
This commit is contained in:
0
qlib/finco/__init__.py
Normal file
0
qlib/finco/__init__.py
Normal file
11
qlib/finco/cli.py
Normal file
11
qlib/finco/cli.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import fire
|
||||||
|
from qlib.finco.task import WorkflowManager
|
||||||
|
|
||||||
|
|
||||||
|
def main(prompt):
|
||||||
|
wm = WorkflowManager()
|
||||||
|
wm.run(prompt)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fire.Fire(main)
|
||||||
8
qlib/finco/conf.py
Normal file
8
qlib/finco/conf.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# TODO: use pydantic for other modules in Qlib
|
||||||
|
from pydantic import BaseSettings
|
||||||
|
|
||||||
|
|
||||||
|
class Conf(BaseSettings):
|
||||||
|
"""module specific settings."""
|
||||||
|
|
||||||
|
...
|
||||||
14
qlib/finco/llm.py
Normal file
14
qlib/finco/llm.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import openai
|
||||||
|
|
||||||
|
|
||||||
|
def example():
|
||||||
|
response = openai.ChatCompletion.create(
|
||||||
|
engine="gpt-35-turbo", # The deployment name you chose when you deployed the ChatGPT or GPT-4 model.
|
||||||
|
# engine="gpt-4", # NOTE: this raises this error: openai.error.RateLimitError: Requests to the Creates a completion for the chat message Operation under Azure OpenAI API version 2023-05-15 have exceeded call rate limit of your current OpenAI S0 pricing tier
|
||||||
|
# engine="gpt-4-32k", # This works for only;
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": "Assistant is a large language model trained by OpenAI."},
|
||||||
|
{"role": "user", "content": "Who were the founders of Microsoft?"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
print(response)
|
||||||
120
qlib/finco/task.py
Normal file
120
qlib/finco/task.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, List
|
||||||
|
from qlib.typehint import Literal
|
||||||
|
|
||||||
|
|
||||||
|
class Task:
|
||||||
|
"""
|
||||||
|
The user's intention, which was initially represented by a prompt, is achieved through a sequence of tasks.
|
||||||
|
|
||||||
|
Some thoughts:
|
||||||
|
- Do we have to split create a new concept of Action besides Task?
|
||||||
|
- Most actions directly modify the disk, with their interfaces taking in and outputting text. The LLM's interface similarly takes in and outputs text.
|
||||||
|
- Some actions will run some commands.
|
||||||
|
|
||||||
|
Maybe we can just categorizing tasks by following?
|
||||||
|
- Planning task (it is at a high level and difficult to execute directly; therefore, it should be further divided):
|
||||||
|
- Action Task
|
||||||
|
- CMD Task: it is expected to run a cmd
|
||||||
|
- Edit Task: it is supposed to edit the code base directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, context=None) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def summarize(self) -> str:
|
||||||
|
"""After the execution of the task, it is supposed to generated some context about the execution"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def update_context(self, latest_context):
|
||||||
|
...
|
||||||
|
|
||||||
|
def execution(self) -> Any:
|
||||||
|
"""The execution results of the task"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PlanTask(Task):
|
||||||
|
def execute(self) -> List[Task]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowTask(PlanTask):
|
||||||
|
"""make the choice which main workflow (RL, SL) will be used"""
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class SLTask(PlanTask):
|
||||||
|
def exeute(self):
|
||||||
|
"""
|
||||||
|
return a list of interested tasks
|
||||||
|
Copy the template project maybe a part of the task
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class ActionTask(Task):
|
||||||
|
def execute(self) -> Literal["fail", "success"]:
|
||||||
|
return "success"
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowManager:
|
||||||
|
"""This manange the whole task automation workflow including tasks and actions"""
|
||||||
|
|
||||||
|
def __init__(self, name="project", output_path=None) -> None:
|
||||||
|
|
||||||
|
if output_path is None:
|
||||||
|
self._output_path = Path.cwd() / name
|
||||||
|
else:
|
||||||
|
self._output_path = Path(output_path)
|
||||||
|
self._context = []
|
||||||
|
|
||||||
|
def add_context(self, task_res):
|
||||||
|
self._context.append(task_res)
|
||||||
|
|
||||||
|
def get_context(self):
|
||||||
|
"""TODO: context manger?"""
|
||||||
|
|
||||||
|
def run(self, prompt: str) -> Path:
|
||||||
|
"""
|
||||||
|
The workflow manager is supposed to generate a codebase based on the prompt
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
prompt: str
|
||||||
|
the prompt user gives
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Path
|
||||||
|
The workflow manager is expected to produce output that includes a codebase containing generated code, results, and reports in a designated location.
|
||||||
|
The path is returned
|
||||||
|
|
||||||
|
The output path should follow a specific format:
|
||||||
|
- TODO: design
|
||||||
|
There is a summarized report where user can start from.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# NOTE: The following items are not designed to make the workflow very flexible.
|
||||||
|
# - The generated tasks can't be changed after geting new information from the execution retuls.
|
||||||
|
# - But it is required in some cases, if we want to build a external dataset, it maybe have to plan like autogpt...
|
||||||
|
|
||||||
|
# NOTE: list may not be enough for general task list
|
||||||
|
task_list = [WorkflowTask(prompt)]
|
||||||
|
while len(task_list):
|
||||||
|
# task_list.ap
|
||||||
|
t = task_list.pop(0)
|
||||||
|
t.update_context(self.get_context())
|
||||||
|
res = t.execute()
|
||||||
|
if isinstance(t, PlanTask):
|
||||||
|
task_list.extend(res)
|
||||||
|
elif isinstance(t, ActionTask):
|
||||||
|
if res != "success":
|
||||||
|
...
|
||||||
|
# TODO: handle the unexpected execution Error
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Unsupported action type")
|
||||||
|
self.add_context(t.summarize())
|
||||||
|
return self._output_path
|
||||||
6
qlib/finco/tpls/README.md
Normal file
6
qlib/finco/tpls/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
This is a set of templates that should be copied for a new project.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
- [ ] [Copier](https://copier.readthedocs.io/en/stable/#quick-start) may be useful if the generation process becomes complicated
|
||||||
72
qlib/finco/tpls/sl/workflow_config.yaml
Normal file
72
qlib/finco/tpls/sl/workflow_config.yaml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
qlib_init:
|
||||||
|
provider_uri: "~/.qlib/qlib_data/cn_data"
|
||||||
|
region: cn
|
||||||
|
market: &market csi300
|
||||||
|
benchmark: &benchmark SH000300
|
||||||
|
data_handler_config: &data_handler_config
|
||||||
|
start_time: 2008-01-01
|
||||||
|
end_time: 2020-08-01
|
||||||
|
fit_start_time: 2008-01-01
|
||||||
|
fit_end_time: 2014-12-31
|
||||||
|
instruments: *market
|
||||||
|
port_analysis_config: &port_analysis_config
|
||||||
|
strategy:
|
||||||
|
class: TopkDropoutStrategy
|
||||||
|
module_path: qlib.contrib.strategy
|
||||||
|
kwargs:
|
||||||
|
model: <MODEL>
|
||||||
|
dataset: <DATASET>
|
||||||
|
topk: 50
|
||||||
|
n_drop: 5
|
||||||
|
backtest:
|
||||||
|
start_time: 2017-01-01
|
||||||
|
end_time: 2020-08-01
|
||||||
|
account: 100000000
|
||||||
|
benchmark: *benchmark
|
||||||
|
exchange_kwargs:
|
||||||
|
limit_threshold: 0.095
|
||||||
|
deal_price: close
|
||||||
|
open_cost: 0.0005
|
||||||
|
close_cost: 0.0015
|
||||||
|
min_cost: 5
|
||||||
|
task:
|
||||||
|
model:
|
||||||
|
class: LGBModel
|
||||||
|
module_path: qlib.contrib.model.gbdt
|
||||||
|
kwargs:
|
||||||
|
loss: mse
|
||||||
|
colsample_bytree: 0.8879
|
||||||
|
learning_rate: 0.2
|
||||||
|
subsample: 0.8789
|
||||||
|
lambda_l1: 205.6999
|
||||||
|
lambda_l2: 580.9768
|
||||||
|
max_depth: 8
|
||||||
|
num_leaves: 210
|
||||||
|
num_threads: 20
|
||||||
|
dataset:
|
||||||
|
class: DatasetH
|
||||||
|
module_path: qlib.data.dataset
|
||||||
|
kwargs:
|
||||||
|
handler:
|
||||||
|
class: Alpha158
|
||||||
|
module_path: qlib.contrib.data.handler
|
||||||
|
kwargs: *data_handler_config
|
||||||
|
segments:
|
||||||
|
train: [2008-01-01, 2014-12-31]
|
||||||
|
valid: [2015-01-01, 2016-12-31]
|
||||||
|
test: [2017-01-01, 2020-08-01]
|
||||||
|
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: *port_analysis_config
|
||||||
14
scripts/finco/README.md
Normal file
14
scripts/finco/README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
```
|
||||||
|
pydantic
|
||||||
|
openai
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# TODOs
|
||||||
|
|
||||||
|
- [ ] Select the appropriate LLM API
|
||||||
|
- Which API is more suitable for meeting our requirements - the original API or an alternative like LangChain?
|
||||||
15
scripts/finco/cmd.sh
Normal file
15
scripts/finco/cmd.sh
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -x # show command
|
||||||
|
set -e # Error on exception
|
||||||
|
|
||||||
|
DIR="$(
|
||||||
|
cd "$(dirname "$(readlink -f "$0")")" || exit
|
||||||
|
pwd -P
|
||||||
|
)"
|
||||||
|
# --load the cridentials
|
||||||
|
if [ -e $DIR/cridential.sh ]; then
|
||||||
|
source $DIR/cridential.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# run the command
|
||||||
|
python -m qlib.finco.cli "please help me build a low turnover strategy that focus more on longterm return"
|
||||||
3
scripts/finco/cridential.sh.example
Normal file
3
scripts/finco/cridential.sh.example
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export OPENAI_API_TYPE=azure # This only necessary for Azure OpenAI
|
||||||
|
export OPENAI_API_KEY=
|
||||||
|
export OPENAI_API_BASE=
|
||||||
Reference in New Issue
Block a user