From a82c9b95359d5b95459762ff5f7bb8f8d76f56e3 Mon Sep 17 00:00:00 2001 From: woldy Date: Tue, 9 Jul 2024 20:39:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- COMMERCIAL_LICENSE.txt | 0 Dockerfile | 0 LICENSE.txt | 0 MANIFEST.in | 0 README.md | 0 database/finhack_structure.sql | 6 +- examples/__init__.py | 0 examples/demo-project/.proj | 0 examples/demo-project/auto/__init__.py | 0 .../backtest/default/default_backtest.py | 11 +- examples/demo-project/indicators/QIML365.py | 0 examples/demo-project/indicators/member.py | 0 .../demo-project/loader/testmodule_loader.py | 0 examples/demo-project/prompt/autoalpha | 0 examples/demo-project/script/qmt.sh | 6 +- .../demo-project/strategy/AITopNStrategy.py | 0 .../demo-project/strategy/AITopNStrategy2.py | 0 .../demo-project/strategy/ChatGPTStrategy.py | 0 .../demo-project/strategy/ChatGPTStrategy1.py | 0 .../demo-project/strategy/ChatGPTStrategy3.py | 0 .../strategy/ChatgptAIStrategy.py | 0 .../demo-project/strategy/DemoStrategy.py | 0 examples/demo-project/strategy/IndexPlus.py | 0 examples/demo-project/strategy/IndexPlus2.py | 0 examples/demo-project/strategy/QMTStrategy.py | 2 +- .../demo-project/strategy/SmallCapStrategy.py | 0 .../demo-project/strategy/testStrategy.py | 55 ++- .../testmodule/default/default_testmodule.py | 0 examples/demo-project/trader/__init__.py | 0 .../demo-project/trader/miniqmt/__init__.py | 0 .../demo-project/trader/miniqmt/calendar.py | 19 + .../demo-project/trader/miniqmt/context.py | 120 ++++++ examples/demo-project/trader/miniqmt/data.py | 24 ++ .../demo-project/trader/miniqmt/dictobj.py | 92 +++++ examples/demo-project/trader/miniqmt/event.py | 183 +++++++++ .../demo-project/trader/miniqmt/function.py | 367 ++++++++++++++++++ .../trader/miniqmt/miniqmt_trader.py | 168 ++++++++ .../demo-project/trader/miniqmt/object.py | 155 ++++++++ .../trader/{qmt => miniqmt}/qmt.proto | 0 .../demo-project/trader/miniqmt/qmtClient.py | 192 +++++++++ .../trader/{qmt => miniqmt}/qmt_pb2.py | 0 .../trader/{qmt => miniqmt}/qmt_pb2_grpc.py | 2 +- examples/demo-project/trader/miniqmt/rules.py | 232 +++++++++++ examples/demo-project/trader/qmt/__init__.py | 0 examples/demo-project/trader/qmt/calendar.py | 0 examples/demo-project/trader/qmt/context.py | 1 + examples/demo-project/trader/qmt/data.py | 0 examples/demo-project/trader/qmt/dictobj.py | 0 examples/demo-project/trader/qmt/event.py | 26 +- examples/demo-project/trader/qmt/function.py | 29 +- examples/demo-project/trader/qmt/object.py | 0 examples/demo-project/trader/qmt/qmtClient.py | 195 +++------- .../demo-project/trader/qmt/qmt_trader.py | 99 +++-- examples/demo-project/trader/qmt/rules.py | 0 .../trader/rqalpha/append_code.py | 0 .../trader/rqalpha/rqalpha_trader.py | 17 +- examples/demo-project/trader/sim/__init__.py | 0 examples/demo-project/trader/sim/calendar.py | 0 examples/demo-project/trader/sim/context.py | 0 examples/demo-project/trader/sim/data.py | 0 examples/demo-project/trader/sim/dictobj.py | 0 examples/demo-project/trader/sim/event.py | 0 examples/demo-project/trader/sim/function.py | 0 examples/demo-project/trader/sim/object.py | 0 examples/demo-project/trader/sim/qmtClient.py | 0 examples/demo-project/trader/sim/rules.py | 0 finhack/__init__.py | 2 +- finhack/collector/__init__.py | 0 finhack/collector/baseCollector.py | 0 finhack/collector/binance/__init__.py | 0 finhack/collector/tushare/__init__.py | 0 .../collector/tushare/tushare_collector.py | 2 +- finhack/core/__init__.py | 0 finhack/core/classes/__init__.py | 0 finhack/core/classes/dictobj.py | 0 finhack/core/command/__init__.py | 0 finhack/core/core.py | 0 finhack/core/data/__init__.py | 0 finhack/core/data/logs/__init__.py | 0 finhack/core/loader/__init__.py | 0 finhack/core/loader/base_loader.py | 0 finhack/core/loader/collector_loader.py | 0 finhack/core/loader/factor_loader.py | 0 finhack/core/loader/helper_loader.py | 0 finhack/core/loader/trader_loader.py | 0 finhack/core/notify.py | 0 finhack/core/version.py | 0 finhack/factor/__init__.py | 0 finhack/factor/default/default_factor.py | 0 finhack/factor/default/factorRepair.py | 0 finhack/helper/__init__.py | 0 finhack/helper/struct/__init__.py | 0 finhack/helper/struct/struct_helper.py | 0 finhack/library/__init__.py | 0 finhack/library/ai.py | 0 finhack/library/class_loader.py | 0 finhack/library/config.py | 0 finhack/library/log.py | 0 finhack/library/mycache.py | 0 finhack/library/utils.py | 0 finhack/market/__init__.py | 0 finhack/market/astock/__init__.py | 0 finhack/market/astock/tushare/__init__.py | 0 finhack/market/astock/tushare/indexHelper.py | 0 finhack/plugin/__init__.py | 0 finhack/plugin/default/__init__.py | 0 finhack/plugin/default/default_plugin.py | 0 finhack/requirements.txt | 5 +- finhack/server/__init__.py | 0 finhack/server/default/__init__.py | 0 finhack/server/default/default_server.py | 12 +- finhack/trader/__init__.py | 0 finhack/trader/default/__init__.py | 0 finhack/trader/default/calendar.py | 0 finhack/trader/default/context.py | 0 finhack/trader/default/data.py | 0 finhack/trader/default/default_trader.py | 0 finhack/trader/default/event.py | 0 finhack/trader/default/function.py | 0 finhack/trader/default/object.py | 0 finhack/trader/default/performance.py | 0 finhack/trader/default/rules.py | 0 finhack/trainer/__init__.py | 0 finhack/trainer/auto/__init__.py | 0 finhack/trainer/auto/auto_trainer.py | 0 finhack/trainer/lightgbm/__init__.py | 0 finhack/trainer/lightgbm/lightgbm_trainer.py | 0 finhack/trainer/trainer.py | 0 finhack/widgets/__init__.py | 0 finhack/widgets/templates/__init__.py | 0 finhack/widgets/templates/empty_project/.proj | 0 .../templates/empty_project/__init__.py | 0 .../templates/empty_project/auto/__init__.py | 0 .../empty_project/auto/default/__init__.py | 0 .../empty_project/backtest/__init__.py | 0 .../backtest/default/__init__.py | 0 .../backtest/default/default_backtest.py | 13 +- .../templates/empty_project/data/__init__.py | 0 .../empty_project/data/cache/__init__.py | 0 .../data/cache/choice/__init__.py | 0 .../data/cache/factors/__init__.py | 0 .../data/cache/index/__init__.py | 0 .../empty_project/data/cache/kv/__init__.py | 0 .../data/cache/market/__init__.py | 0 .../data/cache/notice/__init__.py | 0 .../data/cache/price/__init__.py | 0 .../empty_project/data/cache/runtime.py | 0 .../data/cache/runtime/__init__.py | 0 .../data/cache/runtime/constant.py | 2 +- .../data/cache/runtime/global_var.py | 0 .../cache/single_factors_tmp1/__init__.py | 0 .../cache/single_factors_tmp2/__init__.py | 0 .../empty_project/data/config/__init__.py | 0 .../empty_project/data/config/ai.conf | 0 .../empty_project/data/config/args.conf | 16 +- .../empty_project/data/config/backtest.conf | 4 +- .../empty_project/data/config/constant.conf | 0 .../empty_project/data/config/core.conf | 0 .../data/config/factorlist/__init__.py | 0 .../config/factorlist/alphalist/__init__.py | 0 .../factorlist/indicatorlist/__init__.py | 0 .../config/factorlist/indicatorlist/woldy | 0 .../config/factorlist/trainlist/__init__.py | 0 .../config/factorlist/trainlist/autotrain | 0 .../empty_project/data/config/global_var.conf | 0 .../data/config/sqllist/__init__.py | 0 .../data/config/sqllist/backtest/__init__.py | 0 .../data/config/sqllist/server/__init__.py | 0 .../empty_project/data/config/trader.conf | 0 .../empty_project/data/config/train.conf | 0 .../empty_project/data/factors/__init__.py | 0 .../data/factors/code_factors/__init__.py | 0 .../data/factors/single_factors/__init__.py | 0 .../single_factors_parquet/__init__.py | 0 .../all_factors.parquet/__init__.py | 0 .../factors/single_factors_pkl/__init__.py | 0 .../single_factors_pkl/_tmp/__init__.py | 0 .../single_factors_pkl_tmp/__init__.py | 0 .../single_factors_pkl_tmp/_tmp/__init__.py | 0 .../empty_project/data/logs/__init__.py | 0 .../data/logs/trader/__init__.py | 0 .../empty_project/data/models/__init__.py | 0 .../empty_project/data/preds/__init__.py | 0 .../empty_project/data/quote/__init__.py | 0 .../data/quote/crytpo/__init__.py | 0 .../data/quote/forex/__init__.py | 0 .../data/quote/future/__init__.py | 0 .../data/quote/option/__init__.py | 0 .../data/quote/stock/SH/__init__.py | 0 .../data/quote/stock/SZ/000001.SZ/__init__.py | 0 .../stock/SZ/000001.SZ/daily/__init__.py | 0 .../stock/SZ/000001.SZ/minutely/__init__.py | 0 .../quote/stock/SZ/000001.SZ/tick/__init__.py | 0 .../data/quote/stock/SZ/__init__.py | 0 .../data/quote/stock/__init__.py | 0 .../empty_project/data/reports/__init__.py | 0 .../empty_project/data/reports/index.html | 0 .../data/reports/static/__init__.py | 0 .../data/reports/static/css/__init__.py | 0 .../data/reports/static/images/__init__.py | 0 .../data/reports/static/js/__init__.py | 0 .../data/reports/static/rqalpha/__init__.py | 0 .../data/reports/static/trader/__init__.py | 0 .../empty_project/data/running/__init__.py | 0 .../templates/empty_project/data/running/x.py | 9 + .../empty_project/indicators/QIML365.py | 0 .../empty_project/indicators/member.py | 0 .../loader/1testmodule_loader.py | 0 .../empty_project/loader/__init__.py | 0 .../empty_project/loader/testmodule_loader.py | 0 .../empty_project/prompt/__init__.py | 0 .../empty_project/prompts/__init__.py | 0 .../empty_project/script/__init__.py | 0 .../empty_project/strategy/AITopNStrategy.py | 0 .../empty_project/strategy/ChatGPTStrategy.py | 0 .../empty_project/strategy/DemoStrategy.py | 0 .../empty_project/strategy/__init__.py | 0 .../empty_project/testmodule/__init__.py | 0 .../testmodule/default/__init__.py | 0 .../testmodule/default/default_testmodule.py | 0 .../testmodule/default/testmodule.py | 0 .../empty_project/trader/__init__.py | 0 .../empty_project/trader/qmt/__init__.py | 0 .../empty_project/trader/qmt/calendar.py | 0 .../empty_project/trader/qmt/client.py | 0 .../empty_project/trader/qmt/context.py | 1 + .../empty_project/trader/qmt/data.py | 0 .../empty_project/trader/qmt/dictobj.py | 0 .../empty_project/trader/qmt/event.py | 26 +- .../empty_project/trader/qmt/function.py | 31 +- .../empty_project/trader/qmt/object.py | 1 + .../empty_project/trader/qmt/qmtClient.py | 0 .../empty_project/trader/qmt/qmt_trader.py | 95 +++-- .../empty_project/trader/qmt/rules.py | 0 .../empty_project/trader/rqalpha/__init__.py | 0 .../trader/rqalpha/append_code.py | 0 .../trader/rqalpha/rqalpha_trader.py | 17 +- .../empty_project/trader/sim/__init__.py | 0 .../empty_project/trader/sim/calendar.py | 0 .../empty_project/trader/sim/context.py | 0 .../empty_project/trader/sim/data.py | 0 .../empty_project/trader/sim/dictobj.py | 0 .../empty_project/trader/sim/event.py | 0 .../empty_project/trader/sim/function.py | 0 .../empty_project/trader/sim/object.py | 0 .../empty_project/trader/sim/qmtClient.py | 0 .../empty_project/trader/sim/rules.py | 4 - finhack/widgets/templates/runtime/__init__.py | 0 finhack/widgets/templates/runtime/constant.py | 0 .../widgets/templates/runtime/global_var.py | 0 requirements.txt | 5 +- setup.py | 0 252 files changed, 1967 insertions(+), 279 deletions(-) mode change 100644 => 100755 COMMERCIAL_LICENSE.txt mode change 100644 => 100755 Dockerfile mode change 100644 => 100755 LICENSE.txt mode change 100644 => 100755 MANIFEST.in mode change 100644 => 100755 README.md mode change 100644 => 100755 database/finhack_structure.sql mode change 100644 => 100755 examples/__init__.py mode change 100644 => 100755 examples/demo-project/.proj mode change 100644 => 100755 examples/demo-project/auto/__init__.py mode change 100644 => 100755 examples/demo-project/backtest/default/default_backtest.py mode change 100644 => 100755 examples/demo-project/indicators/QIML365.py mode change 100644 => 100755 examples/demo-project/indicators/member.py mode change 100644 => 100755 examples/demo-project/loader/testmodule_loader.py mode change 100644 => 100755 examples/demo-project/prompt/autoalpha mode change 100644 => 100755 examples/demo-project/strategy/AITopNStrategy.py mode change 100644 => 100755 examples/demo-project/strategy/AITopNStrategy2.py mode change 100644 => 100755 examples/demo-project/strategy/ChatGPTStrategy.py mode change 100644 => 100755 examples/demo-project/strategy/ChatGPTStrategy1.py mode change 100644 => 100755 examples/demo-project/strategy/ChatGPTStrategy3.py mode change 100644 => 100755 examples/demo-project/strategy/ChatgptAIStrategy.py mode change 100644 => 100755 examples/demo-project/strategy/DemoStrategy.py mode change 100644 => 100755 examples/demo-project/strategy/IndexPlus.py mode change 100644 => 100755 examples/demo-project/strategy/IndexPlus2.py mode change 100644 => 100755 examples/demo-project/strategy/QMTStrategy.py mode change 100644 => 100755 examples/demo-project/strategy/SmallCapStrategy.py mode change 100644 => 100755 examples/demo-project/strategy/testStrategy.py mode change 100644 => 100755 examples/demo-project/testmodule/default/default_testmodule.py mode change 100644 => 100755 examples/demo-project/trader/__init__.py create mode 100755 examples/demo-project/trader/miniqmt/__init__.py create mode 100755 examples/demo-project/trader/miniqmt/calendar.py create mode 100755 examples/demo-project/trader/miniqmt/context.py create mode 100755 examples/demo-project/trader/miniqmt/data.py create mode 100755 examples/demo-project/trader/miniqmt/dictobj.py create mode 100755 examples/demo-project/trader/miniqmt/event.py create mode 100755 examples/demo-project/trader/miniqmt/function.py create mode 100755 examples/demo-project/trader/miniqmt/miniqmt_trader.py create mode 100755 examples/demo-project/trader/miniqmt/object.py rename examples/demo-project/trader/{qmt => miniqmt}/qmt.proto (100%) create mode 100755 examples/demo-project/trader/miniqmt/qmtClient.py rename examples/demo-project/trader/{qmt => miniqmt}/qmt_pb2.py (100%) rename examples/demo-project/trader/{qmt => miniqmt}/qmt_pb2_grpc.py (99%) create mode 100755 examples/demo-project/trader/miniqmt/rules.py mode change 100644 => 100755 examples/demo-project/trader/qmt/__init__.py mode change 100644 => 100755 examples/demo-project/trader/qmt/calendar.py mode change 100644 => 100755 examples/demo-project/trader/qmt/context.py mode change 100644 => 100755 examples/demo-project/trader/qmt/data.py mode change 100644 => 100755 examples/demo-project/trader/qmt/dictobj.py mode change 100644 => 100755 examples/demo-project/trader/qmt/event.py mode change 100644 => 100755 examples/demo-project/trader/qmt/function.py mode change 100644 => 100755 examples/demo-project/trader/qmt/object.py mode change 100644 => 100755 examples/demo-project/trader/qmt/qmtClient.py mode change 100644 => 100755 examples/demo-project/trader/qmt/rules.py mode change 100644 => 100755 examples/demo-project/trader/rqalpha/append_code.py mode change 100644 => 100755 examples/demo-project/trader/rqalpha/rqalpha_trader.py mode change 100644 => 100755 examples/demo-project/trader/sim/__init__.py mode change 100644 => 100755 examples/demo-project/trader/sim/calendar.py mode change 100644 => 100755 examples/demo-project/trader/sim/context.py mode change 100644 => 100755 examples/demo-project/trader/sim/data.py mode change 100644 => 100755 examples/demo-project/trader/sim/dictobj.py mode change 100644 => 100755 examples/demo-project/trader/sim/event.py mode change 100644 => 100755 examples/demo-project/trader/sim/function.py mode change 100644 => 100755 examples/demo-project/trader/sim/object.py mode change 100644 => 100755 examples/demo-project/trader/sim/qmtClient.py mode change 100644 => 100755 examples/demo-project/trader/sim/rules.py mode change 100644 => 100755 finhack/__init__.py mode change 100644 => 100755 finhack/collector/__init__.py mode change 100644 => 100755 finhack/collector/baseCollector.py create mode 100644 finhack/collector/binance/__init__.py mode change 100644 => 100755 finhack/collector/tushare/__init__.py mode change 100644 => 100755 finhack/core/__init__.py mode change 100644 => 100755 finhack/core/classes/__init__.py mode change 100644 => 100755 finhack/core/classes/dictobj.py mode change 100644 => 100755 finhack/core/command/__init__.py mode change 100644 => 100755 finhack/core/core.py mode change 100644 => 100755 finhack/core/data/__init__.py mode change 100644 => 100755 finhack/core/data/logs/__init__.py mode change 100644 => 100755 finhack/core/loader/__init__.py mode change 100644 => 100755 finhack/core/loader/base_loader.py mode change 100644 => 100755 finhack/core/loader/collector_loader.py mode change 100644 => 100755 finhack/core/loader/factor_loader.py mode change 100644 => 100755 finhack/core/loader/helper_loader.py mode change 100644 => 100755 finhack/core/loader/trader_loader.py mode change 100644 => 100755 finhack/core/notify.py mode change 100644 => 100755 finhack/core/version.py mode change 100644 => 100755 finhack/factor/__init__.py mode change 100644 => 100755 finhack/factor/default/default_factor.py mode change 100644 => 100755 finhack/factor/default/factorRepair.py mode change 100644 => 100755 finhack/helper/__init__.py mode change 100644 => 100755 finhack/helper/struct/__init__.py mode change 100644 => 100755 finhack/helper/struct/struct_helper.py mode change 100644 => 100755 finhack/library/__init__.py mode change 100644 => 100755 finhack/library/ai.py mode change 100644 => 100755 finhack/library/class_loader.py mode change 100644 => 100755 finhack/library/config.py mode change 100644 => 100755 finhack/library/log.py mode change 100644 => 100755 finhack/library/mycache.py mode change 100644 => 100755 finhack/library/utils.py mode change 100644 => 100755 finhack/market/__init__.py mode change 100644 => 100755 finhack/market/astock/__init__.py mode change 100644 => 100755 finhack/market/astock/tushare/__init__.py mode change 100644 => 100755 finhack/market/astock/tushare/indexHelper.py mode change 100644 => 100755 finhack/plugin/__init__.py mode change 100644 => 100755 finhack/plugin/default/__init__.py mode change 100644 => 100755 finhack/plugin/default/default_plugin.py mode change 100644 => 100755 finhack/requirements.txt mode change 100644 => 100755 finhack/server/__init__.py mode change 100644 => 100755 finhack/server/default/__init__.py mode change 100644 => 100755 finhack/server/default/default_server.py mode change 100644 => 100755 finhack/trader/__init__.py mode change 100644 => 100755 finhack/trader/default/__init__.py mode change 100644 => 100755 finhack/trader/default/calendar.py mode change 100644 => 100755 finhack/trader/default/context.py mode change 100644 => 100755 finhack/trader/default/data.py mode change 100644 => 100755 finhack/trader/default/default_trader.py mode change 100644 => 100755 finhack/trader/default/event.py mode change 100644 => 100755 finhack/trader/default/function.py mode change 100644 => 100755 finhack/trader/default/object.py mode change 100644 => 100755 finhack/trader/default/performance.py mode change 100644 => 100755 finhack/trader/default/rules.py mode change 100644 => 100755 finhack/trainer/__init__.py mode change 100644 => 100755 finhack/trainer/auto/__init__.py mode change 100644 => 100755 finhack/trainer/auto/auto_trainer.py mode change 100644 => 100755 finhack/trainer/lightgbm/__init__.py mode change 100644 => 100755 finhack/trainer/lightgbm/lightgbm_trainer.py mode change 100644 => 100755 finhack/trainer/trainer.py mode change 100644 => 100755 finhack/widgets/__init__.py mode change 100644 => 100755 finhack/widgets/templates/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/.proj mode change 100644 => 100755 finhack/widgets/templates/empty_project/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/auto/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/auto/default/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/backtest/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/backtest/default/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/backtest/default/default_backtest.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/choice/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/factors/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/index/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/kv/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/market/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/notice/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/price/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/runtime.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/runtime/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/runtime/constant.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/runtime/global_var.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/single_factors_tmp1/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/cache/single_factors_tmp2/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/ai.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/args.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/backtest.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/constant.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/core.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/factorlist/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/factorlist/alphalist/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/factorlist/indicatorlist/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/factorlist/indicatorlist/woldy mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/factorlist/trainlist/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/factorlist/trainlist/autotrain mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/global_var.conf create mode 100644 finhack/widgets/templates/empty_project/data/config/sqllist/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/config/sqllist/backtest/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/config/sqllist/server/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/trader.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/config/train.conf mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/code_factors/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors_parquet/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors_parquet/all_factors.parquet/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors_pkl/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors_pkl/_tmp/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors_pkl_tmp/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/factors/single_factors_pkl_tmp/_tmp/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/logs/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/logs/trader/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/models/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/preds/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/crytpo/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/forex/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/future/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/option/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/SH/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/daily/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/minutely/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/tick/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/SZ/__init__.py create mode 100644 finhack/widgets/templates/empty_project/data/quote/stock/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/index.html mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/static/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/static/css/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/static/images/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/static/js/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/static/rqalpha/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/reports/static/trader/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/data/running/__init__.py create mode 100755 finhack/widgets/templates/empty_project/data/running/x.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/indicators/QIML365.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/indicators/member.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/loader/1testmodule_loader.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/loader/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/loader/testmodule_loader.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/prompt/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/prompts/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/script/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/strategy/AITopNStrategy.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/strategy/ChatGPTStrategy.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/strategy/DemoStrategy.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/strategy/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/testmodule/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/testmodule/default/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/testmodule/default/default_testmodule.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/testmodule/default/testmodule.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/calendar.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/client.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/context.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/data.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/dictobj.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/event.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/function.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/object.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/qmtClient.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/qmt/rules.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/rqalpha/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/rqalpha/append_code.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/rqalpha/rqalpha_trader.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/__init__.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/calendar.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/context.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/data.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/dictobj.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/event.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/function.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/object.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/qmtClient.py mode change 100644 => 100755 finhack/widgets/templates/empty_project/trader/sim/rules.py mode change 100644 => 100755 finhack/widgets/templates/runtime/__init__.py mode change 100644 => 100755 finhack/widgets/templates/runtime/constant.py mode change 100644 => 100755 finhack/widgets/templates/runtime/global_var.py mode change 100644 => 100755 requirements.txt mode change 100644 => 100755 setup.py diff --git a/COMMERCIAL_LICENSE.txt b/COMMERCIAL_LICENSE.txt old mode 100644 new mode 100755 diff --git a/Dockerfile b/Dockerfile old mode 100644 new mode 100755 diff --git a/LICENSE.txt b/LICENSE.txt old mode 100644 new mode 100755 diff --git a/MANIFEST.in b/MANIFEST.in old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/database/finhack_structure.sql b/database/finhack_structure.sql old mode 100644 new mode 100755 index 0e98442..b2ec993 --- a/database/finhack_structure.sql +++ b/database/finhack_structure.sql @@ -39,7 +39,7 @@ CREATE TABLE `auto_train` ( `score` double(10,10) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `hash` (`hash`) -) ENGINE=InnoDB AUTO_INCREMENT=14227 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB AUTO_INCREMENT=14397 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -93,7 +93,7 @@ CREATE TABLE `backtest` ( `strategy_code` text, PRIMARY KEY (`id`), UNIQUE KEY `instence_id` (`instance_id`) -) ENGINE=InnoDB AUTO_INCREMENT=443191 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB AUTO_INCREMENT=447981 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -255,4 +255,4 @@ CREATE TABLE `rqalpha` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2024-04-09 14:04:21 +-- Dump completed on 2024-06-28 13:29:27 diff --git a/examples/__init__.py b/examples/__init__.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/.proj b/examples/demo-project/.proj old mode 100644 new mode 100755 diff --git a/examples/demo-project/auto/__init__.py b/examples/demo-project/auto/__init__.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/backtest/default/default_backtest.py b/examples/demo-project/backtest/default/default_backtest.py old mode 100644 new mode 100755 index 0701bdd..d1c8a26 --- a/examples/demo-project/backtest/default/default_backtest.py +++ b/examples/demo-project/backtest/default/default_backtest.py @@ -72,8 +72,15 @@ def rqalpha(self): entry_file_path = os.path.realpath(sys.executable) else: entry_file_path = os.path.realpath(sys.argv[0]) - - bt_list=mydb.selectToList(f"SELECT id, instance_id, features_list, train, model, strategy, start_date, end_date, init_cash, params, total_value, alpha, beta, annual_return, cagr, annual_volatility, info_ratio, downside_risk, R2, sharpe, sortino, calmar, omega, max_down, SQN, created_at, filter, win, server, trade_num, runtime, starttime, endtime, roto, simulate, benchmark, strategy_code FROM `finhack`.`backtest` order by sharpe desc LIMIT 1000",'finhack') + + sql="" + path=f"{BASE_DIR}/data/config/sqllist/backtest/bt_list.sql" + if os.path.exists(path): + with open(path, 'r', encoding='utf-8') as file: + sql= file.read() + else: + sql="SELECT id, instance_id, features_list, train, model, strategy, start_date, end_date, init_cash, params, total_value, alpha, beta, annual_return, cagr, annual_volatility, info_ratio, downside_risk, R2, sharpe, sortino, calmar, omega, max_down, SQN, created_at, filter, win, server, trade_num, runtime, starttime, endtime, roto, simulate, benchmark, strategy_code FROM `finhack`.`backtest` order by sharpe desc LIMIT 1000" + bt_list=mydb.selectToList(sql,'finhack') def to_json(s): dict_str = re.sub(r"DictObj\((.*?)\)", r"{\1}", s) diff --git a/examples/demo-project/indicators/QIML365.py b/examples/demo-project/indicators/QIML365.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/indicators/member.py b/examples/demo-project/indicators/member.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/loader/testmodule_loader.py b/examples/demo-project/loader/testmodule_loader.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/prompt/autoalpha b/examples/demo-project/prompt/autoalpha old mode 100644 new mode 100755 diff --git a/examples/demo-project/script/qmt.sh b/examples/demo-project/script/qmt.sh index a295700..4ffa630 100755 --- a/examples/demo-project/script/qmt.sh +++ b/examples/demo-project/script/qmt.sh @@ -4,6 +4,6 @@ cd /data/code/demo_project /root/anaconda3/envs/finhack/bin/python -u /root/anaconda3/envs/finhack/bin/finhack trader run \ --project_path=/data/code/demo_project/ \ - --vendor=qmt --id=r_ad6709f1d13f642e16d74a40190d06c5 \ - --strategy=QMTStrategy --model_id=929526e7c5f8807a04205c17cc95b742 \ - --params='{"stocknum": "5", "refresh_rate": "5", "stop_loss_threshold": "0.95", "stop_gain_threshold": "1.2"}' >>/tmp/finhack_qmt.log \ No newline at end of file + --vendor=qmt --id=r_golden \ + --strategy=QMTStrategy --model_id=97b190dd39d86b464dd76597cef2dc48 \ + --params='{"stocknum": "30", "refresh_rate": "3", "stop_loss_threshold": "0.9", "stop_gain_threshold": "1.3"}' >>/tmp/finhack_qmt.log \ No newline at end of file diff --git a/examples/demo-project/strategy/AITopNStrategy.py b/examples/demo-project/strategy/AITopNStrategy.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/AITopNStrategy2.py b/examples/demo-project/strategy/AITopNStrategy2.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/ChatGPTStrategy.py b/examples/demo-project/strategy/ChatGPTStrategy.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/ChatGPTStrategy1.py b/examples/demo-project/strategy/ChatGPTStrategy1.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/ChatGPTStrategy3.py b/examples/demo-project/strategy/ChatGPTStrategy3.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/ChatgptAIStrategy.py b/examples/demo-project/strategy/ChatgptAIStrategy.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/DemoStrategy.py b/examples/demo-project/strategy/DemoStrategy.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/IndexPlus.py b/examples/demo-project/strategy/IndexPlus.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/IndexPlus2.py b/examples/demo-project/strategy/IndexPlus2.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/QMTStrategy.py b/examples/demo-project/strategy/QMTStrategy.py old mode 100644 new mode 100755 index bf6dbde..11bc8d1 --- a/examples/demo-project/strategy/QMTStrategy.py +++ b/examples/demo-project/strategy/QMTStrategy.py @@ -136,7 +136,7 @@ def trade_open(context): # 盘尾逻辑 def trade_close(context): - # sync(context) + sync(context) g=context.g adjust_dynamic_parameters(context) diff --git a/examples/demo-project/strategy/SmallCapStrategy.py b/examples/demo-project/strategy/SmallCapStrategy.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/strategy/testStrategy.py b/examples/demo-project/strategy/testStrategy.py old mode 100644 new mode 100755 index ce51402..06a2be0 --- a/examples/demo-project/strategy/testStrategy.py +++ b/examples/demo-project/strategy/testStrategy.py @@ -24,13 +24,13 @@ def initialize(context): # 设定滑点 set_slippage(PriceRelatedSlippage(0.00246), type='stock') - model_id = context.trade.model_id - preds_cache=context.get('params', {}).get('preds_cache', 'False') - if preds_cache.lower()[0:1]=='t': - preds_data = load_preds_data(model_id,True) - else: - preds_data = load_preds_data(model_id) - g.preds=preds_data + # model_id = context.trade.model_id + # preds_cache=context.get('params', {}).get('preds_cache', 'False') + # if preds_cache.lower()[0:1]=='t': + # preds_data = load_preds_data(model_id,True) + # else: + # preds_data = load_preds_data(model_id) + # g.preds=preds_data # 全局变量初始化 g.stock_num = int(context.get('params', {}).get('stocknum', 10)) # 持仓股票数量 g.refresh_rate = int(context.get('params', {}).get('refresh_rate', 10)) # 调仓频率,动态调整 @@ -39,11 +39,34 @@ def initialize(context): g.days = 0 # 交易日计时器 # 每日运行 - run_daily(trade_open, time="09:30") - run_daily(trade_open, time="09:30") - run_daily(trade_open, time="09:30") - run_daily(trade_close, time="15:00") + run_daily(trade_open, time="09:20:10") + run_daily(trade_close, time="14:57:10") + # # 当前时间 + # now = datetime.now() + + + + # # 10分钟后的时间 + # ten_minutes_later = now + timedelta(minutes=60*24) + + # # 当前时间加上10秒,用于第一次调度 + # next_call_time = now + timedelta(seconds=10) + + + + # # 循环,直到达到10分钟后的时间 + # while next_call_time <= ten_minutes_later: + # print(next_call_time.strftime("%H:%M:%S")) + # # 计划函数调用 + # run_daily(test, next_call_time.strftime("%H:%M:%S")) + + # # 更新下一次调用时间(增加10秒) + # next_call_time += timedelta(seconds=10) + + +def days_inc(context): + g.days += 1 # 动态调整策略参数 @@ -55,11 +78,13 @@ def adjust_dynamic_parameters(context): def select_stocks(context): # 加载AI模型预测数据 g=context.g + print(g) now_date = context.current_dt.strftime('%Y%m%d') preds_data=g.preds # 筛选今日预测数据,并排序 pred_today = preds_data[preds_data['trade_date'] == now_date] pred_today_sorted = pred_today.sort_values(by='pred', ascending=False) + print(pred_today_sorted) # 返回股票列表 return pred_today_sorted['ts_code'].tolist() @@ -71,7 +96,9 @@ def should_sell(stock, context): if current_price==None: return False cost_price = context.portfolio.positions[stock].cost_basis + print(f"{stock}的当前价为{current_price},均价为{cost_price},止损价为{cost_price * g.stop_loss_threshold},止盈价为{cost_price * g.stop_gain_threshold}") if current_price <= cost_price * g.stop_loss_threshold or current_price >= cost_price * g.stop_gain_threshold: + print('触发卖出条件') return True return False @@ -106,17 +133,17 @@ def trade_open(context): successed=successed+1 if successed>=num_stocks_to_buy: break - g.days += 1 # 盘尾逻辑 def trade_close(context): - # sync(context) + sync(context) g=context.g adjust_dynamic_parameters(context) # 卖出逻辑 for stock in list(context.portfolio.positions.keys()): if should_sell(stock, context): - order_target_value(stock, 0) \ No newline at end of file + order_target_value(stock, 0) + g.days += 1 \ No newline at end of file diff --git a/examples/demo-project/testmodule/default/default_testmodule.py b/examples/demo-project/testmodule/default/default_testmodule.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/__init__.py b/examples/demo-project/trader/__init__.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/miniqmt/__init__.py b/examples/demo-project/trader/miniqmt/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/examples/demo-project/trader/miniqmt/calendar.py b/examples/demo-project/trader/miniqmt/calendar.py new file mode 100755 index 0000000..8fc6585 --- /dev/null +++ b/examples/demo-project/trader/miniqmt/calendar.py @@ -0,0 +1,19 @@ +from finhack.library.mydb import mydb +class Calendar: + def get_calendar(start_time,end_time,market): + start_time=start_time.replace('-','')[0:8] + end_time=end_time.replace('-','')[0:8] + calendar={} + + if market=='astock': + calendar=Calendar.get_astock_calendar(start_time,end_time) + calendar = [f"{date[:4]}-{date[4:6]}-{date[6:]}" for date in calendar] + return calendar + + + #获取A股交易日历 + def get_astock_calendar(start_time,end_time): + cal=mydb.selectToDf(f"select cal_date from astock_trade_cal where is_open=1 \ + and exchange='SSE' and cal_date>={start_time} and cal_date<={end_time} \ + order by cal_date asc",'tushare') + return cal['cal_date'].tolist() \ No newline at end of file diff --git a/examples/demo-project/trader/miniqmt/context.py b/examples/demo-project/trader/miniqmt/context.py new file mode 100755 index 0000000..e38886f --- /dev/null +++ b/examples/demo-project/trader/miniqmt/context.py @@ -0,0 +1,120 @@ +from trader.miniqmt.dictobj import DictObj + + +g=DictObj({ + 'preds':None +}) + + +context_attr= { + 'id':'', + 'universe':[], + 'previous_date':None, + 'current_dt':None, + 'params':None, + 'trade':DictObj({ + 'market':'', + 'model_id':'', + 'start_time':'', + 'end_time':'', + 'benchmark':'000001', + 'log_type':'', + 'record_type':'', + 'strategy':'', + 'order_volume_ratio':1, + 'slip':0, + 'sliptype':'pricerelated', + 'rule_list':'' + }), + 'g':g, + 'account':DictObj({ + 'username':'', + 'password':'', + 'account_id':'', + 'open_tax':0, + 'close_tax':0.001, + 'open_commission':0.0003, + 'close_commission':0.0003, + 'close_today_commission':0, + 'min_commission':5 + + }), + + 'portfolio':DictObj({ + 'inout_cash':0, + 'cash':0, + 'transferable_cash':0, + 'locked_cash':0, + 'margin':0, + 'total_value':0, + 'previous_value':0, + 'returns':0, + 'starting_cash':0, + 'positions_value':0, + 'portfolio_value':0, + 'locked_cash_by_purchase':0, + 'locked_cash_by_redeem':0, + 'locked_amound_by_redeen':0, + 'positions':{ + + } + }), + + 'data':DictObj({ + 'calendar':[], + 'event_interval_list':[], + 'event_list':[], + 'data_source':'file', + 'daily_info':None, + 'dividend':{}, + 'quote':None, + 'client':None + }), + + 'logs':DictObj({ + 'trade_list':[], + 'order_list':[], + 'position_list':[], + 'return_list':[], + 'trade_returns':[], + 'history':{} + }), + 'performance':DictObj({ + 'returns':[], + 'bench_returns':[], + 'turnover':[], + 'win':0, + 'win_ratio':0, + 'trade_num':0, + 'indicators':{} + }) + + } +context=DictObj(context_attr) + + + + + #'position':{ + # 'xxx':sid 标的代码 + # enable_amount 可用数量 + # amount 总持仓数量 + # last_sale_price 最新价格 + # cost_basis 持仓成本价格(期货不支持) + # today_amount 今日开仓数量(期货不支持,且仅回测有效) + # 期货专用字段: + # delivery_date 交割日,期货使用 + # today_short_amount 空头今仓数量 + # today_long_amount 多头今仓数量 + # long_cost_basis 多头持仓成本 + # short_cost_basis 空头持仓成本 + # margin_rate 保证金比例 + # contract_multiplier 合约乘数 + # long_amount 多头总持仓量 + # short_amount 空头总持仓量 + # long_pnl 多头浮动盈亏 + # short_pnl 空头浮动盈亏 + # long_enable_amount 多头可用数量 + # short_enable_amount 多空头可用数量 + # business_type 业务类型 + # }, \ No newline at end of file diff --git a/examples/demo-project/trader/miniqmt/data.py b/examples/demo-project/trader/miniqmt/data.py new file mode 100755 index 0000000..3c656b9 --- /dev/null +++ b/examples/demo-project/trader/miniqmt/data.py @@ -0,0 +1,24 @@ +from finhack.library.config import Config +from runtime.constant import * +from finhack.market.astock.astock import AStock +import json +import pickle +import pandas as pd +import os +import time +from datetime import datetime +import trader.miniqmt.calendar +import finhack.library.log as Log +from finhack.core.classes.dictobj import DictObj +from trader.miniqmt.qmtClient import qclient + + +class Data: + def get_daily_info(code,context,date=None): + return qclient.getInfo(code) + + #根据当前时间获取价格 + def get_price(code,context=None): + return qclient.getPrice(code) + + diff --git a/examples/demo-project/trader/miniqmt/dictobj.py b/examples/demo-project/trader/miniqmt/dictobj.py new file mode 100755 index 0000000..835740d --- /dev/null +++ b/examples/demo-project/trader/miniqmt/dictobj.py @@ -0,0 +1,92 @@ +import json +class DictObj: + def __init__(self, attr=None): + if attr is None: + attr = {} + # 确保所有字典都被封装为 DictObj + for key, value in attr.items(): + if isinstance(value, dict): + attr[key] = DictObj(value) + self._attributes = attr + + + def __getstate__(self): + # 在序列化时调用,返回对象的状态 + # 将所有 DictObj 实例转换为普通字典 + state = self._attributes.copy() + for key, value in state.items(): + if isinstance(value, DictObj): + state[key] = value.__getstate__() # 递归调用以处理嵌套的 DictObj + return state + + + def __setstate__(self, state): + # 在反序列化时调用,使用保存的状态重新构建对象 + # 将所有普通字典转换回 DictObj 实例 + for key, value in state.items(): + if isinstance(value, dict): + state[key] = DictObj(value) # 递归调用以处理嵌套的字典 + self._attributes = state + + + def get(self, key, default=None): + return self._attributes.get(key, default) + + def __iter__(self): + return iter(self._attributes) + + def __getitem__(self, key): + return self._attributes[key] + + def __setitem__(self, key, value): + if isinstance(value, dict): + value = DictObj(value) + self._attributes[key] = value + + def __getattr__(self, name): + try: + return self._attributes[name] + except KeyError: + raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") + + def __setattr__(self, name, value): + if name == "_attributes": + super().__setattr__(name, value) + else: + if isinstance(value, dict): + value = DictObj(value) + self._attributes[name] = value + + def __contains__(self, key): + return key in self._attributes + + def keys(self): + return self._attributes.keys() + + def values(self): + return self._attributes.values() + + def __len__(self): + return len(self._attributes) + + def items(self): + return self._attributes.items() + + def __str__(self): + attributes = ', '.join(f"{key}={value!r}" for key, value in self._attributes.items()) + return f"{type(self).__name__}({attributes})" + + def __delitem__(self, key): + del self._attributes[key] + + def push(self, key, value): + """添加或更新字典中的键值对。""" + self[key] = value + + def pop(self, key, default=None): + """从字典中移除指定的键并返回其值,如果键不存在,则返回default。""" + return self._attributes.pop(key, default) + + def to_json(self): + """将对象转换为JSON字符串。""" + return json.dumps(self.__getstate__(), ensure_ascii=False) \ No newline at end of file diff --git a/examples/demo-project/trader/miniqmt/event.py b/examples/demo-project/trader/miniqmt/event.py new file mode 100755 index 0000000..ef9eb48 --- /dev/null +++ b/examples/demo-project/trader/miniqmt/event.py @@ -0,0 +1,183 @@ +from trader.miniqmt.data import Data +import finhack.library.log as Log +from trader.miniqmt.function import * +import pandas as pd +from datetime import datetime, timedelta +from finhack.trainer.trainer import Trainer +from finhack.trainer.lightgbm.lightgbm_trainer import LightgbmTrainer +class Event: + def __init__(self): + pass + + def get_event(): + event={} + event['default']={ + 'start_interval':'00:00:00', + 'start_market':'00:00:00', + 'end_market':'23:59:59', + 'end_interval':'23:59:59' + } + + event['astock']={ + 'start_interval':'00:00:00', + 'before_market':'09:10:00', + #'before_market':'02:40:00', + 'pre_opening_start':'09:15:00', + 'pre_opening_end':'09:20:00', + 'matching_start':'09:25:00', + 'morning_start':'09:30:00', + 'morning_end':'11:30:00', + 'afternoon_start':'13:00:00', + 'closing_start':'14:57:00', + 'closing_end':'15:00:00', + 'afternoon_end':'15:00:00', + 'after_market':'18:00:00', + 'end_interval':'23:59:59' + } + + event['astock'] = {**event['default'], **event['astock']} + event['astock'] = sorted(event['astock'].items(), key=lambda x: x[1]) + return event + + + def load_daily_event(context,date): + event_list=[] + daily_event_list=Event.get_event() + for event_interval in context['data']['event_interval_list']: + if event_interval['event_interval']=='daily': + event_interval['event_time']=date+" "+event_interval['time'] + event_list.append(event_interval) + + for event_name,event_time in daily_event_list['astock']: + if hasattr(Event, event_name): + func = getattr(Event, event_name) + new_event={ + 'event_name':event_name, + #'event_func':func, + 'event_time':date+' '+event_time, + 'event_type':'market_event' + } + event_list.append(new_event) + event_list.sort(key=lambda x: x['event_time']) + return event_list + + def load_event(context,start_time,end_time): + event_list=[] + daily_event_list=Event.get_event() + calendar=context['data']['calendar'] + for date in calendar: + for event_name,event_time in daily_event_list['astock']: + if hasattr(Event, event_name): + func = getattr(Event, event_name) + new_event={ + 'event_name':event_name, + #'event_func':func, + 'event_time':date+' '+event_time, + 'event_type':'market_event' + } + context['data']['event_list'].append(new_event) + context['data']['event_list'].sort(key=lambda x: x['event_time']) + + return True + + + def start_interval(context): + now_date=context.current_dt.strftime('%Y%m%d') + start_date=context.trade.start_time[0:10].replace('-','') + end_date=context.trade.end_time[0:10].replace('-','') + print("新的一天开始了"+now_date) + + pass + + + + def before_market(context): + # 获取今天的日期 + today = datetime.today().strftime('%Y%m%d') + # 获取今天前三天的日期 + thirty_days_ago = (datetime.today() - timedelta(days=15)).strftime('%Y%m%d') + model_id=context.trade.model_id + preds=load_preds_data(model_id=model_id,start_time=thirty_days_ago,end_time=today) + context.g.preds=preds + return True + + + + + + #开盘卖出退市股 + def morning_start(context): + for code,pos in context.portfolio.positions.items(): + info=Data.get_daily_info(code=code,context=context) + #print(info) + if info!=None and "退" in info.name: + order_target_value(code,0) + log(f"{code}即将退市,自动卖出!") + + + + #盘后更新 + #处理分红事件,计算持仓信息 + def after_market(context): + Event.update_cash_div_tax(context) + + + + def update_cash_div_tax(context): + pass + + + + def end_interval(context): + Event.update_value(context) + Event.log_turnover(context) + log('---------------------------------') + log(f"当前现金:"+str(context.portfolio.cash)) + log(f"当前持仓:"+str(context.portfolio.positions_value)) + log(f"当前市值:"+str(context.portfolio.total_value)) + log(f"昨日市值:"+str(context.portfolio.previous_value)) + log(f"今日收益:"+str(context.performance.returns[- 1])) + + def update_value(context): + now_date=context.current_dt.strftime('%Y%m%d') + positions_value=0 + for code,pos2 in context.portfolio.positions.items(): + price=Data.get_price(code=code,context=context) + pos=context.portfolio.positions[code] + if price==None: + pass + else: + pos.total_value=pos.amount*price + pos.last_sale_price=price + positions_value=positions_value+pos.total_value + context.portfolio.previous_value=context.portfolio.total_value + context.portfolio.total_value=positions_value+context.portfolio.cash + context.portfolio.positions_value=positions_value + context.performance.returns.append([now_date,context.portfolio.total_value/context.portfolio.previous_value]) + + + def log_turnover(context): + now_date=context.current_dt.strftime('%Y%m%d') + if now_date not in context.logs.history: + context.logs.history[now_date]={} + context.logs.history[now_date]['postion']=context.portfolio.positions + sell_value = context.logs.history.get(now_date, {}).get('sell_value', 0) + buy_value = context.logs.history.get(now_date, {}).get('buy_value', 0) + context.performance.turnover.append(round((sell_value+buy_value)*100/context.portfolio.total_value,2)) + + + + + # sell_value = instance['history'].get(now_date, {}).get('sell_value', 0) + # buy_value = instance['history'].get(now_date, {}).get('buy_value', 0) + # instance['turnover'].append(round((sell_value+buy_value)*100/instance['total_value'],2)) + + # bt.log(instance,"账户余额:"+str(instance['total_value'])+","+now_date) + # if instance['total_value']<0 : + # print("余额小于0") + # print(instance['cash']) + # print(positions_value) + + # exit() + + # return True \ No newline at end of file diff --git a/examples/demo-project/trader/miniqmt/function.py b/examples/demo-project/trader/miniqmt/function.py new file mode 100755 index 0000000..ea57c8c --- /dev/null +++ b/examples/demo-project/trader/miniqmt/function.py @@ -0,0 +1,367 @@ +from trader.miniqmt.context import context +from trader.miniqmt.data import Data +from trader.miniqmt.object import Order,Position +from trader.miniqmt.rules import Rules +from trader.miniqmt.qmtClient import qclient +import re +from finhack.library.config import Config +import bisect +import redis +import finhack.library.log as Log +import hashlib +import json +from runtime.constant import * +import os +import pandas as pd +from finhack.trainer.trainer import Trainer +import shutil +from datetime import datetime, timedelta +from finhack.trainer.lightgbm.lightgbm_trainer import LightgbmTrainer + +def init_context(args): + args=args.__dict__ + + context['params']=args['params'] + context['trade']['market']=args['market'] + context['trade']['start_time']=args['start_time'] + context['trade']['end_time']=args['end_time'] + context['trade']['benchmark']=args['benchmark'] + context['trade']['strategy']=args['strategy'] + strategy_path=f"{BASE_DIR}/strategy/{args['strategy']}.py" + with open(strategy_path, 'r', encoding='utf-8') as file: + context['trade']['strategy_code'] = file.read() + + if args['params']!=None and args['params']!='': + params=json.loads(args['params']) + context['params']=params + if 'model_id' in params: + context['trade']['model_id']=params['model_id'] + else: + context['params']={} + if args['model_id']!='': + context['trade']['model_id']=args['model_id'] + + context['trade']['slip']=float(args['slip']) + context['trade']['sliptype']=args['sliptype'] + context['trade']['rule_list']=args['rule_list'] + + + context['account']['username']=args['username'] + context['account']['password']=args['password'] + context['account']['account_id']='' + + + context['account']['open_tax']=args['open_tax'] + context['account']['close_tax']=args['close_tax'] + context['account']['open_commission']=args['open_commission'] + context['account']['close_commission']=args['close_commission'] + context['account']['close_today_commission']=args['close_today_commission'] + context['account']['min_commission']=args['min_commission'] + + context['portfolio']['previous_value']=float(args['cash']) + context['portfolio']['total_value']=float(args['cash']) + context['portfolio']['cash']=float(args['cash']) + context['portfolio']['starting_cash']=float(args['cash']) + context['data']['data_source']=args['data_source'] + + if args['data_source']=='redis': + cfg=Config.get_config('db','redis') + redisPool = redis.ConnectionPool(host=cfg['host'],port=int(cfg['port']),password=cfg['password'],db=int(cfg['db'])) + client = redis.Redis(connection_pool=redisPool) + context.data.client=client + + context_json = str(args)+str(context['trade'])+str(context['account'])+str(context['portfolio']['cash']) + hash_value = hashlib.md5(context_json.encode()).hexdigest() + if args['id']!='': + context.id=args['id'] + else: + context.id=hash_value + qclient.assetSync(context) + qclient.positionSync(context) + + + + +def set_benchmark(code): + context['trade']['benchmark']=code + +def set_option(key,value): + if key in context['trade']: + context['trade'][key]=value + elif key in context['account']: + context['account'][key]=value + elif key in context['portfolio']: + context['portfolio'][key]=value + pass + +def set_order_cost(cost,type=None): + pass + +def set_slippage(obj,type=None): + pass + +def insert_sorted_list(sorted_list, new_element): + bisect.insort(sorted_list, new_element, key=lambda x: x['event_time']) + +def run_interval(func,time,interval='daily',date_list=[]): + if time=='every_bar': + time='00:00:01' + pattern = r"\d{1,2}:\d{2}" + match = re.match(pattern, time) + if match and time.count(':')==1: + hours, minutes = time.split(":") + time = f"{hours.zfill(2)}:{minutes.zfill(2)}:00" + + + event_interval={ + 'event_name':func.__name__, + 'event_interval':interval, + 'time':time, + 'event_type':'user_event' + } + context['data']['event_interval_list'].append(event_interval) + + # for date in date_list: + # new_event={ + # 'event_name':func.__name__, + # #'event_func':func, + # 'event_time':date+' '+time, + # 'event_type':'user_event' + # } + # context['data']['event_list'].append(new_event) + # context['data']['event_list'].sort(key=lambda x: x['event_time']) + + +def run_daily(func,time,reference_security=None): + return run_interval(func,time,'daily',date_list=context['data']['calendar']) + + +# #这个函数是按交易日,预留,懒得写逻辑 +# def run_tmonthly(func, monthday, time='9:30', reference_security=None, force=False): +# return run_interval(func,time,interval='monthly',days=monthday) + +# #此处和聚宽有差异,这里是自然日 +# def run_monthly(func, monthday, time='9:30', reference_security=None, force=False): +# return run_interval(func,time,interval='monthly',days=monthday) + +# # 按周运行 +# def run_weekly(func, weekday, time='9:30', reference_security=None, force=False): +# return run_interval(func,time,interval='daily',days=weekday) + + +def inout_cash(cash,pindex=None): + context['portfolio']['cash']=context['portfolio']['cash']+cash + + + +#目标股数下单 +def order_target(security, amount, style=None, side='long', pindex=0, close_today=False): + pass + + cash=context['portfolio']['available_cash'] + context['portfolio']['cash']=context['portfolio']['cash']+cash + context['portfolio']['available_cash']=context['portfolio']['available_cash']+cash + + +#按股数下单 +def order(security, amount, style=None, side='long', pindex=0, close_today=False): + if amount>0: + return order_buy(security,amount,9999) + else: + return order_sell(security,-amount,-1) + + + + +#按价值下单 +def order_value(security, value, style=None, side='long', pindex=0, close_today=False): + price=Data.get_price(code=security,context=context) + if price==0: + return False + #print(price) + if price==None: + #print(f"can not get price of {security}") + return False + if value>0: + amount=int(value/price) + return order_buy(security,amount,9999) + elif value<0: + amount=-int(value/price) + return order_sell(security,amount,-1) + + +# #目标股数下单 +# def order_target(security, amount, style=None, side='long', pindex=0, close_today=False): +# if amount>0: +# order_buy(security,amount) +# else: +# order_sell(security,amount) + + +#目标价值下单 +def order_target_value(security, value, style=None, side='long', pindex=0, close_today=False): + price=Data.get_price(code=security,context=context) + if price==None: + #print(f"can not get price of {security}") + return False + target_amount=int(value/price) + now_amount=context.portfolio.positions[security].amount + change_amount=target_amount-now_amount + return order(security,change_amount) + + # now_value=0 + # price=Data.get_price(code=security,context=context) + # if price==None: + # #print(f"can not get price of {security}") + # return + # if security in context.portfolio.positions: + # pos=context.portfolio.positions[security] + # now_value=pos.amount*price + # print("order_target_value",value,now_value) + # print("last_price:"+str(pos.last_sale_price)) + # print("now_price:"+str(price)) + # print("diff:"+str(price/pos.last_sale_price)) + # order_value(security,value-now_value) + + + +#cancel_order 撤单 +def cancel_order(order): + pass + +#获取未完成订单 +def get_open_orders(): + pass + +#获取订单信息 +def get_orders(order_id=None, security=None, status=None): + pass + +#获取成交信息 +def get_trades(): + pass + + + + +# total_value: 总的权益, 包括现金, 保证金(期货)或者仓位(股票)的总价值, 可用来计算收益 +# returns: 总权益的累计收益;(当前总资产 + 今日出入金 - 昨日总资产) / 昨日总资产; +# starting_cash: 初始资金, 现在等于 inout_cash +# positions_value: 持仓价值 +#买入 + + +# class Position(): +# def __init__(self,code,amount,enable_amount,last_sale_price): +# self.code=code +# self.amount=amount +# self.enable_amount=enable_amount +# self.last_sale_price=last_sale_price +# self.cost_basis=last_sale_price +# self.total_value=amount*last_sale_price + +def order_buy(security,amount,price=None): + log(f"调用order_buy买入{security}共{amount}股,价格为{str(None)}") + o=Order(code=security,amount=amount,is_buy=True,context=context) + rules=Rules(order=o,context=context,log=log) + o=rules.apply() + + if o.status!=1: + return False + if o.amount==0: + #log(f"{o.code}--{o.amount},买单数为0,自动取消订单") + return False + if price!=None: + o.price=price + qclient.OrderBuy(o.code,o.amount,o.price) + log(f"下单买入{o.code}共计{o.amount}股,单价{o.price}") + return True + + +def order_sell(security,amount,price=None): + log(f"调用order_sell卖出{security}共{amount}股,价格为{str(None)}") + o=Order(code=security,amount=amount,is_buy=False,context=context) + rules=Rules(order=o,context=context,log=log) + o=rules.apply() + if o.status!=1: + return False + if o.amount==0: + log(f"{o.code}--{o.amount},卖单数为0,自动取消订单") + return False + if price!=None: + o.price=price + qclient.OrderSell(o.code,o.amount,o.price) + log(f"下单卖出{o.code}共计{o.amount}股,单价{o.price}") + return True + + + + + + +def log(message,level='info'): + if context.current_dt==None: + msg='0000-00-00 00:00:00'+" - "+message + else: + msg=str(context.current_dt)+" - "+message + if level == 'info': + Log.tlogger.info(msg) + elif level == 'error': + Log.tlogger.error(msg) + elif level in ['trace', 'debug', 'success', 'warning', 'critical']: + getattr(Log.tlogger, level)(msg) + else: + Log.tlogger.info(msg) + + + +def load_preds_data(model_id,cache=False,trainer='lightgbm',start_time="",end_time=""): + pred_data_path=PREDS_DIR+f"model_{model_id}_pred.pkl" + if cache==True: + try: + if os.path.isfile(pred_data_path): + pred_data=pd.read_pickle(pred_data_path) + return pred_data + except Exception as e: + pass + + start_time=context.trade.start_time if start_time=="" else start_time + end_time=context.trade.end_time if end_time=="" else end_time + start_date=start_time.replace("-",'')[0:8] + end_date=end_time.replace("-",'')[0:8] + preds_df=Trainer.getPredData(model_id,start_date,end_date) + clsLgbTrainer=LightgbmTrainer() + preds=clsLgbTrainer.pred(preds_df,md5=model_id,save=False) + + if cache==True: + preds.to_pickle(pred_data_path) + return preds + +def delete_preds_data(model_id): + pred_data_path=PREDS_DIR+f"model_{model_id}_pred.pkl" + if os.path.exists(pred_data_path): + os.remove(pred_data_path) + + + +def bind_action(strategy): + strategy.set_benchmark=set_benchmark + strategy.set_option=set_option + strategy.set_order_cost=set_order_cost + strategy.set_slippage=set_slippage + strategy.run_daily=run_daily + #懒得写逻辑,后面补吧 + # strategy.run_weekly=run_weekly + # strategy.run_monthly=run_monthly + strategy.inout_cash=inout_cash + strategy.order_value=order_value + strategy.order_target_value=order_target_value + strategy.order_buy=order_buy + strategy.order_sell=order_sell + strategy.log=log + strategy.load_preds_data=load_preds_data + strategy.get_price=Data.get_price + strategy.sync=qclient.sync + + + diff --git a/examples/demo-project/trader/miniqmt/miniqmt_trader.py b/examples/demo-project/trader/miniqmt/miniqmt_trader.py new file mode 100755 index 0000000..6a8d710 --- /dev/null +++ b/examples/demo-project/trader/miniqmt/miniqmt_trader.py @@ -0,0 +1,168 @@ +from runtime.constant import * +import runtime.global_var as global_var +from finhack.library.class_loader import ClassLoader +import cloudpickle as pickle +import sys +import os +import importlib +import finhack.library.log as Log +from trader.miniqmt.calendar import Calendar +from trader.miniqmt.event import Event +from trader.miniqmt.data import Data +from trader.miniqmt.function import * +from trader.miniqmt.object import * +from trader.miniqmt.context import context +from datetime import datetime, timedelta +import time +from functools import partial + +#finhack trader run --model_id=f7fd6531b6ec1ad6bc884ec5c6faeedb --strategy=ChatgptAIStrategy --vendor=qmt + +class MiniqmtTrader: + def load_strategy(self,strategy_name): + if os.path.exists(f"{BASE_DIR}/strategy/{strategy_name}.py"): + module_spec = importlib.util.spec_from_file_location('strategy', f"{BASE_DIR}/strategy/{strategy_name}.py") + strategy_module = importlib.util.module_from_spec(module_spec) + module_spec.loader.exec_module(strategy_module) + return strategy_module + else: + Log.logger.error(f"{BASE_DIR}strategy/{strategy_name}.py NotFound") + pass + + + def status(self): + # 查询状态 + context.id=self.args.id + loaded_context = self.load_context(context) + print(loaded_context.g) + + + + + def save_context(self,context): + context_id=context.id + running_dir = RUNNING_DIR + context_file_path = os.path.join(running_dir, f"{context_id}.pkl") + with open(context_file_path, 'wb') as context_file: + pickle.dump(context, context_file) + Log.logger.info(f"Context saved to {context_file_path}") + + def load_context(self,context): + context_id=context.id + running_dir = RUNNING_DIR + context_file_path = os.path.join(running_dir, f"{context_id}.pkl") + if os.path.exists(context_file_path): + with open(context_file_path, 'rb') as context_file: + loaded_context = pickle.load(context_file) + Log.logger.info(f"Context loaded from {context_file_path}") + return loaded_context + else: + Log.logger.error(f"Context file {context_file_path} not found") + return None + + + def run(self,args=None): + global context + if args!=None: + self.args=args + + t1=time.time() + starttime=datetime.now().strftime("%Y-%m-%d %H:%M:%S") + init_context(self.args) + loaded_context = self.load_context(context) + if loaded_context is not None: + context = loaded_context + else: + pass + + + start_time=context['trade']['start_time'] + end_time=context['trade']['end_time'] + market=context['trade']['market'] + + Log.tlogger=Log.tLog(context.id,logs_dir=LOGS_DIR,background=self.args.background,level=self.args.log_level).logger + log("正在初始化交易上下文") + log("正在获取交易日历") + + calendar=Calendar.get_calendar(start_time,end_time,market=market) + + log("正在加载交易策略") + strategy=self.load_strategy(context['trade']['strategy']) + context['data']['calendar']=calendar + + log("正在绑定交易对象") + bind_object(strategy) + + log("正在绑定交易动作") + bind_action(strategy) + strategy.log=Log.logger + strategy.g=context.g + + if loaded_context is not None: + pass + else: + log("正在初始化事件列表") + event_list=Event.load_event(context,start_time,end_time) + log("正在初始化策略") + strategy.initialize(context) + + self.save_context(context) + + print(context.g) + + + while True: + # 获取当前日期 + now = datetime.now() + # 将日期格式化为"yyyymmdd" + today = now.strftime("%Y-%m-%d") + if today not in calendar: + # 计算到第二天0点的秒数 + midnight = datetime.combine(now + timedelta(days=1), datetime.min.time()) + seconds_until_midnight = (midnight - now).total_seconds() + # 暂停程序直到第二天0点 + log(f"不在交易日历,sleep{seconds_until_midnight}秒") + time.sleep(seconds_until_midnight) + else: + event_list=Event.load_daily_event(context,today) + while event_list: + event = event_list.pop(0) + event_time = datetime.strptime(event['event_time'], '%Y-%m-%d %H:%M:%S') + current_time = datetime.now() # 去除毫秒部分 + context.current_dt=current_time + + # 如果 event_time 比当前时间晚,则将事件放回列表并等待 + if event_time > current_time: + event_list.insert(0, event) # 将事件放回列表 + time_to_wait = (event_time - current_time).total_seconds() + log(f"下次事件时间{event_time},将在{time_to_wait}秒后执行,正在sleep等待…") + time.sleep(time_to_wait) # 等待直到事件时间到达 + else: + # 如果 event_time 在当前时间的10秒钟以内 + if 0 <= (current_time - event_time).total_seconds() < 10: + log(f"执行{event['event_name']}") + + if event['event_type']=="market_event": + event_func = getattr(Event, event['event_name'],None) + elif event['event_type']=="user_event": + event_func = getattr(strategy, event['event_name'],None) + else: + log(f"未知时间{event['event_name']}") + if event_func==None: + time.sleep(1) + else: + event_func(context) + else: + continue # 如果时间早于当前时间超过10秒,则跳过此事件 + + # 更新context的日期信息 + if context.previous_date is None or context.current_dt is None: + pass + elif context.current_dt.date() != event_time.date(): + context.previous_date = context.current_dt.date() + #context.current_dt = event_time + self.save_context(context) + + + + log("全部事件执行完毕") \ No newline at end of file diff --git a/examples/demo-project/trader/miniqmt/object.py b/examples/demo-project/trader/miniqmt/object.py new file mode 100755 index 0000000..ce537b1 --- /dev/null +++ b/examples/demo-project/trader/miniqmt/object.py @@ -0,0 +1,155 @@ +import hashlib +import time +from trader.miniqmt.data import Data + +class OrderCost: + def __init__(self,open_tax=0, close_tax=0.001,open_commission=0.0003, close_commission=0.0003,close_today_commission=0, min_commission=5): + self.open_tax=open_tax + self.close_tax=close_tax + self.open_commission=open_commission + self.close_commission=close_commission + self.close_today_commission=close_today_commission + self.min_commission=min_commission + pass + + + +class Order(): + def __init__(self,code='',amount='',is_buy=True,side='long',action='',context=None): + self.code=code + self.amount=amount + self.enable_amount=amount + self.filled=0 + self.info=Data.get_daily_info(code=code,context=context) + print(self.info) + self.price=Data.get_price(code=code,context=context) + self.order_id = self.generate_order_id() + self.is_buy=is_buy + self.cost=0 + self.slip_value=0 #滑点滑掉了多少 + self.last_sale_price=None + #正常 + self.status=-1 if self.price==None else 1 + + + + def generate_order_id(self): + timestamp = str(int(time.time() * 1000000)) + data = f"{self.code}_{self.amount}_{timestamp}".encode('utf-8') + hash_object = hashlib.sha256(data) + order_id = hash_object.hexdigest() + return order_id + + +class Position(): + def __init__(self,code,amount,enable_amount,last_sale_price): + self.code=code + self.amount=amount + self.enable_amount=enable_amount + self.last_sale_price=last_sale_price + self.cost_basis=last_sale_price + self.total_value=amount*last_sale_price + self.total_cost=amount*last_sale_price + + + #'position':{ + # 'xxx':sid 标的代码 + # enable_amount 可用数量 + # amount 总持仓数量 + # last_sale_price 最新价格 + # cost_basis 持仓成本价格(期货不支持) + # today_amount 今日开仓数量(期货不支持,且仅回测有效) + # 期货专用字段: + # delivery_date 交割日,期货使用 + # today_short_amount 空头今仓数量 + # today_long_amount 多头今仓数量 + # long_cost_basis 多头持仓成本 + # short_cost_basis 空头持仓成本 + # margin_rate 保证金比例 + # contract_multiplier 合约乘数 + # long_amount 多头总持仓量 + # short_amount 空头总持仓量 + # long_pnl 多头浮动盈亏 + # short_pnl 空头浮动盈亏 + # long_enable_amount 多头可用数量 + # short_enable_amount 多空头可用数量 + # business_type 业务类型 + # }, + + + + # instance['positions'][ts_code]['total_value']=instance['positions'][ts_code]['total_value'] + # instance['positions'][ts_code]['amount']=instance['positions'][ts_code]['amount']+amount + # instance['positions'][ts_code]['avg_price']=(instance['positions'][ts_code]['total_value']+price+fees)/instance['positions'][ts_code]['amount'] + # instance['positions'][ts_code]['last_close']=price + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # slip,cost,limit + + + +# status: 状态, 一个OrderStatus值 +# add_time: 订单添加时间, [datetime.datetime]对象 +# is_buy: bool值, 买还是卖,对于期货: +# 开多/平空 -> 买 +# 开空/平多 -> 卖 +# amount: 下单数量, 不管是买还是卖, 都是正数 +# filled: 已经成交的股票数量, 正数 +# security: 股票代码 +# order_id: 订单ID +# price: 平均成交价格, 已经成交的股票的平均成交价格(一个订单可能分多次成交) +# avg_cost: 卖出时表示下卖单前的此股票的持仓成本, 用来计算此次卖出的收益. 买入时表示此次买入的均价(等同于price). +# side: 多/空,'long'/'short' +# action: 开/平, 'open'/'close' +# commission:交易费用(佣金、税费等) + + + +class FixedSlippage(): + def __init__(self,value): + self.value=value + self.type='fixed' + +class PriceRelatedSlippage(): + def __init__(self,value): + self.value=value + self.type='pricerelated' + +class StepRelatedSlippage(): + def __init__(self,value): + self.value=value + self.type='steprelated' + + +def bind_object(strategy): + strategy.OrderCost=OrderCost + strategy.FixedSlippage=FixedSlippage + strategy.PriceRelatedSlippage=PriceRelatedSlippage + strategy.StepRelatedSlippage=StepRelatedSlippage \ No newline at end of file diff --git a/examples/demo-project/trader/qmt/qmt.proto b/examples/demo-project/trader/miniqmt/qmt.proto similarity index 100% rename from examples/demo-project/trader/qmt/qmt.proto rename to examples/demo-project/trader/miniqmt/qmt.proto diff --git a/examples/demo-project/trader/miniqmt/qmtClient.py b/examples/demo-project/trader/miniqmt/qmtClient.py new file mode 100755 index 0000000..181c95e --- /dev/null +++ b/examples/demo-project/trader/miniqmt/qmtClient.py @@ -0,0 +1,192 @@ +import grpc +import trader.miniqmt.qmt_pb2 as qmt_pb2 +import trader.miniqmt.qmt_pb2_grpc as qmt_pb2_grpc +import time +import finhack.library.log as Log +from trader.miniqmt.dictobj import DictObj + +class qmtClient(): + def __init__(self) -> None: + self.channel = grpc.insecure_channel('192.168.8.119:50051') + # 使用该通道创建一个存根 + self.stub = qmt_pb2_grpc.QmtServiceStub(self.channel) + + def protobuf_to_dict(self,obj): + # Base case for recursion termination + if not hasattr(obj, 'DESCRIPTOR'): + return obj + + result = {} + for field in obj.DESCRIPTOR.fields: + value = getattr(obj, field.name) + # Convert repeated message fields to list of dicts + if field.message_type and field.label == field.LABEL_REPEATED: + result[field.name] = [self.protobuf_to_dict(v) for v in value] + # Convert non-repeated message fields to dict + elif field.message_type: + result[field.name] = self.protobuf_to_dict(value) + # Convert repeated scalar fields to list + elif field.label == field.LABEL_REPEATED: + result[field.name] = list(value) + # Convert scalar fields directly + else: + result[field.name] = value + return result + + def assetSync(self,context): + Log.logger.info("开始同步资产数据") + asset= self.getAsset() + context['portfolio']['cash']=asset['cash'] + context['portfolio']['transferable_cash']=asset['cash']-asset['frozen_cash'] + context['portfolio']['locked_cash']=asset['frozen_cash'] + context['portfolio']['total_value']=asset['total_value'] + context['portfolio']['positions_value']=asset['market_value'] + context['portfolio']['portfolio_value=0']=asset['market_value'] + Log.logger.info("结束同步资产数据") + return asset + + def positionSync(self,context): + Log.logger.info("开始同步持仓信息") + positions={ + + } + pos_list= self.GetPositions() + for pos in pos_list: + positions[pos['stock_code']]={ + "code":pos['stock_code'], + "amount":pos['volume'], + "enable_amount":pos['can_use_volume'], + "last_sale_price":pos['open_price'], + "cost_basis":pos['avg_price'], + "total_value":pos['market_value'], + } + context['portfolio']['positions']=positions + Log.logger.info("结束同步持仓信息") + return positions + + def sync(self,context): + Log.logger.info("同步实盘数据") + self.assetSync(context) + self.positionSync(context) + + + def getPrice(self,code): + try: + response=self.stub.GetPrice(qmt_pb2.PriceRequest(code=code)) + asset= self.protobuf_to_dict(response) + return asset['last_price'] + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + + def getInfo(self,code): + try: + response=self.stub.GetDailyInfo(qmt_pb2.DailyInfoRequest(code=code)) + info=self.protobuf_to_dict(response) + info['downLimit']=info['down_limit'] + info['upLimit']=info['up_limit'] + return DictObj(info) + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + def OrderBuy(self,code, amount, price=0, strategy='strategy', remark='remark'): + try: + Log.logger.info(f"向qmtServer下单买入{code}共{amount}股,单价{price}]") + response=self.stub.OrderBuy(qmt_pb2.OrderRequest(code=code, amount=amount, price=price, strategy=strategy, remark=remark)) + seq=self.protobuf_to_dict(response) + return seq['seq'] + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + def OrderSell(self,code, amount, price=0, strategy='strategy', remark='remark'): + try: + Log.logger.info(f"向qmtServer下单卖出{code}共{amount}股,单价{price}") + response=self.stub.OrderSell(qmt_pb2.OrderRequest(code=code, amount=amount, price=price, strategy=strategy, remark=remark)) + seq=self.protobuf_to_dict(response) + return seq + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + def QueryOrders(self): + try: + Log.logger.info(f"向qmtServer查询订单") + response=self.stub.QueryOrders(qmt_pb2.QueryOrdersRequest()) + orders=self.protobuf_to_dict(response) + return orders + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + def CancelOrders(self): + try: + response=self.stub.CancelOrders(qmt_pb2.QueryOrdersRequest()) + return True + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + def RetryOrders(self): + try: + response=self.stub.RetryOrders(qmt_pb2.QueryOrdersRequest()) + return True + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + def getAsset(self): + try: + response=self.stub.GetAsset(qmt_pb2.AssetRequest()) + asset=self.protobuf_to_dict(response) + return asset + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None + + def GetPositions(self): + try: + response=self.stub.GetPositions(qmt_pb2.AssetRequest()) + positions=self.protobuf_to_dict(response) + return positions['positions'] + except grpc._channel._InactiveRpcError as e: + Log.logger.error(f"RPC failed: {e.code()}") + Log.logger.error(f"Details: {e.details()}") + return None + except Exception as e: + Log.logger.error(f"An unexpected error occurred: {e}") + return None +qclient=qmtClient() \ No newline at end of file diff --git a/examples/demo-project/trader/qmt/qmt_pb2.py b/examples/demo-project/trader/miniqmt/qmt_pb2.py similarity index 100% rename from examples/demo-project/trader/qmt/qmt_pb2.py rename to examples/demo-project/trader/miniqmt/qmt_pb2.py diff --git a/examples/demo-project/trader/qmt/qmt_pb2_grpc.py b/examples/demo-project/trader/miniqmt/qmt_pb2_grpc.py similarity index 99% rename from examples/demo-project/trader/qmt/qmt_pb2_grpc.py rename to examples/demo-project/trader/miniqmt/qmt_pb2_grpc.py index 581cc2b..a564f40 100755 --- a/examples/demo-project/trader/qmt/qmt_pb2_grpc.py +++ b/examples/demo-project/trader/miniqmt/qmt_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -import trader.qmt.qmt_pb2 as qmt__pb2 +import trader.miniqmt.qmt_pb2 as qmt__pb2 class QmtServiceStub(object): diff --git a/examples/demo-project/trader/miniqmt/rules.py b/examples/demo-project/trader/miniqmt/rules.py new file mode 100755 index 0000000..e72173d --- /dev/null +++ b/examples/demo-project/trader/miniqmt/rules.py @@ -0,0 +1,232 @@ +import finhack.library.log as Log +import numpy as np +#涨跌停限制 +from trader.miniqmt.function import * + +class Rules(): + def __init__(self,order,context,log=None): + self.order=order + self.context=context + self.rule_list=context.trade.rule_list + if log==None: + self.log=print + else: + self.log=log + + def apply(self,rule_list=None): + if rule_list==None: + rule_list=self.rule_list + rule_list=rule_list.split(",") + + for rule in rule_list: + method_name = f"rule_{rule}" + if hasattr(self, method_name): + method = getattr(self, method_name) + result = method() + self.log(f"{self.order.code}在{method_name}时的订单量为{self.order.amount}",'debug') + if result==False: + self.log(f"{self.order.code}未通过{method_name}规则校验,订单取消!",'warning') + self.order.status=-1 + return self.order + + + #最后再计算一下价格和手续费 + if self.order.is_buy==True: + action='open' + else: + action='close' + value=self.order.amount*self.order.price + account=self.context.account + tax=value*0.001 + commission=value*0.0003 + cost=tax+commission + self.order.value=value + self.order.slip_value=self.context.trade.slip*value + self.order.cost=cost + self.order.last_sale_price=self.order.price + if self.order.last_sale_price==None: + self.order.status=-1 + return self.order + + + + #退市 + def rule_delist(self): + if self.order.price!=None and '退' in self.order.info.name: + self.order.filled=0 + self.log(f"{self.order.code}即将退市,不买入!",'warning') + return False + return True + + + + #ST + def rule_st(self): + if self.order.price!=None and 'ST' in self.order.info.name: + self.order.filled=0 + self.log(f"{self.order.code}ST股,不买入!",'warning') + return False + return True + + + #非主板 + def rule_mainboard(self): + #002也算进去 + if self.order.price!=None and not self.order.code.startswith(('600', '601', '603','000','002')): + self.order.filled=0 + self.log(f"{self.order.code}非主板,不买入!",'warning') + return False + return True + + #停牌 + def rule_stop(self): + if(np.isnan(self.order.price) or int(self.order.info.stop)==1 or self.order.price==0): + self.order.filled=0 + self.log(f"{self.order.code}停牌,无法买入!",'warning') + return False + return True + + + #涨跌停 + def rule_limit(self): + if self.order.is_buy==True: + #这里因为没有判断不限涨跌停的情况,所以加了个price==now_price['high'],但是不严谨 + if self.order.price>=self.order.info.upLimit and self.order.price==self.order.info.high: + self.log(f"{self.order.code}涨停,无法买入!",'warning') + self.order.filled=0 + return False + + else: + if self.order.price<=self.order.info.downLimit and self.order.price==self.order.info.low: + self.order.filled=0 + self.log(f"{self.order.code}跌停,无法卖出!",'warning') + return False + return True + + def rule_100(self): + print('---') + print(self.order.amount) + print(int(self.order.amount/100)*100) + print('---') + if self.order.amount!=int(self.order.amount/100)*100: + self.order.amount=int(self.order.amount/100)*100 + self.log(f"{self.order.code}自动调整交易数量为{self.order.amount}!",'warning') + return True + + + + #滑点 + def rule_slip(self): + #默认有滑点 + # if self.order.is_buy==True: + # self.order.price=self.order.price*(1+self.context.trade.slip) + # else: + # self.order.price=self.order.price*(1-self.context.trade.slip) + + # if self.order.is_buy==True: + # action='open' + # #这里其实应该用self.order.filled,但是怕后面有坑 + # value=self.order.amount*self.order.price + # account=self.context.account + # slip_value=self.context.trade.slip*value + # tax=value*account[action+"_tax"] + # commission=value*account[action+"_commission"] + # if commissionself.order.info.volume*self.context.trade.order_volume_ratio: + # #self.order.amount=self.order.info.volume*context.trade.order_volume_ratio + # self.order.filled=self.order.info.volume*self.context.trade.order_volume_ratio + # self.order.amount=self.order.info.volume*self.context.trade.order_volume_ratio + # self.log(f"{self.order.code}超过当日最大订单数量,已经自动调整。",'warning') + # else: + # self.order.filled=self.order.amount + return True + + + #手续费+税费 + def rule_cost(self): + # #应该是只有买入的时候才会有这个问题吧 + # if self.order.is_buy==True: + # action='open' + # #这里其实应该用self.order.filled,但是怕后面有坑 + # value=self.order.amount*self.order.price + # account=self.context.account + # tax=value*account[action+"_tax"] + # commission=value*account[action+"_commission"] + # if commissioncontext.portfolio.positions[self.order.code].enable_amount: + amount=context.portfolio.positions[self.order.code].enable_amount + + #如果是清仓 + if amount==context.portfolio.positions[self.order.code].amount: + self.order.amount=amount + self.order.filled=self.order.amount + return True + + + #非科创板 + if amount>0 and not self.order.code[:3]=='688': + if(amount<100): + amount=0 + if(amount % 100 !=0): + amount=int(amount/100)*100 + elif amount>0 and self.order.code[:3]=='688': + if(amount<200): + amount=0 + if amount>50000: + amount=50000 + self.order.amount=amount + self.order.filled=self.order.amount + return True + + #A股t+1策略 + def rule_t1(self): + self.order.enable_amount=0 + return True + + #t0策略 + def rule_t0(self): + self.order.enable_amount=self.order.amount + return True + + \ No newline at end of file diff --git a/examples/demo-project/trader/qmt/__init__.py b/examples/demo-project/trader/qmt/__init__.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/qmt/calendar.py b/examples/demo-project/trader/qmt/calendar.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/qmt/context.py b/examples/demo-project/trader/qmt/context.py old mode 100644 new mode 100755 index 651f6d9..3b91360 --- a/examples/demo-project/trader/qmt/context.py +++ b/examples/demo-project/trader/qmt/context.py @@ -62,6 +62,7 @@ 'data':DictObj({ 'calendar':[], + 'event_interval_list':[], 'event_list':[], 'data_source':'file', 'daily_info':None, diff --git a/examples/demo-project/trader/qmt/data.py b/examples/demo-project/trader/qmt/data.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/qmt/dictobj.py b/examples/demo-project/trader/qmt/dictobj.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/qmt/event.py b/examples/demo-project/trader/qmt/event.py old mode 100644 new mode 100755 index c97dd22..78899dc --- a/examples/demo-project/trader/qmt/event.py +++ b/examples/demo-project/trader/qmt/event.py @@ -20,7 +20,7 @@ def get_event(): event['astock']={ 'start_interval':'00:00:00', - 'before_market':'09:10:00', + 'before_market':'09:05:00', #'before_market':'07:52:00', 'pre_opening_start':'09:15:00', 'pre_opening_end':'09:20:00', @@ -38,6 +38,28 @@ def get_event(): event['astock'] = {**event['default'], **event['astock']} event['astock'] = sorted(event['astock'].items(), key=lambda x: x[1]) return event + + + def load_daily_event(context,date): + event_list=[] + daily_event_list=Event.get_event() + for event_interval in context['data']['event_interval_list']: + if event_interval['event_interval']=='daily': + event_interval['event_time']=date+" "+event_interval['time'] + event_list.append(event_interval) + + for event_name,event_time in daily_event_list['astock']: + if hasattr(Event, event_name): + func = getattr(Event, event_name) + new_event={ + 'event_name':event_name, + #'event_func':func, + 'event_time':date+' '+event_time, + 'event_type':'market_event' + } + event_list.append(new_event) + event_list.sort(key=lambda x: x['event_time']) + return event_list def load_event(context,start_time,end_time): event_list=[] @@ -54,7 +76,7 @@ def load_event(context,start_time,end_time): 'event_type':'market_event' } context['data']['event_list'].append(new_event) - context['data']['event_list'].sort(key=lambda x: x['event_time']) + context['data']['event_list'].sort(key=lambda x: x['event_time']) return True diff --git a/examples/demo-project/trader/qmt/function.py b/examples/demo-project/trader/qmt/function.py old mode 100644 new mode 100755 index 0f99593..c8a54e9 --- a/examples/demo-project/trader/qmt/function.py +++ b/examples/demo-project/trader/qmt/function.py @@ -112,16 +112,25 @@ def run_interval(func,time,interval='daily',date_list=[]): hours, minutes = time.split(":") time = f"{hours.zfill(2)}:{minutes.zfill(2)}:00" - for date in date_list: - new_event={ - 'event_name':func.__name__, - #'event_func':func, - 'event_time':date+' '+time, - 'event_type':'user_event' - } - context['data']['event_list'].append(new_event) - context['data']['event_list'].sort(key=lambda x: x['event_time']) - print(len(context['data']['event_list'])) + + event_interval={ + 'event_name':func.__name__, + 'event_interval':interval, + 'time':time, + 'event_type':'user_event' + } + context['data']['event_interval_list'].append(event_interval) + + # for date in date_list: + # new_event={ + # 'event_name':func.__name__, + # #'event_func':func, + # 'event_time':date+' '+time, + # 'event_type':'user_event' + # } + # context['data']['event_list'].append(new_event) + # context['data']['event_list'].sort(key=lambda x: x['event_time']) + def run_daily(func,time,reference_security=None): return run_interval(func,time,'daily',date_list=context['data']['calendar']) diff --git a/examples/demo-project/trader/qmt/object.py b/examples/demo-project/trader/qmt/object.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/qmt/qmtClient.py b/examples/demo-project/trader/qmt/qmtClient.py old mode 100644 new mode 100755 index d3513e9..8b946e4 --- a/examples/demo-project/trader/qmt/qmtClient.py +++ b/examples/demo-project/trader/qmt/qmtClient.py @@ -1,37 +1,28 @@ -import grpc -import trader.qmt.qmt_pb2 as qmt_pb2 -import trader.qmt.qmt_pb2_grpc as qmt_pb2_grpc import time import finhack.library.log as Log from trader.qmt.dictobj import DictObj +import requests +import json + class qmtClient(): - def __init__(self) -> None: - self.channel = grpc.insecure_channel('192.168.8.119:50051') - # 使用该通道创建一个存根 - self.stub = qmt_pb2_grpc.QmtServiceStub(self.channel) - - def protobuf_to_dict(self,obj): - # Base case for recursion termination - if not hasattr(obj, 'DESCRIPTOR'): - return obj - - result = {} - for field in obj.DESCRIPTOR.fields: - value = getattr(obj, field.name) - # Convert repeated message fields to list of dicts - if field.message_type and field.label == field.LABEL_REPEATED: - result[field.name] = [self.protobuf_to_dict(v) for v in value] - # Convert non-repeated message fields to dict - elif field.message_type: - result[field.name] = self.protobuf_to_dict(value) - # Convert repeated scalar fields to list - elif field.label == field.LABEL_REPEATED: - result[field.name] = list(value) - # Convert scalar fields directly - else: - result[field.name] = value - return result + def __init__(self, base_url='http://192.168.8.37:8000'): + self.base_url = base_url + + def send_request(self, endpoint, params=None): + """ Helper method to send HTTP GET requests """ + try: + response = requests.get(f"{self.base_url}{endpoint}", params=params) + response.raise_for_status() # Raises a HTTPError for bad responses + return response.json() # Returns JSON response + except requests.RequestException as e: + print(f"HTTP Request failed: {e}") + return None + + def getAsset(self): + """ Get asset information """ + return self.send_request('/get_asset') + def assetSync(self,context): Log.logger.info("开始同步资产数据") @@ -69,124 +60,44 @@ def sync(self,context): self.assetSync(context) self.positionSync(context) + def getPrice(self, code): + """ Get price for a specific stock code """ + params = {'code': code} + return self.send_request('/get_price', params=params) - def getPrice(self,code): - try: - response=self.stub.GetPrice(qmt_pb2.PriceRequest(code=code)) - asset= self.protobuf_to_dict(response) - return asset['last_price'] - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None + def getInfo(self, code): + """ Get daily information for a specific stock code """ + params = {'code': code} + info=self.send_request('/get_daily_info', params=params) + info['downLimit']=info['down_limit'] + info['upLimit']=info['up_limit'] + return DictObj(info) + def GetPositions(self): + """ Get positions """ + return self.send_request('/get_positions') + + def OrderBuy(self, code, amount, price=0, strategy='strategy', remark='remark'): + """ Send a buy order """ + params = {'code': code, 'amount': amount, 'price': price, 'strategy': strategy, 'remark': remark} + return self.send_request('/order_buy', params=params) + + def OrderSell(self, code, amount, price=0, strategy='strategy', remark='remark'): + """ Send a sell order """ + params = {'code': code, 'amount': amount, 'price': price, 'strategy': strategy, 'remark': remark} + return self.send_request('/order_sell', params=params) - def getInfo(self,code): - try: - response=self.stub.GetDailyInfo(qmt_pb2.DailyInfoRequest(code=code)) - info=self.protobuf_to_dict(response) - info['downLimit']=info['down_limit'] - info['upLimit']=info['up_limit'] - return DictObj(info) - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None - - def OrderBuy(self,code, amount, price=0, strategy='strategy', remark='remark'): - try: - Log.logger.info(f"向qmtServer下单买入{code}共{amount}股,单价{price}]") - response=self.stub.OrderBuy(qmt_pb2.OrderRequest(code=code, amount=amount, price=price, strategy=strategy, remark=remark)) - seq=self.protobuf_to_dict(response) - return seq['seq'] - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None - - def OrderSell(self,code, amount, price=0, strategy='strategy', remark='remark'): - try: - Log.logger.info(f"向qmtServer下单卖出{code}共{amount}股,单价{price}") - response=self.stub.OrderSell(qmt_pb2.OrderRequest(code=code, amount=amount, price=price, strategy=strategy, remark=remark)) - seq=self.protobuf_to_dict(response) - return seq - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None - def QueryOrders(self): - try: - Log.logger.info(f"向qmtServer查询订单") - response=self.stub.QueryOrders(qmt_pb2.QueryOrdersRequest()) - orders=self.protobuf_to_dict(response) - return orders - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None - + """ Query all orders """ + return self.send_request('/query_orders') + def CancelOrders(self): - try: - response=self.stub.CancelOrders(qmt_pb2.QueryOrdersRequest()) - return True - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None + """ Cancel all orders """ + return self.send_request('/cancel_orders') + def RetryOrders(self): - try: - response=self.stub.RetryOrders(qmt_pb2.QueryOrdersRequest()) - return True - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None + """ Retry failed orders """ + return self.send_request('/retry_orders') - def getAsset(self): - try: - response=self.stub.GetAsset(qmt_pb2.AssetRequest()) - asset=self.protobuf_to_dict(response) - return asset - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None - - def GetPositions(self): - try: - response=self.stub.GetPositions(qmt_pb2.AssetRequest()) - positions=self.protobuf_to_dict(response) - return positions['positions'] - except grpc._channel._InactiveRpcError as e: - Log.logger.error(f"RPC failed: {e.code()}") - Log.logger.error(f"Details: {e.details()}") - return None - except Exception as e: - Log.logger.error(f"An unexpected error occurred: {e}") - return None + qclient=qmtClient() \ No newline at end of file diff --git a/examples/demo-project/trader/qmt/qmt_trader.py b/examples/demo-project/trader/qmt/qmt_trader.py index 6d07512..7687511 100755 --- a/examples/demo-project/trader/qmt/qmt_trader.py +++ b/examples/demo-project/trader/qmt/qmt_trader.py @@ -12,7 +12,7 @@ from trader.qmt.function import * from trader.qmt.object import * from trader.qmt.context import context -from datetime import datetime +from datetime import datetime, timedelta import time from functools import partial @@ -29,6 +29,16 @@ def load_strategy(self,strategy_name): Log.logger.error(f"{BASE_DIR}strategy/{strategy_name}.py NotFound") pass + + def status(self): + # 查询状态 + context.id=self.args.id + loaded_context = self.load_context(context) + print(loaded_context.g) + + + + def save_context(self,context): context_id=context.id running_dir = RUNNING_DIR @@ -66,7 +76,6 @@ def run(self,args=None): pass - start_time=context['trade']['start_time'] end_time=context['trade']['end_time'] market=context['trade']['market'] @@ -89,7 +98,6 @@ def run(self,args=None): strategy.log=Log.logger strategy.g=context.g - if loaded_context is not None: pass else: @@ -99,38 +107,59 @@ def run(self,args=None): strategy.initialize(context) self.save_context(context) - while context.data.event_list: - event = context.data.event_list.pop(0) - event_time = datetime.strptime(event['event_time'], '%Y-%m-%d %H:%M:%S') - current_time = datetime.now() # 去除毫秒部分 - context.current_dt=current_time - - # 如果 event_time 比当前时间晚,则将事件放回列表并等待 - if event_time > current_time: - context.data.event_list.insert(0, event) # 将事件放回列表 - time_to_wait = (event_time - current_time).total_seconds() - log(f"下次事件时间{event_time},将在{time_to_wait}秒后执行,正在sleep等待…") - time.sleep(time_to_wait) # 等待直到事件时间到达 + + while True: + # 获取当前日期 + now = datetime.now() + # 将日期格式化为"yyyymmdd" + today = now.strftime("%Y-%m-%d") + if today not in calendar: + # 计算到第二天0点的秒数 + midnight = datetime.combine(now + timedelta(days=1), datetime.min.time()) + seconds_until_midnight = (midnight - now).total_seconds() + # 暂停程序直到第二天0点 + log(f"不在交易日历,sleep{seconds_until_midnight}秒") + time.sleep(seconds_until_midnight) else: - # 如果 event_time 在当前时间的10秒钟以内 - if 0 <= (current_time - event_time).total_seconds() < 10: - log(f"执行{event['event_name']}") - - if event['event_type']=="market_event": - event_func = getattr(Event, event['event_name']) - elif event['event_type']=="user_event": - event_func = getattr(strategy, event['event_name']) + event_list=Event.load_daily_event(context,today) + while event_list: + event = event_list.pop(0) + event_time = datetime.strptime(event['event_time'], '%Y-%m-%d %H:%M:%S') + current_time = datetime.now() # 去除毫秒部分 + context.current_dt=current_time + + # 如果 event_time 比当前时间晚,则将事件放回列表并等待 + if event_time > current_time: + event_list.insert(0, event) # 将事件放回列表 + time_to_wait = (event_time - current_time).total_seconds() + log(f"下次事件时间{event_time},将在{time_to_wait}秒后执行,正在sleep等待…") + time.sleep(time_to_wait) # 等待直到事件时间到达 else: - log(f"未知时间{event['event_name']}") - event_func(context) - else: - continue # 如果时间早于当前时间超过10秒,则跳过此事件 - - # 更新context的日期信息 - if context.previous_date is None or context.current_dt is None: - pass - elif context.current_dt.date() != event_time.date(): - context.previous_date = context.current_dt.date() - #context.current_dt = event_time - self.save_context(context) + # 如果 event_time 在当前时间的10秒钟以内 + if 0 <= (current_time - event_time).total_seconds() < 10: + log(f"执行{event['event_name']}") + + if event['event_type']=="market_event": + event_func = getattr(Event, event['event_name'],None) + elif event['event_type']=="user_event": + event_func = getattr(strategy, event['event_name'],None) + else: + log(f"未知时间{event['event_name']}") + if event_func==None: + time.sleep(1) + else: + event_func(context) + else: + continue # 如果时间早于当前时间超过10秒,则跳过此事件 + + # 更新context的日期信息 + if context.previous_date is None or context.current_dt is None: + pass + elif context.current_dt.date() != event_time.date(): + context.previous_date = context.current_dt.date() + #context.current_dt = event_time + self.save_context(context) + + + log("全部事件执行完毕") \ No newline at end of file diff --git a/examples/demo-project/trader/qmt/rules.py b/examples/demo-project/trader/qmt/rules.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/rqalpha/append_code.py b/examples/demo-project/trader/rqalpha/append_code.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/rqalpha/rqalpha_trader.py b/examples/demo-project/trader/rqalpha/rqalpha_trader.py old mode 100644 new mode 100755 index 57c9428..c6bc1e3 --- a/examples/demo-project/trader/rqalpha/rqalpha_trader.py +++ b/examples/demo-project/trader/rqalpha/rqalpha_trader.py @@ -40,6 +40,14 @@ def insert_import(self,code): return code def replace_init(self,code): + # replace_func_list=[ + # { + # "pattren":"", + # "func":replace_daily, + # } + # + # ] + replace_list={ "initialize(context):":"initialize(context):\n params="+str(self.myargs['params'].to_json())+"\n", 'inout_cash':'#inout_cash', @@ -58,16 +66,20 @@ def replace_init(self,code): "context.context":"context", "context.current_dt":"context.now", 'cost_basis':"avg_price" + } for k,v in replace_list.items(): code=code.replace(k,v) + + + return code - def replace_run_daily_and_collect_names(self,code_str): + def replace_run_daily_and_collect_names(self, code_str): # 编译一个正则表达式模式,用于匹配 run_daily 函数调用 - pattern = re.compile(r'run_daily\((.*?), time="(\d{2}):(\d{2})"\)') + pattern = re.compile(r'run_daily\((.*?), time="(\d{2}):(\d{2})(?::(\d{2}))?"\)') function_names = [] # 用于收集函数名 # 定义一个替换函数 @@ -85,6 +97,7 @@ def replacer(match): + def replace_order_functions(self,code_str): # 编译一个正则表达式模式,用于匹配 order_* 函数调用 diff --git a/examples/demo-project/trader/sim/__init__.py b/examples/demo-project/trader/sim/__init__.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/calendar.py b/examples/demo-project/trader/sim/calendar.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/context.py b/examples/demo-project/trader/sim/context.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/data.py b/examples/demo-project/trader/sim/data.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/dictobj.py b/examples/demo-project/trader/sim/dictobj.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/event.py b/examples/demo-project/trader/sim/event.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/function.py b/examples/demo-project/trader/sim/function.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/object.py b/examples/demo-project/trader/sim/object.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/qmtClient.py b/examples/demo-project/trader/sim/qmtClient.py old mode 100644 new mode 100755 diff --git a/examples/demo-project/trader/sim/rules.py b/examples/demo-project/trader/sim/rules.py old mode 100644 new mode 100755 diff --git a/finhack/__init__.py b/finhack/__init__.py old mode 100644 new mode 100755 index 909f874..d326f7e --- a/finhack/__init__.py +++ b/finhack/__init__.py @@ -1 +1 @@ -__version__ = '0.0.3.dev1' +__version__ = '0.0.3.dev2' diff --git a/finhack/collector/__init__.py b/finhack/collector/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/collector/baseCollector.py b/finhack/collector/baseCollector.py old mode 100644 new mode 100755 diff --git a/finhack/collector/binance/__init__.py b/finhack/collector/binance/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/collector/tushare/__init__.py b/finhack/collector/tushare/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/collector/tushare/tushare_collector.py b/finhack/collector/tushare/tushare_collector.py index 080f912..1fd0093 100755 --- a/finhack/collector/tushare/tushare_collector.py +++ b/finhack/collector/tushare/tushare_collector.py @@ -153,7 +153,7 @@ def getAStockIndex(self): def getAStockOther(self): self.mTread(tsAStockOther,'report_rc') self.mTread(tsAStockOther,'cyq_perf') - self.mTread(tsAStockOther,'cyq_chips') + #self.mTread(tsAStockOther,'cyq_chips') #broker_recommend def getFund(self): diff --git a/finhack/core/__init__.py b/finhack/core/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/core/classes/__init__.py b/finhack/core/classes/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/core/classes/dictobj.py b/finhack/core/classes/dictobj.py old mode 100644 new mode 100755 diff --git a/finhack/core/command/__init__.py b/finhack/core/command/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/core/core.py b/finhack/core/core.py old mode 100644 new mode 100755 diff --git a/finhack/core/data/__init__.py b/finhack/core/data/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/core/data/logs/__init__.py b/finhack/core/data/logs/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/core/loader/__init__.py b/finhack/core/loader/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/core/loader/base_loader.py b/finhack/core/loader/base_loader.py old mode 100644 new mode 100755 diff --git a/finhack/core/loader/collector_loader.py b/finhack/core/loader/collector_loader.py old mode 100644 new mode 100755 diff --git a/finhack/core/loader/factor_loader.py b/finhack/core/loader/factor_loader.py old mode 100644 new mode 100755 diff --git a/finhack/core/loader/helper_loader.py b/finhack/core/loader/helper_loader.py old mode 100644 new mode 100755 diff --git a/finhack/core/loader/trader_loader.py b/finhack/core/loader/trader_loader.py old mode 100644 new mode 100755 diff --git a/finhack/core/notify.py b/finhack/core/notify.py old mode 100644 new mode 100755 diff --git a/finhack/core/version.py b/finhack/core/version.py old mode 100644 new mode 100755 diff --git a/finhack/factor/__init__.py b/finhack/factor/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/factor/default/default_factor.py b/finhack/factor/default/default_factor.py old mode 100644 new mode 100755 diff --git a/finhack/factor/default/factorRepair.py b/finhack/factor/default/factorRepair.py old mode 100644 new mode 100755 diff --git a/finhack/helper/__init__.py b/finhack/helper/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/helper/struct/__init__.py b/finhack/helper/struct/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/helper/struct/struct_helper.py b/finhack/helper/struct/struct_helper.py old mode 100644 new mode 100755 diff --git a/finhack/library/__init__.py b/finhack/library/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/library/ai.py b/finhack/library/ai.py old mode 100644 new mode 100755 diff --git a/finhack/library/class_loader.py b/finhack/library/class_loader.py old mode 100644 new mode 100755 diff --git a/finhack/library/config.py b/finhack/library/config.py old mode 100644 new mode 100755 diff --git a/finhack/library/log.py b/finhack/library/log.py old mode 100644 new mode 100755 diff --git a/finhack/library/mycache.py b/finhack/library/mycache.py old mode 100644 new mode 100755 diff --git a/finhack/library/utils.py b/finhack/library/utils.py old mode 100644 new mode 100755 diff --git a/finhack/market/__init__.py b/finhack/market/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/market/astock/__init__.py b/finhack/market/astock/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/market/astock/tushare/__init__.py b/finhack/market/astock/tushare/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/market/astock/tushare/indexHelper.py b/finhack/market/astock/tushare/indexHelper.py old mode 100644 new mode 100755 diff --git a/finhack/plugin/__init__.py b/finhack/plugin/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/plugin/default/__init__.py b/finhack/plugin/default/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/plugin/default/default_plugin.py b/finhack/plugin/default/default_plugin.py old mode 100644 new mode 100755 diff --git a/finhack/requirements.txt b/finhack/requirements.txt old mode 100644 new mode 100755 index 134c8a8..6a87928 --- a/finhack/requirements.txt +++ b/finhack/requirements.txt @@ -26,4 +26,7 @@ lightgbm==4.2.0 cryptography==39.0.1 alphalens-reloaded==0.4.3 openai==1.12.0 -flask==3.0.2 \ No newline at end of file +flask==3.0.2 +grpcio==1.62.2 +cloudpickle==3.0.0 +dask==2024.4.2 \ No newline at end of file diff --git a/finhack/server/__init__.py b/finhack/server/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/server/default/__init__.py b/finhack/server/default/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/server/default/default_server.py b/finhack/server/default/default_server.py old mode 100644 new mode 100755 index d7b4fed..f79f575 --- a/finhack/server/default/default_server.py +++ b/finhack/server/default/default_server.py @@ -98,12 +98,22 @@ def redirect_to_index(): # else: # bt_list=mydb.selectToList(f"SELECT id, instance_id, features_list, train, model, strategy, start_date, end_date, init_cash, params, total_value, alpha, beta, annual_return, cagr, annual_volatility, info_ratio, downside_risk, R2, sharpe, sortino, calmar, omega, max_down, SQN, created_at, filter, win, server, trade_num, runtime, starttime, endtime, roto, simulate, benchmark, strategy_code FROM `finhack`.`backtest` {where} order by sharpe desc LIMIT 100",'finhack') - sql="""SELECT + + sql="" + path=f"{BASE_DIR}/data/config/sqllist/server/bt_list.sql" + if os.path.exists(path): + with open(path, 'r', encoding='utf-8') as file: + sql= file.read() + else: + sql="""SELECT id, a.instance_id, features_list, train, model, strategy, a.start_date, a.end_date, init_cash, params, a.total_value, a.alpha, a.beta, annual_return, cagr, annual_volatility, info_ratio, a.downside_risk, R2, a.sharpe,b.sharpe as sharpe2, a.sortino, calmar, omega, max_down, SQN, created_at, filter, win, server, trade_num, runtime, starttime, endtime, roto, simulate, a.benchmark, strategy_code FROM `finhack`.`backtest` a RIGHT JOIN rqalpha b on a.instance_id =b.instance_id ORDER BY b.sharpe desc limit 100""" + + bt_list=mydb.selectToList(sql,'finhack') + return render_template('index.html', data=bt_list) # 不再需要检查 __name__ == '__main__',因为这个方法将被直接调用 diff --git a/finhack/trader/__init__.py b/finhack/trader/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/__init__.py b/finhack/trader/default/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/calendar.py b/finhack/trader/default/calendar.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/context.py b/finhack/trader/default/context.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/data.py b/finhack/trader/default/data.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/default_trader.py b/finhack/trader/default/default_trader.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/event.py b/finhack/trader/default/event.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/function.py b/finhack/trader/default/function.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/object.py b/finhack/trader/default/object.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/performance.py b/finhack/trader/default/performance.py old mode 100644 new mode 100755 diff --git a/finhack/trader/default/rules.py b/finhack/trader/default/rules.py old mode 100644 new mode 100755 diff --git a/finhack/trainer/__init__.py b/finhack/trainer/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/trainer/auto/__init__.py b/finhack/trainer/auto/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/trainer/auto/auto_trainer.py b/finhack/trainer/auto/auto_trainer.py old mode 100644 new mode 100755 diff --git a/finhack/trainer/lightgbm/__init__.py b/finhack/trainer/lightgbm/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/trainer/lightgbm/lightgbm_trainer.py b/finhack/trainer/lightgbm/lightgbm_trainer.py old mode 100644 new mode 100755 diff --git a/finhack/trainer/trainer.py b/finhack/trainer/trainer.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/__init__.py b/finhack/widgets/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/__init__.py b/finhack/widgets/templates/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/.proj b/finhack/widgets/templates/empty_project/.proj old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/__init__.py b/finhack/widgets/templates/empty_project/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/auto/__init__.py b/finhack/widgets/templates/empty_project/auto/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/auto/default/__init__.py b/finhack/widgets/templates/empty_project/auto/default/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/backtest/__init__.py b/finhack/widgets/templates/empty_project/backtest/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/backtest/default/__init__.py b/finhack/widgets/templates/empty_project/backtest/default/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/backtest/default/default_backtest.py b/finhack/widgets/templates/empty_project/backtest/default/default_backtest.py old mode 100644 new mode 100755 index 0701bdd..5d31c8a --- a/finhack/widgets/templates/empty_project/backtest/default/default_backtest.py +++ b/finhack/widgets/templates/empty_project/backtest/default/default_backtest.py @@ -72,8 +72,15 @@ def rqalpha(self): entry_file_path = os.path.realpath(sys.executable) else: entry_file_path = os.path.realpath(sys.argv[0]) - - bt_list=mydb.selectToList(f"SELECT id, instance_id, features_list, train, model, strategy, start_date, end_date, init_cash, params, total_value, alpha, beta, annual_return, cagr, annual_volatility, info_ratio, downside_risk, R2, sharpe, sortino, calmar, omega, max_down, SQN, created_at, filter, win, server, trade_num, runtime, starttime, endtime, roto, simulate, benchmark, strategy_code FROM `finhack`.`backtest` order by sharpe desc LIMIT 1000",'finhack') + + sql="" + path=f"{BASE_DIR}/data/config/sqllist/backtest/bt_list.sql" + if os.path.exists(path): + with open(path, 'r', encoding='utf-8') as file: + sql= file.read() + else: + sql="SELECT id, instance_id, features_list, train, model, strategy, start_date, end_date, init_cash, params, total_value, alpha, beta, annual_return, cagr, annual_volatility, info_ratio, downside_risk, R2, sharpe, sortino, calmar, omega, max_down, SQN, created_at, filter, win, server, trade_num, runtime, starttime, endtime, roto, simulate, benchmark, strategy_code FROM `finhack`.`backtest` order by sharpe desc LIMIT 1000" + bt_list=mydb.selectToList(sql,'finhack') def to_json(s): dict_str = re.sub(r"DictObj\((.*?)\)", r"{\1}", s) @@ -99,7 +106,7 @@ def run(self): Data.init_data(cache=True) cash_list = self.args.cash.split(',') strategy_list = self.args.strategy.split(',') - model_list = mydb.selectToDf('select * from auto_train order by rand()', 'finhack') + model_list = mydb.selectToDf('select * from auto_train where id > 14226 order by rand()', 'finhack') semaphore = multiprocessing.Semaphore(int(self.args.process)) # 创建一个信号量,最大允许process个进程同时运行 # print(model_list) diff --git a/finhack/widgets/templates/empty_project/data/__init__.py b/finhack/widgets/templates/empty_project/data/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/__init__.py b/finhack/widgets/templates/empty_project/data/cache/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/choice/__init__.py b/finhack/widgets/templates/empty_project/data/cache/choice/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/factors/__init__.py b/finhack/widgets/templates/empty_project/data/cache/factors/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/index/__init__.py b/finhack/widgets/templates/empty_project/data/cache/index/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/kv/__init__.py b/finhack/widgets/templates/empty_project/data/cache/kv/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/market/__init__.py b/finhack/widgets/templates/empty_project/data/cache/market/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/notice/__init__.py b/finhack/widgets/templates/empty_project/data/cache/notice/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/price/__init__.py b/finhack/widgets/templates/empty_project/data/cache/price/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/runtime.py b/finhack/widgets/templates/empty_project/data/cache/runtime.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/runtime/__init__.py b/finhack/widgets/templates/empty_project/data/cache/runtime/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/runtime/constant.py b/finhack/widgets/templates/empty_project/data/cache/runtime/constant.py old mode 100644 new mode 100755 index e318f89..e2d33d1 --- a/finhack/widgets/templates/empty_project/data/cache/runtime/constant.py +++ b/finhack/widgets/templates/empty_project/data/cache/runtime/constant.py @@ -1,5 +1,5 @@ FRAMEWORK_DIR="/root/anaconda3/envs/finhack/lib/python3.9/site-packages/finhack" -BASE_DIR="/data/code/demo_project/" +BASE_DIR="/data/code/demo_project" DATA_DIR=BASE_DIR+"/data/" CACHE_DIR=DATA_DIR+"cache/" REPORTS_DIR=DATA_DIR+"reports/" diff --git a/finhack/widgets/templates/empty_project/data/cache/runtime/global_var.py b/finhack/widgets/templates/empty_project/data/cache/runtime/global_var.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/single_factors_tmp1/__init__.py b/finhack/widgets/templates/empty_project/data/cache/single_factors_tmp1/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/cache/single_factors_tmp2/__init__.py b/finhack/widgets/templates/empty_project/data/cache/single_factors_tmp2/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/__init__.py b/finhack/widgets/templates/empty_project/data/config/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/ai.conf b/finhack/widgets/templates/empty_project/data/config/ai.conf old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/args.conf b/finhack/widgets/templates/empty_project/data/config/args.conf old mode 100644 new mode 100755 index 9aeedec..9d43640 --- a/finhack/widgets/templates/empty_project/data/config/args.conf +++ b/finhack/widgets/templates/empty_project/data/config/args.conf @@ -25,27 +25,27 @@ task_list=woldy,alpha999 [trainer] -start_date=20100101 -valid_date=20180101 -end_date=20200101 +start_date=20160101 +valid_date=20220101 +end_date=20230101 features= label=abs -shift=10 +shift=5 param= -loss=ds +loss=mse device=gpu filter_name= replace=False min_f=16 -max_f=64 +max_f=128 process=1 [backtest] strategy=testStrategy -cash=20000 -process=28 +cash=1000000 +process=8 [trader] diff --git a/finhack/widgets/templates/empty_project/data/config/backtest.conf b/finhack/widgets/templates/empty_project/data/config/backtest.conf old mode 100644 new mode 100755 index 443facb..a8e82c1 --- a/finhack/widgets/templates/empty_project/data/config/backtest.conf +++ b/finhack/widgets/templates/empty_project/data/config/backtest.conf @@ -12,8 +12,8 @@ change_threshold=0.1 #top=600,800,900 [testStrategy] -stocknum=3,5 -refresh_rate=1,3,5 +stocknum=30,50 +refresh_rate=3,5,7 stop_loss_threshold=0.95,0.9 stop_gain_threshold=1.2,1.25,1.3 preds_cache=True \ No newline at end of file diff --git a/finhack/widgets/templates/empty_project/data/config/constant.conf b/finhack/widgets/templates/empty_project/data/config/constant.conf old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/core.conf b/finhack/widgets/templates/empty_project/data/config/core.conf old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/factorlist/__init__.py b/finhack/widgets/templates/empty_project/data/config/factorlist/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/factorlist/alphalist/__init__.py b/finhack/widgets/templates/empty_project/data/config/factorlist/alphalist/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/factorlist/indicatorlist/__init__.py b/finhack/widgets/templates/empty_project/data/config/factorlist/indicatorlist/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/factorlist/indicatorlist/woldy b/finhack/widgets/templates/empty_project/data/config/factorlist/indicatorlist/woldy old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/factorlist/trainlist/__init__.py b/finhack/widgets/templates/empty_project/data/config/factorlist/trainlist/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/factorlist/trainlist/autotrain b/finhack/widgets/templates/empty_project/data/config/factorlist/trainlist/autotrain old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/global_var.conf b/finhack/widgets/templates/empty_project/data/config/global_var.conf old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/sqllist/__init__.py b/finhack/widgets/templates/empty_project/data/config/sqllist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/config/sqllist/backtest/__init__.py b/finhack/widgets/templates/empty_project/data/config/sqllist/backtest/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/config/sqllist/server/__init__.py b/finhack/widgets/templates/empty_project/data/config/sqllist/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/config/trader.conf b/finhack/widgets/templates/empty_project/data/config/trader.conf old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/config/train.conf b/finhack/widgets/templates/empty_project/data/config/train.conf old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/__init__.py b/finhack/widgets/templates/empty_project/data/factors/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/code_factors/__init__.py b/finhack/widgets/templates/empty_project/data/factors/code_factors/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors_parquet/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors_parquet/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors_parquet/all_factors.parquet/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors_parquet/all_factors.parquet/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl/_tmp/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl/_tmp/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl_tmp/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl_tmp/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl_tmp/_tmp/__init__.py b/finhack/widgets/templates/empty_project/data/factors/single_factors_pkl_tmp/_tmp/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/logs/__init__.py b/finhack/widgets/templates/empty_project/data/logs/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/logs/trader/__init__.py b/finhack/widgets/templates/empty_project/data/logs/trader/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/models/__init__.py b/finhack/widgets/templates/empty_project/data/models/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/preds/__init__.py b/finhack/widgets/templates/empty_project/data/preds/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/quote/__init__.py b/finhack/widgets/templates/empty_project/data/quote/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/crytpo/__init__.py b/finhack/widgets/templates/empty_project/data/quote/crytpo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/forex/__init__.py b/finhack/widgets/templates/empty_project/data/quote/forex/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/future/__init__.py b/finhack/widgets/templates/empty_project/data/quote/future/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/option/__init__.py b/finhack/widgets/templates/empty_project/data/quote/option/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/SH/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/SH/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/daily/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/daily/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/minutely/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/minutely/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/tick/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/SZ/000001.SZ/tick/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/SZ/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/SZ/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/quote/stock/__init__.py b/finhack/widgets/templates/empty_project/data/quote/stock/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/finhack/widgets/templates/empty_project/data/reports/__init__.py b/finhack/widgets/templates/empty_project/data/reports/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/index.html b/finhack/widgets/templates/empty_project/data/reports/index.html old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/static/__init__.py b/finhack/widgets/templates/empty_project/data/reports/static/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/static/css/__init__.py b/finhack/widgets/templates/empty_project/data/reports/static/css/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/static/images/__init__.py b/finhack/widgets/templates/empty_project/data/reports/static/images/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/static/js/__init__.py b/finhack/widgets/templates/empty_project/data/reports/static/js/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/static/rqalpha/__init__.py b/finhack/widgets/templates/empty_project/data/reports/static/rqalpha/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/reports/static/trader/__init__.py b/finhack/widgets/templates/empty_project/data/reports/static/trader/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/running/__init__.py b/finhack/widgets/templates/empty_project/data/running/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/data/running/x.py b/finhack/widgets/templates/empty_project/data/running/x.py new file mode 100755 index 0000000..16b05d4 --- /dev/null +++ b/finhack/widgets/templates/empty_project/data/running/x.py @@ -0,0 +1,9 @@ +import pickle + +# 以二进制读模式打开文件 +with open('test.pkl', 'rb') as f: + data = pickle.load(f) + +# 打印读取的数据 +print(data) + diff --git a/finhack/widgets/templates/empty_project/indicators/QIML365.py b/finhack/widgets/templates/empty_project/indicators/QIML365.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/indicators/member.py b/finhack/widgets/templates/empty_project/indicators/member.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/loader/1testmodule_loader.py b/finhack/widgets/templates/empty_project/loader/1testmodule_loader.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/loader/__init__.py b/finhack/widgets/templates/empty_project/loader/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/loader/testmodule_loader.py b/finhack/widgets/templates/empty_project/loader/testmodule_loader.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/prompt/__init__.py b/finhack/widgets/templates/empty_project/prompt/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/prompts/__init__.py b/finhack/widgets/templates/empty_project/prompts/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/script/__init__.py b/finhack/widgets/templates/empty_project/script/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/strategy/AITopNStrategy.py b/finhack/widgets/templates/empty_project/strategy/AITopNStrategy.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/strategy/ChatGPTStrategy.py b/finhack/widgets/templates/empty_project/strategy/ChatGPTStrategy.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/strategy/DemoStrategy.py b/finhack/widgets/templates/empty_project/strategy/DemoStrategy.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/strategy/__init__.py b/finhack/widgets/templates/empty_project/strategy/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/testmodule/__init__.py b/finhack/widgets/templates/empty_project/testmodule/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/testmodule/default/__init__.py b/finhack/widgets/templates/empty_project/testmodule/default/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/testmodule/default/default_testmodule.py b/finhack/widgets/templates/empty_project/testmodule/default/default_testmodule.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/testmodule/default/testmodule.py b/finhack/widgets/templates/empty_project/testmodule/default/testmodule.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/__init__.py b/finhack/widgets/templates/empty_project/trader/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/__init__.py b/finhack/widgets/templates/empty_project/trader/qmt/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/calendar.py b/finhack/widgets/templates/empty_project/trader/qmt/calendar.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/client.py b/finhack/widgets/templates/empty_project/trader/qmt/client.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/context.py b/finhack/widgets/templates/empty_project/trader/qmt/context.py old mode 100644 new mode 100755 index 651f6d9..3b91360 --- a/finhack/widgets/templates/empty_project/trader/qmt/context.py +++ b/finhack/widgets/templates/empty_project/trader/qmt/context.py @@ -62,6 +62,7 @@ 'data':DictObj({ 'calendar':[], + 'event_interval_list':[], 'event_list':[], 'data_source':'file', 'daily_info':None, diff --git a/finhack/widgets/templates/empty_project/trader/qmt/data.py b/finhack/widgets/templates/empty_project/trader/qmt/data.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/dictobj.py b/finhack/widgets/templates/empty_project/trader/qmt/dictobj.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/event.py b/finhack/widgets/templates/empty_project/trader/qmt/event.py old mode 100644 new mode 100755 index 8594344..f17f9a6 --- a/finhack/widgets/templates/empty_project/trader/qmt/event.py +++ b/finhack/widgets/templates/empty_project/trader/qmt/event.py @@ -38,6 +38,28 @@ def get_event(): event['astock'] = {**event['default'], **event['astock']} event['astock'] = sorted(event['astock'].items(), key=lambda x: x[1]) return event + + + def load_daily_event(context,date): + event_list=[] + daily_event_list=Event.get_event() + for event_interval in context['data']['event_interval_list']: + if event_interval['event_interval']=='daily': + event_interval['event_time']=date+" "+event_interval['time'] + event_list.append(event_interval) + + for event_name,event_time in daily_event_list['astock']: + if hasattr(Event, event_name): + func = getattr(Event, event_name) + new_event={ + 'event_name':event_name, + #'event_func':func, + 'event_time':date+' '+event_time, + 'event_type':'market_event' + } + event_list.append(new_event) + event_list.sort(key=lambda x: x['event_time']) + return event_list def load_event(context,start_time,end_time): event_list=[] @@ -49,12 +71,12 @@ def load_event(context,start_time,end_time): func = getattr(Event, event_name) new_event={ 'event_name':event_name, - 'event_func':func, + #'event_func':func, 'event_time':date+' '+event_time, 'event_type':'market_event' } context['data']['event_list'].append(new_event) - context['data']['event_list'].sort(key=lambda x: x['event_time']) + context['data']['event_list'].sort(key=lambda x: x['event_time']) return True diff --git a/finhack/widgets/templates/empty_project/trader/qmt/function.py b/finhack/widgets/templates/empty_project/trader/qmt/function.py old mode 100644 new mode 100755 index df13b7e..c8a54e9 --- a/finhack/widgets/templates/empty_project/trader/qmt/function.py +++ b/finhack/widgets/templates/empty_project/trader/qmt/function.py @@ -81,6 +81,7 @@ def init_context(args): + def set_benchmark(code): context['trade']['benchmark']=code @@ -111,15 +112,25 @@ def run_interval(func,time,interval='daily',date_list=[]): hours, minutes = time.split(":") time = f"{hours.zfill(2)}:{minutes.zfill(2)}:00" - for date in date_list: - new_event={ - 'event_name':func.__name__, - 'event_func':func, - 'event_time':date+' '+time, - 'event_type':'user_event' - } - context['data']['event_list'].append(new_event) - context['data']['event_list'].sort(key=lambda x: x['event_time']) + + event_interval={ + 'event_name':func.__name__, + 'event_interval':interval, + 'time':time, + 'event_type':'user_event' + } + context['data']['event_interval_list'].append(event_interval) + + # for date in date_list: + # new_event={ + # 'event_name':func.__name__, + # #'event_func':func, + # 'event_time':date+' '+time, + # 'event_type':'user_event' + # } + # context['data']['event_list'].append(new_event) + # context['data']['event_list'].sort(key=lambda x: x['event_time']) + def run_daily(func,time,reference_security=None): return run_interval(func,time,'daily',date_list=context['data']['calendar']) @@ -250,6 +261,7 @@ def get_trades(): # self.total_value=amount*last_sale_price def order_buy(security,amount,price=None): + log(f"调用order_buy买入{security}共{amount}股,价格为{str(None)}") o=Order(code=security,amount=amount,is_buy=True,context=context) rules=Rules(order=o,context=context,log=log) o=rules.apply() @@ -267,6 +279,7 @@ def order_buy(security,amount,price=None): def order_sell(security,amount,price=None): + log(f"调用order_sell卖出{security}共{amount}股,价格为{str(None)}") o=Order(code=security,amount=amount,is_buy=False,context=context) rules=Rules(order=o,context=context,log=log) o=rules.apply() diff --git a/finhack/widgets/templates/empty_project/trader/qmt/object.py b/finhack/widgets/templates/empty_project/trader/qmt/object.py old mode 100644 new mode 100755 index 5cf576b..80a9663 --- a/finhack/widgets/templates/empty_project/trader/qmt/object.py +++ b/finhack/widgets/templates/empty_project/trader/qmt/object.py @@ -21,6 +21,7 @@ def __init__(self,code='',amount='',is_buy=True,side='long',action='',context=No self.enable_amount=amount self.filled=0 self.info=Data.get_daily_info(code=code,context=context) + print(self.info) self.price=Data.get_price(code=code,context=context) self.order_id = self.generate_order_id() self.is_buy=is_buy diff --git a/finhack/widgets/templates/empty_project/trader/qmt/qmtClient.py b/finhack/widgets/templates/empty_project/trader/qmt/qmtClient.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/qmt/qmt_trader.py b/finhack/widgets/templates/empty_project/trader/qmt/qmt_trader.py index 0b640aa..7687511 100755 --- a/finhack/widgets/templates/empty_project/trader/qmt/qmt_trader.py +++ b/finhack/widgets/templates/empty_project/trader/qmt/qmt_trader.py @@ -12,7 +12,7 @@ from trader.qmt.function import * from trader.qmt.object import * from trader.qmt.context import context -from datetime import datetime +from datetime import datetime, timedelta import time from functools import partial @@ -29,6 +29,16 @@ def load_strategy(self,strategy_name): Log.logger.error(f"{BASE_DIR}strategy/{strategy_name}.py NotFound") pass + + def status(self): + # 查询状态 + context.id=self.args.id + loaded_context = self.load_context(context) + print(loaded_context.g) + + + + def save_context(self,context): context_id=context.id running_dir = RUNNING_DIR @@ -64,6 +74,7 @@ def run(self,args=None): context = loaded_context else: pass + start_time=context['trade']['start_time'] end_time=context['trade']['end_time'] @@ -87,7 +98,6 @@ def run(self,args=None): strategy.log=Log.logger strategy.g=context.g - if loaded_context is not None: pass else: @@ -97,30 +107,59 @@ def run(self,args=None): strategy.initialize(context) self.save_context(context) - while context.data.event_list: - event = context.data.event_list.pop(0) - event_time = datetime.strptime(event['event_time'], '%Y-%m-%d %H:%M:%S') - current_time = datetime.now() # 去除毫秒部分 - context.current_dt=current_time - - # 如果 event_time 比当前时间晚,则将事件放回列表并等待 - if event_time > current_time: - context.data.event_list.insert(0, event) # 将事件放回列表 - time_to_wait = (event_time - current_time).total_seconds() - log(f"下次事件时间{event_time},将在{time_to_wait}秒后执行,正在sleep等待…") - time.sleep(time_to_wait) # 等待直到事件时间到达 + + while True: + # 获取当前日期 + now = datetime.now() + # 将日期格式化为"yyyymmdd" + today = now.strftime("%Y-%m-%d") + if today not in calendar: + # 计算到第二天0点的秒数 + midnight = datetime.combine(now + timedelta(days=1), datetime.min.time()) + seconds_until_midnight = (midnight - now).total_seconds() + # 暂停程序直到第二天0点 + log(f"不在交易日历,sleep{seconds_until_midnight}秒") + time.sleep(seconds_until_midnight) else: - # 如果 event_time 在当前时间的10秒钟以内 - if 0 <= (current_time - event_time).total_seconds() < 10: - log(f"执行{event['event_name']}") - event['event_func'](context) - else: - continue # 如果时间早于当前时间超过10秒,则跳过此事件 - - # 更新context的日期信息 - if context.previous_date is None or context.current_dt is None: - pass - elif context.current_dt.date() != event_time.date(): - context.previous_date = context.current_dt.date() - context.current_dt = event_time - self.save_context(context) \ No newline at end of file + event_list=Event.load_daily_event(context,today) + while event_list: + event = event_list.pop(0) + event_time = datetime.strptime(event['event_time'], '%Y-%m-%d %H:%M:%S') + current_time = datetime.now() # 去除毫秒部分 + context.current_dt=current_time + + # 如果 event_time 比当前时间晚,则将事件放回列表并等待 + if event_time > current_time: + event_list.insert(0, event) # 将事件放回列表 + time_to_wait = (event_time - current_time).total_seconds() + log(f"下次事件时间{event_time},将在{time_to_wait}秒后执行,正在sleep等待…") + time.sleep(time_to_wait) # 等待直到事件时间到达 + else: + # 如果 event_time 在当前时间的10秒钟以内 + if 0 <= (current_time - event_time).total_seconds() < 10: + log(f"执行{event['event_name']}") + + if event['event_type']=="market_event": + event_func = getattr(Event, event['event_name'],None) + elif event['event_type']=="user_event": + event_func = getattr(strategy, event['event_name'],None) + else: + log(f"未知时间{event['event_name']}") + if event_func==None: + time.sleep(1) + else: + event_func(context) + else: + continue # 如果时间早于当前时间超过10秒,则跳过此事件 + + # 更新context的日期信息 + if context.previous_date is None or context.current_dt is None: + pass + elif context.current_dt.date() != event_time.date(): + context.previous_date = context.current_dt.date() + #context.current_dt = event_time + self.save_context(context) + + + + log("全部事件执行完毕") \ No newline at end of file diff --git a/finhack/widgets/templates/empty_project/trader/qmt/rules.py b/finhack/widgets/templates/empty_project/trader/qmt/rules.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/rqalpha/__init__.py b/finhack/widgets/templates/empty_project/trader/rqalpha/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/rqalpha/append_code.py b/finhack/widgets/templates/empty_project/trader/rqalpha/append_code.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/rqalpha/rqalpha_trader.py b/finhack/widgets/templates/empty_project/trader/rqalpha/rqalpha_trader.py old mode 100644 new mode 100755 index 57c9428..c6bc1e3 --- a/finhack/widgets/templates/empty_project/trader/rqalpha/rqalpha_trader.py +++ b/finhack/widgets/templates/empty_project/trader/rqalpha/rqalpha_trader.py @@ -40,6 +40,14 @@ def insert_import(self,code): return code def replace_init(self,code): + # replace_func_list=[ + # { + # "pattren":"", + # "func":replace_daily, + # } + # + # ] + replace_list={ "initialize(context):":"initialize(context):\n params="+str(self.myargs['params'].to_json())+"\n", 'inout_cash':'#inout_cash', @@ -58,16 +66,20 @@ def replace_init(self,code): "context.context":"context", "context.current_dt":"context.now", 'cost_basis':"avg_price" + } for k,v in replace_list.items(): code=code.replace(k,v) + + + return code - def replace_run_daily_and_collect_names(self,code_str): + def replace_run_daily_and_collect_names(self, code_str): # 编译一个正则表达式模式,用于匹配 run_daily 函数调用 - pattern = re.compile(r'run_daily\((.*?), time="(\d{2}):(\d{2})"\)') + pattern = re.compile(r'run_daily\((.*?), time="(\d{2}):(\d{2})(?::(\d{2}))?"\)') function_names = [] # 用于收集函数名 # 定义一个替换函数 @@ -85,6 +97,7 @@ def replacer(match): + def replace_order_functions(self,code_str): # 编译一个正则表达式模式,用于匹配 order_* 函数调用 diff --git a/finhack/widgets/templates/empty_project/trader/sim/__init__.py b/finhack/widgets/templates/empty_project/trader/sim/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/calendar.py b/finhack/widgets/templates/empty_project/trader/sim/calendar.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/context.py b/finhack/widgets/templates/empty_project/trader/sim/context.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/data.py b/finhack/widgets/templates/empty_project/trader/sim/data.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/dictobj.py b/finhack/widgets/templates/empty_project/trader/sim/dictobj.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/event.py b/finhack/widgets/templates/empty_project/trader/sim/event.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/function.py b/finhack/widgets/templates/empty_project/trader/sim/function.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/object.py b/finhack/widgets/templates/empty_project/trader/sim/object.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/qmtClient.py b/finhack/widgets/templates/empty_project/trader/sim/qmtClient.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/empty_project/trader/sim/rules.py b/finhack/widgets/templates/empty_project/trader/sim/rules.py old mode 100644 new mode 100755 index 8118d26..0f93849 --- a/finhack/widgets/templates/empty_project/trader/sim/rules.py +++ b/finhack/widgets/templates/empty_project/trader/sim/rules.py @@ -106,10 +106,6 @@ def rule_limit(self): return True def rule_100(self): - print('---') - print(self.order.amount) - print(int(self.order.amount/100)*100) - print('---') if self.order.amount!=int(self.order.amount/100)*100: self.order.amount=int(self.order.amount/100)*100 self.log(f"{self.order.code}自动调整交易数量为{self.order.amount}!",'warning') diff --git a/finhack/widgets/templates/runtime/__init__.py b/finhack/widgets/templates/runtime/__init__.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/runtime/constant.py b/finhack/widgets/templates/runtime/constant.py old mode 100644 new mode 100755 diff --git a/finhack/widgets/templates/runtime/global_var.py b/finhack/widgets/templates/runtime/global_var.py old mode 100644 new mode 100755 diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 index 134c8a8..6a87928 --- a/requirements.txt +++ b/requirements.txt @@ -26,4 +26,7 @@ lightgbm==4.2.0 cryptography==39.0.1 alphalens-reloaded==0.4.3 openai==1.12.0 -flask==3.0.2 \ No newline at end of file +flask==3.0.2 +grpcio==1.62.2 +cloudpickle==3.0.0 +dask==2024.4.2 \ No newline at end of file diff --git a/setup.py b/setup.py old mode 100644 new mode 100755