rqalpha 5.3.8__tar.gz → 5.3.10__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.8/rqalpha.egg-info → rqalpha-5.3.10}/PKG-INFO +1 -1
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/_version.py +3 -3
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/apis/api_base.py +2 -5
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/base_data_source/data_source.py +1 -1
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/data_proxy.py +0 -2
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/environment.py +32 -9
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/interface.py +12 -7
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/api/api_future.py +13 -15
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/api/api_stock.py +20 -25
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/component_validator.py +9 -15
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/position_validator.py +13 -14
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/validator.py +7 -11
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/mod.py +53 -20
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/report/excel_template.py +5 -3
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/report/report.py +53 -8
- rqalpha-5.3.10/rqalpha/mod/rqalpha_mod_sys_analyser/report/templates/summary.xlsx +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/validators/cash_validator.py +18 -19
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/validators/is_trading_validator.py +15 -13
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/validators/price_validator.py +12 -13
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/validators/self_trade_validator.py +11 -12
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/matcher.py +31 -7
- rqalpha-5.3.10/rqalpha/mod/rqalpha_mod_sys_simulation/validator.py +20 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/portfolio/account.py +4 -1
- rqalpha-5.3.10/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.mo +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.po +85 -72
- {rqalpha-5.3.8 → rqalpha-5.3.10/rqalpha.egg-info}/PKG-INFO +1 -1
- {rqalpha-5.3.8 → rqalpha-5.3.10}/setup.cfg +1 -1
- rqalpha-5.3.8/rqalpha/mod/rqalpha_mod_sys_analyser/report/templates/summary.xlsx +0 -0
- rqalpha-5.3.8/rqalpha/mod/rqalpha_mod_sys_simulation/validator.py +0 -18
- rqalpha-5.3.8/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.mo +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/CHANGELOG.rst +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/LICENSE +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/MANIFEST.in +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/README.rst +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/__main__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/api.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/apis/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/apis/api_abstract.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/apis/api_rqdatac.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/apis/names.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/cmds/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/cmds/bundle.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/cmds/entry.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/cmds/misc.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/cmds/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/cmds/run.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/config.yml +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/const.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/events.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/execution_context.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/executor.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/global_var.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/strategy.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/strategy_context.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/strategy_loader.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/core/strategy_universe.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/bar_dict_price_board.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/base_data_source/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/base_data_source/adjust.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/base_data_source/storage_interface.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/base_data_source/storages.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/bundle.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/data/trading_dates_mixin.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/IF1706_20161108.csv +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/IF_macd.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/buy_and_hold.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/data_source/get_csv_module.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/data_source/import_get_csv_module.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/data_source/read_csv_as_df.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/extend_api/rqalpha_mod_extend_api_demo.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/extend_api/test_extend_api.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/golden_cross.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/macd.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/pair_trading.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/rsi.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/run_code_demo.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/run_file_demo.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/run_func_demo.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/subscribe_event.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/test_pt.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/examples/turtle.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/main.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/api/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/position_model.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/consts.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/plot.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/utils.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/plot_store.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/report/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_progress/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_progress/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_risk/validators/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_scheduler/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_scheduler/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_scheduler/scheduler.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/signal_broker.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/simulation_broker.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/simulation_event_source.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/slippage.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_simulation/testing.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/deciders.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/mod.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/utils.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod_config.yml +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/model/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/model/bar.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/model/instrument.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/model/order.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/model/tick.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/model/trade.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/portfolio/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/portfolio/position.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/resource/ricequant-logo.png +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/user_module.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/arg_checker.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/class_helper.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/click_helper.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/concurrent.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/config.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/datetime_func.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/dict_func.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/exception.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/functools.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/i18n.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/log_capture.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/logger.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/package_helper.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/persisit_helper.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/repr.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/risk_free_helper.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/rq_json.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/strategy_loader_help.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/testing/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/testing/fixtures.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/testing/mocking.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/translations/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/translations/zh_Hans_CN/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/utils/typing.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha.egg-info/SOURCES.txt +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha.egg-info/dependency_links.txt +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha.egg-info/entry_points.txt +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha.egg-info/not-zip-safe +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha.egg-info/requires.txt +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha.egg-info/top_level.txt +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/setup.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_accounts/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_accounts/test_account_model.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_accounts/test_futures_settlement_price_type.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_accounts/test_margin_stocks.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_accounts/test_position_models.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_scheduler/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_scheduler/test_physical_time.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_scheduler/test_scheduler.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_simulation/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_simulation/test_management_fee.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_simulation/test_match.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_simulation/test_signal_broker.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_simulation/test_simulation_broker.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_simulation/test_simulation_event_source.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_transaction_cost/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/mod/sys_transaction_cost/test_commission_multiplier.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/test_api_base.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/test_api_future.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/test_api_stock.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/test_config.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/api_tests/utils.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_f_buy_and_hold.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_f_delivery.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_f_macd.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_f_macd_signal.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_f_mean_reverting.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_f_tick_size.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_buy_and_hold.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_dual_thrust.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_pit_tax.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_scheduler.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_tick_size.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_turtle.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_s_turtle_signal.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/test_sf_buy_and_hold.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_data/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_data/test_auto_update_bundle/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_data/test_auto_update_bundle/test_auto_update_bundle_mixin.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_data/test_instrument_mixin.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_data/test_trading_dates_mixin.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_mod/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_mod/test_sys_simulation/__init__.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/unittest/test_mod/test_sys_simulation/test_simulation_event_source.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/tests/utils.py +0 -0
- {rqalpha-5.3.8 → rqalpha-5.3.10}/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-25T10:32:21+0800",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "5.3.
|
|
14
|
+
"full-revisionid": "215d9b2f7ef5175ff99ced5555a81ff7295416c2",
|
|
15
|
+
"version": "5.3.10"
|
|
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 = {
|
|
@@ -18,13 +18,16 @@
|
|
|
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):
|
|
@@ -114,9 +117,7 @@ class Environment(object):
|
|
|
114
117
|
return chain(self._frontend_validators.get(instrument_type, []), self._default_frontend_validators)
|
|
115
118
|
|
|
116
119
|
def submit_order(self, order):
|
|
117
|
-
|
|
118
|
-
account = self.portfolio.get_account(order.order_book_id)
|
|
119
|
-
if all(v.can_submit_order(order, account) for v in self._get_frontend_validators(instrument_type)):
|
|
120
|
+
if self.can_submit_order(order):
|
|
120
121
|
self.broker.submit_order(order)
|
|
121
122
|
return order
|
|
122
123
|
|
|
@@ -124,9 +125,24 @@ class Environment(object):
|
|
|
124
125
|
instrument_type = self.data_proxy.instrument(order.order_book_id).type
|
|
125
126
|
account = self.portfolio.get_account(order.order_book_id)
|
|
126
127
|
for v in chain(self._frontend_validators.get(instrument_type, []), self._default_frontend_validators):
|
|
127
|
-
|
|
128
|
-
|
|
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
|
|
129
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))
|
|
130
146
|
|
|
131
147
|
def get_universe(self):
|
|
132
148
|
return self._universe.get()
|
|
@@ -179,11 +195,18 @@ class Environment(object):
|
|
|
179
195
|
self.calendar_dt = calendar_dt
|
|
180
196
|
self.trading_dt = trading_dt
|
|
181
197
|
|
|
182
|
-
def can_submit_order(self, order):
|
|
198
|
+
def can_submit_order(self, order: 'Order') -> bool:
|
|
183
199
|
# forward compatible
|
|
184
200
|
instrument_type = self.data_proxy.instrument(order.order_book_id).type
|
|
185
201
|
account = self.portfolio.get_account(order.order_book_id)
|
|
186
202
|
for v in self._get_frontend_validators(instrument_type):
|
|
187
|
-
|
|
188
|
-
|
|
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
|
|
189
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
|
|
@@ -649,18 +651,21 @@ class AbstractFrontendValidator(with_metaclass(abc.ABCMeta)):
|
|
|
649
651
|
|
|
650
652
|
扩展模块可以通过 env.add_frontend_validator 添加自定义的前端风控逻辑
|
|
651
653
|
"""
|
|
652
|
-
|
|
653
654
|
@abc.abstractmethod
|
|
654
|
-
def
|
|
655
|
+
def validate_submission(self, order: Order, account: Optional['Account'] = None) -> Optional[str]:
|
|
655
656
|
"""
|
|
656
|
-
|
|
657
|
+
进行下单前的验证,若通过则返回 None
|
|
658
|
+
|
|
659
|
+
:return: `Optional[str]`
|
|
657
660
|
"""
|
|
658
661
|
raise NotImplementedError
|
|
659
|
-
|
|
662
|
+
|
|
660
663
|
@abc.abstractmethod
|
|
661
|
-
def
|
|
664
|
+
def validate_cancellation(self, order: Order, account: Optional['Account'] = None) -> Optional[str]:
|
|
662
665
|
"""
|
|
663
|
-
|
|
666
|
+
进行撤销订单前的验证,若通过则返回 None
|
|
667
|
+
|
|
668
|
+
:return: `Optional[str]`
|
|
664
669
|
"""
|
|
665
670
|
raise NotImplementedError
|
|
666
671
|
|
|
@@ -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)
|
{rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_accounts/component_validator.py
RENAMED
|
@@ -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
|
|
@@ -27,32 +27,31 @@ from rqalpha.utils.i18n import gettext as _
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class PositionValidator(AbstractFrontendValidator):
|
|
30
|
-
def
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
def
|
|
34
|
-
# type: (Order, Optional[Account]) -> bool
|
|
30
|
+
def validate_cancellation(self, order: Order, account: Optional[Account] = None) -> Optional[str]:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
def validate_submission(self, order: Order, account: Optional[Account] = None) -> Optional[str]:
|
|
35
34
|
if account is None:
|
|
36
|
-
return
|
|
35
|
+
return None
|
|
37
36
|
if order.position_effect in (POSITION_EFFECT.OPEN, POSITION_EFFECT.EXERCISE):
|
|
38
|
-
return
|
|
37
|
+
return None
|
|
39
38
|
position = account.get_position(order.order_book_id, order.position_direction) # type: AbstractPosition
|
|
40
39
|
if order.position_effect == POSITION_EFFECT.CLOSE_TODAY and order.quantity > position.today_closable:
|
|
41
|
-
|
|
40
|
+
reason = _(
|
|
42
41
|
"Order Creation Failed: not enough today position {order_book_id} to close, target"
|
|
43
42
|
" quantity is {quantity}, closable today quantity is {closable}").format(
|
|
44
43
|
order_book_id=order.order_book_id,
|
|
45
44
|
quantity=order.quantity,
|
|
46
45
|
closable=position.today_closable,
|
|
47
|
-
)
|
|
48
|
-
return
|
|
46
|
+
)
|
|
47
|
+
return reason
|
|
49
48
|
if order.position_effect == POSITION_EFFECT.CLOSE and order.quantity > position.closable:
|
|
50
|
-
|
|
49
|
+
reason = _(
|
|
51
50
|
"Order Creation Failed: not enough position {order_book_id} to close or exercise, target"
|
|
52
51
|
" sell quantity is {quantity}, closable quantity is {closable}").format(
|
|
53
52
|
order_book_id=order.order_book_id,
|
|
54
53
|
quantity=order.quantity,
|
|
55
54
|
closable=position.closable,
|
|
56
|
-
)
|
|
57
|
-
return
|
|
58
|
-
return
|
|
55
|
+
)
|
|
56
|
+
return reason
|
|
57
|
+
return None
|
|
@@ -9,16 +9,12 @@ from rqalpha.portfolio.account import Account
|
|
|
9
9
|
class MarginInstrumentValidator(AbstractFrontendValidator):
|
|
10
10
|
""" 融资下单品种限制: 当开启股票池限制且有融资余额时只能交易股票和ETF """
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
return True
|
|
14
|
-
|
|
15
|
-
def can_submit_order(self, order, account=None):
|
|
16
|
-
# type: (Order, Optional[Account]) -> bool
|
|
17
|
-
|
|
12
|
+
def validate_submission(self, order: Order, account: Optional[Account] = None) -> Optional[str]:
|
|
18
13
|
if account.cash_liabilities > 0:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
22
|
-
return False
|
|
14
|
+
reason = "Order Creation Failed: cash liabilities > 0, {} not support submit order".format(order.order_book_id)
|
|
15
|
+
return reason
|
|
23
16
|
else:
|
|
24
|
-
return
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
def validate_cancellation(self, order: Order, account: Optional[Account] = None) -> Optional[str]:
|
|
20
|
+
return None
|
|
@@ -33,6 +33,7 @@ from rqalpha.core.events import EVENT
|
|
|
33
33
|
from rqalpha.interface import AbstractMod, AbstractPosition
|
|
34
34
|
from rqalpha.utils.i18n import gettext as _
|
|
35
35
|
from rqalpha.utils import INST_TYPE_IN_STOCK_ACCOUNT
|
|
36
|
+
from rqalpha.utils.datetime_func import convert_int_to_date
|
|
36
37
|
from rqalpha.utils.logger import user_system_log
|
|
37
38
|
from rqalpha.const import DAYS_CNT
|
|
38
39
|
from rqalpha.api import export_as_api
|
|
@@ -131,23 +132,60 @@ class AnalyserMod(AbstractMod):
|
|
|
131
132
|
daily_return_list.append((bar.close / bar.prev_close - 1.0, benchmark[1]))
|
|
132
133
|
weights += benchmark[1]
|
|
133
134
|
return sum([daily[0] * daily[1] / weights for daily in daily_return_list])
|
|
134
|
-
|
|
135
|
-
def
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
135
|
+
|
|
136
|
+
def generate_benchmark_daily_returns_and_portfolio(self, event):
|
|
137
|
+
_s = self._env.config.base.start_date
|
|
138
|
+
_e = self._env.config.base.end_date
|
|
139
|
+
trading_dates = self._env.data_proxy.get_trading_dates(_s, _e)
|
|
140
|
+
if self._benchmark is None:
|
|
141
|
+
self._benchmark_daily_returns = list(np.full(len(trading_dates), np.nan))
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
# generate benchmerk daily returns
|
|
145
|
+
self._benchmark_daily_returns = np.zeros(len(trading_dates))
|
|
146
|
+
weights = 0
|
|
147
|
+
for order_book_id, weight in self._benchmark:
|
|
148
|
+
ins = self._env.data_proxy.instrument(order_book_id)
|
|
149
|
+
if ins is None:
|
|
150
|
+
raise RuntimeError(
|
|
151
|
+
_("benchmark {} not exists, please entry correct order_book_id").format(order_book_id)
|
|
152
|
+
)
|
|
153
|
+
bars = self._env.data_proxy.history_bars(
|
|
154
|
+
order_book_id = order_book_id,
|
|
155
|
+
bar_count = len(trading_dates) + 1, # Get an extra day for calculation
|
|
156
|
+
frequency = "1d",
|
|
157
|
+
field = ["datetime", "close"],
|
|
158
|
+
dt = _e,
|
|
159
|
+
skip_suspended=False,
|
|
160
|
+
)
|
|
161
|
+
if len(bars) == len(trading_dates) + 1:
|
|
162
|
+
if convert_int_to_date(bars[1]['datetime']).date() != _s:
|
|
163
|
+
raise RuntimeError(_(
|
|
164
|
+
"benchmark {} missing data between backtest start date {} and end date {}").format(order_book_id, _s, _e)
|
|
149
165
|
)
|
|
166
|
+
daily_returns = (bars['close'] / np.roll(bars['close'], 1) - 1.0)[1: ]
|
|
167
|
+
self._benchmark_daily_returns = self._benchmark_daily_returns + daily_returns * weight
|
|
168
|
+
weights += weight
|
|
169
|
+
else:
|
|
170
|
+
if len(bars) == 0:
|
|
171
|
+
(available_s, available_e) = (ins.listed_date, ins.de_listed_date)
|
|
172
|
+
else:
|
|
173
|
+
(available_s, available_e) = (convert_int_to_date(bars[0]['datetime']).date(), convert_int_to_date(bars[-1]['datetime']).date())
|
|
174
|
+
raise RuntimeError(
|
|
175
|
+
_("benchmark {} available data start date {} >= backtest start date {} or end date {} <= backtest end "
|
|
176
|
+
"date {}").format(order_book_id, available_s, _s, available_e, _e)
|
|
177
|
+
)
|
|
178
|
+
self._benchmark_daily_returns = self._benchmark_daily_returns / weight
|
|
179
|
+
|
|
180
|
+
# generate benchmark portfolio
|
|
181
|
+
unit_net_value = (self._benchmark_daily_returns + 1).cumprod()
|
|
182
|
+
self._total_benchmark_portfolios = {
|
|
183
|
+
"date": trading_dates,
|
|
184
|
+
"unit_net_value": unit_net_value
|
|
185
|
+
}
|
|
150
186
|
|
|
187
|
+
def _subscribe_events(self, event):
|
|
188
|
+
self._env.event_bus.add_listener(EVENT.BEFORE_STRATEGY_RUN, self.generate_benchmark_daily_returns_and_portfolio)
|
|
151
189
|
self._env.event_bus.add_listener(EVENT.TRADE, self._collect_trade)
|
|
152
190
|
self._env.event_bus.add_listener(EVENT.ORDER_CREATION_PASS, self._collect_order)
|
|
153
191
|
self._env.event_bus.prepend_listener(EVENT.POST_SETTLEMENT, self._collect_daily)
|
|
@@ -164,11 +202,6 @@ class AnalyserMod(AbstractMod):
|
|
|
164
202
|
|
|
165
203
|
self._portfolio_daily_returns.append(portfolio.daily_returns)
|
|
166
204
|
self._total_portfolios.append(self._to_portfolio_record(date, portfolio))
|
|
167
|
-
self._benchmark_daily_returns.append(self.get_benchmark_daily_returns())
|
|
168
|
-
self._total_benchmark_portfolios.append({
|
|
169
|
-
"date": date,
|
|
170
|
-
"unit_net_value": (np.array(self._benchmark_daily_returns) + 1).prod()
|
|
171
|
-
})
|
|
172
205
|
self._daily_pnl.append(portfolio.daily_pnl)
|
|
173
206
|
|
|
174
207
|
for account_type, account in self._env.portfolio.accounts.items():
|
{rqalpha-5.3.8 → rqalpha-5.3.10}/rqalpha/mod/rqalpha_mod_sys_analyser/report/excel_template.py
RENAMED
|
@@ -70,9 +70,10 @@ class VerticalSeriesSchema(SheetSchema):
|
|
|
70
70
|
if not data:
|
|
71
71
|
for key, (row, column, style) in self._cell_map.items():
|
|
72
72
|
self._write_cell(ws, row, column, None, style)
|
|
73
|
-
|
|
74
|
-
for
|
|
75
|
-
|
|
73
|
+
else:
|
|
74
|
+
for key, (row, column, style) in self._cell_map.items():
|
|
75
|
+
for i, item in enumerate(data.get(key, [])):
|
|
76
|
+
self._write_cell(ws, row + i, column, item, style)
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
class SummaryTemplate(ExcelTemplate):
|
|
@@ -83,6 +84,7 @@ class SummaryTemplate(ExcelTemplate):
|
|
|
83
84
|
"月度收益": VerticalSeriesSchema,
|
|
84
85
|
"月度超额收益(几何)": VerticalSeriesSchema,
|
|
85
86
|
"个股权重": VerticalSeriesSchema,
|
|
87
|
+
"压力测试": VerticalSeriesSchema,
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
|