├── .github ├── FUNDING.yml └── workflows │ ├── docker-publish.yml │ ├── pythonapp.yml │ ├── pythonpackage.yml │ ├── qabase_docker.yml │ ├── qabook.yml │ ├── qaeventmq_docker.yml │ └── qajupyter_docker.yml ├── .gitignore ├── .pylintrc ├── .style.yapf ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── QUANTAXIS ├── QAAnalysis │ ├── QAAnalysis_block.py │ ├── QAAnalysis_signal.py │ └── __init__.py ├── QACmd │ └── __init__.py ├── QAData │ ├── QABlockStruct.py │ ├── QADataStruct.py │ ├── QAFeatureStruct.py │ ├── QAFinancialStruct.py │ ├── QAIndicatorStruct.py │ ├── QASeriesStruct.py │ ├── __init__.py │ ├── base_datastruct.py │ ├── data_fq.py │ ├── data_marketvalue.py │ ├── data_resample.py │ ├── dsmethods.py │ ├── financial_mean.py │ ├── level2.py │ ├── paneldatastruct.py │ └── readme.md ├── QAEngine │ ├── QAAsyncSchedule.py │ ├── QAAsyncTask.py │ ├── QAAsyncThread.py │ ├── QAEvent.py │ ├── QATask.py │ ├── QAThreadEngine.py │ ├── __init__.py │ └── readme.md ├── QAFactor │ ├── __init__.py │ ├── feature.py │ ├── featureAnalysis.py │ ├── featureView.py │ ├── featurebacktest.py │ ├── featurepool.py │ └── readme.md ├── QAFetch │ ├── Fetcher.py │ ├── QABitfinex.py │ ├── QABitmex.py │ ├── QAClickhouse.py │ ├── QACrawler.py │ ├── QAEastMoney.py │ ├── QAHexun.py │ ├── QAJQdata.py │ ├── QAKQ.py │ ├── QAOKEx.py │ ├── QAQAWEB.py │ ├── QAQuery.py │ ├── QAQuery_Advance.py │ ├── QAQuery_Async.py │ ├── QATdx.py │ ├── QATdx_adv.py │ ├── QAThs.py │ ├── QATushare.py │ ├── QAbinance.py │ ├── QAdata.py │ ├── QAfinancial.py │ ├── QAhuobi.py │ ├── QAhuobi_realtime.py │ ├── __init__.py │ └── base.py ├── QAIndicator │ ├── __init__.py │ ├── base.py │ ├── hurst.py │ ├── indicators.py │ ├── talib_indicators.py │ ├── talib_numpy.py │ └── talib_series.py ├── QAMarket │ ├── QAOrder.py │ ├── QAPosition.py │ └── market_preset.py ├── QAPubSub │ ├── __init__.py │ ├── base.py │ ├── consumer.py │ ├── debugtoool.py │ ├── declaters.py │ ├── producer.py │ └── setting.py ├── QASU │ ├── __init__.py │ ├── main.py │ ├── save_account.py │ ├── save_backtest.py │ ├── save_binance.py │ ├── save_bitfinex.py │ ├── save_bitmex.py │ ├── save_financialfiles.py │ ├── save_gm.py │ ├── save_huobi.py │ ├── save_jq.py │ ├── save_okex.py │ ├── save_orderhandler.py │ ├── save_position.py │ ├── save_strategy.py │ ├── save_tdx.py │ ├── save_tdx_file.py │ ├── save_tdx_parallelism.py │ ├── save_tushare.py │ ├── save_tusharepro_pg.py │ ├── test_save_strategy.py │ ├── trans_gm.py │ ├── trans_ss.py │ └── user.py ├── QASchedule │ ├── __init__.py │ └── schedulefunc.py ├── QASetting │ ├── QALocalize.py │ ├── __init__.py │ ├── cache.py │ └── executor.py ├── QAStrategy │ ├── __init__.py │ ├── qactabase.py │ ├── qafactorbase.py │ ├── qahedgebase.py │ ├── qamultibase.py │ ├── syncoms.py │ └── util.py ├── QAUtil │ ├── Parallelism.py │ ├── QAAuth.py │ ├── QABar.py │ ├── QACache.py │ ├── QACfg.py │ ├── QACode.py │ ├── QACsv.py │ ├── QADate.py │ ├── QADateTools.py │ ├── QADate_Adv.py │ ├── QADate_trade.py │ ├── QADict.py │ ├── QAError.py │ ├── QAFile.py │ ├── QAList.py │ ├── QALogs.py │ ├── QAMail.py │ ├── QAMongo.py │ ├── QAParameter.py │ ├── QAParameter.pyx │ ├── QAPlot.py │ ├── QARandom.py │ ├── QASetting.py │ ├── QASingleton.py │ ├── QASql.py │ ├── QAText.py │ ├── QATransform.py │ ├── QAWebutil.py │ ├── QAcrypto.py │ ├── __init__.py │ └── host.py ├── QAWebServer │ ├── __init__.py │ ├── basehandles.py │ ├── commandhandler.py │ ├── qifiserver.py │ ├── schedulehandler.py │ ├── server.py │ └── util.py ├── QIFI │ ├── QifiAccount.py │ ├── QifiManager.py │ ├── __init__.py │ ├── qifi.md │ ├── qifi.sql │ └── qifisql.py ├── __init__.py └── __main__.py ├── README.md ├── STU ├── P0_Head.md ├── P1_Prepare.md ├── P2_DataFlow.md ├── P3_Backtest.md ├── P4_Analysis.md ├── P5_REALTIME.md ├── P6_Thought.md └── views01.md ├── _config.yml ├── config ├── QA.sh ├── QA0.txt ├── QA1.txt ├── QA2.txt ├── QA3.txt ├── data_init.py ├── install_docker.sh ├── install_rust.sh ├── readme.md ├── run_backend.sh ├── startjupyter.sh ├── ubuntu16.sh ├── update_all.py ├── update_data.py ├── update_fin.py ├── update_future.py ├── update_x.py └── windows_autojob_updatedata.md ├── dev └── QACache │ └── __init__.py ├── docker ├── ctpbee-base │ └── Dockerfile ├── just_database.yaml ├── k8s_deploy_qaservice │ ├── docker-compose.yaml │ ├── helm_charts │ │ ├── Chart.yaml │ │ ├── README.md │ │ └── templates │ │ │ ├── mgdb-deployment.yaml │ │ │ ├── mgdb-service.yaml │ │ │ ├── qa-deployment.yaml │ │ │ ├── qa-service.yaml │ │ │ ├── qacode-persistentvolumeclaim.yaml │ │ │ ├── qaeventmq-deployment.yaml │ │ │ ├── qaeventmq-service.yaml │ │ │ ├── qamarketcollector-deployment.yaml │ │ │ ├── qamarketcollector-service.yaml │ │ │ ├── qamg-persistentvolumeclaim.yaml │ │ │ ├── qamonitor-deployment.yaml │ │ │ ├── qamonitor-service.yaml │ │ │ ├── qaweb-run-deployment.yaml │ │ │ └── qaweb-run-service.yaml │ └── replicate_3nodes │ │ ├── mgdb-replicationcontroller.yaml │ │ ├── mgdb-service.yaml │ │ ├── qa-replicationcontroller.yaml │ │ ├── qa-service.yaml │ │ ├── qacode-persistentvolumeclaim.yaml │ │ ├── qaeventmq-replicationcontroller.yaml │ │ ├── qaeventmq-service.yaml │ │ ├── qamarketcollector-replicationcontroller.yaml │ │ ├── qamarketcollector-service.yaml │ │ ├── qamg-persistentvolumeclaim.yaml │ │ ├── qamonitor-replicationcontroller.yaml │ │ ├── qamonitor-service.yaml │ │ ├── qaweb-run-replicationcontroller.yaml │ │ └── qaweb-run-service.yaml ├── kite │ ├── qa-base_rust2 │ │ ├── Dockerfile │ │ ├── kitesetup.exp │ │ ├── pip.conf │ │ ├── qa-base_rust2.md │ │ ├── requirements.txt │ │ └── source.list │ ├── qa-community-rust2 │ │ ├── Dockerfile │ │ ├── config │ │ ├── daily_update │ │ ├── qa-community-rust2.md │ │ ├── run-community.sh │ │ ├── runcelery.sh │ │ ├── update_all.py │ │ ├── update_future.py │ │ └── wait_for_it.sh │ ├── qa-jupyter_rust2 │ │ ├── Dockerfile │ │ ├── entrypoint.sh │ │ ├── jupyter_notebook_config.py │ │ ├── jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl │ │ ├── qa-jupyter_rust2.md │ │ ├── requirements.txt │ │ ├── runpy.sh │ │ └── wait_for_it.sh │ └── qa-web-rust2 │ │ ├── Dockerfile │ │ ├── config │ │ ├── daily_update │ │ ├── qa-web-rust2.md │ │ ├── run-community.sh │ │ ├── runcelery.sh │ │ ├── update_all.py │ │ ├── update_future.py │ │ └── wait_for_it.sh ├── qa-base-gitee │ ├── Dockerfile │ ├── config.ini │ ├── pip.conf │ ├── requirements.txt │ └── source.list ├── qa-base │ ├── Dockerfile │ ├── pip.conf │ ├── requirements.txt │ └── source.list ├── qa-community-gpu │ ├── Dockerfile │ ├── readme.txt │ └── setup.sh ├── qa-community-rust │ ├── Dockerfile │ ├── VUWHL │ │ ├── pytdx-1.72r2-py3-none-any.whl │ │ └── quantaxis-1.10.19r1-py3-none-any.whl │ ├── config │ ├── daily_update │ ├── entrypoint.sh │ ├── run-community.sh │ ├── runcelery.sh │ ├── update_all.py │ └── wait_for_it.sh ├── qa-eventmq │ └── Dockerfile ├── qa-jupyter-go-r │ ├── Dockerfile │ ├── entrypoint.sh │ ├── jupyter_notebook_config.py │ ├── pip.conf │ ├── requirements.txt │ ├── runpy.sh │ ├── source.list │ └── wait_for_it.sh ├── qa-jupyter │ ├── Dockerfile │ ├── entrypoint.sh │ ├── jupyter_notebook_config.py │ ├── requirements.txt │ ├── runpy.sh │ └── wait_for_it.sh ├── qa-justdev │ └── docker-compose.yaml ├── qa-monitor │ ├── Dockerfile │ └── glances.conf ├── qa-redis │ └── Dockerfile ├── qa-rust-base │ └── Dockerfile ├── qa-service-future │ ├── docker-compose.yaml │ ├── docker-compose3.yaml │ └── env.env ├── qa-service-pro │ ├── docker-compose.yaml │ ├── docker-compose3.yaml │ └── env.env ├── qa-service-rust │ ├── docker-compose.yaml │ ├── env.env │ ├── start.bat │ └── wait_for_it.sh ├── qa-service │ ├── docker-compose.yaml │ ├── docker-compose3.yaml │ ├── env.env │ ├── start.bat │ └── wait_for_it.sh ├── qa-web │ ├── Dockerfile │ └── entrypoint.sh ├── qaclickhouse │ └── Dockerfile ├── qaservice_docker.sh ├── qavscode │ ├── Dockerfile │ ├── latest.package.json │ └── next.package.json └── readme.md ├── examples ├── factoranalysis.py ├── featureanalysis.ipynb ├── qifiaccountexample.py ├── scheduleserver.py └── test_ckread_qifi.py ├── install_afterrequirements.txt ├── qabook ├── qalogo.png └── quantaxis.tex ├── qalogo.png ├── qapro-rs ├── Cargo.lock ├── Cargo.toml ├── database.yaml ├── example.toml ├── examples │ ├── api.rs │ ├── backtest.rs │ ├── factorlib.rs │ ├── factorplayground.rs │ ├── getdata.rs │ ├── getdataadv.rs │ ├── makeqfq.rs │ ├── qafactor.rs │ └── wsserver.rs ├── readme.md ├── rustfmt.toml └── src │ ├── lib.rs │ ├── main.rs │ ├── parsers │ ├── engine.rs │ ├── lang.rs │ ├── mod.rs │ ├── models.rs │ ├── parser │ │ ├── clauses.rs │ │ ├── elements.rs │ │ ├── expressions.rs │ │ ├── func.rs │ │ ├── keywords.rs │ │ ├── math.rs │ │ ├── mod.rs │ │ ├── select_statement.rs │ │ └── values.rs │ ├── planner │ │ ├── drain.rs │ │ ├── eval.rs │ │ ├── filter.rs │ │ ├── logical_plan.rs │ │ ├── mod.rs │ │ └── project.rs │ ├── pqlir_parser.rs │ ├── sql │ │ ├── env.rs │ │ ├── eval.rs │ │ ├── expr.rs │ │ ├── field.rs │ │ ├── func.rs │ │ ├── mod.rs │ │ ├── selector.rs │ │ ├── sql.rs │ │ ├── utils.rs │ │ └── where_cond.rs │ ├── utils │ │ └── mod.rs │ └── value │ │ ├── json_value.rs │ │ ├── mod.rs │ │ ├── pql_value.rs │ │ ├── pql_vector.rs │ │ ├── table.rs │ │ └── toml_value.rs │ ├── qaaccount │ ├── account.rs │ ├── marketpreset.rs │ ├── mod.rs │ ├── order.rs │ ├── position.rs │ └── transaction.rs │ ├── qaconnector │ ├── clickhouse │ │ ├── ckclient.rs │ │ └── mod.rs │ ├── mod.rs │ ├── mongo │ │ ├── mod.rs │ │ └── mongoclient.rs │ ├── parquet │ │ ├── mod.rs │ │ └── parquetclient.rs │ ├── rabbitmq │ │ ├── mod.rs │ │ └── rmqclient.rs │ └── redis │ │ ├── mod.rs │ │ └── redisclient.rs │ ├── qadata │ ├── arrowbase.rs │ ├── datafunc.rs │ ├── mod.rs │ └── resample.rs │ ├── qadatastruct │ ├── factorstruct.rs │ ├── futureday.rs │ ├── futuremin.rs │ ├── mod.rs │ ├── stockadj.rs │ ├── stockblock.rs │ ├── stockday.rs │ ├── stockl1snapshot.rs │ ├── stockl2snapshot.rs │ ├── stocklist.rs │ └── stockmin.rs │ ├── qaenv │ ├── localenv.rs │ └── mod.rs │ ├── qaexec │ ├── mod.rs │ ├── qacron │ │ └── mod.rs │ ├── qadag │ │ └── mod.rs │ └── qaschedule │ │ └── mod.rs │ ├── qafactor │ ├── factorbacktest.rs │ └── mod.rs │ ├── qafuncs │ ├── mod.rs │ ├── qafactor │ │ ├── hzfactor.rs │ │ └── mod.rs │ └── qaindicator │ │ └── mod.rs │ ├── qahandlers │ ├── factorhandler.rs │ ├── mod.rs │ ├── realtime.rs │ ├── state.rs │ ├── subunsub.rs │ ├── websocket.rs │ └── wshandle.rs │ ├── qalog │ ├── log4.rs │ └── mod.rs │ ├── qamacros │ ├── macros.rs │ └── mod.rs │ ├── qamarket │ ├── mod.rs │ ├── qahexos │ │ ├── mod.rs │ │ └── readme.md │ ├── qaoms │ │ └── mod.rs │ ├── qareal │ │ ├── ctptrader.rs │ │ ├── mod.rs │ │ ├── qifitrader.rs │ │ ├── qmttrader.rs │ │ └── xtptrader.rs │ └── qasim │ │ └── mod.rs │ ├── qaportfolio │ └── lib.rs │ ├── qapraser.rs │ ├── qaprotocol │ ├── mifi │ │ ├── market.rs │ │ ├── mifibase.rs │ │ ├── mod.rs │ │ └── qafastkline.rs │ ├── mod.rs │ └── qifi │ │ ├── account.rs │ │ ├── data.rs │ │ ├── default.rs │ │ ├── func.rs │ │ └── mod.rs │ ├── qapubsub │ ├── instruct_mq.rs │ ├── market_mq.rs │ └── mod.rs │ ├── qarisk │ └── riskmodes │ │ ├── blacklitterman.rs │ │ ├── cov.rs │ │ ├── mod.rs │ │ ├── mvo.rs │ │ └── shrankage.rs │ ├── qaruntime │ ├── base.rs │ ├── mod.rs │ ├── monitor.rs │ ├── qacontext.rs │ └── qamanagers │ │ ├── mod.rs │ │ ├── monitor_manager.rs │ │ └── mq_manager.rs │ ├── qastrategy │ ├── backtest.rs │ ├── mod.rs │ ├── qatemplate.rs │ └── t00.rs │ └── qautil │ ├── mod.rs │ └── tradedate.rs ├── requirements.txt └── setup.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: yutiansut 4 | -------------------------------------------------------------------------------- /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: qa-community-rust-go docker 2 | 3 | on: 4 | push: 5 | # Publish `master` as Docker `latest` image. 6 | branches: 7 | - master 8 | 9 | # Publish `v1.2.3` tags as releases. 10 | tags: 11 | - v* 12 | 13 | # Run tests for any PRs. 14 | pull_request: 15 | 16 | env: 17 | # TODO: Change variable to your image's name. 18 | IMAGE_NAME: qa-community-rust-go 19 | 20 | jobs: 21 | 22 | # Push image to GitHub Packages. 23 | # See also https://docs.docker.com/docker-hub/builds/ 24 | push: 25 | # Ensure test job passes before pushing image. 26 | 27 | 28 | runs-on: ubuntu-latest 29 | if: github.event_name == 'push' 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - name: Build image 35 | run: cd docker/qa-community-rust/ && docker build . --file Dockerfile --tag $IMAGE_NAME 36 | 37 | - name: Log into registry 38 | run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin 39 | 40 | - name: Push image 41 | run: | 42 | IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME 43 | 44 | # Change all uppercase to lowercase 45 | IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') 46 | 47 | # Strip git ref prefix from version 48 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 49 | 50 | # Strip "v" prefix from tag name 51 | [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') 52 | 53 | # Use Docker `latest` tag convention 54 | [ "$VERSION" == "master" ] && VERSION=latest 55 | 56 | echo IMAGE_ID=$IMAGE_ID 57 | echo VERSION=$VERSION 58 | 59 | docker tag $IMAGE_NAME $IMAGE_ID:$VERSION 60 | docker push $IMAGE_ID:$VERSION 61 | -------------------------------------------------------------------------------- /.github/workflows/pythonapp.yml: -------------------------------------------------------------------------------- 1 | name: Python application 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Set up Python 3.8 13 | uses: actions/setup-python@v2 14 | with: 15 | python-version: 3.8 16 | - name: Install dependencies 17 | run: | 18 | python -m pip install --upgrade pip flake8 19 | pip install quantaxis -U 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/pythonpackage.yml: -------------------------------------------------------------------------------- 1 | name: Python package 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | strategy: 10 | max-parallel: 4 11 | matrix: 12 | python-version: [ 3.7, 3.8] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Set up Python ${{ matrix.python-version }} 17 | uses: actions/setup-python@v1 18 | with: 19 | python-version: ${{ matrix.python-version }} 20 | - name: Install dependencies 21 | run: | 22 | python -m pip install --upgrade pip 23 | pip install -r requirements.txt 24 | pip install quantaxis 25 | 26 | -------------------------------------------------------------------------------- /.github/workflows/qabase_docker.yml: -------------------------------------------------------------------------------- 1 | name: qabase docker 2 | 3 | on: 4 | push: 5 | # Publish `master` as Docker `latest` image. 6 | branches: 7 | - master 8 | 9 | # Publish `v1.2.3` tags as releases. 10 | tags: 11 | - v* 12 | 13 | # Run tests for any PRs. 14 | pull_request: 15 | 16 | env: 17 | # TODO: Change variable to your image's name. 18 | IMAGE_NAME: qabase 19 | 20 | jobs: 21 | 22 | # Push image to GitHub Packages. 23 | # See also https://docs.docker.com/docker-hub/builds/ 24 | push: 25 | # Ensure test job passes before pushing image. 26 | 27 | 28 | runs-on: ubuntu-latest 29 | if: github.event_name == 'push' 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - name: Build image 35 | run: cd docker/qa-base/ && docker build . --file Dockerfile --tag $IMAGE_NAME 36 | 37 | - name: Log into registry 38 | run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin 39 | 40 | - name: Push image 41 | run: | 42 | IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME 43 | 44 | # Change all uppercase to lowercase 45 | IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') 46 | 47 | # Strip git ref prefix from version 48 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 49 | 50 | # Strip "v" prefix from tag name 51 | [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') 52 | 53 | # Use Docker `latest` tag convention 54 | [ "$VERSION" == "master" ] && VERSION=latest 55 | 56 | echo IMAGE_ID=$IMAGE_ID 57 | echo VERSION=$VERSION 58 | 59 | docker tag $IMAGE_NAME $IMAGE_ID:$VERSION 60 | docker push $IMAGE_ID:$VERSION 61 | -------------------------------------------------------------------------------- /.github/workflows/qabook.yml: -------------------------------------------------------------------------------- 1 | name: Build LaTeX document 2 | on: 3 | push: 4 | branches: 5 | - "master" 6 | jobs: 7 | build_latex: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Set up Git repository 11 | uses: actions/checkout@v2 12 | - name: Compile Portfolio+ document 13 | uses: xu-cheng/latex-action@v2 14 | with: 15 | root_file: qabook/quantaxis.tex 16 | latexmk_use_xelatex: true 17 | 18 | - uses: "marvinpinto/action-automatic-releases@latest" 19 | with: 20 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 21 | automatic_release_tag: "latest" 22 | prerelease: true 23 | title: "QUANTAXIS BooK" 24 | files: 25 | quantaxis.pdf 26 | -------------------------------------------------------------------------------- /.github/workflows/qaeventmq_docker.yml: -------------------------------------------------------------------------------- 1 | name: qaeventmq docker 2 | 3 | on: 4 | push: 5 | # Publish `master` as Docker `latest` image. 6 | branches: 7 | - master 8 | 9 | # Publish `v1.2.3` tags as releases. 10 | tags: 11 | - v* 12 | 13 | # Run tests for any PRs. 14 | pull_request: 15 | 16 | env: 17 | # TODO: Change variable to your image's name. 18 | IMAGE_NAME: qaeventmq 19 | 20 | jobs: 21 | 22 | # Push image to GitHub Packages. 23 | # See also https://docs.docker.com/docker-hub/builds/ 24 | push: 25 | # Ensure test job passes before pushing image. 26 | 27 | 28 | runs-on: ubuntu-latest 29 | if: github.event_name == 'push' 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - name: Build image 35 | run: cd docker/qa-eventmq/ && docker build . --file Dockerfile --tag $IMAGE_NAME 36 | 37 | - name: Log into registry 38 | run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin 39 | 40 | - name: Push image 41 | run: | 42 | IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME 43 | 44 | # Change all uppercase to lowercase 45 | IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') 46 | 47 | # Strip git ref prefix from version 48 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 49 | 50 | # Strip "v" prefix from tag name 51 | [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') 52 | 53 | # Use Docker `latest` tag convention 54 | [ "$VERSION" == "master" ] && VERSION=latest 55 | 56 | echo IMAGE_ID=$IMAGE_ID 57 | echo VERSION=$VERSION 58 | 59 | docker tag $IMAGE_NAME $IMAGE_ID:$VERSION 60 | docker push $IMAGE_ID:$VERSION 61 | -------------------------------------------------------------------------------- /.github/workflows/qajupyter_docker.yml: -------------------------------------------------------------------------------- 1 | name: qa-jupyer docker 2 | 3 | on: 4 | push: 5 | # Publish `master` as Docker `latest` image. 6 | branches: 7 | - master 8 | 9 | # Publish `v1.2.3` tags as releases. 10 | tags: 11 | - v* 12 | 13 | # Run tests for any PRs. 14 | pull_request: 15 | 16 | env: 17 | # TODO: Change variable to your image's name. 18 | IMAGE_NAME: qa-jupyer 19 | 20 | jobs: 21 | 22 | # Push image to GitHub Packages. 23 | # See also https://docs.docker.com/docker-hub/builds/ 24 | push: 25 | # Ensure test job passes before pushing image. 26 | 27 | 28 | runs-on: ubuntu-latest 29 | if: github.event_name == 'push' 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - name: Build image 35 | run: cd docker/qa-jupyter/ && docker build . --file Dockerfile --tag $IMAGE_NAME 36 | 37 | - name: Log into registry 38 | run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin 39 | 40 | - name: Push image 41 | run: | 42 | IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME 43 | 44 | # Change all uppercase to lowercase 45 | IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') 46 | 47 | # Strip git ref prefix from version 48 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 49 | 50 | # Strip "v" prefix from tag name 51 | [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') 52 | 53 | # Use Docker `latest` tag convention 54 | [ "$VERSION" == "master" ] && VERSION=latest 55 | 56 | echo IMAGE_ID=$IMAGE_ID 57 | echo VERSION=$VERSION 58 | 59 | docker tag $IMAGE_NAME $IMAGE_ID:$VERSION 60 | docker push $IMAGE_ID:$VERSION 61 | -------------------------------------------------------------------------------- /.style.yapf: -------------------------------------------------------------------------------- 1 | [style] 2 | based_on_style = google 3 | spaces_before_comment = 2, 4 4 | SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED = true 5 | SPLIT_ALL_COMMA_SEPARATED_VALUES = true 6 | SPLIT_BEFORE_BITWISE_OPERATOR = true 7 | SPLIT_BEFORE_CLOSING_BRACKET = true 8 | SPLIT_BEFORE_DICT_SET_GENERATOR = true 9 | SPLIT_BEFORE_DOT = true 10 | SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN = true 11 | SPLIT_BEFORE_FIRST_ARGUMENT = true 12 | SPLIT_BEFORE_LOGICAL_OPERATOR = true 13 | SPLIT_BEFORE_NAMED_ASSIGNS = true 14 | SPLIT_COMPLEX_COMPREHENSION = true 15 | DEDENT_CLOSING_BRACKETS = true 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # QUANTAXIS 捐赠列表 2 | 3 | 写代码不易...请作者喝杯咖啡呗? 4 | 5 | 6 | ![](http://picx.gulizhu.com/alipay.png) 7 | 8 | (PS: 支付的时候 请带上你的名字/昵称呀 会维护一个赞助列表~ ) 9 | 10 | ======================= 11 | 12 | - 2017-9-25 沈乐 13 | - 2017-9-25 许海涵 14 | - 2017-9-27 吕少麟 15 | - 2017-9-27 doskoi 16 | - 2017-10-1 zz 17 | - 2017-10-4 Hakase 18 | - 2017-10-4 头上无毛 19 | - 2017-10-5 庆斌 20 | - 2017-10-09 成成 21 | - 2017-10-09 Rainx 徐景 22 | - 2017-10-09 Dice(steven) 23 | - 2017-10-12 沈乐 24 | - 2017-10-12 空空子 25 | - 2017-10-12 宇清 26 | - 2017-10-13 昊 27 | - 2017-10-13 恒光 28 | - 2017-10-30 Ims 黎明 29 | - 2017-11-16 威 30 | - 2017-11-26 SunnyBoy00 31 | - 2017-12-05 威 32 | - 2017-12-06 PdlMojoMoo 33 | - 2017-12-07 威 34 | - 2017-12-19 在云端 35 | - 2017-12-21 双宏 36 | - 2017-12-28 在云端 37 | - 2018-02-03 *明龙 38 | - 2018-04-08 *轶 39 | - 2018-04-10 *林 40 | - 2018-04-10 *荣霖(东北必胜) 41 | - 2018-04-11 *冠 42 | - 2018-04-30 *冠 43 | - 2018-05-04 *文(lid) 44 | - 2018-05-17 申长春 45 | - 2018-06-06 stephen 46 | - 2018-07-13 W *薇 47 | - 2018-07-13 *吉 48 | - 2018-07-14 *剑 49 | - 2018-07-14 叶鸿浩 50 | - 2018-07-16 牧童 51 | - 2018-07-17 lun 52 | - 2018-08-28 Hakase 53 | - 2018-09-04 宇清 54 | - 2018-09-05 *琛 55 | - 2018-09-11 *建明 56 | - 2018-09-21 毛毛 57 | - 2018-09-25 润之大佬 58 | - 2018-10-16 *群 59 | - 2018-12-25 *宁(解语问股) 60 | - 2019-01-09 张杰(哲人石) 61 | - 2019-01-10 hakase 62 | - 2019-01-13 jason(*杰鑫) 63 | - 2019-01-27 *冰 64 | - 2019-02-21 *文星 65 | - 2019-03-24 *百强 66 | - 2019-03-29 *振忠 67 | - 2019-04-09 *彬 68 | - 2019-04-29 *五洲 69 | - 2019-05-14 *长春 70 | - 2019-05-16 *长春 71 | - 2019-07-23 *五洲 72 | - 2019-08-08 *博思 73 | 74 | 75 | 感谢@尧 zhongjy1992@outlook.com 对于1.0.32版本做出的巨大贡献 76 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "qapro-rs"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2021 yutiansut/QUANTAXIS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # QUANTAXIS PR 😇 2 | 3 | 感谢您对于QUANTAXIS的项目的参与~ 🛠请在此完善一下最后的信息~ 4 | 5 | ## 注意 6 | 7 | - 如果非第一次fork, 请先将quantaxis 库的内容PR进您的项目进行更新, 然后再执行对于quantaxis的pr 8 | - 请完善[CHANGELOG](https://github.com/QUANTAXIS/QUANTAXIS/releases)再进行PR 9 | 10 | ## PR前必看 11 | 12 | 请使用如下代码对要PR的代码进行格式化: 13 | 14 | 使用以下代码来格式化 15 | ``` 16 | pip install https://github.com/google/yapf/archive/master.zip 17 | yapf -i --style .style.yapf 18 | ``` 19 | 20 | ## 🛠该PR主要解决的问题🛠: 21 | 22 | 23 | 24 | 作者信息: 25 | 时间: 26 | -------------------------------------------------------------------------------- /QUANTAXIS/QAAnalysis/__init__.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | 26 | from QUANTAXIS.QAAnalysis.QAAnalysis_block import * 27 | -------------------------------------------------------------------------------- /QUANTAXIS/QAData/QAFeatureStruct.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/QUANTAXIS/QAData/QAFeatureStruct.py -------------------------------------------------------------------------------- /QUANTAXIS/QAData/QAFinancialStruct.py: -------------------------------------------------------------------------------- 1 | # coding :utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | """ 25 | 财务指标结构 26 | 27 | """ 28 | import pandas as pd 29 | 30 | from QUANTAXIS.QAData.financial_mean import financial_dict 31 | 32 | 33 | class QA_DataStruct_Financial(): 34 | 35 | def __init__(self, data): 36 | self.data = data 37 | # keys for CN, values for EN 38 | self.colunms_en = list(financial_dict.values()) 39 | self.colunms_cn = list(financial_dict.keys()) 40 | 41 | def __repr__(self): 42 | return '< QA_DataStruct_Financial >' 43 | 44 | def get_report_by_date(self, code, date): 45 | return self.data.loc[pd.Timestamp(date), code] 46 | 47 | def get_key(self, code, reportdate, key): 48 | if isinstance(reportdate, list): 49 | return self.data.loc[( 50 | slice( 51 | pd.Timestamp(reportdate[0]), 52 | pd.Timestamp(reportdate[-1]) 53 | ), 54 | code 55 | ), 56 | key] 57 | else: 58 | return self.data.loc[(pd.Timestamp(reportdate), code), key] 59 | -------------------------------------------------------------------------------- /QUANTAXIS/QAData/paneldatastruct.py: -------------------------------------------------------------------------------- 1 | from clickhouse_driver.util.helpers import column_chunks 2 | import numpy as np 3 | import pandas as pd 4 | from dateutil import parser 5 | 6 | 7 | class QAPanelDataStruct(): 8 | 9 | """ 10 | paneldata 11 | 12 | """ 13 | def __init__(self, data, dtype) -> None: 14 | self.data = data 15 | self.type = dtype 16 | 17 | def get_loc(self, codelist, start, end): 18 | if 'min' in self.type: 19 | start = parser.parse(start) 20 | end = parser.parse(end) 21 | elif 'day' in self.type: 22 | start = parser.parse(start).date() 23 | end = parser.parse(end).date() 24 | 25 | return self.data.loc[slice(start, end), codelist] 26 | 27 | def get_date(self, codelist, date): 28 | if 'min' in self.type: 29 | date = parser.parse(date) 30 | elif 'day' in self.type: 31 | date = parser.parse(date).date() 32 | 33 | return self.data.loc[date, codelist] 34 | -------------------------------------------------------------------------------- /QUANTAXIS/QAData/readme.md: -------------------------------------------------------------------------------- 1 | # QA_DataStruct 2 | 3 | 4 | DataStruct具有的功能: 5 | 6 | - 数据容器 7 | - 数据变换 [分拆/合并/倒序] split/merge/reverse 8 | - 数据透视 pivot 9 | - 数据筛选 select_time/select_time_with_gap/select_code/get_bar 10 | - 数据复权 to_qfq/to_hfq 11 | - 数据显示 show 12 | - 格式变换 to_json/to_pandas/to_list/to_numpy 13 | - 数据库式查询 query 14 | - 画图 plot -------------------------------------------------------------------------------- /QUANTAXIS/QAEngine/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | 25 | from QUANTAXIS.QAEngine.QAEvent import QA_Event, QA_Worker 26 | from QUANTAXIS.QAEngine.QATask import QA_Task 27 | from QUANTAXIS.QAEngine.QAThreadEngine import QA_Thread, QA_Engine 28 | from QUANTAXIS.QAEngine.QAAsyncThread import QA_AsyncThread, QA_AsyncQueue 29 | from QUANTAXIS.QAEngine.QAAsyncTask import QA_AsyncTask 30 | from QUANTAXIS.QAEngine.QAAsyncSchedule import QA_AsyncScheduler, create_QAAsyncScheduler -------------------------------------------------------------------------------- /QUANTAXIS/QAEngine/readme.md: -------------------------------------------------------------------------------- 1 | # QUANTAXIS_ENGINE 2 | 3 | 4 | QUANTAXIS ENGINE 由三个部分组成: 5 | 6 | ``` 7 | QA_Worker/QAEvent 8 | 9 | QA_Task 10 | 11 | QA_Thread / QA_Engine 12 | ``` 13 | 14 | QA_Worker是做事情的主体,主体根据相应的事件(QA_Event),在实际的应用中,QA_Worker 是需要被继承,并修改run()方法的 15 | 16 | QA_Task是主体在某一个时间点做的事件,他被放置于QA_Engine/QA_Thread的事件队列中 17 | 18 | QA_Thread是一个可以快速创建的事件线程,通过向QA_Thread的事件队列推送事件,QA_Thread会完成推送的任务 19 | 20 | QA_Engine是用于管理/创建多个QA_Thread的管理器 -------------------------------------------------------------------------------- /QUANTAXIS/QAFactor/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 因子研究的基础 3 | 4 | 5 | - 数据清洗 6 | 7 | - 因子研究的env_panel 8 | 9 | - 因子标准化数据的存储和读取 10 | 11 | - 因子 12 | 13 | 14 | """ 15 | 16 | from QUANTAXIS.QAFactor.feature import QASingleFactor_DailyBase 17 | from QUANTAXIS.QAFactor.featurepool import MA10 18 | from QUANTAXIS.QAFactor.featureView import QAFeatureView 19 | from QUANTAXIS.QAFactor.featureAnalysis import QAFeatureAnalysis 20 | from QUANTAXIS.QAFactor.featurebacktest import QAFeatureBacktest -------------------------------------------------------------------------------- /QUANTAXIS/QAFactor/featureView.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | import clickhouse_driver 4 | import pandas as pd 5 | from qaenv import (clickhouse_ip, clickhouse_password, clickhouse_port, 6 | clickhouse_user) 7 | 8 | 9 | class QAFeatureView(): 10 | def __init__(self, host=clickhouse_ip, port=clickhouse_port, user=clickhouse_user, password=clickhouse_password) -> None: 11 | self.client = clickhouse_driver.Client(host=host, port=port, user=user, password=password, 12 | database='factor') 13 | 14 | def get_all_factorname(self): 15 | data = self.client.query_dataframe( 16 | 'select factorname from factormetadata').drop_duplicates().factorname.tolist() 17 | return data 18 | 19 | def get_all_tables(self): 20 | return self.client.query_dataframe('show tables').drop_duplicates() 21 | 22 | def get_single_factor(self, factorname, start=None, end=None): 23 | print(factorname) 24 | if start is None and end is None: 25 | res = self.client.query_dataframe( 26 | 'select * from {}'.format(factorname)) 27 | else: 28 | res = self.client.query_dataframe("select * from {} where ((`date` >= '{}')) AND (`date` <= '{}') ".format(factorname, start, end)) 29 | if len(res) > 0: 30 | 31 | res.columns = ['date', 'code', factorname] 32 | res.assign(date=pd.to_datetime(res.date)) 33 | return res.set_index(['date', 'code']).sort_index() 34 | else: 35 | return pd.DataFrame([]) 36 | 37 | def unreg_factor(self, factorname): 38 | self.client.execute( 39 | "ALTER TABLE factormetadata DELETE WHERE factorname='{}'".format(factorname)) 40 | self.client.execute('drop table {}'.format(factorname)) 41 | 42 | def get_all_factor_values(self, factorlist=None, start=None, end=None): 43 | factorlist = self.get_all_factorname() if factorlist is None else factorlist 44 | 45 | res = pd.concat([self.get_single_factor(factor, start, end) 46 | for factor in factorlist], axis=1) 47 | 48 | return res 49 | 50 | 51 | def factor_vif(self): 52 | """ 53 | 因子的 vif 测试 54 | 55 | 56 | 57 | """ 58 | pass 59 | 60 | -------------------------------------------------------------------------------- /QUANTAXIS/QAFactor/featurepool.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from qaenv import (clickhouse_ip, clickhouse_password, clickhouse_port, 3 | clickhouse_user) 4 | from QUANTAXIS.QAFactor.feature import QASingleFactor_DailyBase 5 | from QUANTAXIS.QAFetch.QAClickhouse import QACKClient 6 | from QUANTAXIS.QAIndicator.indicators import QA_indicator_MA 7 | 8 | 9 | class MA10(QASingleFactor_DailyBase): 10 | 11 | def finit(self): 12 | 13 | self.clientr = QACKClient(clickhouse_ip, clickhouse_port, user=clickhouse_user, password=clickhouse_password) 14 | self.factor_name = 'MA10' 15 | 16 | def calc(self) -> pd.DataFrame: 17 | """ 18 | 19 | the example is just a day datasource, u can use the min data to generate a day-frequence factor 20 | 21 | the factor should be in day frequence 22 | """ 23 | 24 | codellist = self.clientr.get_stock_list().order_book_id.tolist() 25 | start = '2020-01-01' 26 | end = '2021-09-22' 27 | data = self.clientr.get_stock_day_qfq_adv(codellist, start, end) 28 | res = data.add_func(QA_indicator_MA, 10) 29 | res.columns = ['factor'] 30 | return res.reset_index().dropna() 31 | -------------------------------------------------------------------------------- /QUANTAXIS/QAFactor/readme.md: -------------------------------------------------------------------------------- 1 | # 关于 QAFactor 2 | 3 | 4 | 1. feature 的定义 5 | 6 | feature 主要是对于行情/另类数据在股票池(全市场/自定义市场)的一个指标计算, 可以作为对于 QAIndicator 模块的衍生和进一步处理, 也可以直接作为因子投资框架下的基础的 feature 控制 7 | 8 | 我们并不直接把因子的研究框架内置在 feature 的定义中, 而是希望可以更多的存储初始状态的计算值, 以方便进行更全面的数据分析和最大程度的原始数据留存 9 | 10 | 11 | 你可以将原始的计算结果方便的保存在 clickhouse 中, 并对于 feature 通过 featureAnalysis 进一步的分析, 如中性化, 标准化等等, 并再次使用此 feature 基类进行存储和二次的读取, 基于 feature 自带的版本控制和 description 描述, 方便的管理因子迭代的过程 12 | 13 | 14 | 2. featureView 一个方便管理全量 feature 的基类 15 | 16 | 基于 featureView 你可以快速的管理多个 feature, 并进行组合和分析, 也可以对于版本进行控制, 支持模糊查询等 17 | 18 | 19 | 3. featureAnalysis 20 | 21 | 在 featureAnalysis 中, 我们可以对于原始 featue 进行进一步的加工和处理, 并可以定义新的 feature 形成一个迭代 22 | 23 | 24 | -------------------------------------------------------------------------------- /QUANTAXIS/QAFetch/QAKQ.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import pandas as pd 4 | 5 | def QA_fetch_get_future_domain(): 6 | """ 7 | 获取快期的主连代码 8 | 9 | return [list] 10 | """ 11 | res = pd.DataFrame(json.loads(requests.get("https://openmd.shinnytech.com/t/md/symbols/latest.json").text)).T 12 | return res.loc[res.ins_name.str.contains('主连')].underlying_symbol.apply(lambda x: x.split('.')[1]).tolist() 13 | 14 | 15 | 16 | 17 | 18 | if __name__ == "__main__": 19 | print(QA_fetch_get_future_domain()) -------------------------------------------------------------------------------- /QUANTAXIS/QAFetch/QAQAWEB.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | 26 | """QUANTAXIS访问获取QAWEB的行情 27 | 28 | 233333 结果变成自己访问自己了 29 | """ 30 | import pandas as pd 31 | from QUANTAXIS.QAUtil.QACode import QA_util_code_tostr 32 | 33 | 34 | def QA_fetch_get_stock_day(code, start, end, ip='192.168.0.1', port='8010'): 35 | pass 36 | # requests.get( 37 | 38 | 39 | def QA_fetch_get_stock_block(): 40 | """ths的版块数据 41 | 42 | Returns: 43 | [type] -- [description] 44 | """ 45 | 46 | url = 'http://data.yutiansut.com/self_block.csv' 47 | try: 48 | bl = pd.read_csv(url) 49 | return bl.assign(code=bl['证券代码'].apply(QA_util_code_tostr), blockname=bl['行业'], name=bl['证券名称'], source='outside', type='outside').set_index('code', drop=False) 50 | except Exception as e: 51 | print(e) 52 | return None 53 | 54 | 55 | if __name__ == "__main__": 56 | print(QA_fetch_get_stock_block()) -------------------------------------------------------------------------------- /QUANTAXIS/QAFetch/QAdata.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/QUANTAXIS/QAFetch/QAdata.py -------------------------------------------------------------------------------- /QUANTAXIS/QAIndicator/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | from QUANTAXIS.QAIndicator.indicators import * 24 | from QUANTAXIS.QAIndicator.base import * 25 | try: 26 | from QUANTAXIS.QAIndicator.talib_series import * 27 | from QUANTAXIS.QAIndicator.talib_numpy import * 28 | from QUANTAXIS.QAIndicator import talib_indicators as talib_qa 29 | except: 30 | print('PLEASE install TALIB to call these methods') 31 | """ 32 | 这个模块是对了对应QA_DataStruct 33 | 34 | 可以被add_func来添加,所以 这个模块的函数必须有一个DataFrame的输入 35 | 36 | 37 | 例如 38 | 39 | import QUANTAXIS as QA 40 | data=QA.QA_fetch_stock_day_adv('000001','2017-01-01','2017-01-31') 41 | data.add_func(QA.) 42 | """ 43 | -------------------------------------------------------------------------------- /QUANTAXIS/QAPubSub/__init__.py: -------------------------------------------------------------------------------- 1 | from QUANTAXIS.QAPubSub.consumer import subscriber,subscriber_topic,subscriber_routing 2 | from QUANTAXIS.QAPubSub.producer import publisher,publisher_topic,publisher_routing 3 | from QUANTAXIS.QAPubSub.base import base_ps 4 | from QUANTAXIS.QAPubSub.debugtoool import debug_sub, debug_pub -------------------------------------------------------------------------------- /QUANTAXIS/QAPubSub/base.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import pika 4 | from QUANTAXIS.QAPubSub.setting import qapubsub_ip, qapubsub_port, qapubsub_user, qapubsub_password 5 | 6 | 7 | class base_ps(): 8 | 9 | def __init__(self, host=qapubsub_ip, port=qapubsub_port, user=qapubsub_user, password=qapubsub_password, channel_number=1, queue_name='', routing_key='default', exchange='', exchange_type='fanout', vhost='/'): 10 | self.host = host 11 | self.port = port 12 | self.user = user 13 | self.password = password 14 | 15 | self.queue_name = queue_name 16 | self.exchange = exchange 17 | self.routing_key = routing_key 18 | self.vhost = vhost 19 | self.exchange_type = exchange_type 20 | self.channel_number = channel_number 21 | # fixed: login with other user, pass failure @zhongjy 22 | self.credentials = pika.PlainCredentials( 23 | self.user, self.password, erase_on_connect=True) 24 | self.connection = pika.BlockingConnection( 25 | pika.ConnectionParameters(host=self.host, port=self.port, virtual_host=self.vhost, 26 | credentials=self.credentials, heartbeat=0, socket_timeout=5, 27 | ) 28 | ) 29 | 30 | self.channel = self.connection.channel( 31 | channel_number=self.channel_number) 32 | 33 | def reconnect(self): 34 | try: 35 | self.connection.close() 36 | except: 37 | pass 38 | 39 | self.connection = pika.BlockingConnection( 40 | pika.ConnectionParameters(host=self.host, port=self.port,credentials=self.credentials, 41 | heartbeat=0, virtual_host=self.vhost, 42 | socket_timeout=5,)) 43 | 44 | self.channel = self.connection.channel( 45 | channel_number=self.channel_number) 46 | return self 47 | 48 | def close(self): 49 | self.connection.close() -------------------------------------------------------------------------------- /QUANTAXIS/QAPubSub/declaters.py: -------------------------------------------------------------------------------- 1 | #app = faust.App('myapp', broker='kafka://localhost') 2 | class QUANTAXIS_PUBSUBER(): 3 | def __init__(self, name, broker='rabbitmq://localhost'): 4 | self.exchange = name 5 | 6 | 7 | #@app.agent(value_type=Order) 8 | 9 | def agent(value_type=order): 10 | pass -------------------------------------------------------------------------------- /QUANTAXIS/QAPubSub/setting.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | qapubsub_ip = os.getenv('QAPUBSUB_IP', 'localhost') 4 | qapubsub_port = os.getenv('QAPUBSUB_PORT', 5672) 5 | qapubsub_user = os.getenv('QAPUBSUB_USER', 'admin') 6 | qapubsub_password = os.getenv('QAPUBSUB_PWD', 'admin') 7 | -------------------------------------------------------------------------------- /QUANTAXIS/QASU/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /QUANTAXIS/QASU/save_position.py: -------------------------------------------------------------------------------- 1 | from pymongo import DESCENDING, ASCENDING 2 | from QUANTAXIS.QAUtil import DATABASE 3 | """对于POSITION的增删改查 4 | """ 5 | 6 | 7 | def save_position(message, collection=DATABASE.positions): 8 | """save account 9 | 10 | Arguments: 11 | message {[type]} -- [description] 12 | 13 | Keyword Arguments: 14 | collection {[type]} -- [description] (default: {DATABASE}) 15 | """ 16 | try: 17 | collection.create_index( 18 | [("account_cookie", ASCENDING), ("portfolio_cookie", ASCENDING), ("user_cookie", ASCENDING), ("position_id", ASCENDING)], unique=True) 19 | except: 20 | pass 21 | collection.update( 22 | {'account_cookie': message['account_cookie'], 'position_id': message['position_id'], 23 | 'portfolio_cookie': message['portfolio_cookie'], 'user_cookie': message['user_cookie']}, 24 | {'$set': message}, 25 | upsert=True 26 | ) 27 | -------------------------------------------------------------------------------- /QUANTAXIS/QASchedule/__init__.py: -------------------------------------------------------------------------------- 1 | ## -------------------------------------------------------------------------------- /QUANTAXIS/QASchedule/schedulefunc.py: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | import os 4 | import toml 5 | def read_config(file): 6 | config = toml.loads(file) 7 | 8 | @read_config 9 | def before_trading(): 10 | pass 11 | 12 | 13 | 14 | @read_config 15 | def on_trading(): 16 | 17 | """ 18 | trading_day 19 | 20 | """ 21 | pass 22 | 23 | @read_config 24 | def after_1530(): 25 | """ 26 | start 15:31 27 | """ 28 | pass 29 | 30 | @read_config 31 | def before_nighttrading(): 32 | 33 | """ 34 | start 8:30 35 | """ 36 | pass 37 | 38 | 39 | @read_config 40 | def before_nighttrading(): 41 | pass 42 | -------------------------------------------------------------------------------- /QUANTAXIS/QASetting/QALocalize.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import os 3 | 4 | """创建本地文件夹 5 | 6 | 7 | 1. setting_path ==> 用于存放配置文件 setting.cfg 8 | 2. cache_path ==> 用于存放临时文件 9 | 3. log_path ==> 用于存放储存的log 10 | 4. download_path ==> 下载的数据/财务文件 11 | 5. strategy_path ==> 存放策略模板 12 | 6. bin_path ==> 存放一些交易的sdk/bin文件等 13 | """ 14 | 15 | 16 | path = os.path.expanduser('~') 17 | qa_path = '{}{}{}'.format(path, os.sep, '.quantaxis') 18 | 19 | 20 | def generate_path(name): 21 | return '{}{}{}'.format(qa_path, os.sep, name) 22 | 23 | 24 | def make_dir(path, exist_ok=True): 25 | os.makedirs(path, exist_ok=exist_ok) 26 | 27 | 28 | setting_path = generate_path('setting') 29 | cache_path = generate_path('cache') 30 | log_path = generate_path('log') 31 | download_path = generate_path('downloads') 32 | strategy_path = generate_path('strategy') 33 | bin_path = generate_path('bin') #给一些dll文件存储用 34 | 35 | 36 | make_dir(qa_path, exist_ok=True) 37 | make_dir(setting_path, exist_ok=True) 38 | make_dir(cache_path, exist_ok=True) 39 | make_dir(download_path, exist_ok=True) 40 | make_dir(log_path, exist_ok=True) 41 | make_dir(strategy_path, exist_ok=True) 42 | make_dir(bin_path, exist_ok=True) 43 | -------------------------------------------------------------------------------- /QUANTAXIS/QASetting/__init__.py: -------------------------------------------------------------------------------- 1 | from QUANTAXIS.QASetting.QALocalize import qa_path, setting_path, cache_path, download_path, log_path -------------------------------------------------------------------------------- /QUANTAXIS/QAStrategy/__init__.py: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | from QUANTAXIS.QAStrategy.util import QA_data_futuremin_resample 4 | from QUANTAXIS.QAStrategy.qactabase import QAStrategyCtaBase 5 | 6 | 7 | """ 8 | QAStrategy 提供了一个示例流程 9 | 包括且不限于 10 | 11 | QACtabase : 单标的研究基类 12 | 13 | QAMultiBase: 多标的多市场的研究基类 14 | 15 | QAHedgeBase: 双标的对冲/套利的研究基类 16 | 17 | QAFactorBase: 因子工厂模式的研究基类 18 | """ 19 | 20 | -------------------------------------------------------------------------------- /QUANTAXIS/QAStrategy/qafactorbase.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/QUANTAXIS/QAStrategy/qafactorbase.py -------------------------------------------------------------------------------- /QUANTAXIS/QAStrategy/qahedgebase.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/QUANTAXIS/QAStrategy/qahedgebase.py -------------------------------------------------------------------------------- /QUANTAXIS/QAStrategy/syncoms.py: -------------------------------------------------------------------------------- 1 | 2 | from QUANTAXIS.QAPubSub.consumer import subscriber_routing 3 | from QUANTAXIS.QAPubSub.producer import publisher_routing 4 | from qaenv import eventmq_ip 5 | import json 6 | 7 | 8 | class QAStrategySyncOrders(): 9 | """ 10 | 订单同步器 11 | 如何挂实盘账户请看 QATrader 12 | http://www.yutiansut.com:3000/topic/5dc865e8c466af76e9e3bdd1 13 | 你可以理解成这是一个流处理的过程 14 | simid 被跟单的策略的id 15 | realid 实盘账户id 16 | realamount 实盘账户的订单数量 17 | """ 18 | 19 | def __init__(self, simid, realid, realamount=1): 20 | self.sub = subscriber_routing( 21 | exchange='QAORDER_ROUTER', host=eventmq_ip, routing_key=simid) 22 | self.pub = publisher_routing( 23 | exchange='QAORDER_ROUTER', host=eventmq_ip, routing_key=realid) 24 | self.realamount = realamount 25 | self.realid = realid 26 | self.simid = simid 27 | 28 | def add_subscriber(self, simid): 29 | self.sub.add_sub('QAORDER_ROUTER', simid) 30 | 31 | def callback(self, a, b, c, data): 32 | d = json.loads(data, encoding='utf-8') 33 | 34 | if d['topic'] == 'send_order': 35 | 36 | self.on_order(d) 37 | 38 | def on_order(self, order): 39 | """在此处理你的订单逻辑 40 | 如果你订阅了多个策略账户 则order['account_cookie']不相同 41 | 42 | Arguments: 43 | order {[type]} -- [description] 44 | """ 45 | self.send_order(order) 46 | 47 | def send_order(self, order): 48 | 49 | order['topic'] = 'sendorder' 50 | order['code'] = order['instrument_id'] 51 | order['account_cookie'] = self.realid 52 | order['user_id'] = self.realid 53 | order['volume'] = self.realamount 54 | order['order_direction'] = order['direction'] 55 | order['order_offset'] = order['offset'] 56 | self.pub.pub(json.dumps(order), routing_key=self.realid) 57 | 58 | def start(self): 59 | self.sub.callback = self.callback 60 | self.sub.start() 61 | -------------------------------------------------------------------------------- /QUANTAXIS/QAStrategy/util.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | def QA_data_futuremin_resample(min_data, type_='5min'): 4 | """期货分钟线采样成大周期 5 | 分钟线采样成子级别的分钟线 6 | future: 7 | vol ==> trade 8 | amount X 9 | """ 10 | 11 | min_data.tradeime = pd.to_datetime(min_data.tradetime) 12 | 13 | CONVERSION = {'code': 'first', 'open': 'first', 'high': 'max', 'low': 'min', 14 | 'close': 'last', 'trade': 'sum', 'tradetime': 'last', 'date': 'last'} 15 | resx = min_data.resample(type_, closed='right', 16 | loffset=type_).apply(CONVERSION) 17 | return resx.dropna().reset_index().set_index(['datetime', 'code']) -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QAAuth.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QACache.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | from time import time 4 | from QUANTAXIS.QAUtil.QASingleton import singleton 5 | 6 | @singleton 7 | class QA_util_cache: 8 | '''简单的缓存系统 9 | 把这个变量保存在内存里, 同时给它一个过期时间, 过期则失效. 10 | ''' 11 | def __init__(self): 12 | '''初始化''' 13 | self.mem = {} 14 | self.time = {} 15 | 16 | def set(self, key, data, age=-1): 17 | '''保存键为key的值,存活时间为age秒''' 18 | self.mem[key] = data 19 | if age == -1: 20 | self.time[key] = -1 21 | else: 22 | self.time[key] = time() + age 23 | return True 24 | 25 | def get(self,key): 26 | '''获取键key对应的值''' 27 | if key in self.mem.keys(): 28 | if self.time[key] == -1 or self.time[key] > time(): 29 | return self.mem[key] 30 | else: 31 | self.delete(key) 32 | return None 33 | else: 34 | return None 35 | 36 | def delete(self,key): 37 | '''删除键为key的条目''' 38 | del self.mem[key] 39 | del self.time[key] 40 | return True 41 | 42 | def clear(self): 43 | '''清空所有缓存''' 44 | self.mem.clear() 45 | self.time.clear() 46 | 47 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QACfg.py: -------------------------------------------------------------------------------- 1 | #coding :utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | from configparser import ConfigParser 26 | 27 | 28 | def QA_util_cfg_initial(CONFIG_FILE): 29 | """[summary] 30 | 31 | Arguments: 32 | CONFIG_FILE {[type]} -- [description] 33 | """ 34 | 35 | pass 36 | 37 | 38 | def QA_util_get_cfg(__file_path, __file_name): 39 | """ 40 | explanation: 41 | 获取配置信息 42 | 43 | params: 44 | * __file_path -> 45 | 含义: 配置文件地址 46 | 类型: str 47 | 参数支持: [] 48 | * __file_name -> 49 | 含义: 文件名 50 | 类型: str 51 | 参数支持: [] 52 | 53 | """ 54 | __setting_file = ConfigParser() 55 | try: 56 | return __setting_file.read(__file_path + __file_name) 57 | except: 58 | return 'wrong' 59 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QADict.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | 26 | def QA_util_dict_remove_key(dicts, key): 27 | """ 28 | 输入一个dict 返回删除后的 29 | """ 30 | 31 | if isinstance(key, list): 32 | for item in key: 33 | try: 34 | dicts.pop(item) 35 | except: 36 | pass 37 | else: 38 | try: 39 | dicts.pop(key) 40 | except: 41 | pass 42 | return dicts 43 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QAError.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | """QUANTAXIS 的error类 25 | 26 | """ 27 | 28 | 29 | class QAError_fetch_data(RuntimeError): 30 | def __init__(self, res): 31 | RuntimeError.__init__(self, 'QA FETCH DATA ERROR', res) 32 | 33 | 34 | class QAError_no_data_in_database(RuntimeError): 35 | def __init__(self, res): 36 | RuntimeError.__init__(self, 'QA FETCH NO DATA ERROR', res) 37 | 38 | 39 | class QAError_crawl_data_web(RuntimeError): 40 | def __init__(self, res): 41 | RuntimeError.__init__(self, 'QA CRAWLER ERROR', res) 42 | 43 | 44 | class QAError_database_connection(RuntimeError): 45 | def __init__(self, res): 46 | RuntimeError.__init__(self, 'QA DATABASE CONNECTION ERROR', res) 47 | 48 | 49 | class QAError_web_connection(RuntimeError): 50 | def __init__(self, res): 51 | RuntimeError.__init__(self, 'QA WEB CONNECTION ERROR', res) 52 | 53 | 54 | class QAError_market_enging_down(RuntimeError): 55 | def __init__(self, res): 56 | RuntimeError.__init__(self, 'QA MARKET ENGING DOWN ERROR', res) 57 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QAFile.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import os 3 | 4 | 5 | def QA_util_file_md5(filename): 6 | 7 | """ 8 | explanation: 9 | 获取文件的MD5值 10 | 11 | params: 12 | * filename ->: 13 | meaning: 文件路径 14 | type: null 15 | optional: [null] 16 | 17 | return: 18 | str 19 | 20 | demonstrate: 21 | Not described 22 | 23 | output: 24 | Not described 25 | """ 26 | 27 | with open(filename, mode='rb') as f: 28 | d = hashlib.md5() 29 | while True: 30 | # 128 is smaller than the typical filesystem block 31 | buf = f.read(4096) 32 | if not buf: 33 | break 34 | d.update(buf) 35 | return d.hexdigest() 36 | 37 | 38 | def QA_util_file_size(filename): 39 | return os.path.getsize(file) 40 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QAList.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | import numpy as np 25 | 26 | 27 | def QA_util_multi_demension_list(row_, col_=0): 28 | # row_ 是行, col_ 是列 29 | """ 30 | 如果需要创建一个[[],[]], 那就用 row_=2,col=0 31 | 其他时候,返回的都是[[None]] 32 | """ 33 | return [[None for col in range(col_)] for row in range(row_)] 34 | 35 | 36 | def QA_util_diff_list(datastruct): 37 | return (np.array(datastruct[1:]) - np.array(datastruct[:-1])).tolist() 38 | -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QASingleton.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | def singleton(cls): 4 | 5 | instances = {} 6 | 7 | def _wrapper(*args, **kwargs): 8 | 9 | if cls not in instances: 10 | 11 | instances[cls] = cls(*args, **kwargs) 12 | 13 | return instances[cls] 14 | 15 | return _wrapper -------------------------------------------------------------------------------- /QUANTAXIS/QAUtil/QAText.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | """ 26 | 这里主要是一些关于文本的代码 27 | 28 | 文本分词 29 | 模糊查询 30 | 正则匹配 31 | """ 32 | 33 | import jieba 34 | import re 35 | import fuzzyfinder 36 | 37 | # 🛠TODO: stock_list中有股票的中文/stock_block中有版块的中文 需要将他们做一些模糊查询 38 | 39 | 40 | 41 | def split_word(input_text,cutall=False): 42 | """ 43 | 使用jieba分词 将输入的语句分词 44 | """ 45 | 46 | return jieba.cut(input_text,cut_all=cutall) 47 | -------------------------------------------------------------------------------- /QUANTAXIS/QAWebServer/__init__.py: -------------------------------------------------------------------------------- 1 | from QUANTAXIS.QAWebServer.basehandles import QABaseHandler, QAWebSocketHandler 2 | from QUANTAXIS.QAWebServer.schedulehandler import QAScheduleQuery, QASchedulerHandler 3 | from QUANTAXIS.QAWebServer.server import start_server 4 | -------------------------------------------------------------------------------- /QUANTAXIS/QAWebServer/util.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import json 3 | import sys 4 | from datetime import date 5 | 6 | APPLICATION_JSON = 'application/json' 7 | APPLICATION_XML = 'application/xml' 8 | TEXT_XML = 'text/xml' 9 | 10 | 11 | boolean = str 12 | 13 | if sys.version_info > (3,): 14 | long = int 15 | unicode = str 16 | str = bytes 17 | 18 | 19 | def convert(value, type): 20 | """ Convert / Cast function """ 21 | if issubclass(type, str) and not (value.upper() in ['FALSE', 'TRUE']): 22 | return value.decode('utf-8') 23 | elif issubclass(type, unicode): 24 | return unicode(value) 25 | elif issubclass(type, int): 26 | return int(value) 27 | elif issubclass(type, long): 28 | return long(value) 29 | elif issubclass(type, float): 30 | return float(value) 31 | elif issubclass(type, boolean) and (value.upper() in ['FALSE', 'TRUE']): 32 | if str(value).upper() == 'TRUE': 33 | return True 34 | elif str(value).upper() == 'FALSE': 35 | return False 36 | else: 37 | return value 38 | 39 | 40 | class CJsonEncoder(json.JSONEncoder): 41 | 42 | def default(self, obj): 43 | if isinstance(obj, datetime.datetime): 44 | return obj.strftime('%Y-%m-%d %H:%M:%S') 45 | elif isinstance(obj, datetime.date): 46 | return obj.strftime('%Y-%m-%d') 47 | else: 48 | return json.JSONEncoder.default(self, obj) 49 | -------------------------------------------------------------------------------- /QUANTAXIS/QIFI/__init__.py: -------------------------------------------------------------------------------- 1 | from QUANTAXIS.QIFI.QifiAccount import QIFI_Account 2 | from QUANTAXIS.QIFI.QifiManager import QA_QIFIMANAGER, QA_QIFISMANAGER 3 | -------------------------------------------------------------------------------- /QUANTAXIS/QIFI/qifisql.py: -------------------------------------------------------------------------------- 1 | ### qifi sql 2 | 3 | import clickhouse_driver 4 | class test: 5 | def __init__(self): 6 | self.client = clickhouse_driver.Client(host='192.168.2.121', database='test', 7 | settings={ 8 | 'insert_block_size': 100000000}, 9 | compression=True) 10 | def execute(self, sql): 11 | return self.client.query_dataframe(sql) 12 | def get_orders(self,user_id): 13 | res=self.execute("select * from test.orders where `user_id`='{}'".format(user_id)) 14 | return res -------------------------------------------------------------------------------- /QUANTAXIS/__main__.py: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | from QUANTAXIS.QACmd import QA_cmd 25 | 26 | if __name__ == '__main__': 27 | 28 | # 确保用户的当前目录是 在根目录下执行 29 | QA_cmd() 30 | -------------------------------------------------------------------------------- /STU/P3_Backtest.md: -------------------------------------------------------------------------------- 1 | # BACKTEST 关于回测 2 | 3 | 在想法出现之后, 你必不可少的面临需要知道你的想法能不能在市场中赚到钱, 这是最原始也是最简单的初衷 4 | 5 | 回测的目的: 6 | 7 | - 快速/较为准确的知晓自己的想法的利润区间 8 | - 验证 9 | 10 | QUANTAXIS 为回测环境提供了一个可定制的账户结构(QIFI) 以及一个数据驱动的测试过程(QAStrategy) 11 | 12 | 但是我们并不限定你的回测代码的构建方式, 一切的环节都是宽松且可自定义的 13 | -------------------------------------------------------------------------------- /STU/P4_Analysis.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/STU/P4_Analysis.md -------------------------------------------------------------------------------- /STU/P5_REALTIME.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/STU/P5_REALTIME.md -------------------------------------------------------------------------------- /STU/P6_Thought.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/STU/P6_Thought.md -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /config/QA.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Please Select: 3 | 帮助:通过编辑修改QA0.txt到QA3.txt执行不同的组合脚本,可以自行修改txt达到目的。 4 | 注意:目前测试mac系统通过,其他系统请自行调试。 5 | 请选择对应数字: 6 | 1.QUANTAXIS >QA1.txt(save all:save stock_day/xdxr/ index_day/ stock_list/index_list) 7 | 2.QUANTAXIS >QA2.txt(save day:save stock_day/xdxr index_day etf_day stock_list/index_list) 8 | 3.QUANTAXIS >QA3.txt(save financialfiles 保存高级财务数据(自1996年开始)) 9 | 0.QUANTAXIS >QA0.txt(save stock_block:保存板块 & save stock_info:保存tushare数据接口获取的股票列表)" 10 | read -p "Enter selection [0-3] >" num 11 | 12 | if [[ $num =~ ^[0-3]$ ]]; then 13 | if [[ $num == 0 ]]; then 14 | echo "QUANTAXIS >QA0.txt" 15 | quantaxis < QA0.txt 16 | exit; 17 | fi 18 | 19 | if [[ $num == 1 ]]; then 20 | echo "QUANTAXIS >QA1.txt" 21 | quantaxis < QA1.txt 22 | exit 23 | fi 24 | 25 | if [[ $num == 2 ]]; then 26 | echo "QUANTAXIS >QA2.txt" 27 | quantaxis < QA2.txt 28 | exit; 29 | fi 30 | 31 | if [[ $num == 3 ]]; then 32 | echo "QUANTAXIS >QA3.txt" 33 | quantaxis < QA3.txt 34 | exit; 35 | fi 36 | else 37 | echo "Invalid entry." >&2 38 | exit 1 39 | fi 40 | -------------------------------------------------------------------------------- /config/QA0.txt: -------------------------------------------------------------------------------- 1 | save stock_block 2 | save stock_info 3 | exit 4 | 5 | -------------------------------------------------------------------------------- /config/QA1.txt: -------------------------------------------------------------------------------- 1 | save all 2 | exit 3 | -------------------------------------------------------------------------------- /config/QA2.txt: -------------------------------------------------------------------------------- 1 | save day 2 | exit 3 | -------------------------------------------------------------------------------- /config/QA3.txt: -------------------------------------------------------------------------------- 1 | save financialfiles 2 | exit 3 | -------------------------------------------------------------------------------- /config/install_docker.sh: -------------------------------------------------------------------------------- 1 | echo 'install_docker' 2 | 3 | curl -sSL https://get.daocloud.io/docker | sh 4 | 5 | curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 6 | chmod +x /usr/local/bin/docker-compose 7 | 8 | 9 | echo 'finished install_docker' 10 | -------------------------------------------------------------------------------- /config/install_rust.sh: -------------------------------------------------------------------------------- 1 | 2 | ENV RUSTUP_HOME=/usr/local/rustup \ 3 | CARGO_HOME=/usr/local/cargo \ 4 | PATH=/usr/local/cargo/bin:$PATH \ 5 | RUST_VERSION=1.57.0 6 | ARG CMAKE_VERSION=3.12.0 7 | WORKDIR /tmp 8 | RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ 9 | && tar xzf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ 10 | && mv cmake-${CMAKE_VERSION}-Linux-x86_64 /usr/local/cmake \ 11 | && cmake -version 12 | 13 | RUN apt-get install -y --allow-downgrades pkg-config zlib1g=1:1.2.8.dfsg-2ubuntu4.1 && apt-get install pkg-config libssl-dev -y 14 | 15 | RUN set -eux; \ 16 | dpkgArch="$(dpkg --print-architecture)"; \ 17 | case "${dpkgArch##*-}" in \ 18 | amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='a46fe67199b7bcbbde2dcbc23ae08db6f29883e260e23899a88b9073effc9076' ;; \ 19 | armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='6af5abbbae02e13a9acae29593ec58116ab0e3eb893fa0381991e8b0934caea1' ;; \ 20 | arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='51862e576f064d859546cca5f3d32297092a850861e567327422e65b60877a1b' ;; \ 21 | i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='91456c3e6b2a3067914b3327f07bc182e2a27c44bff473263ba81174884182be' ;; \ 22 | *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \ 23 | esac; \ 24 | url="https://static.rust-lang.org/rustup/archive/1.18.3/${rustArch}/rustup-init"; \ 25 | wget "$url"; \ 26 | echo "${rustupSha256} *rustup-init" | sha256sum -c -; \ 27 | chmod +x rustup-init; \ 28 | ./rustup-init -y --no-modify-path --default-toolchain $RUST_VERSION; \ 29 | rm rustup-init; \ 30 | chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ 31 | rustup --version; \ 32 | cargo --version; \ 33 | rustc --version; 34 | 35 | RUN set -eux; \ 36 | apt-get update; \ 37 | apt-get install -y build-essential libzmq3-dev pkg-config; 38 | 39 | RUN set -eux; \ 40 | cargo install evcxr_jupyter; \ 41 | evcxr_jupyter --install; 42 | -------------------------------------------------------------------------------- /config/readme.md: -------------------------------------------------------------------------------- 1 | # 配置/脚本区 2 | 3 | - ubuntu16.sh ubuntu 16 一键安装脚本 4 | - startjupyter.sh 开启jupyter notebook 5 | - run_backend.sh 开启mongod后台,WEBKIT前后台 6 | - update_data.py 更新数据脚本 7 | -------------------------------------------------------------------------------- /config/run_backend.sh: -------------------------------------------------------------------------------- 1 | # run mongo 2 | 3 | service mongod restart 4 | 5 | # nohup mongod & 6 | 7 | 8 | cd ../QUANTAXIS_WEBKIT/backend 9 | forever start bin/www 10 | 11 | cd ../web 12 | forever start build/dev-server.js -------------------------------------------------------------------------------- /config/startjupyter.sh: -------------------------------------------------------------------------------- 1 | #sudo python3.6 -m pip install jupyter -i https://pypi.doubanio.com/simple 2 | 3 | cd ../jupyterexample 4 | jupyter notebook --ip=0.0.0.0 --allow-root 5 | -------------------------------------------------------------------------------- /config/update_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | 3 | #coding :utf-8 4 | # 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all 17 | # copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | 27 | import datetime 28 | from QUANTAXIS import (QA_SU_save_etf_day, QA_SU_save_index_day, QA_SU_save_stock_min, 29 | QA_SU_save_stock_block, QA_SU_save_stock_day,QA_SU_save_etf_min, 30 | QA_SU_save_stock_list, QA_SU_save_stock_xdxr, 31 | QA_util_log_info) 32 | 33 | print('SAVE/UPDATE {}'.format(datetime.datetime.now())) 34 | 35 | QA_SU_save_stock_day('tdx') 36 | QA_SU_save_stock_xdxr('tdx') 37 | QA_SU_save_etf_day('tdx') 38 | QA_SU_save_index_day('tdx') 39 | QA_SU_save_stock_list('tdx') 40 | QA_SU_save_stock_block('tdx') 41 | -------------------------------------------------------------------------------- /config/update_fin.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | 3 | #coding :utf-8 4 | # 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016-2021 yutiansut/QUANTAXIS 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all 17 | # copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | 27 | 28 | """对应于save x 29 | """ 30 | from QUANTAXIS.QASU.main import (QA_SU_save_financialfiles_fromtdx) 31 | 32 | if __name__ == '__main__': 33 | QA_SU_save_financialfiles_fromtdx() 34 | -------------------------------------------------------------------------------- /config/update_future.py: -------------------------------------------------------------------------------- 1 | from QUANTAXIS.QASU.main import (QA_SU_save_etf_day, QA_SU_save_etf_min, 2 | QA_SU_save_financialfiles, 3 | QA_SU_save_index_day, QA_SU_save_index_min, 4 | QA_SU_save_stock_block, QA_SU_save_stock_day, 5 | QA_SU_save_stock_info, 6 | QA_SU_save_stock_info_tushare, 7 | QA_SU_save_stock_list, QA_SU_save_stock_min, 8 | QA_SU_save_stock_xdxr,QA_SU_save_future_day,QA_SU_save_future_day_all, 9 | QA_SU_save_future_min,QA_SU_save_future_min_all) 10 | 11 | 12 | QA_SU_save_future_min_all('tdx') 13 | QA_SU_save_future_day_all('tdx') 14 | 15 | -------------------------------------------------------------------------------- /config/windows_autojob_updatedata.md: -------------------------------------------------------------------------------- 1 | # WINDOWS开启自动脚本 2 | 3 | 4 | 5 | - [WINDOWS开启自动脚本](#windows开启自动脚本) 6 | - [打开控制面板-系统和安全-管理工具](#打开控制面板-系统和安全-管理工具) 7 | - [打开计划任务程序](#打开计划任务程序) 8 | - [在计划任务程序中,新建任务](#在计划任务程序中新建任务) 9 | - [创建QUANTAXIS_Update任务](#创建quantaxis_update任务) 10 | - [选择运行时间/频率](#选择运行时间频率) 11 | - [选择执行的命令](#选择执行的命令) 12 | - [配置完毕](#配置完毕) 13 | 14 | 15 | 16 | 我们使用计划任务来开启自动更新任务: 17 | 18 | 19 | ## 打开控制面板-系统和安全-管理工具 20 | ![](http://picx.gulizhu.com/management.png) 21 | 22 | ## 打开计划任务程序 23 | ![](http://picx.gulizhu.com/management2.png) 24 | 25 | ## 在计划任务程序中,新建任务 26 | ![](http://picx.gulizhu.com/task1.png) 27 | 28 | ## 创建QUANTAXIS_Update任务 29 | ![](http://picx.gulizhu.com/task2.png) 30 | 31 | ## 选择运行时间/频率 32 | ![](http://picx.gulizhu.com/task3.png) 33 | 34 | ## 选择执行的命令 35 | ![](http://picx.gulizhu.com/task4.png) 36 | 37 | ## 配置完毕 38 | ![](http://picx.gulizhu.com/task5.png) -------------------------------------------------------------------------------- /dev/QACache/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | cache data 3 | 4 | """ 5 | from pyarrow import parquet, plasma, RecordBatch, MockOutputStream, RecordBatchStreamWriter, RecordBatchStreamReader, FixedSizeBufferWriter, BufferReader 6 | import numpy as np 7 | import pyarrow.plasma as plasma 8 | import pandas as pd 9 | 10 | 11 | from QUANTAXIS.QAData import QADataStruct 12 | 13 | 14 | class PlasmaStore(): 15 | def __init__(self) -> None: 16 | self.client = plasma.connect("/tmp/plasma") 17 | 18 | def store_datastruct(self, data): 19 | return self.store_dataframe(data.data) 20 | 21 | def get_datastruct(self, object_id): 22 | return QADataStruct(self.get_dataframe(object_id)) 23 | 24 | def store_dataframe(self, data): 25 | record_batch = RecordBatch.from_pandas(data) 26 | object_id = plasma.ObjectID(np.random.bytes(20)) 27 | mock_sink = MockOutputStream() 28 | with RecordBatchStreamWriter(mock_sink, record_batch.schema) as stream_writer: 29 | stream_writer.write_batch(record_batch) 30 | data_size = mock_sink.size() 31 | buf = self.client.create(object_id, data_size) 32 | 33 | stream = FixedSizeBufferWriter(buf) 34 | with RecordBatchStreamWriter(stream, record_batch.schema) as stream_writer: 35 | stream_writer.write_batch(record_batch) 36 | self.client.seal(object_id) 37 | return object_id 38 | 39 | def get_dataframe(self, object_id) -> pd.DataFrame: 40 | # Get PlasmaBuffer from ObjectID 41 | [data] = self.client.get_buffers([object_id]) 42 | buffer = BufferReader(data) 43 | reader = RecordBatchStreamReader(buffer) 44 | record_batch = reader.read_next_batch() 45 | return record_batch.to_pandas() 46 | -------------------------------------------------------------------------------- /docker/ctpbee-base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7.4-stretch 2 | 3 | ENV TZ=Asia/Shanghai 4 | ENV DEBIAN_FRONTEND noninteractive 5 | 6 | RUN \ 7 | apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E40EBBA24FF2FC69 \ 8 | && apt-get update \ 9 | && apt-get install -y apt-utils locales --allow\ 10 | && apt install gcc -y --allow\ 11 | && locale-gen zh_CN.GB18030 \ 12 | && pip install quantaxis-servicedetect \ 13 | && localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.GB18030 \ 14 | && echo "LANG=zh_CN.GB18030" > /etc/locale.conf \ 15 | && echo "zh_CN.GB18030 UTF-8" >> /etc/locale.gen \ 16 | && echo "LC_ALL=zh_CN.GB18030" >> /etc/environment 17 | 18 | ENV LANG zh_CN.GB18030 19 | ENV LANGUAGE zh_CN.GB18030 20 | ENV LC_ALL zh_CN.GB18030 21 | 22 | 23 | RUN cd ~ \ 24 | && git clone https://gitee.com/yutiansut/ctpbee \ 25 | && chmod +x ~/ctpbee/examples/run.py \ 26 | && cd ctpbee && pip install -e . 27 | 28 | 29 | EXPOSE 5000 30 | 31 | CMD ["python", "/root/ctpbee/examples/run.py"] 32 | 33 | -------------------------------------------------------------------------------- /docker/just_database.yaml: -------------------------------------------------------------------------------- 1 | version: "2.1" 2 | services: 3 | 4 | redis: 5 | image: 'daocloud.io/quantaxis/qaredis:latest' 6 | ports: 7 | - "6379:6379" 8 | environment: 9 | - TZ=Asia/Shanghai 10 | command: ['redis-server'] 11 | restart: always 12 | networks: 13 | qanetwork_db: 14 | ipv4_address: 172.19.11.2 15 | mgdb: 16 | image: daocloud.io/quantaxis/qamongo_single:latest 17 | ports: 18 | - "27017:27017" 19 | environment: 20 | - TZ=Asia/Shanghai 21 | - MONGO_INITDB_DATABASE=quantaxis 22 | volumes: 23 | - qamg:/data/db 24 | networks: 25 | qanetwork_db: 26 | ipv4_address: 172.19.11.3 27 | restart: always 28 | 29 | qaclickhouse: 30 | image: daocloud.io/quantaxis/qa-clickhouse 31 | ports: 32 | - "9000:9000" 33 | - "8123:8123" 34 | - "9009:9009" 35 | environment: 36 | - TZ=Asia/Shanghai 37 | networks: 38 | qanetwork_db: 39 | ipv4_address: 172.19.11.4 40 | 41 | qaeventmq: 42 | image: daocloud.io/quantaxis/qaeventmq:latest 43 | ports: 44 | - "15672:15672" 45 | - "5672:5672" 46 | - "4369:4369" 47 | environment: 48 | - TZ=Asia/Shanghai 49 | networks: 50 | qanetwork_db: 51 | ipv4_address: 172.19.11.5 52 | restart: always 53 | 54 | 55 | volumes: 56 | qamg: 57 | external: 58 | name: qamg 59 | 60 | networks: 61 | qanetwork_db: 62 | ipam: 63 | config: 64 | - subnet: 172.19.11.0/24 65 | gateway: 172.19.11.1 66 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/Chart.yaml: -------------------------------------------------------------------------------- 1 | name: docker-compose 2 | description: A generated Helm Chart for docker-compose from Skippbox Kompose 3 | version: 0.0.1 4 | keywords: 5 | - docker-compose 6 | sources: 7 | home: 8 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/README.md: -------------------------------------------------------------------------------- 1 | This chart was created by Kompose 2 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/mgdb-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: mgdb 10 | name: mgdb 11 | spec: 12 | replicas: 1 13 | strategy: 14 | type: Recreate 15 | template: 16 | metadata: 17 | creationTimestamp: null 18 | labels: 19 | io.kompose.service: mgdb 20 | spec: 21 | containers: 22 | - env: 23 | - name: MONGO_INITDB_DATABASE 24 | value: quantaxis 25 | - name: TZ 26 | value: Asia/Shanghai 27 | image: daocloud.io/quantaxis/qamongo_single:latest 28 | name: mgdb 29 | ports: 30 | - containerPort: 27017 31 | resources: {} 32 | volumeMounts: 33 | - mountPath: /data/db 34 | name: qamg 35 | restartPolicy: Always 36 | volumes: 37 | - name: qamg 38 | persistentVolumeClaim: 39 | claimName: qamg 40 | status: {} 41 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/mgdb-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: mgdb 10 | name: mgdb 11 | spec: 12 | ports: 13 | - name: "27017" 14 | port: 27017 15 | targetPort: 27017 16 | selector: 17 | io.kompose.service: mgdb 18 | status: 19 | loadBalancer: {} 20 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qa-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qa 10 | name: qa 11 | spec: 12 | replicas: 1 13 | strategy: 14 | type: Recreate 15 | template: 16 | metadata: 17 | creationTimestamp: null 18 | labels: 19 | io.kompose.service: qa 20 | spec: 21 | containers: 22 | - env: 23 | - name: MONGODB 24 | value: mgdb 25 | - name: QAPUBSUB_IP 26 | value: qaeventmq 27 | - name: QAPUBSUB_PORT 28 | value: "5672" 29 | - name: QAPUBSUB_PWD 30 | value: admin 31 | - name: QAPUBSUB_USER 32 | value: admin 33 | - name: QARUN 34 | value: qaweb 35 | - name: TZ 36 | value: Asia/Shanghai 37 | image: daocloud.io/quantaxis/qacommunity:latest 38 | name: qacommunity 39 | ports: 40 | - containerPort: 8888 41 | - containerPort: 80 42 | resources: {} 43 | volumeMounts: 44 | - mountPath: /home 45 | name: qacode 46 | restartPolicy: Always 47 | volumes: 48 | - name: qacode 49 | persistentVolumeClaim: 50 | claimName: qacode 51 | status: {} 52 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qa-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qa 10 | name: qa 11 | spec: 12 | ports: 13 | - name: "8888" 14 | port: 8888 15 | targetPort: 8888 16 | - name: "81" 17 | port: 81 18 | targetPort: 80 19 | selector: 20 | io.kompose.service: qa 21 | status: 22 | loadBalancer: {} 23 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qacode-persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | io.kompose.service: qacode 7 | name: qacode 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: 100Mi 14 | status: {} 15 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qaeventmq-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qaeventmq 10 | name: qaeventmq 11 | spec: 12 | replicas: 1 13 | strategy: {} 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qaeventmq 19 | spec: 20 | containers: 21 | - env: 22 | - name: TZ 23 | value: Asia/Shanghai 24 | image: daocloud.io/quantaxis/qaeventmq:latest 25 | name: qaeventmq 26 | ports: 27 | - containerPort: 15672 28 | - containerPort: 5672 29 | - containerPort: 4369 30 | resources: {} 31 | restartPolicy: Always 32 | status: {} 33 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qaeventmq-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qaeventmq 10 | name: qaeventmq 11 | spec: 12 | ports: 13 | - name: "15672" 14 | port: 15672 15 | targetPort: 15672 16 | - name: "5672" 17 | port: 5672 18 | targetPort: 5672 19 | - name: "4369" 20 | port: 4369 21 | targetPort: 4369 22 | selector: 23 | io.kompose.service: qaeventmq 24 | status: 25 | loadBalancer: {} 26 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qamarketcollector-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qamarketcollector 10 | name: qamarketcollector 11 | spec: 12 | replicas: 1 13 | strategy: {} 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qamarketcollector 19 | spec: 20 | containers: 21 | - args: 22 | - /root/QUANTAXIS_RealtimeCollector/docker/wait_for_it.sh 23 | - qaeventmq:5672 24 | - -- 25 | - /root/QUANTAXIS_RealtimeCollector/docker/start_collector.sh 26 | env: 27 | - name: EventMQ_IP 28 | value: qaeventmq 29 | - name: MONGODB 30 | value: mgdb 31 | image: daocloud.io/quantaxis/qarealtimecollector:latest 32 | name: qamarketcollector 33 | ports: 34 | - containerPort: 8011 35 | resources: {} 36 | restartPolicy: Always 37 | status: {} 38 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qamarketcollector-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qamarketcollector 10 | name: qamarketcollector 11 | spec: 12 | ports: 13 | - name: "8011" 14 | port: 8011 15 | targetPort: 8011 16 | selector: 17 | io.kompose.service: qamarketcollector 18 | status: 19 | loadBalancer: {} 20 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qamg-persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | io.kompose.service: qamg 7 | name: qamg 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: 100Mi 14 | status: {} 15 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qamonitor-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qamonitor 10 | name: qamonitor 11 | spec: 12 | replicas: 1 13 | strategy: {} 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qamonitor 19 | spec: 20 | containers: 21 | - image: daocloud.io/quantaxis/qa-monitor:latest 22 | name: qamonitor 23 | ports: 24 | - containerPort: 61209 25 | - containerPort: 61208 26 | resources: {} 27 | hostPID: true 28 | restartPolicy: Always 29 | securityContext: {} 30 | status: {} 31 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qamonitor-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qamonitor 10 | name: qamonitor 11 | spec: 12 | ports: 13 | - name: "61209" 14 | port: 61209 15 | targetPort: 61209 16 | - name: "61208" 17 | port: 61208 18 | targetPort: 61208 19 | selector: 20 | io.kompose.service: qamonitor 21 | status: 22 | loadBalancer: {} 23 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qaweb-run-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qaweb-run 10 | name: qaweb-run 11 | spec: 12 | replicas: 1 13 | strategy: {} 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qaweb-run 19 | spec: 20 | containers: 21 | - args: 22 | - /root/wait_for_it.sh 23 | - qaeventmq:5672 24 | - -- 25 | - /root/runcelery.sh 26 | env: 27 | - name: MONGODB 28 | value: mgdb 29 | - name: QAPUBSUB_IP 30 | value: qaeventmq 31 | - name: QAPUBSUB_PORT 32 | value: "5672" 33 | - name: QAPUBSUB_PWD 34 | value: admin 35 | - name: QAPUBSUB_USER 36 | value: admin 37 | - name: QARUN_AMQP 38 | value: pyamqp://admin:admin@qaeventmq:5672// 39 | - name: TZ 40 | value: Asia/Shanghai 41 | image: daocloud.io/quantaxis/qarun:latest 42 | name: qarun 43 | ports: 44 | - containerPort: 8010 45 | resources: {} 46 | restartPolicy: Always 47 | status: {} 48 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/helm_charts/templates/qaweb-run-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert -c 6 | kompose.version: 1.18.0 (06a2e56) 7 | creationTimestamp: null 8 | labels: 9 | io.kompose.service: qaweb-run 10 | name: qaweb-run 11 | spec: 12 | ports: 13 | - name: "8010" 14 | port: 8010 15 | targetPort: 8010 16 | selector: 17 | io.kompose.service: qaweb-run 18 | status: 19 | loadBalancer: {} 20 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/mgdb-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: mgdb 11 | name: mgdb 12 | spec: 13 | replicas: 3 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: mgdb 19 | spec: 20 | containers: 21 | - env: 22 | - name: MONGO_INITDB_DATABASE 23 | value: quantaxis 24 | - name: TZ 25 | value: Asia/Shanghai 26 | image: daocloud.io/quantaxis/qamongo_single:latest 27 | name: mgdb 28 | ports: 29 | - containerPort: 27017 30 | resources: {} 31 | volumeMounts: 32 | - mountPath: /data/db 33 | name: qamg 34 | restartPolicy: Always 35 | volumes: 36 | - name: qamg 37 | persistentVolumeClaim: 38 | claimName: qamg 39 | status: 40 | replicas: 0 41 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/mgdb-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: mgdb 11 | name: mgdb 12 | spec: 13 | ports: 14 | - name: "27017" 15 | port: 27017 16 | targetPort: 27017 17 | selector: 18 | io.kompose.service: mgdb 19 | status: 20 | loadBalancer: {} 21 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qa-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qa 11 | name: qa 12 | spec: 13 | replicas: 3 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qa 19 | spec: 20 | containers: 21 | - env: 22 | - name: MONGODB 23 | value: mgdb 24 | - name: QAPUBSUB_IP 25 | value: qaeventmq 26 | - name: QAPUBSUB_PORT 27 | value: "5672" 28 | - name: QAPUBSUB_PWD 29 | value: admin 30 | - name: QAPUBSUB_USER 31 | value: admin 32 | - name: QARUN 33 | value: qaweb 34 | - name: TZ 35 | value: Asia/Shanghai 36 | image: daocloud.io/quantaxis/qacommunity:latest 37 | name: qacommunity 38 | ports: 39 | - containerPort: 8888 40 | - containerPort: 80 41 | resources: {} 42 | volumeMounts: 43 | - mountPath: /home 44 | name: qacode 45 | restartPolicy: Always 46 | volumes: 47 | - name: qacode 48 | persistentVolumeClaim: 49 | claimName: qacode 50 | status: 51 | replicas: 0 52 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qa-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qa 11 | name: qa 12 | spec: 13 | ports: 14 | - name: "8888" 15 | port: 8888 16 | targetPort: 8888 17 | - name: "81" 18 | port: 81 19 | targetPort: 80 20 | selector: 21 | io.kompose.service: qa 22 | status: 23 | loadBalancer: {} 24 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qacode-persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | io.kompose.service: qacode 7 | name: qacode 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: 100Mi 14 | status: {} 15 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qaeventmq-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qaeventmq 11 | name: qaeventmq 12 | spec: 13 | replicas: 3 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qaeventmq 19 | spec: 20 | containers: 21 | - env: 22 | - name: TZ 23 | value: Asia/Shanghai 24 | image: daocloud.io/quantaxis/qaeventmq:latest 25 | name: qaeventmq 26 | ports: 27 | - containerPort: 15672 28 | - containerPort: 5672 29 | - containerPort: 4369 30 | resources: {} 31 | restartPolicy: Always 32 | status: 33 | replicas: 0 34 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qaeventmq-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qaeventmq 11 | name: qaeventmq 12 | spec: 13 | ports: 14 | - name: "15672" 15 | port: 15672 16 | targetPort: 15672 17 | - name: "5672" 18 | port: 5672 19 | targetPort: 5672 20 | - name: "4369" 21 | port: 4369 22 | targetPort: 4369 23 | selector: 24 | io.kompose.service: qaeventmq 25 | status: 26 | loadBalancer: {} 27 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qamarketcollector-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qamarketcollector 11 | name: qamarketcollector 12 | spec: 13 | replicas: 3 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qamarketcollector 19 | spec: 20 | containers: 21 | - args: 22 | - /root/QUANTAXIS_RealtimeCollector/docker/wait_for_it.sh 23 | - qaeventmq:5672 24 | - -- 25 | - /root/QUANTAXIS_RealtimeCollector/docker/start_collector.sh 26 | env: 27 | - name: EventMQ_IP 28 | value: qaeventmq 29 | - name: MONGODB 30 | value: mgdb 31 | image: daocloud.io/quantaxis/qarealtimecollector:latest 32 | name: qamarketcollector 33 | ports: 34 | - containerPort: 8011 35 | resources: {} 36 | restartPolicy: Always 37 | status: 38 | replicas: 0 39 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qamarketcollector-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qamarketcollector 11 | name: qamarketcollector 12 | spec: 13 | ports: 14 | - name: "8011" 15 | port: 8011 16 | targetPort: 8011 17 | selector: 18 | io.kompose.service: qamarketcollector 19 | status: 20 | loadBalancer: {} 21 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qamg-persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | io.kompose.service: qamg 7 | name: qamg 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: 100Mi 14 | status: {} 15 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qamonitor-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qamonitor 11 | name: qamonitor 12 | spec: 13 | replicas: 3 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qamonitor 19 | spec: 20 | containers: 21 | - image: daocloud.io/quantaxis/qa-monitor:latest 22 | name: qamonitor 23 | ports: 24 | - containerPort: 61209 25 | - containerPort: 61208 26 | resources: {} 27 | hostPID: true 28 | restartPolicy: Always 29 | securityContext: {} 30 | status: 31 | replicas: 0 32 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qamonitor-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qamonitor 11 | name: qamonitor 12 | spec: 13 | ports: 14 | - name: "61209" 15 | port: 61209 16 | targetPort: 61209 17 | - name: "61208" 18 | port: 61208 19 | targetPort: 61208 20 | selector: 21 | io.kompose.service: qamonitor 22 | status: 23 | loadBalancer: {} 24 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qaweb-run-replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qaweb-run 11 | name: qaweb-run 12 | spec: 13 | replicas: 3 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | io.kompose.service: qaweb-run 19 | spec: 20 | containers: 21 | - args: 22 | - /root/wait_for_it.sh 23 | - qaeventmq:5672 24 | - -- 25 | - /root/runcelery.sh 26 | env: 27 | - name: MONGODB 28 | value: mgdb 29 | - name: QAPUBSUB_IP 30 | value: qaeventmq 31 | - name: QAPUBSUB_PORT 32 | value: "5672" 33 | - name: QAPUBSUB_PWD 34 | value: admin 35 | - name: QAPUBSUB_USER 36 | value: admin 37 | - name: QARUN_AMQP 38 | value: pyamqp://admin:admin@qaeventmq:5672// 39 | - name: TZ 40 | value: Asia/Shanghai 41 | image: daocloud.io/quantaxis/qarun:latest 42 | name: qarun 43 | ports: 44 | - containerPort: 8010 45 | resources: {} 46 | restartPolicy: Always 47 | status: 48 | replicas: 0 49 | -------------------------------------------------------------------------------- /docker/k8s_deploy_qaservice/replicate_3nodes/qaweb-run-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | kompose.cmd: E:\k8s-for-docker-desktop\kompose-windows-amd64.exe convert --replication-controller 6 | --replicas 3 7 | kompose.version: 1.18.0 (06a2e56) 8 | creationTimestamp: null 9 | labels: 10 | io.kompose.service: qaweb-run 11 | name: qaweb-run 12 | spec: 13 | ports: 14 | - name: "8010" 15 | port: 8010 16 | targetPort: 8010 17 | selector: 18 | io.kompose.service: qaweb-run 19 | status: 20 | loadBalancer: {} 21 | -------------------------------------------------------------------------------- /docker/kite/qa-base_rust2/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM daocloud.io/quantaxis/qaanaconda 2 | ENV TZ=Asia/Shanghai 3 | ENV DEBIAN_FRONTEND noninteractive 4 | COPY requirements.txt /requirements.txt 5 | COPY kitesetup.exp /root/kitesetup.exp 6 | # for mirrors in China 7 | # COPY pip.conf /root/.pip/pip.conf 8 | #COPY source.list /etc/apt/sources.list 9 | RUN apt install gnupg2 -y 10 | 11 | RUN wget -q https://linux.kite.com/dls/linux/current -O /root/kite.sh \ 12 | && apt-get update -y && apt-get install -y expect \ 13 | && chmod +x /root/kitesetup.exp && chmod +x /root/kite.sh \ 14 | && /root/kitesetup.exp 15 | 16 | #COPY source.list /etc/apt/sources.list 17 | RUN apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 3B4FE6ACC0B21F32 40976EAF437D05B5 && apt update && apt upgrade -y 18 | RUN apt install libc-bin debconf -y 19 | RUN apt install locales -fy 20 | RUN apt install gcc -y --force-yes \ 21 | && locale-gen zh_CN.UTF-8 \ 22 | && localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 \ 23 | && echo "LANG=zh_CN.UTF-8" > /etc/locale.conf \ 24 | && echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \ 25 | && echo "LC_ALL=zh_CN.UTF-8" >> /etc/environment 26 | 27 | WORKDIR /root/QUANTAXIS 28 | COPY . . 29 | RUN cd /root/QUANTAXIS \ 30 | && pip install -r /root/QUANTAXIS/requirements.txt -i https://pypi.doubanio.com/simple \ 31 | && pip install quantaxis-servicedetect \ 32 | && pip install quantaxis -U \ 33 | && apt-get clean -y --force-yes \ 34 | && apt-get autoclean -y --force-yes\ 35 | && apt-get autoremove -y --force-yes\ 36 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 37 | 38 | ENV LANG zh_CN.UTF-8 39 | ENV LANGUAGE zh_CN.UTF-8 40 | ENV LC_ALL zh_CN.UTF-8 41 | 42 | RUN \ 43 | cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 44 | && echo "Asia/Shangshai" > /etc/timezone 45 | 46 | # RUN \ 47 | # cd /root/ && mkdir .quantaxis && cd ~/.quantaxis && mkdir setting 48 | RUN mkdir /root/.quantaxis && mkdir /root/.quantaxis/setting 49 | -------------------------------------------------------------------------------- /docker/kite/qa-base_rust2/kitesetup.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect 2 | set timeout -1 3 | spawn /root/kite.sh 4 | expect "Press enter to continue..." 5 | send "\n" 6 | expect "Do you want to continue?" 7 | send "y\n" 8 | expect "Press enter to continue..." 9 | send "\n" 10 | expect eof 11 | -------------------------------------------------------------------------------- /docker/kite/qa-base_rust2/pip.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | index-url = http://mirrors.aliyun.com/pypi/simple/ 3 | [install] 4 | trusted-host=mirrors.aliyun.com -------------------------------------------------------------------------------- /docker/kite/qa-base_rust2/qa-base_rust2.md: -------------------------------------------------------------------------------- 1 | 最新版qa-base基础上增加了Kite Engine组件; 2 | 3 | Kite Engine组件是jupyterlab-kite插件的基础支持模块,实现对kite服务器python等通用编程语言扩展库函数索引,本地库函数索引,本地编程输入词频学习进化; 4 | 5 | Kite Engine安装过程需要人工交互,增加了kitesetup.exp自动应答脚本,就可以正常build镜像; 6 | 7 | DaoCloud现在不开放注册组织了,镜像用不了私人仓库,有需要我可以传群里; 8 | -------------------------------------------------------------------------------- /docker/kite/qa-base_rust2/requirements.txt: -------------------------------------------------------------------------------- 1 | tushare==1.2.59 2 | pytdx>==1.72 3 | -------------------------------------------------------------------------------- /docker/kite/qa-community-rust2/config: -------------------------------------------------------------------------------- 1 | [source.crates-io] 2 | registry = "https://github.com/rust-lang/crates.io-index" 3 | replace-with = 'tuna' 4 | 5 | [source.tuna] 6 | registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" 7 | 8 | 9 | [source.ustc] 10 | registry = "git://mirrors.ustc.edu.cn/crates.io-index" 11 | 12 | 13 | [source.sjtu] 14 | registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index" 15 | 16 | 17 | [source.rustcc] 18 | registry = "https://code.aliyun.com/rustcc/crates.io-index.git" -------------------------------------------------------------------------------- /docker/kite/qa-community-rust2/daily_update: -------------------------------------------------------------------------------- 1 | 18 18 * * mon-fri root /root/QUANTAXIS/config/update_future.py > /proc/1/fd/1 2>/proc/1/fd/2 2 | -------------------------------------------------------------------------------- /docker/kite/qa-community-rust2/qa-community-rust2.md: -------------------------------------------------------------------------------- 1 | UI版镜像文件; 2 | 3 | 增加kite索引库检索目录,并创建本机python库与kite索引库检索目录的软连接,使kite不需要学习即可直接索引本地库函数; 4 | 5 | 本机编程输入词频学习记录需要持久化,新增加一个kite卷; 6 | 7 | 第一次启动前创建数据卷 8 | 9 | docker volume create kite 10 | 11 | docker volume create qamg 12 | 13 | docker volume create qacode 14 | 15 | 修改期货股票两个update文件第一行解释器路径,替换为 #!/opt/conda/bin/python; 16 | -------------------------------------------------------------------------------- /docker/kite/qa-community-rust2/run-community.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 4 | 5 | jupyter lab --allow-root --notebook-dir=/root --config /root/.jupyter/jupyter_notebook_config.py & 6 | exec "$@" 7 | 8 | cd /root/qamazing_community && python -m http.server 80 9 | -------------------------------------------------------------------------------- /docker/kite/qa-community-rust2/runcelery.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo 'start backend & celery' 3 | echo $MONGODB 4 | echo $QARUN_AMQP 5 | #cat /entrypoint.sh 6 | 7 | quantaxis_webserver & 8 | qifi_manager & 9 | qavifiserver & 10 | /root/portfoliohandler & 11 | 12 | echo 'start quantaxis_run job worker' 13 | celery -A quantaxis_run worker --loglevel=info 14 | -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM qa-base_rust2:1.0 2 | #FROM daocloud.io/quantaxis/qabase:latest 3 | COPY jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl /root/QUANTAXIS/home/jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl 4 | COPY entrypoint.sh /entrypoint.sh 5 | COPY jupyter_notebook_config.py /root/.jupyter/ 6 | 7 | WORKDIR home 8 | RUN apt update && apt install make build-essential -y 9 | RUN git clone https://gitee.com/yutiansut/ta-lib \ 10 | && cd ta-lib && chmod +x ./*\ 11 | && ./configure --prefix=/usr \ 12 | && make \ 13 | && make install \ 14 | && cd .. \ 15 | && rm -rf ta-lib \ 16 | && pip install tornado==6.1.0 jupyterlab-kite -i https://pypi.doubanio.com/simple\ 17 | && pip install jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl \ 18 | && pip install xlrd peakutils quantaxis-servicedetect prompt-toolkit -i https://pypi.doubanio.com/simple\ 19 | && pip install quantaxis -U \ 20 | && pip uninstall pytdx -y \ 21 | && pip install pytdx -i https://pypi.doubanio.com/simple\ 22 | && pip install pandarallel qgrid redis aioch quantaxis-pubsub dag-factory apscheduler -i https://pypi.doubanio.com/simple\ 23 | && jupyter nbextension enable --py widgetsnbextension \ 24 | && jupyter serverextension enable --py jupyterlab 25 | 26 | RUN apt update 27 | 28 | RUN apt install -y curl\ 29 | && apt install npm -y \ 30 | && npm install npm -g \ 31 | && npm install n -g 32 | RUN n stable 33 | 34 | 35 | # RUN jupyter nbextension enable --py --sys-prefix qgrid\ 36 | # && jupyter nbextension enable --py --sys-prefix widgetsnbextension\ 37 | # && jupyter labextension install @jupyter-widgets/jupyterlab-manager\ 38 | # && jupyter labextension install qgrid 39 | 40 | 41 | RUN chmod +x /entrypoint.sh 42 | EXPOSE 8888 43 | 44 | COPY runpy.sh /root/ 45 | RUN chmod +x /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 46 | 47 | RUN chmod +x /root/runpy.sh 48 | CMD ["bash", "/root/runpy.sh"] 49 | -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 3 | -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/jupyter_notebook_config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | import os 16 | from IPython.lib import passwd 17 | 18 | c.NotebookApp.ip = '*' 19 | c.NotebookApp.port = int(os.getenv('PORT', 8888)) 20 | c.NotebookApp.open_browser = False 21 | c.MultiKernelManager.default_kernel_name = 'python3' 22 | c.NotebookApp.token = '' 23 | c.NotebookApp.password = u'sha1:a658c59030b6:910b8fff6920f60a451b19a82e465c60f4880b60' 24 | c.NotebookApp.allow_credentials = True 25 | c.NotebookApp.allow_origin = '*' 26 | c.NotebookApp.allow_remote_access = True 27 | c.NotebookApp.disable_check_xsrf = True 28 | c.NotebookApp.tornado_settings = { 'headers': { 'Content-Security-Policy': "" }} 29 | # sets a password if PASSWORD is set in the environment 30 | # if 'PASSWORD' in os.environ: 31 | # password = os.environ['PASSWORD'] 32 | # if password: 33 | # c.NotebookApp.password = passwd(password) 34 | # else: 35 | # c.NotebookApp.password = 'quantaxis' 36 | # c.NotebookApp.token = '' 37 | # del os.environ['PASSWORD'] 38 | -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/docker/kite/qa-jupyter_rust2/jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/qa-jupyter_rust2.md: -------------------------------------------------------------------------------- 1 | 上层镜像用Kite Engine版镜像qa-base_rust2:1.0 ;若该镜像已上传DaoCloud,可改用 DaoCloud 地址; 2 | 3 | 安装jupyterlab-kite,jupyterlab-kite依赖tornado==6.1.0,同时会把jupyterlab升级为3.0.9或更新版。 4 | 5 | 安装jupyterlab官方汉化包jupyterlab_language_pack_zh_CN-0.0.1.dev0-py2.py3-none-any.whl 6 | 7 | jupyterlab-kite依赖tornado==6.1.0会和web service依赖tornado==5.1.1冲突,有两个解决方案 8 | 9 | 方案一、kite版qacommunity-rust-go镜像启动UI容器,原版qacommunity-rust-go镜像启动WEB service容器,这有个问题,两个镜像的镜像层可能没办法互相复用节约磁盘空间了,一个镜像容量8GB左右; 10 | 11 | 方案二、在qa-jupyter_rust2镜像基础上分别build UI和WEB service镜像,UI镜像默认tornado==6.1.0,注释掉原dockerfile文件中tornado==5.1.1的安装语句,WEB service镜像则会安装tornado==5.1.1保证WEB service正常启动。这种情况两个镜像80%的镜像层应该可以复用,能节约6GB左右空间; 12 | -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/requirements.txt: -------------------------------------------------------------------------------- 1 | jupyter-client 2 | jupyter 3 | jupyter-core 4 | jupyterlab 5 | jupyter-console 6 | ta-lib 7 | -------------------------------------------------------------------------------- /docker/kite/qa-jupyter_rust2/runpy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 4 | jupyter lab --allow-root 5 | -------------------------------------------------------------------------------- /docker/kite/qa-web-rust2/config: -------------------------------------------------------------------------------- 1 | [source.crates-io] 2 | registry = "https://github.com/rust-lang/crates.io-index" 3 | replace-with = 'tuna' 4 | 5 | [source.tuna] 6 | registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" 7 | 8 | 9 | [source.ustc] 10 | registry = "git://mirrors.ustc.edu.cn/crates.io-index" 11 | 12 | 13 | [source.sjtu] 14 | registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index" 15 | 16 | 17 | [source.rustcc] 18 | registry = "https://code.aliyun.com/rustcc/crates.io-index.git" -------------------------------------------------------------------------------- /docker/kite/qa-web-rust2/daily_update: -------------------------------------------------------------------------------- 1 | 18 18 * * mon-fri root /root/QUANTAXIS/config/update_future.py > /proc/1/fd/1 2>/proc/1/fd/2 2 | -------------------------------------------------------------------------------- /docker/kite/qa-web-rust2/qa-web-rust2.md: -------------------------------------------------------------------------------- 1 | WEB SERVICE版镜像文件; 2 | 3 | 修改期货股票两个update文件第一行解释器路径,替换为 #!/opt/conda/bin/python; 4 | 5 | 附带web service服务中crontab进程的启动指令,拷贝到yaml文件该服务下替换原来 command:指令行 6 | 7 | command: 8 | - /bin/bash 9 | - -c 10 | - | 11 | /root/wait_for_it.sh qaeventmq:15672 12 | /root/runcelery.sh & 13 | cron -f 14 | -------------------------------------------------------------------------------- /docker/kite/qa-web-rust2/run-community.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 4 | 5 | jupyter lab --allow-root --notebook-dir=/root --config /root/.jupyter/jupyter_notebook_config.py & 6 | exec "$@" 7 | 8 | cd /root/qamazing_community && python -m http.server 80 9 | -------------------------------------------------------------------------------- /docker/kite/qa-web-rust2/runcelery.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo 'start backend & celery' 3 | echo $MONGODB 4 | echo $QARUN_AMQP 5 | #cat /entrypoint.sh 6 | 7 | quantaxis_webserver & 8 | qifi_manager & 9 | qavifiserver & 10 | /root/portfoliohandler & 11 | 12 | echo 'start quantaxis_run job worker' 13 | celery -A quantaxis_run worker --loglevel=info 14 | -------------------------------------------------------------------------------- /docker/qa-base-gitee/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8.6-buster 2 | 3 | ENV TZ=Asia/Shanghai 4 | ENV DEBIAN_FRONTEND noninteractive 5 | 6 | COPY requirements.txt /requirements.txt 7 | # for mirrors in China 8 | COPY pip.conf /root/.pip/pip.conf 9 | COPY source.list /etc/apt/sources.list 10 | RUN apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 3B4FE6ACC0B21F32 40976EAF437D05B5 && apt update 11 | 12 | RUN apt-get update \ 13 | && apt-get install -y apt-utils locales --allow\ 14 | && apt install gcc -y --allow\ 15 | && locale-gen zh_CN.UTF-8 \ 16 | && localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 \ 17 | && echo "LANG=zh_CN.UTF-8" > /etc/locale.conf \ 18 | && echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \ 19 | && echo "LC_ALL=zh_CN.UTF-8" >> /etc/environment 20 | 21 | RUN \ 22 | git clone https://gitee.com/yutiansut/QUANTAXIS \ 23 | && cd QUANTAXIS \ 24 | && pip install -r /QUANTAXIS/requirements.txt -i https://pypi.doubanio.com/simple \ 25 | && pip install -r /requirements.txt -i https://pypi.doubanio.com/simple \ 26 | && pip install quantaxis -U \ 27 | && pip install quantaxis-servicedetect\ 28 | && apt-get clean -y --allow\ 29 | && apt-get autoclean -y --allow\ 30 | && apt-get autoremove -y --allow\ 31 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 32 | 33 | ENV LANG zh_CN.UTF-8 34 | ENV LANGUAGE zh_CN.UTF-8 35 | ENV LC_ALL zh_CN.UTF-8 36 | -------------------------------------------------------------------------------- /docker/qa-base-gitee/config.ini: -------------------------------------------------------------------------------- 1 | [MONGODB] 2 | uri = mongodb://127.0.0.1:27017 3 | -------------------------------------------------------------------------------- /docker/qa-base-gitee/pip.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | index-url = http://mirrors.aliyun.com/pypi/simple/ 3 | [install] 4 | trusted-host=mirrors.aliyun.com -------------------------------------------------------------------------------- /docker/qa-base-gitee/requirements.txt: -------------------------------------------------------------------------------- 1 | tushare 2 | pytdx>=1.67 3 | -------------------------------------------------------------------------------- /docker/qa-base-gitee/source.list: -------------------------------------------------------------------------------- 1 | deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties 2 | deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted 3 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties 4 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted 5 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties 6 | deb http://mirrors.aliyun.com/ubuntu/ xenial universe 7 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe 8 | deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse 9 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse 10 | deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse 11 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties 12 | deb http://archive.canonical.com/ubuntu xenial partner 13 | deb-src http://archive.canonical.com/ubuntu xenial partner 14 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted 15 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties 16 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe 17 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse " -------------------------------------------------------------------------------- /docker/qa-base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM daocloud.io/quantaxis/qaanaconda 2 | 3 | ENV TZ=Asia/Shanghai 4 | ENV DEBIAN_FRONTEND noninteractive 5 | 6 | COPY requirements.txt /requirements.txt 7 | # for mirrors in China 8 | # COPY pip.conf /root/.pip/pip.conf 9 | #COPY source.list /etc/apt/sources.list 10 | RUN apt install gnupg2 -y 11 | 12 | #COPY source.list /etc/apt/sources.list 13 | RUN apt upgrade -y 14 | RUN apt install libc-bin debconf -y 15 | RUN apt install locales -fy 16 | RUN apt install gcc -y --force-yes \ 17 | && locale-gen zh_CN.UTF-8 \ 18 | && localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 \ 19 | && echo "LANG=zh_CN.UTF-8" > /etc/locale.conf \ 20 | && echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \ 21 | && echo "LC_ALL=zh_CN.UTF-8" >> /etc/environment 22 | 23 | 24 | WORKDIR /root/QUANTAXIS 25 | COPY . . 26 | RUN cd /root/QUANTAXIS \ 27 | && pip install -r /root/QUANTAXIS/requirements.txt -i https://pypi.doubanio.com/simple \ 28 | && pip install quantaxis-servicedetect \ 29 | && pip install quantaxis -U \ 30 | && apt-get clean -y --force-yes \ 31 | && apt-get autoclean -y --force-yes\ 32 | && apt-get autoremove -y --force-yes\ 33 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 34 | 35 | ENV LANG zh_CN.UTF-8 36 | ENV LANGUAGE zh_CN.UTF-8 37 | ENV LC_ALL zh_CN.UTF-8 38 | 39 | RUN \ 40 | cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 41 | && echo "Asia/Shangshai" > /etc/timezone 42 | 43 | # RUN \ 44 | # cd /root/ && mkdir .quantaxis && cd ~/.quantaxis && mkdir setting 45 | 46 | 47 | RUN mkdir /root/.quantaxis && mkdir /root/.quantaxis/setting 48 | -------------------------------------------------------------------------------- /docker/qa-base/pip.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | index-url = http://mirrors.aliyun.com/pypi/simple/ 3 | [install] 4 | trusted-host=mirrors.aliyun.com -------------------------------------------------------------------------------- /docker/qa-base/requirements.txt: -------------------------------------------------------------------------------- 1 | tushare 2 | pytdx>=1.67 3 | -------------------------------------------------------------------------------- /docker/qa-base/source.list: -------------------------------------------------------------------------------- 1 | deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties 2 | deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted 3 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties 4 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted 5 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties 6 | deb http://mirrors.aliyun.com/ubuntu/ xenial universe 7 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe 8 | deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse 9 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse 10 | deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse 11 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties 12 | deb http://archive.canonical.com/ubuntu xenial partner 13 | deb-src http://archive.canonical.com/ubuntu xenial partner 14 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted 15 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties 16 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe 17 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse " -------------------------------------------------------------------------------- /docker/qa-community-gpu/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:10.2-runtime-ubuntu18.04 2 | 3 | COPY setup.sh /root/setup.sh 4 | 5 | RUN cd ~ && chmod u+x setup.sh && ./setup.sh && rm -rfv setup.sh 6 | 7 | CMD ["bash", "/entrypoint.sh"] 8 | -------------------------------------------------------------------------------- /docker/qa-community-gpu/readme.txt: -------------------------------------------------------------------------------- 1 | GPU版本的qa-community,预安装各种ml/dl库 2 | 3 | gpu版仅可用于linux,使用gpu版本要求已经掌握nvidia/docker的安装和使用为基础。 4 | gpu版本使用cuda10和cudnn7,默认安装好tf、keras、xgboost三个框架的gpu版及其他ml/dl库,开袋即食 5 | 6 | 其他: 7 | web和jupyter都添加http验证防止网络扫描器,用户名密码都是quantaxis,确认网络环境安全的同学请自己注释掉auth_basic和auth_basic_user_file 8 | jupyter使用QAPUBSUB_PWD作为密码 9 | 镜像已经安装好pyecharts 0.5,在notebook模式下可正常使用,jupyterlab模式官方未适配。 10 | plt支持中文字体 -------------------------------------------------------------------------------- /docker/qa-community-rust/VUWHL/pytdx-1.72r2-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/docker/qa-community-rust/VUWHL/pytdx-1.72r2-py3-none-any.whl -------------------------------------------------------------------------------- /docker/qa-community-rust/VUWHL/quantaxis-1.10.19r1-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/docker/qa-community-rust/VUWHL/quantaxis-1.10.19r1-py3-none-any.whl -------------------------------------------------------------------------------- /docker/qa-community-rust/config: -------------------------------------------------------------------------------- 1 | [source.crates-io] 2 | registry = "https://github.com/rust-lang/crates.io-index" 3 | replace-with = 'tuna' 4 | 5 | [source.tuna] 6 | registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" 7 | 8 | 9 | [source.ustc] 10 | registry = "git://mirrors.ustc.edu.cn/crates.io-index" 11 | 12 | 13 | [source.sjtu] 14 | registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index" 15 | 16 | 17 | [source.rustcc] 18 | registry = "https://code.aliyun.com/rustcc/crates.io-index.git" -------------------------------------------------------------------------------- /docker/qa-community-rust/daily_update: -------------------------------------------------------------------------------- 1 | 18 18 * * mon-fri root /root/QUANTAXIS/config/update_all.py > /proc/1/fd/1 2>/proc/1/fd/2 2 | -------------------------------------------------------------------------------- /docker/qa-community-rust/entrypoint.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | set -e 4 | if [ ! -z "$EXTRA_PIP_PACKAGES" ]; then 5 | echo "+pip install $EXTRA_PIP_PACKAGES" 6 | pip install $EXTRA_PIP_PACKAGES 7 | fi 8 | if [ -z "$*" ]; then 9 | exec bash --login 10 | else 11 | exec "$@" 12 | fi -------------------------------------------------------------------------------- /docker/qa-community-rust/run-community.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 4 | 5 | tini-g --entrypoint.sh & 6 | 7 | jupyter lab --allow-root --notebook-dir=/root --config /root/.jupyter/jupyter_notebook_config.py & 8 | exec "$@" 9 | 10 | cd /root/qamazing_community && python -m http.server 80 -------------------------------------------------------------------------------- /docker/qa-community-rust/runcelery.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo 'start backend & celery' 3 | echo $MONGODB 4 | echo $QARUN_AMQP 5 | #cat /entrypoint.sh 6 | 7 | quantaxis_webserver & 8 | qifi_manager & 9 | qavifiserver & 10 | /root/portfoliohandler & 11 | 12 | echo 'start quantaxis_run job worker' 13 | celery -A quantaxis_run worker --loglevel=info 14 | -------------------------------------------------------------------------------- /docker/qa-eventmq/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rabbitmq:management 2 | 3 | ENV TZ=Asia/Shanghai 4 | 5 | ENV RABBITMQ_DEFAULT_USER=admin 6 | ENV RABBITMQ_DEFAULT_PASS=admin 7 | # RUN rabbitmqctl add_user guest guest \ 8 | # && rabbitmqctl set_user_tags guest administrator \ 9 | # && rabbitmqctl set_permissions -p "/" guest '.*' '.*' '.*' 10 | 11 | 12 | # RUN netstat -ano | grep 5672 13 | # RUN rabbitmqctl set_permissions -p "/" admin '.*' '.*' '.*' 14 | 15 | EXPOSE 15672 16 | EXPOSE 5672 17 | EXPOSE 4369 -------------------------------------------------------------------------------- /docker/qa-jupyter-go-r/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.7/site-packages/QUANTAXIS/QAUtil/QASetting.py 3 | -------------------------------------------------------------------------------- /docker/qa-jupyter-go-r/jupyter_notebook_config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | import os 16 | from IPython.lib import passwd 17 | 18 | c.NotebookApp.ip = '*' 19 | c.NotebookApp.port = int(os.getenv('PORT', 8888)) 20 | c.NotebookApp.open_browser = False 21 | c.MultiKernelManager.default_kernel_name = 'python3' 22 | c.NotebookApp.token = '' 23 | c.NotebookApp.notebook_dir = '~/' 24 | c.NotebookApp.password = u'sha1:a658c59030b6:910b8fff6920f60a451b19a82e465c60f4880b60' 25 | c.NotebookApp.allow_credentials = True 26 | c.NotebookApp.allow_origin = '*' 27 | c.NotebookApp.allow_remote_access = True 28 | c.NotebookApp.disable_check_xsrf = True 29 | c.NotebookApp.tornado_settings = { 'headers': { 'Content-Security-Policy': "" }} 30 | # sets a password if PASSWORD is set in the environment 31 | # if 'PASSWORD' in os.environ: 32 | # password = os.environ['PASSWORD'] 33 | # if password: 34 | # c.NotebookApp.password = passwd(password) 35 | # else: 36 | # c.NotebookApp.password = 'quantaxis' 37 | # c.NotebookApp.token = '' 38 | # del os.environ['PASSWORD'] 39 | -------------------------------------------------------------------------------- /docker/qa-jupyter-go-r/pip.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | index-url = http://mirrors.aliyun.com/pypi/simple/ 3 | [install] 4 | trusted-host=mirrors.aliyun.com -------------------------------------------------------------------------------- /docker/qa-jupyter-go-r/requirements.txt: -------------------------------------------------------------------------------- 1 | jupyter-client 2 | jupyter 3 | jupyter-core 4 | jupyterlab 5 | jupyter-console 6 | ta-lib 7 | -------------------------------------------------------------------------------- /docker/qa-jupyter-go-r/runpy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.7/site-packages/QUANTAXIS/QAUtil/QASetting.py 4 | jupyter lab --allow-root --config=/root/.jupyter/jupyter_notebook_config.py -------------------------------------------------------------------------------- /docker/qa-jupyter-go-r/source.list: -------------------------------------------------------------------------------- 1 | deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties 2 | deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted 3 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties 4 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted 5 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties 6 | deb http://mirrors.aliyun.com/ubuntu/ xenial universe 7 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe 8 | deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse 9 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse 10 | deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse 11 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties 12 | deb http://archive.canonical.com/ubuntu xenial partner 13 | deb-src http://archive.canonical.com/ubuntu xenial partner 14 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted 15 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties 16 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe 17 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse " -------------------------------------------------------------------------------- /docker/qa-jupyter/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM daocloud.io/quantaxis/qabase:latest 2 | 3 | COPY requirements.txt /requirements.txt 4 | COPY entrypoint.sh /entrypoint.sh 5 | COPY jupyter_notebook_config.py /root/.jupyter/ 6 | 7 | WORKDIR home 8 | RUN apt update && apt install make build-essential -y 9 | RUN git clone https://gitee.com/yutiansut/ta-lib \ 10 | && cd ta-lib && chmod +x ./*\ 11 | && ./configure --prefix=/usr \ 12 | && make \ 13 | && make install \ 14 | && cd .. \ 15 | && rm -rf ta-lib \ 16 | #&& pip install -r /requirements.txt -i https://pypi.doubanio.com/simple \ 17 | && pip install xlrd peakutils quantaxis-servicedetect prompt-toolkit -i https://pypi.doubanio.com/simple\ 18 | && pip install quantaxis -U \ 19 | && pip uninstall pytdx -y \ 20 | && pip install pytdx -i https://pypi.doubanio.com/simple\ 21 | && pip install pandarallel qgrid redis aioch quantaxis-pubsub dag-factory apscheduler -i https://pypi.doubanio.com/simple\ 22 | && jupyter nbextension enable --py widgetsnbextension \ 23 | && jupyter serverextension enable --py jupyterlab 24 | 25 | RUN apt update 26 | 27 | RUN apt install -y curl\ 28 | && apt install npm -y \ 29 | && npm install npm -g \ 30 | && npm install n -g 31 | RUN n stable 32 | 33 | 34 | # RUN jupyter nbextension enable --py --sys-prefix qgrid\ 35 | # && jupyter nbextension enable --py --sys-prefix widgetsnbextension\ 36 | # && jupyter labextension install @jupyter-widgets/jupyterlab-manager\ 37 | # && jupyter labextension install qgrid 38 | 39 | 40 | RUN chmod +x /entrypoint.sh 41 | EXPOSE 8888 42 | 43 | COPY runpy.sh /root/ 44 | RUN chmod +x /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 45 | 46 | RUN chmod +x /root/runpy.sh 47 | CMD ["bash", "/root/runpy.sh"] 48 | -------------------------------------------------------------------------------- /docker/qa-jupyter/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 3 | -------------------------------------------------------------------------------- /docker/qa-jupyter/jupyter_notebook_config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | import os 16 | from IPython.lib import passwd 17 | 18 | c.NotebookApp.ip = '*' 19 | c.NotebookApp.port = int(os.getenv('PORT', 8888)) 20 | c.NotebookApp.open_browser = False 21 | c.MultiKernelManager.default_kernel_name = 'python3' 22 | c.NotebookApp.token = '' 23 | c.NotebookApp.password = u'sha1:a658c59030b6:910b8fff6920f60a451b19a82e465c60f4880b60' 24 | c.NotebookApp.allow_credentials = True 25 | c.NotebookApp.allow_origin = '*' 26 | c.NotebookApp.allow_remote_access = True 27 | c.NotebookApp.disable_check_xsrf = True 28 | c.NotebookApp.tornado_settings = { 'headers': { 'Content-Security-Policy': "" }} 29 | # sets a password if PASSWORD is set in the environment 30 | # if 'PASSWORD' in os.environ: 31 | # password = os.environ['PASSWORD'] 32 | # if password: 33 | # c.NotebookApp.password = passwd(password) 34 | # else: 35 | # c.NotebookApp.password = 'quantaxis' 36 | # c.NotebookApp.token = '' 37 | # del os.environ['PASSWORD'] 38 | -------------------------------------------------------------------------------- /docker/qa-jupyter/requirements.txt: -------------------------------------------------------------------------------- 1 | jupyter-client 2 | jupyter 3 | jupyter-core 4 | jupyterlab 5 | jupyter-console 6 | ta-lib 7 | -------------------------------------------------------------------------------- /docker/qa-jupyter/runpy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 4 | jupyter lab --allow-root -------------------------------------------------------------------------------- /docker/qa-justdev/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | services: 3 | 4 | mgdb: 5 | image: daocloud.io/quantaxis/qamongo_single:latest 6 | ports: 7 | - "27017:27017" 8 | environment: 9 | - TZ=Asia/Shanghai 10 | - MONGO_INITDB_DATABASE=quantaxis 11 | volumes: 12 | - qamg:/data/db 13 | networks: 14 | qanetwork_pro: 15 | ipv4_address: 172.19.3.2 16 | restart: always 17 | 18 | qaeventmq: 19 | image: daocloud.io/quantaxis/qaeventmq:latest 20 | ports: 21 | - "15672:15672" 22 | - "5672:5672" 23 | - "4369:4369" 24 | environment: 25 | - TZ=Asia/Shanghai 26 | networks: 27 | qanetwork_pro: 28 | ipv4_address: 172.19.3.5 29 | restart: always 30 | 31 | restart: always 32 | 33 | 34 | qaredis: 35 | image: daocloud.io/quantaxis/qaredis:latest 36 | ports: 37 | - "6379:6379" 38 | environment: 39 | - TZ=Asia/Shanghai 40 | networks: 41 | qanetwork_pro: 42 | ipv4_address: 172.19.3.9 43 | 44 | # qaclickhouse: 45 | # image: daocloud.io/quantaxis/qa-clickhouse 46 | # ports: 47 | # - "9000:9000" 48 | # - "8123:8123" 49 | # - "9009:9009" 50 | # environment: 51 | # - TZ=Asia/Shanghai 52 | # networks: 53 | # qanetwork_pro: 54 | # ipv4_address: 172.19.3.10 55 | 56 | volumes: 57 | qamg: 58 | external: 59 | name: qamg 60 | qacode: 61 | external: 62 | name: qacode 63 | networks: 64 | qanetwork_pro: 65 | ipam: 66 | config: 67 | - subnet: 172.19.3.0/24 68 | gateway: 172.19.3.1 69 | -------------------------------------------------------------------------------- /docker/qa-monitor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nicolargo/glances 2 | ENV GLANCES_OPT="-w" 3 | COPY glances.conf /glances/conf/glances.conf 4 | CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT 5 | -------------------------------------------------------------------------------- /docker/qa-redis/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM library/redis:latest 2 | 3 | 4 | EXPOSE 6379 5 | CMD ["redis-server"] -------------------------------------------------------------------------------- /docker/qa-rust-base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | ENV RUSTUP_HOME=/usr/local/rustup \ 4 | CARGO_HOME=/usr/local/cargo \ 5 | PATH=/usr/local/cargo/bin:$PATH \ 6 | RUST_VERSION=1.57.0 7 | 8 | ARG CMAKE_VERSION=3.12.0 9 | WORKDIR /tmp 10 | 11 | RUN apt update && apt install wget -y 12 | RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ 13 | && tar xzf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ 14 | && mv cmake-${CMAKE_VERSION}-Linux-x86_64 /usr/local/cmake 15 | 16 | RUN set -eux; \ 17 | dpkgArch="$(dpkg --print-architecture)"; \ 18 | case "${dpkgArch##*-}" in \ 19 | amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='49c96f3f74be82f4752b8bffcf81961dea5e6e94ce1ccba94435f12e871c3bdb' ;; \ 20 | armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='5a2be2919319e8778698fa9998002d1ec720efe7cb4f6ee4affb006b5e73f1be' ;; \ 21 | arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='d93ef6f91dab8299f46eef26a56c2d97c66271cea60bf004f2f088a86a697078' ;; \ 22 | i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='e3d0ae3cfce5c6941f74fed61ca83e53d4cd2deb431b906cbd0687f246efede4' ;; \ 23 | *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \ 24 | esac; \ 25 | url="https://static.rust-lang.org/rustup/archive/1.22.1/${rustArch}/rustup-init"; \ 26 | wget "$url"; \ 27 | echo "${rustupSha256} *rustup-init" | sha256sum -c -; \ 28 | chmod +x rustup-init; \ 29 | ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \ 30 | rm rustup-init; \ 31 | chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ 32 | rustup --version; \ 33 | cargo --version; \ 34 | rustc --version; 35 | 36 | RUN set -eux; \ 37 | apt-get update; \ 38 | apt-get install -y build-essential libzmq3-dev pkg-config; -------------------------------------------------------------------------------- /docker/qa-service-future/env.env: -------------------------------------------------------------------------------- 1 | TZ=Asia/Shanghai 2 | LANG=C.UTF-8 3 | MONGO_INITDB_DATABASE=quantaxis 4 | MONGODB=mgdb 5 | QARUN=qaweb 6 | QAPUBSUB_IP=qaeventmq 7 | QAPUBSUB_PORT=5672 8 | QAPUBSUB_USER=admin 9 | QAPUBSUB_PWD=admin 10 | QARUN_AMQP=pyamqp://admin:admin@qaeventmq:5672// 11 | EventMQ_IP=qaeventmq 12 | CTPBEEuserid=133496 13 | CTPBEEpassword=QCHL1234 14 | -------------------------------------------------------------------------------- /docker/qa-service-pro/env.env: -------------------------------------------------------------------------------- 1 | TZ=Asia/Shanghai 2 | LANG=C.UTF-8 3 | POSTGRES_USER=airflow 4 | POSTGRES_PASSWORD=airflow 5 | POSTGRES_DB=airflow 6 | MONGO_INITDB_DATABASE=quantaxis 7 | MONGODB=mgdb 8 | QARUN=qaweb 9 | QAPUBSUB_IP=qaeventmq 10 | QAPUBSUB_PORT=5672 11 | QAPUBSUB_USER=admin 12 | QAPUBSUB_PWD=admin 13 | QARUN_AMQP=pyamqp://admin:admin@qaeventmq:5672// 14 | EventMQ_IP=qaeventmq 15 | LOAD_EX=n 16 | FERNET_KEY=46BKJoQYlPPOexq0OhDZnIlNepKFf87WFwLbfzqDDho= 17 | EXECUTOR=Celery 18 | CTPBEEuserid=133496 19 | CTPBEEpassword=QCHL1234 20 | -------------------------------------------------------------------------------- /docker/qa-service-rust/env.env: -------------------------------------------------------------------------------- 1 | TZ=Asia/Shanghai 2 | LANG=C.UTF-8 3 | MONGO_INITDB_DATABASE=quantaxis 4 | MONGODB=mgdb 5 | QARUN=qaweb 6 | QAPUBSUB_IP=qaeventmq 7 | QAPUBSUB_PORT=5672 8 | QAPUBSUB_USER=admin 9 | QAPUBSUB_PWD=admin 10 | QARUN_AMQP=pyamqp://admin:admin@qaeventmq:5672// 11 | EventMQ_IP=qaeventmq 12 | -------------------------------------------------------------------------------- /docker/qa-service-rust/start.bat: -------------------------------------------------------------------------------- 1 | docker network create -d bridge --subnet 172.11.0.0/24 --gateway 172.11.0.1 qa_network -------------------------------------------------------------------------------- /docker/qa-service/env.env: -------------------------------------------------------------------------------- 1 | TZ=Asia/Shanghai 2 | LANG=C.UTF-8 3 | MONGO_INITDB_DATABASE=quantaxis 4 | MONGODB=mgdb 5 | QARUN=qaweb 6 | QAPUBSUB_IP=qaeventmq 7 | QAPUBSUB_PORT=5672 8 | QAPUBSUB_USER=admin 9 | QAPUBSUB_PWD=admin 10 | QARUN_AMQP=pyamqp://admin:admin@qaeventmq:5672// 11 | EventMQ_IP=qaeventmq 12 | -------------------------------------------------------------------------------- /docker/qa-service/start.bat: -------------------------------------------------------------------------------- 1 | docker network create -d bridge --subnet 172.11.0.0/24 --gateway 172.11.0.1 qa_network -------------------------------------------------------------------------------- /docker/qa-web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM daocloud.io/quantaxis/qabase:latest 2 | 3 | COPY entrypoint.sh /entrypoint.sh 4 | 5 | WORKDIR home 6 | 7 | RUN pip install git+https://github.com/yutiansut/tornado_http2 \ 8 | && pip install quantaxis_webserver \ 9 | && pip install quantaxis -U \ 10 | && pip install tornado==5.1.0 \ 11 | && chmod +x /entrypoint.sh \ 12 | && chmod +x /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 13 | 14 | 15 | 16 | EXPOSE 8010 17 | 18 | CMD ["bash", "/entrypoint.sh"] 19 | -------------------------------------------------------------------------------- /docker/qa-web/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sed -i "s|localhost|$MONGODB|" /opt/conda/lib/python3.8/site-packages/QUANTAXIS/QAUtil/QASetting.py 3 | quantaxis_webserver -------------------------------------------------------------------------------- /docker/qaclickhouse/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM yandex/clickhouse-server 2 | 3 | 4 | EXPOSE 9000 8123 9009 5 | -------------------------------------------------------------------------------- /docker/qaservice_docker.sh: -------------------------------------------------------------------------------- 1 | echo "QUANTAXIS_DOCKER_SERVICE" 2 | 3 | mkdir quantaxis_docker && cd quantaxis_docker 4 | wget https://raw.githubusercontent.com/QUANTAXIS/QUANTAXIS/master/docker/qa-service/docker-compose.yaml 5 | docker volume create qamg 6 | docker volume create qacode 7 | # curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io 8 | docker-compose up -d 9 | -------------------------------------------------------------------------------- /examples/factoranalysis.py: -------------------------------------------------------------------------------- 1 | import QUANTAXIS as QA 2 | import pandas as pd 3 | clickhouse_port = 9001 4 | clickhouse_ip = 'localhost' 5 | clickhouse_user = 'admin' 6 | clickhouse_password = 'admin' 7 | 8 | 9 | class MA(QA.QASingleFactor_DailyBase): 10 | 11 | def finit(self): 12 | 13 | self.clientr = QA.QACKClient( 14 | clickhouse_ip, clickhouse_port, user=clickhouse_user, password=clickhouse_password) 15 | self.factor_name = 'MA5' 16 | 17 | def calc(self) -> pd.DataFrame: 18 | """ 19 | 20 | the example is just a day datasource, u can use the min data to generate a day-frequence factor 21 | 22 | the factor should be in day frequence 23 | """ 24 | 25 | codellist = self.clientr.get_stock_list().order_book_id.tolist() 26 | start = '2020-01-01' 27 | end = '2021-09-22' 28 | data = self.clientr.get_stock_day_qfq_adv(codellist, start, end) 29 | res = data.add_func(QA.QA_indicator_MA, 5) 30 | res.columns = ['factor'] 31 | return res.reset_index().dropna() 32 | 33 | 34 | feature = MA(host=clickhouse_ip, port=clickhouse_port, 35 | user=clickhouse_user, password=clickhouse_password) 36 | feature.update_to_database() 37 | 38 | """ 39 | create feature view 40 | """ 41 | fv = QA.QAFeatureView(host=clickhouse_ip, port=clickhouse_port, 42 | user=clickhouse_user, password=clickhouse_password) 43 | ma5factor = fv.get_single_factor('MA5').sort_index() 44 | 45 | 46 | """ 47 | create analysis 48 | 49 | """ 50 | fa = QA.QAFeatureAnalysis(ma5factor, host=clickhouse_ip, port=clickhouse_port, 51 | user=clickhouse_user, password=clickhouse_password) 52 | 53 | fa.create_tear_sheet() 54 | -------------------------------------------------------------------------------- /examples/qifiaccountexample.py: -------------------------------------------------------------------------------- 1 | from QUANTAXIS.QIFI.QifiAccount import QIFI_Account 2 | 3 | if __name__ == '__main__': 4 | 5 | account = QIFI_Account(username='testx', password='123456', model='BACKTEST', nodatabase=False, dbname='ck', 6 | clickhouse_port=9000, clickhouse_user='default', clickhouse_password='') 7 | 8 | """ 9 | sendorder 10 | 11 | """ 12 | account.initial() 13 | order = account.send_order("000001", 200, 20, 1, datetime='2021-09-30') 14 | 15 | 16 | """ 17 | cancel order 18 | 19 | """ 20 | #cancel = account.cancel_order(order['order_id']) 21 | 22 | 23 | """ 24 | make deal 25 | 26 | """ 27 | account.make_deal(order) 28 | res = list(account.position_qifimsg.values()) 29 | 30 | print(res[0]) 31 | 32 | account.settle() 33 | 34 | """ 35 | next day 36 | """ 37 | 38 | -------------------------------------------------------------------------------- /examples/scheduleserver.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from QUANTAXIS.QAWebServer.schedulehandler import * 4 | from QUANTAXIS.QAWebServer.server import start_server 5 | 6 | def task(job_id): 7 | print('fin', job_id, datetime.datetime.now()) 8 | if job_id == 1: 9 | print('xx1') 10 | elif job_id == '111': 11 | print('xx1') 12 | else: 13 | print('known job', job_id) 14 | 15 | 16 | scheduler = init_scheduler() 17 | 18 | 19 | class ScheduleForRunning(QASchedulerHandler): 20 | 21 | """ 22 | 添加: get http://0.0.0.0:2225/scheduler/map?action=add&job_id=11&interval=2 23 | 查询所有任务: get http://0.0.0.0:2225/scheduler/query 24 | """ 25 | 26 | def get(self): 27 | jobid = self.get_argument('jobid', 1) 28 | action = self.get_argument('action', 'addinterval') 29 | running_interval = self.get_argument('interval', 3) 30 | hour = int(self.get_argument('hour', 3)) 31 | minute = int(self.get_argument('minute', 3)) 32 | second = int(self.get_argument('second', 3)) 33 | if action == 'addinterval': 34 | scheduler.add_job(task, 'interval', 35 | seconds=running_interval, id=jobid, args=(jobid,)) 36 | elif action == 'addcron': 37 | """ 38 | http://0.0.0.0:2225/scheduler/map?action=addcron&hour=4&minute=21&second=0&jobid=z1 39 | """ 40 | scheduler.add_job(task, 'cron', hour=hour, minute=minute, second=second, 41 | id=jobid, args=(jobid,)) 42 | elif action == 'remove': 43 | """ 44 | http://0.0.0.0:2225/scheduler/map?action=remove&jobid=z1 45 | """ 46 | scheduler.remove_job(jobid) 47 | self.write({'res': 'success', 'job_id': jobid}) 48 | 49 | 50 | start_server([(r"/scheduler/map/?", ScheduleForRunning), 51 | (r"/scheduler/query", QAScheduleQuery), ], port=2225) 52 | -------------------------------------------------------------------------------- /examples/test_ckread_qifi.py: -------------------------------------------------------------------------------- 1 | # qifi sql 2 | 3 | from typing import List 4 | import clickhouse_driver 5 | 6 | 7 | class test: 8 | def __init__(self, username, trading_day): 9 | self.client = clickhouse_driver.Client(database='qifi', host='localhost', port=9000, user='default', 10 | settings={ 11 | 'insert_block_size': 100000000}, 12 | compression=True) 13 | self.qifi_id = self.get_qifiid(username, trading_day) 14 | 15 | def execute(self, sql): 16 | return self.client.query_dataframe(sql).to_dict(orient='records') 17 | 18 | def get_qifiid(self, username, trading_day): 19 | return self.client.execute( 20 | "select qifi_id from qifi.qifi where account_cookie ='{}' and trading_day ='{}'".format(username, trading_day))[0][0] 21 | 22 | def get_orders(self) -> List: 23 | res = self.execute( 24 | "select * from qifi.orders where qifi_id='{}'".format(self.qifi_id)) 25 | return res 26 | 27 | def get_trades(self) -> List: 28 | res = self.execute( 29 | "select * from qifi.trades where qifi_id='{}'".format(self.qifi_id)) 30 | return res 31 | 32 | def get_positions(self) -> List: 33 | res = self.execute( 34 | "select * from qifi.positions where qifi_id='{}'".format(self.qifi_id)) 35 | return res 36 | 37 | def get_accounts(self) -> List: 38 | res = self.execute( 39 | "select * from qifi.accounts where qifi_id='{}'".format(self.qifi_id)) 40 | return res 41 | 42 | def get_qifi(self) -> List: 43 | res = self.execute( 44 | "select * from qifi.qifi where qifi_id='{}'".format(self.qifi_id)) 45 | return res 46 | 47 | 48 | if __name__ == "__main__": 49 | t = test('testx', '2021-09-30') 50 | 51 | print(t.qifi_id) 52 | 53 | print(t.get_accounts()) 54 | print(t.get_orders()) 55 | print(t.get_positions()) 56 | print(t.get_trades()) 57 | -------------------------------------------------------------------------------- /install_afterrequirements.txt: -------------------------------------------------------------------------------- 1 | tushare 2 | pytdx>=1.67 3 | -------------------------------------------------------------------------------- /qabook/qalogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qabook/qalogo.png -------------------------------------------------------------------------------- /qalogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qalogo.png -------------------------------------------------------------------------------- /qapro-rs/database.yaml: -------------------------------------------------------------------------------- 1 | version: "2.1" 2 | services: 3 | 4 | redis: 5 | image: 'daocloud.io/quantaxis/qaredis:latest' 6 | ports: 7 | - "6379:6379" 8 | environment: 9 | - TZ=Asia/Shanghai 10 | command: ['redis-server'] 11 | restart: always 12 | networks: 13 | qanetwork_db: 14 | ipv4_address: 172.19.11.2 15 | mgdb: 16 | image: daocloud.io/quantaxis/qamongo_single:latest 17 | ports: 18 | - "27017:27017" 19 | environment: 20 | - TZ=Asia/Shanghai 21 | - MONGO_INITDB_DATABASE=quantaxis 22 | volumes: 23 | - qamg:/data/db 24 | networks: 25 | qanetwork_db: 26 | ipv4_address: 172.19.11.3 27 | restart: always 28 | 29 | qaclickhouse: 30 | image: daocloud.io/quantaxis/qa-clickhouse 31 | ports: 32 | - "9000:9000" 33 | - "8123:8123" 34 | - "9009:9009" 35 | environment: 36 | - TZ=Asia/Shanghai 37 | networks: 38 | qanetwork_db: 39 | ipv4_address: 172.19.11.4 40 | 41 | qaeventmq: 42 | image: daocloud.io/quantaxis/qaeventmq:latest 43 | ports: 44 | - "15672:15672" 45 | - "5672:5672" 46 | - "4369:4369" 47 | environment: 48 | - TZ=Asia/Shanghai 49 | networks: 50 | qanetwork_db: 51 | ipv4_address: 172.19.11.5 52 | restart: always 53 | 54 | 55 | volumes: 56 | qamg: 57 | external: 58 | name: qamg 59 | 60 | networks: 61 | qanetwork_db: 62 | ipam: 63 | config: 64 | - subnet: 172.19.11.0/24 65 | gateway: 172.19.11.1 66 | -------------------------------------------------------------------------------- /qapro-rs/example.toml: -------------------------------------------------------------------------------- 1 | [account] 2 | uri = "mongodb://127.0.0.1:27017" 3 | db = "quantaxis" 4 | 5 | [hisdata] 6 | uri = "mongodb://127.0.0.1:27017" 7 | db = "quantaxis" 8 | 9 | [realtime] 10 | uri = "amqp://admin:admin@127.0.0.1:5672/" 11 | exchange="CTPX" 12 | 13 | [order] 14 | uri = "amqp://admin:admin@127.0.0.1:5672/" 15 | exchange="QASTRATEGY" 16 | 17 | [instruct] 18 | uri = "amqp://admin:admin@127.0.0.1:5672/" 19 | exchange="INSTRUCT" 20 | routing_key="test" 21 | 22 | [ack] 23 | uri = "amqp://admin:admin@127.0.0.1:5672/" 24 | exchange="INSTRUCT_ACK" 25 | 26 | [redis] 27 | uri = "127.0.0.1:6379" 28 | db = 0 29 | [accsetup] 30 | cash_map = '{}' 31 | multiply = 1.0 32 | default = 100000.0 33 | symbol="QUANTAXIS" 34 | 35 | [backtest] 36 | start = "2020-01-01" 37 | 38 | [cli] 39 | name = [ "t00"] 40 | codes = ["300002.XSHE", "600010.XSHG"] 41 | freqs = ["5min", "15min", "30min"] 42 | params = 'default' 43 | 44 | 45 | [clickhouse] 46 | uri = "tcp://default@127.0.0.1:9000?compression=lz4&ping_timeout=42ms" 47 | 48 | 49 | [common] 50 | addr ="127.0.0.1:5000" 51 | log_level="info" 52 | key="000000000" 53 | qifi_gap=3 54 | 55 | [DataPath] 56 | # cache目录必须带/ 或者\ 57 | # /media/data/cache/ linux&mac 58 | # 59 | cache = "/media/data/cache/" 60 | cachestart = "2019-01-01" 61 | cacheend = "2021-12-25" -------------------------------------------------------------------------------- /qapro-rs/examples/api.rs: -------------------------------------------------------------------------------- 1 | use actix::Actor; 2 | 3 | use actix_redis::RedisActor; 4 | use actix_rt::Arbiter; 5 | 6 | use actix_web::{web, App, HttpServer}; 7 | use qapro_rs::qaenv::localenv::CONFIG; 8 | use qapro_rs::qahandlers::factorhandler::FactorHandler; 9 | use qapro_rs::qahandlers::realtime::Realtime; 10 | use qapro_rs::qahandlers::subunsub::{realtime_sub, realtime_unsub}; 11 | use qapro_rs::qahandlers::websocket::websocket_router; 12 | 13 | use qapro_rs::qalog::log4::init_log4; 14 | 15 | #[actix_rt::main] 16 | async fn main() -> std::io::Result<()> { 17 | init_log4("log/qarealtimepro_rs.log"); 18 | println!("{:#?}", &CONFIG.common.addr); 19 | let redis_addr = RedisActor::start(&CONFIG.redis.uri); 20 | let realtime_addr = Realtime::new(redis_addr.clone()).start(); 21 | let factor_addr = FactorHandler::new(realtime_addr.clone()).start(); 22 | HttpServer::new(move || { 23 | App::new() 24 | .data(realtime_addr.clone()) 25 | .data(factor_addr.clone()) 26 | //.service(web::scope("/ws").route("/", web::get().to(index))) 27 | .route("/ws/", web::get().to(websocket_router)) 28 | .route("/realtime_sub", web::post().to(realtime_sub)) 29 | .route("/realtime_unsub", web::post().to(realtime_unsub)) 30 | }) 31 | .bind(&CONFIG.common.addr)? 32 | .run() 33 | .await 34 | } 35 | -------------------------------------------------------------------------------- /qapro-rs/examples/factorlib.rs: -------------------------------------------------------------------------------- 1 | use qapro_rs::qaconnector::clickhouse::ckclient; 2 | use qapro_rs::qaconnector::clickhouse::ckclient::DataConnector; 3 | 4 | #[actix_rt::main] 5 | async fn main() { 6 | let c = ckclient::QACKClient::init(); 7 | 8 | let codelist = ["600010.XSHG", "300002.XSHE"]; 9 | let hisdata = c 10 | .get_stock(Vec::from(codelist), "2021-07-11", "2021-12-22", "1min") 11 | .await 12 | .unwrap(); 13 | println!("{:#?}", hisdata.to_kline()); 14 | } 15 | -------------------------------------------------------------------------------- /qapro-rs/examples/getdata.rs: -------------------------------------------------------------------------------- 1 | use actix_rt; 2 | use chrono::Local; 3 | use qapro_rs::qaconnector::clickhouse::ckclient; 4 | use qapro_rs::qaconnector::clickhouse::ckclient::DataConnector; 5 | use qapro_rs::qaenv::localenv::CONFIG; 6 | use qapro_rs::qalog::log4::init_log4; 7 | use qapro_rs::qaprotocol::mifi::qafastkline::QAKlineBase; 8 | use qapro_rs::qautil::tradedate::get_n_day_before_date9; 9 | use serde_json::Value; 10 | use std::collections::HashMap; 11 | #[actix_rt::main] 12 | async fn main() { 13 | let c = ckclient::QACKClient::init(); 14 | 15 | let codelist = ["600010.XSHG", "300002.XSHE"]; 16 | let hisdata = c 17 | .get_stock(Vec::from(codelist), "2021-07-11", "2021-12-22", "day") 18 | .await 19 | .unwrap(); 20 | 21 | println!( 22 | "QARUNTIME Start: {}", 23 | Local::now().format("%Y-%m-%d %H:%M:%S").to_string() 24 | ); 25 | 26 | init_log4(&CONFIG.cli.log_path); 27 | let names: Vec = CONFIG.cli.name.clone(); 28 | let codes: Vec = CONFIG.cli.codes.clone(); 29 | let frequences: Vec = CONFIG.cli.freqs.clone(); 30 | let json: Value = serde_json::from_str(&format!(r#"{}"#, CONFIG.cli.params.clone())) 31 | .unwrap_or(Value::String("{\"\":\"\"}".to_owned())); 32 | 33 | let count = names.len() * codes.len() * frequences.len(); 34 | // 初始化 MarketMQ 管理 35 | 36 | let mut cash_map: HashMap = 37 | serde_json::from_str(&format!(r#"{}"#, CONFIG.accsetup.cash_map)).unwrap(); 38 | let backtest_start = get_n_day_before_date9(20); 39 | 40 | let mut all_hisdata: HashMap> = HashMap::new(); 41 | for code in codes.iter() { 42 | for frequence in frequences.iter() { 43 | all_hisdata.insert(format!("mongo_{}_{}", code, frequence), hisdata.to_kline()); 44 | all_hisdata.insert(format!("redis_{}_{}", code, frequence), vec![]); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /qapro-rs/examples/qafactor.rs: -------------------------------------------------------------------------------- 1 | use actix_rt; 2 | 3 | use qapro_rs::qaconnector::clickhouse::ckclient; 4 | use qapro_rs::qaconnector::clickhouse::ckclient::DataConnector; 5 | use qapro_rs::qadatastruct::stockday::QADataStruct_StockDay; 6 | use qapro_rs::qaenv::localenv::CONFIG; 7 | use qapro_rs::qalog::log4::init_log4; 8 | use qapro_rs::qaprotocol::mifi::qafastkline::QAKlineBase; 9 | 10 | use polars::prelude::{ChunkCompare, RollingOptions}; 11 | use polars::series::ops::NullBehavior; 12 | use std::fmt::format; 13 | 14 | #[actix_rt::main] 15 | async fn main() { 16 | let c = ckclient::QACKClient::init(); 17 | let factor = c 18 | .get_factor("Asset_LR_Gr", "2021-01-01", "2021-10-01") 19 | .await 20 | .unwrap(); 21 | println!("{:#?}", factor.data); 22 | } 23 | -------------------------------------------------------------------------------- /qapro-rs/examples/wsserver.rs: -------------------------------------------------------------------------------- 1 | use actix::{Actor, StreamHandler}; 2 | use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer}; 3 | use actix_web_actors::ws; 4 | 5 | /// Define HTTP actor 6 | struct MyWs; 7 | 8 | impl Actor for MyWs { 9 | type Context = ws::WebsocketContext; 10 | } 11 | 12 | /// Handler for ws::Message message 13 | impl StreamHandler> for MyWs { 14 | fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { 15 | match msg { 16 | Ok(ws::Message::Ping(msg)) => ctx.pong(&msg), 17 | Ok(ws::Message::Text(text)) => ctx.text(text), 18 | Ok(ws::Message::Binary(bin)) => ctx.binary(bin), 19 | _ => (), 20 | } 21 | } 22 | } 23 | 24 | async fn index(req: HttpRequest, stream: web::Payload) -> Result { 25 | let resp = ws::start(MyWs {}, &req, stream); 26 | println!("{:?}", resp); 27 | resp 28 | } 29 | 30 | #[actix_web::main] 31 | async fn main() -> std::io::Result<()> { 32 | HttpServer::new(|| App::new().route("/ws/", web::get().to(index))) 33 | .bind("127.0.0.1:8080")? 34 | .run() 35 | .await 36 | } 37 | -------------------------------------------------------------------------------- /qapro-rs/readme.md: -------------------------------------------------------------------------------- 1 | ## QAPRO-RS QUANTAXIS & Rust 2 | 3 | [如果需要 simd 的加速支持, 请使用 nightly 版本的 rust] 4 | > cargo +nightly run --color=always --package qapro-rs --release example.toml 5 | 6 | 具体内容可以参见http://www.quantaxis.tech:3000/topic/61c33e858481913fcb6113d5 7 | 8 | 使用方式: 9 | 10 | 首先拉起4个api服务 11 | 12 | - clickhouse 13 | - redis 14 | - mongodb 15 | - rabbitmq 16 | 17 | 如果你本地没有这几个服务 可以使用docker-compose 拉起 18 | 19 | > docker-compose -f database.yaml up -d 20 | 21 | 如果你有部分的服务, 可以修改并删除database.yaml里的代码块 22 | 23 | 24 | 编译方式: [支持windows/ mac/ linux] 25 | 26 | cargo build --release 27 | 28 | 29 | 运行方式 30 | 31 | cargo run --release example.toml 32 | 33 | cargo run --example api --release example.toml [开启的服务在example.toml中配置 默认5000端口] 34 | 35 | 36 | 37 | 38 | @yutiansut 39 | 40 | 2021-12-22 -------------------------------------------------------------------------------- /qapro-rs/rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | max_width = 90 -------------------------------------------------------------------------------- /qapro-rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(box_patterns)] 2 | pub mod qaaccount; 3 | pub mod qaconnector; 4 | pub mod qadata; 5 | pub mod qaenv; 6 | pub mod qamarket; 7 | pub mod qaprotocol; 8 | pub mod qapubsub; 9 | pub mod qaruntime; 10 | pub mod qautil; 11 | 12 | pub mod qafuncs; 13 | pub mod qalog; 14 | pub mod qamacros; 15 | pub mod qapraser; 16 | pub mod qastrategy; 17 | 18 | pub mod qadatastruct; 19 | pub mod qafactor; 20 | pub mod qahandlers; 21 | 22 | pub mod parsers; 23 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/engine.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use crate::parsers::lang::{Lang, LangType}; 4 | use crate::parsers::planner; 5 | use crate::parsers::sql::Sql; 6 | use crate::parsers::value::PqlValue; 7 | 8 | pub fn evaluate(sql: &str, input: &str, from: &str, to: &str) -> anyhow::Result { 9 | let from_lang_type = LangType::from_str(&from)?; 10 | let to_lang_type = LangType::from_str(&to)?; 11 | let mut lang = Lang::from_as(&input, from_lang_type)?; 12 | 13 | let sql = Sql::from_str(&sql)?; 14 | 15 | let result = planner::evaluate(sql, lang.data); 16 | lang.to = to_lang_type; 17 | lang.data = result; 18 | let output = lang.to_string(true)?; 19 | 20 | Ok(output) 21 | } 22 | 23 | pub fn loads(input: &str, from: &str) -> anyhow::Result { 24 | let from_lang_type = LangType::from_str(&from)?; 25 | let lang = Lang::from_as(&input, from_lang_type)?; 26 | let value = lang.data; 27 | Ok(value) 28 | } 29 | 30 | pub fn dumps(data: PqlValue, to: &str) -> anyhow::Result { 31 | let to_lang_type = LangType::from_str(&to)?; 32 | let mut lang = Lang::default(); 33 | lang.data = data; 34 | lang.to = to_lang_type; 35 | let output = lang.to_string(true)?; 36 | Ok(output) 37 | } 38 | 39 | pub fn query_evaluate(data: PqlValue, sql: &str) -> anyhow::Result { 40 | let sql = Sql::from_str(&sql)?; 41 | let data = PqlValue::from(data); 42 | let value = planner::evaluate(sql, data); 43 | Ok(value) 44 | } 45 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/mod.rs: -------------------------------------------------------------------------------- 1 | #![feature(box_patterns)] 2 | pub mod engine; 3 | pub mod lang; 4 | pub mod models; 5 | pub mod parser; 6 | pub mod planner; 7 | pub mod pqlir_parser; 8 | pub mod sql; 9 | pub mod utils; 10 | pub mod value; 11 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/models.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | #[derive(Debug, Clone, PartialEq)] 4 | pub struct Atom { 5 | data: u64, 6 | } 7 | 8 | impl From for Atom { 9 | fn from(v: u64) -> Self { 10 | Self { data: v } 11 | } 12 | } 13 | 14 | impl fmt::Display for Atom { 15 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 16 | writeln!(f, "{{"); 17 | writeln!(f, " '_1': {},", self.data); 18 | writeln!(f, "}}"); 19 | Ok(()) 20 | } 21 | } 22 | 23 | #[derive(Debug, Clone, PartialEq)] 24 | pub struct Array { 25 | data: Vec, 26 | } 27 | 28 | impl From<&[u64]> for Array { 29 | fn from(v: &[u64]) -> Self { 30 | Self { 31 | data: v.to_vec().into_iter().map(Atom::from).collect::>(), 32 | } 33 | } 34 | } 35 | 36 | impl fmt::Display for Array { 37 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 38 | writeln!(f, "<<"); 39 | for atom in self.data.iter() { 40 | writeln!(f, " {},", atom); 41 | } 42 | writeln!(f, ">>")?; 43 | Ok(()) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/parser/func.rs: -------------------------------------------------------------------------------- 1 | use nom::branch::alt; 2 | use nom::bytes::complete::{ tag_no_case}; 3 | use nom::character::complete::char; 4 | use nom::combinator::cut; 5 | use nom::sequence::{preceded, terminated, tuple}; 6 | use nom::IResult; 7 | 8 | use crate::parsers::sql::Expr; 9 | use crate::parsers::sql::Func; 10 | 11 | use crate::parsers::parser::{parse_expr, whitespace}; 12 | 13 | pub fn function(input: &str) -> IResult<&str, Expr> { 14 | let (input, (funcname, _, expr)) = tuple(( 15 | preceded( 16 | whitespace, 17 | alt(( 18 | tag_no_case("count"), 19 | tag_no_case("upper"), 20 | tag_no_case("lower"), 21 | tag_no_case("ceil"), 22 | tag_no_case("floor"), 23 | tag_no_case("round"), 24 | )), 25 | ), 26 | char('('), 27 | cut(terminated( 28 | preceded(whitespace, parse_expr), 29 | preceded(whitespace, char(')')), 30 | )), 31 | ))(input)?; 32 | 33 | let func = match funcname.to_lowercase().as_str() { 34 | "count" => Func::Count(expr), 35 | "upper" => Func::Upper(expr), 36 | _ => todo!(), 37 | }; 38 | 39 | let res = Expr::Func(Box::new(func)); 40 | 41 | Ok((input, res)) 42 | } 43 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/parser/keywords.rs: -------------------------------------------------------------------------------- 1 | use nom::branch::alt; 2 | use nom::bytes::complete::{tag, tag_no_case}; 3 | 4 | use nom::combinator::peek; 5 | 6 | use nom::sequence::terminated; 7 | 8 | use nom::IResult; 9 | 10 | use crate::parsers::parser::elements::eof; 11 | 12 | fn keyword_follow_char(input: &str) -> IResult<&str, &str> { 13 | peek(alt(( 14 | tag(" "), 15 | tag("\n"), 16 | tag(";"), 17 | tag("("), 18 | tag(")"), 19 | tag("\t"), 20 | tag(","), 21 | tag("="), 22 | eof, 23 | )))(input) 24 | } 25 | 26 | pub fn sql_keyword(input: &str) -> IResult<&str, &str> { 27 | alt(( 28 | terminated(tag_no_case("SELECT"), keyword_follow_char), 29 | terminated(tag_no_case("FROM"), keyword_follow_char), 30 | terminated(tag_no_case("WHERE"), keyword_follow_char), 31 | terminated(tag_no_case("ORDER"), keyword_follow_char), 32 | terminated(tag_no_case("BY"), keyword_follow_char), 33 | terminated(tag_no_case("ASC"), keyword_follow_char), 34 | terminated(tag_no_case("DESC"), keyword_follow_char), 35 | terminated(tag_no_case("LIMIT"), keyword_follow_char), 36 | terminated(tag_no_case("OFFSET"), keyword_follow_char), 37 | ))(input) 38 | } 39 | 40 | pub fn clause_delimiter(input: &str) -> IResult<&str, &str> { 41 | alt((sql_keyword, eof))(input) 42 | } 43 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/parser/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod clauses; 2 | pub mod elements; 3 | pub mod expressions; 4 | pub mod func; 5 | pub mod keywords; 6 | pub mod math; 7 | pub mod select_statement; 8 | pub mod values; 9 | 10 | use nom::branch::alt; 11 | use nom::combinator::map; 12 | use nom::number::complete::double; 13 | use nom::IResult; 14 | use ordered_float::OrderedFloat; 15 | 16 | use crate::parsers::value::PqlValue; 17 | pub use elements::{float_number, string_allowed_in_field, whitespace}; 18 | pub use expressions::parse_expr; 19 | pub use expressions::parse_field; 20 | pub use expressions::parse_path_as_expr; 21 | 22 | pub fn parse_value(input: &str) -> IResult<&str, PqlValue> { 23 | alt(( 24 | map(elements::string, |s| PqlValue::Str(s.to_string())), 25 | map(double, |f| PqlValue::Float(OrderedFloat(f as f64))), 26 | ))(input) 27 | } 28 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/parser/values.rs: -------------------------------------------------------------------------------- 1 | use nom::character::complete::multispace0; 2 | use nom::{ 3 | character::complete::{char, digit1}, 4 | combinator::cut, 5 | error::context, 6 | multi::separated_list0, 7 | sequence::{preceded, terminated}, 8 | IResult, 9 | }; 10 | 11 | pub fn array<'a>(input: &'a str) -> IResult<&'a str, Vec> { 12 | let (input, res) = context( 13 | "array", 14 | preceded( 15 | char('['), 16 | preceded( 17 | multispace0, 18 | cut(terminated( 19 | separated_list0(char(','), preceded(multispace0, digit1)), 20 | preceded(multispace0, char(']')), 21 | )), 22 | ), 23 | ), 24 | )(input)?; 25 | 26 | let r = res 27 | .iter() 28 | .map(|s| s.parse::().unwrap()) 29 | .collect::>(); 30 | 31 | Ok((input, r)) 32 | } 33 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/planner/drain.rs: -------------------------------------------------------------------------------- 1 | use crate::parsers::sql::Env; 2 | 3 | use crate::parsers::sql::Field; 4 | 5 | #[derive(Debug, Default, Clone)] 6 | pub struct Drain(pub Vec); 7 | 8 | impl Drain { 9 | pub fn execute(self, env: &mut Env) { 10 | for field in self.0 { 11 | if let Some(alias) = field.alias { 12 | env.insert(&alias, &field.expr); 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/planner/eval.rs: -------------------------------------------------------------------------------- 1 | pub use crate::parsers::planner::LogicalPlan; 2 | pub use crate::parsers::sql::clause::Limit; 3 | pub use crate::parsers::sql::clause::OrderBy; 4 | use crate::parsers::sql::Env; 5 | use crate::parsers::sql::Expr; 6 | use crate::parsers::sql::Sql; 7 | use crate::parsers::value::PqlValue; 8 | 9 | pub fn evaluate<'a>(sql: Sql, data: PqlValue) -> PqlValue { 10 | let mut env = Env::default(); 11 | env.insert("", &Expr::from(data)); 12 | let plan = LogicalPlan::from(sql); 13 | let result = plan.execute(&mut env); 14 | result 15 | } 16 | 17 | #[cfg(test)] 18 | mod tests { 19 | use std::str::FromStr; 20 | 21 | use crate::parsers::planner::LogicalPlan; 22 | use crate::parsers::sql::Env; 23 | use crate::parsers::sql::Sql; 24 | use crate::parsers::value::PqlValue; 25 | 26 | #[test] 27 | fn test_rename() -> anyhow::Result<()> { 28 | let sql = Sql::from_str( 29 | r#" 30 | SELECT e.id, 31 | e.name AS employeeName, 32 | e.title AS title 33 | FROM 34 | { 35 | 'employees': << 36 | { 'id': 3, 'name': 'Bob Smith', 'title': null }, 37 | { 'id': 4, 'name': 'Susan Smith', 'title': 'Dev Mgr' }, 38 | { 'id': 6, 'name': 'Jane Smith', 'title': 'Software Eng 2'} 39 | >> 40 | } AS hr, 41 | hr.employees e 42 | LIMIT 2 43 | "#, 44 | )?; 45 | 46 | let plan = LogicalPlan::from(sql); 47 | let mut env = Env::default(); 48 | let res = plan.execute(&mut env); 49 | 50 | assert_eq!( 51 | res, 52 | PqlValue::from_str( 53 | r#" 54 | [ 55 | { 'id': 3, 'employeeName': 'Bob Smith', 'title': null }, 56 | { 'id': 4, 'employeeName': 'Susan Smith', 'title': 'Dev Mgr' } 57 | ] 58 | "# 59 | )? 60 | ); 61 | 62 | Ok(()) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/planner/mod.rs: -------------------------------------------------------------------------------- 1 | mod drain; 2 | mod eval; 3 | pub mod filter; 4 | mod logical_plan; 5 | pub mod project; 6 | 7 | pub use crate::parsers::sql::clause::Limit; 8 | pub use crate::parsers::sql::clause::OrderBy; 9 | pub use crate::parsers::sql::WhereCond; 10 | 11 | pub use drain::Drain; 12 | pub use eval::evaluate; 13 | pub use filter::Filter; 14 | pub use logical_plan::LogicalPlan; 15 | pub use project::Projection; 16 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/sql/field.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use crate::parsers::parser; 4 | use crate::parsers::sql::Env; 5 | use crate::parsers::sql::Expr; 6 | use crate::parsers::value::PqlValue; 7 | 8 | #[derive(Debug, Default, Clone, PartialEq)] 9 | pub struct Field { 10 | pub expr: Expr, 11 | pub alias: Option, 12 | } 13 | 14 | impl FromStr for Field { 15 | type Err = anyhow::Error; 16 | 17 | fn from_str(s: &str) -> anyhow::Result { 18 | match parser::expressions::parse_field(s) { 19 | Ok((_, field)) => Ok(field), 20 | Err(nom::Err::Error(err)) => { 21 | eprint!("{:#?}", err); 22 | anyhow::bail!("failed") 23 | } 24 | _ => todo!(), 25 | } 26 | } 27 | } 28 | 29 | impl Field { 30 | pub fn expand_fullpath(&self, env: &Env) -> Self { 31 | Self { 32 | expr: self.expr.expand_fullpath(&env), 33 | alias: self.alias.to_owned(), 34 | } 35 | } 36 | 37 | pub fn evaluate(self, env: &Env) -> PqlValue { 38 | let value = self.expr.eval(&env); 39 | value 40 | } 41 | 42 | pub fn rename(self) -> (String, Expr) { 43 | if let Some(alias) = self.alias { 44 | (alias, self.expr) 45 | } else { 46 | let alias = match &self.expr { 47 | Expr::Selector(selector) => selector.to_vec().last().unwrap().to_string(), 48 | _ => todo!(), 49 | }; 50 | (alias, self.expr) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/sql/func.rs: -------------------------------------------------------------------------------- 1 | use crate::parsers::sql::Expr; 2 | 3 | #[derive(Debug, Clone, PartialEq)] 4 | pub enum Func { 5 | Count(Expr), 6 | Upper(Expr), 7 | } 8 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/sql/mod.rs: -------------------------------------------------------------------------------- 1 | mod env; 2 | mod expr; 3 | mod field; 4 | mod func; 5 | mod selector; 6 | mod sql; 7 | mod utils; 8 | mod where_cond; 9 | 10 | pub use env::Env; 11 | pub use expr::Expr; 12 | pub use field::Field; 13 | pub use func::Func; 14 | pub use selector::Selector; 15 | pub use selector::SelectorNode; 16 | pub use sql::Sql; 17 | pub use where_cond::re_from_str; 18 | pub use where_cond::WhereCond; 19 | 20 | pub mod clause { 21 | #[derive(Debug, Default, Clone, PartialEq)] 22 | pub struct OrderBy { 23 | pub label: String, 24 | pub is_asc: bool, 25 | } 26 | 27 | #[derive(Debug, Default, Clone, PartialEq)] 28 | pub struct Limit { 29 | pub limit: u64, 30 | pub offset: u64, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/sql/sql.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use crate::parsers::parser; 4 | pub use crate::parsers::sql::clause::Limit; 5 | pub use crate::parsers::sql::clause::OrderBy; 6 | use crate::parsers::sql::Field; 7 | pub use crate::parsers::sql::WhereCond; 8 | 9 | #[derive(Debug, Default, Clone, PartialEq)] 10 | pub struct Sql { 11 | pub select_clause: Vec, 12 | pub calc_clause: Vec, 13 | pub from_clause: Vec, 14 | pub left_join_clause: Vec, 15 | pub where_clause: Option>, 16 | pub orderby: Option, 17 | pub limit: Option, 18 | } 19 | 20 | impl FromStr for Sql { 21 | type Err = anyhow::Error; 22 | 23 | fn from_str(s: &str) -> anyhow::Result { 24 | parser::select_statement::from_str(s) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/sql/utils.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/sql/where_cond.rs: -------------------------------------------------------------------------------- 1 | use crate::parsers::sql::Env; 2 | use crate::parsers::sql::Expr; 3 | use crate::parsers::sql::Selector; 4 | use crate::parsers::value::PqlValue; 5 | 6 | #[derive(Debug, Clone, PartialEq)] 7 | pub enum WhereCond { 8 | Eq { expr: Expr, right: PqlValue }, 9 | Neq { expr: Expr, right: PqlValue }, 10 | Like { expr: Expr, right: String }, 11 | } 12 | 13 | impl Default for WhereCond { 14 | fn default() -> Self { 15 | Self::Eq { 16 | expr: Expr::default(), 17 | right: PqlValue::default(), 18 | } 19 | } 20 | } 21 | 22 | impl WhereCond { 23 | pub fn as_expr(&self) -> Expr { 24 | match &self { 25 | Self::Eq { expr, right: _ } => expr.to_owned(), 26 | Self::Neq { expr, right: _ } => expr.to_owned(), 27 | Self::Like { expr, right: _ } => expr.to_owned(), 28 | } 29 | } 30 | 31 | pub fn expand_fullpath(self, env: &Env) -> Self { 32 | match self { 33 | Self::Eq { expr, right } => Self::Eq { 34 | expr: expr.expand_fullpath(env), 35 | right, 36 | }, 37 | Self::Neq { expr, right } => Self::Eq { 38 | expr: expr.expand_fullpath(env), 39 | right, 40 | }, 41 | Self::Like { expr, right } => Self::Like { 42 | expr: expr.expand_fullpath(env), 43 | right, 44 | }, 45 | } 46 | } 47 | 48 | pub fn to_path(&self) -> Option { 49 | self.as_expr().to_path() 50 | } 51 | } 52 | 53 | pub fn re_from_str(pattern: &str) -> regex::Regex { 54 | let regex_pattern = match (pattern.starts_with("%"), pattern.ends_with("%")) { 55 | (true, true) => { 56 | format!("{}", pattern.trim_start_matches("%").trim_end_matches("%")) 57 | } 58 | (true, false) => format!("{}$", pattern.trim_start_matches("%")), 59 | (false, true) => format!("^{}", pattern.trim_end_matches("%")), 60 | (false, false) => format!("^{}$", pattern), 61 | }; 62 | let re = regex::Regex::new(®ex_pattern).unwrap(); 63 | re 64 | } 65 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/utils/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | pub fn split_parent_children(sss_org: Vec>) -> (Vec, Vec>) { 4 | let mut sss = sss_org.clone(); 5 | let mut common = Vec::::new(); 6 | 'a: loop { 7 | let mut set = HashSet::::new(); 8 | let mut vec = Vec::>::new(); 9 | for ss in sss.into_iter() { 10 | if let Some((first, tail)) = ss.split_first() { 11 | set.insert(first.to_string()); 12 | vec.push(tail.to_vec()); 13 | } else { 14 | break 'a; 15 | } 16 | if set.len() > 1 { 17 | break 'a; 18 | }; 19 | } 20 | if let Some(s) = set.iter().next() { 21 | common.push(s.to_string()); 22 | } else { 23 | break 'a; 24 | } 25 | sss = vec; 26 | } 27 | 28 | let n = common.len(); 29 | let rest_sss = sss_org 30 | .into_iter() 31 | .map(|ss| { 32 | let (_, right) = ss.split_at(n); 33 | right.to_owned() 34 | }) 35 | .collect::>(); 36 | (common, rest_sss) 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::split_parent_children; 42 | 43 | #[test] 44 | fn eq() { 45 | let ss0 = vec!["hr".to_owned(), "employeesNest".to_owned(), "id".to_owned()]; 46 | let ss1 = vec![ 47 | "hr".to_owned(), 48 | "employeesNest".to_owned(), 49 | "name".to_owned(), 50 | ]; 51 | let ss2 = vec![ 52 | "hr".to_owned(), 53 | "employeesNest".to_owned(), 54 | "projects".to_owned(), 55 | "name".to_owned(), 56 | ]; 57 | 58 | let res = split_parent_children(vec![ss0, ss1, ss2]); 59 | assert_eq!( 60 | res, 61 | ( 62 | vec!["hr".to_owned(), "employeesNest".to_owned(),], 63 | vec![ 64 | vec!["id".to_owned(),], 65 | vec!["name".to_owned(),], 66 | vec!["projects".to_owned(), "name".to_owned(),], 67 | ] 68 | ) 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /qapro-rs/src/parsers/value/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod json_value; 2 | mod pql_value; 3 | mod pql_vector; 4 | 5 | 6 | pub mod table; 7 | mod toml_value; 8 | 9 | pub use json_value::{BJsonValue, JsonValue}; 10 | pub use pql_value::{BPqlValue, PqlValue}; 11 | pub use pql_vector::PqlVector; 12 | pub use toml_value::TomlValue; 13 | -------------------------------------------------------------------------------- /qapro-rs/src/qaaccount/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod account; 2 | pub mod marketpreset; 3 | pub mod order; 4 | pub mod position; 5 | pub mod transaction; 6 | -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/clickhouse/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ckclient; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod clickhouse; 2 | pub mod mongo; 3 | 4 | pub mod redis; 5 | //HISTORY |REALTIME 两种场景需要的代码并不一致 6 | -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/mongo/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mongoclient; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/parquet/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod parquetclient; -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/parquet/parquetclient.rs: -------------------------------------------------------------------------------- 1 | //! Provide storage statistics for parquet files 2 | extern crate parquet; 3 | use parquet::{ 4 | file::reader::{FileReader, SerializedFileReader}, 5 | record::{RecordWriter, Row}, 6 | schema, 7 | }; 8 | 9 | use std::fs::File; 10 | use std::path::Path; 11 | 12 | pub struct QAParquetClient { 13 | filepath: String, 14 | } 15 | 16 | impl QAParquetClient { 17 | pub fn new(filepath: String) -> QAParquetClient { 18 | QAParquetClient { filepath } 19 | } 20 | pub fn get_data(&self) -> Vec { 21 | let mut data: Vec = vec![]; 22 | let file = File::open(&Path::new(&self.filepath)).unwrap(); 23 | let reader = SerializedFileReader::new(file).unwrap(); 24 | let mut iter = reader.get_row_iter(None).unwrap(); 25 | while let Some(record) = iter.next() { 26 | data.push(record); 27 | } 28 | data 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/rabbitmq/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qaconnector/rabbitmq/mod.rs -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/rabbitmq/rmqclient.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qaconnector/rabbitmq/rmqclient.rs -------------------------------------------------------------------------------- /qapro-rs/src/qaconnector/redis/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod redisclient; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadata/arrowbase.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadata/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod arrowbase; 2 | pub mod datafunc; 3 | pub mod resample; 4 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/factorstruct.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::{ 2 | CsvReader, DataFrame, DataType, Field, NamedFrom, ParquetReader, Result as PolarResult, 3 | RollingOptions, Schema, SerReader, Series, 4 | }; 5 | 6 | fn QADataStruct_Factor_schema() -> Schema { 7 | Schema::new(vec![ 8 | Field::new("date", DataType::Utf8), 9 | Field::new("order_book_id", DataType::Utf8), 10 | Field::new("factor", DataType::Float32), 11 | ]) 12 | } 13 | 14 | // same with python model :: // qafactor Daily struct 15 | pub struct QADataStruct_Factor { 16 | pub data: DataFrame, 17 | name: String, 18 | } 19 | 20 | impl QADataStruct_Factor { 21 | pub fn new_from_vec( 22 | date: Vec, 23 | order_book_id: Vec, 24 | factor: Vec, 25 | factorname: String, 26 | ) -> Self { 27 | let dateS = Series::new("date", &date); 28 | 29 | let order_book_idS = Series::new("order_book_id", &order_book_id); 30 | let factorS = Series::new("factor", &factor); 31 | let df = DataFrame::new(vec![dateS, order_book_idS, factorS]).unwrap(); 32 | Self { 33 | data: df 34 | .sort(&["date", "order_book_id"], vec![false, false]) 35 | .unwrap(), 36 | name: factorname, 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/futureday.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/futuremin.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod futureday; 2 | pub mod futuremin; 3 | pub mod stockadj; 4 | pub mod stockblock; 5 | pub mod stockday; 6 | pub mod stockl1snapshot; 7 | pub mod stockl2snapshot; 8 | pub mod stockmin; 9 | 10 | pub mod factorstruct; 11 | pub mod stocklist; 12 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/stockadj.rs: -------------------------------------------------------------------------------- 1 | use crate::qaenv::localenv::CONFIG; 2 | 3 | use polars::prelude::{ 4 | CsvReader, DataFrame, DataType, Field, NamedFrom, ParquetReader, ParquetWriter, 5 | Result as PolarResult, RollingOptions, Schema, SerReader, Series, 6 | }; 7 | use std::fs::File; 8 | 9 | fn QADataStruct_StockAdj_schema() -> Schema { 10 | Schema::new(vec![ 11 | Field::new("date", DataType::Utf8), 12 | Field::new("order_book_id", DataType::Utf8), 13 | Field::new("adj", DataType::Float32), 14 | ]) 15 | } 16 | pub struct QADataStruct_StockAdj { 17 | pub data: DataFrame, 18 | name: String, 19 | } 20 | 21 | impl QADataStruct_StockAdj { 22 | pub fn new_from_vec(date: Vec, order_book_id: Vec, adj: Vec) -> Self { 23 | let dateS = Series::new("date", &date); 24 | 25 | let order_book_idS = Series::new("order_book_id", &order_book_id); 26 | let adjS = Series::new("adj", &adj); 27 | let df = DataFrame::new(vec![dateS, order_book_idS, adjS]).unwrap(); 28 | Self { 29 | data: df 30 | .sort(&["date", "order_book_id"], vec![false, false]) 31 | .unwrap(), 32 | name: "stockadj".to_string(), 33 | } 34 | } 35 | pub fn new_from_parquet(path: &str) -> Self { 36 | let file = File::open(path).expect("Cannot open file."); 37 | let df = ParquetReader::new(file).finish().unwrap(); 38 | Self { 39 | data: df, 40 | name: "stockadj".to_string(), 41 | } 42 | } 43 | 44 | pub fn save_cache(&mut self) { 45 | let cachepath = format!("{}stockadj.parquet", &CONFIG.DataPath.cache); 46 | let file = File::create(cachepath).expect("could not create file"); 47 | 48 | ParquetWriter::new(file).finish(&self.data); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/stockblock.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/stockl1snapshot.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/stockl2snapshot.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/stocklist.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::{ 2 | CsvReader, DataFrame, DataType, Field, NamedFrom, ParquetReader, Result as PolarResult, 3 | RollingOptions, Schema, SerReader, Series, 4 | }; 5 | 6 | ///┌─order_book_id─┬─industry_code─┬─market_tplus─┬─symbol─┬─special_type─┬─exchange─┬─status─┬─type─┬─de_listed_date─┬─listed_date─┬─sector_code_name─┬─abbrev_symbol─┬─sector_code─┬─round_lot─┬─trading_hours───────────┬─board_type─┬─industry_name────────┬─issue_price─┬─trading_code─┬─purchasedate─┐ 7 | 8 | fn QADataStruct_StockAdj_schema() -> Schema { 9 | Schema::new(vec![ 10 | Field::new("order_book_id", DataType::Utf8), 11 | Field::new("listed_date", DataType::Utf8), 12 | Field::new("de_listed_date", DataType::Utf8), 13 | Field::new("symbol", DataType::Utf8), 14 | ]) 15 | } 16 | pub struct QADataStruct_StockList { 17 | pub data: DataFrame, 18 | name: String, 19 | } 20 | 21 | impl QADataStruct_StockList { 22 | pub fn new_from_vec( 23 | order_book_id: Vec, 24 | listed_date: Vec, 25 | delist_date: Vec, 26 | symbol: Vec, 27 | ) -> Self { 28 | let order_book_id_S = Series::new("order_book_id", order_book_id); 29 | let listed_date_S = Series::new("listed_date", listed_date); 30 | let delist_date_S = Series::new("delist_date", delist_date); 31 | 32 | let symbol_S = Series::new("symbol", symbol); 33 | let df = DataFrame::new(vec![ 34 | order_book_id_S, 35 | listed_date_S, 36 | delist_date_S, 37 | symbol_S, 38 | ]) 39 | .unwrap(); 40 | 41 | QADataStruct_StockList { 42 | data: df, 43 | name: "stocklist".to_string(), 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /qapro-rs/src/qadatastruct/stockmin.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qaenv/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod localenv; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qaexec/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod qaschedule; 2 | pub mod qacron; 3 | pub mod qadag; 4 | -------------------------------------------------------------------------------- /qapro-rs/src/qaexec/qacron/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qaexec/qacron/mod.rs -------------------------------------------------------------------------------- /qapro-rs/src/qaexec/qadag/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qaexec/qadag/mod.rs -------------------------------------------------------------------------------- /qapro-rs/src/qaexec/qaschedule/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qaexec/qaschedule/mod.rs -------------------------------------------------------------------------------- /qapro-rs/src/qafactor/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod factorbacktest; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qafuncs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod qafactor; 2 | pub mod qaindicator; 3 | -------------------------------------------------------------------------------- /qapro-rs/src/qafuncs/qafactor/hzfactor.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qafuncs/qafactor/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod hzfactor; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qafuncs/qaindicator/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qahandlers/factorhandler.rs: -------------------------------------------------------------------------------- 1 | use actix::prelude::*; 2 | 3 | use crate::qaenv::localenv::CONFIG; 4 | use crate::qahandlers::realtime::{Realtime, RegisterFactor, RoomMessage}; 5 | use crate::qahandlers::state::WSRsp; 6 | use actix_redis::RedisActor; 7 | use std::collections::HashMap; 8 | use std::time::Duration; 9 | 10 | pub struct FactorHandler { 11 | pub realtime_addr: Addr, 12 | } 13 | 14 | impl FactorHandler { 15 | pub fn new(realtime_addr: Addr) -> Self { 16 | Self { realtime_addr } 17 | } 18 | 19 | pub fn run_int(&mut self) { 20 | let sock = WSRsp::ok("xxxxtest", "realtime_pub").to_string(); 21 | self.realtime_addr.do_send(RoomMessage { 22 | room: "factorx".to_string(), 23 | msg: sock, 24 | }); 25 | } 26 | } 27 | 28 | impl Actor for FactorHandler { 29 | type Context = Context; 30 | 31 | fn started(&mut self, ctx: &mut Self::Context) { 32 | self.realtime_addr 33 | .do_send(RegisterFactor(ctx.address().clone())); 34 | 35 | ctx.run_interval(Duration::from_secs(CONFIG.common.qifi_gap), |act, ctx| { 36 | println!("account_polling query"); 37 | act.run_int(); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /qapro-rs/src/qahandlers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod factorhandler; 2 | pub mod realtime; 3 | pub mod state; 4 | pub mod subunsub; 5 | pub mod websocket; 6 | pub mod wshandle; 7 | -------------------------------------------------------------------------------- /qapro-rs/src/qahandlers/state.rs: -------------------------------------------------------------------------------- 1 | extern crate serde_json; 2 | 3 | use serde::Serialize; 4 | 5 | #[derive(Serialize)] 6 | pub struct Rsp { 7 | code: i32, 8 | data: T, 9 | msg: String, 10 | } 11 | 12 | impl Rsp 13 | where 14 | T: Serialize, 15 | { 16 | pub fn to_string(&self) -> String { 17 | serde_json::to_string(self).unwrap() 18 | } 19 | 20 | pub fn ok(data: T, msg: &str) -> Self { 21 | Self { 22 | code: 200, 23 | data, 24 | msg: msg.to_owned(), 25 | } 26 | } 27 | 28 | pub fn fail(data: T, msg: &str) -> Self { 29 | Self { 30 | code: 400, 31 | data, 32 | msg: msg.to_owned(), 33 | } 34 | } 35 | 36 | pub fn error(data: T, msg: &str) -> Self { 37 | Self { 38 | code: 500, 39 | data, 40 | msg: msg.to_owned(), 41 | } 42 | } 43 | 44 | pub fn not_found(data: T, msg: &str) -> Self { 45 | Self { 46 | code: 404, 47 | data, 48 | msg: msg.to_owned(), 49 | } 50 | } 51 | } 52 | 53 | #[derive(Serialize)] 54 | pub struct WSRsp { 55 | data: T, 56 | topic: String, 57 | code: i32, 58 | } 59 | 60 | impl WSRsp 61 | where 62 | T: Serialize, 63 | { 64 | pub fn ok(data: T, topic: &str) -> Self { 65 | Self { 66 | code: 200, 67 | data, 68 | topic: topic.to_owned(), 69 | } 70 | } 71 | 72 | pub fn fail(data: T, topic: &str) -> Self { 73 | Self { 74 | code: 400, 75 | data, 76 | topic: topic.to_owned(), 77 | } 78 | } 79 | 80 | pub fn error(data: T, topic: &str) -> Self { 81 | Self { 82 | code: 500, 83 | data, 84 | topic: topic.to_owned(), 85 | } 86 | } 87 | 88 | pub fn to_string(&self) -> String { 89 | serde_json::to_string(self).unwrap() 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /qapro-rs/src/qahandlers/subunsub.rs: -------------------------------------------------------------------------------- 1 | use crate::qahandlers::realtime::{Join, Leave, Realtime, RoomType}; 2 | use crate::qahandlers::state::Rsp; 3 | use actix::Addr; 4 | 5 | use actix_web::{web, HttpRequest, HttpResponse}; 6 | use serde::{Deserialize, Serialize}; 7 | 8 | #[derive(Serialize, Clone, Debug, Deserialize)] 9 | pub struct SubscribeForm { 10 | pub sid: String, 11 | pub room: String, 12 | } 13 | 14 | #[derive(Serialize, Clone, Debug, Deserialize)] 15 | pub struct UnSubscribeForm { 16 | pub sid: String, 17 | pub room: String, 18 | } 19 | 20 | pub async fn realtime_sub( 21 | r: HttpRequest, 22 | form: web::Json, 23 | addr: web::Data>, 24 | ) -> HttpResponse { 25 | if let Ok(res) = addr 26 | .send(Join { 27 | id: form.sid.clone(), 28 | room: form.room.clone(), 29 | room_type: RoomType::Factor, 30 | }) 31 | .await 32 | { 33 | if res { 34 | return HttpResponse::Ok().json(Rsp::ok("", "订阅成功")); 35 | } 36 | } 37 | HttpResponse::Ok().json(Rsp::fail("", "订阅失败")) 38 | } 39 | 40 | pub async fn realtime_unsub( 41 | r: HttpRequest, 42 | form: web::Json, 43 | addr: web::Data>, 44 | ) -> HttpResponse { 45 | if let Ok(res) = addr 46 | .send(Leave { 47 | id: form.sid.clone(), 48 | room: form.room.clone(), 49 | room_type: RoomType::Factor, 50 | }) 51 | .await 52 | { 53 | if res { 54 | return HttpResponse::Ok().json(Rsp::ok("", "取消订阅成功")); 55 | } 56 | } 57 | HttpResponse::Ok().json(Rsp::fail("", "取消订阅失败")) 58 | } 59 | -------------------------------------------------------------------------------- /qapro-rs/src/qahandlers/wshandle.rs: -------------------------------------------------------------------------------- 1 | use actix::{Actor, StreamHandler}; 2 | use actix_web::{web, Error, HttpRequest, HttpResponse}; 3 | use actix_web_actors::ws; 4 | 5 | /// Define HTTP actor 6 | pub struct MyWs; 7 | 8 | impl Actor for MyWs { 9 | type Context = ws::WebsocketContext; 10 | } 11 | 12 | /// Handler for ws::Message message 13 | impl StreamHandler> for MyWs { 14 | fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { 15 | match msg { 16 | Ok(ws::Message::Ping(msg)) => ctx.pong(&msg), 17 | Ok(ws::Message::Text(text)) => ctx.text(text), 18 | Ok(ws::Message::Binary(bin)) => ctx.binary(bin), 19 | _ => (), 20 | } 21 | } 22 | } 23 | 24 | pub async fn index(req: HttpRequest, stream: web::Payload) -> Result { 25 | let resp = ws::start(MyWs {}, &req, stream); 26 | println!("{:?}", resp); 27 | resp 28 | } 29 | -------------------------------------------------------------------------------- /qapro-rs/src/qalog/log4.rs: -------------------------------------------------------------------------------- 1 | extern crate log; 2 | extern crate log4rs; 3 | use log::LevelFilter; 4 | use log4rs::append::console::ConsoleAppender; 5 | use log4rs::append::file::FileAppender; 6 | use log4rs::config::{Appender, Config, Logger, Root}; 7 | use log4rs::encode::pattern::PatternEncoder; 8 | 9 | pub fn init_log4(path: &str) { 10 | let stdout = ConsoleAppender::builder().build(); 11 | 12 | let requests = FileAppender::builder() 13 | .encoder(Box::new(PatternEncoder::new( 14 | "[{d(%Y-%m-%d %H:%M:%S)}] [{l}] [thread:{I}] [{f}] [{t}]- {m}{n}", 15 | ))) 16 | .build(path) 17 | .unwrap(); 18 | 19 | let config = Config::builder() 20 | .appender(Appender::builder().build("stdout", Box::new(stdout))) 21 | .appender(Appender::builder().build("requests", Box::new(requests))) 22 | .logger(Logger::builder().build("app::backend::db", LevelFilter::Info)) 23 | .logger( 24 | Logger::builder() 25 | .appender("requests") 26 | .additive(false) 27 | .build("app::requests", LevelFilter::Info), 28 | ) 29 | .build( 30 | Root::builder() 31 | .appender("stdout") 32 | .appender("requests") 33 | .build(LevelFilter::Info), 34 | ) 35 | .unwrap(); 36 | 37 | let handle = log4rs::init_config(config).unwrap(); 38 | } 39 | -------------------------------------------------------------------------------- /qapro-rs/src/qalog/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod log4; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamacros/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! launchstrategy{ 3 | ($name:expr;$code:expr;$json:expr;$ctx:expr;$morm_addr:expr;$mqm_addr:expr;$mdata:expr; $rdata:expr; $($m: ident),*) => { 4 | match $name { 5 | $( 6 | 7 | stringify!($m) => { 8 | // 初始化策略和上下文 9 | println!("{:#?}",$code); 10 | let params = match $json{ 11 | Some(x) => match serde_json::from_value(x.clone()) { 12 | Ok(p) => p, 13 | Err(_) => $m::Params::default(), 14 | }, 15 | None => $m::Params::default(), 16 | }; 17 | let p = serde_json::to_string(¶ms).unwrap(); 18 | let t = $m::QAStrategy::new(params); 19 | // 创建监视器 20 | let mut mor = Monitor::new($ctx, t, $morm_addr); 21 | 22 | mor.backtest($mdata, $rdata); 23 | let addr = mor.start(); 24 | $mqm_addr.do_send(MarketSubscribe { 25 | key: $code.to_string(), 26 | rec: addr.recipient().clone(), 27 | }); 28 | } 29 | )* 30 | _ => {} 31 | } 32 | } 33 | } 34 | 35 | #[macro_export] 36 | macro_rules! mapjobs{ 37 | ($name:expr;$code:expr; $($m: ident),*) => { 38 | match $name { 39 | $( 40 | stringify!($m) => { 41 | 42 | println!("{}", $code); 43 | 44 | })* 45 | _ => {} 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /qapro-rs/src/qamacros/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod macros; 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/mod.rs: -------------------------------------------------------------------------------- 1 | mod qahexos; 2 | pub mod qaoms; 3 | pub mod qareal; 4 | pub mod qasim; 5 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qahexos/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qahexos/readme.md: -------------------------------------------------------------------------------- 1 | ## hexos new 2 | 3 | 4 | --> stock/ options/ etf / index / lof/ future 5 | 6 | 行情分发 2.0 -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qaoms/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::qaaccount::account::QA_Account; 2 | use crate::qaaccount::order::QAOrder; 3 | use crate::qaconnector::mongo::mongoclient::QAMongoClient; 4 | use crate::qaenv::localenv::CONFIG; 5 | use async_trait::async_trait; 6 | use std::collections::HashMap; 7 | pub struct QAOMS { 8 | pub accountmap: HashMap, 9 | pub account_db: QAMongoClient, 10 | pub ordermap: HashMap, 11 | } 12 | 13 | trait OrderCheck { 14 | fn add_main_account(&self, account_cookie: &str); 15 | fn add_sub_account(&self, sub_account_cookie: &str); 16 | } 17 | #[async_trait] 18 | trait Reload { 19 | async fn init() -> Self; 20 | async fn reload_account(&mut self, account: &str) {} 21 | } 22 | 23 | impl OrderCheck for QAOMS { 24 | fn add_main_account(&self, account_cookie: &str) { 25 | todo!() 26 | } 27 | 28 | fn add_sub_account(&self, account_cookie: &str) { 29 | todo!() 30 | } 31 | } 32 | #[async_trait] 33 | impl Reload for QAOMS { 34 | async fn init() -> Self { 35 | Self { 36 | accountmap: HashMap::new(), 37 | account_db: QAMongoClient::new(&*CONFIG.account.uri).await, 38 | ordermap: Default::default(), 39 | } 40 | } 41 | async fn reload_account(&mut self, account_cookie: &str) { 42 | let account = self 43 | .account_db 44 | .get_account(account_cookie.parse().unwrap()) 45 | .await; 46 | self.accountmap.insert(account_cookie.to_string(), account); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qareal/ctptrader.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qareal/mod.rs: -------------------------------------------------------------------------------- 1 | mod ctptrader; 2 | mod qifitrader; 3 | mod qmttrader; 4 | mod xtptrader; 5 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qareal/qifitrader.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qareal/qmttrader.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qareal/xtptrader.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qamarket/qasim/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qapro-rs/src/qaportfolio/lib.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qaportfolio/lib.rs -------------------------------------------------------------------------------- /qapro-rs/src/qaprotocol/mifi/mifibase.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | pub trait Handler { 4 | fn to_json(&self) -> String 5 | where 6 | Self: Serialize, 7 | { 8 | serde_json::to_string(&self).unwrap() 9 | } 10 | fn get_datetime(&self) -> String; 11 | fn get_code(&self) -> String; 12 | fn get_date(&self) -> String; 13 | fn get_open(&self) -> f64; 14 | fn get_close(&self) -> f64; 15 | fn get_high(&self) -> f64; 16 | fn get_low(&self) -> f64; 17 | fn get_vol(&self) -> f64; 18 | fn get_amount(&self) -> f64; 19 | 20 | fn set_datetime(&mut self, datetime: String) {} 21 | fn set_code(&mut self, code: String) {} 22 | fn set_date(&mut self, date: String) {} 23 | fn set_open(&mut self, open: f64) {} 24 | fn set_close(&mut self, close: f64) {} 25 | fn set_high(&mut self, high: f64) {} 26 | fn set_low(&mut self, low: f64) {} 27 | fn set_vol(&mut self, vol: f64) {} 28 | fn set_amount(&mut self, amount: f64) {} 29 | } 30 | -------------------------------------------------------------------------------- /qapro-rs/src/qaprotocol/mifi/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod market; 2 | pub mod mifibase; 3 | 4 | pub mod qafastkline; 5 | -------------------------------------------------------------------------------- /qapro-rs/src/qaprotocol/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mifi; 2 | pub mod qifi; 3 | -------------------------------------------------------------------------------- /qapro-rs/src/qaprotocol/qifi/default.rs: -------------------------------------------------------------------------------- 1 | pub fn default_f64() -> f64 { 2 | 0f64 3 | } 4 | 5 | pub fn default_i64() -> i64 { 6 | 0i64 7 | } 8 | 9 | pub fn default_bool() -> bool { 10 | false 11 | } 12 | 13 | pub fn default_i128() -> i128 { 14 | 0i128 15 | } 16 | 17 | pub fn default_i32() -> i32 { 18 | 0i32 19 | } 20 | 21 | pub fn default_string() -> String { 22 | "".to_string() 23 | } 24 | -------------------------------------------------------------------------------- /qapro-rs/src/qaprotocol/qifi/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod account; 2 | pub mod data; 3 | pub mod default; 4 | pub mod func; 5 | 6 | // pub use crate::account::{Account, BankDetail, Position, Trade, Transfer, Order, QIFI}; 7 | // pub use crate::data::{Bar, DataItem, Tick, L2X}; 8 | // pub use crate::func::{from_bson_, from_serde_value, from_str, from_string, to_doc}; 9 | // 10 | -------------------------------------------------------------------------------- /qapro-rs/src/qapubsub/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod instruct_mq; 2 | pub mod market_mq; 3 | -------------------------------------------------------------------------------- /qapro-rs/src/qarisk/riskmodes/blacklitterman.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qarisk/riskmodes/blacklitterman.rs -------------------------------------------------------------------------------- /qapro-rs/src/qarisk/riskmodes/cov.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qarisk/riskmodes/cov.rs -------------------------------------------------------------------------------- /qapro-rs/src/qarisk/riskmodes/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qarisk/riskmodes/mod.rs -------------------------------------------------------------------------------- /qapro-rs/src/qarisk/riskmodes/mvo.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qarisk/riskmodes/mvo.rs -------------------------------------------------------------------------------- /qapro-rs/src/qarisk/riskmodes/shrankage.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yutiansut/QUANTAXIS/bb7329c379ef86a18dfdd7f54086c03d3801f0f1/qapro-rs/src/qarisk/riskmodes/shrankage.rs -------------------------------------------------------------------------------- /qapro-rs/src/qaruntime/base.rs: -------------------------------------------------------------------------------- 1 | use actix::prelude::*; 2 | use actix::{Actor, Addr, AsyncContext, Context, Handler, Recipient, Supervised}; 3 | 4 | extern crate serde_json; 5 | 6 | use crate::qaruntime::qacontext::MOrder; 7 | 8 | use crate::qaaccount::order::QAOrder; 9 | use crate::qaprotocol::mifi::qafastkline::QAKlineBase; 10 | use crate::qaprotocol::qifi::account::QIFI; 11 | use crate::qapubsub::market_mq::MarketMQ; 12 | use serde::{Deserialize, Serialize}; 13 | use serde_json::Value; 14 | 15 | #[derive(Debug, Message, Clone, Deserialize, Serialize)] 16 | #[rtype(result = "()")] 17 | pub struct Instruct { 18 | pub id: String, 19 | pub topic: String, 20 | pub target: Vec, 21 | pub body: String, 22 | } 23 | 24 | #[derive(Debug, Message, Clone, Deserialize, Serialize)] 25 | #[rtype(result = "()")] 26 | pub struct Ack { 27 | pub id: String, 28 | pub status: i32, 29 | pub ack: String, 30 | pub answerer: String, 31 | } 32 | 33 | #[derive(Debug, Message, Clone, Deserialize, Serialize)] 34 | #[rtype(result = "()")] 35 | pub struct Order { 36 | pub direction: String, 37 | pub offset: String, 38 | pub volume: f64, 39 | pub price: f64, 40 | } 41 | 42 | #[derive(Debug, Message)] 43 | #[rtype(result = "()")] 44 | pub struct AddMonitor { 45 | pub account_cookie: String, 46 | pub rec: Recipient, 47 | } 48 | 49 | #[derive(Debug, Message)] 50 | #[rtype(result = "()")] 51 | pub struct ShowAllMonitor; 52 | 53 | #[derive(Message)] 54 | #[rtype(result = "()")] 55 | pub struct MQAddr { 56 | pub key: String, 57 | pub addr: Addr, 58 | } 59 | 60 | #[derive(Debug, Message)] 61 | #[rtype(result = "()")] 62 | pub struct ShowAllMQ; 63 | 64 | #[derive(Debug, Message)] 65 | #[rtype(result = "()")] 66 | pub struct StartAllMQ; 67 | 68 | #[derive(Debug, Message)] 69 | #[rtype(result = "()")] 70 | pub struct MarketSubscribe { 71 | pub key: String, 72 | pub rec: Recipient, 73 | } 74 | 75 | #[derive(Debug, Message)] 76 | #[rtype(result = "()")] 77 | pub struct QifiRsp { 78 | pub t: i32, 79 | pub data: QIFI, 80 | } 81 | 82 | #[derive(Debug, Message)] 83 | #[rtype(result = "()")] 84 | pub struct QAOrderRsp { 85 | pub data: Vec, 86 | } 87 | 88 | #[derive(Debug, Message)] 89 | #[rtype(result = "()")] 90 | pub struct QAKline { 91 | pub data: QAKlineBase, 92 | } 93 | -------------------------------------------------------------------------------- /qapro-rs/src/qaruntime/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod base; 2 | pub mod monitor; 3 | pub mod qacontext; 4 | pub mod qamanagers; 5 | -------------------------------------------------------------------------------- /qapro-rs/src/qaruntime/qamanagers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod monitor_manager; 2 | pub mod mq_manager; 3 | -------------------------------------------------------------------------------- /qapro-rs/src/qastrategy/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod backtest; 2 | pub mod qatemplate; 3 | pub mod t00; 4 | -------------------------------------------------------------------------------- /qapro-rs/src/qastrategy/qatemplate.rs: -------------------------------------------------------------------------------- 1 | //---------------------- 2 | // T 3 | //--------------------- 4 | use std::f64::INFINITY; 5 | 6 | use chrono::prelude::Utc; 7 | 8 | use crate::qaaccount::{account::QA_Account, order::QAOrder, transaction::QATransaction}; 9 | 10 | use serde::{Deserialize, Serialize}; 11 | 12 | use crate::qadata::datafunc::{dhhv, dllv, max, min, vec_bigger, vec_smaller, Que}; 13 | use crate::qaprotocol::mifi::market::BAR; 14 | use crate::qaruntime::qacontext::{QAContext, StrategyFunc}; 15 | 16 | #[derive(Debug, Serialize, Deserialize, Clone)] 17 | pub struct Params {} 18 | 19 | // impl Params { 20 | // pub fn default() -> Params { 21 | // Params { 22 | // 23 | // } 24 | // } 25 | // } 26 | 27 | #[derive(Debug, Clone)] 28 | pub struct QAStrategy { 29 | pub params: Params, 30 | } 31 | 32 | // impl StrategyFunc for QAStrategy { 33 | // fn on_bar_next(&mut self, data: &BAR, context: &mut QAContext) { 34 | // let bar = data; 35 | // let hour = bar.datetime[11..13].parse::().unwrap(); 36 | // let minute = bar.datetime[14..16].parse::().unwrap(); 37 | // let now = Utc::now(); 38 | // let code = bar.code.as_ref(); 39 | // let long_pos = context.acc.get_volume_long(code); 40 | // let short_pos = context.acc.get_volume_short(code); 41 | // //-----------------Strategy---Content------------------------- 42 | // } 43 | // 44 | // fn on_bar_update(&mut self, data: &BAR, context: &mut QAContext) { 45 | // let bar = data; 46 | // let hour = bar.datetime[11..13].parse::().unwrap(); 47 | // let minute = bar.datetime[14..16].parse::().unwrap(); 48 | // let now = Utc::now(); 49 | // let code = bar.code.as_ref(); 50 | // let long_pos = context.acc.get_volume_long(code); 51 | // let short_pos = context.acc.get_volume_short(code); 52 | // //-----------------Strategy---Content------------------------- 53 | // } 54 | // } 55 | -------------------------------------------------------------------------------- /qapro-rs/src/qautil/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod tradedate; 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pymongo==3.11.2 2 | bs4 3 | pandas>=1.1.5 4 | lxml 5 | matplotlib 6 | requests 7 | numpy>=1.12.0 8 | pytesseract 9 | gevent-websocket>=0.10.1 10 | apscheduler>=3.3.1 11 | zenlog 12 | protobuf>=3.4.0 13 | motor==2.2 14 | retrying 15 | seaborn>=0.11.1 16 | attrs>=17.4.0 17 | pyconvert>=0.6.3 18 | janus==0.4.0 19 | pyecharts_snapshot 20 | async_timeout 21 | IPython 22 | numba 23 | tushare 24 | websocket-client 25 | statsmodels>=0.12.1 26 | scipy 27 | pytdx>=1.67 28 | delegator.py>=0.0.12 29 | flask>=0.12.2 30 | pyecharts>=1.9.0 31 | six>=1.10.0 32 | pika 33 | empyrical 34 | pyfolio 35 | tornado>=6.3.2 36 | qaenv>=0.0.4 37 | lz4 38 | clickhouse-driver 39 | clickhouse-cityhash 40 | alphalens 41 | qanotify 42 | 43 | pyarrow>=6.0.1 --------------------------------------------------------------------------------