rqalpha 5.3.7__tar.gz → 5.3.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rqalpha-5.3.7/rqalpha.egg-info → rqalpha-5.3.9}/PKG-INFO +1 -1
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/_version.py +3 -3
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/api_base.py +2 -5
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/data_source.py +6 -1
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/storages.py +1 -1
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/bundle.py +101 -2
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/data_proxy.py +5 -2
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/trading_dates_mixin.py +9 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/environment.py +34 -10
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/interface.py +26 -7
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/main.py +3 -2
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/api/api_future.py +13 -15
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/api/api_stock.py +20 -25
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/component_validator.py +9 -15
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/position_model.py +6 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/position_validator.py +13 -14
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/validator.py +7 -11
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/mod.py +53 -20
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/report/excel_template.py +5 -3
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/report/report.py +51 -8
- rqalpha-5.3.9/rqalpha/mod/rqalpha_mod_sys_analyser/report/templates/summary.xlsx +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/cash_validator.py +18 -19
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/is_trading_validator.py +15 -13
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/price_validator.py +12 -13
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/self_trade_validator.py +11 -12
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/matcher.py +1 -1
- rqalpha-5.3.9/rqalpha/mod/rqalpha_mod_sys_simulation/validator.py +20 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/portfolio/account.py +0 -1
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/testing/fixtures.py +1 -1
- rqalpha-5.3.9/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.mo +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.po +55 -53
- {rqalpha-5.3.7 → rqalpha-5.3.9/rqalpha.egg-info}/PKG-INFO +1 -1
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/SOURCES.txt +4 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/setup.cfg +1 -1
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_simulation_broker.py +3 -0
- rqalpha-5.3.9/tests/test_f_delivery.py +42 -0
- rqalpha-5.3.9/tests/test_f_tick_size.py +67 -0
- rqalpha-5.3.9/tests/unittest/test_data/test_auto_update_bundle/__init__.py +7 -0
- rqalpha-5.3.9/tests/unittest/test_data/test_auto_update_bundle/test_auto_update_bundle_mixin.py +75 -0
- rqalpha-5.3.7/rqalpha/mod/rqalpha_mod_sys_analyser/report/templates/summary.xlsx +0 -0
- rqalpha-5.3.7/rqalpha/mod/rqalpha_mod_sys_simulation/validator.py +0 -18
- rqalpha-5.3.7/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.mo +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/CHANGELOG.rst +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/LICENSE +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/MANIFEST.in +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/README.rst +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/__main__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/api.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/api_abstract.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/api_rqdatac.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/names.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/bundle.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/entry.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/misc.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/run.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/config.yml +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/const.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/events.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/execution_context.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/executor.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/global_var.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy_context.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy_loader.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy_universe.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/bar_dict_price_board.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/adjust.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/storage_interface.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/IF1706_20161108.csv +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/IF_macd.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/buy_and_hold.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/data_source/get_csv_module.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/data_source/import_get_csv_module.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/data_source/read_csv_as_df.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/extend_api/rqalpha_mod_extend_api_demo.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/extend_api/test_extend_api.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/golden_cross.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/macd.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/pair_trading.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/rsi.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/run_code_demo.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/run_file_demo.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/run_func_demo.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/subscribe_event.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/test_pt.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/turtle.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/api/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/consts.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/plot.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/utils.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot_store.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/report/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_progress/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_progress/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_scheduler/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_scheduler/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_scheduler/scheduler.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/signal_broker.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/simulation_broker.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/simulation_event_source.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/slippage.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/testing.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/deciders.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/mod.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/utils.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod_config.yml +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/bar.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/instrument.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/order.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/tick.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/trade.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/portfolio/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/portfolio/position.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/resource/ricequant-logo.png +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/user_module.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/arg_checker.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/class_helper.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/click_helper.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/concurrent.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/config.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/datetime_func.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/dict_func.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/exception.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/functools.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/i18n.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/log_capture.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/logger.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/package_helper.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/persisit_helper.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/repr.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/risk_free_helper.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/rq_json.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/strategy_loader_help.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/testing/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/testing/mocking.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/zh_Hans_CN/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/typing.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/dependency_links.txt +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/entry_points.txt +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/not-zip-safe +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/requires.txt +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/top_level.txt +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/setup.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_account_model.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_futures_settlement_price_type.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_margin_stocks.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_position_models.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_scheduler/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_scheduler/test_physical_time.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_scheduler/test_scheduler.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_management_fee.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_match.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_signal_broker.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_simulation_event_source.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_transaction_cost/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_transaction_cost/test_commission_multiplier.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_api_base.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_api_future.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_api_stock.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_config.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/utils.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_buy_and_hold.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_macd.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_macd_signal.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_mean_reverting.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_buy_and_hold.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_dual_thrust.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_pit_tax.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_scheduler.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_tick_size.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_turtle.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_turtle_signal.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_sf_buy_and_hold.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_data/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_data/test_instrument_mixin.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_data/test_trading_dates_mixin.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_mod/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_mod/test_sys_simulation/__init__.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_mod/test_sys_simulation/test_simulation_event_source.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/utils.py +0 -0
- {rqalpha-5.3.7 → rqalpha-5.3.9}/versioneer.py +0 -0
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-
|
|
11
|
+
"date": "2024-04-12T18:06:46+0800",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "5.3.
|
|
14
|
+
"full-revisionid": "9095b0aebd0ed705a38a669b85da16310a714468",
|
|
15
|
+
"version": "5.3.9"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -170,11 +170,8 @@ def submit_order(id_or_ins, amount, side, price=None, position_effect=None):
|
|
|
170
170
|
style = cal_style(price, None)
|
|
171
171
|
market_price = env.get_last_price(order_book_id)
|
|
172
172
|
if not is_valid_price(market_price):
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
order_book_id=order_book_id
|
|
176
|
-
)
|
|
177
|
-
)
|
|
173
|
+
reason = _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
|
|
174
|
+
env.order_creation_failed(order_book_id, reason)
|
|
178
175
|
return
|
|
179
176
|
|
|
180
177
|
amount = int(amount)
|
|
@@ -42,7 +42,7 @@ from rqalpha.data.base_data_source.storages import (DateSet, DayBarStore, Divide
|
|
|
42
42
|
ExchangeTradingCalendarStore, FutureDayBarStore,
|
|
43
43
|
FutureInfoStore, FuturesTradingParametersStore,InstrumentStore,
|
|
44
44
|
ShareTransformationStore, SimpleFactorStore,
|
|
45
|
-
YieldCurveStore)
|
|
45
|
+
YieldCurveStore, FuturesTradingParameters)
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
BAR_RESAMPLE_FIELD_METHODS = {
|
|
@@ -400,3 +400,8 @@ class BaseDataSource(AbstractDataSource):
|
|
|
400
400
|
|
|
401
401
|
def get_algo_bar(self, id_or_ins, start_min, end_min, dt):
|
|
402
402
|
raise NotImplementedError("open source rqalpha not support algo order")
|
|
403
|
+
|
|
404
|
+
def get_open_auction_volume(self, instrument, dt):
|
|
405
|
+
# type: (Instrument, datetime.datetime) -> float
|
|
406
|
+
volume = self.get_open_auction_bar(instrument, dt)['volume']
|
|
407
|
+
return volume
|
|
@@ -116,7 +116,7 @@ class FutureInfoStore(object):
|
|
|
116
116
|
order_book_id = instrument.order_book_id
|
|
117
117
|
underlying_symbol = instrument.underlying_symbol
|
|
118
118
|
custom_info = self._custom_data.get(order_book_id) or self._custom_data.get(underlying_symbol)
|
|
119
|
-
info = self._default_data.get(order_book_id) or self.
|
|
119
|
+
info = self._default_data.get(order_book_id) or self._default_data.get(underlying_symbol)
|
|
120
120
|
if custom_info:
|
|
121
121
|
info = copy(info) or {}
|
|
122
122
|
info.update(custom_info)
|
|
@@ -18,17 +18,23 @@ import os
|
|
|
18
18
|
import pickle
|
|
19
19
|
import re
|
|
20
20
|
from itertools import chain
|
|
21
|
+
from typing import Callable, Optional, List
|
|
21
22
|
|
|
22
23
|
import h5py
|
|
23
24
|
import numpy as np
|
|
25
|
+
import pandas as pd
|
|
24
26
|
from rqalpha.apis.api_rqdatac import rqdatac
|
|
25
27
|
from rqalpha.utils.concurrent import (ProgressedProcessPoolExecutor,
|
|
26
28
|
ProgressedTask)
|
|
27
29
|
from rqalpha.utils.datetime_func import (convert_date_to_date_int,
|
|
28
|
-
convert_date_to_int)
|
|
30
|
+
convert_date_to_int,)
|
|
29
31
|
from rqalpha.utils.exception import RQDatacVersionTooLow
|
|
30
32
|
from rqalpha.utils.i18n import gettext as _
|
|
31
|
-
from rqalpha.utils.logger import system_log
|
|
33
|
+
from rqalpha.utils.logger import system_log
|
|
34
|
+
from rqalpha.const import TRADING_CALENDAR_TYPE
|
|
35
|
+
from rqalpha.utils.functools import lru_cache
|
|
36
|
+
from rqalpha.environment import Environment
|
|
37
|
+
from rqalpha.model.instrument import Instrument
|
|
32
38
|
|
|
33
39
|
START_DATE = 20050104
|
|
34
40
|
END_DATE = 29991231
|
|
@@ -624,3 +630,96 @@ def update_futures_trading_parameters(path, end_date):
|
|
|
624
630
|
FUTURES_TRADING_PARAMETERS_FIELDS,
|
|
625
631
|
end_date
|
|
626
632
|
)
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
class AutomaticUpdateBundle(object):
|
|
636
|
+
def __init__(self, path: str, filename: str, api: Callable, fields: List[str], end_date: datetime.date) -> None:
|
|
637
|
+
if not os.path.exists(path):
|
|
638
|
+
os.makedirs(path)
|
|
639
|
+
self._file = os.path.join(path, filename)
|
|
640
|
+
self._trading_dates = None
|
|
641
|
+
self._filename = filename
|
|
642
|
+
self._api = api
|
|
643
|
+
self._fields = fields
|
|
644
|
+
self._end_date = end_date
|
|
645
|
+
self.updated = []
|
|
646
|
+
self._env = Environment.get_instance()
|
|
647
|
+
|
|
648
|
+
def get_data(self, instrument: Instrument, dt: datetime.date) -> Optional[np.ndarray]:
|
|
649
|
+
dt = convert_date_to_date_int(dt)
|
|
650
|
+
data = self._get_data_all_time(instrument)
|
|
651
|
+
if data is None:
|
|
652
|
+
return data
|
|
653
|
+
else:
|
|
654
|
+
try:
|
|
655
|
+
data = data[np.searchsorted(data['trading_dt'], dt)]
|
|
656
|
+
except IndexError:
|
|
657
|
+
data = None
|
|
658
|
+
return data
|
|
659
|
+
|
|
660
|
+
@lru_cache(128)
|
|
661
|
+
def _get_data_all_time(self, instrument: Instrument) -> Optional[np.ndarray]:
|
|
662
|
+
if instrument.order_book_id not in self.updated:
|
|
663
|
+
self._auto_update_task(instrument)
|
|
664
|
+
self.updated.append(instrument.order_book_id)
|
|
665
|
+
with h5py.File(self._file, "r") as h5:
|
|
666
|
+
data = h5[instrument.order_book_id][:]
|
|
667
|
+
if len(data) == 0:
|
|
668
|
+
return None
|
|
669
|
+
return data
|
|
670
|
+
|
|
671
|
+
def _auto_update_task(self, instrument: Instrument) -> None:
|
|
672
|
+
"""
|
|
673
|
+
在 rqalpha 策略运行过程中自动更新所需的日线数据
|
|
674
|
+
|
|
675
|
+
:param instrument: 合约对象
|
|
676
|
+
:type instrument: `Instrument`
|
|
677
|
+
"""
|
|
678
|
+
order_book_id = instrument.order_book_id
|
|
679
|
+
start_date = START_DATE
|
|
680
|
+
try:
|
|
681
|
+
h5 = h5py.File(self._file, "a")
|
|
682
|
+
if order_book_id in h5:
|
|
683
|
+
if len(h5[order_book_id][:]) != 0:
|
|
684
|
+
last_date = datetime.datetime.strptime(str(h5[order_book_id][-1]['trading_dt']), "%Y%m%d").date()
|
|
685
|
+
if last_date >= self._end_date:
|
|
686
|
+
return
|
|
687
|
+
start_date = self._env.data_proxy._data_source.get_next_trading_date(last_date).date()
|
|
688
|
+
if start_date > self._end_date:
|
|
689
|
+
return
|
|
690
|
+
arr = self._get_array(instrument, start_date)
|
|
691
|
+
if arr is None:
|
|
692
|
+
if order_book_id not in h5:
|
|
693
|
+
arr = np.array([])
|
|
694
|
+
h5.create_dataset(order_book_id, data=arr)
|
|
695
|
+
else:
|
|
696
|
+
if order_book_id in h5:
|
|
697
|
+
data = np.array(
|
|
698
|
+
[tuple(i) for i in chain(h5[order_book_id][:], arr)],
|
|
699
|
+
dtype=h5[order_book_id].dtype)
|
|
700
|
+
del h5[order_book_id]
|
|
701
|
+
h5.create_dataset(order_book_id, data=data)
|
|
702
|
+
else:
|
|
703
|
+
h5.create_dataset(order_book_id, data=arr)
|
|
704
|
+
except OSError as e:
|
|
705
|
+
raise OSError(_("File {} update failed, if it is using, please update later, "
|
|
706
|
+
"or you can delete then update again".format(self._file))) from e
|
|
707
|
+
finally:
|
|
708
|
+
h5.close()
|
|
709
|
+
|
|
710
|
+
def _get_array(self, instrument: Instrument, start_date: datetime.date) -> Optional[np.ndarray]:
|
|
711
|
+
df = self._api(instrument.order_book_id, start_date, self._end_date, self._fields)
|
|
712
|
+
if not (df is None or df.empty):
|
|
713
|
+
df = df[self._fields].loc[instrument.order_book_id] # rqdatac.get_open_auction_info get Futures's data will auto add 'open_interest' and 'prev_settlement'
|
|
714
|
+
record = df.iloc[0: 1].to_records()
|
|
715
|
+
dtype = [('trading_dt', 'int')]
|
|
716
|
+
for field in self._fields:
|
|
717
|
+
dtype.append((field, record.dtype[field]))
|
|
718
|
+
trading_dt = self._env.data_proxy._data_source.batch_get_trading_date(df.index)
|
|
719
|
+
trading_dt = convert_date_to_date_int(trading_dt)
|
|
720
|
+
arr = np.ones((trading_dt.shape[0], ), dtype=dtype)
|
|
721
|
+
arr['trading_dt'] = trading_dt
|
|
722
|
+
for field in self._fields:
|
|
723
|
+
arr[field] = df[field].values
|
|
724
|
+
return arr
|
|
725
|
+
return None
|
|
@@ -185,6 +185,11 @@ class DataProxy(TradingDatesMixin):
|
|
|
185
185
|
"datetime", "open", "limit_up", "limit_down", "volume", "total_turnover"
|
|
186
186
|
]}
|
|
187
187
|
return PartialBarObject(instrument, bar)
|
|
188
|
+
|
|
189
|
+
def get_open_auction_volume(self, order_book_id, dt):
|
|
190
|
+
instrument = self.instruments(order_book_id)
|
|
191
|
+
volume = self._data_source.get_open_auction_volume(instrument, dt)
|
|
192
|
+
return volume
|
|
188
193
|
|
|
189
194
|
def history(self, order_book_id, bar_count, frequency, field, dt):
|
|
190
195
|
data = self.history_bars(order_book_id, bar_count, frequency,
|
|
@@ -321,5 +326,3 @@ class DataProxy(TradingDatesMixin):
|
|
|
321
326
|
return np.nan, 0
|
|
322
327
|
bar = self._data_source.get_algo_bar(id_or_ins, order_style.start_min, order_style.end_min, dt)
|
|
323
328
|
return (bar[order_style.TYPE], bar["volume"]) if bar else (np.nan, 0)
|
|
324
|
-
|
|
325
|
-
|
|
@@ -19,6 +19,7 @@ import datetime
|
|
|
19
19
|
from typing import Dict, Optional, Union
|
|
20
20
|
|
|
21
21
|
import pandas as pd
|
|
22
|
+
import numpy as np
|
|
22
23
|
|
|
23
24
|
from rqalpha.utils.functools import lru_cache
|
|
24
25
|
from rqalpha.const import TRADING_CALENDAR_TYPE
|
|
@@ -114,3 +115,11 @@ class TradingDatesMixin(object):
|
|
|
114
115
|
return trading_dates[pos + 1]
|
|
115
116
|
|
|
116
117
|
return td
|
|
118
|
+
|
|
119
|
+
def batch_get_trading_date(self, dt_index: pd.DatetimeIndex):
|
|
120
|
+
# 获取 numpy.array 中所有时间所在的交易日
|
|
121
|
+
# 认为晚八点后为第二个交易日,认为晚八点至次日凌晨四点为夜盘
|
|
122
|
+
dt = dt_index - datetime.timedelta(hours=4)
|
|
123
|
+
trading_dates = self.get_trading_calendar(TRADING_CALENDAR_TYPE.EXCHANGE)
|
|
124
|
+
pos = trading_dates.searchsorted(dt.date) + np.where(dt.hour >= 16, 1, 0)
|
|
125
|
+
return trading_dates[pos]
|
|
@@ -18,19 +18,22 @@
|
|
|
18
18
|
from datetime import datetime
|
|
19
19
|
from typing import Optional, Dict, List
|
|
20
20
|
from itertools import chain
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
21
22
|
|
|
22
23
|
import rqalpha
|
|
23
|
-
from rqalpha.core.events import EventBus
|
|
24
|
+
from rqalpha.core.events import EventBus, Event, EVENT
|
|
24
25
|
from rqalpha.const import INSTRUMENT_TYPE
|
|
25
26
|
from rqalpha.utils.logger import system_log, user_log, user_system_log
|
|
26
27
|
from rqalpha.core.global_var import GlobalVars
|
|
27
28
|
from rqalpha.utils.i18n import gettext as _
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from rqalpha.model.order import Order
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
class Environment(object):
|
|
31
34
|
_env = None # type: Environment
|
|
32
35
|
|
|
33
|
-
def __init__(self, config):
|
|
36
|
+
def __init__(self, config, rqdatac_init):
|
|
34
37
|
Environment._env = self
|
|
35
38
|
self.config = config
|
|
36
39
|
self.data_proxy = None # type: Optional[rqalpha.data.data_proxy.DataProxy]
|
|
@@ -55,6 +58,7 @@ class Environment(object):
|
|
|
55
58
|
self._frontend_validators = {} # type: Dict[str, List]
|
|
56
59
|
self._default_frontend_validators = []
|
|
57
60
|
self._transaction_cost_decider_dict = {}
|
|
61
|
+
self.rqdatac_init = rqdatac_init # type: Boolean
|
|
58
62
|
|
|
59
63
|
# Environment.event_bus used in StrategyUniverse()
|
|
60
64
|
from rqalpha.core.strategy_universe import StrategyUniverse
|
|
@@ -113,9 +117,7 @@ class Environment(object):
|
|
|
113
117
|
return chain(self._frontend_validators.get(instrument_type, []), self._default_frontend_validators)
|
|
114
118
|
|
|
115
119
|
def submit_order(self, order):
|
|
116
|
-
|
|
117
|
-
account = self.portfolio.get_account(order.order_book_id)
|
|
118
|
-
if all(v.can_submit_order(order, account) for v in self._get_frontend_validators(instrument_type)):
|
|
120
|
+
if self.can_submit_order(order):
|
|
119
121
|
self.broker.submit_order(order)
|
|
120
122
|
return order
|
|
121
123
|
|
|
@@ -123,9 +125,24 @@ class Environment(object):
|
|
|
123
125
|
instrument_type = self.data_proxy.instrument(order.order_book_id).type
|
|
124
126
|
account = self.portfolio.get_account(order.order_book_id)
|
|
125
127
|
for v in chain(self._frontend_validators.get(instrument_type, []), self._default_frontend_validators):
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
try:
|
|
129
|
+
reason = v.validate_cancellation(order, account)
|
|
130
|
+
if reason:
|
|
131
|
+
self.order_cancellation_failed(order_book_id=order.order_book_id, reason=reason)
|
|
132
|
+
return False
|
|
133
|
+
except NotImplementedError:
|
|
134
|
+
# 避免由于某些 mod 版本未更新,Validator method 未修改
|
|
135
|
+
if not v.can_cancel_order(order, account):
|
|
136
|
+
return False
|
|
128
137
|
return True
|
|
138
|
+
|
|
139
|
+
def order_creation_failed(self, order_book_id, reason):
|
|
140
|
+
user_system_log.warn(reason)
|
|
141
|
+
self.event_bus.publish_event(Event(EVENT.ORDER_CREATION_REJECT, order_book_id=order_book_id, reason=reason))
|
|
142
|
+
|
|
143
|
+
def order_cancellation_failed(self, order_book_id, reason):
|
|
144
|
+
user_system_log.warn(reason)
|
|
145
|
+
self.event_bus.publish_event(Event(EVENT.ORDER_CANCELLATION_REJECT, order_book_id=order_book_id, reason=reason))
|
|
129
146
|
|
|
130
147
|
def get_universe(self):
|
|
131
148
|
return self._universe.get()
|
|
@@ -178,11 +195,18 @@ class Environment(object):
|
|
|
178
195
|
self.calendar_dt = calendar_dt
|
|
179
196
|
self.trading_dt = trading_dt
|
|
180
197
|
|
|
181
|
-
def can_submit_order(self, order):
|
|
198
|
+
def can_submit_order(self, order: 'Order') -> bool:
|
|
182
199
|
# forward compatible
|
|
183
200
|
instrument_type = self.data_proxy.instrument(order.order_book_id).type
|
|
184
201
|
account = self.portfolio.get_account(order.order_book_id)
|
|
185
202
|
for v in self._get_frontend_validators(instrument_type):
|
|
186
|
-
|
|
187
|
-
|
|
203
|
+
try:
|
|
204
|
+
reason = v.validate_submission(order, account)
|
|
205
|
+
if reason:
|
|
206
|
+
self.order_creation_failed(order_book_id=order.order_book_id, reason=reason)
|
|
207
|
+
return False
|
|
208
|
+
except NotImplementedError:
|
|
209
|
+
# 避免由于某些 mod 版本未更新,Validator method 未修改
|
|
210
|
+
if not v.can_submit_order(order, account):
|
|
211
|
+
return False
|
|
188
212
|
return True
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
import abc
|
|
19
19
|
from datetime import datetime, date
|
|
20
|
-
from typing import Any, Union, Optional, Iterable, Dict, List, Sequence
|
|
20
|
+
from typing import Any, Union, Optional, Iterable, Dict, List, Sequence, TYPE_CHECKING
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from rqalpha.portfolio.account import Account
|
|
21
23
|
|
|
22
24
|
import numpy
|
|
23
25
|
from six import with_metaclass
|
|
@@ -347,6 +349,20 @@ class AbstractDataSource(object):
|
|
|
347
349
|
datetime, open, limit_up, limit_down, volume, total_turnover
|
|
348
350
|
"""
|
|
349
351
|
raise NotImplementedError
|
|
352
|
+
|
|
353
|
+
def get_open_auction_volume(self, instrument, dt):
|
|
354
|
+
"""
|
|
355
|
+
获取指定资产当日的集合竞价成交量
|
|
356
|
+
|
|
357
|
+
:param instrument: 合约对象
|
|
358
|
+
:type instrument: class:`~Instrument`
|
|
359
|
+
|
|
360
|
+
:param dt: 集合竞价时间
|
|
361
|
+
:type dt: datetime.datetime
|
|
362
|
+
|
|
363
|
+
:return: `float`
|
|
364
|
+
"""
|
|
365
|
+
raise NotImplementedError
|
|
350
366
|
|
|
351
367
|
def get_settle_price(self, instrument, date):
|
|
352
368
|
"""
|
|
@@ -635,18 +651,21 @@ class AbstractFrontendValidator(with_metaclass(abc.ABCMeta)):
|
|
|
635
651
|
|
|
636
652
|
扩展模块可以通过 env.add_frontend_validator 添加自定义的前端风控逻辑
|
|
637
653
|
"""
|
|
638
|
-
|
|
639
654
|
@abc.abstractmethod
|
|
640
|
-
def
|
|
655
|
+
def validate_submission(self, order: Order, account: Optional['Account'] = None) -> Optional[str]:
|
|
641
656
|
"""
|
|
642
|
-
|
|
657
|
+
进行下单前的验证,若通过则返回 None
|
|
658
|
+
|
|
659
|
+
:return: `Optional[str]`
|
|
643
660
|
"""
|
|
644
661
|
raise NotImplementedError
|
|
645
|
-
|
|
662
|
+
|
|
646
663
|
@abc.abstractmethod
|
|
647
|
-
def
|
|
664
|
+
def validate_cancellation(self, order: Order, account: Optional['Account'] = None) -> Optional[str]:
|
|
648
665
|
"""
|
|
649
|
-
|
|
666
|
+
进行撤销订单前的验证,若通过则返回 None
|
|
667
|
+
|
|
668
|
+
:return: `Optional[str]`
|
|
650
669
|
"""
|
|
651
670
|
raise NotImplementedError
|
|
652
671
|
|
|
@@ -122,12 +122,14 @@ def init_rqdatac(rqdatac_uri):
|
|
|
122
122
|
init_rqdatac_env(rqdatac_uri)
|
|
123
123
|
try:
|
|
124
124
|
rqdatac.init()
|
|
125
|
+
return True
|
|
125
126
|
except Exception as e:
|
|
126
127
|
system_log.warn(_('rqdatac init failed, some apis will not function properly: {}').format(str(e)))
|
|
128
|
+
return
|
|
127
129
|
|
|
128
130
|
|
|
129
131
|
def run(config, source_code=None, user_funcs=None):
|
|
130
|
-
env = Environment(config)
|
|
132
|
+
env = Environment(config, init_rqdatac(getattr(config.base, 'rqdatac_uri', None)))
|
|
131
133
|
persist_helper = None
|
|
132
134
|
init_succeed = False
|
|
133
135
|
mod_handler = ModHandler()
|
|
@@ -136,7 +138,6 @@ def run(config, source_code=None, user_funcs=None):
|
|
|
136
138
|
# avoid register handlers everytime
|
|
137
139
|
# when running in ipython
|
|
138
140
|
set_loggers(config)
|
|
139
|
-
init_rqdatac(getattr(config.base, 'rqdatac_uri', None))
|
|
140
141
|
system_log.debug("\n" + pformat(config.convert_to_dict()))
|
|
141
142
|
|
|
142
143
|
env.set_strategy_loader(init_strategy_loader(env, source_code, user_funcs, config))
|
|
@@ -47,9 +47,10 @@ def _submit_order(id_or_ins, amount, side, position_effect, style):
|
|
|
47
47
|
|
|
48
48
|
amount = int(amount)
|
|
49
49
|
if amount == 0:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
50
|
+
reason = _(u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}").format(
|
|
51
|
+
order_book_id=order_book_id
|
|
52
|
+
)
|
|
53
|
+
env.order_creation_failed(order_book_id=order_book_id, reason=reason)
|
|
53
54
|
return None
|
|
54
55
|
if isinstance(style, LimitOrder) and np.isnan(style.get_limit_price()):
|
|
55
56
|
raise RQInvalidArgument(_(u"Limit order price should not be nan."))
|
|
@@ -62,23 +63,21 @@ def _submit_order(id_or_ins, amount, side, position_effect, style):
|
|
|
62
63
|
|
|
63
64
|
price = env.get_last_price(order_book_id)
|
|
64
65
|
if not is_valid_price(price):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
66
|
+
reason = _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
|
|
67
|
+
env.order_creation_failed(order_book_id=order_book_id, reason=reason)
|
|
68
68
|
return
|
|
69
69
|
|
|
70
|
-
env = Environment.get_instance()
|
|
71
|
-
|
|
72
70
|
orders = []
|
|
73
71
|
if position_effect in (POSITION_EFFECT.CLOSE_TODAY, POSITION_EFFECT.CLOSE):
|
|
74
72
|
direction = POSITION_DIRECTION.LONG if side == SIDE.SELL else POSITION_DIRECTION.SHORT
|
|
75
73
|
position = env.portfolio.get_position(order_book_id, direction) # type: Position
|
|
76
74
|
if position_effect == POSITION_EFFECT.CLOSE_TODAY:
|
|
77
75
|
if amount > position.today_closable:
|
|
78
|
-
|
|
76
|
+
reason = _(
|
|
79
77
|
"Order Creation Failed: "
|
|
80
|
-
"close today amount {amount} is larger than today closable quantity {quantity}"
|
|
81
|
-
|
|
78
|
+
"close today amount {amount} is larger than today closable quantity {quantity}").format(
|
|
79
|
+
amount=amount, quantity=position.today_closable)
|
|
80
|
+
env.order_creation_failed(order_book_id=order_book_id, reason=reason)
|
|
82
81
|
return []
|
|
83
82
|
orders.append(Order.__from_create__(
|
|
84
83
|
order_book_id, amount, side, style, POSITION_EFFECT.CLOSE_TODAY
|
|
@@ -86,10 +85,9 @@ def _submit_order(id_or_ins, amount, side, position_effect, style):
|
|
|
86
85
|
else:
|
|
87
86
|
quantity, old_quantity = position.quantity, position.old_quantity
|
|
88
87
|
if amount > quantity:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
))
|
|
88
|
+
reason = _(u"Order Creation Failed: close amount {amount} is larger than position quantity {quantity}").format(
|
|
89
|
+
amount=amount, quantity=quantity)
|
|
90
|
+
env.order_creation_failed(order_book_id=order_book_id, reason=reason)
|
|
93
91
|
return []
|
|
94
92
|
if amount > old_quantity:
|
|
95
93
|
if old_quantity != 0:
|
|
@@ -34,9 +34,9 @@ from rqalpha.const import (DEFAULT_ACCOUNT_TYPE, EXECUTION_PHASE,
|
|
|
34
34
|
INSTRUMENT_TYPE, ORDER_TYPE, POSITION_DIRECTION,
|
|
35
35
|
POSITION_EFFECT, SIDE)
|
|
36
36
|
from rqalpha.core.execution_context import ExecutionContext
|
|
37
|
+
from rqalpha.core.events import Event, EVENT
|
|
37
38
|
from rqalpha.environment import Environment
|
|
38
|
-
from rqalpha.mod.rqalpha_mod_sys_risk.validators.cash_validator import
|
|
39
|
-
is_cash_enough
|
|
39
|
+
from rqalpha.mod.rqalpha_mod_sys_risk.validators.cash_validator import validate_cash
|
|
40
40
|
from rqalpha.model.instrument import IndustryCode as industry_code
|
|
41
41
|
from rqalpha.model.instrument import IndustryCodeItem, Instrument
|
|
42
42
|
from rqalpha.model.instrument import SectorCode as sector_code
|
|
@@ -100,8 +100,8 @@ def _submit_order(ins, amount, side, position_effect, style, current_quantity, a
|
|
|
100
100
|
raise RQInvalidArgument(_(u"Limit order price should not be nan."))
|
|
101
101
|
price = env.data_proxy.get_last_price(ins.order_book_id)
|
|
102
102
|
if not is_valid_price(price):
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
reason = _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=ins.order_book_id)
|
|
104
|
+
env.order_creation_failed(order_book_id=ins.order_book_id, reason=reason)
|
|
105
105
|
return
|
|
106
106
|
|
|
107
107
|
if (side == SIDE.BUY and current_quantity != -amount) or (side == SIDE.SELL and current_quantity != abs(amount)):
|
|
@@ -109,14 +109,13 @@ def _submit_order(ins, amount, side, position_effect, style, current_quantity, a
|
|
|
109
109
|
amount = _round_order_quantity(ins, amount)
|
|
110
110
|
|
|
111
111
|
if amount == 0:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
).format(order_book_id=ins.order_book_id))
|
|
112
|
+
reason = _(u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}").format(order_book_id=ins.order_book_id)
|
|
113
|
+
env.order_creation_failed(order_book_id=ins.order_book_id, reason=reason)
|
|
115
114
|
return
|
|
116
115
|
order = Order.__from_create__(ins.order_book_id, abs(amount), side, style, position_effect)
|
|
117
116
|
if side == SIDE.BUY and auto_switch_order_value:
|
|
118
117
|
account, position, ins = _get_account_position_ins(ins)
|
|
119
|
-
if
|
|
118
|
+
if validate_cash(env, order, account.cash):
|
|
120
119
|
user_system_log.warn(_(
|
|
121
120
|
"insufficient cash, use all remaining cash({}) to create order"
|
|
122
121
|
).format(account.cash))
|
|
@@ -129,7 +128,7 @@ def _order_shares(ins, amount, style, quantity, auto_switch_order_value):
|
|
|
129
128
|
return _submit_order(ins, amount, side, position_effect, style, quantity, auto_switch_order_value)
|
|
130
129
|
|
|
131
130
|
|
|
132
|
-
def _order_value(account, position, ins, cash_amount, style):
|
|
131
|
+
def _order_value(account, position, ins, cash_amount, style, zero_amount_as_exception=True):
|
|
133
132
|
env = Environment.get_instance()
|
|
134
133
|
if cash_amount > 0:
|
|
135
134
|
cash_amount = min(cash_amount, account.cash)
|
|
@@ -138,9 +137,8 @@ def _order_value(account, position, ins, cash_amount, style):
|
|
|
138
137
|
else:
|
|
139
138
|
price = env.data_proxy.get_last_price(ins.order_book_id)
|
|
140
139
|
if not is_valid_price(price):
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
140
|
+
reason = _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=ins.order_book_id)
|
|
141
|
+
env.order_creation_failed(order_book_id=ins.order_book_id, reason=reason)
|
|
144
142
|
return
|
|
145
143
|
|
|
146
144
|
amount = int(Decimal(cash_amount) / Decimal(price))
|
|
@@ -155,9 +153,9 @@ def _order_value(account, position, ins, cash_amount, style):
|
|
|
155
153
|
break
|
|
156
154
|
amount -= round_lot
|
|
157
155
|
else:
|
|
158
|
-
|
|
159
|
-
u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}"
|
|
160
|
-
|
|
156
|
+
if zero_amount_as_exception:
|
|
157
|
+
reason = _(u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}").format(order_book_id=ins.order_book_id)
|
|
158
|
+
env.order_creation_failed(order_book_id=ins.order_book_id, reason=reason)
|
|
161
159
|
return
|
|
162
160
|
|
|
163
161
|
if amount < 0:
|
|
@@ -198,7 +196,7 @@ def stock_order_target_value(id_or_ins, cash_amount, price_or_style=None, price=
|
|
|
198
196
|
)
|
|
199
197
|
_delta = cash_amount - position.market_value
|
|
200
198
|
_style = open_style if _delta > 0 else close_style
|
|
201
|
-
return _order_value(account, position, ins, _delta, _style)
|
|
199
|
+
return _order_value(account, position, ins, _delta, _style, zero_amount_as_exception=False)
|
|
202
200
|
|
|
203
201
|
|
|
204
202
|
@order_target_percent.register(INST_TYPE_IN_STOCK_ACCOUNT)
|
|
@@ -211,7 +209,7 @@ def stock_order_target_percent(id_or_ins, percent, price_or_style=None, price=No
|
|
|
211
209
|
)
|
|
212
210
|
_delta = account.total_value * percent - position.market_value
|
|
213
211
|
_style = open_style if _delta > 0 else close_style
|
|
214
|
-
return _order_value(account, position, ins, _delta, _style)
|
|
212
|
+
return _order_value(account, position, ins, _delta, _style, zero_amount_as_exception=False)
|
|
215
213
|
|
|
216
214
|
|
|
217
215
|
@order.register(INST_TYPE_IN_STOCK_ACCOUNT)
|
|
@@ -342,9 +340,8 @@ def order_target_portfolio(
|
|
|
342
340
|
order_book_id = ins.order_book_id
|
|
343
341
|
last_price = env.data_proxy.get_last_price(order_book_id)
|
|
344
342
|
if not is_valid_price(last_price):
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
)
|
|
343
|
+
reason = _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
|
|
344
|
+
env.order_creation_failed(order_book_id=order_book_id, reason=reason)
|
|
348
345
|
continue
|
|
349
346
|
|
|
350
347
|
price_or_style = price_or_styles.get(ins.order_book_id)
|
|
@@ -380,12 +377,10 @@ def order_target_portfolio(
|
|
|
380
377
|
open_price = _get_order_style_price(order_book_id, open_style)
|
|
381
378
|
close_price = _get_order_style_price(order_book_id, close_style)
|
|
382
379
|
if not (is_valid_price(close_price) and is_valid_price(open_price)):
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
"Invalid close/open price {close_price}/{open_price}").format(
|
|
386
|
-
id_or_ins=order_book_id, close_price=close_price, open_price=open_price
|
|
387
|
-
)
|
|
380
|
+
reason = _("Adjust position of {id_or_ins} Failed: Invalid close/open price {close_price}/{open_price}").format(
|
|
381
|
+
id_or_ins=order_book_id, close_price=close_price, open_price=open_price
|
|
388
382
|
)
|
|
383
|
+
env.order_creation_failed(order_book_id=order_book_id, reason=reason)
|
|
389
384
|
continue
|
|
390
385
|
|
|
391
386
|
delta_quantity = (account_value * target_percent / close_price) - current_quantities.get(order_book_id, 0)
|
|
@@ -13,24 +13,18 @@ class MarginComponentValidator(AbstractFrontendValidator):
|
|
|
13
13
|
self._margin_type = margin_type
|
|
14
14
|
from rqalpha.apis.api_rqdatac import get_margin_stocks
|
|
15
15
|
self._get_margin_stocks = get_margin_stocks
|
|
16
|
-
|
|
17
|
-
def
|
|
18
|
-
return True
|
|
19
|
-
|
|
20
|
-
def can_submit_order(self, order, account=None):
|
|
21
|
-
# type: (Order, Optional[Account]) -> bool
|
|
22
|
-
|
|
16
|
+
|
|
17
|
+
def validate_submission(self, order: Order, account: Optional[Account] = None) -> Optional[str]:
|
|
23
18
|
# 没负债等于没融资,则不需要限制股票池
|
|
24
19
|
if account.cash_liabilities == 0:
|
|
25
|
-
return
|
|
26
|
-
|
|
20
|
+
return None
|
|
27
21
|
symbols = self._get_margin_stocks(margin_type=self._margin_type)
|
|
28
|
-
|
|
29
22
|
# 是否在股票池中
|
|
30
23
|
if order.order_book_id in set(symbols):
|
|
31
|
-
return
|
|
24
|
+
return None
|
|
32
25
|
else:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
reason = "Order Creation Failed: margin stock pool not contains {}.".format(order.order_book_id)
|
|
27
|
+
return reason
|
|
28
|
+
|
|
29
|
+
def validate_cancellation(self, order: Order, account: Optional[Account] = None) -> Optional[str]:
|
|
30
|
+
return None
|
|
@@ -318,6 +318,12 @@ class FuturePosition(Position):
|
|
|
318
318
|
user_system_log.warn(_(u"{order_book_id} is expired, close all positions by system").format(
|
|
319
319
|
order_book_id=self._order_book_id
|
|
320
320
|
))
|
|
321
|
+
account = self._env.get_account(self._order_book_id)
|
|
322
|
+
side = SIDE.SELL if self.direction == POSITION_DIRECTION.LONG else SIDE.BUY
|
|
323
|
+
trade = Trade.__from_create__(
|
|
324
|
+
None, self.last_price, self._quantity, side, POSITION_EFFECT.CLOSE, self._order_book_id
|
|
325
|
+
)
|
|
326
|
+
self._env.event_bus.publish_event(Event(EVENT.TRADE, account=account, trade=trade, order=None))
|
|
321
327
|
self._quantity = self._old_quantity = 0
|
|
322
328
|
return delta_cash
|
|
323
329
|
|