Showing preview only (1,293K chars total). Download the full file or copy to clipboard to get everything.
Repository: myhhub/stock
Branch: master
Commit: 732eb1ab73b9
Files: 133
Total size: 1.2 MB
Directory structure:
gitextract_qm3wy6o4/
├── .github/
│ └── workflows/
│ ├── azure-container-webapp.yml
│ └── docker-image.yml
├── .gitignore
├── LICENSE
├── README.md
├── cron/
│ ├── cron.hourly/
│ │ └── run_hourly
│ ├── cron.monthly/
│ │ └── run_monthly
│ └── cron.workdayly/
│ └── run_workdayly
├── docker/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── Dockerfile
│ ├── build.sh
│ └── docker-compose.yml
├── instock/
│ ├── .gitignore
│ ├── __init__.py
│ ├── bin/
│ │ ├── restart_web.sh
│ │ ├── run_cron.sh
│ │ ├── run_job.bat
│ │ ├── run_job.sh
│ │ ├── run_trade.bat
│ │ ├── run_web.bat
│ │ └── run_web.sh
│ ├── config/
│ │ ├── .gitignore
│ │ ├── eastmoney_cookie.txt
│ │ ├── proxy.txt
│ │ └── trade_client.json
│ ├── core/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── backtest/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ └── rate_stats.py
│ │ ├── crawling/
│ │ │ ├── __init__.py
│ │ │ ├── fund_etf_em.py
│ │ │ ├── stock_chip_race.py
│ │ │ ├── stock_cpbd.py
│ │ │ ├── stock_dzjy_em.py
│ │ │ ├── stock_fhps_em.py
│ │ │ ├── stock_fund_em.py
│ │ │ ├── stock_hist_em.py
│ │ │ ├── stock_lhb_em.py
│ │ │ ├── stock_lhb_sina.py
│ │ │ ├── stock_limitup_reason.py
│ │ │ ├── stock_selection.py
│ │ │ └── trade_date_hist.py
│ │ ├── eastmoney_fetcher.py
│ │ ├── indicator/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ └── calculate_indicator.py
│ │ ├── kline/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── cyq.js
│ │ │ ├── cyq.py
│ │ │ ├── indicator_web_dic.py
│ │ │ └── visualization.py
│ │ ├── pattern/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ └── pattern_recognitions.py
│ │ ├── singleton_proxy.py
│ │ ├── singleton_stock.py
│ │ ├── singleton_stock_web_module_data.py
│ │ ├── singleton_trade_date.py
│ │ ├── stockfetch.py
│ │ ├── strategy/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── backtrace_ma250.py
│ │ │ ├── breakthrough_platform.py
│ │ │ ├── climax_limitdown.py
│ │ │ ├── enter.py
│ │ │ ├── high_tight_flag.py
│ │ │ ├── keep_increasing.py
│ │ │ ├── low_atr.py
│ │ │ ├── low_backtrace_increase.py
│ │ │ ├── parking_apron.py
│ │ │ └── turtle_trade.py
│ │ ├── tablestructure.py
│ │ └── web_module_data.py
│ ├── job/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── backtest_data_daily_job.py
│ │ ├── basic_data_after_close_daily_job.py
│ │ ├── basic_data_daily_job.py
│ │ ├── basic_data_other_daily_job.py
│ │ ├── execute_daily_job.py
│ │ ├── indicators_data_daily_job.py
│ │ ├── init_job.py
│ │ ├── klinepattern_data_daily_job.py
│ │ ├── selection_data_daily_job.py
│ │ └── strategy_data_daily_job.py
│ ├── trade/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── robot/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── engine/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── __init__.py
│ │ │ │ ├── clock_engine.py
│ │ │ │ ├── event_engine.py
│ │ │ │ └── main_engine.py
│ │ │ └── infrastructure/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── default_handler.py
│ │ │ ├── strategy_template.py
│ │ │ └── strategy_wrapper.py
│ │ ├── strategies/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── stagging.py
│ │ │ └── stratey1.py
│ │ ├── trade_service.py
│ │ └── usage.md
│ └── web/
│ ├── .gitignore
│ ├── __init__.py
│ ├── base.py
│ ├── dataIndicatorsHandler.py
│ ├── dataTableHandler.py
│ ├── static/
│ │ ├── css/
│ │ │ ├── bootstrap.min-3.4.1.css
│ │ │ ├── font-awesome.min-4.5.0.css
│ │ │ └── gc.spread.sheets.excel2013white.css
│ │ └── js/
│ │ ├── FileSaver.js
│ │ ├── bootstrap.min-3.4.1.js
│ │ └── jquery.min-3.7.1.js
│ ├── templates/
│ │ ├── common/
│ │ │ ├── footer.html
│ │ │ ├── header.html
│ │ │ ├── left_menu.html
│ │ │ └── meta.html
│ │ ├── index.html
│ │ ├── layout/
│ │ │ ├── default.html
│ │ │ ├── indicators-main.html
│ │ │ ├── indicators.html
│ │ │ └── main.html
│ │ ├── stock_indicators.html
│ │ └── stock_web.html
│ └── web_service.py
├── requirements.txt
└── supervisor/
└── supervisord.conf
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/azure-container-webapp.yml
================================================
# 当提交推送到默认分支时,此工作流将构建 Docker 容器并将其推送到 Azure Web 应用程序。
#
# 此工作流假设您已创建目标 Azure 应用服务 Web 应用。
#相关说明,请参阅 https://docs.microsoft.com/en-us/azure/app-service/quickstart-custom-container?tabs=dotnet&pivots=container-linux
#
# 配置此工作流程:
#
# 1.下载Azure Web应用程序的发布配置文件。您可以从Azure门户中Web应用程序的概述页面下载此文件。
#相关详细信息:https://docs.microsoft.com/en-us/azure/app-service/deploy-github-actions?tabs=applevel#generate-deployment-credentials
#
# 2. 在存储库中创建一个名为 AZURE_WEBAPP_PUBLISH_PROFILE 的密钥,将发布配置文件内容粘贴为密钥的值。
# 有关获取发布配置文件的说明,请参阅:https://docs.microsoft.com/azure/app-service/deploy-github-actions#configure-the-github-secret
#
# 3.创建具有“repo”和“read:packages”权限的GitHub个人访问令牌。
#
# 4.在Azure Web应用程序上创建三个应用程序设置:
# DOCKER_REGISTRY_SERVER_URL:将其设置为“https://ghcr.io”
# DOCKER_REGISTRY_SERVER_USERNAME:将其设置为拥有存储库的GitHub用户名或组织
# DOCKER_REGISTRY_SERVER_PASSWORD:将其设置为上一步中PAT令牌的值
#
# 5.更改 AZURE_WEBAPP_NAME 的值。
#
#相关Azure的GitHub Actions的更多信息:https://github.com/Azure/Actions
# 有关 Azure Web Apps 部署操作的更多信息:https://github.com/Azure/webapps-deploy
# 有关开始使用 GitHub Action 工作流部署到 Azure 的更多示例:https://github.com/Azure/actions-workflow-samples
名称:名称:构建容器并将其部署到 Azure Web App
环境:
: AZURE_WEBAPP_NAME : your-app-name # 将其设置为您的 Azure Web 应用程序的名称# 将其设置为您的 Azure Web 应用程序的名称
在:
推:
分支: [ 分支:[ “主” ] “master” ]
工作流程_调度:
权限:
内容: 内容: 阅读
工作:
建造者:
running-on : 运行:ubuntu-latest
脚步:
-使用: - 使用:actions/checkout@v3
-姓名 : - 名称:设置 Docker Buildx
使用: 使用: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0# v3.0.0
- name : - 名称:登录GitHubContainer
使用: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0# v3.0.0
和:
开花: 开花:ghcr.io
用户名: 用户名:$ { { github.actor } } { { github.actor } }
密码: 密码:$ { { github.token } } { { github.token } }
-姓名 : - name:小写的存储库名称和用户名
run : 运行: echo "REPO=${GITHUB_REPOSITORY,,}" >>$ { GITHUB_ENV } “REPO=$ { GITHUB_REPOSITORY , , } ” >>$ { GITHUB_ENV }
-名称: -名称:建造容器将其容器容器中
使用: 使用: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0# v5.0.0
和:
推:真
标签: 标签:ghcr.io/$ { { env.REPO } } : $ { { github.sha } } { { env.REPO } } : $ { { github.sha } }
文件: 文件:./Dockerfile
部署:
权限:
内容: 内容:无
连续运行 : 运行:ubuntu-latest
需求: 需求: 建设
环境:
名称:《发展》
url : 网址:$ { { steps.deploy-to-webapp.outputs.webapp-url } } { { steps.deploy-to-webapp.outputs.webapp-url } }
脚步:
-姓名 : - name:小写的存储库名称和用户名
运行:echo “REPO=$ { GITHUB_REPOSITORY , , } ” >>$ { GITHUB_ENV }
-姓名:部署到Azure Web App
ID :部署到webapp
用途:azure/webapps-deploy@v2
和:
应用程序名称:$ { { env.AZURE_WEBAPP_NAME } }
发布配置文件:$ { { Secrets.AZURE_WEBAPP_PUBLISH_PROFILE } }
图片:'ghcr.io/${{ env.REPO }}:${{ github.sha }}'
================================================
FILE: .github/workflows/docker-image.yml
================================================
姓名:名称:Docker 镜像 CI
on:
push:
branches: [ 分支:[“主”]"master" ]
pull_request:
branches: [ 分支:[“主”]"master" ]
jobs:
build:
runs-on: 运行:ubuntu-latest
steps:
- uses: - 使用:actions/checkout@v3
- name: - 名称:构建 Docker 镜像
run: 运行: docker build 。--file Dockerfile --tag my-image-name:$(日期 +%s): $(日期 +%s)
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
cache/
log/
test/
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
[对应IMA知识库](https://ima.qq.com/wiki/?shareId=8b0da768c77bc863f1cad8eb9482e37a6eeb26ad7171523b687d48c1a67c8e2c):专业量化级股票因子池,每日更新全网全域股票数据,个股信息覆盖超2200个维度栏目,为个股精选提供高维度、高质量的数据核心支撑。 https://ima.qq.com/wiki/?shareId=8b0da768c77bc863f1cad8eb9482e37a6eeb26ad7171523b687d48c1a67c8e2c 。
**InStock股票系统**
InStock股票系统,抓取每日股票、ETF关键数据,计算股票技术指标、筹码分布,识别K线各种形态,综合选股,内置多种选股策略,支持选股验证回测,支持自动交易,支持批量时间,运行高效,支持PC、平板、手机移动设备显示,同时提供Docker镜像方便安装,是量化投资的好帮手。
The stock system,Capture key data on daily stocks and ETFs, calculate stock technical indicators, chip distribution, Position Cost Distribution(CYQ), identify various K-line forms, comprehensive stock selection, built-in multiple stock selection strategies, support stock selection verification and backtesting, support automatic trading, and support batch time , runs efficiently, supports display on PCs, tablets, and mobile phones, and provides Docker images for easy installation, making it a good helper for quantitative investment.
Docker镜像:https://hub.docker.com/r/mayanghua/instock 。
# 功能介绍
## 一:综合选股
综合选股支持股票范围、基本面、技术面、消息面、人气指标、行情数据等方面共200多个信息栏目进行自由组合选股。选股条件分为以下大类:
```
1.股票范围
市场、 行业、地区、 概念、 风格、指数成份、 上市时间。
2.基本面
估值指标、每股指标、盈利能力、成长能力、资本结构与偿债能力、股本股东。
3.技术面
MACD金叉、KDJ金叉、放量突破、低位资金净流入、高位资金净流出、向上突破均线、均线多头排列、均线空头排列、连涨放量、下跌无量、一根大阳线、两根大阳线、旭日东升、强势多方、炮拨云见日、七仙女下凡(七连阴)、八仙过海(八连阳)、九阳神功(九连阳)、四串阳、天量法则、放量上攻、穿头破脚、倒转锤头、射击之星、黄昏之星、曙光初现、身怀六甲、乌云盖顶、早晨之星、窄幅整理。
4.消息面
公告大事、机构关注情况、机构持股家数、机构持股比例。
5.人气指标
股吧人气排名、人气排名变化、人气排名连涨、人气排名连跌、人气排名创新高、人气排名创新低、新晋粉丝占比、铁杆粉丝占比、7日关注排名、今日浏览排名。
6.行情数据
股价表现、成交情况、资金流向、行情统计、沪深股通。
```


## 二:股票每日数据
包括每日股票数据、股票资金流向、股票分红配送、股票龙虎榜、股票大宗交易、股票基本面数据、行业资金流向、概念资金流向、早盘抢筹数据、尾盘抢筹数据、涨停原因揭密、每日ETF数据。
抓取A股票每日数据,主要为一些关键数据,同时封装抓取方法,方便扩展系统获取个人关注的数据。


## 三:股票指标计算
基于talib、pandas 计算指标,计算高效准确。调整个别指标公式,确保结果和同花顺、通信达结果一致。
指标:
```
1、MACD 2、KDJ 3、BOLL 4、TRIX,TRMA 5、CR 6、SMA 7、RSI
8、VR,MAVR 9、ROC 10、DMI,+DI,-DI,DX,ADX,ADXR 11、W&R
12、CCI 13、TR、ATR 14、DMA、AMA 15、OBV 16、SAR 17、PSY
18、BRAR 19、EMV 20、BIAS 21、TEMA 22、MFI 23、VWMA
24、PPO 25、WT 26、Supertrend 27、DPO 28、VHF 29、RVI
30、FI 31、ENE 32、STOCHRSI
```


## 四:判断买入卖出的股票
根据指标判定可能买入卖出的股票,具体筛选条件如下:
```
KDJ:
1、超买区:K值在80以上,D值在70以上,J值大于90时为超买。一般情况下,股价有可能下跌。投资者应谨慎行事,局外人不应再追涨,局内人应适时卖出。
2、超卖区:K值在20以下,D值在30以下为超卖区。一般情况下,股价有可能上涨,反弹的可能性增大。局内人不应轻易抛出股票,局外人可寻机入场。
RSI:
1、当六日指标上升到达80时,表示股市已有超买现象,如果一旦继续上升,超过90以上时,则表示已到严重超买的警戒区,股价已形成头部,极可能在短期内反转回转。
2、当六日强弱指标下降至20时,表示股市有超卖现象,如果一旦继续下降至10以下时则表示已到严重超卖区域,股价极可能有止跌回升的机会。
CCI:
1、当CCI>﹢100时,表明股价已经进入非常态区间——超买区间,股价的异动现象应多加关注。
2、当CCI<﹣100时,表明股价已经进入另一个非常态区间——超卖区间,投资者可以逢低吸纳股票。
CR:
1、跌穿a、b、c、d四条线,再由低点向上爬升160时,为短线获利的一个良机,应适当卖出股票。
2、CR跌至40以下时,是建仓良机。
WR:
1、当%R线达到20时,市场处于超买状况,走势可能即将见顶。
2、当%R线达到80时,市场处于超卖状况,股价走势随时可能见底。
VR:
1、获利区域160-450根据情况获利了结。
2、低价区域40-70可以买进。
```

## 五:K线形态识别
精准识别61种K线形态,支持用户自选形态识别。
识别形态:
```
1、两只乌鸦2、三只乌鸦3、三内部上涨和下跌4、三线打击5、三外部上涨和下跌6、南方三星7、三个白兵8、弃婴
9、大敌当前10、捉腰带线11、脱离12、收盘缺影线13、藏婴吞没14、反击线15、乌云压顶16、十字17、十字星
18、蜻蜓十字/T形十字19、吞噬模式20、十字暮星 21、暮星22、向上/下跳空并列阳线23、墓碑十字/倒T十字
24、锤头25、上吊线26、母子线27、十字孕线28、风高浪大线29、陷阱30、修正陷阱31、家鸽32、三胞胎乌鸦
33、颈内线34、倒锤头35、反冲形态36、由较长缺影线决定的反冲形态37、梯底38、长脚十字39、长蜡烛
40、光头光脚/缺影线 41、相同低价42、铺垫43、十字晨星44、晨星45、颈上线46、刺透形态47、黄包车夫
48、上升/下降三法49、分离线50、射击之星51、短蜡烛52、纺锤53、停顿形态54、条形三明治55、探水竿
56、跳空并列阴阳线57、插入58、三星59、奇特三河床60、向上跳空的两只乌鸦61、上升/下降跳空三法
```
形态识别结果:
```
负:出现卖出信号
0:没有出现该形态
正:出现买入信号
```


## 六:筹码分布
筹码分布通过计算一定时间范围内股票的:最高价、最低价、成交数,输出对应价格成交数占整个流通盘比值的分布图形。计算高效准确,结果与东方财富等专业软件的一致,缺省计算210个交易日的成本,可以自行设定时间范围。

## 七:策略选股
内置放量上涨、停机坪、回踩年线、突破平台、放量跌停等多种选股策略,同时封装了策略模板,方便扩展实现自己的策略。
```
1、放量上涨
1)当日比前一天上涨小于2%或收盘价小于开盘价。
2)当日成交额不低于2亿。
3)当日成交量/5日平均成交量>=2。
2、均线多头
MA30向上
1)30日前的30日均线<20日前的30日均线<10日前的30日均线<当日的30日均线。
2)(当日的30日均线/30日前的30日均线)>1.2。
3、停机坪
1)最近15日有涨幅大于9.5%,且必须是放量上涨。
2)紧接的下个交易日必须高开,收盘价必须上涨,且与开盘价不能大于等于相差3%。
3)接下2、3个交易日必须高开,收盘价必须上涨,且与开盘价不能大于等于相差3%,且每天涨跌幅在5%间。
4、回踩年线
1)分2个时间段:前段=最近60交易日最高收盘价之前交易日(长度>0),后段=最高价当日及后面的交易日。
2)前段由年线(250日)以下向上突破。
3)后段必须在年线以上运行,且后段最低价日与最高价日相差必须在10-50日间。
4)回踩伴随缩量:最高价日交易量/后段最低价日交易量>2,后段最低价/最高价<0.8。
5、突破平台
1)60日内某日收盘价>=60日均线>开盘价。
2)且【1】放量上涨。
3)且【1】间之前时间,任意一天收盘价与60日均线偏离在-5%~20%之间。
6、无大幅回撤
1)当日收盘价比60日前的收盘价的涨幅小于0.6。
2)最近60日,不能有单日跌幅超7%、高开低走7%、两日累计跌幅10%、两日高开低走累计10%。
7、海龟交易法则
最后一个交易日收市价为指定区间内最高价。
1)当日收盘价>=最近60日最高收盘价。
8、高而窄的旗形
1)必须至少上市交易60日。
2)当日收盘价/之前24~10日的最低价>=1.9。
3)之前24~10日必须连续两天涨幅大于等于9.5%。
9、放量跌停。
1)跌>9.5%。
2)成交额不低于2亿。
3)成交量至少是5日平均成交量的4倍。
10、低ATR成长
1)必须至少上市交易250日。
2)最近10个交易日的最高收盘价必须比最近10个交易日的最低收盘价高1.1倍。
11、股票基本面选股
1)市盈率小于等于20,且大于0。
2)市净率小于等于10。
3)净资产收益率大于等于15。
```

## 八:选股验证
对指标、策略等选出的股票进行回测,验证策略的成功率,是否可用。

## 九:自动交易
支持自动交易,内置自动打新股的策略及示例策略,由于**涉及金钱**,规避可能存在风险,没有提供其他交易策略。
具有交易日志,以及支持为每个交易策略配置交易日志。
**特别提醒**:交易日10:00点会触发打新,不想打新的删除stagging.py或不要启动“交易服务”。

## 十:关注功能
支持股票关注,关注股票在各个模块(含有的)置顶、标红显示。
## 十一:支持批量
可以通过时间段、枚举时间、当前时间进行指标计算、策略选股及回测等。同时支持智能识别交易日,可以输入任意日期。
具体执行设置如下:
```
------整体作业,支持批量作业------
当前时间作业 python execute_daily_job.py
单个时间作业 python execute_daily_job.py 2022-03-01
枚举时间作业 python execute_daily_job.py 2022-01-01,2021-02-08,2022-03-12
区间时间作业 python execute_daily_job.py 2022-01-01 2022-03-01
------单功能作业,支持批量作业,回测数据自动填补到当前
基础数据实时作业 python basic_data_daily_job.py
基础数据非实时作业 python basic_data_other_daily_job.py
指标数据作业 python indicators_data_daily_job.py
K线形态作业 klinepattern_data_daily_job.py
策略数据作业 python strategy_data_daily_job.py
回测数据 python backtest_data_daily_job.py
```
## 十二:支持代理及Cookie
支持多代理获取数据。由于很多网站对大量请求有防护机制,使用单一IP地址频繁访问可能导致被封禁或限制访问。代理IP能够帮助分散请求来源,避免单一IP被封锁,从而保证爬虫程序的稳定运行。
支持注入Cookie,解决数据获取频率过高,限制数据获取。
## 十三:存储采用数据库设计
数据存储采用数据库设计,能保存历史数据,以及对数据进行扩展分析、统计、挖掘。系统实现自动创建数据库、数据表,封装了批量更新、插入数据,方便业务扩展。

## 十四:展示采用web设计
采用web设计,可视化展示结果。对展示进行封装,添加新的业务表单,只需要配置视图字典就可自动出现业务可视化界面,方便业务功能扩展。
## 十五:运行高效
采用多线程、单例共享资源有效提高运算效率。1天数据的抓取、计算指标、形态识别、策略选股、回测等全部任务运行时间大概4分钟(普通笔记本),计算天数越多效率越高。
## 十六:方便调试
系统运行的重要日志记录在stock_execute_job.log(数据抓取、处理、分析)、stock_web.log(web服务)、stock_trade.log(交易服务),方便调试发现问题。

# 安装说明
本系统支持Windows、Linux、MacOS,同时本系统创建了Docker镜像,按自己需要选择安装方式。
下面按分常规安装方式、docker镜像安装方式进行一一说明。
## 一:常规安装方式
建议windows下安装,方便操作及使用系统,同时安装也非常简单。
以下安装及运行以windows为例进行介绍。
### 1.安装python
项目开发使用python 3.11,建议最新版。
```
(1)在官网 https://www.python.org/downloads/ 下载安装包,一键安装即可,安装切记勾选自动设置环境变量。
(2)配置永久全局国内镜像库(因为有墙,无法正常安装库文件),执行如下dos命令:
python pip config --global set global.index-url https://mirrors.aliyun.com/pypi/simple/
# 如果你只想为当前用户设置,你也可以去掉下面的"--global"选项
```
### 2.安装mysql
建议最新版。
```
在官网 https://dev.mysql.com/downloads/mysql/ 下载安装包,一键安装即可。
```
### 3.安装 TA-Lib 共享静态库和头文件
安装 TA-Lib C/C++ 共享静态库和头文件
```
https://ta-lib.org/install/ 下载最新 ta-lib 共享静态库和头文件,按照说明进行安装。
安装方式按官方建议,会更简单:
Windows Executable Installer
macOS Homebrew
Linux Debian packages
```
### 4.安装依赖库
依赖库都是目前最新版本。
a.安装依赖库:
```
#dos切换到本系统的根目录,执行下面命令:
python -m pip install -r requirements.txt
```
b.若想升级项目依赖库至最新版,可以通过下面方法:
先打开requirements.txt,然后修改文件中的“==”为“>=”,接着执行下面命令:
```
python -m pip install -r requirements.txt --upgrade
```
c.若扩展了本项目,可以通过下面方法生成项目依赖:
```
#使用pipreqs生成项目相关依赖的requirements.txt
python -m pip install pipreqs
# 安装pipreqs,若有安装可跳过
python -m pipreqs --encoding utf-8 --force ./
# 本项目是utf-8编码
```
### 5.安装 Navicat(可选)
Navicat可以方便管理数据库,以及可以手工对数据进行查看、处理、分析、挖掘。
Navicat是一套可创建多个连接的数据库管理工具,用以方便管理 MySQL、Oracle、PostgreSQL、SQLite、SQL Server、MariaDB 和 MongoDB 等不同类型的数据库
```
(1)在官网 https://www.navicat.com.cn/download/navicat-premium 下载安装包,一键安装即可。
(2)然后下载破解补丁: https://pan.baidu.com/s/18XpTHrm9OiLEl3u6z_uxnw 提取码: 8888 ,破解即可。
```
### 6.配置数据库
一般可能会修改的信息是”数据库访问密码“。
修改database.py相关信息:
```
db_host = "localhost" # 数据库服务主机
db_user = "root" # 数据库访问用户
db_password = "root" # 数据库访问密码
db_port = 3306 # 数据库服务端口
db_charset = "utf8mb4" # 数据库字符集
```
### 7.配置代理
不使用代理,跳过本步。
具体设置如下:
编辑proxy.txt,添加有效代理,格式为:ip:port,带认证代理username:password@ip:port,每个代理占一行。当不使用代理时清空该文件。
编辑保存完代理文件,若本系统已经启动,需要重启本系统,才能生效。
示例代理:
```
127.0.0.1:7860
52.13.248.29:3128
35.178.104.4:80
abc:123456@65.1.244.232:3128
13.126.79.133:80
54.212.22.168:3128
```
注意:以上均为无效代理。
### 8.设置东方财富网Cookie
东方财富数据获取频率过高,会限制获取数据,可以通过注入cookie解决。
以下是详细的操作步骤:
```
1、获取Cookie
打开浏览器,访问东方财富网行情页面:https://quote.eastmoney.com/center/gridlist.html#hs_a_board
登录账号(如果有东方财富网账号,建议登录以获取更稳定的Cookie)
打开开发者工具:
切换到Network(网络)选项卡
刷新页面(按 F5 或点击浏览器刷新按钮)
选择任意请求:在网络请求列表中,选择任意一个请求(建议选择URL包含 push2.eastmoney.com 的请求)
查看Cookie:在请求详情中,找到 Request Headers(请求头)部分,复制完整的 Cookie 值
保存Cookie:将复制的Cookie值保存下来,稍后使用
2、设置Cookie的两种方式
方式一:通过环境变量设置(推荐)
Windows系统:
cmd命令: setx EAST_MONEY_COOKIE "你的Cookie值"
重启Python环境:设置环境变量后,需要重启Python IDE或命令提示符窗口
Linux/macOS系统:
bash命令:export EAST_MONEY_COOKIE="你的Cookie值"
注意:这种方式只在当前终端会话有效,若要永久设置,需要编辑 ~/.bashrc 或 ~/.zshrc 文件
方式二:通过文件设置
编辑eastmoney_cookie.txt文件,替换Cookie。
3、注意事项
Cookie有效期:东方财富网的Cookie通常会在一段时间后过期(一般为几天到几周),如突然无法正常工作,可能是Cookie过期了,需要重新获取并设置
定期更新:建议每隔一段时间(如每周)更新一次Cookie,以确保爬取的稳定性
多账号轮换:如果有多个东方财富网账号,可以轮换使用不同账号的Cookie,进一步降低被限制的风险
```
### 9.安装自动交易(可选)
```
1.安装交易软件
1.1 通用同花顺客户端券商的客户
通用同花顺客户端:
https://activity.ths123.com/acmake/cache/1361.html
1.2 专用同花顺客户端券商的客户
自行去券商官网找同花顺专用版
例如:广发的下载核新独立委托端(同花顺版):
http://www.gf.com.cn/softdownload/index?tab=1
2.安装tesseract(自动识别验证码)
第一种方法.下载编译好的
在下面链接页,根据操作系统选择相应版本
https://digi.bib.uni-mannheim.de/tesseract/
第二种方法.用源码编译
下载源码:https://github.com/tesseract-ocr/tesseract
注意:
安装完要将安装路径设置到PATH环境变量里。
下面提供dos命令设置,以管理员身份运行cmd,输入:
setx /m PATH "%PATH%;C:\Program Files\Tesseract-OCR"
3.设置交易配置
3.1.修改trade_client.json
"user": "888888888888", #交易账号
"password": "888888", #交易密码
"exe_path": "C:/gfzqrzrq/xiadan.exe" #交易软件路径
3.2.修改trade_service.py
broker = 'gf_client' #这是广发
详情参阅usage.md,配置对应券商
```
### 10.运行说明
#### 10.1.执行数据抓取、处理、分析、识别
支持批量作业,具体参见run_job.bat中的注释说明。
建议将其加入到任务计划中,工作日的每天17:00执行。
**数据抓取、处理原则:**
1).开盘即有且无历史数据的:综合选股、每日股票数据、股票资金流向、股票分红配送、龙虎榜、每日ETF数据;
2).收盘即有且有历史数据的:股票指标数据、股票K线形态、股票策略数据;
3).收盘后1~2小时才有且有历史数据的:大宗交易。
运行run_job.bat,会依据上面原则获取各模块当前或前个交易日的数据。
```
运行 run_job.bat
```
若想看开盘后的当前实时数据,可以运行下面,很快大概1秒:
```
#基础数据作业
python basic_data_daily_job.py
```
#### 10.2.启动web服务
```
运行 run_web.bat
```
启动服务后,打开浏览器,输入:http://localhost:9988/ ,即可使用本系统的可视化功能。
#### 10.3.启动交易服务
```
运行 run_trade.bat
```
## 二:docker镜像安装方式
没有docker环境,可以参考:[VirtualBox虚拟机安装Ubuntu](https://www.ljjyy.com/archives/2019/10/100590.html),里面也介绍了python、docker等常用软件的安装,若想在Windows下安装docker自行百度。
### 1.配置代理
不使用代理,跳过本步。
系统安装完成后,可以通过编辑宿主机的代理文件,来配置代理。
具体设置如下:
编辑宿主的代理文件,添加有效代理,格式为:ip:port,带认证代理username:password@ip:port,每个代理占一行。当不使用代理时清空该文件。
编辑完代理文件,若本系统已经启动,需要重启本系统,才能生效。
示例创建代理:
```
sudo sh -c 'echo "127.0.0.1:7860" > /data/instockproxy.txt'
#创建代理文件,会自动替换掉原代理文件
sudo sh -c 'echo "52.13.248.29:3128" >> /data/instockproxy.txt'
#追加代理
sudo sh -c 'echo "abc:123456@35.178.104.4:80" >> /data/instockproxy.txt'
#追加代理
```
注意:以上均为无效代理。
### 2.配置东方财富网Cookie
不使用Cookie,跳过本步。
系统安装完成后,可以通过编辑宿主机的代理文件,来配置Cookie。
详细请参阅:常规安装方式,设置东方财富网Cookie。
```
sudo sh -c 'echo "你的Cookie值" > /data/eastmoneycookie.txt'
#创建代理文件,会自动替换掉原代理文件
```
### 3.安装数据库镜像
如果已经有Mysql、mariadb数据库可以跳过本步。
运行下面命令:
**特别提醒:执行命令的用户要有root权限,其他命令也如此。例如:ubuntu系统在命令前加上sudo** ,sudo docker......
```
docker network create InStockService
docker run -d --name InStockDbService \
--network InStockService \
-v /data/mariadb/data:/var/lib/instockdb \
-e MYSQL_ROOT_PASSWORD=root \
library/mariadb:latest
```
### 4.安装本系统镜像
a.若按上面【1.安装数据库镜像】装的数据库,运行下面命令:
```
docker run -dit --name InStock --network=InStockService \
-p 9988:9988 \
-v /data/instockproxy.txt:/data/InStock/instock/config/proxy.txt \
-v /data/eastmoneycookie.txt:/data/InStock/instock/config/eastmoney_cookie.txt \
-e db_host=InStockDbService \
mayanghua/instock:latest
```
b.已经有Mysql、mariadb数据库,运行下面命令:
```
docker run -dit --name InStock \
-p 9988:9988 \
-v /data/instockproxy.txt:/data/InStock/instock/config/proxy.txt \
-v /data/eastmoneycookie.txt:/data/InStock/instock/config/eastmoney_cookie.txt \
-e db_host=localhost \
-e db_user=root \
-e db_password=root \
-e db_database=instockdb \
-e db_port=3306 \
mayanghua/instock:latest
```
docker -e 参数说明:
```
db_host # 数据库服务主机
db_user # 数据库访问用户
db_password # 数据库访问密码
db_database # 数据库名称
db_port # 数据库服务端口
```
按自己数据库实际情况配置参数。
### 5. 系统运行
启动容器后,会自动运行,首先会初始化数据、启动web服务。然后每小时执行“基础数据抓取”,每天17:30执行所有的数据抓取、处理、分析、识别、回测。
打开浏览器,输入:http://localhost:9988/ ,即可使用本系统的可视化功能。
### 6.历史数据
历史数据抓取、处理、分析、识别、回测,运行下面命令:
```
docker exec -it InStock bash
cat InStock/instock/bin/run_job.sh
#查看run_job.sh注释,自己选择作业
------整体作业,支持批量作业------
当前时间作业 python execute_daily_job.py
单个时间作业 python execute_daily_job.py 2022-03-01
枚举时间作业 python execute_daily_job.py 2022-01-01,2021-02-08,2022-03-12
区间时间作业 python execute_daily_job.py 2022-01-01 2022-03-01
------单功能作业,支持批量作业,回测数据自动填补到当前
综合选股作业 python selection_data_daily_job.py
基础数据实时作业 python basic_data_daily_job.py
基础数据收盘2小时后作业 python backtest_data_daily_job.py
基础数据非实时作业 python basic_data_other_daily_job.py
指标数据作业 python indicators_data_daily_job.py
K线形态作业 klinepattern_data_daily_job.py
策略数据作业 python strategy_data_daily_job.py
回测数据 python backtest_data_daily_job.py
第一种方法:
python execute_daily_job.py 2023-03-01,2023-03-02
第二种方法:
修改run_job.sh,然后运行 bash InStock/instock/bin/run_job.sh
```
### 7.查看日志
运行下面命令:
```
docker exec -it InStock bash
cat InStock/instock/log/stock_execute_job.log
cat InStock/instock/log/stock_web.log
```
### 8.docker常用命令
```
docker container stop InStock InStockDbService
#停止容器
docker container prune
#回收容器
docker rmi mayanghua/instock:latest library/mariadb:latest
#删除镜像
```
具体参见:[Docker基础之 二.镜像及容器的基本操作](https://www.ljjyy.com/archives/2018/06/100208.html)
### 9.自动交易
目前只支持windows。参考常规安装方式,只需安装python、依赖库,**不需安装mysql、talib等**。
# 特别声明
股市有风险投资需谨慎,本系统只能用于学习、股票分析,投资盈亏概不负责。
本系统中的表格为第三方商业控件,仅使用了评估版进行学习及测试。
================================================
FILE: cron/cron.hourly/run_hourly
================================================
#!/bin/sh
/usr/local/bin/python3 /data/InStock/instock/job/basic_data_daily_job.py
#mkdir -p /data/logs
#DATE=`date +%Y-%m-%d:%H:%M:%S`
#echo $DATE >> /data/logs/hourly.log
================================================
FILE: cron/cron.monthly/run_monthly
================================================
#!/bin/sh
#清除缓存数据
rm -rf /data/InStock/instock/cache/hist/*
#MONTH=`date -d '' +%Y%m`
#cd /data/InStock/instock/cache/hist && rm -rf !(${MONTH})
#DATE=`date -d '' +%Y-%m-%d`
#DATE_1=`date -d '-1 days' +%Y-%m-%d`
#DATE_2=`date -d '-2 days' +%Y-%m-%d`
#cd /data/InStock/instock/cache/hist/${MONTH} && rm -rf !(${DATE}|${DATE_1}|${DATE_2})
#mkdir -p /data/logs
#DATE=`date +%Y-%m-%d:%H:%M:%S`
#echo $DATE >> /data/logs/monthly.log
================================================
FILE: cron/cron.workdayly/run_workdayly
================================================
#!/bin/sh
/usr/local/bin/python3 /data/InStock/instock/job/execute_daily_job.py
#mkdir -p /data/logs
#DATE=`date +%Y-%m-%d:%H:%M:%S`
#echo $DATE >> /data/logs/workdayly.log
================================================
FILE: docker/.dockerignore
================================================
.git
.idea
*.bat
*.md
requirements.txt
================================================
FILE: docker/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
docker.*
/cookie.txt
================================================
FILE: docker/Dockerfile
================================================
# 基础镜像
# https://hub.docker.com/_/python/tags?page=1&name=3.11-slim-bullseye
FROM docker.io/python:3.11-slim-bullseye
MAINTAINER myh
#增加语言utf-8
ENV LANG=zh_CN.UTF-8
ENV LC_CTYPE=zh_CN.UTF-8
ENV LC_ALL=C
ENV PYTHONPATH=/data/InStock
EXPOSE 9988
# 使用国内镜像地址加速。修改debian apt更新地址,pip地址,设置时区
# https://opsx.alibaba.com/mirror
# https://mirrors.tuna.tsinghua.edu.cn/help/pypi/
# cat /etc/apt/sources.list 参考原始地址,再确定怎么样替换
# 安装依赖库
# apt-get autoremove -y 删除没有用的依赖lib
# apt-get --purge remove 软件包名称 , 删除已安装包(不保留配置文件)
RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list && \
echo "[global]\n\
index-url = https://mirrors.aliyun.com/pypi/simple\n\
trusted-host = mirrors.aliyun.com" > /etc/pip.conf && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
apt-get update && \
apt-get install -y cron gcc make python3-dev default-libmysqlclient-dev build-essential pkg-config curl && \
pip install supervisor && \
pip install mysqlclient && \
pip install requests && \
pip install arrow && \
pip install numpy && \
pip install SQLAlchemy && \
pip install PyMySQL && \
pip install Logbook && \
pip install python_dateutil && \
pip install py_mini_racer && \
pip install tqdm && \
pip install beautifulsoup4 && \
pip install bokeh && \
pip install pandas && \
pip install urllib3 && \
pip install tornado && \
pip install mini-racer && \
pip install easytrader && \
mkdir ta-lib && \
curl -SL $(curl -s https://api.github.com/repos/ta-lib/ta-lib/releases/latest | grep browser_download_url | cut -d'"' -f4 |grep -E 'tar.gz$') | tar -xz --strip-components=1 -C ./ta-lib && \
cd ta-lib/ && \
./configure && \
make && \
make install && \
cd .. && \
pip install TA-Lib && \
rm -rf ta-lib* && \
apt-get --purge remove -y gcc make python3-dev default-libmysqlclient-dev curl && \
rm -rf /root/.cache/* && rm -rf /var/lib/apt/lists/* && apt-get clean && apt-get autoclean && apt-get autoremove -y
WORKDIR /data
#InStock软件
COPY stock /data/InStock
COPY cron/cron.hourly /etc/cron.hourly
COPY cron/cron.workdayly /etc/cron.workdayly
COPY cron/cron.monthly /etc/cron.monthly
#add cron sesrvice.
#任务调度
RUN chmod 755 /data/InStock/instock/bin/run_*.sh && \
chmod 755 /etc/cron.hourly/* && chmod 755 /etc/cron.workdayly/* && chmod 755 /etc/cron.monthly/* && \
echo "SHELL=/bin/sh \n\
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \n\
# min hour day month weekday command \n\
*/30 9,10,11,13,14,15 * * 1-5 /bin/run-parts /etc/cron.hourly \n\
30 17 * * 1-5 /bin/run-parts /etc/cron.workdayly \n\
30 10 * * 3,6 /bin/run-parts /etc/cron.monthly \n" > /var/spool/cron/crontabs/root && \
chmod 600 /var/spool/cron/crontabs/root
ENTRYPOINT ["supervisord","-n","-c","/data/InStock/supervisor/supervisord.conf"]
================================================
FILE: docker/build.sh
================================================
#!/bin/sh
rm -rf stock
rsync -av --progress ../../stock . --exclude .git --exclude .idea --exclude *.md --exclude *.bat --exclude __pycache__ --exclude .gitignore --exclude stock/cron --exclude stock/img --exclude stock/docker --exclude instock/cache --exclude instock/log --exclude instock/test
rm -rf cron
cp -r ../../stock/cron .
DOCKER_NAME=mayanghua/instock
TAG1=$(date "+%Y%m")
TAG2=latest
echo " docker build -f Dockerfile -t ${DOCKER_NAME} ."
docker build -f Dockerfile -t ${DOCKER_NAME}:${TAG1} -t ${DOCKER_NAME}:${TAG2} .
echo "#################################################################"
echo " docker push ${DOCKER_NAME} "
docker push ${DOCKER_NAME}:${TAG1}
docker push ${DOCKER_NAME}:${TAG2}
================================================
FILE: docker/docker-compose.yml
================================================
version: '4.0.0'
services:
instockdbservice:
image: library/mariadb:latest
container_name: InStockDbService
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- /data/mariadb/data:/var/lib/instockdb
networks:
- instock_network
instock:
image: mayanghua/instock:latest
container_name: InStock
ports:
- "9988:9988"
environment:
db_host: InStockDbService
volumes:
- /data/instockproxy.txt:/data/InStock/instock/config/proxy.txt
depends_on:
- instockdbservice
networks:
- instock_network
networks:
instock_network:
driver: bridge
================================================
FILE: instock/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
cache/
data/
log/
proxy/
================================================
FILE: instock/__init__.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = 'myh '
__date__ = '2023/4/3 '
================================================
FILE: instock/bin/restart_web.sh
================================================
#!/bin/sh
ps -ef | grep python3 | grep '/data/InStock/instock/web/web_service.py' | awk '{print$2}' | xargs kill -9
================================================
FILE: instock/bin/run_cron.sh
================================================
#!/bin/sh
export PYTHONIOENCODING=utf-8
export LANG=zh_CN.UTF-8
export PYTHONPATH=/data/InStock
export LC_CTYPE=zh_CN.UTF-8
# 环境变量输出
# https://stackoverflow.com/questions/27771781/how-can-i-access-docker-set-environment-variables-from-a-cron-job
printenv | grep -v "no_proxy" >> /etc/environment
#启动cron服务。在前台
/usr/sbin/cron -f
================================================
FILE: instock/bin/run_job.bat
================================================
chcp 65001
@echo off
cd %~dp0
cd ..
cd job
echo ------整体作业,支持批量作业------
echo 当前时间作业 python execute_daily_job.py
echo 1个时间作业 python execute_daily_job.py 2023-03-01
echo N个时间作业 python execute_daily_job.py 2023-03-01,2023-03-02
echo 区间作业 python execute_daily_job.py 2023-03-01 2023-03-21
echo ------单功能作业,除了创建数据库,其他都支持批量作业------
echo 创建数据库作业 python init_job.py
echo 综合选股作业 python selection_data_daily_job.py
echo 基础数据实时作业 python basic_data_daily_job.py
echo 基础数据收盘2小时后作业 python backtest_data_daily_job.py
echo 基础数据非实时作业 python basic_data_other_daily_job.py
echo 指标数据作业 python indicators_data_daily_job.py
echo K线形态作业 klinepattern_data_daily_job.py
echo 策略数据作业 python strategy_data_daily_job.py
echo 回测数据 python backtest_data_daily_job.py
echo ------正在执行作业中,请等待------
:: python execute_daily_job.py 2022-01-24,2022-02-25,2022-03-24,2022-04-18,2022-05-18,2022-06-06,2022-07-21,2022-08-26,2022-09-16,2022-10-28,2022-11-04,2022-12-16
::python execute_daily_job.py 2022-01-10,2022-02-14,2022-03-14,2022-04-11,2022-05-10,2022-06-13,2022-07-04,2022-08-08,2022-09-05,2022-10-11,2022-11-14,2022-12-05
:: python execute_daily_job.py 2022-05-18 2022-05-25
python execute_daily_job.py
pause
exit
================================================
FILE: instock/bin/run_job.sh
================================================
#!/bin/sh
#export PYTHONPATH=/data/InStock
#nohup &
/usr/local/bin/python3 /data/InStock/instock/job/execute_daily_job.py
echo ------整体作业 支持批量作业------
echo 当前时间作业 python execute_daily_job.py
echo 1个时间作业 python execute_daily_job.py 2023-03-01
echo N个时间作业 python execute_daily_job.py 2023-03-01,2023-03-02
echo 区间作业 python execute_daily_job.py 2023-03-01 2023-03-21
echo ------单功能作业 除了创建数据库 其他都支持批量作业------
echo 创建数据库作业 python init_job.py
echo 综合选股作业 python selection_data_daily_job.py
echo 基础数据实时作业 python basic_data_daily_job.py
echo 基础数据收盘2小时后作业 python backtest_data_daily_job.py
echo 基础数据非实时作业 python basic_data_other_daily_job.py
echo 指标数据作业 python indicators_data_daily_job.py
echo K线形态作业 klinepattern_data_daily_job.py
echo 策略数据作业 python strategy_data_daily_job.py
echo 回测数据 python backtest_data_daily_job.py
echo ------正在执行作业中 请等待------
================================================
FILE: instock/bin/run_trade.bat
================================================
chcp 65001
@echo off
cd %~dp0
cd ..
cd trade
python trade_service.py
echo ------交易服务已启动,请不要关闭------
pause
exit
================================================
FILE: instock/bin/run_web.bat
================================================
chcp 65001
@echo off
cd %~dp0
cd ..
cd web
python web_service.py
echo ------Web服务已启动,请不要关闭------
echo 访问地址 : http://localhost:9988/
pause
exit
================================================
FILE: instock/bin/run_web.sh
================================================
#!/bin/bash
/usr/local/bin/python3 /data/InStock/instock/web/web_service.py
echo ------Web服务已启动 请不要关闭------
echo 访问地址 : http://localhost:9988/
================================================
FILE: instock/config/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
gf_client.json
================================================
FILE: instock/config/eastmoney_cookie.txt
================================================
================================================
FILE: instock/config/proxy.txt
================================================
================================================
FILE: instock/config/trade_client.json
================================================
{
"user": "888888888888",
"password": "888888",
"exe_path": "C:/gfzqrzrq/xiadan.exe"
}
================================================
FILE: instock/core/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
captcha/
crawling/stock_selection_strengthen.py
================================================
FILE: instock/core/__init__.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = 'myh '
__date__ = '2023/4/3 '
================================================
FILE: instock/core/backtest/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
================================================
FILE: instock/core/backtest/__init__.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = 'myh '
__date__ = '2023/3/13 '
================================================
FILE: instock/core/backtest/rate_stats.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
import numpy as np
import pandas as pd
__author__ = 'myh '
__date__ = '2023/3/10 '
def get_rates(code_name, data, stock_column, threshold=101):
try:
# 增加空判断,如果是空返回 0 数据。
if data is None:
return None
start_date = code_name[0]
code = code_name[1]
# 设置返回数组。
stock_data_list = [start_date, code]
mask = (data['date'] >= start_date)
data = data.loc[mask].copy()
data = data.head(n=threshold)
if len(data.index) <= 1:
return None
close1 = data.iloc[0]['close']
# data.loc[:, 'sum_pct_change'] = data['close'].apply(lambda x: round(100 * (x - close1) / close1, 2))
data.loc[:, 'sum_pct_change'] = np.around(100 * (data['close'].values - close1) / close1, decimals=2)
# 计算区间最高、最低价格
first = True
col_len = len(data.columns)
for row in data.values:
if first:
first = False
else:
stock_data_list.append(row[col_len-1])
_l = len(stock_column) - len(stock_data_list)
for i in range(0, _l):
stock_data_list.append(None)
except Exception as e:
logging.error(f"rate_stats.get_rates处理异常:{code}代码{e}")
return pd.Series(stock_data_list, index=stock_column)
================================================
FILE: instock/core/crawling/__init__.py
================================================
================================================
FILE: instock/core/crawling/fund_etf_em.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/1/4 12:18
Desc: 东方财富-ETF 行情
https://quote.eastmoney.com/sh513500.html
"""
import random
import time
from functools import lru_cache
import math
import pandas as pd
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def fund_etf_spot_em() -> pd.DataFrame:
"""
东方财富-ETF 实时行情
https://quote.eastmoney.com/center/gridlist.html#fund_etf
:return: ETF 实时行情
:rtype: pandas.DataFrame
"""
url = "http://88.push2.eastmoney.com/api/qt/clist/get"
page_size = 50
page_current = 1
params = {
"pn": page_current,
"pz": page_size,
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"wbp2u": "|0|0|0|web",
"fid": "f12",
"fs": "b:MK0021,b:MK0022,b:MK0023,b:MK0024",
"fields": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152",
"_": "1672806290972",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["data"]["diff"]
if not data:
return pd.DataFrame()
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df = pd.DataFrame(data)
temp_df.rename(
columns={
"f12": "代码",
"f14": "名称",
"f2": "最新价",
"f3": "涨跌幅",
"f4": "涨跌额",
"f5": "成交量",
"f6": "成交额",
"f17": "开盘价",
"f15": "最高价",
"f16": "最低价",
"f18": "昨收",
"f8": "换手率",
"f21": "流通市值",
"f20": "总市值",
},
inplace=True,
)
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"开盘价",
"最高价",
"最低价",
"昨收",
"换手率",
"流通市值",
"总市值",
]
]
temp_df["最新价"] = pd.to_numeric(temp_df["最新价"], errors="coerce")
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"], errors="coerce")
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"], errors="coerce")
temp_df["开盘价"] = pd.to_numeric(temp_df["开盘价"], errors="coerce")
temp_df["最高价"] = pd.to_numeric(temp_df["最高价"], errors="coerce")
temp_df["最低价"] = pd.to_numeric(temp_df["最低价"], errors="coerce")
temp_df["昨收"] = pd.to_numeric(temp_df["昨收"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
temp_df["流通市值"] = pd.to_numeric(temp_df["流通市值"], errors="coerce")
temp_df["总市值"] = pd.to_numeric(temp_df["总市值"], errors="coerce")
return temp_df
@lru_cache()
def _fund_etf_code_id_map_em() -> dict:
"""
东方财富-ETF 代码和市场标识映射
https://quote.eastmoney.com/center/gridlist.html#fund_etf
:return: ETF 代码和市场标识映射
:rtype: pandas.DataFrame
"""
url = "http://88.push2.eastmoney.com/api/qt/clist/get"
params = {
"pn": "1",
"pz": "5000",
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"wbp2u": "|0|0|0|web",
"fid": "f3",
"fs": "b:MK0021,b:MK0022,b:MK0023,b:MK0024",
"fields": "f12,f13",
"_": "1672806290972",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["data"]["diff"])
temp_dict = dict(zip(temp_df["f12"], temp_df["f13"]))
return temp_dict
def fund_etf_hist_em(
symbol: str = "159707",
period: str = "daily",
start_date: str = "19700101",
end_date: str = "20500101",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富-ETF 行情
https://quote.eastmoney.com/sz159707.html
:param symbol: ETF 代码
:type symbol: str
:param period: choice of {'daily', 'weekly', 'monthly'}
:type period: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param adjust: choice of {"qfq": "前复权", "hfq": "后复权", "": "不复权"}
:type adjust: str
:return: 每日行情
:rtype: pandas.DataFrame
"""
code_id_dict = _fund_etf_code_id_map_em()
adjust_dict = {"qfq": "1", "hfq": "2", "": "0"}
period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
url = "http://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period_dict[period],
"fqt": adjust_dict[adjust],
"secid": f"{code_id_dict[symbol]}.{symbol}",
"beg": start_date,
"end": end_date,
"_": "1623766962675",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
if not (data_json["data"] and data_json["data"]["klines"]):
return pd.DataFrame()
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
temp_df.columns = [
"日期",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["日期"])
temp_df.reset_index(inplace=True, drop=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["振幅"] = pd.to_numeric(temp_df["振幅"])
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"])
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"])
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"])
return temp_df
def fund_etf_hist_min_em(
symbol: str = "159707",
start_date: str = "1979-09-01 09:32:00",
end_date: str = "2222-01-01 09:32:00",
period: str = "5",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富-ETF 行情
https://quote.eastmoney.com/sz159707.html
:param symbol: ETF 代码
:type symbol: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param period: choice of {'1', '5', '15', '30', '60'}
:type period: str
:param adjust: choice of {'', 'qfq', 'hfq'}
:type adjust: str
:return: 每日分时行情
:rtype: pandas.DataFrame
"""
code_id_dict = _fund_etf_code_id_map_em()
adjust_map = {
"": "0",
"qfq": "1",
"hfq": "2",
}
if period == "1":
url = "https://push2his.eastmoney.com/api/qt/stock/trends2/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"ndays": "5",
"iscr": "0",
"secid": f"{code_id_dict[symbol]}.{symbol}",
"_": "1623766962675",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["trends"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"最新价",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["最新价"] = pd.to_numeric(temp_df["最新价"])
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
return temp_df
else:
url = "http://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period,
"fqt": adjust_map[adjust],
"secid": f"{code_id_dict[symbol]}.{symbol}",
"beg": "0",
"end": "20500000",
"_": "1630930917857",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["klines"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["振幅"] = pd.to_numeric(temp_df["振幅"])
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"])
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"])
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"])
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
temp_df = temp_df[
[
"时间",
"开盘",
"收盘",
"最高",
"最低",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"振幅",
"换手率",
]
]
return temp_df
if __name__ == "__main__":
fund_etf_spot_em_df = fund_etf_spot_em()
print(fund_etf_spot_em_df)
fund_etf_hist_hfq_em_df = fund_etf_hist_em(
symbol="513500",
period="daily",
start_date="20000101",
end_date="20230201",
adjust="hfq",
)
print(fund_etf_hist_hfq_em_df)
fund_etf_hist_qfq_em_df = fund_etf_hist_em(
symbol="000001",
period="daily",
start_date="20000101",
end_date="20230201",
adjust="qfq",
)
print(fund_etf_hist_qfq_em_df)
fund_etf_hist_em_df = fund_etf_hist_em(
symbol="513500",
period="daily",
start_date="20000101",
end_date="20230201",
adjust="",
)
print(fund_etf_hist_em_df)
fund_etf_hist_min_em_df = fund_etf_hist_min_em(
symbol="513500",
period="5",
adjust="hfq",
start_date="2023-01-01 09:32:00",
end_date="2023-01-04 14:40:00",
)
print(fund_etf_hist_min_em_df)
================================================
FILE: instock/core/crawling/stock_chip_race.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/2/26 12:18
Desc: 通达信抢筹
http://excalc.icfqs.com:7616/TQLEX?Entry=HQServ.hq_nlp
"""
import pandas as pd
import requests
from instock.core.singleton_proxy import proxys
__author__ = 'myh '
__date__ = '2025/2/26 '
def stock_chip_race_open(date: str = "") -> pd.DataFrame:
"""
通达信竞价抢筹_早盘抢筹
http://excalc.icfqs.com:7616/TQLEX?Entry=HQServ.hq_nlp
:return: 早盘抢筹
:rtype: pandas.DataFrame
"""
url = "http://excalc.icfqs.com:7616/TQLEX?Entry=HQServ.hq_nlp"
#sort:1抢筹委托金额, 2抢筹成交金额, 3开盘金额, 4抢筹幅度, 5抢筹占比
if date=="":
params = [{"funcId": 20, "offset": 0, "count": 100, "sort": 1, "period": 0,
"Token": "6679f5cadca97d68245a086793fc1bfc0a50b487487c812f", "modname": "JJQC"}]
else:
params = [{"funcId": 20, "offset": 0, "count": 100, "sort": 1, "period": 0,
"Token": "6679f5cadca97d68245a086793fc1bfc0a50b487487c812f", "modname": "JJQC", "date": date}]
headers = {
"Content-Type": "application/json; charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 TdxW",
}
r = requests.post(url, proxies = proxys().get_proxies(), json=params,headers=headers)
data_json = r.json()
data = data_json["datas"]
if not data:
return pd.DataFrame()
temp_df = pd.DataFrame(data)
temp_df.columns = [
"代码",
"名称",
"昨收",
"今开",
"开盘金额",
"抢筹幅度",
"抢筹委托金额",
"抢筹成交金额",
"最新价",
"_",
"天",
"板",
]
temp_df["昨收"] = temp_df["昨收"]/10000
temp_df["今开"] = temp_df["今开"] / 10000
temp_df["抢筹幅度"] = round(temp_df["抢筹幅度"] * 100, 2)
temp_df["最新价"] = round(temp_df["最新价"], 2)
temp_df["涨跌幅"] = round((temp_df["最新价"] / temp_df["昨收"]-1) * 100, 2)
temp_df["抢筹占比"] = round((temp_df["抢筹成交金额"] / temp_df["开盘金额"]) * 100, 2)
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"涨跌幅",
"昨收",
"今开",
"开盘金额",
"抢筹幅度",
"抢筹委托金额",
"抢筹成交金额",
"抢筹占比",
"天",
"板",
]
]
return temp_df
def stock_chip_race_end(date: str = "") -> pd.DataFrame:
"""
通达信竞价抢筹_尾盘抢筹
http://excalc.icfqs.com:7616/TQLEX?Entry=HQServ.hq_nlp
:return: 尾盘抢筹
:rtype: pandas.DataFrame
"""
url = "http://excalc.icfqs.com:7616/TQLEX?Entry=HQServ.hq_nlp"
#sort:1抢筹委托金额, 2抢筹成交金额, 3开盘金额, 4抢筹幅度, 5抢筹占比
if date=="":
params = [{"funcId": 20, "offset": 0, "count": 100, "sort": 1, "period": 1,
"Token": "6679f5cadca97d68245a086793fc1bfc0a50b487487c812f", "modname": "JJQC"}]
else:
params = [{"funcId": 20, "offset": 0, "count": 100, "sort": 1, "period": 1,
"Token": "6679f5cadca97d68245a086793fc1bfc0a50b487487c812f", "modname": "JJQC", "date": date}]
headers = {
"Content-Type": "application/json; charset=UTF-8",
"User-Agent": "TdxW",
}
r = requests.post(url, proxies = proxys().get_proxies(), json=params,headers=headers)
data_json = r.json()
data = data_json["datas"]
if not data:
return pd.DataFrame()
temp_df = pd.DataFrame(data)
temp_df.columns = [
"代码",
"名称",
"昨收",
"今开",
"收盘金额",
"抢筹幅度",
"抢筹委托金额",
"抢筹成交金额",
"最新价",
"_",
"天",
"板",
]
temp_df["昨收"] = temp_df["昨收"]/10000
temp_df["今开"] = temp_df["今开"] / 10000
temp_df["抢筹幅度"] = round(temp_df["抢筹幅度"] * 100, 2)
temp_df["最新价"] = round(temp_df["最新价"], 2)
temp_df["涨跌幅"] = round((temp_df["最新价"] / temp_df["昨收"]-1) * 100, 2)
temp_df["抢筹占比"] = round((temp_df["抢筹成交金额"] / temp_df["收盘金额"]) * 100, 2)
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"涨跌幅",
"昨收",
"今开",
"收盘金额",
"抢筹幅度",
"抢筹委托金额",
"抢筹成交金额",
"抢筹占比",
"天",
"板",
]
]
return temp_df
if __name__ == "__main__":
fund_chip_race_open_df = stock_chip_race_open()
print(fund_chip_race_open_df)
fund_chip_race_end_df = stock_chip_race_end()
print(fund_chip_race_end_df)
================================================
FILE: instock/core/crawling/stock_cpbd.py
================================================
# -*- coding:utf-8 -*-
# !/usr/bin/env python
import pandas as pd
import instock.core.tablestructure as tbs
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_cpbd_em(symbol: str = "688041") -> pd.DataFrame:
"""
东方财富网-个股-操盘必读
https://emweb.securities.eastmoney.com/PC_HSF10/OperationsRequired/Index?type=web&code=SH688041#
:param symbol: 带市场标识的股票代码
:type symbol: str
:return: 操盘必读
:rtype: pandas.DataFrame
"""
url = "https://emweb.securities.eastmoney.com/PC_HSF10/OperationsRequired/PageAjax"
if symbol.startswith("6"):
symbol = f"SH{symbol}"
else:
symbol = f"SZ{symbol}"
params = {"code": symbol}
r = fetcher.make_request(url, params=params)
data_json = r.json()
zxzb = data_json["zxzb"] # 主要指标
if len(zxzb) < 1:
return None
data_dict = zxzb[0]
zxzbOther = data_json["zxzbOther"] # 其它指标,计算出来
if len(zxzbOther) > 0:
zxzbOther = zxzbOther[0]
data_dict = {**data_dict, **zxzbOther}
# zxzbhq = data_json["zxzbhq"] # 其它指标,计算出来
# if len(zxzbhq) > 0:
# data_dict = {**data_dict, **zxzbhq}
_ssbks = data_json["ssbk"] # 所属板块
ssbk = None
for s in _ssbks:
_v = s.get('BOARD_NAME')
if _v is not None:
if ssbk is None:
ssbk = f"{_v}"
else:
ssbk = f"{ssbk}、{_v}"
data_dict["BOARD_NAME"] = ssbk
gdrs = data_json["gdrs"] # 股东分析
if len(gdrs) > 0:
gdrs = gdrs[0]
data_dict = {**data_dict, **gdrs}
lhbd = data_json["lhbd"] # 龙虎榜单
if len(lhbd) > 0:
lhbd = lhbd[0]
lhbd["LHBD_DATE"] = lhbd.pop("TRADE_DATE")
data_dict = {**data_dict, **lhbd}
dzjy = data_json["dzjy"] # 大宗交易
if len(dzjy) > 0:
dzjy = dzjy[0]
dzjy["DZJY_DATE"] = dzjy.pop("TRADE_DATE")
data_dict = {**data_dict, **dzjy}
rzrq = data_json["rzrq"] # 融资融券
if len(rzrq) > 0:
rzrq = rzrq[0]
rzrq["RZRQ_DATE"] = rzrq.pop("TRADE_DATE")
data_dict = {**data_dict, **rzrq}
tbs.CN_STOCK_CPBD
# temp_df["报告期"] = pd.to_datetime(temp_df["报告期"], errors="coerce").dt.date
# temp_df["每股收益"] = pd.to_numeric(temp_df["每股收益"], errors="coerce")
# temp_df["每股净资产"] = pd.to_numeric(temp_df["每股净资产"], errors="coerce")
# temp_df["每股经营现金流"] = pd.to_numeric(temp_df["每股经营现金流"], errors="coerce")
# temp_df["每股公积金"] = pd.to_numeric(temp_df["每股公积金"], errors="coerce")
# temp_df["每股未分配利润"] = pd.to_numeric(temp_df["每股未分配利润"], errors="coerce")
# temp_df["加权净资产收益率"] = pd.to_numeric(temp_df["加权净资产收益率"], errors="coerce")
# temp_df["毛利率"] = pd.to_numeric(temp_df["毛利率"], errors="coerce")
# temp_df["资产负债率"] = pd.to_numeric(temp_df["资产负债率"], errors="coerce")
# temp_df["营业收入"] = pd.to_numeric(temp_df["营业收入"], errors="coerce")
# temp_df["营业收入滚动环比增长"] = pd.to_numeric(temp_df["营业收入同比增长"], errors="coerce")
# temp_df["营业收入同比增长"] = pd.to_numeric(temp_df["营业收入同比增长"], errors="coerce")
# temp_df["归属净利润"] = pd.to_numeric(temp_df["归属净利润"], errors="coerce")
# temp_df["归属净利润滚动环比增长"] = pd.to_numeric(temp_df["归属净利润滚动环比增长"], errors="coerce")
# temp_df["归属净利润同比增长"] = pd.to_numeric(temp_df["归属净利润同比增长"], errors="coerce")
# temp_df["扣非净利润"] = pd.to_numeric(temp_df["归属净利润"], errors="coerce")
# temp_df["扣非净利润滚动环比增长"] = pd.to_numeric(temp_df["扣非净利润滚动环比增长"], errors="coerce")
# temp_df["扣非净利润同比增长"] = pd.to_numeric(temp_df["扣非净利润同比增长"], errors="coerce")
# temp_df["总股本"] = pd.to_numeric(temp_df["总股本"], errors="coerce")
# temp_df["已流通股份"] = pd.to_numeric(temp_df["已流通股份"], errors="coerce")
def stock_zjlx_em(symbol: str = "688041") -> pd.DataFrame:
"""
东方财富网-个股-资金流向
https://data.eastmoney.com/zjlx/688041.html
:param symbol: 带市场标识的股票代码
:type symbol: str
:return: 操盘必读
:rtype: pandas.DataFrame
"""
url = "https://push2his.eastmoney.com/api/qt/stock/fflow/daykline/get"
if symbol.startswith("6"):
symbol = f"1.{symbol}"
else:
symbol = f"0.{symbol}"
params = {
"lmt": "0",
"klt": "1",
"fields1": "f1,f2,f3,f7",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65",
"ut": "b2884a393a59ad64002292a3e90d46a5",
"secid": symbol
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
klines = data_json["klines"] # 主要指标
"日期","主力净流入额","小单净流入额","中单净流入额","大单净流入额","超大单净流入额","主力净流入占比", "小单净流入占比", "中单净流入占比", "大单净流入占比", "超大单净流入占比"
"收盘价","涨跌幅"
if len(klines) < 1:
return None
if __name__ == "__main__":
stock_cpbd_em_df = stock_zjlx_em(symbol="000001")
print(stock_cpbd_em_df)
================================================
FILE: instock/core/crawling/stock_dzjy_em.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2022/5/16 15:31
Desc: 东方财富网-数据中心-大宗交易-市场统计
http://data.eastmoney.com/dzjy/dzjy_sctj.aspx
"""
import random
import time
import pandas as pd
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_dzjy_sctj() -> pd.DataFrame:
"""
东方财富网-数据中心-大宗交易-市场统计
http://data.eastmoney.com/dzjy/dzjy_sctj.aspx
:return: 市场统计表
:rtype: pandas.DataFrame
"""
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
'sortColumns': 'TRADE_DATE',
'sortTypes': '-1',
'pageSize': '500',
'pageNumber': '1',
'reportName': 'PRT_BLOCKTRADE_MARKET_STA',
'columns': 'TRADE_DATE,SZ_INDEX,SZ_CHANGE_RATE,BLOCKTRADE_DEAL_AMT,PREMIUM_DEAL_AMT,PREMIUM_RATIO,DISCOUNT_DEAL_AMT,DISCOUNT_RATIO',
'source': 'WEB',
'client': 'WEB',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = int(data_json['result']["pages"])
big_df = pd.DataFrame()
for page in range(1, total_page+1):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({'pageNumber': page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json['result']["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df['index'] = big_df['index'] + 1
big_df.columns = [
"序号",
"交易日期",
"上证指数",
"上证指数涨跌幅",
"大宗交易成交总额",
"溢价成交总额",
"溢价成交总额占比",
"折价成交总额",
"折价成交总额占比",
]
big_df["交易日期"] = pd.to_datetime(big_df["交易日期"]).dt.date
big_df["上证指数"] = pd.to_numeric(big_df["上证指数"])
big_df["上证指数涨跌幅"] = pd.to_numeric(big_df["上证指数涨跌幅"])
big_df["大宗交易成交总额"] = pd.to_numeric(big_df["大宗交易成交总额"])
big_df["溢价成交总额"] = pd.to_numeric(big_df["溢价成交总额"])
big_df["溢价成交总额占比"] = pd.to_numeric(big_df["溢价成交总额占比"])
big_df["折价成交总额"] = pd.to_numeric(big_df["折价成交总额"])
big_df["折价成交总额占比"] = pd.to_numeric(big_df["折价成交总额占比"])
return big_df
def stock_dzjy_mrmx(symbol: str = '基金', start_date: str = '20220104', end_date: str = '20220104') -> pd.DataFrame:
"""
东方财富网-数据中心-大宗交易-每日明细
http://data.eastmoney.com/dzjy/dzjy_mrmxa.aspx
:param symbol: choice of {'A股', 'B股', '基金', '债券'}
:type symbol: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:return: 每日明细
:rtype: pandas.DataFrame
"""
symbol_map = {
'A股': '1',
'B股': '2',
'基金': '3',
'债券': '4',
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
'sortColumns': 'SECURITY_CODE',
'sortTypes': '1',
'pageSize': '5000',
'pageNumber': '1',
'reportName': 'RPT_DATA_BLOCKTRADE',
'columns': 'TRADE_DATE,SECURITY_CODE,SECUCODE,SECURITY_NAME_ABBR,CHANGE_RATE,CLOSE_PRICE,DEAL_PRICE,PREMIUM_RATIO,DEAL_VOLUME,DEAL_AMT,TURNOVER_RATE,BUYER_NAME,SELLER_NAME,CHANGE_RATE_1DAYS,CHANGE_RATE_5DAYS,CHANGE_RATE_10DAYS,CHANGE_RATE_20DAYS,BUYER_CODE,SELLER_CODE',
'source': 'WEB',
'client': 'WEB',
'filter': f"""(SECURITY_TYPE_WEB={symbol_map[symbol]})(TRADE_DATE>='{'-'.join([start_date[:4], start_date[4:6], start_date[6:]])}')(TRADE_DATE<='{'-'.join([end_date[:4], end_date[4:6], end_date[6:]])}')"""
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
if not data_json['result']["data"]:
return pd.DataFrame()
temp_df = pd.DataFrame(data_json['result']["data"])
temp_df.reset_index(inplace=True)
temp_df['index'] = temp_df.index + 1
if symbol in {'A股'}:
temp_df.columns = [
"序号",
"交易日期",
"证券代码",
"-",
"证券简称",
"涨跌幅",
"收盘价",
"成交价",
"折溢率",
"成交量",
"成交额",
"成交额/流通市值",
"买方营业部",
"卖方营业部",
"_",
"_",
"_",
"_",
"_",
"_",
]
temp_df["交易日期"] = pd.to_datetime(temp_df["交易日期"]).dt.date
temp_df = temp_df[[
"序号",
"交易日期",
"证券代码",
"证券简称",
"涨跌幅",
"收盘价",
"成交价",
"折溢率",
"成交量",
"成交额",
"成交额/流通市值",
"买方营业部",
"卖方营业部",
]]
temp_df['涨跌幅'] = pd.to_numeric(temp_df['涨跌幅'])
temp_df['收盘价'] = pd.to_numeric(temp_df['收盘价'])
temp_df['成交价'] = pd.to_numeric(temp_df['成交价'])
temp_df['折溢率'] = pd.to_numeric(temp_df['折溢率'])
temp_df['成交量'] = pd.to_numeric(temp_df['成交量'])
temp_df['成交额'] = pd.to_numeric(temp_df['成交额'])
temp_df['成交额/流通市值'] = pd.to_numeric(temp_df['成交额/流通市值'])
if symbol in {'B股', '基金', '债券'}:
temp_df.columns = [
"序号",
"交易日期",
"证券代码",
"-",
"证券简称",
"-",
"-",
"成交价",
"-",
"成交量",
"成交额",
"-",
"买方营业部",
"卖方营业部",
"_",
"_",
"_",
"_",
"_",
"_",
]
temp_df["交易日期"] = pd.to_datetime(temp_df["交易日期"]).dt.date
temp_df = temp_df[[
"序号",
"交易日期",
"证券代码",
"证券简称",
"成交价",
"成交量",
"成交额",
"买方营业部",
"卖方营业部",
]]
temp_df['成交价'] = pd.to_numeric(temp_df['成交价'])
temp_df['成交量'] = pd.to_numeric(temp_df['成交量'])
temp_df['成交额'] = pd.to_numeric(temp_df['成交额'])
return temp_df
def stock_dzjy_mrtj(start_date: str = '20220105', end_date: str = '20220105') -> pd.DataFrame:
"""
东方财富网-数据中心-大宗交易-每日统计
http://data.eastmoney.com/dzjy/dzjy_mrtj.aspx
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:return: 每日统计
:rtype: pandas.DataFrame
"""
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
'sortColumns': 'TURNOVERRATE',
'sortTypes': '-1',
'pageSize': '5000',
'pageNumber': '1',
'reportName': 'RPT_BLOCKTRADE_STA',
'columns': 'TRADE_DATE,SECURITY_CODE,SECUCODE,SECURITY_NAME_ABBR,CHANGE_RATE,CLOSE_PRICE,AVERAGE_PRICE,PREMIUM_RATIO,DEAL_NUM,VOLUME,DEAL_AMT,TURNOVERRATE,D1_CLOSE_ADJCHRATE,D5_CLOSE_ADJCHRATE,D10_CLOSE_ADJCHRATE,D20_CLOSE_ADJCHRATE',
'source': 'WEB',
'client': 'WEB',
'filter': f"(TRADE_DATE>='{'-'.join([start_date[:4], start_date[4:6], start_date[6:]])}')(TRADE_DATE<='{'-'.join([end_date[:4], end_date[4:6], end_date[6:]])}')"
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json['result']["data"])
temp_df.reset_index(inplace=True)
temp_df['index'] = temp_df.index + 1
temp_df.columns = [
"序号",
"交易日期",
"证券代码",
"-",
"证券简称",
"涨跌幅",
"收盘价",
"成交价",
"折溢率",
"成交笔数",
"成交总量",
"成交总额",
"成交总额/流通市值",
"_",
"_",
"_",
"_",
]
temp_df["交易日期"] = pd.to_datetime(temp_df["交易日期"]).dt.date
temp_df = temp_df[[
"序号",
"交易日期",
"证券代码",
"证券简称",
"收盘价",
"涨跌幅",
"成交价",
"折溢率",
"成交笔数",
"成交总量",
"成交总额",
"成交总额/流通市值",
]]
temp_df['涨跌幅'] = pd.to_numeric(temp_df['涨跌幅'])
temp_df['收盘价'] = pd.to_numeric(temp_df['收盘价'])
temp_df['成交价'] = pd.to_numeric(temp_df['成交价'])
temp_df['折溢率'] = pd.to_numeric(temp_df['折溢率'])
temp_df['成交笔数'] = pd.to_numeric(temp_df['成交笔数'])
temp_df['成交总量'] = pd.to_numeric(temp_df['成交总量'])
temp_df['成交总额'] = pd.to_numeric(temp_df['成交总额'])
temp_df['成交总额/流通市值'] = pd.to_numeric(temp_df['成交总额/流通市值'])
return temp_df
def stock_dzjy_hygtj(symbol: str = '近三月') -> pd.DataFrame:
"""
东方财富网-数据中心-大宗交易-活跃 A 股统计
http://data.eastmoney.com/dzjy/dzjy_hygtj.aspx
:param symbol: choice of {'近一月', '近三月', '近六月', '近一年'}
:type symbol: str
:return: 活跃 A 股统计
:rtype: pandas.DataFrame
"""
period_map = {
'近一月': '1',
'近三月': '3',
'近六月': '6',
'近一年': '12',
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
'sortColumns': 'DEAL_NUM,SECURITY_CODE',
'sortTypes': '-1,-1',
'pageSize': '5000',
'pageNumber': '1',
'reportName': 'RPT_BLOCKTRADE_ACSTA',
'columns': 'SECURITY_CODE,SECUCODE,SECURITY_NAME_ABBR,CLOSE_PRICE,CHANGE_RATE,TRADE_DATE,DEAL_AMT,PREMIUM_RATIO,SUM_TURNOVERRATE,DEAL_NUM,PREMIUM_TIMES,DISCOUNT_TIMES,D1_AVG_ADJCHRATE,D5_AVG_ADJCHRATE,D10_AVG_ADJCHRATE,D20_AVG_ADJCHRATE,DATE_TYPE_CODE',
'source': 'WEB',
'client': 'WEB',
'filter': f'(DATE_TYPE_CODE={period_map[symbol]})',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json['result']["pages"]
big_df = pd.DataFrame()
for page in range(1, int(total_page)+1):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json['result']["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df['index'] = big_df.index + 1
big_df.columns = [
"序号",
"证券代码",
"_",
"证券简称",
"最新价",
"涨跌幅",
"最近上榜日",
"总成交额",
"折溢率",
"成交总额/流通市值",
"上榜次数-总计",
"上榜次数-溢价",
"上榜次数-折价",
"上榜日后平均涨跌幅-1日",
"上榜日后平均涨跌幅-5日",
"上榜日后平均涨跌幅-10日",
"上榜日后平均涨跌幅-20日",
"_",
]
big_df = big_df[[
"序号",
"证券代码",
"证券简称",
"最新价",
"涨跌幅",
"最近上榜日",
"上榜次数-总计",
"上榜次数-溢价",
"上榜次数-折价",
"总成交额",
"折溢率",
"成交总额/流通市值",
"上榜日后平均涨跌幅-1日",
"上榜日后平均涨跌幅-5日",
"上榜日后平均涨跌幅-10日",
"上榜日后平均涨跌幅-20日",
]]
big_df["最近上榜日"] = pd.to_datetime(big_df["最近上榜日"]).dt.date
big_df["最新价"] = pd.to_numeric(big_df["最新价"])
big_df["涨跌幅"] = pd.to_numeric(big_df["涨跌幅"])
big_df["上榜次数-总计"] = pd.to_numeric(big_df["上榜次数-总计"])
big_df["上榜次数-溢价"] = pd.to_numeric(big_df["上榜次数-溢价"])
big_df["上榜次数-折价"] = pd.to_numeric(big_df["上榜次数-折价"])
big_df["总成交额"] = pd.to_numeric(big_df["总成交额"])
big_df["折溢率"] = pd.to_numeric(big_df["折溢率"])
big_df["成交总额/流通市值"] = pd.to_numeric(big_df["成交总额/流通市值"])
big_df["上榜日后平均涨跌幅-1日"] = pd.to_numeric(big_df["上榜日后平均涨跌幅-1日"])
big_df["上榜日后平均涨跌幅-5日"] = pd.to_numeric(big_df["上榜日后平均涨跌幅-5日"])
big_df["上榜日后平均涨跌幅-10日"] = pd.to_numeric(big_df["上榜日后平均涨跌幅-10日"])
big_df["上榜日后平均涨跌幅-20日"] = pd.to_numeric(big_df["上榜日后平均涨跌幅-20日"])
return big_df
def stock_dzjy_hyyybtj(symbol: str = '近3日') -> pd.DataFrame:
"""
东方财富网-数据中心-大宗交易-活跃营业部统计
https://data.eastmoney.com/dzjy/dzjy_hyyybtj.html
:param symbol: choice of {'当前交易日', '近3日', '近5日', '近10日', '近30日'}
:type symbol: str
:return: 活跃营业部统计
:rtype: pandas.DataFrame
"""
period_map = {
'当前交易日': '1',
'近3日': '3',
'近5日': '5',
'近10日': '10',
'近30日': '30',
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
'sortColumns': 'BUYER_NUM,TOTAL_BUYAMT',
'sortTypes': '-1,-1',
'pageSize': '5000',
'pageNumber': '1',
'reportName': 'RPT_BLOCKTRADE_OPERATEDEPTSTATISTICS',
'columns': 'OPERATEDEPT_CODE,OPERATEDEPT_NAME,ONLIST_DATE,STOCK_DETAILS,BUYER_NUM,SELLER_NUM,TOTAL_BUYAMT,TOTAL_SELLAMT,TOTAL_NETAMT,N_DATE',
'source': 'WEB',
'client': 'WEB',
'filter': f'(N_DATE=-{period_map[symbol]})',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json['result']["pages"]
big_df = pd.DataFrame()
for page in range(1, int(total_page)+1):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json['result']["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df['index'] = big_df.index + 1
big_df.columns = [
"序号",
"_",
"营业部名称",
"最近上榜日",
"买入的股票",
"次数总计-买入",
"次数总计-卖出",
"成交金额统计-买入",
"成交金额统计-卖出",
"成交金额统计-净买入额",
"_",
]
big_df = big_df[[
"序号",
"最近上榜日",
"营业部名称",
"次数总计-买入",
"次数总计-卖出",
"成交金额统计-买入",
"成交金额统计-卖出",
"成交金额统计-净买入额",
"买入的股票",
]]
big_df["最近上榜日"] = pd.to_datetime(big_df["最近上榜日"]).dt.date
big_df["次数总计-买入"] = pd.to_numeric(big_df["次数总计-买入"])
big_df["次数总计-卖出"] = pd.to_numeric(big_df["次数总计-卖出"])
big_df["成交金额统计-买入"] = pd.to_numeric(big_df["成交金额统计-买入"])
big_df["成交金额统计-卖出"] = pd.to_numeric(big_df["成交金额统计-卖出"])
big_df["成交金额统计-净买入额"] = pd.to_numeric(big_df["成交金额统计-净买入额"])
return big_df
def stock_dzjy_yybph(symbol: str = '近三月') -> pd.DataFrame:
"""
东方财富网-数据中心-大宗交易-营业部排行
http://data.eastmoney.com/dzjy/dzjy_yybph.aspx
:param symbol: choice of {'近一月', '近三月', '近六月', '近一年'}
:type symbol: str
:return: 营业部排行
:rtype: pandas.DataFrame
"""
period_map = {
'近一月': '30',
'近三月': '90',
'近六月': '120',
'近一年': '360',
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
'sortColumns': 'D5_BUYER_NUM,D1_AVERAGE_INCREASE',
'sortTypes': '-1,-1',
'pageSize': '5000',
'pageNumber': '1',
'reportName': 'RPT_BLOCKTRADE_OPERATEDEPT_RANK',
'columns': 'OPERATEDEPT_CODE,OPERATEDEPT_NAME,D1_BUYER_NUM,D1_AVERAGE_INCREASE,D1_RISE_PROBABILITY,D5_BUYER_NUM,D5_AVERAGE_INCREASE,D5_RISE_PROBABILITY,D10_BUYER_NUM,D10_AVERAGE_INCREASE,D10_RISE_PROBABILITY,D20_BUYER_NUM,D20_AVERAGE_INCREASE,D20_RISE_PROBABILITY,N_DATE,RELATED_ORG_CODE',
'source': 'WEB',
'client': 'WEB',
'filter': f'(N_DATE=-{period_map[symbol]})',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json['result']["pages"]
big_df = pd.DataFrame()
for page in range(1, int(total_page)+1):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json['result']["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df['index'] = big_df.index + 1
big_df.columns = [
"序号",
"_",
"营业部名称",
"上榜后1天-买入次数",
"上榜后1天-平均涨幅",
"上榜后1天-上涨概率",
"上榜后5天-买入次数",
"上榜后5天-平均涨幅",
"上榜后5天-上涨概率",
"上榜后10天-买入次数",
"上榜后10天-平均涨幅",
"上榜后10天-上涨概率",
"上榜后20天-买入次数",
"上榜后20天-平均涨幅",
"上榜后20天-上涨概率",
"_",
"_",
]
big_df = big_df[[
"序号",
"营业部名称",
"上榜后1天-买入次数",
"上榜后1天-平均涨幅",
"上榜后1天-上涨概率",
"上榜后5天-买入次数",
"上榜后5天-平均涨幅",
"上榜后5天-上涨概率",
"上榜后10天-买入次数",
"上榜后10天-平均涨幅",
"上榜后10天-上涨概率",
"上榜后20天-买入次数",
"上榜后20天-平均涨幅",
"上榜后20天-上涨概率",
]]
big_df['上榜后1天-买入次数'] = pd.to_numeric(big_df['上榜后1天-买入次数'])
big_df['上榜后1天-平均涨幅'] = pd.to_numeric(big_df['上榜后1天-平均涨幅'])
big_df['上榜后1天-上涨概率'] = pd.to_numeric(big_df['上榜后1天-上涨概率'])
big_df['上榜后5天-买入次数'] = pd.to_numeric(big_df['上榜后5天-买入次数'])
big_df['上榜后5天-平均涨幅'] = pd.to_numeric(big_df['上榜后5天-平均涨幅'])
big_df['上榜后5天-上涨概率'] = pd.to_numeric(big_df['上榜后5天-上涨概率'])
big_df['上榜后10天-买入次数'] = pd.to_numeric(big_df['上榜后10天-买入次数'])
big_df['上榜后10天-平均涨幅'] = pd.to_numeric(big_df['上榜后10天-平均涨幅'])
big_df['上榜后10天-上涨概率'] = pd.to_numeric(big_df['上榜后10天-上涨概率'])
big_df['上榜后20天-买入次数'] = pd.to_numeric(big_df['上榜后20天-买入次数'])
big_df['上榜后20天-平均涨幅'] = pd.to_numeric(big_df['上榜后20天-平均涨幅'])
big_df['上榜后20天-上涨概率'] = pd.to_numeric(big_df['上榜后20天-上涨概率'])
return big_df
if __name__ == "__main__":
stock_dzjy_sctj_df = stock_dzjy_sctj()
print(stock_dzjy_sctj_df)
stock_dzjy_mrmx_df = stock_dzjy_mrmx(symbol='债券', start_date='20201204', end_date='20201204')
print(stock_dzjy_mrmx_df)
stock_dzjy_mrtj_df = stock_dzjy_mrtj(start_date='20201204', end_date='20201204')
print(stock_dzjy_mrtj_df)
stock_dzjy_hygtj_df = stock_dzjy_hygtj(symbol='近三月')
print(stock_dzjy_hygtj_df)
stock_dzjy_hyyybtj_df = stock_dzjy_hyyybtj(symbol='近3日')
print(stock_dzjy_hyyybtj_df)
stock_dzjy_yybph_df = stock_dzjy_yybph(symbol='近三月')
print(stock_dzjy_yybph_df)
================================================
FILE: instock/core/crawling/stock_fhps_em.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/4/7 15:22
Desc: 东方财富网-数据中心-年报季报-分红送配
https://data.eastmoney.com/yjfp/
"""
import random
import time
import pandas as pd
from tqdm import tqdm
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_fhps_em(date: str = "20231231") -> pd.DataFrame:
"""
东方财富网-数据中心-年报季报-分红送配
https://data.eastmoney.com/yjfp/
:param date: 分红送配报告期
:type date: str
:return: 分红送配
:rtype: pandas.DataFrame
"""
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "PLAN_NOTICE_DATE",
"sortTypes": "-1",
"pageSize": "500",
"pageNumber": "1",
"reportName": "RPT_SHAREBONUS_DET",
"columns": "ALL",
"quoteColumns": "",
"js": '{"data":(x),"pages":(tp)}',
"source": "WEB",
"client": "WEB",
"filter": f"""(REPORT_DATE='{"-".join([date[:4], date[4:6], date[6:]])}')""",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_pages = int(data_json["result"]["pages"])
big_df = pd.DataFrame()
for page in tqdm(range(1, total_pages + 1), leave=False):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
if not temp_df.empty:
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df.columns = [
"_",
"名称",
"_",
"_",
"代码",
"送转股份-送转总比例",
"送转股份-送转比例",
"送转股份-转股比例",
"现金分红-现金分红比例",
"预案公告日",
"股权登记日",
"除权除息日",
"_",
"方案进度",
"_",
"最新公告日期",
"_",
"_",
"_",
"每股收益",
"每股净资产",
"每股公积金",
"每股未分配利润",
"净利润同比增长",
"总股本",
"_",
"现金分红-股息率",
"-",
"-",
"-",
]
big_df = big_df[
[
"代码",
"名称",
"送转股份-送转总比例",
"送转股份-送转比例",
"送转股份-转股比例",
"现金分红-现金分红比例",
"现金分红-股息率",
"每股收益",
"每股净资产",
"每股公积金",
"每股未分配利润",
"净利润同比增长",
"总股本",
"预案公告日",
"股权登记日",
"除权除息日",
"方案进度",
"最新公告日期",
]
]
big_df["送转股份-送转总比例"] = pd.to_numeric(
big_df["送转股份-送转总比例"], errors="coerce"
)
big_df["送转股份-送转比例"] = pd.to_numeric(
big_df["送转股份-送转比例"], errors="coerce"
)
big_df["送转股份-转股比例"] = pd.to_numeric(
big_df["送转股份-转股比例"], errors="coerce"
)
big_df["现金分红-现金分红比例"] = pd.to_numeric(
big_df["现金分红-现金分红比例"], errors="coerce"
)
big_df["现金分红-股息率"] = pd.to_numeric(
big_df["现金分红-股息率"], errors="coerce"
)
big_df["每股收益"] = pd.to_numeric(big_df["每股收益"], errors="coerce")
big_df["每股净资产"] = pd.to_numeric(big_df["每股净资产"], errors="coerce")
big_df["每股公积金"] = pd.to_numeric(big_df["每股公积金"], errors="coerce")
big_df["每股未分配利润"] = pd.to_numeric(big_df["每股未分配利润"], errors="coerce")
big_df["净利润同比增长"] = pd.to_numeric(big_df["净利润同比增长"], errors="coerce")
big_df["总股本"] = pd.to_numeric(big_df["总股本"], errors="coerce")
big_df["预案公告日"] = pd.to_datetime(big_df["预案公告日"], errors="coerce").dt.date
big_df["股权登记日"] = pd.to_datetime(big_df["股权登记日"], errors="coerce").dt.date
big_df["除权除息日"] = pd.to_datetime(big_df["除权除息日"], errors="coerce").dt.date
big_df["最新公告日期"] = pd.to_datetime(
big_df["最新公告日期"], errors="coerce"
).dt.date
big_df.sort_values(["最新公告日期"], inplace=True, ignore_index=True)
return big_df
if __name__ == "__main__":
stock_fhps_em_df = stock_fhps_em(date="20221231")
print(stock_fhps_em_df)
================================================
FILE: instock/core/crawling/stock_fund_em.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2023/5/16 15:30
Desc: 东方财富网-数据中心-资金流向
https://data.eastmoney.com/zjlx/detail.html
"""
import json
import random
import time
import math
import pandas as pd
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_individual_fund_flow_rank(indicator: str = "5日") -> pd.DataFrame:
"""
东方财富网-数据中心-资金流向-排名
https://data.eastmoney.com/zjlx/detail.html
:param indicator: choice of {"今日", "3日", "5日", "10日"}
:type indicator: str
:return: 指定 indicator 资金流向排行
:rtype: pandas.DataFrame
"""
indicator_map = {
"今日": [
"f62",
"f12,f14,f2,f3,f62,f184,f66,f69,f72,f75,f78,f81,f84,f87,f204,f205,f124",
],
"3日": [
"f267",
"f12,f14,f2,f127,f267,f268,f269,f270,f271,f272,f273,f274,f275,f276,f257,f258,f124",
],
"5日": [
"f164",
"f12,f14,f2,f109,f164,f165,f166,f167,f168,f169,f170,f171,f172,f173,f257,f258,f124",
],
"10日": [
"f174",
"f12,f14,f2,f160,f174,f175,f176,f177,f178,f179,f180,f181,f182,f183,f260,f261,f124",
],
}
url = "http://push2.eastmoney.com/api/qt/clist/get"
page_size = 50
page_current = 1
params = {
"fid": indicator_map[indicator][0],
"po": "1",
"pz": page_size,
"pn": page_current,
"np": "1",
"fltt": "2",
"invt": "2",
"ut": "b2884a393a59ad64002292a3e90d46a5",
"fs": "m:0+t:6+f:!2,m:0+t:13+f:!2,m:0+t:80+f:!2,m:1+t:2+f:!2,m:1+t:23+f:!2,m:0+t:7+f:!2,m:1+t:3+f:!2",
"fields": indicator_map[indicator][1],
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["data"]["diff"]
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df = pd.DataFrame(data)
temp_df = temp_df[~temp_df["f2"].isin(["-"])]
if indicator == "今日":
temp_df.columns = [
"最新价",
"今日涨跌幅",
"代码",
"名称",
"今日主力净流入-净额",
"今日超大单净流入-净额",
"今日超大单净流入-净占比",
"今日大单净流入-净额",
"今日大单净流入-净占比",
"今日中单净流入-净额",
"今日中单净流入-净占比",
"今日小单净流入-净额",
"今日小单净流入-净占比",
"_",
"今日主力净流入-净占比",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"今日涨跌幅",
"今日主力净流入-净额",
"今日主力净流入-净占比",
"今日超大单净流入-净额",
"今日超大单净流入-净占比",
"今日大单净流入-净额",
"今日大单净流入-净占比",
"今日中单净流入-净额",
"今日中单净流入-净占比",
"今日小单净流入-净额",
"今日小单净流入-净占比",
]
]
elif indicator == "3日":
temp_df.columns = [
"最新价",
"代码",
"名称",
"_",
"3日涨跌幅",
"_",
"_",
"_",
"3日主力净流入-净额",
"3日主力净流入-净占比",
"3日超大单净流入-净额",
"3日超大单净流入-净占比",
"3日大单净流入-净额",
"3日大单净流入-净占比",
"3日中单净流入-净额",
"3日中单净流入-净占比",
"3日小单净流入-净额",
"3日小单净流入-净占比",
]
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"3日涨跌幅",
"3日主力净流入-净额",
"3日主力净流入-净占比",
"3日超大单净流入-净额",
"3日超大单净流入-净占比",
"3日大单净流入-净额",
"3日大单净流入-净占比",
"3日中单净流入-净额",
"3日中单净流入-净占比",
"3日小单净流入-净额",
"3日小单净流入-净占比",
]
]
elif indicator == "5日":
temp_df.columns = [
"最新价",
"代码",
"名称",
"5日涨跌幅",
"_",
"5日主力净流入-净额",
"5日主力净流入-净占比",
"5日超大单净流入-净额",
"5日超大单净流入-净占比",
"5日大单净流入-净额",
"5日大单净流入-净占比",
"5日中单净流入-净额",
"5日中单净流入-净占比",
"5日小单净流入-净额",
"5日小单净流入-净占比",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"5日涨跌幅",
"5日主力净流入-净额",
"5日主力净流入-净占比",
"5日超大单净流入-净额",
"5日超大单净流入-净占比",
"5日大单净流入-净额",
"5日大单净流入-净占比",
"5日中单净流入-净额",
"5日中单净流入-净占比",
"5日小单净流入-净额",
"5日小单净流入-净占比",
]
]
elif indicator == "10日":
temp_df.columns = [
"最新价",
"代码",
"名称",
"_",
"10日涨跌幅",
"10日主力净流入-净额",
"10日主力净流入-净占比",
"10日超大单净流入-净额",
"10日超大单净流入-净占比",
"10日大单净流入-净额",
"10日大单净流入-净占比",
"10日中单净流入-净额",
"10日中单净流入-净占比",
"10日小单净流入-净额",
"10日小单净流入-净占比",
"_",
"_",
"_",
]
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"10日涨跌幅",
"10日主力净流入-净额",
"10日主力净流入-净占比",
"10日超大单净流入-净额",
"10日超大单净流入-净占比",
"10日大单净流入-净额",
"10日大单净流入-净占比",
"10日中单净流入-净额",
"10日中单净流入-净占比",
"10日小单净流入-净额",
"10日小单净流入-净占比",
]
]
# temp_df['最新价'] = pd.to_numeric(temp_df['最新价'], errors="coerce").fillna(0)
return temp_df
def stock_sector_fund_flow_rank(
indicator: str = "10日", sector_type: str = "行业资金流"
) -> pd.DataFrame:
"""
东方财富网-数据中心-资金流向-板块资金流-排名
https://data.eastmoney.com/bkzj/hy.html
:param indicator: choice of {"今日", "5日", "10日"}
:type indicator: str
:param sector_type: choice of {"行业资金流", "概念资金流", "地域资金流"}
:type sector_type: str
:return: 指定参数的资金流排名数据
:rtype: pandas.DataFrame
"""
sector_type_map = {"行业资金流": "2", "概念资金流": "3", "地域资金流": "1"}
indicator_map = {
"今日": [
"f62",
"1",
"f12,f14,f2,f3,f62,f184,f66,f69,f72,f75,f78,f81,f84,f87,f204,f205,f124",
],
"5日": [
"f164",
"5",
"f12,f14,f2,f109,f164,f165,f166,f167,f168,f169,f170,f171,f172,f173,f257,f258,f124",
],
"10日": [
"f174",
"10",
"f12,f14,f2,f160,f174,f175,f176,f177,f178,f179,f180,f181,f182,f183,f260,f261,f124",
],
}
url = "http://push2.eastmoney.com/api/qt/clist/get"
page_size = 50
page_current = 1
params = {
"pn": page_current,
"pz": page_size,
"po": "1",
"np": "1",
"ut": "b2884a393a59ad64002292a3e90d46a5",
"fltt": "2",
"invt": "2",
"fid0": indicator_map[indicator][0],
"fs": f"m:90 t:{sector_type_map[sector_type]}",
"stat": indicator_map[indicator][1],
"fields": indicator_map[indicator][2],
"rt": "52975239",
"cb": "jQuery18308357908311220152_1589256588824",
"_": int(time.time() * 1000),
}
r = fetcher.make_request(url, params=params)
text_data = r.text
data_json = json.loads(text_data[text_data.find("{") : -2])
data = data_json["data"]["diff"]
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
text_data = r.text
json_data = json.loads(text_data[text_data.find("{"): -2])
_data = json_data["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df = pd.DataFrame(data)
temp_df = temp_df[~temp_df["f2"].isin(["-"])]
if indicator == "今日":
temp_df.columns = [
"-",
"今日涨跌幅",
"_",
"名称",
"今日主力净流入-净额",
"今日超大单净流入-净额",
"今日超大单净流入-净占比",
"今日大单净流入-净额",
"今日大单净流入-净占比",
"今日中单净流入-净额",
"今日中单净流入-净占比",
"今日小单净流入-净额",
"今日小单净流入-净占比",
"-",
"今日主力净流入-净占比",
"今日主力净流入最大股",
"今日主力净流入最大股代码",
"是否净流入",
]
temp_df = temp_df[
[
"名称",
"今日涨跌幅",
"今日主力净流入-净额",
"今日主力净流入-净占比",
"今日超大单净流入-净额",
"今日超大单净流入-净占比",
"今日大单净流入-净额",
"今日大单净流入-净占比",
"今日中单净流入-净额",
"今日中单净流入-净占比",
"今日小单净流入-净额",
"今日小单净流入-净占比",
"今日主力净流入最大股",
]
]
elif indicator == "5日":
temp_df.columns = [
"-",
"_",
"名称",
"5日涨跌幅",
"_",
"5日主力净流入-净额",
"5日主力净流入-净占比",
"5日超大单净流入-净额",
"5日超大单净流入-净占比",
"5日大单净流入-净额",
"5日大单净流入-净占比",
"5日中单净流入-净额",
"5日中单净流入-净占比",
"5日小单净流入-净额",
"5日小单净流入-净占比",
"5日主力净流入最大股",
"_",
"_",
]
temp_df = temp_df[
[
"名称",
"5日涨跌幅",
"5日主力净流入-净额",
"5日主力净流入-净占比",
"5日超大单净流入-净额",
"5日超大单净流入-净占比",
"5日大单净流入-净额",
"5日大单净流入-净占比",
"5日中单净流入-净额",
"5日中单净流入-净占比",
"5日小单净流入-净额",
"5日小单净流入-净占比",
"5日主力净流入最大股",
]
]
elif indicator == "10日":
temp_df.columns = [
"-",
"_",
"名称",
"_",
"10日涨跌幅",
"10日主力净流入-净额",
"10日主力净流入-净占比",
"10日超大单净流入-净额",
"10日超大单净流入-净占比",
"10日大单净流入-净额",
"10日大单净流入-净占比",
"10日中单净流入-净额",
"10日中单净流入-净占比",
"10日小单净流入-净额",
"10日小单净流入-净占比",
"10日主力净流入最大股",
"_",
"_",
]
temp_df = temp_df[
[
"名称",
"10日涨跌幅",
"10日主力净流入-净额",
"10日主力净流入-净占比",
"10日超大单净流入-净额",
"10日超大单净流入-净占比",
"10日大单净流入-净额",
"10日大单净流入-净占比",
"10日中单净流入-净额",
"10日中单净流入-净占比",
"10日小单净流入-净额",
"10日小单净流入-净占比",
"10日主力净流入最大股",
]
]
return temp_df
if __name__ == "__main__":
stock_individual_fund_flow_rank_df = stock_individual_fund_flow_rank(indicator="今日")
print(stock_individual_fund_flow_rank_df)
stock_individual_fund_flow_rank_df = stock_individual_fund_flow_rank(indicator="3日")
print(stock_individual_fund_flow_rank_df)
stock_individual_fund_flow_rank_df = stock_individual_fund_flow_rank(indicator="5日")
print(stock_individual_fund_flow_rank_df)
stock_individual_fund_flow_rank_df = stock_individual_fund_flow_rank(
indicator="10日"
)
print(stock_individual_fund_flow_rank_df)
stock_sector_fund_flow_rank_df = stock_sector_fund_flow_rank(
indicator="5日", sector_type="概念资金流"
)
print(stock_sector_fund_flow_rank_df)
stock_sector_fund_flow_rank_df = stock_sector_fund_flow_rank(
indicator="今日", sector_type="行业资金流"
)
print(stock_sector_fund_flow_rank_df)
================================================
FILE: instock/core/crawling/stock_hist_em.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2022/6/19 15:26
Desc: 东方财富网-行情首页-沪深京 A 股
"""
import random
import time
import pandas as pd
import math
from functools import lru_cache
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_zh_a_spot_em() -> pd.DataFrame:
"""
东方财富网-沪深京 A 股-实时行情
https://quote.eastmoney.com/center/gridlist.html#hs_a_board
:return: 实时行情
:rtype: pandas.DataFrame
"""
url = "http://82.push2.eastmoney.com/api/qt/clist/get"
page_size = 50
page_current = 1
params = {
"pn": page_current,
"pz": page_size,
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f12",
"fs": "m:0 t:6,m:0 t:80,m:1 t:2,m:1 t:23,m:0 t:81 s:2048",
"fields": "f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f14,f15,f16,f17,f18,f20,f21,f22,f23,f24,f25,f26,f37,f38,f39,f40,f41,f45,f46,f48,f49,f57,f61,f100,f112,f113,f114,f115,f221",
"_": "1623833739532",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["data"]["diff"]
if not data:
return pd.DataFrame()
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df = pd.DataFrame(data)
temp_df.columns = [
"最新价",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"振幅",
"换手率",
"市盈率动",
"量比",
"5分钟涨跌",
"代码",
"名称",
"最高",
"最低",
"今开",
"昨收",
"总市值",
"流通市值",
"涨速",
"市净率",
"60日涨跌幅",
"年初至今涨跌幅",
"上市时间",
"加权净资产收益率",
"总股本",
"已流通股份",
"营业收入",
"营业收入同比增长",
"归属净利润",
"归属净利润同比增长",
"每股未分配利润",
"毛利率",
"资产负债率",
"每股公积金",
"所处行业",
"每股收益",
"每股净资产",
"市盈率静",
"市盈率TTM",
"报告期"
]
temp_df = temp_df[
[
"代码",
"名称",
"最新价",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"振幅",
"换手率",
"量比",
"今开",
"最高",
"最低",
"昨收",
"涨速",
"5分钟涨跌",
"60日涨跌幅",
"年初至今涨跌幅",
"市盈率动",
"市盈率TTM",
"市盈率静",
"市净率",
"每股收益",
"每股净资产",
"每股公积金",
"每股未分配利润",
"加权净资产收益率",
"毛利率",
"资产负债率",
"营业收入",
"营业收入同比增长",
"归属净利润",
"归属净利润同比增长",
"报告期",
"总股本",
"已流通股份",
"总市值",
"流通市值",
"所处行业",
"上市时间"
]
]
temp_df["最新价"] = pd.to_numeric(temp_df["最新价"], errors="coerce")
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"], errors="coerce")
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"], errors="coerce")
temp_df["振幅"] = pd.to_numeric(temp_df["振幅"], errors="coerce")
temp_df["量比"] = pd.to_numeric(temp_df["量比"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
temp_df["最高"] = pd.to_numeric(temp_df["最高"], errors="coerce")
temp_df["最低"] = pd.to_numeric(temp_df["最低"], errors="coerce")
temp_df["今开"] = pd.to_numeric(temp_df["今开"], errors="coerce")
temp_df["昨收"] = pd.to_numeric(temp_df["昨收"], errors="coerce")
temp_df["涨速"] = pd.to_numeric(temp_df["涨速"], errors="coerce")
temp_df["5分钟涨跌"] = pd.to_numeric(temp_df["5分钟涨跌"], errors="coerce")
temp_df["60日涨跌幅"] = pd.to_numeric(temp_df["60日涨跌幅"], errors="coerce")
temp_df["年初至今涨跌幅"] = pd.to_numeric(temp_df["年初至今涨跌幅"], errors="coerce")
temp_df["市盈率动"] = pd.to_numeric(temp_df["市盈率动"], errors="coerce")
temp_df["市盈率TTM"] = pd.to_numeric(temp_df["市盈率TTM"], errors="coerce")
temp_df["市盈率静"] = pd.to_numeric(temp_df["市盈率静"], errors="coerce")
temp_df["市净率"] = pd.to_numeric(temp_df["市净率"], errors="coerce")
temp_df["每股收益"] = pd.to_numeric(temp_df["每股收益"], errors="coerce")
temp_df["每股净资产"] = pd.to_numeric(temp_df["每股净资产"], errors="coerce")
temp_df["每股公积金"] = pd.to_numeric(temp_df["每股公积金"], errors="coerce")
temp_df["每股未分配利润"] = pd.to_numeric(temp_df["每股未分配利润"], errors="coerce")
temp_df["加权净资产收益率"] = pd.to_numeric(temp_df["加权净资产收益率"], errors="coerce")
temp_df["毛利率"] = pd.to_numeric(temp_df["毛利率"], errors="coerce")
temp_df["资产负债率"] = pd.to_numeric(temp_df["资产负债率"], errors="coerce")
temp_df["营业收入"] = pd.to_numeric(temp_df["营业收入"], errors="coerce")
temp_df["营业收入同比增长"] = pd.to_numeric(temp_df["营业收入同比增长"], errors="coerce")
temp_df["归属净利润"] = pd.to_numeric(temp_df["归属净利润"], errors="coerce")
temp_df["归属净利润同比增长"] = pd.to_numeric(temp_df["归属净利润同比增长"], errors="coerce")
temp_df["报告期"] = pd.to_datetime(temp_df["报告期"], format='%Y%m%d', errors="coerce")
temp_df["总股本"] = pd.to_numeric(temp_df["总股本"], errors="coerce")
temp_df["已流通股份"] = pd.to_numeric(temp_df["已流通股份"], errors="coerce")
temp_df["总市值"] = pd.to_numeric(temp_df["总市值"], errors="coerce")
temp_df["流通市值"] = pd.to_numeric(temp_df["流通市值"], errors="coerce")
temp_df["上市时间"] = pd.to_datetime(temp_df["上市时间"], format='%Y%m%d', errors="coerce")
return temp_df
@lru_cache()
def code_id_map_em() -> dict:
"""
东方财富-股票和市场代码
http://quote.eastmoney.com/center/gridlist.html#hs_a_board
:return: 股票和市场代码
:rtype: dict
"""
url = "http://80.push2.eastmoney.com/api/qt/clist/get"
page_size = 50
page_current = 1
params = {
"pn": page_current,
"pz": page_size,
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f12",
"fs": "m:1 t:2,m:1 t:23",
"fields": "f12",
"_": "1623833739532",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["data"]["diff"]
if not data:
return dict()
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df = pd.DataFrame(data)
temp_df["market_id"] = 1
temp_df.columns = ["sh_code", "sh_id"]
code_id_dict = dict(zip(temp_df["sh_code"], temp_df["sh_id"]))
page_current = 1
params = {
"pn": page_current,
"pz": page_size,
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f12",
"fs": "m:0 t:6,m:0 t:80",
"fields": "f12",
"_": "1623833739532",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["data"]["diff"]
if not data:
return dict()
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df_sz = pd.DataFrame(data)
temp_df_sz["sz_id"] = 0
code_id_dict.update(dict(zip(temp_df_sz["f12"], temp_df_sz["sz_id"])))
page_current = 1
params = {
"pn": page_current,
"pz": page_size,
"po": "1",
"np": "1",
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
"fltt": "2",
"invt": "2",
"fid": "f12",
"fs": "m:0 t:81 s:2048",
"fields": "f12",
"_": "1623833739532",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["data"]["diff"]
if not data:
return dict()
data_count = data_json["data"]["total"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["pn"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["data"]["diff"]
data.extend(_data)
page_count =page_count - 1
temp_df_sz = pd.DataFrame(data)
temp_df_sz["bj_id"] = 0
code_id_dict.update(dict(zip(temp_df_sz["f12"], temp_df_sz["bj_id"])))
return code_id_dict
def stock_zh_a_hist(
symbol: str = "000001",
period: str = "daily",
start_date: str = "19700101",
end_date: str = "20500101",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富网-行情首页-沪深京 A 股-每日行情
https://quote.eastmoney.com/concept/sh603777.html?from=classic
:param symbol: 股票代码
:type symbol: str
:param period: choice of {'daily', 'weekly', 'monthly'}
:type period: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param adjust: choice of {"qfq": "前复权", "hfq": "后复权", "": "不复权"}
:type adjust: str
:return: 每日行情
:rtype: pandas.DataFrame
"""
code_id_dict = code_id_map_em()
adjust_dict = {"qfq": "1", "hfq": "2", "": "0"}
period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
url = "http://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period_dict[period],
"fqt": adjust_dict[adjust],
"secid": f"1.{symbol}" if symbol.startswith('6') else f"0.{symbol}",
"beg": start_date,
"end": end_date,
"_": "1623766962675",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
if not (data_json["data"] and data_json["data"]["klines"]):
return pd.DataFrame()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["klines"]]
)
temp_df.columns = [
"日期",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["日期"])
temp_df.reset_index(inplace=True, drop=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["振幅"] = pd.to_numeric(temp_df["振幅"])
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"])
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"])
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"])
return temp_df
def stock_zh_a_hist_min_em(
symbol: str = "000001",
start_date: str = "1979-09-01 09:32:00",
end_date: str = "2222-01-01 09:32:00",
period: str = "5",
adjust: str = "",
) -> pd.DataFrame:
"""
东方财富网-行情首页-沪深京 A 股-每日分时行情
https://quote.eastmoney.com/concept/sh603777.html?from=classic
:param symbol: 股票代码
:type symbol: str
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:param period: choice of {'1', '5', '15', '30', '60'}
:type period: str
:param adjust: choice of {'', 'qfq', 'hfq'}
:type adjust: str
:return: 每日分时行情
:rtype: pandas.DataFrame
"""
code_id_dict = code_id_map_em()
adjust_map = {
"": "0",
"qfq": "1",
"hfq": "2",
}
if period == "1":
url = "https://push2his.eastmoney.com/api/qt/stock/trends2/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"ndays": "5",
"iscr": "0",
"secid": f"1.{symbol}" if symbol.startswith('6') else f"0.{symbol}",
"_": "1623766962675",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["trends"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"最新价",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["最新价"] = pd.to_numeric(temp_df["最新价"])
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
return temp_df
else:
url = "http://push2his.eastmoney.com/api/qt/stock/kline/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",
"ut": "7eea3edcaed734bea9cbfc24409ed989",
"klt": period,
"fqt": adjust_map[adjust],
"secid": f"1.{symbol}" if symbol.startswith('6') else f"0.{symbol}",
"beg": "0",
"end": "20500000",
"_": "1630930917857",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["klines"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"振幅",
"涨跌幅",
"涨跌额",
"换手率",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
temp_df = temp_df[start_date:end_date]
temp_df.reset_index(drop=True, inplace=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["振幅"] = pd.to_numeric(temp_df["振幅"])
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"])
temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"])
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"])
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
temp_df = temp_df[
[
"时间",
"开盘",
"收盘",
"最高",
"最低",
"涨跌幅",
"涨跌额",
"成交量",
"成交额",
"振幅",
"换手率",
]
]
return temp_df
def stock_zh_a_hist_pre_min_em(
symbol: str = "000001",
start_time: str = "09:00:00",
end_time: str = "15:50:00",
) -> pd.DataFrame:
"""
东方财富网-行情首页-沪深京 A 股-每日分时行情包含盘前数据
http://quote.eastmoney.com/concept/sh603777.html?from=classic
:param symbol: 股票代码
:type symbol: str
:param start_time: 开始时间
:type start_time: str
:param end_time: 结束时间
:type end_time: str
:return: 每日分时行情包含盘前数据
:rtype: pandas.DataFrame
"""
code_id_dict = code_id_map_em()
url = "https://push2.eastmoney.com/api/qt/stock/trends2/get"
params = {
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58",
"ut": "fa5fd1943c7b386f172d6893dbfba10b",
"ndays": "1",
"iscr": "1",
"iscca": "0",
"secid": f"1.{symbol}" if symbol.startswith('6') else f"0.{symbol}",
"_": "1623766962675",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(
[item.split(",") for item in data_json["data"]["trends"]]
)
temp_df.columns = [
"时间",
"开盘",
"收盘",
"最高",
"最低",
"成交量",
"成交额",
"最新价",
]
temp_df.index = pd.to_datetime(temp_df["时间"])
date_format = temp_df.index[0].date().isoformat()
temp_df = temp_df[
date_format + " " + start_time : date_format + " " + end_time
]
temp_df.reset_index(drop=True, inplace=True)
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"])
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"])
temp_df["最高"] = pd.to_numeric(temp_df["最高"])
temp_df["最低"] = pd.to_numeric(temp_df["最低"])
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"])
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"])
temp_df["最新价"] = pd.to_numeric(temp_df["最新价"])
temp_df["时间"] = pd.to_datetime(temp_df["时间"]).astype(str)
return temp_df
if __name__ == "__main__":
stock_zh_a_spot_em_df = stock_zh_a_spot_em()
print(stock_zh_a_spot_em_df)
code_id_map_em_df = code_id_map_em()
print(code_id_map_em_df)
stock_zh_a_hist_df = stock_zh_a_hist(
symbol="000001",
period="daily",
start_date="20220516",
end_date="20220722",
adjust="hfq",
)
print(stock_zh_a_hist_df)
stock_zh_a_hist_min_em_df = stock_zh_a_hist_min_em(symbol="000001", period="1")
print(stock_zh_a_hist_min_em_df)
stock_zh_a_hist_pre_min_em_df = stock_zh_a_hist_pre_min_em(symbol="000001")
print(stock_zh_a_hist_pre_min_em_df)
stock_zh_a_spot_em_df = stock_zh_a_spot_em()
print(stock_zh_a_spot_em_df)
stock_zh_a_hist_min_em_df = stock_zh_a_hist_min_em(
symbol="000001", period='1'
)
print(stock_zh_a_hist_min_em_df)
stock_zh_a_hist_df = stock_zh_a_hist(
symbol="000001",
period="daily",
start_date="20170301",
end_date="20211115",
adjust="hfq",
)
print(stock_zh_a_hist_df)
================================================
FILE: instock/core/crawling/stock_lhb_em.py
================================================
# -*- coding:utf-8 -*-
# !/usr/bin/env python
"""
Date: 2022/3/15 17:32
Desc: 东方财富网-数据中心-龙虎榜单
https://data.eastmoney.com/stock/tradedetail.html
"""
import random
import time
import pandas as pd
from tqdm import tqdm
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_lhb_detail_em(
start_date: str = "20230403", end_date: str = "20230417"
) -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-龙虎榜详情
https://data.eastmoney.com/stock/tradedetail.html
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:return: 龙虎榜详情
:rtype: pandas.DataFrame
"""
start_date = "-".join([start_date[:4], start_date[4:6], start_date[6:]])
end_date = "-".join([end_date[:4], end_date[4:6], end_date[6:]])
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "SECURITY_CODE,TRADE_DATE",
"sortTypes": "1,-1",
"pageSize": "5000",
"pageNumber": "1",
"reportName": "RPT_DAILYBILLBOARD_DETAILSNEW",
"columns": "SECURITY_CODE,SECUCODE,SECURITY_NAME_ABBR,TRADE_DATE,EXPLAIN,CLOSE_PRICE,CHANGE_RATE,BILLBOARD_NET_AMT,BILLBOARD_BUY_AMT,BILLBOARD_SELL_AMT,BILLBOARD_DEAL_AMT,ACCUM_AMOUNT,DEAL_NET_RATIO,DEAL_AMOUNT_RATIO,TURNOVERRATE,FREE_MARKET_CAP,EXPLANATION,D1_CLOSE_ADJCHRATE,D2_CLOSE_ADJCHRATE,D5_CLOSE_ADJCHRATE,D10_CLOSE_ADJCHRATE,SECURITY_TYPE_CODE",
"source": "WEB",
"client": "WEB",
"filter": f"(TRADE_DATE<='{end_date}')(TRADE_DATE>='{start_date}')",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page_num = data_json["result"]["pages"]
big_df = pd.DataFrame()
for page in range(1, total_page_num + 1):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update(
{
"pageNumber": page,
}
)
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
big_df.rename(
columns={
"index": "-",
"SECURITY_CODE": "代码",
"SECUCODE": "-",
"SECURITY_NAME_ABBR": "名称",
"TRADE_DATE": "上榜日",
"EXPLAIN": "解读",
"CLOSE_PRICE": "收盘价",
"CHANGE_RATE": "涨跌幅",
"BILLBOARD_NET_AMT": "龙虎榜净买额",
"BILLBOARD_BUY_AMT": "龙虎榜买入额",
"BILLBOARD_SELL_AMT": "龙虎榜卖出额",
"BILLBOARD_DEAL_AMT": "龙虎榜成交额",
"ACCUM_AMOUNT": "市场总成交额",
"DEAL_NET_RATIO": "净买额占总成交比",
"DEAL_AMOUNT_RATIO": "成交额占总成交比",
"TURNOVERRATE": "换手率",
"FREE_MARKET_CAP": "流通市值",
"EXPLANATION": "上榜原因",
"D1_CLOSE_ADJCHRATE": "上榜后1日",
"D2_CLOSE_ADJCHRATE": "上榜后2日",
"D5_CLOSE_ADJCHRATE": "上榜后5日",
"D10_CLOSE_ADJCHRATE": "上榜后10日",
},
inplace=True,
)
big_df = big_df[
[
"代码",
"名称",
"上榜日",
"解读",
"收盘价",
"涨跌幅",
"龙虎榜净买额",
"龙虎榜买入额",
"龙虎榜卖出额",
"龙虎榜成交额",
"市场总成交额",
"净买额占总成交比",
"成交额占总成交比",
"换手率",
"流通市值",
"上榜原因",
"上榜后1日",
"上榜后2日",
"上榜后5日",
"上榜后10日",
]
]
big_df["上榜日"] = pd.to_datetime(big_df["上榜日"]).dt.date
big_df["收盘价"] = pd.to_numeric(big_df["收盘价"], errors="coerce")
big_df["涨跌幅"] = pd.to_numeric(big_df["涨跌幅"], errors="coerce")
big_df["龙虎榜净买额"] = pd.to_numeric(big_df["龙虎榜净买额"], errors="coerce")
big_df["龙虎榜买入额"] = pd.to_numeric(big_df["龙虎榜买入额"], errors="coerce")
big_df["龙虎榜卖出额"] = pd.to_numeric(big_df["龙虎榜卖出额"], errors="coerce")
big_df["龙虎榜成交额"] = pd.to_numeric(big_df["龙虎榜成交额"], errors="coerce")
big_df["市场总成交额"] = pd.to_numeric(big_df["市场总成交额"], errors="coerce")
big_df["净买额占总成交比"] = pd.to_numeric(big_df["净买额占总成交比"], errors="coerce")
big_df["成交额占总成交比"] = pd.to_numeric(big_df["成交额占总成交比"], errors="coerce")
big_df["换手率"] = pd.to_numeric(big_df["换手率"], errors="coerce")
big_df["流通市值"] = pd.to_numeric(big_df["流通市值"], errors="coerce")
big_df["上榜后1日"] = pd.to_numeric(big_df["上榜后1日"], errors="coerce")
big_df["上榜后2日"] = pd.to_numeric(big_df["上榜后2日"], errors="coerce")
big_df["上榜后5日"] = pd.to_numeric(big_df["上榜后5日"], errors="coerce")
big_df["上榜后10日"] = pd.to_numeric(big_df["上榜后10日"], errors="coerce")
return big_df
def stock_lhb_stock_statistic_em(symbol: str = "近一月") -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-个股上榜统计
https://data.eastmoney.com/stock/tradedetail.html
:param symbol: choice of {"近一月", "近三月", "近六月", "近一年"}
:type symbol: str
:return: 个股上榜统计
:rtype: pandas.DataFrame
"""
symbol_map = {
"近一月": "01",
"近三月": "02",
"近六月": "03",
"近一年": "04",
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "BILLBOARD_TIMES,LATEST_TDATE,SECURITY_CODE",
"sortTypes": "-1,-1,1",
"pageSize": "500",
"pageNumber": "1",
"reportName": "RPT_BILLBOARD_TRADEALL",
"columns": "ALL",
"source": "WEB",
"client": "WEB",
"filter": f'(STATISTICS_CYCLE="{symbol_map[symbol]}")',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = temp_df.index + 1
temp_df.columns = [
"序号",
"-",
"代码",
"最近上榜日",
"名称",
"近1个月涨跌幅",
"近3个月涨跌幅",
"近6个月涨跌幅",
"近1年涨跌幅",
"涨跌幅",
"收盘价",
"-",
"龙虎榜总成交额",
"龙虎榜净买额",
"-",
"-",
"机构买入净额",
"上榜次数",
"龙虎榜买入额",
"龙虎榜卖出额",
"机构买入总额",
"机构卖出总额",
"买方机构次数",
"卖方机构次数",
"-",
]
temp_df = temp_df[
[
"序号",
"代码",
"名称",
"最近上榜日",
"收盘价",
"涨跌幅",
"上榜次数",
"龙虎榜净买额",
"龙虎榜买入额",
"龙虎榜卖出额",
"龙虎榜总成交额",
"买方机构次数",
"卖方机构次数",
"机构买入净额",
"机构买入总额",
"机构卖出总额",
"近1个月涨跌幅",
"近3个月涨跌幅",
"近6个月涨跌幅",
"近1年涨跌幅",
]
]
temp_df["最近上榜日"] = pd.to_datetime(temp_df["最近上榜日"]).dt.date
return temp_df
def stock_lhb_jgmmtj_em(
start_date: str = "20220906", end_date: str = "20220906"
) -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-机构买卖每日统计
https://data.eastmoney.com/stock/jgmmtj.html
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:return: 机构买卖每日统计
:rtype: pandas.DataFrame
"""
start_date = "-".join([start_date[:4], start_date[4:6], start_date[6:]])
end_date = "-".join([end_date[:4], end_date[4:6], end_date[6:]])
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "NET_BUY_AMT,TRADE_DATE,SECURITY_CODE",
"sortTypes": "-1,-1,1",
"pageSize": "5000",
"pageNumber": "1",
"reportName": "RPT_ORGANIZATION_TRADE_DETAILS",
"columns": "ALL",
"source": "WEB",
"client": "WEB",
"filter": f"(TRADE_DATE>='{start_date}')(TRADE_DATE<='{end_date}')",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = temp_df.index + 1
temp_df.columns = [
"序号",
"-",
"名称",
"代码",
"上榜日期",
"收盘价",
"涨跌幅",
"买方机构数",
"卖方机构数",
"机构买入总额",
"机构卖出总额",
"机构买入净额",
"市场总成交额",
"机构净买额占总成交额比",
"换手率",
"流通市值",
"上榜原因",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
"-",
]
temp_df = temp_df[
[
"序号",
"代码",
"名称",
"收盘价",
"涨跌幅",
"买方机构数",
"卖方机构数",
"机构买入总额",
"机构卖出总额",
"机构买入净额",
"市场总成交额",
"机构净买额占总成交额比",
"换手率",
"流通市值",
"上榜原因",
"上榜日期",
]
]
temp_df["上榜日期"] = pd.to_datetime(temp_df["上榜日期"]).dt.date
temp_df["收盘价"] = pd.to_numeric(temp_df["收盘价"], errors="coerce")
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
temp_df["买方机构数"] = pd.to_numeric(temp_df["买方机构数"], errors="coerce")
temp_df["卖方机构数"] = pd.to_numeric(temp_df["卖方机构数"], errors="coerce")
temp_df["机构买入总额"] = pd.to_numeric(temp_df["机构买入总额"], errors="coerce")
temp_df["机构卖出总额"] = pd.to_numeric(temp_df["机构卖出总额"], errors="coerce")
temp_df["机构买入净额"] = pd.to_numeric(temp_df["机构买入净额"], errors="coerce")
temp_df["市场总成交额"] = pd.to_numeric(temp_df["市场总成交额"], errors="coerce")
temp_df["机构净买额占总成交额比"] = pd.to_numeric(temp_df["机构净买额占总成交额比"], errors="coerce")
temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
temp_df["流通市值"] = pd.to_numeric(temp_df["流通市值"], errors="coerce")
return temp_df
def stock_lhb_jgstatistic_em(symbol: str = "近一月") -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-机构席位追踪
https://data.eastmoney.com/stock/jgstatistic.html
:param symbol: choice of {"近一月", "近三月", "近六月", "近一年"}
:type symbol: str
:return: 机构席位追踪
:rtype: pandas.DataFrame
"""
symbol_map = {
"近一月": "01",
"近三月": "02",
"近六月": "03",
"近一年": "04",
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "ONLIST_TIMES,SECURITY_CODE",
"sortTypes": "-1,1",
"pageSize": "5000",
"pageNumber": "1",
"reportName": "RPT_ORGANIZATION_SEATNEW",
"columns": "ALL",
"source": "WEB",
"client": "WEB",
"filter": f'(STATISTICSCYCLE="{symbol_map[symbol]}")',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json["result"]["pages"]
big_df = pd.DataFrame()
for page in tqdm(range(1, total_page + 1), leave=False):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
big_df.rename(
columns={
"index": "序号",
"SECURITY_CODE": "代码",
"SECURITY_NAME_ABBR": "名称",
"CLOSE_PRICE": "收盘价",
"CHANGE_RATE": "涨跌幅",
"AMOUNT": "龙虎榜成交金额",
"ONLIST_TIMES": "上榜次数",
"BUY_AMT": "机构买入额",
"BUY_TIMES": "机构买入次数",
"SELL_AMT": "机构卖出额",
"SELL_TIMES": "机构卖出次数",
"NET_BUY_AMT": "机构净买额",
"M1_CLOSE_ADJCHRATE": "近1个月涨跌幅",
"M3_CLOSE_ADJCHRATE": "近3个月涨跌幅",
"M6_CLOSE_ADJCHRATE": "近6个月涨跌幅",
"Y1_CLOSE_ADJCHRATE": "近1年涨跌幅",
},
inplace=True,
)
big_df = big_df[
[
"序号",
"代码",
"名称",
"收盘价",
"涨跌幅",
"龙虎榜成交金额",
"上榜次数",
"机构买入额",
"机构买入次数",
"机构卖出额",
"机构卖出次数",
"机构净买额",
"近1个月涨跌幅",
"近3个月涨跌幅",
"近6个月涨跌幅",
"近1年涨跌幅",
]
]
big_df["收盘价"] = pd.to_numeric(big_df["收盘价"], errors="coerce")
big_df["涨跌幅"] = pd.to_numeric(big_df["涨跌幅"], errors="coerce")
big_df["龙虎榜成交金额"] = pd.to_numeric(big_df["龙虎榜成交金额"], errors="coerce")
big_df["上榜次数"] = pd.to_numeric(big_df["上榜次数"], errors="coerce")
big_df["机构买入额"] = pd.to_numeric(big_df["机构买入额"], errors="coerce")
big_df["机构买入次数"] = pd.to_numeric(big_df["机构买入次数"], errors="coerce")
big_df["机构卖出额"] = pd.to_numeric(big_df["机构卖出额"], errors="coerce")
big_df["机构卖出次数"] = pd.to_numeric(big_df["机构卖出次数"], errors="coerce")
big_df["机构净买额"] = pd.to_numeric(big_df["机构净买额"], errors="coerce")
big_df["近1个月涨跌幅"] = pd.to_numeric(big_df["近1个月涨跌幅"], errors="coerce")
big_df["近3个月涨跌幅"] = pd.to_numeric(big_df["近3个月涨跌幅"], errors="coerce")
big_df["近6个月涨跌幅"] = pd.to_numeric(big_df["近6个月涨跌幅"], errors="coerce")
big_df["近1年涨跌幅"] = pd.to_numeric(big_df["近1年涨跌幅"], errors="coerce")
return big_df
def stock_lhb_hyyyb_em(
start_date: str = "20220324", end_date: str = "20220324"
) -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-每日活跃营业部
https://data.eastmoney.com/stock/jgmmtj.html
:param start_date: 开始日期
:type start_date: str
:param end_date: 结束日期
:type end_date: str
:return: 每日活跃营业部
:rtype: pandas.DataFrame
"""
start_date = "-".join([start_date[:4], start_date[4:6], start_date[6:]])
end_date = "-".join([end_date[:4], end_date[4:6], end_date[6:]])
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "TOTAL_NETAMT,ONLIST_DATE,OPERATEDEPT_CODE",
"sortTypes": "-1,-1,1",
"pageSize": "5000",
"pageNumber": "1",
"reportName": "RPT_OPERATEDEPT_ACTIVE",
"columns": "ALL",
"source": "WEB",
"client": "WEB",
"filter": f"(ONLIST_DATE>='{start_date}')(ONLIST_DATE<='{end_date}')",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json["result"]["pages"]
big_df = pd.DataFrame()
for page in tqdm(range(1, total_page + 1), leave=False):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
big_df.columns = [
"序号",
"营业部名称",
"上榜日",
"买入个股数",
"卖出个股数",
"买入总金额",
"卖出总金额",
"总买卖净额",
"-",
"-",
"买入股票",
"-",
"-",
]
big_df = big_df[
[
"序号",
"营业部名称",
"上榜日",
"买入个股数",
"卖出个股数",
"买入总金额",
"卖出总金额",
"总买卖净额",
"买入股票",
]
]
big_df["上榜日"] = pd.to_datetime(big_df["上榜日"]).dt.date
big_df["买入个股数"] = pd.to_numeric(big_df["买入个股数"])
big_df["卖出个股数"] = pd.to_numeric(big_df["卖出个股数"])
big_df["买入总金额"] = pd.to_numeric(big_df["买入总金额"])
big_df["卖出总金额"] = pd.to_numeric(big_df["卖出总金额"])
big_df["总买卖净额"] = pd.to_numeric(big_df["总买卖净额"])
return big_df
def stock_lhb_yybph_em(symbol: str = "近一月") -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-营业部排行
https://data.eastmoney.com/stock/yybph.html
:param symbol: choice of {"近一月", "近三月", "近六月", "近一年"}
:type symbol: str
:return: 营业部排行
:rtype: pandas.DataFrame
"""
symbol_map = {
"近一月": "01",
"近三月": "02",
"近六月": "03",
"近一年": "04",
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "TOTAL_BUYER_SALESTIMES_1DAY,OPERATEDEPT_CODE",
"sortTypes": "-1,1",
"pageSize": "5000",
"pageNumber": "1",
"reportName": "RPT_RATEDEPT_RETURNT_RANKING",
"columns": "ALL",
"source": "WEB",
"client": "WEB",
"filter": f'(STATISTICSCYCLE="{symbol_map[symbol]}")',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json["result"]["pages"]
big_df = pd.DataFrame()
for page in tqdm(range(1, total_page + 1), leave=False):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
big_df.rename(
columns={
"index": "序号",
"OPERATEDEPT_NAME": "营业部名称",
"TOTAL_BUYER_SALESTIMES_1DAY": "上榜后1天-买入次数",
"AVERAGE_INCREASE_1DAY": "上榜后1天-平均涨幅",
"RISE_PROBABILITY_1DAY": "上榜后1天-上涨概率",
"TOTAL_BUYER_SALESTIMES_2DAY": "上榜后2天-买入次数",
"AVERAGE_INCREASE_2DAY": "上榜后2天-平均涨幅",
"RISE_PROBABILITY_2DAY": "上榜后2天-上涨概率",
"TOTAL_BUYER_SALESTIMES_3DAY": "上榜后3天-买入次数",
"AVERAGE_INCREASE_3DAY": "上榜后3天-平均涨幅",
"RISE_PROBABILITY_3DAY": "上榜后3天-上涨概率",
"TOTAL_BUYER_SALESTIMES_5DAY": "上榜后5天-买入次数",
"AVERAGE_INCREASE_5DAY": "上榜后5天-平均涨幅",
"RISE_PROBABILITY_5DAY": "上榜后5天-上涨概率",
"TOTAL_BUYER_SALESTIMES_10DAY": "上榜后10天-买入次数",
"AVERAGE_INCREASE_10DAY": "上榜后10天-平均涨幅",
"RISE_PROBABILITY_10DAY": "上榜后10天-上涨概率",
},
inplace=True,
)
big_df = big_df[
[
"序号",
"营业部名称",
"上榜后1天-买入次数",
"上榜后1天-平均涨幅",
"上榜后1天-上涨概率",
"上榜后2天-买入次数",
"上榜后2天-平均涨幅",
"上榜后2天-上涨概率",
"上榜后3天-买入次数",
"上榜后3天-平均涨幅",
"上榜后3天-上涨概率",
"上榜后5天-买入次数",
"上榜后5天-平均涨幅",
"上榜后5天-上涨概率",
"上榜后10天-买入次数",
"上榜后10天-平均涨幅",
"上榜后10天-上涨概率",
]
]
big_df["上榜后1天-买入次数"] = pd.to_numeric(big_df["上榜后1天-买入次数"], errors="coerce")
big_df["上榜后1天-平均涨幅"] = pd.to_numeric(big_df["上榜后1天-平均涨幅"], errors="coerce")
big_df["上榜后1天-上涨概率"] = pd.to_numeric(big_df["上榜后1天-上涨概率"], errors="coerce")
big_df["上榜后2天-买入次数"] = pd.to_numeric(big_df["上榜后2天-买入次数"], errors="coerce")
big_df["上榜后2天-平均涨幅"] = pd.to_numeric(big_df["上榜后2天-平均涨幅"], errors="coerce")
big_df["上榜后2天-上涨概率"] = pd.to_numeric(big_df["上榜后2天-上涨概率"], errors="coerce")
big_df["上榜后3天-买入次数"] = pd.to_numeric(big_df["上榜后3天-买入次数"], errors="coerce")
big_df["上榜后3天-平均涨幅"] = pd.to_numeric(big_df["上榜后3天-平均涨幅"], errors="coerce")
big_df["上榜后3天-上涨概率"] = pd.to_numeric(big_df["上榜后3天-上涨概率"], errors="coerce")
big_df["上榜后5天-买入次数"] = pd.to_numeric(big_df["上榜后5天-买入次数"], errors="coerce")
big_df["上榜后5天-平均涨幅"] = pd.to_numeric(big_df["上榜后5天-平均涨幅"], errors="coerce")
big_df["上榜后5天-上涨概率"] = pd.to_numeric(big_df["上榜后5天-上涨概率"], errors="coerce")
big_df["上榜后10天-买入次数"] = pd.to_numeric(big_df["上榜后10天-买入次数"], errors="coerce")
big_df["上榜后10天-平均涨幅"] = pd.to_numeric(big_df["上榜后10天-平均涨幅"], errors="coerce")
big_df["上榜后10天-上涨概率"] = pd.to_numeric(big_df["上榜后10天-上涨概率"], errors="coerce")
return big_df
def stock_lhb_traderstatistic_em(symbol: str = "近一月") -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-营业部统计
https://data.eastmoney.com/stock/traderstatistic.html
:param symbol: choice of {"近一月", "近三月", "近六月", "近一年"}
:type symbol: str
:return: 营业部统计
:rtype: pandas.DataFrame
"""
symbol_map = {
"近一月": "01",
"近三月": "02",
"近六月": "03",
"近一年": "04",
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"sortColumns": "AMOUNT,OPERATEDEPT_CODE",
"sortTypes": "-1,1",
"pageSize": "5000",
"pageNumber": "1",
"reportName": "RPT_OPERATEDEPT_LIST_STATISTICS",
"columns": "ALL",
"source": "WEB",
"client": "WEB",
"filter": f'(STATISTICSCYCLE="{symbol_map[symbol]}")',
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
total_page = data_json["result"]["pages"]
big_df = pd.DataFrame()
for page in tqdm(range(1, total_page + 1), leave=False):
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
params.update({"pageNumber": page})
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.reset_index(inplace=True)
big_df["index"] = big_df.index + 1
big_df.rename(
columns={
"index": "序号",
"OPERATEDEPT_NAME": "营业部名称",
"AMOUNT": "龙虎榜成交金额",
"SALES_ONLIST_TIMES": "上榜次数",
"ACT_BUY": "买入额",
"TOTAL_BUYER_SALESTIMES": "买入次数",
"ACT_SELL": "卖出额",
"TOTAL_SELLER_SALESTIMES": "卖出次数",
},
inplace=True,
)
big_df = big_df[
[
"序号",
"营业部名称",
"龙虎榜成交金额",
"上榜次数",
"买入额",
"买入次数",
"卖出额",
"卖出次数",
]
]
big_df["龙虎榜成交金额"] = pd.to_numeric(big_df["龙虎榜成交金额"], errors="coerce")
big_df["上榜次数"] = pd.to_numeric(big_df["上榜次数"], errors="coerce")
big_df["买入额"] = pd.to_numeric(big_df["买入额"], errors="coerce")
big_df["买入次数"] = pd.to_numeric(big_df["买入次数"], errors="coerce")
big_df["卖出额"] = pd.to_numeric(big_df["卖出额"], errors="coerce")
big_df["卖出次数"] = pd.to_numeric(big_df["卖出次数"], errors="coerce")
return big_df
def stock_lhb_stock_detail_date_em(symbol: str = "600077") -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-个股龙虎榜详情-日期
https://data.eastmoney.com/stock/tradedetail.html
:param symbol: 股票代码
:type symbol: str
:return: 个股龙虎榜详情-日期
:rtype: pandas.DataFrame
"""
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"reportName": "RPT_LHB_BOARDDATE",
"columns": "SECURITY_CODE,TRADE_DATE,TR_DATE",
"filter": f'(SECURITY_CODE="{symbol}")',
"pageNumber": "1",
"pageSize": "1000",
"sortTypes": "-1",
"sortColumns": "TRADE_DATE",
"source": "WEB",
"client": "WEB",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = temp_df.index + 1
temp_df.columns = [
"序号",
"股票代码",
"交易日",
"-",
]
temp_df = temp_df[
[
"序号",
"股票代码",
"交易日",
]
]
temp_df["交易日"] = pd.to_datetime(temp_df["交易日"]).dt.date
return temp_df
def stock_lhb_stock_detail_em(
symbol: str = "000788", date: str = "20220315", flag: str = "卖出"
) -> pd.DataFrame:
"""
东方财富网-数据中心-龙虎榜单-个股龙虎榜详情
https://data.eastmoney.com/stock/lhb/600077.html
:param symbol: 股票代码
:type symbol: str
:param date: 查询日期; 需要通过 ak.stock_lhb_stock_detail_date_em(symbol="600077") 接口获取相应股票的有龙虎榜详情数据的日期
:type date: str
:param flag: choice of {"买入", "卖出"}
:type flag: str
:return: 个股龙虎榜详情
:rtype: pandas.DataFrame
"""
flag_map = {
"买入": "BUY",
"卖出": "SELL",
}
report_map = {
"买入": "RPT_BILLBOARD_DAILYDETAILSBUY",
"卖出": "RPT_BILLBOARD_DAILYDETAILSSELL",
}
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
params = {
"reportName": report_map[flag],
"columns": "ALL",
"filter": f"""(TRADE_DATE='{'-'.join([date[:4], date[4:6], date[6:]])}')(SECURITY_CODE="{symbol}")""",
"pageNumber": "1",
"pageSize": "500",
"sortTypes": "-1",
"sortColumns": flag_map[flag],
"source": "WEB",
"client": "WEB",
"_": "1647338693644",
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json["result"]["data"])
temp_df.reset_index(inplace=True)
temp_df["index"] = temp_df.index + 1
if flag == "买入":
temp_df.columns = [
"序号",
"-",
"-",
"-",
"-",
"交易营业部名称",
"类型",
"-",
"-",
"-",
"-",
"买入金额",
"卖出金额",
"净额",
"-",
"-",
"-",
"-",
"买入金额-占总成交比例",
"卖出金额-占总成交比例",
"-",
]
temp_df = temp_df[
[
"序号",
"交易营业部名称",
"买入金额",
"买入金额-占总成交比例",
"卖出金额",
"卖出金额-占总成交比例",
"净额",
"类型",
]
]
temp_df["买入金额"] = pd.to_numeric(temp_df["买入金额"])
temp_df["买入金额-占总成交比例"] = pd.to_numeric(temp_df["买入金额-占总成交比例"])
temp_df["卖出金额"] = pd.to_numeric(temp_df["卖出金额"])
temp_df["卖出金额-占总成交比例"] = pd.to_numeric(temp_df["卖出金额-占总成交比例"])
temp_df.sort_values("类型", inplace=True)
temp_df.reset_index(inplace=True, drop=True)
temp_df["序号"] = range(1, len(temp_df["序号"]) + 1)
else:
temp_df.columns = [
"序号",
"-",
"-",
"-",
"-",
"交易营业部名称",
"类型",
"-",
"-",
"-",
"-",
"买入金额",
"卖出金额",
"净额",
"-",
"-",
"-",
"-",
"买入金额-占总成交比例",
"卖出金额-占总成交比例",
"-",
]
temp_df = temp_df[
[
"序号",
"交易营业部名称",
"买入金额",
"买入金额-占总成交比例",
"卖出金额",
"卖出金额-占总成交比例",
"净额",
"类型",
]
]
temp_df["买入金额"] = pd.to_numeric(temp_df["买入金额"])
temp_df["买入金额-占总成交比例"] = pd.to_numeric(temp_df["买入金额-占总成交比例"])
temp_df["卖出金额"] = pd.to_numeric(temp_df["卖出金额"])
temp_df["卖出金额-占总成交比例"] = pd.to_numeric(temp_df["卖出金额-占总成交比例"])
temp_df.sort_values("类型", inplace=True)
temp_df.reset_index(inplace=True, drop=True)
temp_df["序号"] = range(1, len(temp_df["序号"]) + 1)
return temp_df
if __name__ == "__main__":
stock_lhb_detail_em_df = stock_lhb_detail_em(
start_date="20230403", end_date="20230417"
)
print(stock_lhb_detail_em_df)
stock_lhb_stock_statistic_em_df = stock_lhb_stock_statistic_em(symbol="近一月")
print(stock_lhb_stock_statistic_em_df)
stock_lhb_stock_statistic_em_df = stock_lhb_stock_statistic_em(symbol="近三月")
print(stock_lhb_stock_statistic_em_df)
stock_lhb_stock_statistic_em_df = stock_lhb_stock_statistic_em(symbol="近六月")
print(stock_lhb_stock_statistic_em_df)
stock_lhb_stock_statistic_em_df = stock_lhb_stock_statistic_em(symbol="近一年")
print(stock_lhb_stock_statistic_em_df)
stock_lhb_jgmmtj_em_df = stock_lhb_jgmmtj_em(
start_date="20220904", end_date="20220906"
)
print(stock_lhb_jgmmtj_em_df)
stock_lhb_jgstatistic_em_df = stock_lhb_jgstatistic_em(symbol="近一月")
print(stock_lhb_jgstatistic_em_df)
stock_lhb_hyyyb_em_df = stock_lhb_hyyyb_em(
start_date="20220324", end_date="20220324"
)
print(stock_lhb_hyyyb_em_df)
stock_lhb_yybph_em_df = stock_lhb_yybph_em(symbol="近一月")
print(stock_lhb_yybph_em_df)
stock_lhb_traderstatistic_em_df = stock_lhb_traderstatistic_em(symbol="近一月")
print(stock_lhb_traderstatistic_em_df)
stock_lhb_stock_detail_date_em_df = stock_lhb_stock_detail_date_em(symbol="002901")
print(stock_lhb_stock_detail_date_em_df)
stock_lhb_stock_detail_em_df = stock_lhb_stock_detail_em(
symbol="002901", date="20221012", flag="买入"
)
print(stock_lhb_stock_detail_em_df)
stock_lhb_stock_detail_em_df = stock_lhb_stock_detail_em(
symbol="600016", date="20220324", flag="买入"
)
print(stock_lhb_stock_detail_em_df)
================================================
FILE: instock/core/crawling/stock_lhb_sina.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/5/10 00:00
Desc: 新浪财经-龙虎榜
https://vip.stock.finance.sina.com.cn/q/go.php/vInvestConsult/kind/lhb/index.phtml
"""
from io import StringIO
import pandas as pd
import requests
from bs4 import BeautifulSoup
from tqdm import tqdm
from instock.core.singleton_proxy import proxys
def stock_lhb_detail_daily_sina(date: str = "20240222") -> pd.DataFrame:
"""
龙虎榜-每日详情
https://vip.stock.finance.sina.com.cn/q/go.php/vInvestConsult/kind/lhb/index.phtml
:param date: 交易日
:type date: str
:return: 龙虎榜-每日详情
:rtype: pandas.DataFrame
"""
date = "-".join([date[:4], date[4:6], date[6:]])
url = "https://vip.stock.finance.sina.com.cn/q/go.php/vInvestConsult/kind/lhb/index.phtml"
params = {"tradedate": date}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
soup = BeautifulSoup(r.text, features="lxml")
selected_html = soup.find(name="div", attrs={"class": "list"}).find_all(
name="table", attrs={"class": "list_table"}
)
big_df = pd.DataFrame()
for table in selected_html:
temp_df = pd.read_html(StringIO(table.prettify()), header=0, skiprows=1)[0]
temp_symbol = pd.read_html(StringIO(table.prettify()))[0].iat[0, 0]
temp_df["指标"] = temp_symbol
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df["股票代码"] = big_df["股票代码"].astype(str).str.zfill(6)
del big_df["查看详情"]
big_df.columns = [
"序号",
"股票代码",
"股票名称",
"收盘价",
"对应值",
"成交量",
"成交额",
"指标",
]
big_df["收盘价"] = pd.to_numeric(big_df["收盘价"], errors="coerce")
big_df["对应值"] = pd.to_numeric(big_df["对应值"], errors="coerce")
big_df["成交量"] = pd.to_numeric(big_df["成交量"], errors="coerce")
big_df["成交额"] = pd.to_numeric(big_df["成交额"], errors="coerce")
return big_df
def _find_last_page(
url: str = "https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/ggtj/index.phtml",
recent_day: str = "60",
):
params = {
"last": recent_day,
"p": "1",
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
soup = BeautifulSoup(r.text, "lxml")
try:
previous_page = int(soup.find_all(attrs={"class": "page"})[-2].text)
except: # noqa: E722
previous_page = 1
if previous_page != 1:
while True:
params = {
"last": recent_day,
"p": previous_page,
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
soup = BeautifulSoup(r.text, features="lxml")
last_page = int(soup.find_all(attrs={"class": "page"})[-2].text)
if last_page != previous_page:
previous_page = last_page
continue
else:
break
return previous_page
def stock_lhb_ggtj_sina(symbol: str = "5") -> pd.DataFrame:
"""
龙虎榜-个股上榜统计
https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/ggtj/index.phtml
:param symbol: choice of {"5": 最近 5 天; "10": 最近 10 天; "30": 最近 30 天; "60": 最近 60 天;}
:type symbol: str
:return: 龙虎榜-个股上榜统计
:rtype: pandas.DataFrame
"""
url = (
"https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/ggtj/index.phtml"
)
last_page_num = _find_last_page(url, symbol)
big_df = pd.DataFrame()
for page in tqdm(range(1, last_page_num + 1), leave=False):
params = {
"last": symbol,
"p": page,
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
temp_df = pd.read_html(StringIO(r.text))[0].iloc[0:, :]
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df["股票代码"] = big_df["股票代码"].astype(str).str.zfill(6)
big_df.columns = [
"股票代码",
"股票名称",
"上榜次数",
"累积购买额",
"累积卖出额",
"净额",
"买入席位数",
"卖出席位数",
]
return big_df
def stock_lhb_yytj_sina(symbol: str = "5") -> pd.DataFrame:
"""
龙虎榜-营业部上榜统计
https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/yytj/index.phtml
:param symbol: choice of {"5": 最近 5 天; "10": 最近 10 天; "30": 最近 30 天; "60": 最近 60 天;}
:type symbol: str
:return: 龙虎榜-营业部上榜统计
:rtype: pandas.DataFrame
"""
url = (
"https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/yytj/index.phtml"
)
last_page_num = _find_last_page(url, symbol)
big_df = pd.DataFrame()
for page in tqdm(range(1, last_page_num + 1), leave=False):
params = {
"last": "5",
"p": page,
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
temp_df = pd.read_html(StringIO(r.text))[0].iloc[0:, :]
big_df = pd.concat([big_df, temp_df], ignore_index=True)
big_df.columns = [
"营业部名称",
"上榜次数",
"累积购买额",
"买入席位数",
"累积卖出额",
"卖出席位数",
"买入前三股票",
]
big_df["上榜次数"] = pd.to_numeric(big_df["上榜次数"], errors="coerce")
big_df["买入席位数"] = pd.to_numeric(big_df["买入席位数"], errors="coerce")
big_df["卖出席位数"] = pd.to_numeric(big_df["卖出席位数"], errors="coerce")
return big_df
def stock_lhb_jgzz_sina(symbol: str = "5") -> pd.DataFrame:
"""
龙虎榜-机构席位追踪
https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/jgzz/index.phtml
:param symbol: choice of {"5": 最近 5 天; "10": 最近 10 天; "30": 最近 30 天; "60": 最近 60 天;}
:type symbol: str
:return: 龙虎榜-机构席位追踪
:rtype: pandas.DataFrame
"""
url = (
"https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/jgzz/index.phtml"
)
last_page_num = _find_last_page(url, symbol)
big_df = pd.DataFrame()
for page in tqdm(range(1, last_page_num + 1), leave=False):
params = {
"last": symbol,
"p": page,
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
temp_df = pd.read_html(StringIO(r.text))[0].iloc[0:, :]
if temp_df.empty:
continue
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df["股票代码"] = big_df["股票代码"].astype(str).str.zfill(6)
del big_df["当前价"]
del big_df["涨跌幅"]
big_df.columns = [
"股票代码",
"股票名称",
"累积买入额",
"买入次数",
"累积卖出额",
"卖出次数",
"净额",
]
big_df["买入次数"] = pd.to_numeric(big_df["买入次数"], errors="coerce")
big_df["卖出次数"] = pd.to_numeric(big_df["卖出次数"], errors="coerce")
return big_df
def stock_lhb_jgmx_sina() -> pd.DataFrame:
"""
龙虎榜-机构席位成交明细
https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/jgmx/index.phtml
:return: 龙虎榜-机构席位成交明细
:rtype: pandas.DataFrame
"""
url = (
"https://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/jgmx/index.phtml"
)
params = {
"p": "1",
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
soup = BeautifulSoup(r.text, features="lxml")
try:
last_page_num = int(soup.find_all(attrs={"class": "page"})[-2].text)
except: # noqa: E722
last_page_num = 1
big_df = pd.DataFrame()
for page in tqdm(range(1, last_page_num + 1), leave=False):
params = {
"p": page,
}
r = requests.get(url, proxies = proxys().get_proxies(), params=params)
temp_df = pd.read_html(StringIO(r.text))[0].iloc[0:, :]
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
big_df["股票代码"] = big_df["股票代码"].astype(str).str.zfill(6)
big_df["交易日期"] = pd.to_datetime(big_df["交易日期"], errors="coerce").dt.date
big_df.rename(
columns={
"机构席位买入额(万)": "机构席位买入额",
"机构席位卖出额(万)": "机构席位卖出额",
},
inplace=True,
)
big_df["机构席位买入额"] = pd.to_numeric(big_df["机构席位买入额"], errors="coerce")
big_df["机构席位卖出额"] = pd.to_numeric(big_df["机构席位卖出额"], errors="coerce")
return big_df
if __name__ == "__main__":
stock_lhb_detail_daily_sina_df = stock_lhb_detail_daily_sina(date="20240222")
print(stock_lhb_detail_daily_sina_df)
stock_lhb_ggtj_sina_df = stock_lhb_ggtj_sina(symbol="5")
print(stock_lhb_ggtj_sina_df)
stock_lhb_yytj_sina_df = stock_lhb_yytj_sina(symbol="5")
print(stock_lhb_yytj_sina_df)
stock_lhb_jgzz_sina_df = stock_lhb_jgzz_sina(symbol="5")
print(stock_lhb_jgzz_sina_df)
stock_lhb_jgmx_sina_df = stock_lhb_jgmx_sina()
print(stock_lhb_jgmx_sina_df)
================================================
FILE: instock/core/crawling/stock_limitup_reason.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/2/26 12:18
Desc: 同花顺涨停原因
http://zx.10jqka.com.cn/event/api/getharden/date/2025-02-21/orderby/date/orderway/desc/charset/GBK/
"""
import pandas as pd
import requests
import re
import numpy as np
from instock.core.singleton_proxy import proxys
__author__ = 'myh '
__date__ = '2025/5/9 '
def stock_limitup_reason(date: str = "2025-02-27") -> pd.DataFrame:
"""
同花顺涨停原因
http://zx.10jqka.com.cn/event/api/getharden/date/2025-02-27/orderby/date/orderway/desc/charset/GBK/
:return: 涨停原因
:rtype: pandas.DataFrame
"""
url = f"http://zx.10jqka.com.cn/event/api/getharden/date/{date}/orderby/date/orderway/desc/charset/GBK/"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Thx"
}
r = requests.get(url, proxies = proxys().get_proxies(), headers=headers)
data_json = r.json()
data = data_json["data"]
if not data:
return pd.DataFrame()
temp_df = pd.DataFrame(data)
if len(temp_df.columns)<7:
temp_df.columns = [
"ID",
"名称",
"代码",
"原因",
"日期",
"_",
]
temp_df["最新价"] = np.nan
temp_df["涨跌额"] = np.nan
temp_df["涨跌幅"] = np.nan
temp_df["换手率"] = np.nan
temp_df["成交额"] = np.nan
temp_df["成交量"] = np.nan
temp_df["DDE"] = np.nan
else:
temp_df.columns = [
"ID",
"名称",
"代码",
"原因",
"日期",
"最新价",
"涨跌额",
"涨跌幅",
"换手率",
"成交额",
"成交量",
"DDE",
"_",
]
temp_df["详因"] = temp_df.apply(stock_limitup_detail, axis=1)
temp_df["换手率"] = round(temp_df["换手率"], 2)
temp_df = temp_df[
[
"日期",
"代码",
"名称",
"原因",
"详因",
"最新价",
"涨跌幅",
"涨跌额",
"换手率",
"成交量",
"成交额",
"DDE",
]
]
return temp_df
def stock_limitup_detail(row):
"""
同花顺涨停详因
http://zx.10jqka.com.cn/event/harden/stockreason/id/70870005
:return: 涨停详因
:rtype: pandas.DataFrame
"""
url = f"http://zx.10jqka.com.cn/event/harden/stockreason/id/{row['ID']}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"
}
r = requests.get(url, proxies = proxys().get_proxies(), headers=headers)
data_text = r.text
# match_title = re.search(r"var title = '(.*?)';", data_text)
# _title = ""
# if match_title:
# _title = match_title.group(1)
pattern_data = re.search(r"var data = '(.*?)';", data_text)
_data = ""
if pattern_data:
_data = pattern_data.group(1).replace("<spanclass="hl">", "").replace("</span>", "").replace("&quot;", "\"")
return _data
# reason = f"{_title}\r\n{_data}"
# return reason
if __name__ == "__main__":
stock_limitup_reason_df = stock_limitup_reason()
print(stock_limitup_reason_df)
================================================
FILE: instock/core/crawling/stock_selection.py
================================================
# -*- coding:utf-8 -*-
# !/usr/bin/env python
import math
import random
import time
import pandas as pd
import instock.core.tablestructure as tbs
from instock.core.eastmoney_fetcher import eastmoney_fetcher
__author__ = 'myh '
__date__ = '2025/12/31 '
# 创建全局实例,供所有函数使用
fetcher = eastmoney_fetcher()
def stock_selection() -> pd.DataFrame:
"""
东方财富网-个股-选股器
https://data.eastmoney.com/xuangu/
:return: 选股器
:rtype: pandas.DataFrame
"""
cols = tbs.TABLE_CN_STOCK_SELECTION['columns']
page_size = 50
page_current = 1
sty = "" # 初始值 "SECUCODE,SECURITY_CODE,SECURITY_NAME_ABBR,CHANGE_RATE"
for k in cols:
sty = f"{sty},{cols[k]['map']}"
url = "https://data.eastmoney.com/dataapi/xuangu/list"
params = {
"sty": sty[1:],
"filter": "(MARKET+in+(\"上交所主板\",\"深交所主板\",\"深交所创业板\"))(NEW_PRICE>0)",
"p": page_current,
"ps": page_size,
"source": "SELECT_SECURITIES",
"client": "WEB"
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
data = data_json["result"]["data"]
if not data:
return pd.DataFrame()
data_count = data_json["result"]["count"]
page_count = math.ceil(data_count/page_size)
while page_count > 1:
# 添加随机延迟,避免爬取过快
time.sleep(random.uniform(1, 1.5))
page_current = page_current + 1
params["p"] = page_current
r = fetcher.make_request(url, params=params)
data_json = r.json()
_data = data_json["result"]["data"]
data.extend(_data)
page_count =page_count - 1
temp_df = pd.DataFrame(data)
mask = ~temp_df['CONCEPT'].isna()
temp_df.loc[mask, 'CONCEPT'] = temp_df.loc[mask, 'CONCEPT'].apply(lambda x: ', '.join(x))
mask = ~temp_df['STYLE'].isna()
temp_df.loc[mask, 'STYLE'] = temp_df.loc[mask, 'STYLE'].apply(lambda x: ', '.join(x))
for k in cols:
t = tbs.get_field_type_name(cols[k]["type"])
if t == 'numeric':
temp_df[cols[k]["map"]] = pd.to_numeric(temp_df[cols[k]["map"]], errors="coerce")
elif t == 'datetime':
temp_df[cols[k]["map"]] = pd.to_datetime(temp_df[cols[k]["map"]], errors="coerce").dt.date
return temp_df
def stock_selection_params():
"""
东方财富网-个股-选股器-选股指标
https://data.eastmoney.com/xuangu/
:return: 选股器-选股指标
:rtype: pandas.DataFrame
"""
url = "https://datacenter-web.eastmoney.com/wstock/selection/api/data/get"
params = {
"type": "RPTA_PCNEW_WHOLE",
"sty": "ALL",
"p": 1,
"ps": 1000,
"source": "SELECT_SECURITIES",
"client": "WEB"
}
r = fetcher.make_request(url, params=params)
data_json = r.json()
zxzb = data_json["result"]["data"] # 指标
print(zxzb)
if __name__ == "__main__":
stock_selection_df = stock_selection()
print(stock_selection)
# stock_selection_params()
================================================
FILE: instock/core/crawling/trade_date_hist.py
================================================
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2022/10/1 19:27
Desc: 新浪财经-交易日历
https://finance.sina.com.cn/realstock/company/klc_td_sh.txt
此处可以用来更新 calendar.json 文件,注意末尾没有 "," 号
"""
import datetime
import pandas as pd
import requests
from py_mini_racer import MiniRacer
from instock.core.singleton_proxy import proxys
hk_js_decode = """
function d(t) {
var e, i, n, r, a, o, s, l = (arguments,
864e5), u = 7657, c = [], h = [], d = ~(3 << 30), f = 1 << 30,
p = [0, 3, 5, 6, 9, 10, 12, 15, 17, 18, 20, 23, 24, 27, 29, 30], m = Math, g = function () {
var l, u;
for (l = 0; 64 > l; l++)
h[l] = m.pow(2, l),
26 > l && (c[l] = v(l + 65),
c[l + 26] = v(l + 97),
10 > l && (c[l + 52] = v(l + 48)));
for (c.push("+", "/"),
c = c.join(""),
i = t.split(""),
n = i.length,
l = 0; n > l; l++)
i[l] = c.indexOf(i[l]);
return r = {},
e = o = 0,
a = {},
u = w([12, 6]),
s = 63 ^ u[1],
{
_1479: T,
_136: _,
_200: S,
_139: k,
_197: _mi_run
}["_" + u[0]] || function () {
return []
}
}, v = String.fromCharCode, b = function (t) {
return t === {}._
}, N = function () {
var t, e;
for (t = y(),
e = 1; ;) {
if (!y())
return e * (2 * t - 1);
e++
}
}, y = function () {
var t;
return e >= n ? 0 : (t = i[e] & 1 << o,
o++,
o >= 6 && (o -= 6,
e++),
!!t)
}, w = function (t, r, a) {
var s, l, u, c, d;
for (l = [],
u = 0,
r || (r = []),
a || (a = []),
s = 0; s < t.length; s++)
if (c = t[s],
u = 0,
c) {
if (e >= n)
return l;
if (t[s] <= 0)
u = 0;
else if (t[s] <= 30) {
for (; d = 6 - o,
d = c > d ? d : c,
u |= (i[e] >> o & (1 << d) - 1) << t[s] - c,
o += d,
o >= 6 && (o -= 6,
e++),
c -= d,
!(0 >= c);)
;
r[s] && u >= h[t[s] - 1] && (u -= h[t[s]])
} else
u = w([30, t[s] - 30], [0, r[s]]),
a[s] || (u = u[0] + u[1] * h[30]);
l[s] = u
} else
l[s] = 0;
return l
}, x = function (t) {
var e, i, n;
for (t > 1 && (e = 0),
e = 0; t > e; e++)
r.d++,
n = r.d % 7,
(3 == n || 4 == n) && (r.d += 5 - n);
return i = new Date,
i.setTime((u + r.d) * l),
i
}, S = function () {
var t, i, a, o, l;
if (s >= 1)
return [];
for (r.d = w([18], [1])[0] - 1,
a = w([3, 3, 30, 6]),
r.p = a[0],
r.ld = a[1],
r.cd = a[2],
r.c = a[3],
r.m = m.pow(10, r.p),
r.pc = r.cd / r.m,
i = [],
t = 0; o = {
d: 1
},
y() && (a = w([3])[0],
0 == a ? o.d = w([6])[0] : 1 == a ? (r.d = w([18])[0],
o.d = 0) : o.d = a),
l = {
day: x(o.d)
},
y() && (r.ld += N()),
a = w([3 * r.ld], [1]),
r.cd += a[0],
l.close = r.cd / r.m,
i.push(l),
!(e >= n) && (e != n - 1 || 63 & (r.c ^ t + 1)); t++)
;
return i[0].prevclose = r.pc,
i
}, _ = function () {
var t, i, a, o, l, u, c, h, d, f, p;
if (s > 2)
return [];
for (c = [],
d = {
v: "volume",
p: "price",
a: "avg_price"
},
r.d = w([18], [1])[0] - 1,
h = {
day: x(1)
},
a = w(1 > s ? [3, 3, 4, 1, 1, 1, 5] : [4, 4, 4, 1, 1, 1, 3]),
t = 0; 7 > t; t++)
r[["la", "lp", "lv", "tv", "rv", "zv", "pp"][t]] = a[t];
for (r.m = m.pow(10, r.pp),
s >= 1 ? (a = w([3, 3]),
r.c = a[0],
a = a[1]) : (a = 5,
r.c = 2),
r.pc = w([6 * a])[0],
h.pc = r.pc / r.m,
r.cp = r.pc,
r.da = 0,
r.sa = r.sv = 0,
t = 0; !(e >= n) && (e != n - 1 || 7 & (r.c ^ t)); t++) {
for (l = {},
o = {},
f = r.tv ? y() : 1,
i = 0; 3 > i; i++)
if (p = ["v", "p", "a"][i],
(f ? y() : 0) && (a = N(),
r["l" + p] += a),
u = "v" == p && r.rv ? y() : 1,
a = w([3 * r["l" + p] + ("v" == p ? 7 * u : 0)], [!!i])[0] * (u ? 1 : 100),
o[p] = a,
"v" == p) {
if (!(l[d[p]] = a) && (s > 1 || 241 > t) && (r.zv ? !y() : 1)) {
o.p = 0;
break
}
} else
"a" == p && (r.da = (1 > s ? 0 : r.da) + o.a);
r.sv += o.v,
l[d.p] = (r.cp += o.p) / r.m,
r.sa += o.v * r.cp,
l[d.a] = b(o.a) ? t ? c[t - 1][d.a] : l[d.p] : r.sv ? ((m.floor((r.sa * (2e3 / r.m) + r.sv) / r.sv) >> 1) + r.da) / 1e3 : l[d.p] + r.da / 1e3,
c.push(l)
}
return c[0].date = h.day,
c[0].prevclose = h.pc,
c
}, T = function () {
var t, e, i, n, a, o, l;
if (s >= 1)
return [];
for (r.lv = 0,
r.ld = 0,
r.cd = 0,
r.cv = [0, 0],
r.p = w([6])[0],
r.d = w([18], [1])[0] - 1,
r.m = m.pow(10, r.p),
a = w([3, 3]),
r.md = a[0],
r.mv = a[1],
t = []; a = w([6]),
a.length;) {
if (i = {
c: a[0]
},
n = {},
i.d = 1,
32 & i.c)
for (; ;) {
if (a = w([6])[0],
63 == (16 | a)) {
l = 16 & a ? "x" : "u",
a = w([3, 3]),
i[l + "_d"] = a[0] + r.md,
i[l + "_v"] = a[1] + r.mv;
break
}
if (32 & a) {
o = 8 & a ? "d" : "v",
l = 16 & a ? "x" : "u",
i[l + "_" + o] = (7 & a) + r["m" + o];
break
}
if (o = 15 & a,
0 == o ? i.d = w([6])[0] : 1 == o ? (r.d = o = w([18])[0],
i.d = 0) : i.d = o,
!(16 & a))
break
}
n.date = x(i.d);
for (o in {
v: 0,
d: 0
})
b(i["x_" + o]) || (r["l" + o] = i["x_" + o]),
b(i["u_" + o]) && (i["u_" + o] = r["l" + o]);
for (i.l_l = [i.u_d, i.u_d, i.u_d, i.u_d, i.u_v],
l = p[15 & i.c],
1 & i.u_v && (l = 31 - l),
16 & i.c && (i.l_l[4] += 2),
e = 0; 5 > e; e++)
l & 1 << 4 - e && i.l_l[e]++,
i.l_l[e] *= 3;
i.d_v = w(i.l_l, [1, 0, 0, 1, 1], [0, 0, 0, 0, 1]),
o = r.cd + i.d_v[0],
n.open = o / r.m,
n.high = (o + i.d_v[1]) / r.m,
n.low = (o - i.d_v[2]) / r.m,
n.close = (o + i.d_v[3]) / r.m,
a = i.d_v[4],
"number" == typeof a && (a = [a, a >= 0 ? 0 : -1]),
r.cd = o + i.d_v[3],
l = r.cv[0] + a[0],
r.cv = [l & d, r.cv[1] + a[1] + !!((r.cv[0] & d) + (a[0] & d) & f)],
n.volume = (r.cv[0] & f - 1) + r.cv[1] * f,
t.push(n)
}
return t
}, k = function () {
var t, e, i, n;
if (s > 1)
return [];
for (r.l = 0,
n = -1,
r.d = w([18])[0] - 1,
i = w([18])[0]; r.d < i;)
e = x(1),
0 >= n ? (y() && (r.l += N()),
n = w([3 * r.l], [0])[0] + 1,
t || (t = [e],
n--)) : t.push(e),
n--;
return t
};
return _mi_run = function () {
var t, i, a, o;
if (s >= 1)
return [];
for (r.f = w([6])[0],
r.c = w([6])[0],
a = [],
r.dv = [],
r.dl = [],
t = 0; t < r.f; t++)
r.dv[t] = 0,
r.dl[t] = 0;
for (t = 0; !(e >= n) && (e != n - 1 || 7 & (r.c ^ t)); t++) {
for (o = [],
i = 0; i < r.f; i++)
y() && (r.dl[i] += N()),
r.dv[i] += w([3 * r.dl[i]], [1])[0],
o[i] = r.dv[i];
a.push(o)
}
return a
}
,
g()()
}
"""
def tool_trade_date_hist_sina() -> pd.DataFrame:
"""
交易日历-历史数据
https://finance.sina.com.cn/realstock/company/klc_td_sh.txt
:return: 交易日历
:rtype: pandas.DataFrame
"""
url = "https://finance.sina.com.cn/realstock/company/klc_td_sh.txt"
r = requests.get(url, proxies = proxys().get_proxies())
js_code = MiniRacer()
js_code.eval(hk_js_decode)
dict_list = js_code.call(
"d", r.text.split("=")[1].split(";")[0].replace('"', "")
) # 执行js解密代码
temp_df = pd.DataFrame(dict_list)
temp_df.columns = ["trade_date"]
temp_df["trade_date"] = pd.to_datetime(temp_df["trade_date"]).dt.date
temp_list = temp_df["trade_date"].to_list()
temp_list.append(datetime.date(1992, 5, 4)) # 是交易日但是交易日历缺失该日期
temp_list.sort()
temp_df = pd.DataFrame(temp_list, columns=["trade_date"])
return temp_df
if __name__ == "__main__":
tool_trade_date_hist_df = tool_trade_date_hist_sina()
print(tool_trade_date_hist_df)
================================================
FILE: instock/core/eastmoney_fetcher.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from pathlib import Path
import time
import random
from instock.core.singleton_proxy import proxys
__author__ = 'myh '
__date__ = '2025/12/31 '
class eastmoney_fetcher:
"""
东方财富网数据获取器
封装了Cookie管理、会话管理和请求发送功能
"""
def __init__(self):
"""初始化获取器"""
self.base_dir = os.path.dirname(os.path.dirname(__file__))
self.session = self._create_session()
self.proxies = proxys().get_proxies()
def _get_cookie(self):
"""
获取东方财富网的Cookie
优先级:环境变量 > 文件 > 默认Cookie
"""
# 1. 尝试从环境变量获取
cookie = os.environ.get('EAST_MONEY_COOKIE')
if cookie:
# print("环境变量中的Cookie: 已设置")
return cookie
# 2. 尝试从文件获取
cookie_file = Path(os.path.join(self.base_dir, 'config', 'eastmoney_cookie.txt'))
if cookie_file.exists():
with open(cookie_file, 'r') as f:
cookie = f.read().strip()
if cookie:
# print("文件中的Cookie: 已设置")
return cookie
# 3. 默认Cookie(可能过期,仅作为备选)
return 'st_si=78948464251292; st_psi=20260205091253851-119144370567-1089607836; st_pvi=07789985376191; st_sp=2026-02-05%2009%3A11%3A13; st_inirUrl=https%3A%2F%2Fxuangu.eastmoney.com%2FResult; st_sn=12; st_asi=20260205091253851-119144370567-1089607836-webznxg.dbssk.qxg-1'
def _create_session(self):
"""创建并配置会话"""
session = requests.Session()
# 配置连接池
retry_strategy = Retry(
total=3,
backoff_factor=0.1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["HEAD", "GET", "POST", "OPTIONS"]
)
adapter = HTTPAdapter(
max_retries=retry_strategy,
pool_connections=50, # 增加连接池大小
pool_maxsize=50 # 增加连接池最大大小
)
# 为http和https请求添加适配器
session.mount("http://", adapter)
session.mount("https://", adapter)
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Referer': 'https://quote.eastmoney.com/',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Accept-Encoding': 'gzip, deflate, br, zstd',
'Connection': 'keep-alive',
}
session.headers.update(headers)
# 设置Cookie
session.cookies.update({'Cookie': self._get_cookie()})
return session
def make_request(self, url, params=None, retry=3, timeout=10):
"""
发送请求
:param url: 请求URL
:param params: 请求参数
:param retry: 重试次数
:param timeout: 超时时间
:return: 响应对象
"""
for i in range(retry):
try:
response = self.session.get(
url,
proxies=self.proxies,
params=params,
timeout=timeout
)
response.raise_for_status() # 检查HTTP错误
return response
except requests.exceptions.RequestException as e:
print(f"请求错误: {e}, 第 {i + 1}/{retry} 次重试")
if i < retry - 1:
# 随机延迟后重试
time.sleep(random.uniform(1, 3))
else:
raise
def make_post_request(self, url, data=None, json=None, params=None, retry=3, timeout=60):
"""
发送POST请求
:param url: 请求URL
:param data: 请求数据(表单形式)
:param json: 请求数据(JSON形式)
:param params: URL参数
:param retry: 重试次数
:param timeout: 超时时间
:return: 响应对象
"""
for i in range(retry):
try:
response = self.session.post(
url,
proxies=self.proxies,
params=params,
data=data,
json=json,
timeout=timeout
)
response.raise_for_status() # 检查HTTP错误
return response
except requests.exceptions.RequestException as e:
print(f"请求错误: {e}, 第 {i + 1}/{retry} 次重试")
if i < retry - 1:
# 随机延迟后重试
time.sleep(random.uniform(1, 3))
else:
raise
def update_cookie(self, new_cookie):
"""
更新Cookie
:param new_cookie: 新的Cookie值
"""
self.session.cookies.update({'Cookie': new_cookie})
================================================
FILE: instock/core/indicator/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs document
gitextract_qm3wy6o4/
├── .github/
│ └── workflows/
│ ├── azure-container-webapp.yml
│ └── docker-image.yml
├── .gitignore
├── LICENSE
├── README.md
├── cron/
│ ├── cron.hourly/
│ │ └── run_hourly
│ ├── cron.monthly/
│ │ └── run_monthly
│ └── cron.workdayly/
│ └── run_workdayly
├── docker/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── Dockerfile
│ ├── build.sh
│ └── docker-compose.yml
├── instock/
│ ├── .gitignore
│ ├── __init__.py
│ ├── bin/
│ │ ├── restart_web.sh
│ │ ├── run_cron.sh
│ │ ├── run_job.bat
│ │ ├── run_job.sh
│ │ ├── run_trade.bat
│ │ ├── run_web.bat
│ │ └── run_web.sh
│ ├── config/
│ │ ├── .gitignore
│ │ ├── eastmoney_cookie.txt
│ │ ├── proxy.txt
│ │ └── trade_client.json
│ ├── core/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── backtest/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ └── rate_stats.py
│ │ ├── crawling/
│ │ │ ├── __init__.py
│ │ │ ├── fund_etf_em.py
│ │ │ ├── stock_chip_race.py
│ │ │ ├── stock_cpbd.py
│ │ │ ├── stock_dzjy_em.py
│ │ │ ├── stock_fhps_em.py
│ │ │ ├── stock_fund_em.py
│ │ │ ├── stock_hist_em.py
│ │ │ ├── stock_lhb_em.py
│ │ │ ├── stock_lhb_sina.py
│ │ │ ├── stock_limitup_reason.py
│ │ │ ├── stock_selection.py
│ │ │ └── trade_date_hist.py
│ │ ├── eastmoney_fetcher.py
│ │ ├── indicator/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ └── calculate_indicator.py
│ │ ├── kline/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── cyq.js
│ │ │ ├── cyq.py
│ │ │ ├── indicator_web_dic.py
│ │ │ └── visualization.py
│ │ ├── pattern/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ └── pattern_recognitions.py
│ │ ├── singleton_proxy.py
│ │ ├── singleton_stock.py
│ │ ├── singleton_stock_web_module_data.py
│ │ ├── singleton_trade_date.py
│ │ ├── stockfetch.py
│ │ ├── strategy/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── backtrace_ma250.py
│ │ │ ├── breakthrough_platform.py
│ │ │ ├── climax_limitdown.py
│ │ │ ├── enter.py
│ │ │ ├── high_tight_flag.py
│ │ │ ├── keep_increasing.py
│ │ │ ├── low_atr.py
│ │ │ ├── low_backtrace_increase.py
│ │ │ ├── parking_apron.py
│ │ │ └── turtle_trade.py
│ │ ├── tablestructure.py
│ │ └── web_module_data.py
│ ├── job/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── backtest_data_daily_job.py
│ │ ├── basic_data_after_close_daily_job.py
│ │ ├── basic_data_daily_job.py
│ │ ├── basic_data_other_daily_job.py
│ │ ├── execute_daily_job.py
│ │ ├── indicators_data_daily_job.py
│ │ ├── init_job.py
│ │ ├── klinepattern_data_daily_job.py
│ │ ├── selection_data_daily_job.py
│ │ └── strategy_data_daily_job.py
│ ├── trade/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── robot/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── engine/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── __init__.py
│ │ │ │ ├── clock_engine.py
│ │ │ │ ├── event_engine.py
│ │ │ │ └── main_engine.py
│ │ │ └── infrastructure/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── default_handler.py
│ │ │ ├── strategy_template.py
│ │ │ └── strategy_wrapper.py
│ │ ├── strategies/
│ │ │ ├── .gitignore
│ │ │ ├── __init__.py
│ │ │ ├── stagging.py
│ │ │ └── stratey1.py
│ │ ├── trade_service.py
│ │ └── usage.md
│ └── web/
│ ├── .gitignore
│ ├── __init__.py
│ ├── base.py
│ ├── dataIndicatorsHandler.py
│ ├── dataTableHandler.py
│ ├── static/
│ │ ├── css/
│ │ │ ├── bootstrap.min-3.4.1.css
│ │ │ ├── font-awesome.min-4.5.0.css
│ │ │ └── gc.spread.sheets.excel2013white.css
│ │ └── js/
│ │ ├── FileSaver.js
│ │ ├── bootstrap.min-3.4.1.js
│ │ └── jquery.min-3.7.1.js
│ ├── templates/
│ │ ├── common/
│ │ │ ├── footer.html
│ │ │ ├── header.html
│ │ │ ├── left_menu.html
│ │ │ └── meta.html
│ │ ├── index.html
│ │ ├── layout/
│ │ │ ├── default.html
│ │ │ ├── indicators-main.html
│ │ │ ├── indicators.html
│ │ │ └── main.html
│ │ ├── stock_indicators.html
│ │ └── stock_web.html
│ └── web_service.py
├── requirements.txt
└── supervisor/
└── supervisord.conf
SYMBOL INDEX (351 symbols across 62 files)
FILE: instock/core/backtest/rate_stats.py
function get_rates (line 12) | def get_rates(code_name, data, stock_column, threshold=101):
FILE: instock/core/crawling/fund_etf_em.py
function fund_etf_spot_em (line 21) | def fund_etf_spot_em() -> pd.DataFrame:
function _fund_etf_code_id_map_em (line 119) | def _fund_etf_code_id_map_em() -> dict:
function fund_etf_hist_em (line 147) | def fund_etf_hist_em(
function fund_etf_hist_min_em (line 219) | def fund_etf_hist_min_em(
FILE: instock/core/crawling/stock_chip_race.py
function stock_chip_race_open (line 16) | def stock_chip_race_open(date: str = "") -> pd.DataFrame:
function stock_chip_race_end (line 84) | def stock_chip_race_end(date: str = "") -> pd.DataFrame:
FILE: instock/core/crawling/stock_cpbd.py
function stock_cpbd_em (line 14) | def stock_cpbd_em(symbol: str = "688041") -> pd.DataFrame:
function stock_zjlx_em (line 105) | def stock_zjlx_em(symbol: str = "688041") -> pd.DataFrame:
FILE: instock/core/crawling/stock_dzjy_em.py
function stock_dzjy_sctj (line 20) | def stock_dzjy_sctj() -> pd.DataFrame:
function stock_dzjy_mrmx (line 75) | def stock_dzjy_mrmx(symbol: str = '基金', start_date: str = '20220104', en...
function stock_dzjy_mrtj (line 200) | def stock_dzjy_mrtj(start_date: str = '20220105', end_date: str = '20220...
function stock_dzjy_hygtj (line 273) | def stock_dzjy_hygtj(symbol: str = '近三月') -> pd.DataFrame:
function stock_dzjy_hyyybtj (line 369) | def stock_dzjy_hyyybtj(symbol: str = '近3日') -> pd.DataFrame:
function stock_dzjy_yybph (line 445) | def stock_dzjy_yybph(symbol: str = '近三月') -> pd.DataFrame:
FILE: instock/core/crawling/stock_fhps_em.py
function stock_fhps_em (line 21) | def stock_fhps_em(date: str = "20231231") -> pd.DataFrame:
FILE: instock/core/crawling/stock_fund_em.py
function stock_individual_fund_flow_rank (line 21) | def stock_individual_fund_flow_rank(indicator: str = "5日") -> pd.DataFrame:
function stock_sector_fund_flow_rank (line 241) | def stock_sector_fund_flow_rank(
FILE: instock/core/crawling/stock_hist_em.py
function stock_zh_a_spot_em (line 21) | def stock_zh_a_spot_em() -> pd.DataFrame:
function code_id_map_em (line 192) | def code_id_map_em() -> dict:
function stock_zh_a_hist (line 313) | def stock_zh_a_hist(
function stock_zh_a_hist_min_em (line 388) | def stock_zh_a_hist_min_em(
function stock_zh_a_hist_pre_min_em (line 518) | def stock_zh_a_hist_pre_min_em(
FILE: instock/core/crawling/stock_lhb_em.py
function stock_lhb_detail_em (line 21) | def stock_lhb_detail_em(
function stock_lhb_stock_statistic_em (line 139) | def stock_lhb_stock_statistic_em(symbol: str = "近一月") -> pd.DataFrame:
function stock_lhb_jgmmtj_em (line 226) | def stock_lhb_jgmmtj_em(
function stock_lhb_jgstatistic_em (line 322) | def stock_lhb_jgstatistic_em(symbol: str = "近一月") -> pd.DataFrame:
function stock_lhb_hyyyb_em (line 422) | def stock_lhb_hyyyb_em(
function stock_lhb_yybph_em (line 503) | def stock_lhb_yybph_em(symbol: str = "近一月") -> pd.DataFrame:
function stock_lhb_traderstatistic_em (line 611) | def stock_lhb_traderstatistic_em(symbol: str = "近一月") -> pd.DataFrame:
function stock_lhb_stock_detail_date_em (line 688) | def stock_lhb_stock_detail_date_em(symbol: str = "600077") -> pd.DataFrame:
function stock_lhb_stock_detail_em (line 731) | def stock_lhb_stock_detail_em(
FILE: instock/core/crawling/stock_lhb_sina.py
function stock_lhb_detail_daily_sina (line 17) | def stock_lhb_detail_daily_sina(date: str = "20240222") -> pd.DataFrame:
function _find_last_page (line 59) | def _find_last_page(
function stock_lhb_ggtj_sina (line 90) | def stock_lhb_ggtj_sina(symbol: str = "5") -> pd.DataFrame:
function stock_lhb_yytj_sina (line 126) | def stock_lhb_yytj_sina(symbol: str = "5") -> pd.DataFrame:
function stock_lhb_jgzz_sina (line 163) | def stock_lhb_jgzz_sina(symbol: str = "5") -> pd.DataFrame:
function stock_lhb_jgmx_sina (line 204) | def stock_lhb_jgmx_sina() -> pd.DataFrame:
FILE: instock/core/crawling/stock_limitup_reason.py
function stock_limitup_reason (line 18) | def stock_limitup_reason(date: str = "2025-02-27") -> pd.DataFrame:
function stock_limitup_detail (line 92) | def stock_limitup_detail(row):
FILE: instock/core/crawling/stock_selection.py
function stock_selection (line 17) | def stock_selection() -> pd.DataFrame:
function stock_selection_params (line 76) | def stock_selection_params():
FILE: instock/core/crawling/trade_date_hist.py
function tool_trade_date_hist_sina (line 306) | def tool_trade_date_hist_sina() -> pd.DataFrame:
FILE: instock/core/eastmoney_fetcher.py
class eastmoney_fetcher (line 16) | class eastmoney_fetcher:
method __init__ (line 22) | def __init__(self):
method _get_cookie (line 28) | def _get_cookie(self):
method _create_session (line 51) | def _create_session(self):
method make_request (line 86) | def make_request(self, url, params=None, retry=3, timeout=10):
method make_post_request (line 113) | def make_post_request(self, url, data=None, json=None, params=None, re...
method update_cookie (line 144) | def update_cookie(self, new_cookie):
FILE: instock/core/indicator/calculate_indicator.py
function get_indicators (line 13) | def get_indicators(data, end_date=None, threshold=120, calc_threshold=No...
function get_indicator (line 417) | def get_indicator(code_name, data, stock_column, date=None, calc_thresho...
FILE: instock/core/kline/cyq.js
function CYQCalculator (line 9) | function CYQCalculator(kdata, accuracyFactor, range, cyq_days) {
function getCostByChip (line 138) | function getCostByChip(chip) {
function CYQData (line 153) | function CYQData() {
function CYQDraw (line 228) | function CYQDraw(index) {
FILE: instock/core/kline/cyq.py
class CYQCalculator (line 13) | class CYQCalculator:
method __init__ (line 14) | def __init__(self, kdata, accuracy_factor=150, crange=120, cyq_days=210):
method calc (line 27) | def calc(self, index):
FILE: instock/core/kline/visualization.py
function get_plot_kline (line 29) | def get_plot_kline(code, stock, date, stock_name):
FILE: instock/core/pattern/pattern_recognitions.py
function get_pattern_recognitions (line 10) | def get_pattern_recognitions(data, stock_column, end_date=None, threshol...
function get_pattern_recognition (line 37) | def get_pattern_recognition(code_name, data, stock_column, date=None, ca...
FILE: instock/core/singleton_proxy.py
class proxys (line 20) | class proxys(metaclass=singleton_type):
method __init__ (line 21) | def __init__(self):
method get_data (line 28) | def get_data(self):
method get_proxies (line 31) | def get_proxies(self):
FILE: instock/core/singleton_stock.py
class stock_data (line 16) | class stock_data(metaclass=singleton_type):
method __init__ (line 17) | def __init__(self, date):
method get_data (line 23) | def get_data(self):
class stock_hist_data (line 28) | class stock_hist_data(metaclass=singleton_type):
method __init__ (line 29) | def __init__(self, date=None, stocks=None, workers=16):
method get_data (line 58) | def get_data(self):
FILE: instock/core/singleton_stock_web_module_data.py
class stock_web_module_data (line 12) | class stock_web_module_data(metaclass=singleton_type):
method __init__ (line 13) | def __init__(self):
method get_data_list (line 237) | def get_data_list(self):
method get_data (line 240) | def get_data(self, name):
FILE: instock/core/singleton_trade_date.py
class stock_trade_date (line 13) | class stock_trade_date(metaclass=singleton_type):
method __init__ (line 14) | def __init__(self):
method get_data (line 20) | def get_data(self):
FILE: instock/core/stockfetch.py
function is_a_stock (line 43) | def is_a_stock(code):
function is_not_st (line 49) | def is_not_st(name):
function is_open (line 54) | def is_open(price):
function is_open_with_line (line 58) | def is_open_with_line(price):
function fetch_stocks_trade_date (line 63) | def fetch_stocks_trade_date():
function fetch_etfs (line 76) | def fetch_etfs(date):
function fetch_stocks (line 94) | def fetch_stocks(date):
function fetch_stock_selection (line 111) | def fetch_stock_selection():
function fetch_stocks_fund_flow (line 125) | def fetch_stocks_fund_flow(index):
function fetch_stocks_sector_fund_flow (line 140) | def fetch_stocks_sector_fund_flow(index_sector, index_indicator):
function fetch_stocks_bonus (line 154) | def fetch_stocks_bonus(date):
function fetch_stock_top_entity_data (line 172) | def fetch_stock_top_entity_data(date):
function fetch_stock_lhb_data (line 203) | def fetch_stock_lhb_data(date,count=12):
function fetch_stock_top_data (line 227) | def fetch_stock_top_data(date):
function fetch_stock_blocktrade_data (line 248) | def fetch_stock_blocktrade_data(date):
function fetch_stock_chip_race_open (line 269) | def fetch_stock_chip_race_open(date):
function fetch_stock_chip_race_end (line 288) | def fetch_stock_chip_race_end(date):
function fetch_stock_limitup_reason (line 307) | def fetch_stock_limitup_reason(date):
function fetch_etf_hist (line 320) | def fetch_etf_hist(data_base, date_start=None, date_end=None, adjust='qf...
function fetch_stock_hist (line 348) | def fetch_stock_hist(data_base, date_start=None, is_cache=True):
function stock_hist_cache (line 368) | def stock_hist_cache(code, date_start, date_end=None, is_cache=True, adj...
FILE: instock/core/strategy/backtrace_ma250.py
function check (line 17) | def check(code_name, data, date=None, threshold=60):
FILE: instock/core/strategy/breakthrough_platform.py
function check (line 17) | def check(code_name, data, date=None, threshold=60):
FILE: instock/core/strategy/climax_limitdown.py
function check (line 15) | def check(code_name, data, date=None, threshold=60):
FILE: instock/core/strategy/enter.py
function check_volume (line 16) | def check_volume(code_name, data, date=None, threshold=60):
FILE: instock/core/strategy/high_tight_flag.py
function check_high_tight (line 13) | def check_high_tight(code_name, data, date=None, threshold=60, istop=Fal...
FILE: instock/core/strategy/keep_increasing.py
function check (line 15) | def check(code_name, data, date=None, threshold=30):
FILE: instock/core/strategy/low_atr.py
function check_low_increase (line 12) | def check_low_increase(code_name, data, date=None, ma_short=30, ma_long=...
FILE: instock/core/strategy/low_backtrace_increase.py
function check (line 12) | def check(code_name, data, date=None, threshold=60):
FILE: instock/core/strategy/parking_apron.py
function check (line 15) | def check(code_name, data, date=None, threshold=15):
function check_internal (line 40) | def check_internal(data, limitup_row):
FILE: instock/core/strategy/turtle_trade.py
function check_enter (line 14) | def check_enter(code_name, data, date=None, threshold=60):
FILE: instock/core/tablestructure.py
function get_field_cn (line 1038) | def get_field_cn(key, table):
function get_field_cns (line 1045) | def get_field_cns(cols):
function get_field_types (line 1064) | def get_field_types(cols):
function get_field_type_name (line 1071) | def get_field_type_name(col_type):
FILE: instock/core/web_module_data.py
class web_module_data (line 9) | class web_module_data:
method __init__ (line 10) | def __init__(self, mode, type, ico, name, table_name, columns, column_...
FILE: instock/job/backtest_data_daily_job.py
function prepare (line 25) | def prepare():
function process (line 45) | def process(table, data_all, date, backtest_column):
function run_check (line 74) | def run_check(stocks, data_all, date, backtest_column, workers=40):
function main (line 97) | def main():
FILE: instock/job/basic_data_after_close_daily_job.py
function save_after_close_stock_blocktrade_data (line 21) | def save_after_close_stock_blocktrade_data(date):
function save_after_close_stock_chip_race_end_data (line 41) | def save_after_close_stock_chip_race_end_data(date):
function main (line 60) | def main():
FILE: instock/job/basic_data_daily_job.py
function save_nph_stock_spot_data (line 22) | def save_nph_stock_spot_data(date, before=True):
function save_nph_etf_spot_data (line 47) | def save_nph_etf_spot_data(date, before=True):
function main (line 71) | def main():
FILE: instock/job/basic_data_other_daily_job.py
function save_nph_stock_lhb_data (line 22) | def save_nph_stock_lhb_data(date, before=True):
function save_nph_stock_top_data (line 45) | def save_nph_stock_top_data(date, before=True):
function save_nph_stock_fund_flow_data (line 69) | def save_nph_stock_fund_flow_data(date, before=True):
function run_check_stock_fund_flow (line 107) | def run_check_stock_fund_flow(times):
function save_nph_stock_sector_fund_flow_data (line 136) | def save_nph_stock_sector_fund_flow_data(date, before=True):
function stock_sector_fund_flow_data (line 146) | def stock_sector_fund_flow_data(date, index_sector):
function run_check_stock_sector_fund_flow (line 184) | def run_check_stock_sector_fund_flow(index_sector, times):
function save_nph_stock_bonus (line 206) | def save_nph_stock_bonus(date, before=True):
function stock_spot_buy (line 229) | def stock_spot_buy(date):
function stock_chip_race_open_data (line 257) | def stock_chip_race_open_data(date):
function stock_imitup_reason_data (line 278) | def stock_imitup_reason_data(date):
function main (line 297) | def main():
FILE: instock/job/execute_daily_job.py
function main (line 35) | def main():
FILE: instock/job/indicators_data_daily_job.py
function prepare (line 24) | def prepare(date):
function run_check (line 61) | def run_check(stocks, date=None, workers=40):
function guess_buy (line 88) | def guess_buy(date):
function guess_sell (line 123) | def guess_sell(date):
function main (line 156) | def main():
FILE: instock/job/init_job.py
function create_new_database (line 20) | def create_new_database():
function create_new_base_table (line 34) | def create_new_base_table():
function check_database (line 46) | def check_database():
function main (line 52) | def main():
FILE: instock/job/klinepattern_data_daily_job.py
function prepare (line 24) | def prepare(date):
function run_check (line 59) | def run_check(stocks, date=None, workers=40):
function main (line 82) | def main():
FILE: instock/job/selection_data_daily_job.py
function save_nph_stock_selection_data (line 22) | def save_nph_stock_selection_data(date, before=True):
function main (line 46) | def main():
FILE: instock/job/strategy_data_daily_job.py
function prepare (line 23) | def prepare(date, strategy):
function run_check (line 57) | def run_check(strategy_fun, table_name, stocks, date, workers=40):
function main (line 85) | def main():
FILE: instock/trade/robot/engine/clock_engine.py
class Clock (line 17) | class Clock:
method __init__ (line 18) | def __init__(self, trading_time, clock_event):
class ClockIntervalHandler (line 23) | class ClockIntervalHandler:
method __init__ (line 24) | def __init__(self, clock_engine, interval, trading=True, call=None):
method is_active (line 37) | def is_active(self):
method __eq__ (line 43) | def __eq__(self, other):
method __hash__ (line 49) | def __hash__(self):
class ClockMomentHandler (line 53) | class ClockMomentHandler:
method __init__ (line 54) | def __init__(self, clock_engine, clock_type, moment=None, is_trading_d...
method update_next_time (line 76) | def update_next_time(self):
method is_active (line 92) | def is_active(self):
class ClockEngine (line 99) | class ClockEngine:
method __init__ (line 106) | def __init__(self, event_engine, tzinfo=None):
method _init_clock_handler (line 126) | def _init_clock_handler(self):
method now (line 155) | def now(self):
method now_dt (line 163) | def now_dt(self):
method start (line 169) | def start(self):
method clocktick (line 172) | def clocktick(self):
method tock (line 177) | def tock(self):
method _tock (line 183) | def _tock(self):
method push_event_type (line 201) | def push_event_type(self, clock_handler):
method stop (line 205) | def stop(self):
method is_tradetime_now (line 208) | def is_tradetime_now(self):
method register_moment (line 211) | def register_moment(self, clock_type, moment, makeup=False):
method _register_moment (line 214) | def _register_moment(self, clock_type, moment, is_trading_date=True, m...
method register_interval (line 224) | def register_interval(self, interval_minute, trading=True):
method _register_interval (line 227) | def _register_interval(self, interval_minute, trading=True, call=None):
FILE: instock/trade/robot/engine/event_engine.py
class Event (line 13) | class Event:
method __init__ (line 14) | def __init__(self, event_type, data=None):
class EventEngine (line 19) | class EventEngine:
method __init__ (line 22) | def __init__(self):
method __run (line 36) | def __run(self):
method __process (line 46) | def __process(self, event):
method start (line 54) | def start(self):
method stop (line 59) | def stop(self):
method register (line 64) | def register(self, event_type, handler):
method unregister (line 69) | def unregister(self, event_type, handler):
method put (line 79) | def put(self, event):
method queue_size (line 83) | def queue_size(self):
FILE: instock/trade/robot/engine/main_engine.py
class MainEngine (line 22) | class MainEngine:
method __init__ (line 25) | def __init__(self, broker=None, need_data=None, log_handler=DefaultLog...
method start (line 81) | def start(self):
method load (line 92) | def load(self, names, strategy_file):
method strategy_listen_event (line 135) | def strategy_listen_event(self, strategy, _type="listen"):
method load_strategy (line 150) | def load_strategy(self, names=None):
method _load_strategy (line 165) | def _load_strategy(self):
method get_strategy (line 173) | def get_strategy(self, name):
method add_before_shutdown (line 179) | def add_before_shutdown(self, shutdown):
method add_after_shutdown (line 187) | def add_after_shutdown(self, shutdown):
method _add_main_shutdown (line 194) | def _add_main_shutdown(self, shutdown):
method _shutdown (line 201) | def _shutdown(self, sig, frame):
FILE: instock/trade/robot/infrastructure/default_handler.py
class DefaultLogHandler (line 15) | class DefaultLogHandler(object):
method __init__ (line 18) | def __init__(self, name='default', log_type='stdout', filepath='defaul...
method __getattr__ (line 35) | def __getattr__(self, item, *args, **kwargs):
FILE: instock/trade/robot/infrastructure/strategy_template.py
class StrategyTemplate (line 9) | class StrategyTemplate:
method __init__ (line 12) | def __init__(self, user, log_handler, main_engine):
method init (line 20) | def init(self):
method strategy (line 24) | def strategy(self):
method clock (line 27) | def clock(self, event):
method log_handler (line 30) | def log_handler(self):
method shutdown (line 37) | def shutdown(self):
FILE: instock/trade/robot/infrastructure/strategy_wrapper.py
class ProcessWrapper (line 12) | class ProcessWrapper(object):
method __init__ (line 13) | def __init__(self, strategy):
method stop (line 21) | def stop(self):
method on_clock (line 25) | def on_clock(self, event):
method _process_clock (line 28) | def _process_clock(self):
method _process (line 40) | def _process(self):
FILE: instock/trade/strategies/stagging.py
class Strategy (line 14) | class Strategy(StrategyTemplate):
method init (line 17) | def init(self):
method strategy (line 32) | def strategy(self):
method clock (line 36) | def clock(self, event):
method log_handler (line 44) | def log_handler(self):
method shutdown (line 51) | def shutdown(self):
FILE: instock/trade/strategies/stratey1.py
class Strategy (line 14) | class Strategy(StrategyTemplate):
method init (line 17) | def init(self):
method strategy (line 32) | def strategy(self):
method clock (line 47) | def clock(self, event):
method log_handler (line 55) | def log_handler(self):
method shutdown (line 62) | def shutdown(self):
FILE: instock/trade/trade_service.py
function main (line 19) | def main():
FILE: instock/web/base.py
class BaseHandler (line 13) | class BaseHandler(tornado.web.RequestHandler, ABC):
method db (line 15) | def db(self):
class LeftMenu (line 25) | class LeftMenu:
method __init__ (line 26) | def __init__(self, url):
function GetLeftMenu (line 32) | def GetLeftMenu(url):
FILE: instock/web/dataIndicatorsHandler.py
class GetDataIndicatorsHandler (line 16) | class GetDataIndicatorsHandler(webBase.BaseHandler, ABC):
method get (line 18) | def get(self):
class SaveCollectHandler (line 44) | class SaveCollectHandler(webBase.BaseHandler, ABC):
method get (line 46) | def get(self):
FILE: instock/web/dataTableHandler.py
class MyEncoder (line 18) | class MyEncoder(json.JSONEncoder):
method default (line 20) | def default(self, obj):
class GetStockHtmlHandler (line 32) | class GetStockHtmlHandler(webBase.BaseHandler, ABC):
method get (line 34) | def get(self):
class GetStockDataHandler (line 47) | class GetStockDataHandler(webBase.BaseHandler, ABC):
method get (line 48) | def get(self):
FILE: instock/web/static/js/FileSaver.js
function bom (line 19) | function bom (blob, opts) {
function download (line 34) | function download (url, name, opts) {
function corsEnabled (line 47) | function corsEnabled (url) {
function click (line 58) | function click (node) {
FILE: instock/web/static/js/bootstrap.min-3.4.1.js
function n (line 6) | function n(){o.detach().trigger("closed.bs.alert").remove()}
function i (line 6) | function i(o){return this.each(function(){var t=s(this),e=t.data("bs.but...
function r (line 6) | function r(n){return this.each(function(){var t=p(this),e=t.data("bs.car...
function n (line 6) | function n(t){var e,i=t.attr("data-target")||(e=t.attr("href"))&&e.repla...
function l (line 6) | function l(o){return this.each(function(){var t=a(this),e=t.data("bs.col...
function l (line 6) | function l(t){var e=t.attr("data-target");e||(e=(e=t.attr("href"))&&/#[A...
function s (line 6) | function s(o){o&&3===o.which||(a(".dropdown-backdrop").remove(),a(r).eac...
function r (line 6) | function r(o,n){return this.each(function(){var t=a(this),e=t.data("bs.m...
function u (line 6) | function u(t,e){var i=t.nodeName.toLowerCase();if(-1!==g.inArray(i,e))re...
function n (line 6) | function n(t,e,i){if(0===t.length)return t;if(i&&"function"==typeof i)re...
function n (line 6) | function n(){"in"!=e.hoverState&&i.detach(),e.$element&&e.$element.remov...
function n (line 6) | function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(...
function e (line 6) | function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scr...
function e (line 6) | function e(i){return this.each(function(){var t=r(this),e=t.data("bs.tab...
function s (line 6) | function s(){o.removeClass("active").find("> .dropdown-menu > .active")....
function i (line 6) | function i(o){return this.each(function(){var t=l(this),e=t.data("bs.aff...
FILE: instock/web/static/js/jquery.min-3.7.1.js
function m (line 2) | function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e...
function x (line 2) | function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof...
function c (line 2) | function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e...
function fe (line 2) | function fe(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLower...
function p (line 2) | function p(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCode...
function I (line 2) | function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeTyp...
function W (line 2) | function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cach...
function F (line 2) | function F(e){return e[S]=!0,e}
function $ (line 2) | function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e...
function B (line 2) | function B(t){return function(e){return fe(e,"input")&&e.type===t}}
function _ (line 2) | function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&...
function z (line 2) | function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.d...
function X (line 2) | function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a...
function U (line 2) | function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}
function V (line 2) | function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeTyp...
function G (line 2) | function G(){}
function Y (line 2) | function Y(e,t){var n,r,i,o,a,s,u,l=c[e+" "];if(l)return t?0:l.slice(0);...
function Q (line 2) | function Q(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}
function J (line 2) | function J(a,e,t){var s=e.dir,u=e.next,l=u||s,c=t&&"parentNode"===l,f=n+...
function K (line 2) | function K(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--...
function Z (line 2) | function Z(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o...
function ee (line 2) | function ee(d,h,g,v,y,e){return v&&!v[S]&&(v=ee(v)),y&&!y[S]&&(y=ee(y,e)...
function te (line 2) | function te(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.r...
function ne (line 2) | function ne(e,t){var n,v,y,m,x,r,i=[],o=[],a=u[e+" "];if(!a){t||(t=Y(e))...
function re (line 2) | function re(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&Y(e=l...
function T (line 2) | function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t...
function A (line 2) | function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}
function N (line 2) | function N(e){return e}
function q (line 2) | function q(e){throw e}
function L (line 2) | function L(e,t,n,r){var i;try{e&&v(i=e.promise)?i.call(e).done(t).fail(n...
function l (line 2) | function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(...
function P (line 2) | function P(){C.removeEventListener("DOMContentLoaded",P),ie.removeEventL...
function W (line 2) | function W(e,t){return t.toUpperCase()}
function F (line 2) | function F(e){return e.replace(R,"ms-").replace(I,W)}
function B (line 2) | function B(){this.expando=ce.expando+B.uid++}
function V (line 2) | function V(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.r...
function te (line 2) | function te(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:functio...
function re (line 2) | function re(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[...
function Se (line 2) | function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagNa...
function Ee (line 2) | function Ee(e,t){for(var n=0,r=e.length;n<r;n++)_.set(e[n],"globalEval",...
function Ae (line 2) | function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),...
function Ne (line 2) | function Ne(){return!0}
function qe (line 2) | function qe(){return!1}
function Le (line 2) | function Le(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"...
function He (line 2) | function He(e,r,t){t?(_.set(e,r,!1),ce.event.add(e,r,{namespace:!1,handl...
function o (line 2) | function o(e){if(C.documentMode){var t=_.get(this,"handle"),n=ce.event.f...
function Re (line 2) | function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild...
function Ie (line 2) | function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}
function We (line 2) | function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.sli...
function Fe (line 2) | function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=...
function $e (line 2) | function $e(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],...
function Be (line 2) | function Be(e,t,n){for(var r,i=t?ce.filter(t,e):e,o=0;null!=(r=i[o]);o++...
function Ge (line 2) | function Ge(e,t,n){var r,i,o,a,s=ze.test(t),u=e.style;return(n=n||Xe(e))...
function Ye (line 2) | function Ye(e,t){return{get:function(){if(!e())return(this.get=t).apply(...
function e (line 2) | function e(){if(l){u.style.cssText="position:absolute;left:-11111px;widt...
function t (line 2) | function t(e){return Math.round(parseFloat(e))}
function Ze (line 2) | function Ze(e){var t=ce.cssProps[e]||Ke[e];return t||(e in Je?e:Ke[e]=fu...
function rt (line 2) | function rt(e,t,n){var r=Y.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3...
function it (line 2) | function it(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0,l=0;if(n===(r?"bo...
function ot (line 2) | function ot(e,t,n){var r=Xe(e),i=(!le.boxSizingReliable()||n)&&"border-b...
function at (line 2) | function at(e,t,n,r,i){return new at.prototype.init(e,t,n,r,i)}
function dt (line 2) | function dt(){ut&&(!1===C.hidden&&ie.requestAnimationFrame?ie.requestAni...
function ht (line 2) | function ht(){return ie.setTimeout(function(){st=void 0}),st=Date.now()}
function gt (line 2) | function gt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin...
function vt (line 2) | function vt(e,t,n){for(var r,i=(yt.tweeners[t]||[]).concat(yt.tweeners["...
function yt (line 2) | function yt(o,e,t){var n,a,r=0,i=yt.prefilters.length,s=ce.Deferred().al...
function Tt (line 2) | function Tt(e){return(e.match(D)||[]).join(" ")}
function Ct (line 2) | function Ct(e){return e.getAttribute&&e.getAttribute("class")||""}
function kt (line 2) | function kt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(D)|...
function Pt (line 2) | function Pt(n,e,r,i){var t;if(Array.isArray(e))ce.each(e,function(e,t){r...
function Ut (line 2) | function Ut(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var ...
function Vt (line 2) | function Vt(t,i,o,a){var s={},u=t===_t;function l(e){var r;return s[e]=!...
function Gt (line 2) | function Gt(e,t){var n,r,i=ce.ajaxSettings.flatOptions||{};for(n in t)vo...
function l (line 2) | function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&ie.clearTimeout(d),c=v...
FILE: instock/web/web_service.py
class Application (line 35) | class Application(tornado.web.Application):
method __init__ (line 36) | def __init__(self):
class HomeHandler (line 63) | class HomeHandler(webBase.BaseHandler, ABC):
method get (line 65) | def get(self):
function main (line 71) | def main():
Condensed preview — 133 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,317K chars).
[
{
"path": ".github/workflows/azure-container-webapp.yml",
"chars": 3071,
"preview": "# 当提交推送到默认分支时,此工作流将构建 Docker 容器并将其推送到 Azure Web 应用程序。\n#\n# 此工作流假设您已创建目标 Azure 应用服务 Web 应用。\n#相关说明,请参阅 https://docs.microso"
},
{
"path": ".github/workflows/docker-image.yml",
"chars": 357,
"preview": "姓名:名称:Docker 镜像 CI\n\non:\n push:\n branches: [ 分支:[“主”]\"master\" ]\n pull_request:\n branches: [ 分支:[“主”]\"master"
},
{
"path": ".gitignore",
"chars": 3083,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 14020,
"preview": "[对应IMA知识库](https://ima.qq.com/wiki/?shareId=8b0da768c77bc863f1cad8eb9482e37a6eeb26ad7171523b687d48c1a67c8e2c):专业量化级股票因子池"
},
{
"path": "cron/cron.hourly/run_hourly",
"chars": 173,
"preview": "#!/bin/sh\n\n/usr/local/bin/python3 /data/InStock/instock/job/basic_data_daily_job.py\n#mkdir -p /data/logs\n#DATE=`date +%Y"
},
{
"path": "cron/cron.monthly/run_monthly",
"chars": 430,
"preview": "#!/bin/sh\n\n#清除缓存数据\nrm -rf /data/InStock/instock/cache/hist/*\n#MONTH=`date -d '' +%Y%m`\n#cd /data/InStock/instock/cache/h"
},
{
"path": "cron/cron.workdayly/run_workdayly",
"chars": 174,
"preview": "#!/bin/sh\n\n/usr/local/bin/python3 /data/InStock/instock/job/execute_daily_job.py\n\n#mkdir -p /data/logs\n#DATE=`date +%Y-%"
},
{
"path": "docker/.dockerignore",
"chars": 38,
"preview": ".git\n.idea\n*.bat\n*.md\nrequirements.txt"
},
{
"path": "docker/.gitignore",
"chars": 3087,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "docker/Dockerfile",
"chars": 2948,
"preview": "# 基础镜像\n# https://hub.docker.com/_/python/tags?page=1&name=3.11-slim-bullseye\nFROM docker.io/python:3.11-slim-bullseye\n\nM"
},
{
"path": "docker/build.sh",
"chars": 714,
"preview": "#!/bin/sh\n\nrm -rf stock\nrsync -av --progress ../../stock . --exclude .git --exclude .idea --exclude *.md --exclude *.bat"
},
{
"path": "docker/docker-compose.yml",
"chars": 633,
"preview": "version: '4.0.0'\n\nservices:\n instockdbservice:\n image: library/mariadb:latest\n container_name: InStockDbService\n "
},
{
"path": "instock/.gitignore",
"chars": 3090,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/__init__.py",
"chars": 91,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/3 '\n"
},
{
"path": "instock/bin/restart_web.sh",
"chars": 117,
"preview": "#!/bin/sh\n\nps -ef | grep python3 | grep '/data/InStock/instock/web/web_service.py' | awk '{print$2}' | xargs kill -9\n"
},
{
"path": "instock/bin/run_cron.sh",
"chars": 330,
"preview": "#!/bin/sh\n\nexport PYTHONIOENCODING=utf-8\nexport LANG=zh_CN.UTF-8\nexport PYTHONPATH=/data/InStock\nexport LC_CTYPE=zh_CN.U"
},
{
"path": "instock/bin/run_job.bat",
"chars": 1181,
"preview": "chcp 65001\n@echo off\ncd %~dp0\ncd ..\ncd job\necho ------整体作业,支持批量作业------\necho 当前时间作业 python execute_daily_job.py\necho 1个时"
},
{
"path": "instock/bin/run_job.sh",
"chars": 847,
"preview": "#!/bin/sh\n\n#export PYTHONPATH=/data/InStock\n\n#nohup &\n/usr/local/bin/python3 /data/InStock/instock/job/execute_daily_jo"
},
{
"path": "instock/bin/run_trade.bat",
"chars": 111,
"preview": "chcp 65001\n@echo off\ncd %~dp0\ncd ..\ncd trade\npython trade_service.py\necho ------交易服务已启动,请不要关闭------\npause\nexit\n"
},
{
"path": "instock/bin/run_web.bat",
"chars": 143,
"preview": "chcp 65001\n@echo off\ncd %~dp0\ncd ..\ncd web\npython web_service.py\necho ------Web服务已启动,请不要关闭------\necho 访问地址 : http://loca"
},
{
"path": "instock/bin/run_web.sh",
"chars": 145,
"preview": "#!/bin/bash\n\n/usr/local/bin/python3 /data/InStock/instock/web/web_service.py\n\necho ------Web服务已启动 请不要关闭------\necho 访问地址 "
},
{
"path": "instock/config/.gitignore",
"chars": 3082,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/config/eastmoney_cookie.txt",
"chars": 0,
"preview": ""
},
{
"path": "instock/config/proxy.txt",
"chars": 0,
"preview": ""
},
{
"path": "instock/config/trade_client.json",
"chars": 92,
"preview": "{\n \"user\": \"888888888888\",\n \"password\": \"888888\",\n \"exe_path\": \"C:/gfzqrzrq/xiadan.exe\"\n}"
},
{
"path": "instock/core/.gitignore",
"chars": 3125,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/core/__init__.py",
"chars": 91,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/3 '\n"
},
{
"path": "instock/core/backtest/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/core/backtest/__init__.py",
"chars": 92,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/3/13 '\n"
},
{
"path": "instock/core/backtest/rate_stats.py",
"chars": 1376,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport numpy as np\nimport pandas as pd\n\n__author__ = 'myh"
},
{
"path": "instock/core/crawling/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "instock/core/crawling/fund_etf_em.py",
"chars": 11748,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2023/1/4 12:18\nDesc: 东方财富-ETF 行情\nhttps://quote.eastmoney.com/sh51"
},
{
"path": "instock/core/crawling/stock_chip_race.py",
"chars": 4411,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2025/2/26 12:18\nDesc: 通达信抢筹\nhttp://excalc.icfqs.com:7616/TQLEX?En"
},
{
"path": "instock/core/crawling/stock_cpbd.py",
"chars": 4816,
"preview": "# -*- coding:utf-8 -*-\n# !/usr/bin/env python\n\nimport pandas as pd\nimport instock.core.tablestructure as tbs\nfrom instoc"
},
{
"path": "instock/core/crawling/stock_dzjy_em.py",
"chars": 17437,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2022/5/16 15:31\nDesc: 东方财富网-数据中心-大宗交易-市场统计\nhttp://data.eastmoney."
},
{
"path": "instock/core/crawling/stock_fhps_em.py",
"chars": 4105,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2023/4/7 15:22\nDesc: 东方财富网-数据中心-年报季报-分红送配\nhttps://data.eastmoney."
},
{
"path": "instock/core/crawling/stock_fund_em.py",
"chars": 12429,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2023/5/16 15:30\nDesc: 东方财富网-数据中心-资金流向\nhttps://data.eastmoney.com/"
},
{
"path": "instock/core/crawling/stock_hist_em.py",
"chars": 19182,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2022/6/19 15:26\nDesc: 东方财富网-行情首页-沪深京 A 股\n\"\"\"\nimport random\nimport"
},
{
"path": "instock/core/crawling/stock_lhb_em.py",
"chars": 28481,
"preview": "# -*- coding:utf-8 -*-\n# !/usr/bin/env python\n\"\"\"\nDate: 2022/3/15 17:32\nDesc: 东方财富网-数据中心-龙虎榜单\nhttps://data.eastmoney.com"
},
{
"path": "instock/core/crawling/stock_lhb_sina.py",
"chars": 8569,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2024/5/10 00:00\nDesc: 新浪财经-龙虎榜\nhttps://vip.stock.finance.sina.com"
},
{
"path": "instock/core/crawling/stock_limitup_reason.py",
"chars": 3263,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2025/2/26 12:18\nDesc: 同花顺涨停原因\nhttp://zx.10jqka.com.cn/event/api/g"
},
{
"path": "instock/core/crawling/stock_selection.py",
"chars": 2919,
"preview": "# -*- coding:utf-8 -*-\n# !/usr/bin/env python\n\nimport math\nimport random\nimport time\nimport pandas as pd\nimport instock."
},
{
"path": "instock/core/crawling/trade_date_hist.py",
"chars": 12060,
"preview": "#!/usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\nDate: 2022/10/1 19:27\nDesc: 新浪财经-交易日历\nhttps://finance.sina.com.cn/reals"
},
{
"path": "instock/core/eastmoney_fetcher.py",
"chars": 4734,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os\nimport requests\nfrom requests.adapters import HTTPAdapter\nfrom"
},
{
"path": "instock/core/indicator/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/core/indicator/__init__.py",
"chars": 92,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'mmm '\n__date__ = '2023/3/10 '\n"
},
{
"path": "instock/core/indicator/calculate_indicator.py",
"chars": 25759,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport pandas as pd\nimport numpy as np\nimport talib as tl"
},
{
"path": "instock/core/kline/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/core/kline/__init__.py",
"chars": 91,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/6 '\n"
},
{
"path": "instock/core/kline/cyq.js",
"chars": 11280,
"preview": "// @ts-nocheck\n/**\n * 筹码分布算法\n * @param {Array.<Array.<string>>} kdata K图数据 [date,open,close,high,low,volume,amount,ampli"
},
{
"path": "instock/core/kline/cyq.py",
"chars": 5973,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2025/1/6 '\n\n\n# * 筹码分布算法\n# * @param {Ar"
},
{
"path": "instock/core/kline/indicator_web_dic.py",
"chars": 7113,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/6 '\n\n\n# 全部指标数据汇总\nindicators_dic ="
},
{
"path": "instock/core/kline/visualization.py",
"chars": 14625,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n\nimport numpy as np\nimport json\nimport logging\nimport os.path\n# 首映 bokeh"
},
{
"path": "instock/core/pattern/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/core/pattern/__init__.py",
"chars": 92,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/3/13 '\n"
},
{
"path": "instock/core/pattern/pattern_recognitions.py",
"chars": 1902,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport logging\n\n__author__ = 'myh '\n__date__ = '2023/3/24 '\n\n\ndef get_pa"
},
{
"path": "instock/core/singleton_proxy.py",
"chars": 1826,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os.path\nimport sys\nimport random\nfrom instock.lib.singleton_type "
},
{
"path": "instock/core/singleton_stock.py",
"chars": 2071,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport concurrent.futures\nimport instock.core.stockfetch "
},
{
"path": "instock/core/singleton_stock_web_module_data.py",
"chars": 12060,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\nimport instock.core.tablestructure as tbs\nfrom instock.lib.singleton_ty"
},
{
"path": "instock/core/singleton_trade_date.py",
"chars": 502,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport instock.core.stockfetch as stf\nfrom instock.lib.si"
},
{
"path": "instock/core/stockfetch.py",
"chars": 13945,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport os.path\nimport datetime\nimport numpy as np\nimport "
},
{
"path": "instock/core/strategy/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/core/strategy/__init__.py",
"chars": 92,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'mmm '\n__date__ = '2023/3/10 '\n"
},
{
"path": "instock/core/strategy/backtrace_ma250.py",
"chars": 2729,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\nimport numpy as np\nimport talib as tl\nfrom datetime import datetime, ti"
},
{
"path": "instock/core/strategy/breakthrough_platform.py",
"chars": 1526,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\nfrom datetime import datetime\nimport numpy as np\nimport talib as tl\nfro"
},
{
"path": "instock/core/strategy/climax_limitdown.py",
"chars": 1234,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\n\nimport numpy as np\nimport talib as tl\n\n__author__ = 'myh '\n__date__ = "
},
{
"path": "instock/core/strategy/enter.py",
"chars": 1300,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\nimport numpy as np\nimport talib as tl\n\n\n__author__ = 'myh '\n__date__ = "
},
{
"path": "instock/core/strategy/high_tight_flag.py",
"chars": 1172,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\n\n__author__ = 'myh '\n__date__ = '2023/3/10 '\n\n\n# 高而窄的旗形\n# 1.必须至少上市交易60日"
},
{
"path": "instock/core/strategy/keep_increasing.py",
"chars": 1023,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\nimport numpy as np\nimport talib as tl\n\n__author__ = 'myh '\n__date__ = '"
},
{
"path": "instock/core/strategy/low_atr.py",
"chars": 1681,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\n\n__author__ = 'myh '\n__date__ = '2023/3/10 '\n\n\n# 低ATR成长\n# 1.必须至少上市交易250"
},
{
"path": "instock/core/strategy/low_backtrace_increase.py",
"chars": 1218,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\n\n__author__ = 'myh '\n__date__ = '2023/3/10 '\n\n\n# 无大幅回撤\n# 1.当日收盘价比60日前的收"
},
{
"path": "instock/core/strategy/parking_apron.py",
"chars": 2063,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\nfrom datetime import datetime\nfrom instock.core.strategy import turtle_"
},
{
"path": "instock/core/strategy/turtle_trade.py",
"chars": 765,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\n\n__author__ = 'myh '\n__date__ = '2023/3/10 '\n\n# 总市值\nBALANCE = 200000\n\n#"
},
{
"path": "instock/core/tablestructure.py",
"chars": 93189,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nfrom sqlalchemy import DATE, VARCHAR, FLOAT, BIGINT, SmallInteger, DATET"
},
{
"path": "instock/core/web_module_data.py",
"chars": 715,
"preview": "#!/usr/local/bin/python\n# -*- coding: utf-8 -*-\n\n\n__author__ = 'myh '\n__date__ = '2023/5/11 '\n\n\nclass web_module_data:\n "
},
{
"path": "instock/job/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/job/__init__.py",
"chars": 91,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/3 '\n"
},
{
"path": "instock/job/backtest_data_daily_job.py",
"chars": 3361,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\n\nimport logging\nimport concurrent.futures\nimport pandas as pd\nimport o"
},
{
"path": "instock/job/basic_data_after_close_daily_job.py",
"chars": 2170,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport os.path\nimport sys\n\ncpath_current = os.path.dirn"
},
{
"path": "instock/job/basic_data_daily_job.py",
"chars": 2168,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport os.path\nimport sys\n\ncpath_current = os.path.dirn"
},
{
"path": "instock/job/basic_data_other_daily_job.py",
"chars": 10651,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport concurrent.futures\nimport os.path\nimport sys\nimp"
},
{
"path": "instock/job/execute_daily_job.py",
"chars": 1766,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n\nimport time\nimport datetime\nimport concurrent.futures\nimport logging\nim"
},
{
"path": "instock/job/indicators_data_daily_job.py",
"chars": 6037,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\n\nimport logging\nimport concurrent.futures\nimport pandas as pd\nimport o"
},
{
"path": "instock/job/init_job.py",
"chars": 2031,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\n\nimport logging\nimport pymysql\nimport os.path\nimport sys\n\ncpath_curren"
},
{
"path": "instock/job/klinepattern_data_daily_job.py",
"chars": 2844,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\n\nimport logging\nimport concurrent.futures\nimport pandas as pd\nimport o"
},
{
"path": "instock/job/selection_data_daily_job.py",
"chars": 1364,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\n\nimport logging\nimport pandas as pd\nimport os.path\nimport sys\n\ncpath_c"
},
{
"path": "instock/job/strategy_data_daily_job.py",
"chars": 3371,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport concurrent.futures\nimport pandas as pd\nimport os"
},
{
"path": "instock/trade/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/trade/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "instock/trade/robot/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/trade/robot/__init__.py",
"chars": 92,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/13 '\n"
},
{
"path": "instock/trade/robot/engine/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/trade/robot/engine/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "instock/trade/robot/engine/clock_engine.py",
"chars": 6928,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport datetime\nfrom collections import deque\nfrom threading import Thre"
},
{
"path": "instock/trade/robot/engine/event_engine.py",
"chars": 2128,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n\nfrom collections import defaultdict\nfrom queue import Queue, Empty\nfrom"
},
{
"path": "instock/trade/robot/engine/main_engine.py",
"chars": 7486,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport importlib\nimport os\nimport pathlib\nimport signal\nimport sys\nimpor"
},
{
"path": "instock/trade/robot/infrastructure/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/trade/robot/infrastructure/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "instock/trade/robot/infrastructure/default_handler.py",
"chars": 1202,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os\nimport sys\nimport logbook\nfrom logbook import Logger, StreamHa"
},
{
"path": "instock/trade/robot/infrastructure/strategy_template.py",
"chars": 830,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n\n__author__ = 'myh '\n__date__ = '2023/4/10 '\n\n\nclass StrategyTemplate:\n "
},
{
"path": "instock/trade/robot/infrastructure/strategy_wrapper.py",
"chars": 1034,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n\nimport multiprocessing as mp\nfrom threading import Thread\n\n__author__ ="
},
{
"path": "instock/trade/strategies/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/trade/strategies/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "instock/trade/strategies/stagging.py",
"chars": 1726,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os.path\nimport datetime as dt\nfrom dateutil import tz\nfrom instoc"
},
{
"path": "instock/trade/strategies/stratey1.py",
"chars": 2114,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os.path\nimport datetime as dt\nfrom dateutil import tz\nfrom instoc"
},
{
"path": "instock/trade/trade_service.py",
"chars": 899,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os.path\nimport sys\n# 在项目运行时,临时将项目路径添加到环境变量\ncpath_current = os.pat"
},
{
"path": "instock/trade/usage.md",
"chars": 7030,
"preview": "## 一、引入\n\n```python\nimport easytrader\n```\n\n## 二、设置交易客户端类型\n\n**海通客户端**\n\n```python\nuser = easytrader.use('htzq_client')\n```\n"
},
{
"path": "instock/web/.gitignore",
"chars": 3077,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "instock/web/__init__.py",
"chars": 91,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\n__author__ = 'myh '\n__date__ = '2023/4/3 '\n"
},
{
"path": "instock/web/base.py",
"chars": 749,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nfrom abc import ABC\nimport tornado.web\nimport instock.core.singleton_s"
},
{
"path": "instock/web/dataIndicatorsHandler.py",
"chars": 2360,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nfrom abc import ABC\nfrom tornado import gen\nimport logging\nimport inst"
},
{
"path": "instock/web/dataTableHandler.py",
"chars": 2465,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\n\nimport json\nfrom abc import ABC\nfrom tornado import gen\n# import logg"
},
{
"path": "instock/web/static/css/bootstrap.min-3.4.1.css",
"chars": 121457,
"preview": "/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://"
},
{
"path": "instock/web/static/css/font-awesome.min-4.5.0.css",
"chars": 27466,
"preview": "/*!\n * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome\n * License - http://fontawesome.io/lice"
},
{
"path": "instock/web/static/css/gc.spread.sheets.excel2013white.css",
"chars": 446751,
"preview": "@charset \"UTF-8\";\n/*----- css variables -----*/\n:root {\n --sjs-theme-font-family: \"Segoe UI\", Calibri, Thonburi, Arial,"
},
{
"path": "instock/web/static/js/FileSaver.js",
"chars": 5628,
"preview": "/*\n* FileSaver.js\n* A saveAs() FileSaver implementation.\n*\n* By Eli Grey, http://eligrey.com\n*\n* License : https://githu"
},
{
"path": "instock/web/static/js/bootstrap.min-3.4.1.js",
"chars": 39680,
"preview": "/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under the MIT licen"
},
{
"path": "instock/web/static/js/jquery.min-3.7.1.js",
"chars": 87532,
"preview": "/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */\n!function(e,t){\"use strict\";\"ob"
},
{
"path": "instock/web/templates/common/footer.html",
"chars": 28,
"preview": "{% block footer %}\n{% end %}"
},
{
"path": "instock/web/templates/common/header.html",
"chars": 28,
"preview": "{% block header %}\n{% end %}"
},
{
"path": "instock/web/templates/common/left_menu.html",
"chars": 4573,
"preview": "{% block left_menu %}\n<link rel=\"stylesheet\" href=\"/static/css/ace.min.css\" class=\"ace-main-stylesheet\" id=\"main-ace-sty"
},
{
"path": "instock/web/templates/common/meta.html",
"chars": 661,
"preview": "{% block meta %}\n<meta name=\"spreadjs culture\" content=\"zh-cn\" />\n<link rel=\"icon\" href=\"/static/img/favicon.ico\">\n<link"
},
{
"path": "instock/web/templates/index.html",
"chars": 13751,
"preview": "{% extends \"layout/default.html\" %}\n\n{% block main_content %}\n<div class=\"page-content\">\n <h3 class=\"header smaller l"
},
{
"path": "instock/web/templates/layout/default.html",
"chars": 179,
"preview": "{% extends \"../common/meta.html\" %}\n{% extends \"../common/header.html\" %}\n{% extends \"../common/footer.html\" %}\n{% exten"
},
{
"path": "instock/web/templates/layout/indicators-main.html",
"chars": 642,
"preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\" />\n\t\t<meta charset=\"utf-8"
},
{
"path": "instock/web/templates/layout/indicators.html",
"chars": 73,
"preview": "{% extends \"../common/meta.html\" %}\n\n{% extends \"indicators-main.html\" %}"
},
{
"path": "instock/web/templates/layout/main.html",
"chars": 900,
"preview": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\" />\n\t\t<meta charset=\"utf-8"
},
{
"path": "instock/web/templates/stock_indicators.html",
"chars": 990,
"preview": "{% extends \"layout/indicators.html\" %}\n{% block main_content %}\n<script type=\"text/javascript\" src=\"/static/js/bokeh-3.8"
},
{
"path": "instock/web/templates/stock_web.html",
"chars": 10126,
"preview": "{% extends \"layout/default.html\" %}\n\n{% block main_content %}\n<link rel=\"stylesheet\" href=\"/static/css/bootstrap-datepic"
},
{
"path": "instock/web/web_service.py",
"chars": 2770,
"preview": "#!/usr/local/bin/python3\n# -*- coding: utf-8 -*-\n\nimport logging\nimport os.path\nimport sys\nfrom abc import ABC\n\nimport t"
},
{
"path": "requirements.txt",
"chars": 307,
"preview": "numpy==2.4.1\npandas==2.3.3\npy_mini_racer==0.6.0\nmini-racer==0.13.2\nTA_Lib==0.6.8\narrow==1.4.0\nbokeh==3.8.1\nPyMySQL==1.1."
},
{
"path": "supervisor/supervisord.conf",
"chars": 1523,
"preview": "[unix_http_server]\nfile=/tmp/supervisor.sock ; the path to the socket file\n\n[inet_http_server] ; inet (TCP) se"
}
]
About this extraction
This page contains the full source code of the myhhub/stock GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 133 files (1.2 MB), approximately 467.1k tokens, and a symbol index with 351 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.