python-quanta 0.3.10__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_quanta-0.3.10 → python_quanta-0.4.0}/PKG-INFO +1 -1
- {python_quanta-0.3.10 → python_quanta-0.4.0}/pyproject.toml +1 -1
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/python_quanta.egg-info/PKG-INFO +1 -1
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/python_quanta.egg-info/SOURCES.txt +8 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/__init__.py +1 -1
- python_quanta-0.4.0/src/quanta/data/__init__.py +4 -0
- python_quanta-0.4.0/src/quanta/data/joinquant/__init__.py +10 -0
- python_quanta-0.4.0/src/quanta/data/joinquant/dt_table/__init__.py +11 -0
- python_quanta-0.4.0/src/quanta/data/joinquant/dt_table/main.py +107 -0
- python_quanta-0.4.0/src/quanta/data/joinquant/id_table/__init__.py +12 -0
- python_quanta-0.4.0/src/quanta/data/joinquant/id_table/main.py +96 -0
- python_quanta-0.4.0/src/quanta/data/joinquant/meta/main.py +201 -0
- python_quanta-0.4.0/src/quanta/libs/db/_engines/__init__.py +1 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/README.md +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/setup.cfg +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/python_quanta.egg-info/dependency_links.txt +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/python_quanta.egg-info/requires.txt +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/python_quanta.egg-info/top_level.txt +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/config/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/config/_internal.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/config/data.yaml +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/config/flow.yaml +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/config/libs.yaml +0 -0
- {python_quanta-0.3.10/src/quanta/libs/_pandas/analysis → python_quanta-0.4.0/src/quanta/data/joinquant/meta}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/duckui.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_extra_pandas/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_extra_pandas/core.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_extra_pandas/main.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_extra_pandas/old_main.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_main/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_main/_base.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_main/_connect.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/__init__.py +0 -0
- {python_quanta-0.3.10/src/quanta/libs/_pandas/gen → python_quanta-0.4.0/src/quanta/libs/_pandas/analysis}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/analysis/core.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/analysis/dev.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/analysis/main.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/db/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/db/dev.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/db/main.py +0 -0
- {python_quanta-0.3.10/src/quanta/libs/_pandas/rollings → python_quanta-0.4.0/src/quanta/libs/_pandas/gen}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/gen/core.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/gen/dev.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/gen/main.py +0 -0
- {python_quanta-0.3.10/src/quanta/libs/_pandas/stats → python_quanta-0.4.0/src/quanta/libs/_pandas/rollings}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/rollings/base.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/rollings/core.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/rollings/dev.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/rollings/main.py +0 -0
- {python_quanta-0.3.10/src/quanta/libs/_pandas/tools → python_quanta-0.4.0/src/quanta/libs/_pandas/stats}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/stats/core.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/stats/dev.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/stats/main.py +0 -0
- {python_quanta-0.3.10/src/quanta/libs/db → python_quanta-0.4.0/src/quanta/libs/_pandas/tools}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/tools/core.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/tools/dev.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_pandas/tools/main.py +0 -0
- {python_quanta-0.3.10/src/quanta/libs/db/_engines → python_quanta-0.4.0/src/quanta/libs/db}/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/_data_type_standard/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/_data_type_standard/main.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/_engines/DuckDB.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/_engines/MySQL.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/_engines/meta.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/main.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/utils/__init__.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/utils/_base.py +0 -0
- {python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/utils/_decorator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-quanta
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A quantitative analysis project for financial data.
|
|
5
5
|
Author-email: Porco Rosso <porcorossobaojiel@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/porcorossobaojie/quanta.git
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# D:\codes\quanta\pyproject.toml
|
|
2
2
|
[project]
|
|
3
3
|
name = "python-quanta" # 你的项目名称,建议与你的顶级包名(例如 src/quanta)一致
|
|
4
|
-
version = "0.
|
|
4
|
+
version = "0.4.0" # 项目版本号
|
|
5
5
|
description = "A quantitative analysis project for financial data." # 项目的简短描述
|
|
6
6
|
readme = "README.md" # 指向你的 README 文件
|
|
7
7
|
requires-python = ">=3.9" # 项目所需的 Python 版本
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-quanta
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A quantitative analysis project for financial data.
|
|
5
5
|
Author-email: Porco Rosso <porcorossobaojiel@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/porcorossobaojie/quanta.git
|
|
@@ -12,6 +12,14 @@ src/quanta/config/_internal.py
|
|
|
12
12
|
src/quanta/config/data.yaml
|
|
13
13
|
src/quanta/config/flow.yaml
|
|
14
14
|
src/quanta/config/libs.yaml
|
|
15
|
+
src/quanta/data/__init__.py
|
|
16
|
+
src/quanta/data/joinquant/__init__.py
|
|
17
|
+
src/quanta/data/joinquant/dt_table/__init__.py
|
|
18
|
+
src/quanta/data/joinquant/dt_table/main.py
|
|
19
|
+
src/quanta/data/joinquant/id_table/__init__.py
|
|
20
|
+
src/quanta/data/joinquant/id_table/main.py
|
|
21
|
+
src/quanta/data/joinquant/meta/__init__.py
|
|
22
|
+
src/quanta/data/joinquant/meta/main.py
|
|
15
23
|
src/quanta/libs/__init__.py
|
|
16
24
|
src/quanta/libs/_flow/__init__.py
|
|
17
25
|
src/quanta/libs/_flow/_extra_pandas/__init__.py
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from ....config import settings as _settings
|
|
2
|
+
_config = _settings('data').tables.dt_table
|
|
3
|
+
|
|
4
|
+
from .main import main as _class_obj
|
|
5
|
+
|
|
6
|
+
__all__ = ['daily']
|
|
7
|
+
def daily():
|
|
8
|
+
for i in _config.values():
|
|
9
|
+
instance_obj = _class_obj(**i)
|
|
10
|
+
instance_obj.daily()
|
|
11
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Fri Feb 6 15:33:11 2026
|
|
4
|
+
|
|
5
|
+
@author: Porco Rosso
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import jqdatasdk as jq
|
|
9
|
+
from typing import Any, Literal
|
|
10
|
+
import pandas as pd
|
|
11
|
+
|
|
12
|
+
from ....data.joinquant.meta.main import main as meta
|
|
13
|
+
from ....config import settings
|
|
14
|
+
config = settings('data')
|
|
15
|
+
|
|
16
|
+
class main(meta):
|
|
17
|
+
"""
|
|
18
|
+
===========================================================================
|
|
19
|
+
|
|
20
|
+
Main class for handling trade date table data from JoinQuant.
|
|
21
|
+
|
|
22
|
+
This class extends the meta class to provide specific data processing
|
|
23
|
+
and daily update functionalities for trade date related tables.
|
|
24
|
+
|
|
25
|
+
---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
处理 JoinQuant 交易日期表数据的主类。
|
|
28
|
+
|
|
29
|
+
此类扩展了元类,为交易日期相关表提供特定的数据处理和每日更新功能。
|
|
30
|
+
|
|
31
|
+
---------------------------------------------------------------------------
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __data_standard_aindexweights__(self, df, **kwargs):
|
|
35
|
+
df = self.__data_standard__(df, **kwargs)
|
|
36
|
+
df[self.trade_dt] = pd.to_datetime(kwargs.get('start_date')) + pd.Timedelta(pd.Timedelta(config.tables.recommand_settings.time_bias))
|
|
37
|
+
df[list(self.columns_information.get('weight').keys())[0]] = df[list(self.columns_information.get('weight').keys())[0]] / 100
|
|
38
|
+
return df
|
|
39
|
+
|
|
40
|
+
def __data_standard_astockindustrys__(self, df, **kwargs):
|
|
41
|
+
df.columns = ['_'.join([''.join(i[0].split('_')), i[1].split('_')[-1]]) for i in df.columns]
|
|
42
|
+
df = self.__data_standard__(df, **kwargs)
|
|
43
|
+
return df
|
|
44
|
+
|
|
45
|
+
def __data_standard_astockconcept__(self, df, **kwargs):
|
|
46
|
+
df['level_1'] = kwargs.get('start_date')
|
|
47
|
+
df = self.__data_standard__(df, **kwargs)
|
|
48
|
+
return df
|
|
49
|
+
|
|
50
|
+
def pipeline(self, **kwargs: Any) -> pd.DataFrame:
|
|
51
|
+
df = super().pipeline(**kwargs)
|
|
52
|
+
|
|
53
|
+
# construct returns of portfolio by calculated with close price(first use adj price if have)
|
|
54
|
+
if isinstance(self.columns_information, dict):
|
|
55
|
+
ret_key = self.columns_information.get('returns', None)
|
|
56
|
+
else:
|
|
57
|
+
x = eval(f"jq.get_table_info({self.columns_information})")
|
|
58
|
+
x.iloc[:, 0] = x.iloc[:, 0].replace(config.tables.transform | {'code': self.code})
|
|
59
|
+
x.iloc[:, 2] = x.iloc[:, 2].replace({'date': 'datetime', 'DATE': 'datetime'})
|
|
60
|
+
x = x.set_index(x.columns[0]).iloc[:, [1, 0]].T.to_dict('list')
|
|
61
|
+
ret_key = x.get('returns', None)
|
|
62
|
+
if ret_key is not None:
|
|
63
|
+
ret_key = list(ret_key.keys())[0]
|
|
64
|
+
try:
|
|
65
|
+
df[ret_key] = df['close_adj'] / df['preclose_adj'] - 1
|
|
66
|
+
except Exception:
|
|
67
|
+
df[ret_key] = df['close'] / df['preclose'] - 1
|
|
68
|
+
df = df[df.drop([self.trade_dt, self.code], axis=1, errors='ignore').notnull().any(axis=1)]
|
|
69
|
+
return df
|
|
70
|
+
|
|
71
|
+
def daily(self, if_exists: Literal['append', 'replace'] = 'append') -> None:
|
|
72
|
+
if self.table == 'astocklisting': # this table inform the on list time for each stock, which will replace every day
|
|
73
|
+
self.drop_table()
|
|
74
|
+
self.create_table()
|
|
75
|
+
df = self.pipeline()
|
|
76
|
+
self.__write__(df, log=True)
|
|
77
|
+
|
|
78
|
+
else:
|
|
79
|
+
if if_exists == 'replace':
|
|
80
|
+
self.drop_table()
|
|
81
|
+
|
|
82
|
+
if not self.table_exist():
|
|
83
|
+
getattr(self, f"create_table_{self.table}", self.create_table)()
|
|
84
|
+
|
|
85
|
+
id_key = self.__find_max_of_exist_table__(self.trade_dt)
|
|
86
|
+
days = self._trade_days[self._trade_days > id_key]
|
|
87
|
+
|
|
88
|
+
if len(days):
|
|
89
|
+
i = 0
|
|
90
|
+
periods = self.periods
|
|
91
|
+
total = len(days)
|
|
92
|
+
|
|
93
|
+
while i < total or jq.get_query_count()['spare'] < 1000000:
|
|
94
|
+
start_date = days[i]
|
|
95
|
+
end_idx = min(i + periods - 1, total - 1)
|
|
96
|
+
end_date = days[end_idx]
|
|
97
|
+
df = self.pipeline(start_date=str(start_date.date()), end_date=str(end_date.date()))
|
|
98
|
+
print(f"Update to date: {end_date}; Query count left: {jq.get_query_count()['spare']}")
|
|
99
|
+
self.__write__(df, log=True)
|
|
100
|
+
if end_date >= days.max():
|
|
101
|
+
break
|
|
102
|
+
i = end_idx + 1
|
|
103
|
+
|
|
104
|
+
'''
|
|
105
|
+
self = main(**config.tables.dt_table.aindexweights)
|
|
106
|
+
self.daily()
|
|
107
|
+
'''
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from ....config import settings as _settings
|
|
2
|
+
_config = _settings('data').tables.id_table
|
|
3
|
+
|
|
4
|
+
from .main import main as _class_obj
|
|
5
|
+
|
|
6
|
+
__all__ = ['daily']
|
|
7
|
+
def daily():
|
|
8
|
+
for i in _config.values():
|
|
9
|
+
instance_obj = _class_obj(**i)
|
|
10
|
+
instance_obj.daily()
|
|
11
|
+
|
|
12
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Fri Feb 6 11:11:28 2026
|
|
4
|
+
|
|
5
|
+
@author: Porco Rosso
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Literal
|
|
9
|
+
|
|
10
|
+
import pandas as pd
|
|
11
|
+
|
|
12
|
+
from ....data.joinquant.meta.main import main as meta
|
|
13
|
+
|
|
14
|
+
from ....config import settings
|
|
15
|
+
config = settings('data')
|
|
16
|
+
|
|
17
|
+
class main(meta):
|
|
18
|
+
"""
|
|
19
|
+
===========================================================================
|
|
20
|
+
|
|
21
|
+
Main class for handling announcement date table data from JoinQuant.
|
|
22
|
+
|
|
23
|
+
This class extends the meta class to provide specific data processing
|
|
24
|
+
and daily update functionalities for announcement date related tables.
|
|
25
|
+
|
|
26
|
+
---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
处理 JoinQuant 公告日期表数据的主类。
|
|
29
|
+
|
|
30
|
+
此类扩展了元类,为公告日期相关表提供特定的数据处理和每日更新功能。
|
|
31
|
+
|
|
32
|
+
---------------------------------------------------------------------------
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def create_table_afundshare(self, **kwargs):
|
|
36
|
+
columns = {self.trade_dt if i == self.report_period else i:j for i,j in self.columns.items()}
|
|
37
|
+
self.create_table(columns = columns)
|
|
38
|
+
|
|
39
|
+
def __data_standard_afundshare__(self, df, **kwargs):
|
|
40
|
+
df = self.__data_standard__(df, date=self.report_period)
|
|
41
|
+
df = df.rename({self.report_period: self.trade_dt}, axis=1)
|
|
42
|
+
df[self.trade_dt] = pd.to_datetime(df[self.trade_dt]) + pd.Timedelta(config.tables.recommand_settings.time_bias)
|
|
43
|
+
return df
|
|
44
|
+
|
|
45
|
+
def daily(self, if_exists: Literal['append', 'replace'] = 'append') -> None:
|
|
46
|
+
"""
|
|
47
|
+
===========================================================================
|
|
48
|
+
|
|
49
|
+
Performs daily updates for the announcement date table.
|
|
50
|
+
|
|
51
|
+
This method handles the logic for appending or replacing data based on
|
|
52
|
+
the `if_exists` parameter, ensuring the table is up-to-date.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
if_exists : Literal['append', 'replace'], optional
|
|
57
|
+
Determines how to handle existing data. 'append' adds new data,
|
|
58
|
+
'replace' drops the table and recreates it before adding data.
|
|
59
|
+
Defaults to 'append'.
|
|
60
|
+
|
|
61
|
+
---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
执行公告日期表的每日更新。
|
|
64
|
+
|
|
65
|
+
此方法根据 `if_exists` 参数处理追加或替换数据的逻辑,确保表格是最新的。
|
|
66
|
+
|
|
67
|
+
参数
|
|
68
|
+
----------
|
|
69
|
+
if_exists : Literal['append', 'replace'], optional
|
|
70
|
+
确定如何处理现有数据。'append' 添加新数据,'replace' 在添加数据前
|
|
71
|
+
删除并重新创建表格。默认为 'append'。
|
|
72
|
+
|
|
73
|
+
---------------------------------------------------------------------------
|
|
74
|
+
"""
|
|
75
|
+
if if_exists == 'replace':
|
|
76
|
+
self.drop_table()
|
|
77
|
+
|
|
78
|
+
if not self.table_exist():
|
|
79
|
+
getattr(self, f"create_table_{self.table}", self.create_table)()
|
|
80
|
+
|
|
81
|
+
id_key = self.__find_max_of_exist_table__(self.id_key)
|
|
82
|
+
df = self.pipeline(id_key=id_key)
|
|
83
|
+
self.__write__(df, log=True)
|
|
84
|
+
while len(df):
|
|
85
|
+
id_key = df[self.id_key].max()
|
|
86
|
+
df = self.pipeline(id_key=id_key)
|
|
87
|
+
self.__write__(df, log=True)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
'''
|
|
92
|
+
|
|
93
|
+
self = main(**config.tables.id_table.astockstatus)
|
|
94
|
+
self.daily()
|
|
95
|
+
|
|
96
|
+
'''
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Thu Feb 12 15:43:22 2026
|
|
4
|
+
|
|
5
|
+
@author: Porco Rosso
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, List, Union
|
|
9
|
+
import numpy as np
|
|
10
|
+
import pandas as pd
|
|
11
|
+
import jqdatasdk as jq
|
|
12
|
+
|
|
13
|
+
from ....libs.utils import merge_dicts
|
|
14
|
+
from ....config import settings, login_info
|
|
15
|
+
from ....libs.db.main import main as db
|
|
16
|
+
|
|
17
|
+
#jq.auth(**login_info('account').joinquant)
|
|
18
|
+
config = settings('data')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class main(db, type('recommand_settings', (), config.tables.recommand_settings.key)):
|
|
22
|
+
|
|
23
|
+
def __init__(self, **kwargs):
|
|
24
|
+
super().__init__(**kwargs)
|
|
25
|
+
self.__env_init__()
|
|
26
|
+
self._stock = jq.get_all_securities('stock', date=None).index.tolist()
|
|
27
|
+
_fund = jq.get_all_securities('fund', date=None)
|
|
28
|
+
self._fund = _fund[_fund.iloc[:, -1] == 'etf'].index.tolist()
|
|
29
|
+
self._index = jq.get_all_securities('index', date=None).index.tolist()
|
|
30
|
+
_trade_days = pd.to_datetime(jq.get_trade_days('2005-01-01')) + pd.Timedelta(config.tables.recommand_settings.time_bias)
|
|
31
|
+
self._trade_days = _trade_days[_trade_days <= pd.Timestamp.today() - pd.Timedelta(4, 'h')]
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def portfolio_type(self):
|
|
35
|
+
for i in config.public_keys.recommand_settings.portfolio_types:
|
|
36
|
+
if i in self.table:
|
|
37
|
+
return i
|
|
38
|
+
@property
|
|
39
|
+
def code(self):
|
|
40
|
+
attr = f"{self.portfolio_type}_code"
|
|
41
|
+
return getattr(self, attr)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def columns(self) -> Dict:
|
|
45
|
+
"""
|
|
46
|
+
===========================================================================
|
|
47
|
+
|
|
48
|
+
Returns the column information for the current table.
|
|
49
|
+
|
|
50
|
+
This property dynamically retrieves and formats column metadata,
|
|
51
|
+
including renaming and type mapping.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
Dict
|
|
56
|
+
A dictionary where keys are column names and values are their types.
|
|
57
|
+
|
|
58
|
+
---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
返回当前表的列信息。
|
|
61
|
+
|
|
62
|
+
此属性动态检索和格式化列元数据,包括重命名和类型映射。
|
|
63
|
+
|
|
64
|
+
返回
|
|
65
|
+
-------
|
|
66
|
+
Dict
|
|
67
|
+
一个字典,其中键是列名,值是其类型。
|
|
68
|
+
|
|
69
|
+
---------------------------------------------------------------------------
|
|
70
|
+
"""
|
|
71
|
+
if isinstance(self.columns_information, dict):
|
|
72
|
+
x = merge_dicts(*list(self.columns_information.values()))
|
|
73
|
+
else:
|
|
74
|
+
x = eval(f"jq.get_table_info({self.columns_information})")
|
|
75
|
+
x.iloc[:, 0] = x.iloc[:, 0].replace(config.tables.transform | {'code': self.code})
|
|
76
|
+
x.iloc[:, 2] = x.iloc[:, 2].replace({'date': 'datetime', 'DATE': 'datetime'})
|
|
77
|
+
x = x.set_index(x.columns[0]).iloc[:, [1, 0]].T.to_dict('list')
|
|
78
|
+
return x
|
|
79
|
+
|
|
80
|
+
def __columns_rename__(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
81
|
+
"""
|
|
82
|
+
===========================================================================
|
|
83
|
+
|
|
84
|
+
Renames columns of the input DataFrame based on predefined mappings.
|
|
85
|
+
|
|
86
|
+
This internal method handles column renaming and ensures consistency
|
|
87
|
+
across different data sources, including handling multi-level columns.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
df : pd.DataFrame
|
|
92
|
+
The DataFrame whose columns need to be renamed.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
pd.DataFrame
|
|
97
|
+
The DataFrame with renamed columns.
|
|
98
|
+
|
|
99
|
+
---------------------------------------------------------------------------
|
|
100
|
+
|
|
101
|
+
根据预定义的映射重命名输入 DataFrame 的列。
|
|
102
|
+
|
|
103
|
+
此内部方法处理列重命名并确保不同数据源之间的一致性,包括处理多级列。
|
|
104
|
+
|
|
105
|
+
参数
|
|
106
|
+
----------
|
|
107
|
+
df : pd.DataFrame
|
|
108
|
+
需要重命名列的 DataFrame。
|
|
109
|
+
|
|
110
|
+
返回
|
|
111
|
+
-------
|
|
112
|
+
pd.DataFrame
|
|
113
|
+
列已重命名的 DataFrame。
|
|
114
|
+
|
|
115
|
+
---------------------------------------------------------------------------
|
|
116
|
+
"""
|
|
117
|
+
if isinstance(self.columns_information, dict):
|
|
118
|
+
rename_dic = {i: list(j.keys())[0] for i, j in self.columns_information.items()}
|
|
119
|
+
else:
|
|
120
|
+
rename_dic = config.tables.transform | {'code': self.code}
|
|
121
|
+
df = df.reset_index().rename(rename_dic, axis=1)
|
|
122
|
+
df = df.loc[:, df.columns.isin(list(self.columns.keys()))]
|
|
123
|
+
return df
|
|
124
|
+
|
|
125
|
+
def __get_data_from_jq_remote__(self, **kwargs: Any) -> pd.DataFrame:
|
|
126
|
+
df = eval(self.commands.format(**kwargs))
|
|
127
|
+
return df
|
|
128
|
+
|
|
129
|
+
def __data_standard__(self, df: pd.DataFrame, **kwargs: Any) -> pd.DataFrame:
|
|
130
|
+
# df columns renaed as create_table's columns
|
|
131
|
+
df = self.__columns_rename__(df)
|
|
132
|
+
# add time bias on trade_dt or ann_dt
|
|
133
|
+
for i in [self.ann_dt, self.trade_dt]:
|
|
134
|
+
if i in df.columns:
|
|
135
|
+
df[i] = pd.to_datetime(df[i]) + pd.Timedelta(config.tables.recommand_settings.time_bias)
|
|
136
|
+
if (i not in df.columns) and i in self.columns.keys():
|
|
137
|
+
try:
|
|
138
|
+
df[i] = pd.to_datetime(kwargs['start_date']) + pd.Timedelta(config.tables.recommand_settings.time_bias)
|
|
139
|
+
except KeyError:
|
|
140
|
+
pass
|
|
141
|
+
# replace nan and standard codes
|
|
142
|
+
df = df.replace({np.inf: np.nan, -np.inf: np.nan})
|
|
143
|
+
if self.portfolio_type == 'astock':
|
|
144
|
+
df = df[df[self.code].str.contains(r'^\d', na=False)]
|
|
145
|
+
elif self.portfolio_type == 'afund':
|
|
146
|
+
df = df[df[self.code].isin(self._fund)]
|
|
147
|
+
# standard code code means: 000001.xxxx, check need normalize or not
|
|
148
|
+
if (df[self.code].apply(lambda x: len(x)) != 6 + 1 + 4).any():
|
|
149
|
+
df[self.code] = jq.normalize_code(df[self.code].to_list())
|
|
150
|
+
return df
|
|
151
|
+
|
|
152
|
+
def pipeline(self, **kwargs: Any) -> pd.DataFrame:
|
|
153
|
+
df = self.__get_data_from_jq_remote__(**kwargs)
|
|
154
|
+
func = getattr(self, f"__data_standard_{self.table}__", self.__data_standard__)
|
|
155
|
+
df = func(df, **kwargs)
|
|
156
|
+
return df
|
|
157
|
+
|
|
158
|
+
def __find_max_of_exist_table__(self, columns: str, **kwargs: Any) -> Union[int, float, pd.Timestamp]:
|
|
159
|
+
id_key = None
|
|
160
|
+
if self.table_exist():
|
|
161
|
+
id_key = self.__read__(columns=f'MAX({columns})', show_time=False, **kwargs).iloc[0, 0]
|
|
162
|
+
id_key = None if pd.isnull(id_key) else id_key
|
|
163
|
+
|
|
164
|
+
if id_key is None:
|
|
165
|
+
if 'DATE' in self.columns.get(columns, ['None'])[0].upper():
|
|
166
|
+
id_key = pd.to_datetime(getattr(self, 'date_start', config.tables.recommand_settings.date_start))
|
|
167
|
+
else:
|
|
168
|
+
id_key = 0
|
|
169
|
+
return id_key
|
|
170
|
+
|
|
171
|
+
def table_exist(self):
|
|
172
|
+
return super().__table_exist__()
|
|
173
|
+
|
|
174
|
+
def drop_table(self, **kwargs: Any) -> None:
|
|
175
|
+
parameters = self.__parameters__({'log': True}, kwargs)
|
|
176
|
+
super().__drop_table__(**parameters)
|
|
177
|
+
|
|
178
|
+
def create_table(self, **kwargs: Any) -> None:
|
|
179
|
+
parameters = {'columns': self.columns, 'log': True}
|
|
180
|
+
if self.engine_type == 'MySQL':
|
|
181
|
+
keys = (
|
|
182
|
+
self.ann_dt
|
|
183
|
+
if self.trade_dt not in self.columns.keys()
|
|
184
|
+
else self.trade_dt
|
|
185
|
+
)
|
|
186
|
+
partition = None if keys != self.trade_dt else {self.trade_dt: eval(config.tables.recommand_settings.key.partition)}
|
|
187
|
+
parameters = (
|
|
188
|
+
self.__parameters__()
|
|
189
|
+
| {'keys': keys, 'partition': partition}
|
|
190
|
+
| {'columns': self.columns, 'log': True}
|
|
191
|
+
| kwargs
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
parameters = self.__parameters__(parameters, kwargs)
|
|
195
|
+
super().__create_table__(**parameters)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
'''
|
|
199
|
+
self = main(**config.tables.id_table.astockstatus)
|
|
200
|
+
|
|
201
|
+
'''
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#
|
|
File without changes
|
|
File without changes
|
{python_quanta-0.3.10 → python_quanta-0.4.0}/src/python_quanta.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_extra_pandas/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/_flow/_extra_pandas/old_main.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_quanta-0.3.10 → python_quanta-0.4.0}/src/quanta/libs/db/_data_type_standard/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|