From a64a112b460043852ebfbc264e0f85fc92147248 Mon Sep 17 00:00:00 2001 From: Guofu Li Date: Mon, 31 Oct 2022 10:58:03 +0800 Subject: [PATCH] Updates --- .gitignore | 1 + ipynb/ddb.ipynb | 1391 +++++++++- ipynb/ddb_daily_factor.ipynb | 3141 ++++++++++++++++++++++ ipynb/ddb_index.ipynb | 4208 ++++++++++++++++++++++++++++++ ipynb/mssql.ipynb | 108 +- ipynb/未命名.ipynb | 173 ++ src/loader/DDBDailyLoader.py | 152 +- src/loader/DDBEntityLoader.py | 12 + src/loader/DDBIndexLoader.py | 286 ++ src/loader/DDBIndexLoaderWind.py | 52 + src/run.py | 21 +- 11 files changed, 9456 insertions(+), 89 deletions(-) create mode 100644 ipynb/ddb_daily_factor.ipynb create mode 100644 ipynb/ddb_index.ipynb create mode 100644 ipynb/未命名.ipynb create mode 100644 src/loader/DDBEntityLoader.py create mode 100644 src/loader/DDBIndexLoader.py create mode 100644 src/loader/DDBIndexLoaderWind.py diff --git a/.gitignore b/.gitignore index f29e05e..8376bf1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .DS_Store *.DS_Store + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/ipynb/ddb.ipynb b/ipynb/ddb.ipynb index f839689..c983338 100644 --- a/ipynb/ddb.ipynb +++ b/ipynb/ddb.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "id": "7246e0c8-61cd-4cbf-a978-aa0dc0172d6d", "metadata": {}, "outputs": [], @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "id": "5d0f471e-682e-43cc-abdb-7e52f3bbd707", "metadata": {}, "outputs": [], @@ -93,40 +93,33 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 127, "id": "45c4cbc3-08a1-4083-8117-44e8e3364375", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Failed to connect to host = localhost port = 8848 with error code 111\n" - ] - }, - { - "ename": "RuntimeError", - "evalue": " in login: Couldn't send script/function to the remote host because the connection has been closed", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [2]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mdolphindb\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mddb\u001b[39;00m\n\u001b[1;32m 2\u001b[0m sess \u001b[38;5;241m=\u001b[39m ddb\u001b[38;5;241m.\u001b[39msession(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mlocalhost\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;241m8848\u001b[39m)\n\u001b[0;32m----> 3\u001b[0m \u001b[43msess\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlogin\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43madmin\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m123456\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;66;03m# backup(backup_path, sql_obj, force, parallel)\u001b[39;00m\n\u001b[1;32m 6\u001b[0m sess\u001b[38;5;241m.\u001b[39mrun(\u001b[38;5;124m\"\"\"\u001b[39m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;124m backup(\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/data/dolphindb/backup/\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m, , false, false);\u001b[39m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;124m backup(\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/data/dolphindb/backup/\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m, , false, false);\n", + " // backup('/data/dolphindb/backup/', , false, false);\n", + " //backup('/data/dolphindb/backup/', , false, false);\n", - " backup('/data/dolphindb/backup/', , false, false);\n", "\"\"\")" ] }, @@ -158,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 128, "id": "84f99b12-e868-425e-bcd3-1733feea7524", "metadata": {}, "outputs": [ @@ -193,7 +186,7 @@ " \n", " 0\n", " dfs://daily_stock_ts\n", - " idx_daily_concept\n", + " hft_daily_factor\n", " True\n", " \n", " \n", @@ -202,28 +195,29 @@ "" ], "text/plain": [ - " dbName tableName success errorMsg\n", - "0 dfs://daily_stock_ts idx_daily_concept True " + " dbName tableName success errorMsg\n", + "0 dfs://daily_stock_ts hft_daily_factor True " ] }, - "execution_count": 7, + "execution_count": 128, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "#sess = ddb.session('192.168.1.7', 8848)\n", "sess = ddb.session('localhost', 8848)\n", "sess.login('admin', '123456')\n", "\n", "sess.run(\"\"\"\n", - " dropTable(database(\"dfs://daily_stock_ts\"), \"idx_daily_concept\");\n", - " migrate('/data/dolphindb/backup/', \"dfs://daily_stock_ts\", \"idx_daily_concept\");\n", + " //dropTable(database(\"dfs://daily_stock_ts\"), \"hft_daily_factor\");\n", + " migrate('/data/dolphindb/backup/', \"dfs://daily_stock_ts\", \"hft_daily_factor\");\n", "\"\"\")" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 5, "id": "8b7dae3d-aef1-4c50-92b2-460d4fea0a96", "metadata": {}, "outputs": [ @@ -255,16 +249,26 @@ " \n", " \n", " 0\n", + " daily_factor\n", + " 1ffH\n", + " \n", + " \n", + " 1\n", + " idx_daily_kline\n", + " 1eZs\n", + " \n", + " \n", + " 2\n", " idx_daily_concept\n", " 1esb\n", " \n", " \n", - " 1\n", + " 3\n", " hft_daily_factor\n", - " u6J\n", + " 1eYB\n", " \n", " \n", - " 2\n", + " 4\n", " daily_kline\n", " uoH\n", " \n", @@ -274,32 +278,49 @@ ], "text/plain": [ " tableName physicalIndex\n", - "0 idx_daily_concept 1esb\n", - "1 hft_daily_factor u6J\n", - "2 daily_kline uoH" + "0 daily_factor 1ffH\n", + "1 idx_daily_kline 1eZs\n", + "2 idx_daily_concept 1esb\n", + "3 hft_daily_factor 1eYB\n", + "4 daily_kline uoH" ] }, - "execution_count": 13, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "#sess = ddb.session('192.168.1.7', 8848)\n", "sess = ddb.session('localhost', 8848)\n", "sess.login('admin', '123456')\n", "\n", "sess.run(\"\"\"\n", " //getAllDBs()\n", " //listTables(\"dfs://info_stock_ts\");\n", - " //listTables(\"dfs://hft_stock_ts\");\n", " listTables(\"dfs://daily_stock_ts\");\n", - " //schema(loadTable(\"dfs://daily_stock_ts\", \"idx_daily_concept\"))\n", + " //listTables(\"dfs://pit_stock_ts\");\n", + " //schema(loadTable(\"dfs://daily_stock_ts\", \"hft_daily_factor\"))\n", + " //dropTable(database(\"dfs://daily_stock_ts\"), \"idx_daily_kline\")\n", + " //schema(loadTable(\"dfs://pit_stock_ts\", \"earnings_preannouncement\"))\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03c3d7d2-1953-48a4-bf6e-fac3807c0d9c", + "metadata": {}, + "outputs": [], + "source": [ + "sess.run(\"\"\"\n", + " schema(loadTable(\"dfs://pit_stock_ts\", ))\n", "\"\"\")" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 153, "id": "fb23b78d-c402-4c11-9504-c61793e5a2a3", "metadata": {}, "outputs": [ @@ -339,20 +360,56 @@ " 'partitionSites': None}" ] }, - "execution_count": 14, + "execution_count": 153, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('192.168.1.7', 8848)\n", + "sess.login('admin', '123456')\n", + "\n", "sess.run(\"\"\"\n", " schema(loadTable(\"dfs://daily_stock_ts\", \"daily_kline\"))\n", - "\"\"\")" + "\"\"\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "0a52b3b0-8095-46d7-97e9-f47b56168faf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['code', 'm_nDate']" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df['name'].to_list()[:2]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "f117c6c9-9b7a-4196-b721-8afaa5f3b3d7", + "metadata": {}, + "outputs": [], + "source": [ + "df[2:].to_csv(\"../assets/idx_concept_list.csv\")" ] }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 41, "id": "84e9e3df-aec7-4edf-96fc-2481ed6790b5", "metadata": {}, "outputs": [ @@ -388,19 +445,22 @@ " 0\n", " dfs://daily_stock_ts\n", " idx_daily_concept\n", - " True\n", - " \n", + " False\n", + " table named idx_daily_concept already existed ...\n", " \n", " \n", "\n", "" ], "text/plain": [ - " dbName tableName success errorMsg\n", - "0 dfs://daily_stock_ts idx_daily_concept True " + " dbName tableName success \\\n", + "0 dfs://daily_stock_ts idx_daily_concept False \n", + "\n", + " errorMsg \n", + "0 table named idx_daily_concept already existed ... " ] }, - "execution_count": 84, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -415,20 +475,220 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 157, "id": "58ac1e6f-51cd-4d35-a34f-8220fca52acb", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codereport_periodappear_at_dateS_PROFITNOTICE_STYLES_PROFITNOTICE_CHANGEMINS_PROFITNOTICE_CHANGEMAXS_PROFITNOTICE_NETPROFITMINS_PROFITNOTICE_NETPROFITMAXS_PROFITNOTICE_REASON
0600000.SH2002-12-312002-08-17预增10.0001.000000e+010.000000e+000.000000e+00nan
1600000.SH2004-12-312005-01-08预增23.2372.323700e+011.930000e+091.930000e+09nan
2600000.SH2007-06-302007-07-20预增50.0001.000000e+080.000000e+000.000000e+00nan
3600000.SH2008-03-312008-04-14预增180.0001.000000e+080.000000e+000.000000e+00nan
4600000.SH2008-06-302008-04-26预警0.0000.000000e+000.000000e+000.000000e+00公司资产规模增长.利差提高.非利息收入增长.有效所得税率降低.资产质量持续优化.拨备计提减少等。
5600000.SH2008-06-302008-07-04预增140.0001.000000e+080.000000e+000.000000e+00nan
6600000.SH2008-09-302008-08-23预增0.0000.000000e+000.000000e+000.000000e+00nan
7600000.SH2008-09-302008-10-14预增150.0001.500000e+020.000000e+000.000000e+00公司2008年一至三季度同比资产规模增长,资产质量稳定使风险成本下降,利差扩大,非利息收入增...
8600000.SH2008-12-312008-10-30预警0.0000.000000e+000.000000e+000.000000e+00实施新税法,有效所得税率降低;公司资产规模进一步扩大,利息收入增加;非利息收入持续增长;资产...
\n", + "
" + ], + "text/plain": [ + " code report_period appear_at_date S_PROFITNOTICE_STYLE \\\n", + "0 600000.SH 2002-12-31 2002-08-17 预增 \n", + "1 600000.SH 2004-12-31 2005-01-08 预增 \n", + "2 600000.SH 2007-06-30 2007-07-20 预增 \n", + "3 600000.SH 2008-03-31 2008-04-14 预增 \n", + "4 600000.SH 2008-06-30 2008-04-26 预警 \n", + "5 600000.SH 2008-06-30 2008-07-04 预增 \n", + "6 600000.SH 2008-09-30 2008-08-23 预增 \n", + "7 600000.SH 2008-09-30 2008-10-14 预增 \n", + "8 600000.SH 2008-12-31 2008-10-30 预警 \n", + "\n", + " S_PROFITNOTICE_CHANGEMIN S_PROFITNOTICE_CHANGEMAX \\\n", + "0 10.000 1.000000e+01 \n", + "1 23.237 2.323700e+01 \n", + "2 50.000 1.000000e+08 \n", + "3 180.000 1.000000e+08 \n", + "4 0.000 0.000000e+00 \n", + "5 140.000 1.000000e+08 \n", + "6 0.000 0.000000e+00 \n", + "7 150.000 1.500000e+02 \n", + "8 0.000 0.000000e+00 \n", + "\n", + " S_PROFITNOTICE_NETPROFITMIN S_PROFITNOTICE_NETPROFITMAX \\\n", + "0 0.000000e+00 0.000000e+00 \n", + "1 1.930000e+09 1.930000e+09 \n", + "2 0.000000e+00 0.000000e+00 \n", + "3 0.000000e+00 0.000000e+00 \n", + "4 0.000000e+00 0.000000e+00 \n", + "5 0.000000e+00 0.000000e+00 \n", + "6 0.000000e+00 0.000000e+00 \n", + "7 0.000000e+00 0.000000e+00 \n", + "8 0.000000e+00 0.000000e+00 \n", + "\n", + " S_PROFITNOTICE_REASON \n", + "0 nan \n", + "1 nan \n", + "2 nan \n", + "3 nan \n", + "4 公司资产规模增长.利差提高.非利息收入增长.有效所得税率降低.资产质量持续优化.拨备计提减少等。 \n", + "5 nan \n", + "6 nan \n", + "7 公司2008年一至三季度同比资产规模增长,资产质量稳定使风险成本下降,利差扩大,非利息收入增... \n", + "8 实施新税法,有效所得税率降低;公司资产规模进一步扩大,利息收入增加;非利息收入持续增长;资产... " + ] + }, + "execution_count": 157, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')\n", "sess.run(\"\"\"\n", - " \n", + " // select * from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\") where code='600000.SH' and m_nDate=2020.01.02\n", + " //select min(appear_at_date), max(appear_at_date) from loadTable(\"dfs://pit_stock_ts\", \"earnings_preannouncement\") \n", + " select * from loadTable(\"dfs://pit_stock_ts\", \"earnings_preannouncement\") where code=\"600000.SH\"\n", "\"\"\")" ] }, { "cell_type": "code", - "execution_count": 16, - "id": "3411a78a-4efc-4693-af3f-44abe6ba166e", + "execution_count": 158, + "id": "a9d1396f-a7e8-4c83-a983-2d48ef894362", "metadata": {}, "outputs": [ { @@ -452,30 +712,1041 @@ " \n", " \n", " \n", - " min_m_nDate\n", + " S_PROFITNOTICE_STYLE\n", " \n", " \n", " \n", " \n", " 0\n", - " 2006-01-04\n", + " 减亏\n", + " \n", + " \n", + " 1\n", + " 增亏\n", + " \n", + " \n", + " 2\n", + " 预亏\n", + " \n", + " \n", + " 3\n", + " 预减\n", + " \n", + " \n", + " 4\n", + " 预增\n", + " \n", + " \n", + " 5\n", + " 预平\n", + " \n", + " \n", + " 6\n", + " 预盈\n", + " \n", + " \n", + " 7\n", + " 预警\n", " \n", " \n", "\n", "" ], "text/plain": [ - " min_m_nDate\n", - "0 2006-01-04" + " S_PROFITNOTICE_STYLE\n", + "0 减亏\n", + "1 增亏\n", + "2 预亏\n", + "3 预减\n", + "4 预增\n", + "5 预平\n", + "6 预盈\n", + "7 预警" + ] + }, + "execution_count": 158, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select S_PROFITNOTICE_STYLE from loadTable(\"dfs://pit_stock_ts\", \"earnings_preannouncement\") group by S_PROFITNOTICE_STYLE\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "id": "5e665dca-835e-4fda-9509-fc79498efe76", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codereport_periodappear_at_dateEQY_RECORD_DTEX_DTDVD_PAYOUT_DTS_DIV_PRELANDATES_DIV_SMTGDATEDVD_ANN_DTS_DIV_BASESHARES_DIV_BONUSRATES_DIV_CONVERSEDRATEMEMOS_DIV_PREANNDT
0600000.SH2001-12-312002-03-212002-08-212002-08-222002-08-272002-03-212002-06-292002-08-170.000000e+000.50.5nanNaT
1600000.SH2002-12-312003-03-292003-06-202003-06-232003-06-272003-03-292003-04-302003-06-170.000000e+000.00.0nanNaT
2600000.SH2003-12-312004-02-272004-05-192004-05-202004-05-252004-02-272004-03-312004-05-150.000000e+000.00.0nanNaT
3600000.SH2004-12-312005-02-262005-05-112005-05-122005-05-162005-02-262005-04-272005-04-303.915000e+090.00.0nanNaT
4600000.SH2005-12-312006-03-022006-05-242006-05-252006-05-292006-03-022006-04-062006-05-193.915000e+090.00.0nanNaT
5600000.SH2006-12-312007-03-242007-07-172007-07-182007-07-202007-03-242007-05-222007-07-134.354883e+090.00.0nanNaT
6600000.SH2007-12-312008-02-282008-04-232008-04-242008-04-292008-02-282008-03-202008-04-184.354883e+090.30.0nanNaT
7600000.SH2008-12-312009-04-102009-06-082009-06-092009-06-162009-04-102009-05-052009-06-035.661348e+090.40.0nanNaT
8600000.SH2009-12-312010-04-072010-06-092010-06-102010-06-182010-04-072010-04-282010-06-048.830046e+090.30.0nanNaT
9600000.SH2010-12-312011-03-302011-06-022011-06-032011-06-132011-03-302011-04-282011-05-301.434882e+100.30.0nanNaT
10600000.SH2011-12-312012-03-162012-06-252012-06-262012-06-292012-03-162012-06-132012-06-191.865347e+100.00.0nanNaT
11600000.SH2012-12-312013-03-142013-05-312013-06-032013-06-072013-03-142013-05-162013-05-271.865347e+100.00.0nanNaT
12600000.SH2013-12-312014-03-202014-06-232014-06-242014-06-242014-03-202014-05-262014-06-171.865347e+100.00.0nanNaT
13600000.SH2014-12-312015-03-192015-06-192015-06-232015-06-232015-03-192015-05-152015-06-161.865347e+100.00.0nanNaT
14600000.SH2015-12-312016-04-072016-06-222016-06-232016-06-232016-04-072016-04-282016-06-161.965298e+100.10.1nanNaT
15600000.SH2016-12-312017-04-012017-05-242017-05-252017-05-252017-04-012017-04-252017-05-192.161828e+100.30.3nanNaT
16600000.SH2017-12-312018-04-282018-07-122018-07-132018-07-132018-04-282018-05-282018-07-062.935208e+100.00.0nanNaT
17600000.SH2018-12-312019-03-262019-06-102019-06-112019-06-112019-03-262019-04-242019-06-042.935208e+100.00.0nanNaT
18600000.SH2019-12-312020-04-252020-07-222020-07-232020-07-232020-04-252020-06-192020-07-162.935212e+100.00.0nanNaT
19600000.SH2020-12-312021-03-272021-07-202021-07-212021-07-212021-03-272021-06-112021-07-132.935216e+100.00.0nanNaT
20600000.SH2021-12-312022-04-28NaTNaTNaT2022-04-28NaTNaT2.935217e+100.00.0nanNaT
\n", + "
" + ], + "text/plain": [ + " code report_period appear_at_date EQY_RECORD_DT EX_DT \\\n", + "0 600000.SH 2001-12-31 2002-03-21 2002-08-21 2002-08-22 \n", + "1 600000.SH 2002-12-31 2003-03-29 2003-06-20 2003-06-23 \n", + "2 600000.SH 2003-12-31 2004-02-27 2004-05-19 2004-05-20 \n", + "3 600000.SH 2004-12-31 2005-02-26 2005-05-11 2005-05-12 \n", + "4 600000.SH 2005-12-31 2006-03-02 2006-05-24 2006-05-25 \n", + "5 600000.SH 2006-12-31 2007-03-24 2007-07-17 2007-07-18 \n", + "6 600000.SH 2007-12-31 2008-02-28 2008-04-23 2008-04-24 \n", + "7 600000.SH 2008-12-31 2009-04-10 2009-06-08 2009-06-09 \n", + "8 600000.SH 2009-12-31 2010-04-07 2010-06-09 2010-06-10 \n", + "9 600000.SH 2010-12-31 2011-03-30 2011-06-02 2011-06-03 \n", + "10 600000.SH 2011-12-31 2012-03-16 2012-06-25 2012-06-26 \n", + "11 600000.SH 2012-12-31 2013-03-14 2013-05-31 2013-06-03 \n", + "12 600000.SH 2013-12-31 2014-03-20 2014-06-23 2014-06-24 \n", + "13 600000.SH 2014-12-31 2015-03-19 2015-06-19 2015-06-23 \n", + "14 600000.SH 2015-12-31 2016-04-07 2016-06-22 2016-06-23 \n", + "15 600000.SH 2016-12-31 2017-04-01 2017-05-24 2017-05-25 \n", + "16 600000.SH 2017-12-31 2018-04-28 2018-07-12 2018-07-13 \n", + "17 600000.SH 2018-12-31 2019-03-26 2019-06-10 2019-06-11 \n", + "18 600000.SH 2019-12-31 2020-04-25 2020-07-22 2020-07-23 \n", + "19 600000.SH 2020-12-31 2021-03-27 2021-07-20 2021-07-21 \n", + "20 600000.SH 2021-12-31 2022-04-28 NaT NaT \n", + "\n", + " DVD_PAYOUT_DT S_DIV_PRELANDATE S_DIV_SMTGDATE DVD_ANN_DT S_DIV_BASESHARE \\\n", + "0 2002-08-27 2002-03-21 2002-06-29 2002-08-17 0.000000e+00 \n", + "1 2003-06-27 2003-03-29 2003-04-30 2003-06-17 0.000000e+00 \n", + "2 2004-05-25 2004-02-27 2004-03-31 2004-05-15 0.000000e+00 \n", + "3 2005-05-16 2005-02-26 2005-04-27 2005-04-30 3.915000e+09 \n", + "4 2006-05-29 2006-03-02 2006-04-06 2006-05-19 3.915000e+09 \n", + "5 2007-07-20 2007-03-24 2007-05-22 2007-07-13 4.354883e+09 \n", + "6 2008-04-29 2008-02-28 2008-03-20 2008-04-18 4.354883e+09 \n", + "7 2009-06-16 2009-04-10 2009-05-05 2009-06-03 5.661348e+09 \n", + "8 2010-06-18 2010-04-07 2010-04-28 2010-06-04 8.830046e+09 \n", + "9 2011-06-13 2011-03-30 2011-04-28 2011-05-30 1.434882e+10 \n", + "10 2012-06-29 2012-03-16 2012-06-13 2012-06-19 1.865347e+10 \n", + "11 2013-06-07 2013-03-14 2013-05-16 2013-05-27 1.865347e+10 \n", + "12 2014-06-24 2014-03-20 2014-05-26 2014-06-17 1.865347e+10 \n", + "13 2015-06-23 2015-03-19 2015-05-15 2015-06-16 1.865347e+10 \n", + "14 2016-06-23 2016-04-07 2016-04-28 2016-06-16 1.965298e+10 \n", + "15 2017-05-25 2017-04-01 2017-04-25 2017-05-19 2.161828e+10 \n", + "16 2018-07-13 2018-04-28 2018-05-28 2018-07-06 2.935208e+10 \n", + "17 2019-06-11 2019-03-26 2019-04-24 2019-06-04 2.935208e+10 \n", + "18 2020-07-23 2020-04-25 2020-06-19 2020-07-16 2.935212e+10 \n", + "19 2021-07-21 2021-03-27 2021-06-11 2021-07-13 2.935216e+10 \n", + "20 NaT 2022-04-28 NaT NaT 2.935217e+10 \n", + "\n", + " S_DIV_BONUSRATE S_DIV_CONVERSEDRATE MEMO S_DIV_PREANNDT \n", + "0 0.5 0.5 nan NaT \n", + "1 0.0 0.0 nan NaT \n", + "2 0.0 0.0 nan NaT \n", + "3 0.0 0.0 nan NaT \n", + "4 0.0 0.0 nan NaT \n", + "5 0.0 0.0 nan NaT \n", + "6 0.3 0.0 nan NaT \n", + "7 0.4 0.0 nan NaT \n", + "8 0.3 0.0 nan NaT \n", + "9 0.3 0.0 nan NaT \n", + "10 0.0 0.0 nan NaT \n", + "11 0.0 0.0 nan NaT \n", + "12 0.0 0.0 nan NaT \n", + "13 0.0 0.0 nan NaT \n", + "14 0.1 0.1 nan NaT \n", + "15 0.3 0.3 nan NaT \n", + "16 0.0 0.0 nan NaT \n", + "17 0.0 0.0 nan NaT \n", + "18 0.0 0.0 nan NaT \n", + "19 0.0 0.0 nan NaT \n", + "20 0.0 0.0 nan NaT " + ] + }, + "execution_count": 156, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')\n", + "sess.run(\"\"\"\n", + " select top 100 * from loadTable(\"dfs://pit_stock_ts\", \"divident\") where code=\"600000.SH\"\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "f67794f5-ffc2-42fb-8dd8-faed6ecfad02", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codecount
0000106.SH3080
1000844.SH2350
2000919.SH3080
3399210.SZ765
4399300.SZ3080
.........
980857244.SW3079
981857421.SW3080
982859512.SW3079
983859852.SW3080
984I899001.CS1862
\n", + "

985 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " code count\n", + "0 000106.SH 3080\n", + "1 000844.SH 2350\n", + "2 000919.SH 3080\n", + "3 399210.SZ 765\n", + "4 399300.SZ 3080\n", + ".. ... ...\n", + "980 857244.SW 3079\n", + "981 857421.SW 3080\n", + "982 859512.SW 3079\n", + "983 859852.SW 3080\n", + "984 I899001.CS 1862\n", + "\n", + "[985 rows x 2 columns]" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select code, count(*) from loadTable(\"dfs://daily_stock_ts\", \"idx_daily_kline\") group by code\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "3411a78a-4efc-4693-af3f-44abe6ba166e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
m_nDatecodecloseyclosePctChgfactor
02020-09-11600519.SH1733.001705.801.5945603.334994
12020-09-14600519.SH1766.001733.001.9042123.334994
22020-09-15600519.SH1760.001766.00-0.3397513.334994
32020-09-16600519.SH1725.101760.00-1.9829553.334994
42020-09-17600519.SH1670.521725.10-3.1638753.334994
52020-09-18600519.SH1695.001670.521.4654123.334994
\n", + "
" + ], + "text/plain": [ + " m_nDate code close yclose PctChg factor\n", + "0 2020-09-11 600519.SH 1733.00 1705.80 1.594560 3.334994\n", + "1 2020-09-14 600519.SH 1766.00 1733.00 1.904212 3.334994\n", + "2 2020-09-15 600519.SH 1760.00 1766.00 -0.339751 3.334994\n", + "3 2020-09-16 600519.SH 1725.10 1760.00 -1.982955 3.334994\n", + "4 2020-09-17 600519.SH 1670.52 1725.10 -3.163875 3.334994\n", + "5 2020-09-18 600519.SH 1695.00 1670.52 1.465412 3.334994" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')\n", + "\n", + "# sess.run(\"select top 100 code, m_nDate, log(amount + 1) as log_amount from loadTable('dfs://daily_stock_ts', 'daily_kline')\")\n", + "#sess.run(\"select top 100 * from loadTable('dfs://daily_stock_ts', 'daily_kline') where IsGoDelist>0\")\n", + "#sess.run(\"select m_nDate, count(code) from loadTable('dfs://daily_stock_ts', 'daily_kline') group by m_nDate order by m_nDate desc\")\n", + "sess.run(\"select top 100 m_nDate, code, close, yclose, PctChg, factor from loadTable('dfs://daily_stock_ts', 'daily_kline') where code='600519.SH' and m_nDate>2020.09.10 and m_nDate<2020.09.20 order by m_nDate asc\")" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "988f7b87-e221-4847-ad21-88844a1a7349", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ycloseclosefactor
instrumentdatetime
000300.SH2010-01-043575.6840NaNNaN
2010-01-053535.22903535.22901.000000
2010-01-063564.03803564.03801.000000
2010-01-073541.72703541.72701.000000
2010-01-083471.45603471.45601.000000
............
2022-08-294107.54554107.54551.000698
2022-08-304089.52054089.52051.000698
2022-08-314075.79374075.79371.000698
2022-09-014078.84024078.84021.000698
2022-09-024043.73954043.73951.000698
\n", + "

3080 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " yclose close factor\n", + "instrument datetime \n", + "000300.SH 2010-01-04 3575.6840 NaN NaN\n", + " 2010-01-05 3535.2290 3535.2290 1.000000\n", + " 2010-01-06 3564.0380 3564.0380 1.000000\n", + " 2010-01-07 3541.7270 3541.7270 1.000000\n", + " 2010-01-08 3471.4560 3471.4560 1.000000\n", + "... ... ... ...\n", + " 2022-08-29 4107.5455 4107.5455 1.000698\n", + " 2022-08-30 4089.5205 4089.5205 1.000698\n", + " 2022-08-31 4075.7937 4075.7937 1.000698\n", + " 2022-09-01 4078.8402 4078.8402 1.000698\n", + " 2022-09-02 4043.7395 4043.7395 1.000698\n", + "\n", + "[3080 rows x 3 columns]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " base = select code, m_nDate, close, yclose \n", + " from loadTable('dfs://daily_stock_ts', 'idx_daily_kline') where code='000300.SH' \n", + " order by m_nDate asc;\n", + " previous = select code, temporalAdd(m_nDate, 1, \"d\") as m_nDate, close, yclose \n", + " from loadTable('dfs://daily_stock_ts', 'idx_daily_kline') where code='000300.SH' \n", + " order by m_nDate asc;\n", + " select code as instrument, m_nDate as datetime, base.yclose, previous.close, cumprod(previous.close/base.yclose) as factor from aj(base, previous, `code`m_nDate);\n", + "\"\"\")\n", + "df.set_index(['instrument', 'datetime'], inplace=True)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "d1228611-d953-425e-bbfa-d3d91418e3aa", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ycloseclosefactor2factor
instrumentdatetime
600519.SH2020-09-161760.01760.03.3349943.334994
\n", + "
" + ], + "text/plain": [ + " yclose close factor2 factor\n", + "instrument datetime \n", + "600519.SH 2020-09-16 1760.0 1760.0 3.334994 3.334994" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "row = df[df.index.get_level_values(\"datetime\") == '2020-09-16']\n", + "row" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "4f73a4a0-e828-40c1-92c3-8bfe6491fa08", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "instrument datetime \n", + "600519.SH 2020-09-16 527.737026\n", + "dtype: float64" ] }, - "execution_count": 16, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "sess.run(\"select min(m_nDate) from loadTable('dfs://daily_stock_ts', 'daily_kline')\")" + "row['close'] / row['factor']" ] }, { diff --git a/ipynb/ddb_daily_factor.ipynb b/ipynb/ddb_daily_factor.ipynb new file mode 100644 index 0000000..6995c26 --- /dev/null +++ b/ipynb/ddb_daily_factor.ipynb @@ -0,0 +1,3141 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "a4915372-8508-45ce-ba31-8aef7c5b0ef1", + "metadata": {}, + "outputs": [], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "id": "ebd3b848-e0ce-4d0f-94f7-78a687040e80", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatedowmoy
0000400.SZ2006-01-0421
1000400.SZ2006-01-0531
2000400.SZ2006-01-0641
3000400.SZ2006-01-0901
4000400.SZ2006-01-1011
...............
95000400.SZ2011-01-2511
96000400.SZ2011-01-2621
97000400.SZ2011-01-2731
98000400.SZ2011-01-2841
99000400.SZ2011-01-3101
\n", + "

100 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate dow moy\n", + "0 000400.SZ 2006-01-04 2 1\n", + "1 000400.SZ 2006-01-05 3 1\n", + "2 000400.SZ 2006-01-06 4 1\n", + "3 000400.SZ 2006-01-09 0 1\n", + "4 000400.SZ 2006-01-10 1 1\n", + ".. ... ... ... ...\n", + "95 000400.SZ 2011-01-25 1 1\n", + "96 000400.SZ 2011-01-26 2 1\n", + "97 000400.SZ 2011-01-27 3 1\n", + "98 000400.SZ 2011-01-28 4 1\n", + "99 000400.SZ 2011-01-31 0 1\n", + "\n", + "[100 rows x 4 columns]" + ] + }, + "execution_count": 108, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select top 100 code, m_nDate, dayOfWeek(m_nDate) as dow, monthOfYear(m_nDate) as moy \n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " where monthOfYear(m_nDate) = 1\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "id": "ae07f021-409d-4b8b-8676-ff2a0f54bb34", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatevol_20
2776841600000.SH2006-01-04NaN
2776842600000.SH2006-01-05NaN
2776843600000.SH2006-01-06NaN
2776844600000.SH2006-01-09NaN
2776845600000.SH2006-01-10NaN
............
2780773600000.SH2022-08-040.291758
2780774600000.SH2022-08-050.289024
2780775600000.SH2022-08-080.283952
2780776600000.SH2022-08-090.270085
2780777600000.SH2022-08-100.256963
\n", + "

3937 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate vol_20\n", + "2776841 600000.SH 2006-01-04 NaN\n", + "2776842 600000.SH 2006-01-05 NaN\n", + "2776843 600000.SH 2006-01-06 NaN\n", + "2776844 600000.SH 2006-01-09 NaN\n", + "2776845 600000.SH 2006-01-10 NaN\n", + "... ... ... ...\n", + "2780773 600000.SH 2022-08-04 0.291758\n", + "2780774 600000.SH 2022-08-05 0.289024\n", + "2780775 600000.SH 2022-08-08 0.283952\n", + "2780776 600000.SH 2022-08-09 0.270085\n", + "2780777 600000.SH 2022-08-10 0.256963\n", + "\n", + "[3937 rows x 3 columns]" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " vol_20 = select code, m_nDate, mstdp(close, 20, 9) as vol_20\n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " context by code;\n", + " vol_20\n", + "\"\"\")\n", + "df[df['code'] == '600000.SH']" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "cffabf93-81d3-4075-b80a-1c761ccd95b6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDaterank_vol_20
0000400.SZ2006-01-04NaN
1000515.SZ2006-01-04NaN
2000558.SZ2006-01-04NaN
3000602.SZ2006-01-04NaN
4000731.SZ2006-01-04NaN
............
10403520688272.SH2022-08-100.901734
10403521688320.SH2022-08-100.985756
10403522688739.SH2022-08-100.707267
10403523688777.SH2022-08-100.960776
10403524830964.NE2022-08-100.021263
\n", + "

10403525 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate rank_vol_20\n", + "0 000400.SZ 2006-01-04 NaN\n", + "1 000515.SZ 2006-01-04 NaN\n", + "2 000558.SZ 2006-01-04 NaN\n", + "3 000602.SZ 2006-01-04 NaN\n", + "4 000731.SZ 2006-01-04 NaN\n", + "... ... ... ...\n", + "10403520 688272.SH 2022-08-10 0.901734\n", + "10403521 688320.SH 2022-08-10 0.985756\n", + "10403522 688739.SH 2022-08-10 0.707267\n", + "10403523 688777.SH 2022-08-10 0.960776\n", + "10403524 830964.NE 2022-08-10 0.021263\n", + "\n", + "[10403525 rows x 3 columns]" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " rank_vol_20 = select code, m_nDate, rank(vol_20, tiesMethod='average', percent=true)\n", + " from vol_20 context by m_nDate;\n", + " rank_vol_20\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "f10dd713-e516-48bc-a232-f1570eef03ff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDaterank_vol_20
2295890000400.SZ2012-01-050.932731
2295891000558.SZ2012-01-050.191422
2295892000602.SZ2012-01-050.367946
2295893000731.SZ2012-01-050.252370
2295894000752.SZ2012-01-050.734537
............
2298104600586.SH2012-01-050.126862
2298105600660.SH2012-01-050.031603
2298106601299.SH2012-01-050.127765
2298107601788.SH2012-01-050.419413
2298108601988.SH2012-01-050.000451
\n", + "

2219 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate rank_vol_20\n", + "2295890 000400.SZ 2012-01-05 0.932731\n", + "2295891 000558.SZ 2012-01-05 0.191422\n", + "2295892 000602.SZ 2012-01-05 0.367946\n", + "2295893 000731.SZ 2012-01-05 0.252370\n", + "2295894 000752.SZ 2012-01-05 0.734537\n", + "... ... ... ...\n", + "2298104 600586.SH 2012-01-05 0.126862\n", + "2298105 600660.SH 2012-01-05 0.031603\n", + "2298106 601299.SH 2012-01-05 0.127765\n", + "2298107 601788.SH 2012-01-05 0.419413\n", + "2298108 601988.SH 2012-01-05 0.000451\n", + "\n", + "[2219 rows x 3 columns]" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[df['m_nDate'] == '2012-01-05']" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "972934f5-35c7-4874-b990-4ce0f9d58965", + "metadata": {}, + "outputs": [], + "source": [ + "df = sess.run(\"\"\"\n", + " corr_5 = select code, m_nDate, mcorr(high, vol, 5) as corr_5\n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " context by code;\n", + " corr_5\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "id": "d3442f93-3beb-40c1-92c1-7f2d2d0e8ec3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatedelta_corr_5
5873882600000.SH2006-01-11NaN
5873883600000.SH2006-01-12NaN
5873884600000.SH2006-01-13NaN
5873885600000.SH2006-01-160.111578
5873886600000.SH2006-01-170.053048
5873887600000.SH2006-01-180.680933
5873888600000.SH2006-01-19-0.530191
5873889600000.SH2006-01-20-0.283952
5873890600000.SH2006-01-23-0.295373
5873891600000.SH2006-01-24-0.105135
\n", + "
" + ], + "text/plain": [ + " code m_nDate delta_corr_5\n", + "5873882 600000.SH 2006-01-11 NaN\n", + "5873883 600000.SH 2006-01-12 NaN\n", + "5873884 600000.SH 2006-01-13 NaN\n", + "5873885 600000.SH 2006-01-16 0.111578\n", + "5873886 600000.SH 2006-01-17 0.053048\n", + "5873887 600000.SH 2006-01-18 0.680933\n", + "5873888 600000.SH 2006-01-19 -0.530191\n", + "5873889 600000.SH 2006-01-20 -0.283952\n", + "5873890 600000.SH 2006-01-23 -0.295373\n", + "5873891 600000.SH 2006-01-24 -0.105135" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " delta_corr_5 = select code, m_nDate, mfirst(corr_5, 5) - corr_5 as delta_corr_5\n", + " from corr_5 context by code;\n", + " delta_corr_5\n", + "\"\"\")\n", + "df[df['code'] == '600000.SH'].iloc[5:15]" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "id": "b70d0329-0f82-4fef-a6e1-faf2068e85f4", + "metadata": {}, + "outputs": [], + "source": [ + "df = sess.run(\"\"\"\n", + " alpha101_22 = select code, m_nDate, delta_corr_5 * rank_vol_20 as alpha101_22\n", + " from ej(rank_vol_20, delta_corr_5, `code`m_nDate);\n", + " alpha101_22\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "id": "4fbb58eb-58fa-40d9-a0e8-32e9b4868629", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatealpha101_22
0000400.SZ2006-01-04NaN
1000515.SZ2006-01-04NaN
2000558.SZ2006-01-04NaN
3000602.SZ2006-01-04NaN
4000731.SZ2006-01-04NaN
............
10403520688272.SH2022-08-100.280800
10403521688320.SH2022-08-100.464768
10403522688739.SH2022-08-100.054898
10403523688777.SH2022-08-100.427098
10403524830964.NE2022-08-10-0.016451
\n", + "

10403525 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate alpha101_22\n", + "0 000400.SZ 2006-01-04 NaN\n", + "1 000515.SZ 2006-01-04 NaN\n", + "2 000558.SZ 2006-01-04 NaN\n", + "3 000602.SZ 2006-01-04 NaN\n", + "4 000731.SZ 2006-01-04 NaN\n", + "... ... ... ...\n", + "10403520 688272.SH 2022-08-10 0.280800\n", + "10403521 688320.SH 2022-08-10 0.464768\n", + "10403522 688739.SH 2022-08-10 0.054898\n", + "10403523 688777.SH 2022-08-10 0.427098\n", + "10403524 830964.NE 2022-08-10 -0.016451\n", + "\n", + "[10403525 rows x 3 columns]" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f211d667-4932-457e-9051-667607f8a105", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatemonth_of_year
0000400.SZ2006-01-041
1000400.SZ2006-01-051
2000400.SZ2006-01-061
3000400.SZ2006-01-091
4000400.SZ2006-01-101
............
95000400.SZ2006-06-066
96000400.SZ2006-06-076
97000400.SZ2006-06-086
98000400.SZ2006-06-096
99000400.SZ2006-06-126
\n", + "

100 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate month_of_year\n", + "0 000400.SZ 2006-01-04 1\n", + "1 000400.SZ 2006-01-05 1\n", + "2 000400.SZ 2006-01-06 1\n", + "3 000400.SZ 2006-01-09 1\n", + "4 000400.SZ 2006-01-10 1\n", + ".. ... ... ...\n", + "95 000400.SZ 2006-06-06 6\n", + "96 000400.SZ 2006-06-07 6\n", + "97 000400.SZ 2006-06-08 6\n", + "98 000400.SZ 2006-06-09 6\n", + "99 000400.SZ 2006-06-12 6\n", + "\n", + "[100 rows x 3 columns]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select top 100 code, m_nDate, monthOfYear(m_nDate) as month_of_year \n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "id": "fc62191a-94f6-4172-a2a2-39907d94e6b5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatetrend_with_turnovertrend_with_amountabs_trend_with_turnoverabs_trend_with_amountalpha101_22
0000400.SZ2006-01-04NaN0.0821850.1019430.0821850.101943
1000400.SZ2006-01-05NaN0.0062550.0248390.0062550.024839
2000400.SZ2006-01-06NaN-0.004377-0.0111940.0043770.011194
3000400.SZ2006-01-09NaN0.0295490.0661960.0295490.066196
4000400.SZ2006-01-10NaN0.0117160.0132020.0117160.013202
........................
95000400.SZ2006-06-060.1210660.021408-0.019479-0.0214080.019479
96000400.SZ2006-06-070.0910730.099845-0.084317-0.0998450.084317
97000400.SZ2006-06-08-0.3368590.007474-0.006340-0.0074740.006340
98000400.SZ2006-06-09-0.453049-0.0050570.002774-0.0050570.002774
99000400.SZ2006-06-12-0.244429-0.0073220.006228-0.0073220.006228
\n", + "

100 rows × 7 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate trend_with_turnover trend_with_amount \\\n", + "0 000400.SZ 2006-01-04 NaN 0.082185 \n", + "1 000400.SZ 2006-01-05 NaN 0.006255 \n", + "2 000400.SZ 2006-01-06 NaN -0.004377 \n", + "3 000400.SZ 2006-01-09 NaN 0.029549 \n", + "4 000400.SZ 2006-01-10 NaN 0.011716 \n", + ".. ... ... ... ... \n", + "95 000400.SZ 2006-06-06 0.121066 0.021408 \n", + "96 000400.SZ 2006-06-07 0.091073 0.099845 \n", + "97 000400.SZ 2006-06-08 -0.336859 0.007474 \n", + "98 000400.SZ 2006-06-09 -0.453049 -0.005057 \n", + "99 000400.SZ 2006-06-12 -0.244429 -0.007322 \n", + "\n", + " abs_trend_with_turnover abs_trend_with_amount alpha101_22 \n", + "0 0.101943 0.082185 0.101943 \n", + "1 0.024839 0.006255 0.024839 \n", + "2 -0.011194 0.004377 0.011194 \n", + "3 0.066196 0.029549 0.066196 \n", + "4 0.013202 0.011716 0.013202 \n", + ".. ... ... ... \n", + "95 -0.019479 -0.021408 0.019479 \n", + "96 -0.084317 -0.099845 0.084317 \n", + "97 -0.006340 -0.007474 0.006340 \n", + "98 0.002774 -0.005057 0.002774 \n", + "99 0.006228 -0.007322 0.006228 \n", + "\n", + "[100 rows x 7 columns]" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select top 100 * \n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_factor\")\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "081d51c7-f9d5-4493-bc16-a03945d1e4c2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateopenhighlowcloseIsZtIsT
0000622.SZ2018-10-103.173.203.113.130False
1000622.SZ2018-10-113.023.112.822.830False
2000622.SZ2018-10-122.852.862.622.770False
3000622.SZ2018-10-152.802.872.732.730False
4000622.SZ2018-10-162.732.812.602.670False
5000622.SZ2018-10-172.712.742.572.660False
6000622.SZ2018-10-182.672.672.462.500False
7000622.SZ2018-10-192.422.592.422.580False
8000622.SZ2018-10-222.842.842.842.841False
9000622.SZ2018-10-233.123.122.843.121True
10000622.SZ2018-10-243.133.433.023.431True
11000622.SZ2018-10-253.703.773.613.771True
12000622.SZ2018-10-264.154.154.154.151False
13000622.SZ2018-10-294.304.574.254.571True
14000622.SZ2018-10-304.585.034.465.031True
15000622.SZ2018-11-055.535.535.535.531False
16000622.SZ2018-11-066.086.086.086.081False
17000622.SZ2018-11-076.456.696.336.691True
18000622.SZ2018-11-087.257.366.987.361True
19000622.SZ2018-11-097.388.107.267.900False
\n", + "
" + ], + "text/plain": [ + " code m_nDate open high low close IsZt IsT\n", + "0 000622.SZ 2018-10-10 3.17 3.20 3.11 3.13 0 False\n", + "1 000622.SZ 2018-10-11 3.02 3.11 2.82 2.83 0 False\n", + "2 000622.SZ 2018-10-12 2.85 2.86 2.62 2.77 0 False\n", + "3 000622.SZ 2018-10-15 2.80 2.87 2.73 2.73 0 False\n", + "4 000622.SZ 2018-10-16 2.73 2.81 2.60 2.67 0 False\n", + "5 000622.SZ 2018-10-17 2.71 2.74 2.57 2.66 0 False\n", + "6 000622.SZ 2018-10-18 2.67 2.67 2.46 2.50 0 False\n", + "7 000622.SZ 2018-10-19 2.42 2.59 2.42 2.58 0 False\n", + "8 000622.SZ 2018-10-22 2.84 2.84 2.84 2.84 1 False\n", + "9 000622.SZ 2018-10-23 3.12 3.12 2.84 3.12 1 True\n", + "10 000622.SZ 2018-10-24 3.13 3.43 3.02 3.43 1 True\n", + "11 000622.SZ 2018-10-25 3.70 3.77 3.61 3.77 1 True\n", + "12 000622.SZ 2018-10-26 4.15 4.15 4.15 4.15 1 False\n", + "13 000622.SZ 2018-10-29 4.30 4.57 4.25 4.57 1 True\n", + "14 000622.SZ 2018-10-30 4.58 5.03 4.46 5.03 1 True\n", + "15 000622.SZ 2018-11-05 5.53 5.53 5.53 5.53 1 False\n", + "16 000622.SZ 2018-11-06 6.08 6.08 6.08 6.08 1 False\n", + "17 000622.SZ 2018-11-07 6.45 6.69 6.33 6.69 1 True\n", + "18 000622.SZ 2018-11-08 7.25 7.36 6.98 7.36 1 True\n", + "19 000622.SZ 2018-11-09 7.38 8.10 7.26 7.90 0 False" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select code, m_nDate, open, high, low, close, IsZt, \\\n", + " (IsZt and high=close and low!=close) as IsT \\\n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\") \n", + " where code='000622.SZ' and m_nDate>=2018.10.10 and m_nDate<=2018.11.10\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "14c51fe0-3791-4f5b-8ccc-bfd43f0f5be9", + "metadata": {}, + "outputs": [], + "source": [ + "sess.run(\"\"\"\n", + " t1 = select code, m_nDate, amount/vol as vwap from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\") \n", + " where code='000400.SZ' and m_nDate>=2014.01.04 and m_nDate<=2014.02.04;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "29bc4089-4df1-4bea-800f-d01e893d08bd", + "metadata": {}, + "outputs": [], + "source": [ + "sess.run(\"\"\"\n", + " t2 = select code, m_nDate, vwap from loadTable(\"dfs://daily_stock_ts\", \"hft_daily_factor\")\n", + " where code='000400.SZ' and m_nDate>=2014.01.04 and m_nDate<=2014.02.04\n", + "\"\"\") " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b98b12d4-1068-4c98-8374-bbc1adce01a3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatevwapt2_vwapvwap_sub
0000400.SZ2014-01-0630.62853330.982086-0.353552
1000400.SZ2014-01-0733.00400032.6129760.391024
2000400.SZ2014-01-0832.90872432.6109450.297780
3000400.SZ2014-01-0933.56331533.736282-0.172967
4000400.SZ2014-01-1032.01233932.273132-0.260793
5000400.SZ2014-01-1332.30144032.1131600.188280
6000400.SZ2014-01-1432.49557132.781237-0.285666
7000400.SZ2014-01-1533.79142733.7507420.040686
8000400.SZ2014-01-1634.69570834.871143-0.175435
9000400.SZ2014-01-1733.91033033.978306-0.067975
10000400.SZ2014-01-2033.70738933.731507-0.024118
11000400.SZ2014-01-2133.33821033.663293-0.325083
12000400.SZ2014-01-2234.04644033.6571110.389329
13000400.SZ2014-01-2334.02809334.028356-0.000263
14000400.SZ2014-01-2433.91991633.8790260.040890
15000400.SZ2014-01-2734.10455633.9498440.154712
16000400.SZ2014-01-2833.92630234.179352-0.253050
17000400.SZ2014-01-2934.04629333.9170530.129240
18000400.SZ2014-01-3034.04107034.464937-0.423867
\n", + "
" + ], + "text/plain": [ + " code m_nDate vwap t2_vwap vwap_sub\n", + "0 000400.SZ 2014-01-06 30.628533 30.982086 -0.353552\n", + "1 000400.SZ 2014-01-07 33.004000 32.612976 0.391024\n", + "2 000400.SZ 2014-01-08 32.908724 32.610945 0.297780\n", + "3 000400.SZ 2014-01-09 33.563315 33.736282 -0.172967\n", + "4 000400.SZ 2014-01-10 32.012339 32.273132 -0.260793\n", + "5 000400.SZ 2014-01-13 32.301440 32.113160 0.188280\n", + "6 000400.SZ 2014-01-14 32.495571 32.781237 -0.285666\n", + "7 000400.SZ 2014-01-15 33.791427 33.750742 0.040686\n", + "8 000400.SZ 2014-01-16 34.695708 34.871143 -0.175435\n", + "9 000400.SZ 2014-01-17 33.910330 33.978306 -0.067975\n", + "10 000400.SZ 2014-01-20 33.707389 33.731507 -0.024118\n", + "11 000400.SZ 2014-01-21 33.338210 33.663293 -0.325083\n", + "12 000400.SZ 2014-01-22 34.046440 33.657111 0.389329\n", + "13 000400.SZ 2014-01-23 34.028093 34.028356 -0.000263\n", + "14 000400.SZ 2014-01-24 33.919916 33.879026 0.040890\n", + "15 000400.SZ 2014-01-27 34.104556 33.949844 0.154712\n", + "16 000400.SZ 2014-01-28 33.926302 34.179352 -0.253050\n", + "17 000400.SZ 2014-01-29 34.046293 33.917053 0.129240\n", + "18 000400.SZ 2014-01-30 34.041070 34.464937 -0.423867" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select *, t1.vwap-t2.vwap from ej(t1, t2, `code`m_nDate)\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "b0543222-4201-4ca7-8a38-2f561adecd76", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
winsorize
00.191026
10.082927
20.143954
3-0.060634
40.014164
......
39320.014144
39330.042313
3934-0.020979
39350.000000
3936-0.021067
\n", + "

3937 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " winsorize\n", + "0 0.191026\n", + "1 0.082927\n", + "2 0.143954\n", + "3 -0.060634\n", + "4 0.014164\n", + "... ...\n", + "3932 0.014144\n", + "3933 0.042313\n", + "3934 -0.020979\n", + "3935 0.000000\n", + "3936 -0.021067\n", + "\n", + "[3937 rows x 1 columns]" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " t1 = select winsorize(PctChg/20, 0.05) from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\") where code=\"600000.SH\";\n", + " t1;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "4d0ac236-d2b3-4724-9f89-040d85e95221", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateamountamount_rankamount_with_trend
0000400.SZ2006-01-043.265679e+070.4103210.661152
1000515.SZ2006-01-049.116335e+060.1776650.462941
2000558.SZ2006-01-042.417575e+06-0.2318100.209710
3000602.SZ2006-01-041.767682e+070.3147210.705630
4000731.SZ2006-01-041.402217e+070.2724200.675770
..................
10403520688272.SH2022-08-107.012509e+07-0.0147270.271909
10403521688320.SH2022-08-101.067048e+080.1014420.561355
10403522688739.SH2022-08-101.035707e+07-0.4421220.030941
10403523688777.SH2022-08-104.529292e+080.3943360.751877
10403524830964.NE2022-08-105.583561e+05-0.4934090.002081
\n", + "

10403525 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate amount amount_rank amount_with_trend\n", + "0 000400.SZ 2006-01-04 3.265679e+07 0.410321 0.661152\n", + "1 000515.SZ 2006-01-04 9.116335e+06 0.177665 0.462941\n", + "2 000558.SZ 2006-01-04 2.417575e+06 -0.231810 0.209710\n", + "3 000602.SZ 2006-01-04 1.767682e+07 0.314721 0.705630\n", + "4 000731.SZ 2006-01-04 1.402217e+07 0.272420 0.675770\n", + "... ... ... ... ... ...\n", + "10403520 688272.SH 2022-08-10 7.012509e+07 -0.014727 0.271909\n", + "10403521 688320.SH 2022-08-10 1.067048e+08 0.101442 0.561355\n", + "10403522 688739.SH 2022-08-10 1.035707e+07 -0.442122 0.030941\n", + "10403523 688777.SH 2022-08-10 4.529292e+08 0.394336 0.751877\n", + "10403524 830964.NE 2022-08-10 5.583561e+05 -0.493409 0.002081\n", + "\n", + "[10403525 rows x 5 columns]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " select \n", + " code, m_nDate, \n", + " amount, \n", + " rank(amount,tiesMethod='average', percent=true)-0.5 as amount_rank,\n", + " rank(amount,tiesMethod='average', percent=true)-0.5 * winsorize(abs(PctChg)/10, 0.02) as amount_with_trend\n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " context by m_nDate\n", + "\"\"\")\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "id": "b0d7d22f-6d80-45ed-b685-0cbc0daccd13", + "metadata": {}, + "outputs": [], + "source": [ + "df = sess.run(\"\"\"\n", + " tableInsert(\n", + " loadTable(\"dfs://daily_stock_ts\", \"daily_factor\"),\n", + " select \n", + " code, m_nDate, \n", + " rank(amount,tiesMethod='average', percent=true)-0.5 * winsorize(abs(PctChg), 0.02) \n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " context by m_nDate\n", + " )\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "id": "a72d9b1f-a84a-463f-87b8-1841d51afd5e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatetrend_with_amount
0000400.SZ2006-01-040.101943
1000400.SZ2006-01-050.024839
2000400.SZ2006-01-06-0.011194
3000400.SZ2006-01-090.066196
4000400.SZ2006-01-100.013202
............
95000400.SZ2006-06-06-0.019479
96000400.SZ2006-06-07-0.084317
97000400.SZ2006-06-08-0.006340
98000400.SZ2006-06-090.002774
99000400.SZ2006-06-120.006228
\n", + "

100 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate trend_with_amount\n", + "0 000400.SZ 2006-01-04 0.101943\n", + "1 000400.SZ 2006-01-05 0.024839\n", + "2 000400.SZ 2006-01-06 -0.011194\n", + "3 000400.SZ 2006-01-09 0.066196\n", + "4 000400.SZ 2006-01-10 0.013202\n", + ".. ... ... ...\n", + "95 000400.SZ 2006-06-06 -0.019479\n", + "96 000400.SZ 2006-06-07 -0.084317\n", + "97 000400.SZ 2006-06-08 -0.006340\n", + "98 000400.SZ 2006-06-09 0.002774\n", + "99 000400.SZ 2006-06-12 0.006228\n", + "\n", + "[100 rows x 3 columns]" + ] + }, + "execution_count": 118, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select top 100 * from loadTable(\"dfs://daily_stock_ts\", \"daily_factor\")\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "id": "bbf2d32b-db27-4f3d-820e-8d53ff936b2d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateamountrank_amount_sub
0000400.SZ2006-01-043.265679e+070.410321
1182000400.SZ2006-01-052.582027e+070.338525
2402000400.SZ2006-01-063.477456e+070.361201
3634000400.SZ2006-01-093.356378e+070.374590
4854000400.SZ2006-01-105.437912e+070.438322
...............
10379267000400.SZ2022-08-041.660664e+090.487822
10384112000400.SZ2022-08-051.430263e+090.480821
10388961000400.SZ2022-08-089.427016e+080.464359
10393815000400.SZ2022-08-099.085981e+080.464985
10398670000400.SZ2022-08-101.074877e+090.471164
\n", + "

3786 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate amount rank_amount_sub\n", + "0 000400.SZ 2006-01-04 3.265679e+07 0.410321\n", + "1182 000400.SZ 2006-01-05 2.582027e+07 0.338525\n", + "2402 000400.SZ 2006-01-06 3.477456e+07 0.361201\n", + "3634 000400.SZ 2006-01-09 3.356378e+07 0.374590\n", + "4854 000400.SZ 2006-01-10 5.437912e+07 0.438322\n", + "... ... ... ... ...\n", + "10379267 000400.SZ 2022-08-04 1.660664e+09 0.487822\n", + "10384112 000400.SZ 2022-08-05 1.430263e+09 0.480821\n", + "10388961 000400.SZ 2022-08-08 9.427016e+08 0.464359\n", + "10393815 000400.SZ 2022-08-09 9.085981e+08 0.464985\n", + "10398670 000400.SZ 2022-08-10 1.074877e+09 0.471164\n", + "\n", + "[3786 rows x 4 columns]" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[df['code'] == '000400.SZ']" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "0548beb0-9cc7-4c27-9383-2519e72b62a6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDatetrend_with_amounttrend_with_turnover
0000400.SZ2006-01-042.4619291.984772
1000515.SZ2006-01-040.7629781.693085
2000558.SZ2006-01-04-0.2711230.042549
3000602.SZ2006-01-040.6866640.895247
4000731.SZ2006-01-040.5265840.304176
...............
10403520688272.SH2022-08-10-0.0628452.001800
10403521688320.SH2022-08-100.0813300.256045
10403522688739.SH2022-08-10-0.238192-0.179157
10403523688777.SH2022-08-101.1235320.242664
10403524830964.NE2022-08-10-0.000000-0.000000
\n", + "

10403525 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate trend_with_amount trend_with_turnover\n", + "0 000400.SZ 2006-01-04 2.461929 1.984772\n", + "1 000515.SZ 2006-01-04 0.762978 1.693085\n", + "2 000558.SZ 2006-01-04 -0.271123 0.042549\n", + "3 000602.SZ 2006-01-04 0.686664 0.895247\n", + "4 000731.SZ 2006-01-04 0.526584 0.304176\n", + "... ... ... ... ...\n", + "10403520 688272.SH 2022-08-10 -0.062845 2.001800\n", + "10403521 688320.SH 2022-08-10 0.081330 0.256045\n", + "10403522 688739.SH 2022-08-10 -0.238192 -0.179157\n", + "10403523 688777.SH 2022-08-10 1.123532 0.242664\n", + "10403524 830964.NE 2022-08-10 -0.000000 -0.000000\n", + "\n", + "[10403525 rows x 4 columns]" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " f = select \n", + " code, m_nDate, \n", + " (rank(amount, tiesMethod='average', percent=true) - 0.5) * abs(winsorize(PctChg, 0.01)) as trend_with_amount,\n", + " (rank((amount/MarketValues), tiesMethod='average', percent=true) - 0.5) * abs(winsorize(PctChg, 0.01)) as trend_with_turnover\n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " context by m_nDate\n", + " f;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "b604dd48-2869-41d8-a001-275ab0b49594", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDaterank_PctChg_sub
0000400.SZ2006-01-030.461697
1000400.SZ2006-01-040.241123
2000400.SZ2006-01-05-0.124425
3000400.SZ2006-01-080.399528
4000400.SZ2006-01-090.108267
............
10403520830964.NE2022-08-03-0.027355
10403521830964.NE2022-08-04-0.070112
10403522830964.NE2022-08-070.050077
10403523830964.NE2022-08-08-0.027355
10403524830964.NE2022-08-09-0.027355
\n", + "

10403525 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate rank_PctChg_sub\n", + "0 000400.SZ 2006-01-03 0.461697\n", + "1 000400.SZ 2006-01-04 0.241123\n", + "2 000400.SZ 2006-01-05 -0.124425\n", + "3 000400.SZ 2006-01-08 0.399528\n", + "4 000400.SZ 2006-01-09 0.108267\n", + "... ... ... ...\n", + "10403520 830964.NE 2022-08-03 -0.027355\n", + "10403521 830964.NE 2022-08-04 -0.070112\n", + "10403522 830964.NE 2022-08-07 0.050077\n", + "10403523 830964.NE 2022-08-08 -0.027355\n", + "10403524 830964.NE 2022-08-09 -0.027355\n", + "\n", + "[10403525 rows x 3 columns]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " r = select \n", + " code, m_nDate-1 as m_nDate, \n", + " rank(PctChg, percent=true)-0.5 \n", + " from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\");\n", + " r;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "id": "daab613f-9e6b-4f75-bfbe-80a2293912c3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDaterank_PctChg_subalpha101_22_m_nDatealpha101_22
0000400.SZ2006-01-030.461697NaTNaN
1000400.SZ2006-01-040.2411232006-01-04NaN
2000400.SZ2006-01-05-0.1244252006-01-05NaN
3000400.SZ2006-01-080.3995282006-01-06NaN
4000400.SZ2006-01-090.1082672006-01-09NaN
..................
10403520830964.NE2022-08-03-0.0273552022-08-030.008355
10403521830964.NE2022-08-04-0.0701122022-08-040.015653
10403522830964.NE2022-08-070.0500772022-08-050.014966
10403523830964.NE2022-08-08-0.0273552022-08-08-0.034349
10403524830964.NE2022-08-09-0.0273552022-08-09-0.021269
\n", + "

10403525 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate rank_PctChg_sub alpha101_22_m_nDate \\\n", + "0 000400.SZ 2006-01-03 0.461697 NaT \n", + "1 000400.SZ 2006-01-04 0.241123 2006-01-04 \n", + "2 000400.SZ 2006-01-05 -0.124425 2006-01-05 \n", + "3 000400.SZ 2006-01-08 0.399528 2006-01-06 \n", + "4 000400.SZ 2006-01-09 0.108267 2006-01-09 \n", + "... ... ... ... ... \n", + "10403520 830964.NE 2022-08-03 -0.027355 2022-08-03 \n", + "10403521 830964.NE 2022-08-04 -0.070112 2022-08-04 \n", + "10403522 830964.NE 2022-08-07 0.050077 2022-08-05 \n", + "10403523 830964.NE 2022-08-08 -0.027355 2022-08-08 \n", + "10403524 830964.NE 2022-08-09 -0.027355 2022-08-09 \n", + "\n", + " alpha101_22 \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "... ... \n", + "10403520 0.008355 \n", + "10403521 0.015653 \n", + "10403522 0.014966 \n", + "10403523 -0.034349 \n", + "10403524 -0.021269 \n", + "\n", + "[10403525 rows x 5 columns]" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " select * from aj(r, alpha101_22, `code`m_nDate)\n", + "\"\"\")\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "id": "ea2c353c-2e74-46f1-86c9-48322e9f9296", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
rank_PctChg_subalpha101_22
rank_PctChg_sub1.000000-0.006789
alpha101_22-0.0067891.000000
\n", + "
" + ], + "text/plain": [ + " rank_PctChg_sub alpha101_22\n", + "rank_PctChg_sub 1.000000 -0.006789\n", + "alpha101_22 -0.006789 1.000000" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[[\"rank_PctChg_sub\", \"alpha101_22\"]].dropna().corr()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "aac33fb2-d06b-4456-81a2-cf8476a13d4d", + "metadata": {}, + "outputs": [], + "source": [ + "df = df.set_index([\"m_nDate\"])[['rank_PctChg_sub', 'trend_with_amount', 'trend_with_turnover']].dropna()" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "bc7447a7-be59-481b-b15a-d2ff59355135", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
rank_PctChg_subtrend_with_amounttrend_with_turnover
rank_PctChg_sub1.000000-0.041950-0.032851
trend_with_amount-0.0419501.0000000.622215
trend_with_turnover-0.0328510.6222151.000000
\n", + "
" + ], + "text/plain": [ + " rank_PctChg_sub trend_with_amount trend_with_turnover\n", + "rank_PctChg_sub 1.000000 -0.041950 -0.032851\n", + "trend_with_amount -0.041950 1.000000 0.622215\n", + "trend_with_turnover -0.032851 0.622215 1.000000" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.corr(method=\"pearson\")" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "259aad61-545d-48b2-80d1-7588e2b1b95e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.0417603527848196" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from scipy.spatial import distance\n", + "1 - distance.cosine(df['rank_PctChg_sub'], df['trend_with_amount'])" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "84a31edf-a9cd-47bb-9f2b-384a45479c2d", + "metadata": {}, + "outputs": [], + "source": [ + "s_corr = df[[\"rank_PctChg_sub\", \"trend_with_amount\"]]\\\n", + " .groupby(\"m_nDate\").apply(lambda _df : 1 - distance.cosine(_df['rank_PctChg_sub'], _df['trend_with_amount']))" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "0574a132-0744-412d-a2b3-e7d5b78c3d7a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.3412639405204461" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(s_corr > 0) / len(s_corr)" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "id": "faac8d09-0e8c-409e-85e9-0cb2d567e7b6", + "metadata": {}, + "outputs": [ + { + "ename": "RuntimeError", + "evalue": " in run: Server response: 'select code as symbol,m_nDate as date,open,close,high,low,vol as volume,amount,cjbs,yclose,PctChg,amount / vol as vwap,FloatShares,MarketValues,trend_with_turnover,trend_with_amount,k_skew,k_advrev,k_tail30trade,k_vpcorr,k_largeorder_ret,factor from lj(lj(loadTable(\"dfs://daily_stock_ts\", \"daily_kline\"),loadTable(\"dfs://daily_stock_ts\", \"daily_factor\"),[\"code\",\"m_nDate\"]),loadTable(\"dfs://daily_stock_ts\", \"hft_daily_factor\"),[\"code\",\"m_nDate\"]) where partition(code, 0) order by m_nDate asc => Multiple-table join does not support partitioned table except the first table!' script: '\n select code as symbol, m_nDate as date, open, close, high, low, vol as volume, amount, cjbs, yclose, PctChg, amount/vol as vwap, FloatShares, MarketValues, trend_with_turnover, trend_with_amount, k_skew, k_advrev, k_tail30trade, k_vpcorr, k_largeorder_ret, factor as factor\n from lj(lj(loadTable('dfs://daily_stock_ts', 'daily_kline'), loadTable('dfs://daily_stock_ts', 'daily_factor'), `code`m_nDate), loadTable('dfs://daily_stock_ts', 'hft_daily_factor'), `code`m_nDate) where partition(code, 0)\n order by m_nDate asc;\n'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [131]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msess\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\"\"\u001b[39;49m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;124;43m select code as symbol, m_nDate as date, open, close, high, low, vol as volume, amount, cjbs, yclose, PctChg, amount/vol as vwap, FloatShares, MarketValues, trend_with_turnover, trend_with_amount, k_skew, k_advrev, k_tail30trade, k_vpcorr, k_largeorder_ret, factor as factor\u001b[39;49m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;124;43m from lj(lj(loadTable(\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mdfs://daily_stock_ts\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mdaily_kline\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m), loadTable(\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mdfs://daily_stock_ts\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mdaily_factor\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m), `code`m_nDate), loadTable(\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mdfs://daily_stock_ts\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mhft_daily_factor\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m), `code`m_nDate) where partition(code, 0)\u001b[39;49m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;124;43m order by m_nDate asc;\u001b[39;49m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;124;43m\"\"\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/.venv/tinysoft/lib/python3.8/site-packages/dolphindb/session.py:161\u001b[0m, in \u001b[0;36msession.run\u001b[0;34m(self, script, *args, **kwargs)\u001b[0m\n\u001b[1;32m 159\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfetchSize\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m kwargs\u001b[38;5;241m.\u001b[39mkeys():\n\u001b[1;32m 160\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m BlockReader(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcpp\u001b[38;5;241m.\u001b[39mrunBlock(script, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs))\n\u001b[0;32m--> 161\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcpp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mscript\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[0;31mRuntimeError\u001b[0m: in run: Server response: 'select code as symbol,m_nDate as date,open,close,high,low,vol as volume,amount,cjbs,yclose,PctChg,amount / vol as vwap,FloatShares,MarketValues,trend_with_turnover,trend_with_amount,k_skew,k_advrev,k_tail30trade,k_vpcorr,k_largeorder_ret,factor from lj(lj(loadTable(\"dfs://daily_stock_ts\", \"daily_kline\"),loadTable(\"dfs://daily_stock_ts\", \"daily_factor\"),[\"code\",\"m_nDate\"]),loadTable(\"dfs://daily_stock_ts\", \"hft_daily_factor\"),[\"code\",\"m_nDate\"]) where partition(code, 0) order by m_nDate asc => Multiple-table join does not support partitioned table except the first table!' script: '\n select code as symbol, m_nDate as date, open, close, high, low, vol as volume, amount, cjbs, yclose, PctChg, amount/vol as vwap, FloatShares, MarketValues, trend_with_turnover, trend_with_amount, k_skew, k_advrev, k_tail30trade, k_vpcorr, k_largeorder_ret, factor as factor\n from lj(lj(loadTable('dfs://daily_stock_ts', 'daily_kline'), loadTable('dfs://daily_stock_ts', 'daily_factor'), `code`m_nDate), loadTable('dfs://daily_stock_ts', 'hft_daily_factor'), `code`m_nDate) where partition(code, 0)\n order by m_nDate asc;\n'" + ] + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select code as symbol, m_nDate as date, open, close, high, low, vol as volume, amount, cjbs, yclose, PctChg, amount/vol as vwap, FloatShares, MarketValues, trend_with_turnover, trend_with_amount, k_skew, k_advrev, k_tail30trade, k_vpcorr, k_largeorder_ret, factor as factor\n", + " from lj(lj(loadTable('dfs://daily_stock_ts', 'daily_kline'), loadTable('dfs://daily_stock_ts', 'daily_factor'), `code`m_nDate), loadTable('dfs://daily_stock_ts', 'hft_daily_factor'), `code`m_nDate) where partition(code, 0)\n", + " order by m_nDate asc;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "7f05d056-4369-4f30-9f3e-47505799532e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
abs
01.491228
13.027605
20.388937
39.987086
41.056751
......
90538610.000000
90538620.298507
90538630.299401
90538640.000000
90538650.000000
\n", + "

9053866 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " abs\n", + "0 1.491228\n", + "1 3.027605\n", + "2 0.388937\n", + "3 9.987086\n", + "4 1.056751\n", + "... ...\n", + "9053861 0.000000\n", + "9053862 0.298507\n", + "9053863 0.299401\n", + "9053864 0.000000\n", + "9053865 0.000000\n", + "\n", + "[9053866 rows x 1 columns]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + "select abs(winsorize(PctChg, 0.01)) from lj(loadTable('dfs://daily_stock_ts', 'daily_kline'), loadTable('dfs://daily_stock_ts', 'daily_factor'), `code`m_nDate) \n", + "where m_nDate > 2010.01.01\n", + "\"\"\")\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "90805827-5fe0-416c-9c6f-58473cbad48b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[]], dtype=object)" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "df.hist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e5869db1-4134-426a-a8a0-782cc27ff198", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "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.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/ipynb/ddb_index.ipynb b/ipynb/ddb_index.ipynb new file mode 100644 index 0000000..64cf679 --- /dev/null +++ b/ipynb/ddb_index.ipynb @@ -0,0 +1,4208 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 69, + "id": "a98e649f-c649-437c-8b43-8f4b17660524", + "metadata": {}, + "outputs": [], + "source": [ + "import sqlalchemy as sa\n", + "engine = sa.create_engine(\n", + " 'mssql+pyodbc://sa:passw0rd!@192.168.1.7/master?driver=ODBC+Driver+18+for+SQL+Server',\n", + " connect_args = {\n", + " \"TrustServerCertificate\": \"yes\"\n", + " }, echo=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "7d0a8dc0-4a98-4766-b0f7-6b2bf61e8514", + "metadata": {}, + "outputs": [], + "source": [ + "with engine.connect() as conn:\n", + " rs = conn.execute(\"select SecID from [IndexInfo].[dbo].[Constituents] group by SecID\")\n", + " stock_list = [stock_id for (stock_id,) in rs.fetchall()]\n", + " \n", + " rs = conn.execute(\"select IndexID from [IndexInfo].[dbo].[Constituents] group by IndexID\")\n", + " index_list = [index_id for (index_id,) in rs.fetchall()]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "id": "cb3235f9-7719-4e94-9a8f-65cd535a2a5e", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "with engine.connect() as conn:\n", + " rs = conn.execute(\"\"\"\n", + " select \n", + " SecID, \n", + " CONCAT(SUBSTRING(EnterDate, 1, 4), '-', SUBSTRING(EnterDate, 5, 2), '-', SUBSTRING(EnterDate, 7, 2)) AS EnterDate, \n", + " CONCAT(SUBSTRING(ExitDate, 1, 4), '-', SUBSTRING(ExitDate, 5, 2), '-', SUBSTRING(ExitDate, 7, 2)) AS ExitDate\n", + " FROM (SELECT\n", + " SecID, \n", + " CAST(EnterDate AS varchar) AS EnterDate,\n", + " CAST(IIF(ExitDate=0, 20220630, ExitDate) AS varchar) AS ExitDate \n", + " from [IndexInfo].[dbo].[Constituents] where IndexID='SH000852'\n", + " )t\n", + " \"\"\")\n", + " index_info = rs.fetchall()\n", + "\n", + "index_info = pd.DataFrame(index_info)\n", + "index_info\n", + "index_info.to_csv('csi1000.txt', sep='\\t', columns=['SecID', 'EnterDate', 'ExitDate'], index=False, header=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc14e8be-a360-4a49-88fb-a9763d8ba655", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "def make_date(series):\n", + " # 特别是对于分红表,如果某些关键日期还未公布,则会填充0,导致日期解析失败\n", + " series.loc[series == 0] = np.nan\n", + " return pd.to_datetime(\n", + " series.astype(str), format='%Y%m%d')\n", + "\n", + "\n", + "with engine.connect() as conn:\n", + " rs = conn.execute(\"select SecID from [IndexInfo].[dbo].[Constituents] group by SecID\")\n", + " stock_list = [stock_id for (stock_id,) in rs.fetchall()]\n", + "\n", + " rs = conn.execute(\"select IndexID from [IndexInfo].[dbo].[Constituents] group by IndexID\")\n", + " concept_list = [index_id for (index_id,) in rs.fetchall()]\n", + " \n", + " stat = \"select distinct S_INFO_WINDCODE, TRADE_DT from Level2BytesKline.dbo.KLine\"\n", + " rs = conn.execute(stat)\n", + " stock_date_list = [(stock_name, date) for stock_name, date in rs.fetchall()]\n", + " df_calendar = pd.DataFrame(stock_date_list, columns=['code', 'm_nDate'])\n", + " df_calendar['m_nDate'] = make_date(df_calendar['m_nDate'])\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "5bc376b2-1e59-4d4d-a630-37c99884b2d5", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "\n", + "def tscode_to_windcode(series):\n", + " return series.apply(lambda x : x[2:] + '.' + x[:2])\n", + "\n", + "\n", + "def _make_stock2concept_onehot():\n", + " # 从calendar中截取出与当前stock有关的日期,然后设置成index\n", + " # 此处calendar使用的是海通高频数据构建,因此股票代码为WIND-CODE\n", + " for wind_code, df_calendar_stock in df_calendar.groupby('code'):\n", + " ts_code = wind_code[-2:] + wind_code[:-3]\n", + " \n", + " df_calendar_stock.set_index(['code', 'm_nDate'], inplace=True)\n", + "\n", + " # 纵表转横表,`concept_list`作为列名\n", + " df_stock2concept = pd.DataFrame(0, index=df_calendar_stock.index, columns=concept_list)\n", + "\n", + " # 从Sql-Server中读取`stock_id`所对应的概念板块进出日期\n", + " # 此数据是从天软指数数据中提取,因此需要使用TSCODE\n", + " with engine.connect() as conn:\n", + " code = \"\"\"\n", + " select \n", + " SecId, IndexID, EnterDate, ExitDate \n", + " from \n", + " [IndexInfo].[dbo].[Constituents] \n", + " where \n", + " SecID='{stock_id}'\n", + " \"\"\".format(\n", + " stock_id = ts_code\n", + " )\n", + " print(code)\n", + " rs = conn.execute(code)\n", + " row_list = rs.fetchall()\n", + "\n", + " for (stock_id, concept_id, start_date, end_date) in row_list:\n", + " _mark_stock2concept_onehot(df_stock2concept[concept_id], concept_id, start_date, end_date)\n", + "\n", + " yield df_stock2concept\n", + "\n", + "\n", + "def _mark_stock2concept_onehot(df_stock2concept, concept_id, start_date, end_date):\n", + " # 个股成为某个概念(指数)的起始日期是必定会提供的\n", + " # 但是截止日期可能缺失,确实一般意味着当前仍然是在此概念板块中\n", + " # 因此会通过将日期填充至最后一日来表示当前仍然在此概念板块内\n", + " if end_date is None or end_date == 0:\n", + " start_date = pd.to_datetime(str(start_date), format='%Y%m%d')\n", + " df_stock2concept.loc[df_stock2concept.index.get_level_values('m_nDate') >= start_date] = 1\n", + " else:\n", + " start_date = pd.to_datetime(str(start_date), format='%Y%m%d')\n", + " end_date = pd.to_datetime(str(end_date), format='%Y%m%d')\n", + " df_stock2concept.loc[\n", + " (df_stock2concept.index.get_level_values('m_nDate') >= start_date) & \n", + " (df_stock2concept.index.get_level_values('m_nDate') <= end_date)\n", + " ] = 1" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "a67786e5-4776-4492-8a87-72defe93eda4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " select \n", + " SecId, IndexID, EnterDate, ExitDate \n", + " from \n", + " [IndexInfo].[dbo].[Constituents] \n", + " where \n", + " SecID='SZ000001'\n", + " \n", + "('SZ000001', 'SH000940', 20090925, 0)\n", + "('SZ000001', 'SZ399619', 20110615, 0)\n", + "('SZ000001', 'SH000980', 20110510, 0)\n", + "('SZ000001', 'SZ399387', 20111202, 0)\n", + "('SZ000001', 'SZ399920', 20100129, 20180611)\n", + "('SZ000001', 'SZ399920', 20200615, 20210615)\n", + "('SZ000001', 'SH000918', 20080121, 20180611)\n", + "('SZ000001', 'SZ399404', 20150520, 20180102)\n", + "('SZ000001', 'SZ399405', 20131205, 20160104)\n", + "('SZ000001', 'SZ399405', 20180102, 20200615)\n", + "('SZ000001', 'SH000919', 20080121, 20200615)\n", + "('SZ000001', 'SZ399405', 20220613, 0)\n", + "('SZ000001', 'SH000919', 20210615, 0)\n", + "('SZ000001', 'SZ399921', 20100129, 0)\n", + "('SZ000001', 'SZ399004', 20030102, 0)\n", + "('SZ000001', 'SZ399925', 20120702, 0)\n", + "('SZ000001', 'SZ399371', 20100104, 20180702)\n", + "('SZ000001', 'SH000803', 20120109, 20130701)\n", + "('SZ000001', 'SH000803', 20141215, 20180611)\n", + "('SZ000001', 'SH000803', 20190617, 20200615)\n", + "('SZ000001', 'SH000803', 20201214, 20211213)\n", + "('SZ000001', 'SH000803', 20220613, 0)\n", + "('SZ000001', 'SZ399007', 20091104, 0)\n", + "('SZ000001', 'SZ399370', 20100701, 20180702)\n", + "('SZ000001', 'SW857831', 20211213, 0)\n", + "('SZ000001', 'SZ399940', 20090925, 0)\n", + "('SZ000001', 'SH000300', 20050408, 0)\n", + "('SZ000001', 'SH000906', 20070115, 0)\n", + "('SZ000001', 'SH000903', 20060529, 20220613)\n", + "('SZ000001', 'SZ399918', 20080121, 20180611)\n", + "('SZ000001', 'SZ399919', 20080121, 20200615)\n", + "('SZ000001', 'SZ399919', 20210615, 0)\n", + "('SZ000001', 'SZ399661', 20121220, 20130701)\n", + "('SZ000001', 'SZ399088', 20200218, 0)\n", + "('SZ000001', 'SH000971', 20101202, 0)\n", + "('SZ000001', 'SZ399701', 20100510, 0)\n", + "('SZ000001', 'SZ399661', 20150105, 20180702)\n", + "('SZ000001', 'SH000842', 20121221, 0)\n", + "('SZ000001', 'SZ399661', 20190102, 0)\n", + "('SZ000001', 'SH000843', 20130701, 20160613)\n", + "('SZ000001', 'SH000844', 20130107, 20130701)\n", + "('SZ000001', 'SZ399314', 20050203, 0)\n", + "('SZ000001', 'SH000844', 20160613, 0)\n", + "('SZ000001', 'SZ399659', 20121123, 0)\n", + "('SZ000001', 'SZ399400', 20130320, 0)\n", + "('SZ000001', 'SH000967', 20100602, 0)\n", + "('SZ000001', 'SZ399630', 20110901, 20180702)\n", + "('SZ000001', 'SW801780', 20140221, 0)\n", + "('SZ000001', 'SW801783', 20211213, 0)\n", + "('SZ000001', 'SH000965', 20100602, 0)\n", + "('SZ000001', 'SZ399980', 20110510, 0)\n", + "('SZ000001', 'SZ399981', 20110613, 0)\n", + "('SZ000001', 'SH000951', 20091028, 0)\n", + "('SZ000001', 'SZ399631', 20110901, 20180702)\n", + "('SZ000001', 'SZ399631', 20191216, 20220613)\n", + "('SZ000001', 'SZ399632', 20111028, 0)\n", + "('SZ000001', 'SZ399633', 20111028, 0)\n", + "('SZ000001', 'SH000829', 20120806, 20130701)\n", + "('SZ000001', 'SH000829', 20160613, 20180611)\n", + "('SZ000001', 'SZ399011', 20110901, 0)\n", + "('SZ000001', 'SH000828', 20130701, 20160613)\n", + "('SZ000001', 'SH000828', 20180611, 20201214)\n", + "('SZ000001', 'SZ399644', 20130201, 0)\n", + "('SZ000001', 'SZ399645', 20120612, 20130701)\n", + "('SZ000001', 'SZ399645', 20140701, 0)\n", + "('SZ000001', 'SZ399656', 20121119, 0)\n", + "('SZ000001', 'SZ399703', 20100510, 0)\n", + "('SZ000001', 'SZ399657', 20121119, 0)\n", + "('SZ000001', 'SH000981', 20110613, 0)\n", + "('SZ000001', 'SZ399300', 20050408, 0)\n", + "('SZ000001', 'SZ399662', 20130701, 20140701)\n", + "('SZ000001', 'SZ399686', 20150831, 0)\n", + "('SZ000001', 'SZ399002', 19950123, 0)\n", + "('SZ000001', 'SW801190', 19910403, 20140221)\n", + "('SZ000001', 'SW801192', 19910403, 20211213)\n", + "('SZ000001', 'SZ399001', 19950123, 0)\n", + "('SZ000001', 'SZ399984', 20110802, 0)\n", + "('SZ000001', 'SZ399431', 20141230, 0)\n", + "('SZ000001', 'SH000920', 20100129, 20180611)\n", + "('SZ000001', 'SZ399985', 20110802, 0)\n", + "('SZ000001', 'SZ399702', 20100510, 0)\n", + "('SZ000001', 'SH000920', 20200615, 20210615)\n", + "('SZ000001', 'SZ399310', 20050905, 0)\n", + "('SZ000001', 'SH000921', 20100129, 0)\n", + "('SZ000001', 'SZ399311', 20050203, 0)\n", + "('SZ000001', 'SZ399372', 20100701, 20180702)\n", + "('SZ000001', 'SZ399373', 20100104, 20180702)\n", + "('SZ000001', 'SH000925', 20120702, 0)\n", + "('SZ000001', 'SW851911', 19910403, 20211213)\n", + "('SZ000001', 'SH000984', 20110802, 0)\n", + "('SZ000001', 'SZ399903', 20060529, 20220613)\n", + "('SZ000001', 'SZ399312', 20050203, 0)\n", + "('SZ000001', 'SH000985', 20110802, 0)\n", + "('SZ000001', 'SZ399313', 20050104, 0)\n", + "('SZ000001', 'SZ399330', 20030102, 0)\n", + "('SZ000001', 'SZ399986', 20130715, 0)\n", + "('SZ000001', 'SZ399348', 20091104, 20220613)\n", + "('SZ000001', 'SZ399344', 20091104, 0)\n", + "('SZ000001', 'SZ399906', 20070115, 0)\n", + "('SZ000001', 'SZ399345', 20100701, 0)\n", + "('SZ000001', 'SZ399346', 20100701, 20170103)\n", + "('SZ000001', 'SZ399347', 20091104, 0)\n", + " SH000009 SH000010 SH000015 SH000016 SH000020 \\\n", + "code m_nDate \n", + "000001.SZ 2013-01-04 0 0 0 0 0 \n", + " 2013-01-07 0 0 0 0 0 \n", + " 2013-01-08 0 0 0 0 0 \n", + " 2013-01-09 0 0 0 0 0 \n", + " 2013-01-10 0 0 0 0 0 \n", + "... ... ... ... ... ... \n", + " 2022-07-04 0 0 0 0 0 \n", + " 2022-07-05 0 0 0 0 0 \n", + " 2022-07-06 0 0 0 0 0 \n", + " 2022-07-07 0 0 0 0 0 \n", + " 2022-07-08 0 0 0 0 0 \n", + "\n", + " SH000028 SH000029 SH000030 SH000031 SH000032 ... \\\n", + "code m_nDate ... \n", + "000001.SZ 2013-01-04 0 0 0 0 0 ... \n", + " 2013-01-07 0 0 0 0 0 ... \n", + " 2013-01-08 0 0 0 0 0 ... \n", + " 2013-01-09 0 0 0 0 0 ... \n", + " 2013-01-10 0 0 0 0 0 ... \n", + "... ... ... ... ... ... ... \n", + " 2022-07-04 0 0 0 0 0 ... \n", + " 2022-07-05 0 0 0 0 0 ... \n", + " 2022-07-06 0 0 0 0 0 ... \n", + " 2022-07-07 0 0 0 0 0 ... \n", + " 2022-07-08 0 0 0 0 0 ... \n", + "\n", + " SZ399980 SZ399981 SZ399982 SZ399983 SZ399984 \\\n", + "code m_nDate \n", + "000001.SZ 2013-01-04 1 1 0 0 1 \n", + " 2013-01-07 1 1 0 0 1 \n", + " 2013-01-08 1 1 0 0 1 \n", + " 2013-01-09 1 1 0 0 1 \n", + " 2013-01-10 1 1 0 0 1 \n", + "... ... ... ... ... ... \n", + " 2022-07-04 1 1 0 0 1 \n", + " 2022-07-05 1 1 0 0 1 \n", + " 2022-07-06 1 1 0 0 1 \n", + " 2022-07-07 1 1 0 0 1 \n", + " 2022-07-08 1 1 0 0 1 \n", + "\n", + " SZ399985 SZ399986 SZ399990 SZ399995 SZ399998 \n", + "code m_nDate \n", + "000001.SZ 2013-01-04 1 0 0 0 0 \n", + " 2013-01-07 1 0 0 0 0 \n", + " 2013-01-08 1 0 0 0 0 \n", + " 2013-01-09 1 0 0 0 0 \n", + " 2013-01-10 1 0 0 0 0 \n", + "... ... ... ... ... ... \n", + " 2022-07-04 1 1 0 0 0 \n", + " 2022-07-05 1 1 0 0 0 \n", + " 2022-07-06 1 1 0 0 0 \n", + " 2022-07-07 1 1 0 0 0 \n", + " 2022-07-08 1 1 0 0 0 \n", + "\n", + "[2309 rows x 949 columns]\n" + ] + } + ], + "source": [ + "for df in _make_stock2concept_onehot():\n", + " print(df)\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "0d307d4f-e202-4246-871b-dc5d8e9252a7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "000001.SZ SZ000001\n", + "\n", + " select \n", + " SecId, IndexID, EnterDate, ExitDate \n", + " from \n", + " [IndexInfo].[dbo].[Constituents] \n", + " where \n", + " SecID='SZ000001'\n", + " \n", + "('SZ000001', 'SH000940', 20090925, 0)\n", + "('SZ000001', 'SZ399619', 20110615, 0)\n", + "('SZ000001', 'SH000980', 20110510, 0)\n", + "('SZ000001', 'SZ399387', 20111202, 0)\n", + "('SZ000001', 'SZ399920', 20100129, 20180611)\n", + "('SZ000001', 'SZ399920', 20200615, 20210615)\n", + "('SZ000001', 'SH000918', 20080121, 20180611)\n", + "('SZ000001', 'SZ399404', 20150520, 20180102)\n", + "('SZ000001', 'SZ399405', 20131205, 20160104)\n", + "('SZ000001', 'SZ399405', 20180102, 20200615)\n", + "('SZ000001', 'SH000919', 20080121, 20200615)\n", + "('SZ000001', 'SZ399405', 20220613, 0)\n", + "('SZ000001', 'SH000919', 20210615, 0)\n", + "('SZ000001', 'SZ399921', 20100129, 0)\n", + "('SZ000001', 'SZ399004', 20030102, 0)\n", + "('SZ000001', 'SZ399925', 20120702, 0)\n", + "('SZ000001', 'SZ399371', 20100104, 20180702)\n", + "('SZ000001', 'SH000803', 20120109, 20130701)\n", + "('SZ000001', 'SH000803', 20141215, 20180611)\n", + "('SZ000001', 'SH000803', 20190617, 20200615)\n", + "('SZ000001', 'SH000803', 20201214, 20211213)\n", + "('SZ000001', 'SH000803', 20220613, 0)\n", + "('SZ000001', 'SZ399007', 20091104, 0)\n", + "('SZ000001', 'SZ399370', 20100701, 20180702)\n", + "('SZ000001', 'SW857831', 20211213, 0)\n", + "('SZ000001', 'SZ399940', 20090925, 0)\n", + "('SZ000001', 'SH000300', 20050408, 0)\n", + "('SZ000001', 'SH000906', 20070115, 0)\n", + "('SZ000001', 'SH000903', 20060529, 20220613)\n", + "('SZ000001', 'SZ399918', 20080121, 20180611)\n", + "('SZ000001', 'SZ399919', 20080121, 20200615)\n", + "('SZ000001', 'SZ399919', 20210615, 0)\n", + "('SZ000001', 'SZ399661', 20121220, 20130701)\n", + "('SZ000001', 'SZ399088', 20200218, 0)\n", + "('SZ000001', 'SH000971', 20101202, 0)\n", + "('SZ000001', 'SZ399701', 20100510, 0)\n", + "('SZ000001', 'SZ399661', 20150105, 20180702)\n", + "('SZ000001', 'SH000842', 20121221, 0)\n", + "('SZ000001', 'SZ399661', 20190102, 0)\n", + "('SZ000001', 'SH000843', 20130701, 20160613)\n", + "('SZ000001', 'SH000844', 20130107, 20130701)\n", + "('SZ000001', 'SZ399314', 20050203, 0)\n", + "('SZ000001', 'SH000844', 20160613, 0)\n", + "('SZ000001', 'SZ399659', 20121123, 0)\n", + "('SZ000001', 'SZ399400', 20130320, 0)\n", + "('SZ000001', 'SH000967', 20100602, 0)\n", + "('SZ000001', 'SZ399630', 20110901, 20180702)\n", + "('SZ000001', 'SW801780', 20140221, 0)\n", + "('SZ000001', 'SW801783', 20211213, 0)\n", + "('SZ000001', 'SH000965', 20100602, 0)\n", + "('SZ000001', 'SZ399980', 20110510, 0)\n", + "('SZ000001', 'SZ399981', 20110613, 0)\n", + "('SZ000001', 'SH000951', 20091028, 0)\n", + "('SZ000001', 'SZ399631', 20110901, 20180702)\n", + "('SZ000001', 'SZ399631', 20191216, 20220613)\n", + "('SZ000001', 'SZ399632', 20111028, 0)\n", + "('SZ000001', 'SZ399633', 20111028, 0)\n", + "('SZ000001', 'SH000829', 20120806, 20130701)\n", + "('SZ000001', 'SH000829', 20160613, 20180611)\n", + "('SZ000001', 'SZ399011', 20110901, 0)\n", + "('SZ000001', 'SH000828', 20130701, 20160613)\n", + "('SZ000001', 'SH000828', 20180611, 20201214)\n", + "('SZ000001', 'SZ399644', 20130201, 0)\n", + "('SZ000001', 'SZ399645', 20120612, 20130701)\n", + "('SZ000001', 'SZ399645', 20140701, 0)\n", + "('SZ000001', 'SZ399656', 20121119, 0)\n", + "('SZ000001', 'SZ399703', 20100510, 0)\n", + "('SZ000001', 'SZ399657', 20121119, 0)\n", + "('SZ000001', 'SH000981', 20110613, 0)\n", + "('SZ000001', 'SZ399300', 20050408, 0)\n", + "('SZ000001', 'SZ399662', 20130701, 20140701)\n", + "('SZ000001', 'SZ399686', 20150831, 0)\n", + "('SZ000001', 'SZ399002', 19950123, 0)\n", + "('SZ000001', 'SW801190', 19910403, 20140221)\n", + "('SZ000001', 'SW801192', 19910403, 20211213)\n", + "('SZ000001', 'SZ399001', 19950123, 0)\n", + "('SZ000001', 'SZ399984', 20110802, 0)\n", + "('SZ000001', 'SZ399431', 20141230, 0)\n", + "('SZ000001', 'SH000920', 20100129, 20180611)\n", + "('SZ000001', 'SZ399985', 20110802, 0)\n", + "('SZ000001', 'SZ399702', 20100510, 0)\n", + "('SZ000001', 'SH000920', 20200615, 20210615)\n", + "('SZ000001', 'SZ399310', 20050905, 0)\n", + "('SZ000001', 'SH000921', 20100129, 0)\n", + "('SZ000001', 'SZ399311', 20050203, 0)\n", + "('SZ000001', 'SZ399372', 20100701, 20180702)\n", + "('SZ000001', 'SZ399373', 20100104, 20180702)\n", + "('SZ000001', 'SH000925', 20120702, 0)\n", + "('SZ000001', 'SW851911', 19910403, 20211213)\n", + "('SZ000001', 'SH000984', 20110802, 0)\n", + "('SZ000001', 'SZ399903', 20060529, 20220613)\n", + "('SZ000001', 'SZ399312', 20050203, 0)\n", + "('SZ000001', 'SH000985', 20110802, 0)\n", + "('SZ000001', 'SZ399313', 20050104, 0)\n", + "('SZ000001', 'SZ399330', 20030102, 0)\n", + "('SZ000001', 'SZ399986', 20130715, 0)\n", + "('SZ000001', 'SZ399348', 20091104, 20220613)\n", + "('SZ000001', 'SZ399344', 20091104, 0)\n", + "('SZ000001', 'SZ399906', 20070115, 0)\n", + "('SZ000001', 'SZ399345', 20100701, 0)\n", + "('SZ000001', 'SZ399346', 20100701, 20170103)\n", + "('SZ000001', 'SZ399347', 20091104, 0)\n" + ] + } + ], + "source": [ + "stock2concept = _make_stock2concept_onehot('000001.SZ')" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "dbc2211d-75ec-4642-a686-ef5cd569afd6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "code m_nDate \n", + "000001.SZ 2013-01-04 1\n", + " 2013-01-07 1\n", + " 2013-01-08 1\n", + " 2013-01-09 1\n", + " 2013-01-10 1\n", + " ..\n", + " 2022-07-04 0\n", + " 2022-07-05 0\n", + " 2022-07-06 0\n", + " 2022-07-07 0\n", + " 2022-07-08 0\n", + "Name: SZ399920, Length: 2309, dtype: int64" + ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stock2concept['SZ399920']" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "51dd0b40-ad19-4e82-80ac-1af35042e8b2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateSH000009SH000010SH000015SH000016SH000020SH000028SH000029SH000030...SZ399980SZ399981SZ399982SZ399983SZ399984SZ399985SZ399986SZ399990SZ399995SZ399998
0600000.SH2006-01-04FalseTrueFalseTrueFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
1600000.SH2006-01-05FalseTrueFalseTrueFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
2600000.SH2006-01-06FalseTrueFalseTrueFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
3600000.SH2006-01-09FalseTrueFalseTrueFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
4600000.SH2006-01-10FalseTrueFalseTrueFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
..................................................................
3932600000.SH2022-08-04FalseTrueFalseFalseFalseFalseTrueFalse...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
3933600000.SH2022-08-05FalseTrueFalseFalseFalseFalseTrueFalse...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
3934600000.SH2022-08-08FalseTrueFalseFalseFalseFalseTrueFalse...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
3935600000.SH2022-08-09FalseTrueFalseFalseFalseFalseTrueFalse...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
3936600000.SH2022-08-10FalseTrueFalseFalseFalseFalseTrueFalse...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
\n", + "

3937 rows × 951 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate SH000009 SH000010 SH000015 SH000016 SH000020 \\\n", + "0 600000.SH 2006-01-04 False True False True False \n", + "1 600000.SH 2006-01-05 False True False True False \n", + "2 600000.SH 2006-01-06 False True False True False \n", + "3 600000.SH 2006-01-09 False True False True False \n", + "4 600000.SH 2006-01-10 False True False True False \n", + "... ... ... ... ... ... ... ... \n", + "3932 600000.SH 2022-08-04 False True False False False \n", + "3933 600000.SH 2022-08-05 False True False False False \n", + "3934 600000.SH 2022-08-08 False True False False False \n", + "3935 600000.SH 2022-08-09 False True False False False \n", + "3936 600000.SH 2022-08-10 False True False False False \n", + "\n", + " SH000028 SH000029 SH000030 ... SZ399980 SZ399981 SZ399982 \\\n", + "0 False False False ... False False False \n", + "1 False False False ... False False False \n", + "2 False False False ... False False False \n", + "3 False False False ... False False False \n", + "4 False False False ... False False False \n", + "... ... ... ... ... ... ... ... \n", + "3932 False True False ... True True False \n", + "3933 False True False ... True True False \n", + "3934 False True False ... True True False \n", + "3935 False True False ... True True False \n", + "3936 False True False ... True True False \n", + "\n", + " SZ399983 SZ399984 SZ399985 SZ399986 SZ399990 SZ399995 SZ399998 \n", + "0 False False False False False False False \n", + "1 False False False False False False False \n", + "2 False False False False False False False \n", + "3 False False False False False False False \n", + "4 False False False False False False False \n", + "... ... ... ... ... ... ... ... \n", + "3932 False True True True False False False \n", + "3933 False True True True False False False \n", + "3934 False True True True False False False \n", + "3935 False True True True False False False \n", + "3936 False True True True False False False \n", + "\n", + "[3937 rows x 951 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('192.168.1.7', 8848)\n", + "sess.login('admin', '123456')\n", + "\n", + "sess.run(\"\"\"\n", + " select * from loadTable(\"dfs://daily_stock_ts\", \"idx_daily_concept\") where code='600000.SH' order by m_nDate asc\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b1fe53e6-ad7f-42fb-a7ce-5c304d88ec1b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateIsZtIsDtIsSTIsGoDelistFloatSharesMarketValues
0000400.SZ2006-01-0400002.566080e+081.224020e+09
1000400.SZ2006-01-0500002.566080e+081.241983e+09
2000400.SZ2006-01-0600002.566080e+081.234284e+09
3000400.SZ2006-01-0900002.566080e+081.277908e+09
4000400.SZ2006-01-1000002.566080e+081.285606e+09
...........................
7718600000.SH2022-08-0400002.935217e+102.081069e+11
7719600000.SH2022-08-0500002.935217e+102.098680e+11
7720600000.SH2022-08-0800002.935217e+102.089875e+11
7721600000.SH2022-08-0900002.935217e+102.089875e+11
7722600000.SH2022-08-1000002.935217e+102.081069e+11
\n", + "

7723 rows × 8 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate IsZt IsDt IsST IsGoDelist FloatShares \\\n", + "0 000400.SZ 2006-01-04 0 0 0 0 2.566080e+08 \n", + "1 000400.SZ 2006-01-05 0 0 0 0 2.566080e+08 \n", + "2 000400.SZ 2006-01-06 0 0 0 0 2.566080e+08 \n", + "3 000400.SZ 2006-01-09 0 0 0 0 2.566080e+08 \n", + "4 000400.SZ 2006-01-10 0 0 0 0 2.566080e+08 \n", + "... ... ... ... ... ... ... ... \n", + "7718 600000.SH 2022-08-04 0 0 0 0 2.935217e+10 \n", + "7719 600000.SH 2022-08-05 0 0 0 0 2.935217e+10 \n", + "7720 600000.SH 2022-08-08 0 0 0 0 2.935217e+10 \n", + "7721 600000.SH 2022-08-09 0 0 0 0 2.935217e+10 \n", + "7722 600000.SH 2022-08-10 0 0 0 0 2.935217e+10 \n", + "\n", + " MarketValues \n", + "0 1.224020e+09 \n", + "1 1.241983e+09 \n", + "2 1.234284e+09 \n", + "3 1.277908e+09 \n", + "4 1.285606e+09 \n", + "... ... \n", + "7718 2.081069e+11 \n", + "7719 2.098680e+11 \n", + "7720 2.089875e+11 \n", + "7721 2.089875e+11 \n", + "7722 2.081069e+11 \n", + "\n", + "[7723 rows x 8 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')\n", + "\n", + "sess.run(\"\"\"\n", + " select code, m_nDate, IsZt, IsDt, IsST, IsGoDelist, FloatShares, MarketValues \n", + " from loadTable('dfs://daily_stock_ts', 'daily_kline')\n", + " where code in (\"600000.SH\", \"000400.SZ\")\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "id": "d6831dd2-75b7-41db-9f87-3e9df85a8699", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDate
0600000.SH2013-01-04
1600000.SH2013-01-05
2600000.SH2013-01-06
3600000.SH2013-01-07
4600000.SH2013-01-08
.........
719600004.SH2013-12-27
720600004.SH2013-12-28
721600004.SH2013-12-29
722600004.SH2013-12-30
723600004.SH2013-12-31
\n", + "

724 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate\n", + "0 600000.SH 2013-01-04\n", + "1 600000.SH 2013-01-05\n", + "2 600000.SH 2013-01-06\n", + "3 600000.SH 2013-01-07\n", + "4 600000.SH 2013-01-08\n", + ".. ... ...\n", + "719 600004.SH 2013-12-27\n", + "720 600004.SH 2013-12-28\n", + "721 600004.SH 2013-12-29\n", + "722 600004.SH 2013-12-30\n", + "723 600004.SH 2013-12-31\n", + "\n", + "[724 rows x 2 columns]" + ] + }, + "execution_count": 145, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')\n", + "\n", + "sess.run(\"\"\"\n", + " tbl = table(100:0, `code`m_nDate, [SYMBOL, DATE])\n", + " \n", + " m_nDate = 2013.01.04..2013.12.31;\n", + " code = take('600000.SH', size(m_nDate));\n", + " tbl.append!(table(code, m_nDate));\n", + " \n", + " m_nDate = 2013.01.04..2013.12.31;\n", + " code = take('600004.SH', size(m_nDate));\n", + " tbl.append!(table(code, m_nDate));\n", + " \n", + " tbl;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "616c7cd3-7871-43c6-b619-f7137fc6556e", + "metadata": {}, + "outputs": [], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a98da4c3-cf3c-4429-b51f-dba8a1f4d2d3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
code
0000400.SZ
1000515.SZ
2000558.SZ
3000602.SZ
4000677.SZ
......
5010688272.SH
5011688320.SH
5012688739.SH
5013688777.SH
5014830964.NE
\n", + "

5015 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " code\n", + "0 000400.SZ\n", + "1 000515.SZ\n", + "2 000558.SZ\n", + "3 000602.SZ\n", + "4 000677.SZ\n", + "... ...\n", + "5010 688272.SH\n", + "5011 688320.SH\n", + "5012 688739.SH\n", + "5013 688777.SH\n", + "5014 830964.NE\n", + "\n", + "[5015 rows x 1 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = sess.run(\"\"\"\n", + " select code from loadTable('dfs://daily_stock_ts', 'idx_daily_concept') group by code\n", + "\"\"\")\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1743a25d-c627-42b4-b6da-b250884a2252", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codestock_id
0000400.SZ0
1000515.SZ1
2000558.SZ2
3000602.SZ3
4000677.SZ4
.........
5010688272.SH5010
5011688320.SH5011
5012688739.SH5012
5013688777.SH5013
5014830964.NE5014
\n", + "

5015 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " code stock_id\n", + "0 000400.SZ 0\n", + "1 000515.SZ 1\n", + "2 000558.SZ 2\n", + "3 000602.SZ 3\n", + "4 000677.SZ 4\n", + "... ... ...\n", + "5010 688272.SH 5010\n", + "5011 688320.SH 5011\n", + "5012 688739.SH 5012\n", + "5013 688777.SH 5013\n", + "5014 830964.NE 5014\n", + "\n", + "[5015 rows x 2 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"stock_id\"] = df.index\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "31f2b644-e4b8-4c96-be54-edc7367370de", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codestock_id
0000400.SZ0
1000515.SZ1
2000558.SZ2
3000602.SZ3
4000677.SZ4
.........
5010688272.SH5010
5011688320.SH5011
5012688739.SH5012
5013688777.SH5013
5014830964.NE5014
\n", + "

5015 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " code stock_id\n", + "0 000400.SZ 0\n", + "1 000515.SZ 1\n", + "2 000558.SZ 2\n", + "3 000602.SZ 3\n", + "4 000677.SZ 4\n", + "... ... ...\n", + "5010 688272.SH 5010\n", + "5011 688320.SH 5011\n", + "5012 688739.SH 5012\n", + "5013 688777.SH 5013\n", + "5014 830964.NE 5014\n", + "\n", + "[5015 rows x 2 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3a249c9-879d-4387-9045-27fe72a38cf3", + "metadata": {}, + "outputs": [], + "source": [ + "sess.run(\"\"\"\n", + " cumsum(select * from loadTable('dfs://daily_stock_ts', 'idx_daily_concept') where code in (\"600000.SH\", \"000400.SZ\", \"600001.SH\") context by code)\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "1c606584-6765-41cd-9487-984e1f2c4bff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cumsum_SH000016codem_nDateSH000009SH000010SH000015SH000016SH000020SH000028SH000029...SZ399980SZ399981SZ399982SZ399983SZ399984SZ399985SZ399986SZ399990SZ399995SZ399998
00000400.SZ2006-01-04FalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
10000400.SZ2006-01-05FalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
20000400.SZ2006-01-06FalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
30000400.SZ2006-01-09FalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
40000400.SZ2006-01-10FalseFalseFalseFalseFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
..................................................................
8569645600001.SH2009-12-09FalseTrueTrueFalseFalseFalseTrue...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
8570645600001.SH2009-12-10FalseTrueTrueFalseFalseFalseTrue...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
8571645600001.SH2009-12-11FalseTrueTrueFalseFalseFalseTrue...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
8572645600001.SH2009-12-14FalseTrueTrueFalseFalseFalseTrue...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
8573645600001.SH2009-12-15FalseTrueTrueFalseFalseFalseTrue...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
\n", + "

8574 rows × 952 columns

\n", + "
" + ], + "text/plain": [ + " cumsum_SH000016 code m_nDate SH000009 SH000010 SH000015 \\\n", + "0 0 000400.SZ 2006-01-04 False False False \n", + "1 0 000400.SZ 2006-01-05 False False False \n", + "2 0 000400.SZ 2006-01-06 False False False \n", + "3 0 000400.SZ 2006-01-09 False False False \n", + "4 0 000400.SZ 2006-01-10 False False False \n", + "... ... ... ... ... ... ... \n", + "8569 645 600001.SH 2009-12-09 False True True \n", + "8570 645 600001.SH 2009-12-10 False True True \n", + "8571 645 600001.SH 2009-12-11 False True True \n", + "8572 645 600001.SH 2009-12-14 False True True \n", + "8573 645 600001.SH 2009-12-15 False True True \n", + "\n", + " SH000016 SH000020 SH000028 SH000029 ... SZ399980 SZ399981 \\\n", + "0 False False False False ... False False \n", + "1 False False False False ... False False \n", + "2 False False False False ... False False \n", + "3 False False False False ... False False \n", + "4 False False False False ... False False \n", + "... ... ... ... ... ... ... ... \n", + "8569 False False False True ... False False \n", + "8570 False False False True ... False False \n", + "8571 False False False True ... False False \n", + "8572 False False False True ... False False \n", + "8573 False False False True ... False False \n", + "\n", + " SZ399982 SZ399983 SZ399984 SZ399985 SZ399986 SZ399990 SZ399995 \\\n", + "0 False False False False False False False \n", + "1 False False False False False False False \n", + "2 False False False False False False False \n", + "3 False False False False False False False \n", + "4 False False False False False False False \n", + "... ... ... ... ... ... ... ... \n", + "8569 False False False False False False False \n", + "8570 False False False False False False False \n", + "8571 False False False False False False False \n", + "8572 False False False False False False False \n", + "8573 False False False False False False False \n", + "\n", + " SZ399998 \n", + "0 False \n", + "1 False \n", + "2 False \n", + "3 False \n", + "4 False \n", + "... ... \n", + "8569 False \n", + "8570 False \n", + "8571 False \n", + "8572 False \n", + "8573 False \n", + "\n", + "[8574 rows x 952 columns]" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "sess.run(\"\"\"\n", + " tbl = select cumsum(SH000016), * from loadTable('dfs://daily_stock_ts', 'idx_daily_concept') where code in (\"600000.SH\", \"000400.SZ\", \"600001.SH\",) context by code;\n", + " tbl;\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "5d51ac5d-b17f-4105-85b8-63e3a0c4e962", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cumsum_SH000016codem_nDateSH000009SH000010SH000015SH000016SH000020SH000028SH000029...SZ399980SZ399981SZ399982SZ399983SZ399984SZ399985SZ399986SZ399990SZ399995SZ399998
01600000.SH2006-01-04FalseTrueFalseTrueFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
12600000.SH2006-01-05FalseTrueFalseTrueFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
23600000.SH2006-01-06FalseTrueFalseTrueFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
34600000.SH2006-01-09FalseTrueFalseTrueFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
45600000.SH2006-01-10FalseTrueFalseTrueFalseFalseFalse...FalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
..................................................................
39323895600000.SH2022-08-04FalseTrueFalseFalseFalseFalseTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
39333895600000.SH2022-08-05FalseTrueFalseFalseFalseFalseTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
39343895600000.SH2022-08-08FalseTrueFalseFalseFalseFalseTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
39353895600000.SH2022-08-09FalseTrueFalseFalseFalseFalseTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
39363895600000.SH2022-08-10FalseTrueFalseFalseFalseFalseTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
\n", + "

3937 rows × 952 columns

\n", + "
" + ], + "text/plain": [ + " cumsum_SH000016 code m_nDate SH000009 SH000010 SH000015 \\\n", + "0 1 600000.SH 2006-01-04 False True False \n", + "1 2 600000.SH 2006-01-05 False True False \n", + "2 3 600000.SH 2006-01-06 False True False \n", + "3 4 600000.SH 2006-01-09 False True False \n", + "4 5 600000.SH 2006-01-10 False True False \n", + "... ... ... ... ... ... ... \n", + "3932 3895 600000.SH 2022-08-04 False True False \n", + "3933 3895 600000.SH 2022-08-05 False True False \n", + "3934 3895 600000.SH 2022-08-08 False True False \n", + "3935 3895 600000.SH 2022-08-09 False True False \n", + "3936 3895 600000.SH 2022-08-10 False True False \n", + "\n", + " SH000016 SH000020 SH000028 SH000029 ... SZ399980 SZ399981 \\\n", + "0 True False False False ... False False \n", + "1 True False False False ... False False \n", + "2 True False False False ... False False \n", + "3 True False False False ... False False \n", + "4 True False False False ... False False \n", + "... ... ... ... ... ... ... ... \n", + "3932 False False False True ... True True \n", + "3933 False False False True ... True True \n", + "3934 False False False True ... True True \n", + "3935 False False False True ... True True \n", + "3936 False False False True ... True True \n", + "\n", + " SZ399982 SZ399983 SZ399984 SZ399985 SZ399986 SZ399990 SZ399995 \\\n", + "0 False False False False False False False \n", + "1 False False False False False False False \n", + "2 False False False False False False False \n", + "3 False False False False False False False \n", + "4 False False False False False False False \n", + "... ... ... ... ... ... ... ... \n", + "3932 False False True True True False False \n", + "3933 False False True True True False False \n", + "3934 False False True True True False False \n", + "3935 False False True True True False False \n", + "3936 False False True True True False False \n", + "\n", + " SZ399998 \n", + "0 False \n", + "1 False \n", + "2 False \n", + "3 False \n", + "4 False \n", + "... ... \n", + "3932 False \n", + "3933 False \n", + "3934 False \n", + "3935 False \n", + "3936 False \n", + "\n", + "[3937 rows x 952 columns]" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " select * from tbl where code='600000.SH'\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "6ef3d70e-b8a3-4a17-91bd-2dc4a37a993f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateSH000009SH000010SH000015SH000016SH000020SH000028SH000029SH000030...SZ399980SZ399981SZ399982SZ399983SZ399984SZ399985SZ399986SZ399990SZ399995SZ399998
0600000.SH2006-01-0401010000...0000000000
1600000.SH2006-01-0502020000...0000000000
2600000.SH2006-01-0603030000...0000000000
3600000.SH2006-01-0904040000...0000000000
4600000.SH2006-01-1005050000...0000000000
..................................................................
3932600000.SH2022-08-040393394238950297331282973...2701267800264226422174000
3933600000.SH2022-08-050393494238950297331292973...2702267900264326432175000
3934600000.SH2022-08-080393594238950297331302973...2703268000264426442176000
3935600000.SH2022-08-090393694238950297331312973...2704268100264526452177000
3936600000.SH2022-08-100393794238950297331322973...2705268200264626462178000
\n", + "

3937 rows × 951 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate SH000009 SH000010 SH000015 SH000016 SH000020 \\\n", + "0 600000.SH 2006-01-04 0 1 0 1 0 \n", + "1 600000.SH 2006-01-05 0 2 0 2 0 \n", + "2 600000.SH 2006-01-06 0 3 0 3 0 \n", + "3 600000.SH 2006-01-09 0 4 0 4 0 \n", + "4 600000.SH 2006-01-10 0 5 0 5 0 \n", + "... ... ... ... ... ... ... ... \n", + "3932 600000.SH 2022-08-04 0 3933 942 3895 0 \n", + "3933 600000.SH 2022-08-05 0 3934 942 3895 0 \n", + "3934 600000.SH 2022-08-08 0 3935 942 3895 0 \n", + "3935 600000.SH 2022-08-09 0 3936 942 3895 0 \n", + "3936 600000.SH 2022-08-10 0 3937 942 3895 0 \n", + "\n", + " SH000028 SH000029 SH000030 ... SZ399980 SZ399981 SZ399982 \\\n", + "0 0 0 0 ... 0 0 0 \n", + "1 0 0 0 ... 0 0 0 \n", + "2 0 0 0 ... 0 0 0 \n", + "3 0 0 0 ... 0 0 0 \n", + "4 0 0 0 ... 0 0 0 \n", + "... ... ... ... ... ... ... ... \n", + "3932 2973 3128 2973 ... 2701 2678 0 \n", + "3933 2973 3129 2973 ... 2702 2679 0 \n", + "3934 2973 3130 2973 ... 2703 2680 0 \n", + "3935 2973 3131 2973 ... 2704 2681 0 \n", + "3936 2973 3132 2973 ... 2705 2682 0 \n", + "\n", + " SZ399983 SZ399984 SZ399985 SZ399986 SZ399990 SZ399995 SZ399998 \n", + "0 0 0 0 0 0 0 0 \n", + "1 0 0 0 0 0 0 0 \n", + "2 0 0 0 0 0 0 0 \n", + "3 0 0 0 0 0 0 0 \n", + "4 0 0 0 0 0 0 0 \n", + "... ... ... ... ... ... ... ... \n", + "3932 0 2642 2642 2174 0 0 0 \n", + "3933 0 2643 2643 2175 0 0 0 \n", + "3934 0 2644 2644 2176 0 0 0 \n", + "3935 0 2645 2645 2177 0 0 0 \n", + "3936 0 2646 2646 2178 0 0 0 \n", + "\n", + "[3937 rows x 951 columns]" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"\"\"\n", + " cumsum(select * from loadTable('dfs://daily_stock_ts', 'idx_daily_concept') where code in (\"600000.SH\"))\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e5c75dfd-b9e8-4ab1-b0a0-684d96852d32", + "metadata": {}, + "outputs": [], + "source": [ + "df = df[['code', 'm_nDate', 'SH000009', 'SH000010', 'SH000015']]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1242241b-c0dc-4ff8-a84b-ed3877db1acb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SH000009SH000010SH000015
m_nDatecode
2006-01-04000400.SZFalseFalseFalse
2006-01-05000400.SZFalseFalseFalse
2006-01-06000400.SZFalseFalseFalse
2006-01-09000400.SZFalseFalseFalse
2006-01-10000400.SZFalseFalseFalse
...............
2022-08-04600000.SHFalseTrueFalse
2022-08-05600000.SHFalseTrueFalse
2022-08-08600000.SHFalseTrueFalse
2022-08-09600000.SHFalseTrueFalse
2022-08-10600000.SHFalseTrueFalse
\n", + "

7723 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " SH000009 SH000010 SH000015\n", + "m_nDate code \n", + "2006-01-04 000400.SZ False False False\n", + "2006-01-05 000400.SZ False False False\n", + "2006-01-06 000400.SZ False False False\n", + "2006-01-09 000400.SZ False False False\n", + "2006-01-10 000400.SZ False False False\n", + "... ... ... ...\n", + "2022-08-04 600000.SH False True False\n", + "2022-08-05 600000.SH False True False\n", + "2022-08-08 600000.SH False True False\n", + "2022-08-09 600000.SH False True False\n", + "2022-08-10 600000.SH False True False\n", + "\n", + "[7723 rows x 3 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.set_index(['m_nDate', 'code'], inplace=True)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "aedb5cde-bfee-4e38-bbf1-9d8a763a0cd9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4034" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_groups = df.groupby(axis=0, level=\"m_nDate\")\n", + "len(df_groups)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "62de77bd-7c19-49a5-bce4-05989346afd8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DatetimeIndex(['2006-01-04', '2006-01-05', '2006-01-06', '2006-01-09',\n", + " '2006-01-10', '2006-01-11', '2006-01-12', '2006-01-13',\n", + " '2006-01-16', '2006-01-17',\n", + " ...\n", + " '2022-07-28', '2022-07-29', '2022-08-01', '2022-08-02',\n", + " '2022-08-03', '2022-08-04', '2022-08-05', '2022-08-08',\n", + " '2022-08-09', '2022-08-10'],\n", + " dtype='datetime64[ns]', name='m_nDate', length=4034, freq=None)" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "index_datetime = df.index.unique(level=\"m_nDate\").sort_values(ascending=True)\n", + "index_datetime" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "a2e9d3a5-7a78-486c-a726-2070336d5f49", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "m_nDate\n", + "2006-01-04 1.000000\n", + "2006-01-05 1.024547\n", + "2006-01-06 1.049095\n", + "2006-01-09 1.073642\n", + "2006-01-10 1.098190\n", + " ... \n", + "2022-08-04 99.901810\n", + "2022-08-05 99.926358\n", + "2022-08-08 99.950905\n", + "2022-08-09 99.975453\n", + "2022-08-10 100.000000\n", + "Name: weight, Length: 4034, dtype: float64" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "series = pd.Series(np.linspace(1.0, 100.0, len(index_datetime)), index=index_datetime, name=\"weight\")\n", + "series" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "889094a8-06a9-412d-8a45-5412ec507856", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
weight
m_nDatecode
2006-01-04000400.SZ1.000000
600000.SH1.000000
2006-01-05000400.SZ1.024547
600000.SH1.024547
2006-01-06000400.SZ1.049095
.........
2022-08-08600000.SH99.950905
2022-08-09000400.SZ99.975453
600000.SH99.975453
2022-08-10000400.SZ100.000000
600000.SH100.000000
\n", + "

7723 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " weight\n", + "m_nDate code \n", + "2006-01-04 000400.SZ 1.000000\n", + " 600000.SH 1.000000\n", + "2006-01-05 000400.SZ 1.024547\n", + " 600000.SH 1.024547\n", + "2006-01-06 000400.SZ 1.049095\n", + "... ...\n", + "2022-08-08 600000.SH 99.950905\n", + "2022-08-09 000400.SZ 99.975453\n", + " 600000.SH 99.975453\n", + "2022-08-10 000400.SZ 100.000000\n", + " 600000.SH 100.000000\n", + "\n", + "[7723 rows x 1 columns]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df2 = pd.DataFrame(index=df.index, )\n", + "df3 = df2.join(series, on=\"m_nDate\")\n", + "df3.sort_index(level=\"m_nDate\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c62690d3-b263-4c4e-97db-f7d609524f2d", + "metadata": {}, + "outputs": [], + "source": [ + "df3." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "e8386b34-41a3-42fe-a36a-d54509f5ccb1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
0
(2006-01-04 00:00:00, 000400.SZ)NaN
(2006-01-05 00:00:00, 000400.SZ)NaN
(2006-01-06 00:00:00, 000400.SZ)NaN
(2006-01-09 00:00:00, 000400.SZ)NaN
(2006-01-10 00:00:00, 000400.SZ)NaN
......
137989440000000000099.901810
137998080000000000099.926358
138006720000000000099.950905
138015360000000000099.975453
1380240000000000000100.000000
\n", + "

11757 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " 0\n", + "(2006-01-04 00:00:00, 000400.SZ) NaN\n", + "(2006-01-05 00:00:00, 000400.SZ) NaN\n", + "(2006-01-06 00:00:00, 000400.SZ) NaN\n", + "(2006-01-09 00:00:00, 000400.SZ) NaN\n", + "(2006-01-10 00:00:00, 000400.SZ) NaN\n", + "... ...\n", + "1379894400000000000 99.901810\n", + "1379980800000000000 99.926358\n", + "1380067200000000000 99.950905\n", + "1380153600000000000 99.975453\n", + "1380240000000000000 100.000000\n", + "\n", + "[11757 rows x 1 columns]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.concat([df2, series])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "392da2ae-51e1-41d1-a3f6-044506e1cf63", + "metadata": {}, + "outputs": [], + "source": [ + "dfs = []\n", + "for code, df_sub in df.groupby(level=\"code\"):\n", + " dfs.append((df_sub.index, df_sub.values))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "2fae9b71-0e29-4717-afb6-e3540d06ed67", + "metadata": {}, + "outputs": [], + "source": [ + "index_list, data_list = zip(*dfs)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "910caab8-38ea-4b7d-acc6-b5d0275f46a0", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "index = np.concatenate(index_list)\n", + "data = np.concatenate(data_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "3ea1efee-f719-4b42-a815-83c1e39a6beb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MultiIndex([('2006-01-04', '000400.SZ'),\n", + " ('2006-01-05', '000400.SZ'),\n", + " ('2006-01-06', '000400.SZ'),\n", + " ('2006-01-09', '000400.SZ'),\n", + " ('2006-01-10', '000400.SZ'),\n", + " ('2006-01-11', '000400.SZ'),\n", + " ('2006-01-12', '000400.SZ'),\n", + " ('2006-01-13', '000400.SZ'),\n", + " ('2006-01-16', '000400.SZ'),\n", + " ('2006-01-17', '000400.SZ'),\n", + " ...\n", + " ('2022-07-28', '000400.SZ'),\n", + " ('2022-07-29', '000400.SZ'),\n", + " ('2022-08-01', '000400.SZ'),\n", + " ('2022-08-02', '000400.SZ'),\n", + " ('2022-08-03', '000400.SZ'),\n", + " ('2022-08-04', '000400.SZ'),\n", + " ('2022-08-05', '000400.SZ'),\n", + " ('2022-08-08', '000400.SZ'),\n", + " ('2022-08-09', '000400.SZ'),\n", + " ('2022-08-10', '000400.SZ')],\n", + " names=['m_nDate', 'code'], length=3786)" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "index_list[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "c88aba7b-8069-4d2b-bba4-b6af420c82ba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MultiIndex([('2006-01-04', '000400.SZ'),\n", + " ('2006-01-05', '000400.SZ'),\n", + " ('2006-01-06', '000400.SZ'),\n", + " ('2006-01-09', '000400.SZ'),\n", + " ('2006-01-10', '000400.SZ'),\n", + " ('2006-01-11', '000400.SZ'),\n", + " ('2006-01-12', '000400.SZ'),\n", + " ('2006-01-13', '000400.SZ'),\n", + " ('2006-01-16', '000400.SZ'),\n", + " ('2006-01-17', '000400.SZ'),\n", + " ...\n", + " ('2022-07-28', '600000.SH'),\n", + " ('2022-07-29', '600000.SH'),\n", + " ('2022-08-01', '600000.SH'),\n", + " ('2022-08-02', '600000.SH'),\n", + " ('2022-08-03', '600000.SH'),\n", + " ('2022-08-04', '600000.SH'),\n", + " ('2022-08-05', '600000.SH'),\n", + " ('2022-08-08', '600000.SH'),\n", + " ('2022-08-09', '600000.SH'),\n", + " ('2022-08-10', '600000.SH')],\n", + " names=['datetime', 'instrument'], length=7723)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.MultiIndex.from_tuples(index, names=['datetime', 'instrument'])" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "04129932-e234-403a-b193-997c7d9ad014", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "df2 = pd.DataFrame(data, index=pd.MultiIndex.from_tuples(index, names=['datetime', 'instrument']), columns=df.columns)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "cf85603e-44af-47e0-8c1d-ac1fa2750528", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SH000009SH000010SH000015
datetimeinstrument
2006-01-04000400.SZFalseFalseFalse
2006-01-05000400.SZFalseFalseFalse
2006-01-06000400.SZFalseFalseFalse
2006-01-09000400.SZFalseFalseFalse
2006-01-10000400.SZFalseFalseFalse
...............
2022-08-04600000.SHFalseTrueFalse
2022-08-05600000.SHFalseTrueFalse
2022-08-08600000.SHFalseTrueFalse
2022-08-09600000.SHFalseTrueFalse
2022-08-10600000.SHFalseTrueFalse
\n", + "

7723 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " SH000009 SH000010 SH000015\n", + "datetime instrument \n", + "2006-01-04 000400.SZ False False False\n", + "2006-01-05 000400.SZ False False False\n", + "2006-01-06 000400.SZ False False False\n", + "2006-01-09 000400.SZ False False False\n", + "2006-01-10 000400.SZ False False False\n", + "... ... ... ...\n", + "2022-08-04 600000.SH False True False\n", + "2022-08-05 600000.SH False True False\n", + "2022-08-08 600000.SH False True False\n", + "2022-08-09 600000.SH False True False\n", + "2022-08-10 600000.SH False True False\n", + "\n", + "[7723 rows x 3 columns]" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df2" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "0f5085bb-b70d-4551-a8bd-87aee7696b94", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['SH000009', 'SH000010', 'SH000015'], dtype='object')" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df2.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9e3aa8b8-2c55-45dc-8ab4-9bf255affb61", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SH000009SH000010SH000015
m_nDatecode
2006-01-04000400.SZ000
2006-01-05000400.SZ000
2006-01-06000400.SZ000
2006-01-09000400.SZ000
2006-01-10000400.SZ000
...............
2022-08-04600000.SH03933942
2022-08-05600000.SH03934942
2022-08-08600000.SH03935942
2022-08-09600000.SH03936942
2022-08-10600000.SH03937942
\n", + "

7723 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " SH000009 SH000010 SH000015\n", + "m_nDate code \n", + "2006-01-04 000400.SZ 0 0 0\n", + "2006-01-05 000400.SZ 0 0 0\n", + "2006-01-06 000400.SZ 0 0 0\n", + "2006-01-09 000400.SZ 0 0 0\n", + "2006-01-10 000400.SZ 0 0 0\n", + "... ... ... ...\n", + "2022-08-04 600000.SH 0 3933 942\n", + "2022-08-05 600000.SH 0 3934 942\n", + "2022-08-08 600000.SH 0 3935 942\n", + "2022-08-09 600000.SH 0 3936 942\n", + "2022-08-10 600000.SH 0 3937 942\n", + "\n", + "[7723 rows x 3 columns]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.groupby(axis=0, level='code').apply('cumsum')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e0255168-01e4-43fe-b480-dbd76aeec26f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " SH000009 SH000010 SH000015\n", + "m_nDate code \n", + "2006-01-04 000400.SZ False False False\n", + "2006-01-05 000400.SZ False False False\n", + "2006-01-06 000400.SZ False False False\n", + "2006-01-09 000400.SZ False False False\n", + "2006-01-10 000400.SZ False False False\n", + "\n", + " SH000009 SH000010 SH000015\n", + "m_nDate code \n", + "2006-01-04 600000.SH False True False\n", + "2006-01-05 600000.SH False True False\n", + "2006-01-06 600000.SH False True False\n", + "2006-01-09 600000.SH False True False\n", + "2006-01-10 600000.SH False True False\n", + "\n" + ] + } + ], + "source": [ + "for code, sub_df in .\n", + ".:\n", + " print(sub_df.head())\n", + " sub_df = sub_df.apply('cumsum')\n", + " print(sub_df.head)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5357df6d-12ce-4421-ac81-3356e9c3e708", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 147, + "id": "86761b9b-cd9d-4cba-8b65-ad70c4fe3ab5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDateSH000009SH000010SH000015SH000016SH000020SH000028SH000029SH000030...SZ399980SZ399981SZ399982SZ399983SZ399984SZ399985SZ399986SZ399990SZ399995SZ399998
0600004.SH2013-01-04TrueFalseTrueFalseFalseFalseFalseFalse...FalseFalseTrueFalseFalseTrueFalseFalseFalseFalse
1600004.SH2013-01-07TrueFalseFalseFalseFalseFalseFalseFalse...FalseFalseTrueFalseFalseTrueFalseFalseFalseFalse
2600004.SH2013-01-08TrueFalseFalseFalseFalseFalseFalseFalse...FalseFalseTrueFalseFalseTrueFalseFalseFalseFalse
3600004.SH2013-01-09TrueFalseFalseFalseFalseFalseFalseFalse...FalseFalseTrueFalseFalseTrueFalseFalseFalseFalse
4600004.SH2013-01-10TrueFalseFalseFalseFalseFalseFalseFalse...FalseFalseTrueFalseFalseTrueFalseFalseFalseFalse
..................................................................
471600000.SH2013-12-25FalseTrueTrueTrueFalseTrueTrueTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
472600000.SH2013-12-26FalseTrueTrueTrueFalseTrueTrueTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
473600000.SH2013-12-27FalseTrueTrueTrueFalseTrueTrueTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
474600000.SH2013-12-30FalseTrueTrueTrueFalseTrueTrueTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
475600000.SH2013-12-31FalseTrueTrueTrueFalseTrueTrueTrue...TrueTrueFalseFalseTrueTrueTrueFalseFalseFalse
\n", + "

476 rows × 951 columns

\n", + "
" + ], + "text/plain": [ + " code m_nDate SH000009 SH000010 SH000015 SH000016 SH000020 \\\n", + "0 600004.SH 2013-01-04 True False True False False \n", + "1 600004.SH 2013-01-07 True False False False False \n", + "2 600004.SH 2013-01-08 True False False False False \n", + "3 600004.SH 2013-01-09 True False False False False \n", + "4 600004.SH 2013-01-10 True False False False False \n", + ".. ... ... ... ... ... ... ... \n", + "471 600000.SH 2013-12-25 False True True True False \n", + "472 600000.SH 2013-12-26 False True True True False \n", + "473 600000.SH 2013-12-27 False True True True False \n", + "474 600000.SH 2013-12-30 False True True True False \n", + "475 600000.SH 2013-12-31 False True True True False \n", + "\n", + " SH000028 SH000029 SH000030 ... SZ399980 SZ399981 SZ399982 \\\n", + "0 False False False ... False False True \n", + "1 False False False ... False False True \n", + "2 False False False ... False False True \n", + "3 False False False ... False False True \n", + "4 False False False ... False False True \n", + ".. ... ... ... ... ... ... ... \n", + "471 True True True ... True True False \n", + "472 True True True ... True True False \n", + "473 True True True ... True True False \n", + "474 True True True ... True True False \n", + "475 True True True ... True True False \n", + "\n", + " SZ399983 SZ399984 SZ399985 SZ399986 SZ399990 SZ399995 SZ399998 \n", + "0 False False True False False False False \n", + "1 False False True False False False False \n", + "2 False False True False False False False \n", + "3 False False True False False False False \n", + "4 False False True False False False False \n", + ".. ... ... ... ... ... ... ... \n", + "471 False True True True False False False \n", + "472 False True True True False False False \n", + "473 False True True True False False False \n", + "474 False True True True False False False \n", + "475 False True True True False False False \n", + "\n", + "[476 rows x 951 columns]" + ] + }, + "execution_count": 147, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sess.run(\"select top 1000 * from ej(tbl, loadTable('dfs://daily_stock_ts', 'idx_daily_concept'), `code`m_nDate) map\")" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "id": "a4cd1087-f2e0-491f-92c3-6359c7a5135d", + "metadata": {}, + "outputs": [], + "source": [ + "df = df.set_index(['code', 'm_nDate']).astype('int')" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "id": "7397b95c-a451-4b3a-a8d8-9c99c01180dc", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(32, 32))\n", + "ax = sns.heatmap(df.to_numpy()[:,:], cmap='hot')" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "id": "d2d5e7d0-c84a-49fc-ab22-5c07d28699b8", + "metadata": {}, + "outputs": [], + "source": [ + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "112c1ea9-fa76-418a-ad75-e2191aac85fa", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "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.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/ipynb/mssql.ipynb b/ipynb/mssql.ipynb index a81402d..db7876c 100644 --- a/ipynb/mssql.ipynb +++ b/ipynb/mssql.ipynb @@ -28,16 +28,118 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "with engine.connect() as conn:\n", - " stat = \"select [StockID], [date] from [StockDaily].[dbo].[DailyKLine] group by [StockID], [date]\"\n", - " rs = conn.execute(statd)\n", + " stat = \"select [StockID], [date] from [IndexDaily].[dbo].[DailyKLine] group by [StockID], [date]\"\n", + " rs = conn.execute(stat)\n", " stock_date_list = [(stock_name, date) for stock_name, date in rs.fetchall()]" ] }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "df = pd.DataFrame(stock_date_list, columns=['code', 'm_nDate'])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
codem_nDate
CSI00014020120912
20120913
20120914
20120917
20120918
......
SZ39999520220829
20220830
20220831
20220901
20220902
\n", + "

403101 rows × 0 columns

\n", + "
" + ], + "text/plain": [ + "Empty DataFrame\n", + "Columns: []\n", + "Index: [(CSI000140, 20120912), (CSI000140, 20120913), (CSI000140, 20120914), (CSI000140, 20120917), (CSI000140, 20120918), (CSI000140, 20120919), (CSI000140, 20120920), (CSI000140, 20120921), (CSI000140, 20120924), (CSI000140, 20120925), (CSI000140, 20120926), (CSI000140, 20120927), (CSI000140, 20120928), (CSI000140, 20121008), (CSI000140, 20121009), (CSI000140, 20121010), (CSI000140, 20121011), (CSI000140, 20121012), (CSI000140, 20121015), (CSI000140, 20121016), (CSI000140, 20121017), (CSI000140, 20121018), (CSI000140, 20121019), (CSI000140, 20121022), (CSI000140, 20121023), (CSI000140, 20121024), (CSI000140, 20121025), (CSI000140, 20121026), (CSI000140, 20121029), (CSI000140, 20121030), (CSI000140, 20121031), (CSI000140, 20121101), (CSI000140, 20121102), (CSI000140, 20121105), (CSI000140, 20121106), (CSI000140, 20121107), (CSI000140, 20121108), (CSI000140, 20121109), (CSI000140, 20121112), (CSI000140, 20121113), (CSI000140, 20121114), (CSI000140, 20121115), (CSI000140, 20121116), (CSI000140, 20121119), (CSI000140, 20121120), (CSI000140, 20121121), (CSI000140, 20121122), (CSI000140, 20121123), (CSI000140, 20121126), (CSI000140, 20121127), (CSI000140, 20121128), (CSI000140, 20121129), (CSI000140, 20121130), (CSI000140, 20121203), (CSI000140, 20121204), (CSI000140, 20121205), (CSI000140, 20121206), (CSI000140, 20121207), (CSI000140, 20121210), (CSI000140, 20121211), (CSI000140, 20121212), (CSI000140, 20121213), (CSI000140, 20121214), (CSI000140, 20121217), (CSI000140, 20121218), (CSI000140, 20121219), (CSI000140, 20121220), (CSI000140, 20121221), (CSI000140, 20121224), (CSI000140, 20121225), (CSI000140, 20121226), (CSI000140, 20121227), (CSI000140, 20121228), (CSI000140, 20121231), (CSI000140, 20130104), (CSI000140, 20130107), (CSI000140, 20130108), (CSI000140, 20130109), (CSI000140, 20130110), (CSI000140, 20130111), (CSI000140, 20130115), (CSI000140, 20130116), (CSI000140, 20130117), (CSI000140, 20130118), (CSI000140, 20130121), (CSI000140, 20130122), (CSI000140, 20130123), (CSI000140, 20130124), (CSI000140, 20130125), (CSI000140, 20130128), (CSI000140, 20130129), (CSI000140, 20130130), (CSI000140, 20130131), (CSI000140, 20130201), (CSI000140, 20130204), (CSI000140, 20130205), (CSI000140, 20130206), (CSI000140, 20130207), (CSI000140, 20130208), (CSI000140, 20130218), ...]\n", + "\n", + "[403101 rows x 0 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.set_index(['code', 'm_nDate']).sort_index()" + ] + }, { "cell_type": "code", "execution_count": 6, diff --git a/ipynb/未命名.ipynb b/ipynb/未命名.ipynb new file mode 100644 index 0000000..3c63623 --- /dev/null +++ b/ipynb/未命名.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "118641f9-96c3-4fd3-aea2-7ecdae17492e", + "metadata": {}, + "outputs": [], + "source": [ + "import dolphindb as ddb\n", + "\n", + "sess = ddb.session('localhost', 8848)\n", + "sess.login('admin', '123456')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "44e3d35e-2e84-44fc-a3d2-00eaa0135460", + "metadata": {}, + "outputs": [], + "source": [ + "df = sess.run(\"\"\"\n", + " select code from loadTable(\"dfs://daily_stock_ts\", \"daily_kline\")\n", + " group by code order by code asc\n", + "\"\"\")\n", + "\n", + "df[\"entity_id\"] = df.index\n", + "df.set_index(\"code\", inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "20a6066d-8efb-40fd-8a3b-3d848c8c0073", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
entity_id
code
000001.SZ0
000002.SZ1
000004.SZ2
000005.SZ3
000006.SZ4
......
871970.NE5010
871981.NE5011
872925.NE5012
873169.NE5013
873223.NE5014
\n", + "

5015 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " entity_id\n", + "code \n", + "000001.SZ 0\n", + "000002.SZ 1\n", + "000004.SZ 2\n", + "000005.SZ 3\n", + "000006.SZ 4\n", + "... ...\n", + "871970.NE 5010\n", + "871981.NE 5011\n", + "872925.NE 5012\n", + "873169.NE 5013\n", + "873223.NE 5014\n", + "\n", + "[5015 rows x 1 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc934d77-3cc1-458f-9e28-3f0715e9b87b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "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.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/loader/DDBDailyLoader.py b/src/loader/DDBDailyLoader.py index abdaa8c..cfa6c85 100644 --- a/src/loader/DDBDailyLoader.py +++ b/src/loader/DDBDailyLoader.py @@ -18,8 +18,7 @@ import dolphindb as ddb import dolphindb.settings as keys import sqlalchemy as sa - -import ProtoBuffEntitys +from .DDBLoader import DDBLoader class DDBDailyLoader(DDBLoader): @@ -45,6 +44,8 @@ class DDBDailyLoader(DDBLoader): 'DOUBLE' ] + memory_table_name = 'daily_kline_mem' + partition_table_name = 'daily_kline' def create_ddb_database(self): # TODO: daily数据库已经在DDBDailyFactor中被创建了 @@ -62,7 +63,7 @@ class DDBDailyLoader(DDBLoader): print('Did load database from', self.ddb_path) - def create_ddb_partition_table(self, memory_table_name, partition_table_name): + def create_ddb_partition_table(self): # TODO: 现在只做一个日频行情数据表,今后可能考虑把基本面数据也迁移过来 # 由于日频行情数据的表结构相对简单,所以直接把表结构写在这里代码里即可 @@ -84,37 +85,35 @@ class DDBDailyLoader(DDBLoader): """.format( ddb_daily_path = self.ddb_path, ddb_daily_dbname = self.ddb_dbname, - memory_table_name = memory_table_name, - partition_table_name = partition_table_name, + memory_table_name = self.memory_table_name, + partition_table_name = self.partition_table_name, )) - def create_ddb_memory_table(self, memory_table_name, capacity): + def create_ddb_memory_table(self, capacity): self.ddb_sess.run(""" // 先创建一个空的内存表用来表征结构,如果无需插入数据,capacity可以设为10 {memory_table_name} = table({capacity}:0, {col_names}, [{col_types}]); """.format( - memory_table_name = memory_table_name, + memory_table_name = self.memory_table_name, capacity = capacity, col_names = '`' + '`'.join(self.daily_kline_cols), col_types = ', '.join(self.daily_kline_col_types) )) - def dump_daily_kline_to_ddb(self): + def dump_to_ddb(self): # 先创建一个分区表,然后再逐个股票的数据插入 # 1. 需要额外控制在插入第一个股票数据的时候创建分区表比较麻烦 # 2. python程序中的dataframe直接上传到dolphindb内存表,不需要考虑内存表字段类型,分区表中设置好即可 - memory_table_name = 'daily_kline_mem' - partition_table_name = 'daily_kline' - self.create_ddb_memory_table(memory_table_name, 10) + self.create_ddb_memory_table(10) print('Did create ddb memory table.') - pprint(self.ddb_sess.run(f"schema({memory_table_name})")) - self.create_ddb_partition_table(memory_table_name, partition_table_name) + pprint(self.ddb_sess.run(f"schema({self.memory_table_name})")) + self.create_ddb_partition_table() print('Did create ddb partition table.') - pprint(self.ddb_sess.run(f"schema({partition_table_name})")) + pprint(self.ddb_sess.run(f"schema({self.partition_table_name})")) with self.mssql_engine.connect() as conn: stat = "select distinct [StockID] from [StockDaily].dbo.[DailyKLine]" @@ -137,24 +136,133 @@ class DDBDailyLoader(DDBLoader): df = pd.DataFrame(row_list) df['date'] = DDBLoader.make_date(df['date']) df['StockID'] = DDBLoader.tscode_to_windcode(df['StockID']) - self.ddb_sess.upload({memory_table_name : df}) + self.ddb_sess.upload({self.memory_table_name : df}) #print('Did upload dataframe to ddb.') - #pprint(self.ddb_sess.run(f"schema({memory_table_name})")) + #pprint(self.ddb_sess.run(f"schema({self.memory_table_name})")) #break - self.ddb_sess.run(f"{partition_table_name}.tableInsert({memory_table_name})") + self.ddb_sess.run(f"{self.partition_table_name}.tableInsert({self.memory_table_name})") + + +class DDBDailyFactorLoader(DDBDailyLoader): + + daily_kline_cols = [ + 'code', 'm_nDate', + # 4种量价配合的因子 + 'trend_with_turnover', 'trend_with_amount', + "abs_trend_with_turnover", "abs_trend_with_amount", + # Alpha101中,量价背离的因子 + "alpha101_22" + ] + + daily_kline_col_types = [ + 'SYMBOL', 'DATE', + 'DOUBLE', 'DOUBLE', + 'DOUBLE', 'DOUBLE', + 'DOUBLE' + ] + + + memory_table_name = 'daily_factor_mem' + partition_table_name = 'daily_factor' + + + def dump_to_ddb(self): + self.create_ddb_memory_table(10) + print('Did create ddb memory table.') + pprint(self.ddb_sess.run(f"schema({self.memory_table_name})")) + + self.create_ddb_partition_table() + print('Did create ddb partition table.') + pprint(self.ddb_sess.run(f"schema({self.partition_table_name})")) + + df_list = [ + self.alpha101_22, + self.trend_with_amount, + ] + df = pd.concat(df_list, axis=1) + df.reset_index(inplace=True) + print('Did prepare the dataframe for insertion:') + print(df.head()) + + self.ddb_sess.upload({"tbl": df}) + self.ddb_sess.run("tableInsert(loadTable('dfs://daily_stock_ts', 'daily_factor'), tbl)") + pprint("Did dump data to partition table.") + + + @property + def alpha101_22(self): + + sql = """ + vol_20 = select code, m_nDate, mstdp(close, 20, 9) as vol_20 + from loadTable("dfs://daily_stock_ts", "daily_kline") + context by code; + + rank_vol_20 = select code, m_nDate, rank(vol_20, tiesMethod='average', percent=true) + from vol_20 context by m_nDate; + + corr_5 = select code, m_nDate, mcorr(high, vol, 5) as corr_5 + from loadTable("dfs://daily_stock_ts", "daily_kline") + context by code; + + delta_corr_5 = select code, m_nDate, mfirst(corr_5, 5) - corr_5 as delta_corr_5 + from corr_5 context by code; + + alpha101_22 = select code, m_nDate, delta_corr_5 * rank_vol_20 as alpha101_22 + from ej(rank_vol_20, delta_corr_5, `code`m_nDate); + + alpha101_22; + """ + + df = self.ddb_sess.run(sql) + df.set_index(["code", "m_nDate"], inplace=True) + return df + + + @property + def trend_with_amount(self): + + factor_list = [ + 'trend_with_turnover', 'trend_with_amount', + "abs_trend_with_turnover", "abs_trend_with_amount", + ] + + factor_def = { + "trend_with_turnover": "(rank(amount/MarketValues, tiesMethod='average', percent=true) - 0.5) * winsorize(PctChg/20, 0.05)", + "trend_with_amount": "(rank(amount, tiesMethod='average', percent=true) - 0.5) * winsorize(PctChg/20, 0.05)", + "abs_trend_with_turnover": "(rank(amount/MarketValues, tiesMethod='average', percent=true) - 0.5) * abs(winsorize(PctChg/20, 0.05))", + "abs_trend_with_amount": "(rank(amount, tiesMethod='average', percent=true) - 0.5) * abs(winsorize(PctChg/20, 0.05))", + } + + cols = ", ".join([ + f"{factor_def[factor_name]} as {factor_name}" \ + for factor_name in factor_list + ]) + + sql = f""" + select code, m_nDate, {cols} + from loadTable("dfs://daily_stock_ts", "daily_kline") + context by m_nDate + """ + print("factor sql for trend with amount: " + sql) + + df = self.ddb_sess.run(sql) + df.set_index(["code", "m_nDate"], inplace=True) + return df def main(): - # TODO: - # 可以使用`Fire`库,对函数调用再做一次封装,就可以避免每次运行不同参数时候需要修改内部多处的代码。 + # TODO: + # 可以使用`Fire`库,对函数调用再做一次封装,就可以避免每次运行不同参数时候需要修改内部多处的代码。 # 日频行情数据 - loader = DDBDailyLoader() + #loader = DDBDailyLoader() + + loader = DDBDailyFactorLoader() loader.load_ddb_database() - #loader.dump_daily_kline_to_ddb() + loader.dump_to_ddb() + - if __name__ == '__main__': main() diff --git a/src/loader/DDBEntityLoader.py b/src/loader/DDBEntityLoader.py new file mode 100644 index 0000000..750539b --- /dev/null +++ b/src/loader/DDBEntityLoader.py @@ -0,0 +1,12 @@ + + +from .DDBLoader import DDBLoader + + +class DDBEntityLoader(DDBLoader): + + ddb_path = "dfs://daily_stock_ts" + ddb_dbname = "db_daily_stock_ts" + + def __init__(self, dtype, **kwargs): + pass diff --git a/src/loader/DDBIndexLoader.py b/src/loader/DDBIndexLoader.py new file mode 100644 index 0000000..c4350e6 --- /dev/null +++ b/src/loader/DDBIndexLoader.py @@ -0,0 +1,286 @@ +import pickle +import functools +import warnings + +from pprint import pprint +from pathlib import Path +from tqdm import tqdm +from multiprocessing import Pool + +import numpy as np +import pandas as pd + +import dolphindb as ddb +import dolphindb.settings as keys + +import sqlalchemy as sa + +from .DDBLoader import DDBLoader + + +class DDBIndexLoader(DDBLoader): + + ddb_path = "dfs://daily_stock_ts" + ddb_dbname = "db_daily_stock_ts" + + + def __init__(self, dtype, **kwargs): + # TODO: 后续版本中,父类的构造函数里可能会增加一些设置项 + super().__init__(**kwargs) + self.dtype = dtype + + if dtype == "concept": + self.mem_tbl_name = "mem_idx_daily_concept" + self.part_tbl_name ="idx_daily_concept" + elif dtype == "kline": + self.mem_tbl_name = "mem_idx_daily_kline" + self.part_tbl_name ="idx_daily_kline" + else: + raise NotImplementedError(f"Unsupported `dtype` argument: {dtype}") + + self.make_fields() + self.make_calendar_df() + + + def make_fields(self): + if self.dtype == "concept": + with self.mssql_engine.connect() as conn: + rs = conn.execute("select IndexID from [IndexInfo].[dbo].[Constituents] group by IndexID") + self.fields = [index_id for (index_id,) in rs.fetchall()] + elif self.dtype == "kline": + self.fields = ['open', 'high', 'low', 'close', 'vol', 'amount', 'yclose'] + + + def make_calendar_df(self): + # 这里我们使用天软日K先数据表来构造交易日历 + with self.mssql_engine.connect() as conn: + if self.dtype == "concept": + stat = "select [StockID], [date] from [StockDaily].[dbo].[DailyKLine] group by [StockID], [date]" + elif self.dtype == "kline": + stat = "select [StockID], [date] from [IndexDaily].[dbo].[DailyKLine] group by [StockID], [date]" + else: + raise NotImplementedError(f"Unsupported dtype: {self.dtype}") + + rs = conn.execute(stat) + stock_date_list = [(stock_name, date) for stock_name, date in rs.fetchall()] + + self.df_calendar = pd.DataFrame(stock_date_list, columns=['code', 'm_nDate']) + self.df_calendar['m_nDate'] = self.make_date(self.df_calendar['m_nDate']) + self.df_calendar['code'] = self.tscode_to_windcode(self.df_calendar['code']) + + print('Did make the DataFrame for calendar') + print(self.df_calendar.head()) + + + def load_ddb_database(self): + self.ddb_sess.run(""" + {dbName} = database(directory='{dbPath}') + """.format( + dbName = self.ddb_dbname, + dbPath = self.ddb_path + )) + print('Did load database from', self.ddb_path) + + + def create_ddb_partition_table(self): + if self.dtype == "concept": + self._create_ddb_memory_table_concept() + elif self.dtype == "kline": + self._create_ddb_memory_table_kline() + + pprint(f"Did create memory table: {self.mem_tbl_name}") + #res = self.ddb_sess.run(f"schema({mem_tbl_name}).colDefs") + + if self.ddb_sess.existsTable(self.ddb_path, self.part_tbl_name): + pprint(f"Will drop partition table: {self.part_tbl_name}") + self.ddb_sess.dropTable(self.ddb_path, self.part_tbl_name) + + self.ddb_sess.run(""" + {part_tbl_name} = {ddb_dbname}.createPartitionedTable( + table = {mem_tbl_name}, + tableName = `{part_tbl_name}, + partitionColumns = `code, + sortColumns = `code`m_nDate, + compressMethods = {{m_nDate:"delta"}} + ) + """.format( + ddb_dbname = self.ddb_dbname, + part_tbl_name = self.part_tbl_name, + mem_tbl_name = self.mem_tbl_name + )) + + + def _create_ddb_memory_table_concept(self): + + concept_list = self.fields + col_name_list = ['code', 'm_nDate'] + concept_list + col_type_list = ['SYMBOL', 'DATE'] + ['BOOL'] * len(concept_list) + code = """ + {mem_tbl_name} = table( + {capacity}:0, + {col_names}, + [{col_types}] + ); + """.format( + mem_tbl_name = self.mem_tbl_name, + capacity = 10, + col_names = '`' + '`'.join(col_name_list), + col_types = ','.join(col_type_list) + ) + pprint(f"Will create mem table by:\n{code}") + self.ddb_sess.run(code) + + + def _create_ddb_memory_table_kline(self): + + col_name_list = ['code', 'm_nDate'] + self.fields + col_type_list = ['SYMBOL', 'DATE'] + ['DOUBLE'] * len(self.fields) + code = """ + {mem_tbl_name} = table( + {capacity} : 0, + {col_names}, + [{col_types}] + ); + """.format( + mem_tbl_name = self.mem_tbl_name, + capacity = 10, + col_names = '`' + '`'.join(col_name_list), + col_types = ','.join(col_type_list) + ) + pprint(f"Will create mem table by:\n{code}") + self.ddb_sess.run(code) + + + def _make_idx_daily_kline(self): + with tqdm(self.df_calendar.groupby('code')) as pbar: + for wind_code, df_calendar_stock in pbar: + pbar.set_description(f"Will work on {wind_code}") + + # 生成ts-code,用于查询Sql-Server中天软的概念板块指数 + ts_code = wind_code[-2:] + wind_code[:-3] + + df_calendar_stock.set_index(['code', 'm_nDate'], inplace=True) + + with self.mssql_engine.connect() as conn: + code = """ + select + {field_list} + from + [IndexDaily].[dbo].[DailyKLine] + where + StockID='{index_id}' + """.format( + field_list = ','.join([f"[{field}]" for field in (['StockID', 'date'] + self.fields)]), + index_id = ts_code + ) + rs = conn.execute(code) + row_list = rs.fetchall() + + df = pd.DataFrame(row_list, columns=['code', 'm_nDate'] + self.fields) + df['code'] = self.tscode_to_windcode(df['code']) + df['m_nDate'] = self.make_date(df['m_nDate']) + df.set_index(['code', 'm_nDate'], inplace=True) + + yield wind_code, df + + + def dump_idx_daily_kline_to_ddb(self): + + for idx_id, df in self._make_idx_daily_kline(): + df.reset_index(inplace=True) + #pprint(f"Will append to partiton table: \n{df}") + self.ddb_sess.upload({self.mem_tbl_name : df}) + self.ddb_sess.run(""" + append!(loadTable('{dbPath}', `{part_tbl_name}), {mem_tbl_name}) + """.format( + dbPath = self.ddb_path, + part_tbl_name = self.part_tbl_name, + mem_tbl_name = self.mem_tbl_name + )) + + + @staticmethod + def _mark_stock2concept_onehot(df_stock2concept, concept_id, start_date, end_date): + # 个股成为某个概念(指数)的起始日期是必定会提供的 + # 但是截止日期可能缺失,确实一般意味着当前仍然是在此概念板块中 + # 因此会通过将日期填充至最后一日来表示当前仍然在此概念板块内 + if end_date is None or end_date == 0: + start_date = pd.to_datetime(str(start_date), format='%Y%m%d') + df_stock2concept.loc[df_stock2concept.index.get_level_values('m_nDate') >= start_date] = True + else: + start_date = pd.to_datetime(str(start_date), format='%Y%m%d') + end_date = pd.to_datetime(str(end_date), format='%Y%m%d') + df_stock2concept.loc[ + (df_stock2concept.index.get_level_values('m_nDate') >= start_date) & + (df_stock2concept.index.get_level_values('m_nDate') <= end_date) + ] = True + + + def _make_stock2concept_onehot(self): + + # 从calendar中截取出与当前stock有关的日期,然后设置成index + # 此处calendar使用的是海通高频数据构建,因此股票代码为WIND-CODE + + # 对calendar根据股票代码进行分组 + with tqdm(self.df_calendar.groupby('code')) as pbar: + for wind_code, df_calendar_stock in pbar: + pbar.set_description(f"Will work on {wind_code}") + + # 生成ts-code,用于查询Sql-Server中天软的概念板块指数 + ts_code = wind_code[-2:] + wind_code[:-3] + + df_calendar_stock.set_index(['code', 'm_nDate'], inplace=True) + + # 纵表转横表,`concept_list`作为列名 + df_stock2concept = pd.DataFrame( + False, # one-hot横表,初始化都是0,后续根据Sql-Server的进出日期标注1 + index=df_calendar_stock.index, + columns=concept_list, + dtype="bool" + ) + + # 从Sql-Server中读取`stock_id`所对应的概念板块进出日期 + # 此数据是从天软指数数据中提取,因此需要使用TSCODE + with self.mssql_engine.connect() as conn: + code = """ + select + SecId, IndexID, EnterDate, ExitDate + from + [IndexInfo].[dbo].[Constituents] + where + SecID='{stock_id}' + """.format( + stock_id = ts_code + ) + rs = conn.execute(code) + row_list = rs.fetchall() + + # 从Sql-Server读取出单个股票的所有板块进出日期后,开始进行标记 + for (stock_id, concept_id, start_date, end_date) in row_list: + # mark the one-hot position one-by-one + self._mark_stock2concept_onehot( + df_stock2concept[concept_id], + concept_id, + start_date, end_date + ) + + # yield the marked one-hot dataframe for one stock + yield wind_code, df_stock2concept + + + def dump_idx_concept_to_ddb(self): + + concept = self.fields + + for stock_id, df in self._make_stock2concept_onehot(concept_list): + df.reset_index(inplace=True) + self.ddb_sess.upload({self.mem_tbl_name : df}) + self.ddb_sess.run(""" + append!(loadTable('{dbPath}', `{part_tbl_name}), {mem_tbl_name}) + """.format( + dbPath = self.ddb_path, + part_tbl_name = self.part_tbl_name, + mem_tbl_name = self.mem_tbl_name + )) + + diff --git a/src/loader/DDBIndexLoaderWind.py b/src/loader/DDBIndexLoaderWind.py new file mode 100644 index 0000000..2a557e1 --- /dev/null +++ b/src/loader/DDBIndexLoaderWind.py @@ -0,0 +1,52 @@ + +from DDBIndexLoader import DDBIndexLoader + + +class DDBIndexLoaderWind(DDBIndexLoader): + + def __init__(self, dtype, **kwargs): + # TODO: 后续版本中,父类的构造函数里可能会增加一些设置项 + super().__init__(**kwargs) + self.dtype = dtype + + if dtype == "concept": + self.mem_tbl_name = "mem_idx_daily_concept_wind" + self.part_tbl_name ="idx_daily_concept_wind" + elif dtype == "kline": + self.mem_tbl_name = "mem_idx_daily_kline_wind" + self.part_tbl_name ="idx_daily_kline_wind" + else: + raise NotImplementedError(f"Unsupported `dtype` argument: {dtype}") + + self.make_fields() + self.make_calendar_df() + + + def make_fields(self): + if self.dtype == "concept": + with self.mssql_engine.connect() as conn: + rs = conn.execute("select [WIND_SEC_CODE] from [IndexInfo].[dbo].[Constituents] group by IndexID") + self.fields = [index_id for (index_id,) in rs.fetchall()] + elif self.dtype == "kline": + self.fields = ['open', 'high', 'low', 'close', 'vol', 'amount', 'yclose'] + + + def make_calendar_df(self): + # 这里我们使用天软日K先数据表来构造交易日历 + with self.mssql_engine.connect() as conn: + if self.dtype == "concept": + stat = "select [StockID], [date] from [StockDaily].[dbo].[DailyKLine] group by [StockID], [date]" + elif self.dtype == "kline": + stat = "select [StockID], [date] from [IndexDaily].[dbo].[DailyKLine] group by [StockID], [date]" + else: + raise NotImplementedError(f"Unsupported dtype: {self.dtype}") + + rs = conn.execute(stat) + stock_date_list = [(stock_name, date) for stock_name, date in rs.fetchall()] + + self.df_calendar = pd.DataFrame(stock_date_list, columns=['code', 'm_nDate']) + self.df_calendar['m_nDate'] = self.make_date(self.df_calendar['m_nDate']) + self.df_calendar['code'] = self.tscode_to_windcode(self.df_calendar['code']) + + print('Did make the DataFrame for calendar') + print(self.df_calendar.head()) diff --git a/src/run.py b/src/run.py index b4e65da..f53f98f 100644 --- a/src/run.py +++ b/src/run.py @@ -3,14 +3,20 @@ from loader.DDBPITLoader import DDBPITLoader from loader.DDBHFTLoader import DDBHFTLoader from loader.DDBBasicInfoLoader import DDBBasicInfoLoader from loader.DDBIndexLoader import DDBIndexLoader +from loader.DDBDailyLoader import DDBDailyLoader, DDBDailyFactorLoader def create_index_data(): # 板块指数数据 - loader = DDBIndexLoader(host='192.168.1.7') + loader = DDBIndexLoader(dtype="kline", host='localhost') loader.load_ddb_database() + + #mem_tbl_name, part_tbl_name, fields = loader.create_ddb_partition_table("concept") + #loader.dump_idx_concept_to_ddb(mem_tbl_name, part_tbl_name, concept_list) + + # 指数日K线数据 loader.create_ddb_partition_table() - loader.dump_idx_concept_to_ddb() + loader.dump_idx_daily_kline_to_ddb() def create_hft_data(): @@ -46,7 +52,13 @@ def create_daily_kline_data(): # 日频行情数据 loader = DDBDailyLoader() loader.load_ddb_database() - loader.dump_daily_kline_to_ddb() + loader.dump_to_ddb() + + +def create_daily_factor_data(): + loader = DDBDailyFactorLoader(host="localhost") + loader.load_ddb_database() + loader.dump_to_ddb() @@ -54,7 +66,8 @@ def main(): # TODO: # 可以使用`Fire`库,对函数调用再做一次封装,就可以避免每次运行不同参数时候需要修改内部多处的代码。 - create_index_data() + create_daily_factor_data() + #create_index_data() #create_hft_data() #create_pit_data()