From ec1a37367b3ff76aa9e8bdff8a9dd814b87cfe3c Mon Sep 17 00:00:00 2001 From: foolcage <5533061@qq.com> Date: Wed, 5 Jun 2024 23:12:33 +0800 Subject: [PATCH] Move some common feature from examples to main package --- examples/README.MD | 6 +-- examples/query_snippet.py | 7 +-- examples/report_utils.py | 3 +- examples/reports/report_core_compay.py | 2 +- examples/requirements.txt | 1 - examples/utils.py | 34 +------------- examples/zhdate/__init__.py | 1 - requirements.txt | 3 +- src/zvt/broker/qmt/qmt_quote.py | 22 +++++---- src/zvt/contract/api.py | 9 +++- src/zvt/fill_project.py | 6 +-- src/zvt/informer/inform_utils.py | 54 +++++++++++++++++++++++ src/zvt/utils/__init__.py | 6 +++ src/zvt/utils/inform_utils.py | 16 ------- src/zvt/utils/model_utils.py | 4 ++ src/zvt/utils/time_utils.py | 4 +- src/zvt/utils/utils.py | 3 ++ src/zvt/zhdate/__init__.py | 25 +++++++++++ {examples => src/zvt}/zhdate/constants.py | 2 + {examples => src/zvt}/zhdate/zhdate.py | 6 ++- {examples => src/zvt/zhdate}/ztime.py | 5 ++- 21 files changed, 137 insertions(+), 82 deletions(-) delete mode 100644 examples/zhdate/__init__.py create mode 100644 src/zvt/informer/inform_utils.py delete mode 100644 src/zvt/utils/inform_utils.py create mode 100644 src/zvt/zhdate/__init__.py rename {examples => src/zvt}/zhdate/constants.py (99%) rename {examples => src/zvt}/zhdate/zhdate.py (98%) rename {examples => src/zvt/zhdate}/ztime.py (95%) diff --git a/examples/README.MD b/examples/README.MD index b8dbe03d..4fdadade 100644 --- a/examples/README.MD +++ b/examples/README.MD @@ -1,5 +1 @@ -The examples is updating with master source code. -Run with specific version e.g. v0.9.16 need to -``` -git checkout v0.10.1 -``` +The examples are updating with master source code. diff --git a/examples/query_snippet.py b/examples/query_snippet.py index 67f5e63d..28bf598b 100644 --- a/examples/query_snippet.py +++ b/examples/query_snippet.py @@ -52,6 +52,7 @@ def get_sub_tag_stocks(tag="低空经济"): if __name__ == "__main__": - a = get_block_stocks() - b = get_sub_tag_stocks() - print(set(a) - set(b)) + # a = get_block_stocks() + # b = get_sub_tag_stocks() + # print(set(a) - set(b)) + print(Stock.query_data(provider="em", return_type="dict")) diff --git a/examples/report_utils.py b/examples/report_utils.py index 4c09984d..b16ae5d2 100644 --- a/examples/report_utils.py +++ b/examples/report_utils.py @@ -4,7 +4,7 @@ from typing import Type from examples.tag_utils import group_stocks_by_tag, get_main_line_tags, get_main_line_hidden_tags -from examples.utils import add_to_eastmoney, msg_group_stocks_by_topic +from examples.utils import msg_group_stocks_by_topic from zvt import zvt_config from zvt.api import get_top_volume_entities, TopType from zvt.api.kdata import get_latest_kdata_date, get_kdata_schema, default_adjust_type @@ -16,6 +16,7 @@ from zvt.domain import StockNews from zvt.informer import EmailInformer from zvt.utils import date_time_by_interval +from zvt.informer.inform_utils import add_to_eastmoney logger = logging.getLogger("__name__") diff --git a/examples/reports/report_core_compay.py b/examples/reports/report_core_compay.py index 430c4e3b..3e5915fd 100644 --- a/examples/reports/report_core_compay.py +++ b/examples/reports/report_core_compay.py @@ -6,12 +6,12 @@ from examples.factors.fundamental_selector import FundamentalSelector from examples.reports import get_subscriber_emails, stocks_with_info -from examples.utils import add_to_eastmoney from zvt import init_log, zvt_config from zvt.contract.api import get_entities from zvt.domain import Stock from zvt.factors.target_selector import TargetSelector from zvt.informer.informer import EmailInformer +from zvt.informer.inform_utils import add_to_eastmoney from zvt.utils.time_utils import now_pd_timestamp, to_time_str logger = logging.getLogger(__name__) diff --git a/examples/requirements.txt b/examples/requirements.txt index b33a6107..290c539e 100644 --- a/examples/requirements.txt +++ b/examples/requirements.txt @@ -1,5 +1,4 @@ zvt >= 0.10.1 apscheduler >= 3.4.0 -eastmoneypy == 0.1.5 tabulate>=0.8.8 ta \ No newline at end of file diff --git a/examples/utils.py b/examples/utils.py index 246e9bce..7710f550 100644 --- a/examples/utils.py +++ b/examples/utils.py @@ -2,47 +2,15 @@ import json import logging import os -import time -import eastmoneypy import pandas as pd -import requests + from zvt.domain import StockNews, Stock, LimitUpInfo from zvt.utils import date_time_by_interval, today logger = logging.getLogger(__name__) -def add_to_eastmoney(codes, group, entity_type="stock", over_write=True): - with requests.Session() as session: - codes = list(set(codes)) - if over_write: - try: - eastmoneypy.del_group(group_name=group, session=session) - except: - pass - try: - eastmoneypy.create_group(group_name=group, session=session) - except: - pass - - group_id = eastmoneypy.get_group_id(group, session=session) - - for code in codes: - eastmoneypy.add_to_group(code=code, entity_type=entity_type, group_id=group_id, session=session) - - -def clean_groups(keep=None): - if keep is None: - keep = ["自选股", "练气", "重要板块", "主线"] - - with requests.Session() as session: - groups = eastmoneypy.get_groups(session=session) - groups_to_clean = [group["gid"] for group in groups if group["gname"] not in keep] - for gid in groups_to_clean: - eastmoneypy.del_group(group_id=gid, session=session) - - def get_hot_words_config(): with open(os.path.join(os.path.dirname(__file__), "hot.json")) as f: return json.load(f) diff --git a/examples/zhdate/__init__.py b/examples/zhdate/__init__.py deleted file mode 100644 index 40a96afc..00000000 --- a/examples/zhdate/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/requirements.txt b/requirements.txt index 11f8bea5..f47fdef4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,4 +15,5 @@ dash_daq==0.5.0 scikit-learn==1.2.1 fastapi==0.110.0 fastapi-pagination==0.12.23 -apscheduler==3.10.4 \ No newline at end of file +apscheduler==3.10.4 +eastmoneypy==0.1.7 \ No newline at end of file diff --git a/src/zvt/broker/qmt/qmt_quote.py b/src/zvt/broker/qmt/qmt_quote.py index 2474665b..516540a1 100644 --- a/src/zvt/broker/qmt/qmt_quote.py +++ b/src/zvt/broker/qmt/qmt_quote.py @@ -1,30 +1,21 @@ # -*- coding: utf-8 -*- -import json import logging import time -import datetime + import numpy as np import pandas as pd from xtquant import xtdata -from sqlalchemy import text -from zvt.api import get_recent_report_date -from zvt.common.query_models import TimeUnit + from zvt.contract import IntervalLevel, AdjustType -from zvt.contract.api import decode_entity_id, df_to_db, get_db_engine, get_schema_columns, get_db_session +from zvt.contract.api import decode_entity_id, df_to_db, get_db_session from zvt.domain import StockQuote, Stock from zvt.utils import ( to_time_str, current_date, to_pd_timestamp, - now_time_str, - date_time_by_interval, pd_is_not_null, - TIME_FORMAT_DAY, - TIME_FORMAT_MINUTE2, ) -from sqlalchemy.dialects.sqlite import insert - # https://dict.thinktrader.net/nativeApi/start_now.html?id=e2M5nZ logger = logging.getLogger(__name__) @@ -247,7 +238,14 @@ def download_capital_data(): ) +def clear_history_quote(): + session = get_db_session("qmt", data_schema=StockQuote) + session.query(StockQuote).filter(StockQuote.timestamp < current_date()).delete() + session.commit() + + if __name__ == "__main__": + clear_history_quote() Stock.record_data(provider="em") stocks = get_qmt_stocks() print(stocks) diff --git a/src/zvt/contract/api.py b/src/zvt/contract/api.py index 9d32176f..715fdfed 100644 --- a/src/zvt/contract/api.py +++ b/src/zvt/contract/api.py @@ -253,6 +253,13 @@ def get_by_id(data_schema, id: str, provider: str = None, session: Session = Non return session.query(data_schema).get(id) +def _row2dict(row): + d = {} + for column in row.__table__.columns: + d[column.name] = getattr(row, column.name) + return d + + def get_data( data_schema: Type[Mixin], ids: List[str] = None, @@ -376,7 +383,7 @@ def get_data( return query.all() elif return_type == "dict": domains = query.all() - return [item.__dict__ for item in domains] + return [_row2dict(item) for item in domains] elif return_type == "select": return query.selectable diff --git a/src/zvt/fill_project.py b/src/zvt/fill_project.py index e6cec900..d0a29b00 100644 --- a/src/zvt/fill_project.py +++ b/src/zvt/fill_project.py @@ -90,12 +90,12 @@ def gen_kdata_schemas(): # zip_dir(ZVT_TEST_DATA_PATH, zip_file_name=DATA_SAMPLE_ZIP_PATH) # gen_exports("contract", export_modules=["schema"]) # gen_exports("ml") - # gen_exports("utils") + gen_exports("utils", export_var=True) # gen_exports('informer') # gen_exports("api") # gen_exports('trader') # gen_exports('autocode') - # gen_exports("ml") - gen_kdata_schemas() + gen_exports("zhdate") + # gen_kdata_schemas() # gen_exports("recorders") # gen_exports("tag") diff --git a/src/zvt/informer/inform_utils.py b/src/zvt/informer/inform_utils.py new file mode 100644 index 00000000..a4fe4565 --- /dev/null +++ b/src/zvt/informer/inform_utils.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +import eastmoneypy + +from zvt import zvt_config +from zvt.contract.api import get_entities +from zvt.informer import EmailInformer + +import requests + + +def inform_email(entity_ids, entity_type, target_date, title, provider): + msg = "no targets" + if entity_ids: + entities = get_entities(provider=provider, entity_type=entity_type, entity_ids=entity_ids, return_type="domain") + assert len(entities) == len(entity_ids) + + infos = [f"{entity.name}({entity.code})" for entity in entities] + msg = "\n".join(infos) + "\n" + + EmailInformer().send_message(zvt_config["email_username"], f"{target_date} {title}", msg) + + +def add_to_eastmoney(codes, group, entity_type="stock", over_write=True): + with requests.Session() as session: + codes = list(set(codes)) + if over_write: + try: + eastmoneypy.del_group(group_name=group, session=session) + except: + pass + try: + eastmoneypy.create_group(group_name=group, session=session) + except: + pass + + group_id = eastmoneypy.get_group_id(group, session=session) + + for code in codes: + eastmoneypy.add_to_group(code=code, entity_type=entity_type, group_id=group_id, session=session) + + +def clean_groups(keep): + if keep is None: + keep = ["自选股", "练气", "重要板块", "主线"] + + with requests.Session() as session: + groups = eastmoneypy.get_groups(session=session) + groups_to_clean = [group["gid"] for group in groups if group["gname"] not in keep] + for gid in groups_to_clean: + eastmoneypy.del_group(group_id=gid, session=session) + + +# the __all__ is generated +__all__ = ["inform_email", "add_to_eastmoney", "clean_groups"] diff --git a/src/zvt/utils/__init__.py b/src/zvt/utils/__init__.py index 598f5cc3..7e3d1fe1 100644 --- a/src/zvt/utils/__init__.py +++ b/src/zvt/utils/__init__.py @@ -6,6 +6,12 @@ # common code of the package # export interface in __all__ which contains __all__ of its sub modules +# import all from submodule model_utils +from .model_utils import * +from .model_utils import __all__ as _model_utils_all + +__all__ += _model_utils_all + # import all from submodule str_utils from .str_utils import * from .str_utils import __all__ as _str_utils_all diff --git a/src/zvt/utils/inform_utils.py b/src/zvt/utils/inform_utils.py deleted file mode 100644 index 0f21824e..00000000 --- a/src/zvt/utils/inform_utils.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -from zvt import zvt_config -from zvt.contract.api import get_entities -from zvt.informer import EmailInformer - - -def inform_email(entity_ids, entity_type, target_date, title, provider): - msg = "no targets" - if entity_ids: - entities = get_entities(provider=provider, entity_type=entity_type, entity_ids=entity_ids, return_type="domain") - assert len(entities) == len(entity_ids) - - infos = [f"{entity.name}({entity.code})" for entity in entities] - msg = "\n".join(infos) + "\n" - - EmailInformer().send_message(zvt_config["email_username"], f"{target_date} {title}", msg) diff --git a/src/zvt/utils/model_utils.py b/src/zvt/utils/model_utils.py index 37349f04..9690fa43 100644 --- a/src/zvt/utils/model_utils.py +++ b/src/zvt/utils/model_utils.py @@ -3,3 +3,7 @@ def update_model(db_model, schema): for key, value in schema.dict().items(): if value is not None: setattr(db_model, key, value) + + +# the __all__ is generated +__all__ = ["update_model"] diff --git a/src/zvt/utils/time_utils.py b/src/zvt/utils/time_utils.py index 106349ac..dcdd9bb4 100644 --- a/src/zvt/utils/time_utils.py +++ b/src/zvt/utils/time_utils.py @@ -277,14 +277,17 @@ def count_interval(start_date, end_date): "TIME_FORMAT_DAY", "TIME_FORMAT_DAY1", "TIME_FORMAT_MINUTE", + "TIME_FORMAT_SECOND", "TIME_FORMAT_MINUTE1", "TIME_FORMAT_MINUTE2", "to_pd_timestamp", + "get_local_timezone", "to_timestamp", "now_timestamp", "now_pd_timestamp", "today", "current_date", + "tomorrow_date", "to_time_str", "now_time_str", "date_time_by_interval", @@ -306,5 +309,4 @@ def count_interval(start_date, end_date): "is_in_same_interval", "split_time_interval", "count_interval", - "tomorrow_date", ] diff --git a/src/zvt/utils/utils.py b/src/zvt/utils/utils.py index 2170f2be..12f48025 100644 --- a/src/zvt/utils/utils.py +++ b/src/zvt/utils/utils.py @@ -312,6 +312,9 @@ def fill_dict(src, dst): "iterate_with_step", "url_unquote", "parse_url_params", + "set_one_and_only_one", "flatten_list", + "to_str", "compare_dicts", + "fill_dict", ] diff --git a/src/zvt/zhdate/__init__.py b/src/zvt/zhdate/__init__.py new file mode 100644 index 00000000..88f55c4e --- /dev/null +++ b/src/zvt/zhdate/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# the __all__ is generated +__all__ = [] + +# __init__.py structure: +# common code of the package +# export interface in __all__ which contains __all__ of its sub modules + +# import all from submodule constants +from .constants import * +from .constants import __all__ as _constants_all + +__all__ += _constants_all + +# import all from submodule ztime +from .ztime import * +from .ztime import __all__ as _ztime_all + +__all__ += _ztime_all + +# import all from submodule zhdate +from .zhdate import * +from .zhdate import __all__ as _zhdate_all + +__all__ += _zhdate_all diff --git a/examples/zhdate/constants.py b/src/zvt/zhdate/constants.py similarity index 99% rename from examples/zhdate/constants.py rename to src/zvt/zhdate/constants.py index 94e50a65..8bc0a6b3 100644 --- a/examples/zhdate/constants.py +++ b/src/zvt/zhdate/constants.py @@ -422,3 +422,5 @@ """ 从1900年,至2100年每年的农历春节的公历日期 """ +# the __all__ is generated +__all__ = [] diff --git a/examples/zhdate/zhdate.py b/src/zvt/zhdate/zhdate.py similarity index 98% rename from examples/zhdate/zhdate.py rename to src/zvt/zhdate/zhdate.py index 2fa68b42..ea0296f1 100644 --- a/examples/zhdate/zhdate.py +++ b/src/zvt/zhdate/zhdate.py @@ -5,7 +5,7 @@ from datetime import datetime, timedelta from itertools import accumulate -from examples.zhdate.constants import CHINESEYEARCODE, CHINESENEWYEAR +from zvt.zhdate.constants import CHINESEYEARCODE, CHINESENEWYEAR class ZhDate: @@ -255,3 +255,7 @@ def month_days(year): [int] -- 农历年份所对应的农历月份天数列表 """ return ZhDate.decode(CHINESEYEARCODE[year - 1900]) + + +# the __all__ is generated +__all__ = [] diff --git a/examples/ztime.py b/src/zvt/zhdate/ztime.py similarity index 95% rename from examples/ztime.py rename to src/zvt/zhdate/ztime.py index f4e5053d..365e754e 100644 --- a/examples/ztime.py +++ b/src/zvt/zhdate/ztime.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from examples.zhdate.zhdate import ZhDate - from zvt.utils import to_pd_timestamp, current_date, count_interval +from zvt.zhdate.zhdate import ZhDate def holiday_distance(timestamp=None, days=15): @@ -65,3 +64,5 @@ def holiday_distance(timestamp=None, days=15): # for month in range(1, 13): # holiday_distance(f"2023-{month}-15") # holiday_distance(f"2023-{month}-20") +# the __all__ is generated +__all__ = ["holiday_distance"]