mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-01 01:51:18 +08:00
492 lines
32 KiB
Plaintext
492 lines
32 KiB
Plaintext
{
|
|
"metadata": {
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.7.9-final"
|
|
},
|
|
"orig_nbformat": 2,
|
|
"kernelspec": {
|
|
"name": "python3",
|
|
"display_name": "Python 3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2,
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import sys\n",
|
|
"import copy\n",
|
|
"from pathlib import Path\n",
|
|
"\n",
|
|
"import qlib\n",
|
|
"import numpy as np\n",
|
|
"import pandas as pd\n",
|
|
"from qlib.config import REG_CN\n",
|
|
"from qlib.contrib.model.gbdt import LGBModel\n",
|
|
"from qlib.contrib.data.handler import Alpha158\n",
|
|
"from qlib.contrib.strategy.strategy import TopkDropoutStrategy\n",
|
|
"from qlib.contrib.evaluate import (\n",
|
|
" backtest as normal_backtest,\n",
|
|
" risk_analysis,\n",
|
|
")\n",
|
|
"from qlib.utils import exists_qlib_data, init_instance_by_config\n",
|
|
"from qlib.workflow import R\n",
|
|
"from qlib.workflow.record_temp import SignalRecord, PortAnaRecord\n",
|
|
"from qlib.utils import flatten_dict"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"output_type": "stream",
|
|
"name": "stderr",
|
|
"text": [
|
|
"[20768:MainThread](2020-11-27 08:15:01,096) INFO - qlib.Initialization - [__init__.py:41] - default_conf: client.\n",
|
|
"[20768:MainThread](2020-11-27 08:15:03,120) WARNING - qlib.Initialization - [__init__.py:57] - redis connection failed(host=127.0.0.1 port=6379), cache will not be used!\n",
|
|
"[20768:MainThread](2020-11-27 08:15:03,121) INFO - qlib.Initialization - [__init__.py:76] - qlib successfully initialized based on client settings.\n",
|
|
"[20768:MainThread](2020-11-27 08:15:03,122) INFO - qlib.Initialization - [__init__.py:79] - data_path=C:\\Users\\v-donzh\\.qlib\\qlib_data\\cn_data\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# use default data\n",
|
|
"# NOTE: need to download data from remote: python scripts/get_data.py qlib_data_cn --target_dir ~/.qlib/qlib_data/cn_data\n",
|
|
"provider_uri = \"~/.qlib/qlib_data/cn_data\" # target_dir\n",
|
|
"if not exists_qlib_data(provider_uri):\n",
|
|
" print(f\"Qlib data is not found in {provider_uri}\")\n",
|
|
" sys.path.append(str(Path.cwd().parent.joinpath(\"scripts\")))\n",
|
|
" from get_data import GetData\n",
|
|
" GetData().qlib_data(target_dir=provider_uri, region=REG_CN)\n",
|
|
"qlib.init(provider_uri=provider_uri, region=REG_CN)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"market = \"csi300\"\n",
|
|
"benchmark = \"SH000300\""
|
|
]
|
|
},
|
|
{
|
|
"source": [
|
|
"## Model Training"
|
|
],
|
|
"cell_type": "markdown",
|
|
"metadata": {}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"output_type": "stream",
|
|
"name": "stderr",
|
|
"text": [
|
|
"[20768:MainThread](2020-11-27 08:15:55,319) INFO - qlib.timer - [log.py:81] - Time cost: 52.158s | Loading data Done\n",
|
|
"[20768:MainThread](2020-11-27 08:15:56,107) INFO - qlib.timer - [log.py:81] - Time cost: 0.669s | DropnaLabel Done\n",
|
|
"[20768:MainThread](2020-11-27 08:15:59,716) INFO - qlib.timer - [log.py:81] - Time cost: 3.608s | CSZScoreNorm Done\n",
|
|
"[20768:MainThread](2020-11-27 08:15:59,717) INFO - qlib.timer - [log.py:81] - Time cost: 4.397s | fit & process data Done\n",
|
|
"[20768:MainThread](2020-11-27 08:15:59,717) INFO - qlib.timer - [log.py:81] - Time cost: 56.556s | Init data Done\n",
|
|
"[20768:MainThread](2020-11-27 08:15:59,722) INFO - qlib.workflow - [exp.py:180] - Experiment 1 starts running ...\n",
|
|
"[20768:MainThread](2020-11-27 08:16:00,133) INFO - qlib.workflow - [recorder.py:234] - Recorder 46e50379b45a4a7684c683cd423535a9 starts running under Experiment 1 ...\n",
|
|
"[20768:MainThread](2020-11-27 08:16:00,134) INFO - qlib.workflow - [expm.py:251] - No tracking URI is provided. The default tracking URI is set as `mlruns` under the working directory.\n",
|
|
"Training until validation scores don't improve for 50 rounds\n",
|
|
"[20]\ttrain's l2: 0.990556\tvalid's l2: 0.994299\n",
|
|
"[40]\ttrain's l2: 0.986919\tvalid's l2: 0.993683\n",
|
|
"[60]\ttrain's l2: 0.984485\tvalid's l2: 0.993495\n",
|
|
"[80]\ttrain's l2: 0.982363\tvalid's l2: 0.993365\n",
|
|
"[100]\ttrain's l2: 0.980538\tvalid's l2: 0.993251\n",
|
|
"[120]\ttrain's l2: 0.978755\tvalid's l2: 0.993265\n",
|
|
"[140]\ttrain's l2: 0.977079\tvalid's l2: 0.993324\n",
|
|
"[160]\ttrain's l2: 0.97535\tvalid's l2: 0.99336\n",
|
|
"Early stopping, best iteration is:\n",
|
|
"[118]\ttrain's l2: 0.978921\tvalid's l2: 0.993248\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"###################################\n",
|
|
"# train model\n",
|
|
"###################################\n",
|
|
"data_handler_config = {\n",
|
|
" \"start_time\": \"2008-01-01\",\n",
|
|
" \"end_time\": \"2020-08-01\",\n",
|
|
" \"fit_start_time\": \"2008-01-01\",\n",
|
|
" \"fit_end_time\": \"2014-12-31\",\n",
|
|
" \"instruments\": market,\n",
|
|
"}\n",
|
|
"\n",
|
|
"task = {\n",
|
|
" \"model\": {\n",
|
|
" \"class\": \"LGBModel\",\n",
|
|
" \"module_path\": \"qlib.contrib.model.gbdt\",\n",
|
|
" \"kwargs\": {\n",
|
|
" \"loss\": \"mse\",\n",
|
|
" \"colsample_bytree\": 0.8879,\n",
|
|
" \"learning_rate\": 0.0421,\n",
|
|
" \"subsample\": 0.8789,\n",
|
|
" \"lambda_l1\": 205.6999,\n",
|
|
" \"lambda_l2\": 580.9768,\n",
|
|
" \"max_depth\": 8,\n",
|
|
" \"num_leaves\": 210,\n",
|
|
" \"num_threads\": 20,\n",
|
|
" },\n",
|
|
" },\n",
|
|
" \"dataset\": {\n",
|
|
" \"class\": \"DatasetH\",\n",
|
|
" \"module_path\": \"qlib.data.dataset\",\n",
|
|
" \"kwargs\": {\n",
|
|
" \"handler\": {\n",
|
|
" \"class\": \"Alpha158\",\n",
|
|
" \"module_path\": \"qlib.contrib.data.handler\",\n",
|
|
" \"kwargs\": data_handler_config,\n",
|
|
" },\n",
|
|
" \"segments\": {\n",
|
|
" \"train\": (\"2008-01-01\", \"2014-12-31\"),\n",
|
|
" \"valid\": (\"2015-01-01\", \"2016-12-31\"),\n",
|
|
" \"test\": (\"2017-01-01\", \"2020-08-01\"),\n",
|
|
" },\n",
|
|
" },\n",
|
|
" },\n",
|
|
"}\n",
|
|
"\n",
|
|
"# model initiaiton\n",
|
|
"model = init_instance_by_config(task[\"model\"])\n",
|
|
"dataset = init_instance_by_config(task[\"dataset\"])\n",
|
|
"\n",
|
|
"# start exp to train model\n",
|
|
"with R.start(experiment_name=\"train_model\"):\n",
|
|
" R.log_params(**flatten_dict(task))\n",
|
|
" model.fit(dataset)\n",
|
|
" R.save_objects(trained_model=model)\n",
|
|
" rid = R.get_recorder().id\n"
|
|
]
|
|
},
|
|
{
|
|
"source": [
|
|
"## Optimization Based Strategy"
|
|
],
|
|
"cell_type": "markdown",
|
|
"metadata": {}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from qlib.contrib.strategy.strategy import BaseStrategy\n",
|
|
"\n",
|
|
"\n",
|
|
"class OptBasedStrategy(BaseStrategy):\n",
|
|
" \"\"\"Optimization Based Strategy\"\"\"\n",
|
|
"\n",
|
|
" def __init__(self, data_handler, cov_estimator, optimizer):\n",
|
|
" self.data_handler = data_handler\n",
|
|
" self.cov_estimator = cov_estimator\n",
|
|
" self.optimizer = optimizer\n",
|
|
"\n",
|
|
" def generate_order_list(self, score_series, current, trade_exchange, pred_date, trade_date):\n",
|
|
" \"\"\"\n",
|
|
" Parameters\n",
|
|
" -----------\n",
|
|
" score_series : pd.Seires\n",
|
|
" stock_id , score.\n",
|
|
" current : Position()\n",
|
|
" current of account.\n",
|
|
" trade_exchange : Exchange()\n",
|
|
" exchange.\n",
|
|
" trade_date : pd.Timestamp\n",
|
|
" date.\n",
|
|
" \"\"\"\n",
|
|
" score_series = score_series.dropna()\n",
|
|
"\n",
|
|
" # check stock holdings, if\n",
|
|
" # 1. doesn't have score: target amount = 0 (force sell)\n",
|
|
" # 2. stock not tradable: target amount = current amount\n",
|
|
" current_position = current.get_stock_amount_dict()\n",
|
|
" target_position = {}\n",
|
|
" for stock_id in current_position:\n",
|
|
" if not trade_exchange.is_stock_tradable(stock_id=stock_id, trade_date=trade_date):\n",
|
|
" target_position[stock_id] = current_position[stock_id]\n",
|
|
" elif stock_id not in score_series.index:\n",
|
|
" target_position[stock_id] = 0\n",
|
|
" else:\n",
|
|
" # need to be solved by optimizer\n",
|
|
" pass\n",
|
|
"\n",
|
|
" # filter scores, if\n",
|
|
" # 1. kept in `amount_dict` by previous rules\n",
|
|
" # 2. not tradable\n",
|
|
" skipped = []\n",
|
|
" for stock_id in score_series.index:\n",
|
|
" if stock_id in target_position:\n",
|
|
" skipped.append(stock_id)\n",
|
|
" elif not trade_exchange.is_stock_tradable(stock_id=stock_id, trade_date=trade_date):\n",
|
|
" skipped.append(stock_id)\n",
|
|
" score_series = score_series[~score_series.index.isin(skipped)]\n",
|
|
"\n",
|
|
" # calc remaining value\n",
|
|
" current_value = pd.Series({\n",
|
|
" stock_id: trade_exchange.get_close(stock_id, pred_date) * amount\n",
|
|
" for stock_id, amount in current_position.items()\n",
|
|
" })\n",
|
|
" risk_total_value = self.get_risk_degree(trade_date) * current.calculate_value()\n",
|
|
" traded_value = risk_total_value - current_value.loc[list(target_position)].sum()\n",
|
|
"\n",
|
|
" # portfolio init weight\n",
|
|
" init_weight = current_value.reindex(score_series.index, fill_value=0)\n",
|
|
" init_weight /= init_weight.sum() + 1e-12\n",
|
|
"\n",
|
|
" # covariance estimation\n",
|
|
" selector = (self.data_handler.get_range_selector(pred_date, 252), score_series.index)\n",
|
|
" price = self.data_handler.fetch(selector, level=None, squeeze=True)\n",
|
|
" cov = self.cov_estimator(price)\n",
|
|
" cov = cov.reindex(\n",
|
|
" index=score_series.index, \n",
|
|
" columns=score_series.index, \n",
|
|
" #fill_value=cov.max().max()\n",
|
|
" )\n",
|
|
"\n",
|
|
" # optimize target portfolio\n",
|
|
" target_weight = self.optimizer(cov, score_series, init_weight)\n",
|
|
" for stock_id, weight in target_weight.items():\n",
|
|
" try:\n",
|
|
" target_position[stock_id] = traded_value * weight / trade_exchange.get_close(stock_id, pred_date)\n",
|
|
" except Exception as e:\n",
|
|
" print(e)\n",
|
|
" target_position[stock_id] = 0\n",
|
|
" print(target_weight[target_weight>1e-4])\n",
|
|
"\n",
|
|
" # generate order list\n",
|
|
" order_list = trade_exchange.generate_order_for_target_amount_position(\n",
|
|
" target_position=target_position,\n",
|
|
" current_position=current_position,\n",
|
|
" trade_date=trade_date,\n",
|
|
" )\n",
|
|
"\n",
|
|
" return order_list\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from qlib.data.dataset.loader import QlibDataLoader\n",
|
|
"from qlib.data.dataset.handler import DataHandler\n",
|
|
"from qlib.model.riskmodel import ShrinkCovEstimator\n",
|
|
"from qlib.portfolio.optimizer import PortfolioOptimizer"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"output_type": "stream",
|
|
"name": "stderr",
|
|
"text": [
|
|
"[20768:MainThread](2020-11-27 08:45:28,512) INFO - qlib.timer - [log.py:81] - Time cost: 14.502s | Loading data Done\n",
|
|
"[20768:MainThread](2020-11-27 08:45:28,513) INFO - qlib.timer - [log.py:81] - Time cost: 14.503s | Init data Done\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"data_loader = QlibDataLoader([\"$close\"])\n",
|
|
"data_handler = DataHandler(\"all\", \"2015-01-01\", \"2020-08-01\", data_loader)\n",
|
|
"cov_estimator = ShrinkCovEstimator(nan_option=\"mask\")\n",
|
|
"optimizer = PortfolioOptimizer(\"mvo\", lamb=1.0, delta=0.2)\n",
|
|
"strategy = OptBasedStrategy(data_handler, cov_estimator, optimizer)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"output_type": "stream",
|
|
"name": "stderr",
|
|
"text": [
|
|
"[20768:MainThread](2020-11-27 08:45:28,543) INFO - qlib.workflow - [exp.py:180] - Experiment 2 starts running ...\n",
|
|
"[20768:MainThread](2020-11-27 08:45:28,581) INFO - qlib.workflow - [recorder.py:234] - Recorder d9bd45391cf5431bb339531baf5fb6f2 starts running under Experiment 2 ...\n",
|
|
"[20768:MainThread](2020-11-27 08:45:28,582) INFO - qlib.workflow - [expm.py:251] - No tracking URI is provided. The default tracking URI is set as `mlruns` under the working directory.\n",
|
|
"[20768:MainThread](2020-11-27 08:45:29,433) INFO - qlib.workflow - [record_temp.py:127] - Signal record 'pred.pkl' has been saved as the artifact of the Experiment 2\n",
|
|
"[20768:MainThread](2020-11-27 08:45:29,525) INFO - qlib.Evaluate - [evaluate.py:161] - Create new exchange\n",
|
|
"'The following are prediction results of the LGBModel model.'\n",
|
|
" score\n",
|
|
"datetime instrument \n",
|
|
"2017-01-03 SH600000 -0.033506\n",
|
|
" SH600008 0.002120\n",
|
|
" SH600009 0.032941\n",
|
|
" SH600010 -0.012371\n",
|
|
" SH600015 -0.140312\n",
|
|
"C:\\Users\\v-donzh\\AppData\\Local\\Continuum\\miniconda3\\envs\\qlib\\lib\\site-packages\\ipykernel_launcher.py:55: DeprecationWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.\n",
|
|
"instrument\n",
|
|
"SH600000 2.868027e-12\n",
|
|
"SH600008 1.341080e-12\n",
|
|
"SH600009 5.131225e-12\n",
|
|
"SH600010 3.890177e-12\n",
|
|
"SH600015 1.781055e-11\n",
|
|
" ... \n",
|
|
"SZ300146 2.841964e-12\n",
|
|
"SZ300168 4.603490e-12\n",
|
|
"SZ300182 9.855511e-12\n",
|
|
"SZ300251 1.495177e-12\n",
|
|
"SZ300315 4.054219e-12\n",
|
|
"Length: 290, dtype: float64\n",
|
|
"instrument\n",
|
|
"SH600000 5.253178e-12\n",
|
|
"SH600008 1.901077e-14\n",
|
|
"SH600009 5.573006e-12\n",
|
|
"SH600010 6.129089e-14\n",
|
|
"SH600015 7.236246e-14\n",
|
|
" ... \n",
|
|
"SZ300146 4.604396e-12\n",
|
|
"SZ300168 4.705359e-12\n",
|
|
"SZ300182 6.358140e-14\n",
|
|
"SZ300251 5.347927e-12\n",
|
|
"SZ300315 1.288077e-13\n",
|
|
"Length: 289, dtype: float64\n",
|
|
"instrument\n",
|
|
"SH600000 1.181534e-14\n",
|
|
"SH600008 3.480454e-14\n",
|
|
"SH600009 1.902741e-13\n",
|
|
"SH600010 8.388080e-12\n",
|
|
"SH600015 1.490974e-13\n",
|
|
" ... \n",
|
|
"SZ300146 9.838926e-13\n",
|
|
"SZ300168 1.790169e-11\n",
|
|
"SZ300182 1.002664e-11\n",
|
|
"SZ300251 2.097283e-12\n",
|
|
"SZ300315 1.180997e-11\n",
|
|
"Length: 288, dtype: float64\n",
|
|
"instrument\n",
|
|
"SH600000 4.027211e-14\n",
|
|
"SH600008 1.067081e-14\n",
|
|
"SH600009 1.010989e-13\n",
|
|
"SH600010 1.605190e-12\n",
|
|
"SH600015 6.075465e-14\n",
|
|
" ... \n",
|
|
"SZ300146 7.338274e-12\n",
|
|
"SZ300168 1.990990e-11\n",
|
|
"SZ300182 4.891503e-12\n",
|
|
"SZ300251 1.067670e-11\n",
|
|
"SZ300315 1.009767e-11\n",
|
|
"Length: 288, dtype: float64\n",
|
|
"instrument\n",
|
|
"SH600000 2.518140e-12\n",
|
|
"SH600008 5.504712e-13\n",
|
|
"SH600009 3.185232e-12\n",
|
|
"SH600010 3.641971e-13\n",
|
|
"SH600015 1.902283e-14\n",
|
|
" ... \n",
|
|
"SZ300146 5.427494e-14\n",
|
|
"SZ300168 7.620411e-13\n",
|
|
"SZ300182 2.484372e-14\n",
|
|
"SZ300251 5.261806e-13\n",
|
|
"SZ300315 1.412130e-13\n",
|
|
"Length: 288, dtype: float64\n",
|
|
"('SH600666', Timestamp('2017-01-10 00:00:00'))\n",
|
|
"instrument\n",
|
|
"SH600000 7.466386e-12\n",
|
|
"SH600008 1.348026e-15\n",
|
|
"SH600009 1.111042e-11\n",
|
|
"SH600010 6.740600e-14\n",
|
|
"SH600015 1.049665e-11\n",
|
|
" ... \n",
|
|
"SZ300146 6.842294e-14\n",
|
|
"SZ300168 1.750970e-13\n",
|
|
"SZ300182 6.916267e-14\n",
|
|
"SZ300251 9.068748e-14\n",
|
|
"SZ300315 1.193522e-13\n",
|
|
"Length: 289, dtype: float64\n"
|
|
]
|
|
},
|
|
{
|
|
"output_type": "error",
|
|
"ename": "ValueError",
|
|
"evalue": "only have -0.104491644538939 SZ002475, require 1448416.2584415162",
|
|
"traceback": [
|
|
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
|
|
"\u001b[1;32m<ipython-input-16-2e7986244749>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 30\u001b[0m \u001b[1;31m# backtest & analysis\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 31\u001b[0m \u001b[0mpar\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mPortAnaRecord\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrecorder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mport_analysis_config\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 32\u001b[1;33m \u001b[0mpar\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgenerate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
|
|
"\u001b[1;32md:\\qlib\\qlib\\workflow\\record_temp.py\u001b[0m in \u001b[0;36mgenerate\u001b[1;34m(self, **kwargs)\u001b[0m\n\u001b[0;32m 230\u001b[0m \u001b[1;31m# custom strategy and get backtest\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 231\u001b[0m \u001b[0mpred_score\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mload\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 232\u001b[1;33m \u001b[0mreport_normal\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpositions_normal\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnormal_backtest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpred_score\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstrategy\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstrategy\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbacktest_config\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 233\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrecorder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msave_objects\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m**\u001b[0m\u001b[1;33m{\u001b[0m\u001b[1;34m\"report_normal.pkl\"\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mreport_normal\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0martifact_path\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mPortAnaRecord\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_path\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 234\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrecorder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msave_objects\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m**\u001b[0m\u001b[1;33m{\u001b[0m\u001b[1;34m\"positions_normal.pkl\"\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mpositions_normal\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0martifact_path\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mPortAnaRecord\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_path\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\evaluate.py\u001b[0m in \u001b[0;36mbacktest\u001b[1;34m(pred, account, shift, benchmark, verbose, **kwargs)\u001b[0m\n\u001b[0;32m 269\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mverbose\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 270\u001b[0m \u001b[0maccount\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0maccount\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 271\u001b[1;33m \u001b[0mbenchmark\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mbenchmark\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 272\u001b[0m )\n\u001b[0;32m 273\u001b[0m \u001b[1;31m# for compatibility of the old API. return the dict positions\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\backtest\\backtest.py\u001b[0m in \u001b[0;36mbacktest\u001b[1;34m(pred, strategy, trade_exchange, shift, verbose, account, benchmark)\u001b[0m\n\u001b[0;32m 107\u001b[0m \u001b[1;31m# NOTE: The following operation will modify order.amount.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 108\u001b[0m \u001b[1;31m# NOTE: If it is buy and the cash is insufficient, the tradable amount will be recalculated\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 109\u001b[1;33m \u001b[0mtrade_info\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mexecutor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtrade_account\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0morder_list\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_date\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 110\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 111\u001b[0m \u001b[1;31m# 5. Update account information according to transaction\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\online\\executor.py\u001b[0m in \u001b[0;36mexecute\u001b[1;34m(self, trade_account, order_list, trade_date)\u001b[0m\n\u001b[0;32m 145\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrade_exchange\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcheck_order\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mTrue\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 146\u001b[0m \u001b[1;31m# execute the order\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 147\u001b[1;33m \u001b[0mtrade_val\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_cost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_price\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrade_exchange\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdeal_order\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_account\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0maccount\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 148\u001b[0m \u001b[0mtrade_info\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_val\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_cost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_price\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 149\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mverbose\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\backtest\\exchange.py\u001b[0m in \u001b[0;36mdeal_order\u001b[1;34m(self, order, trade_account, position)\u001b[0m\n\u001b[0;32m 209\u001b[0m \u001b[1;31m# Otherwise, it will result some stock with 0 amount in the position\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 210\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mtrade_account\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 211\u001b[1;33m \u001b[0mtrade_account\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mupdate_order\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_val\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrade_val\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcost\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrade_cost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_price\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrade_price\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 212\u001b[0m \u001b[1;32melif\u001b[0m \u001b[0mposition\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 213\u001b[0m \u001b[0mposition\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mupdate_order\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_val\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrade_val\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcost\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrade_cost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_price\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrade_price\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\backtest\\account.py\u001b[0m in \u001b[0;36mupdate_order\u001b[1;34m(self, order, trade_val, cost, trade_price)\u001b[0m\n\u001b[0;32m 77\u001b[0m \u001b[1;31m# update current position\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 78\u001b[0m \u001b[1;31m# for may sell all of stock_id\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 79\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcurrent\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mupdate_order\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_val\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_price\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 80\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 81\u001b[0m \u001b[1;31m# buy stock\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\backtest\\position.py\u001b[0m in \u001b[0;36mupdate_order\u001b[1;34m(self, order, trade_val, cost, trade_price)\u001b[0m\n\u001b[0;32m 81\u001b[0m \u001b[1;32melif\u001b[0m \u001b[0morder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdirection\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mOrder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mSELL\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 82\u001b[0m \u001b[1;31m# SELL\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 83\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msell_stock\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstock_id\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_val\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_price\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 84\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 85\u001b[0m \u001b[1;32mraise\u001b[0m \u001b[0mNotImplementedError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"do not suppotr order direction {}\"\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdirection\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;32md:\\qlib\\qlib\\contrib\\backtest\\position.py\u001b[0m in \u001b[0;36msell_stock\u001b[1;34m(self, stock_id, trade_val, cost, trade_price)\u001b[0m\n\u001b[0;32m 64\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mposition\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mstock_id\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"amount\"\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1e-5\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 65\u001b[0m raise ValueError(\n\u001b[1;32m---> 66\u001b[1;33m \u001b[1;34m\"only have {} {}, require {}\"\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mposition\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mstock_id\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"amount\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstock_id\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrade_amount\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 67\u001b[0m )\n\u001b[0;32m 68\u001b[0m \u001b[1;32melif\u001b[0m \u001b[0mabs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mposition\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mstock_id\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"amount\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m<=\u001b[0m \u001b[1;36m1e-5\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
|
"\u001b[1;31mValueError\u001b[0m: only have -0.104491644538939 SZ002475, require 1448416.2584415162"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"###################################\n",
|
|
"# prediction, backtest & analysis\n",
|
|
"###################################\n",
|
|
"port_analysis_config = {\n",
|
|
" \"strategy\": strategy,\n",
|
|
" \"backtest\": {\n",
|
|
" \"verbose\": False,\n",
|
|
" \"limit_threshold\": 0.095,\n",
|
|
" \"account\": 100000000,\n",
|
|
" \"benchmark\": benchmark,\n",
|
|
" \"deal_price\": \"close\",\n",
|
|
" \"open_cost\": 0.0005,\n",
|
|
" \"close_cost\": 0.0015,\n",
|
|
" \"min_cost\": 5,\n",
|
|
" },\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"# backtest and analysis\n",
|
|
"with R.start(experiment_name=\"backtest_analysis\"):\n",
|
|
" recorder = R.get_recorder(rid, experiment_name=\"train_model\")\n",
|
|
" model = recorder.load_object(\"trained_model\")\n",
|
|
"\n",
|
|
" # prediction\n",
|
|
" recorder = R.get_recorder()\n",
|
|
" ba_rid = recorder.id\n",
|
|
" sr = SignalRecord(model, dataset, recorder)\n",
|
|
" sr.generate()\n",
|
|
"\n",
|
|
" # backtest & analysis\n",
|
|
" par = PortAnaRecord(recorder, port_analysis_config)\n",
|
|
" par.generate()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
]
|
|
} |