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.
Files changed (209) hide show
  1. {rqalpha-5.3.7/rqalpha.egg-info → rqalpha-5.3.9}/PKG-INFO +1 -1
  2. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/_version.py +3 -3
  3. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/api_base.py +2 -5
  4. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/data_source.py +6 -1
  5. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/storages.py +1 -1
  6. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/bundle.py +101 -2
  7. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/data_proxy.py +5 -2
  8. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/trading_dates_mixin.py +9 -0
  9. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/environment.py +34 -10
  10. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/interface.py +26 -7
  11. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/main.py +3 -2
  12. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/api/api_future.py +13 -15
  13. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/api/api_stock.py +20 -25
  14. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/component_validator.py +9 -15
  15. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/position_model.py +6 -0
  16. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/position_validator.py +13 -14
  17. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/validator.py +7 -11
  18. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/mod.py +53 -20
  19. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/report/excel_template.py +5 -3
  20. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/report/report.py +51 -8
  21. rqalpha-5.3.9/rqalpha/mod/rqalpha_mod_sys_analyser/report/templates/summary.xlsx +0 -0
  22. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/cash_validator.py +18 -19
  23. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/is_trading_validator.py +15 -13
  24. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/price_validator.py +12 -13
  25. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/self_trade_validator.py +11 -12
  26. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/matcher.py +1 -1
  27. rqalpha-5.3.9/rqalpha/mod/rqalpha_mod_sys_simulation/validator.py +20 -0
  28. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/portfolio/account.py +0 -1
  29. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/testing/fixtures.py +1 -1
  30. rqalpha-5.3.9/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.mo +0 -0
  31. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.po +55 -53
  32. {rqalpha-5.3.7 → rqalpha-5.3.9/rqalpha.egg-info}/PKG-INFO +1 -1
  33. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/SOURCES.txt +4 -0
  34. {rqalpha-5.3.7 → rqalpha-5.3.9}/setup.cfg +1 -1
  35. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_simulation_broker.py +3 -0
  36. rqalpha-5.3.9/tests/test_f_delivery.py +42 -0
  37. rqalpha-5.3.9/tests/test_f_tick_size.py +67 -0
  38. rqalpha-5.3.9/tests/unittest/test_data/test_auto_update_bundle/__init__.py +7 -0
  39. rqalpha-5.3.9/tests/unittest/test_data/test_auto_update_bundle/test_auto_update_bundle_mixin.py +75 -0
  40. rqalpha-5.3.7/rqalpha/mod/rqalpha_mod_sys_analyser/report/templates/summary.xlsx +0 -0
  41. rqalpha-5.3.7/rqalpha/mod/rqalpha_mod_sys_simulation/validator.py +0 -18
  42. rqalpha-5.3.7/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/messages.mo +0 -0
  43. {rqalpha-5.3.7 → rqalpha-5.3.9}/CHANGELOG.rst +0 -0
  44. {rqalpha-5.3.7 → rqalpha-5.3.9}/LICENSE +0 -0
  45. {rqalpha-5.3.7 → rqalpha-5.3.9}/MANIFEST.in +0 -0
  46. {rqalpha-5.3.7 → rqalpha-5.3.9}/README.rst +0 -0
  47. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/__init__.py +0 -0
  48. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/__main__.py +0 -0
  49. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/api.py +0 -0
  50. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/__init__.py +0 -0
  51. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/api_abstract.py +0 -0
  52. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/api_rqdatac.py +0 -0
  53. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/apis/names.py +0 -0
  54. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/__init__.py +0 -0
  55. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/bundle.py +0 -0
  56. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/entry.py +0 -0
  57. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/misc.py +0 -0
  58. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/mod.py +0 -0
  59. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/cmds/run.py +0 -0
  60. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/config.yml +0 -0
  61. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/const.py +0 -0
  62. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/__init__.py +0 -0
  63. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/events.py +0 -0
  64. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/execution_context.py +0 -0
  65. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/executor.py +0 -0
  66. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/global_var.py +0 -0
  67. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy.py +0 -0
  68. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy_context.py +0 -0
  69. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy_loader.py +0 -0
  70. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/core/strategy_universe.py +0 -0
  71. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/__init__.py +0 -0
  72. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/bar_dict_price_board.py +0 -0
  73. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/__init__.py +0 -0
  74. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/adjust.py +0 -0
  75. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/data/base_data_source/storage_interface.py +0 -0
  76. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/IF1706_20161108.csv +0 -0
  77. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/IF_macd.py +0 -0
  78. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/buy_and_hold.py +0 -0
  79. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/data_source/get_csv_module.py +0 -0
  80. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/data_source/import_get_csv_module.py +0 -0
  81. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/data_source/read_csv_as_df.py +0 -0
  82. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/extend_api/rqalpha_mod_extend_api_demo.py +0 -0
  83. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/extend_api/test_extend_api.py +0 -0
  84. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/golden_cross.py +0 -0
  85. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/macd.py +0 -0
  86. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/pair_trading.py +0 -0
  87. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/rsi.py +0 -0
  88. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/run_code_demo.py +0 -0
  89. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/run_file_demo.py +0 -0
  90. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/run_func_demo.py +0 -0
  91. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/subscribe_event.py +0 -0
  92. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/test_pt.py +0 -0
  93. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/examples/turtle.py +0 -0
  94. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/__init__.py +0 -0
  95. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/__init__.py +0 -0
  96. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/api/__init__.py +0 -0
  97. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_accounts/mod.py +0 -0
  98. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/__init__.py +0 -0
  99. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/__init__.py +0 -0
  100. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/consts.py +0 -0
  101. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/plot.py +0 -0
  102. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot/utils.py +0 -0
  103. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/plot_store.py +0 -0
  104. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_analyser/report/__init__.py +0 -0
  105. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_progress/__init__.py +0 -0
  106. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_progress/mod.py +0 -0
  107. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/__init__.py +0 -0
  108. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/mod.py +0 -0
  109. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_risk/validators/__init__.py +0 -0
  110. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_scheduler/__init__.py +0 -0
  111. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_scheduler/mod.py +0 -0
  112. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_scheduler/scheduler.py +0 -0
  113. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/__init__.py +0 -0
  114. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/mod.py +0 -0
  115. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/signal_broker.py +0 -0
  116. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/simulation_broker.py +0 -0
  117. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/simulation_event_source.py +0 -0
  118. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/slippage.py +0 -0
  119. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_simulation/testing.py +0 -0
  120. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/__init__.py +0 -0
  121. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/deciders.py +0 -0
  122. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/rqalpha_mod_sys_transaction_cost/mod.py +0 -0
  123. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod/utils.py +0 -0
  124. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/mod_config.yml +0 -0
  125. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/__init__.py +0 -0
  126. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/bar.py +0 -0
  127. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/instrument.py +0 -0
  128. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/order.py +0 -0
  129. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/tick.py +0 -0
  130. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/model/trade.py +0 -0
  131. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/portfolio/__init__.py +0 -0
  132. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/portfolio/position.py +0 -0
  133. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/resource/ricequant-logo.png +0 -0
  134. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/user_module.py +0 -0
  135. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/__init__.py +0 -0
  136. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/arg_checker.py +0 -0
  137. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/class_helper.py +0 -0
  138. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/click_helper.py +0 -0
  139. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/concurrent.py +0 -0
  140. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/config.py +0 -0
  141. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/datetime_func.py +0 -0
  142. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/dict_func.py +0 -0
  143. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/exception.py +0 -0
  144. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/functools.py +0 -0
  145. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/i18n.py +0 -0
  146. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/log_capture.py +0 -0
  147. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/logger.py +0 -0
  148. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/package_helper.py +0 -0
  149. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/persisit_helper.py +0 -0
  150. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/repr.py +0 -0
  151. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/risk_free_helper.py +0 -0
  152. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/rq_json.py +0 -0
  153. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/strategy_loader_help.py +0 -0
  154. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/testing/__init__.py +0 -0
  155. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/testing/mocking.py +0 -0
  156. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/__init__.py +0 -0
  157. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/zh_Hans_CN/LC_MESSAGES/__init__.py +0 -0
  158. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/translations/zh_Hans_CN/__init__.py +0 -0
  159. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha/utils/typing.py +0 -0
  160. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/dependency_links.txt +0 -0
  161. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/entry_points.txt +0 -0
  162. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/not-zip-safe +0 -0
  163. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/requires.txt +0 -0
  164. {rqalpha-5.3.7 → rqalpha-5.3.9}/rqalpha.egg-info/top_level.txt +0 -0
  165. {rqalpha-5.3.7 → rqalpha-5.3.9}/setup.py +0 -0
  166. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/__init__.py +0 -0
  167. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/__init__.py +0 -0
  168. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/__init__.py +0 -0
  169. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/__init__.py +0 -0
  170. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_account_model.py +0 -0
  171. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_futures_settlement_price_type.py +0 -0
  172. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_margin_stocks.py +0 -0
  173. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_accounts/test_position_models.py +0 -0
  174. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_scheduler/__init__.py +0 -0
  175. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_scheduler/test_physical_time.py +0 -0
  176. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_scheduler/test_scheduler.py +0 -0
  177. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/__init__.py +0 -0
  178. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_management_fee.py +0 -0
  179. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_match.py +0 -0
  180. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_signal_broker.py +0 -0
  181. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_simulation/test_simulation_event_source.py +0 -0
  182. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_transaction_cost/__init__.py +0 -0
  183. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/mod/sys_transaction_cost/test_commission_multiplier.py +0 -0
  184. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_api_base.py +0 -0
  185. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_api_future.py +0 -0
  186. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_api_stock.py +0 -0
  187. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/test_config.py +0 -0
  188. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/api_tests/utils.py +0 -0
  189. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_buy_and_hold.py +0 -0
  190. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_macd.py +0 -0
  191. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_macd_signal.py +0 -0
  192. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_f_mean_reverting.py +0 -0
  193. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_buy_and_hold.py +0 -0
  194. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_dual_thrust.py +0 -0
  195. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_pit_tax.py +0 -0
  196. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_scheduler.py +0 -0
  197. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_tick_size.py +0 -0
  198. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_turtle.py +0 -0
  199. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_s_turtle_signal.py +0 -0
  200. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/test_sf_buy_and_hold.py +0 -0
  201. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/__init__.py +0 -0
  202. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_data/__init__.py +0 -0
  203. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_data/test_instrument_mixin.py +0 -0
  204. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_data/test_trading_dates_mixin.py +0 -0
  205. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_mod/__init__.py +0 -0
  206. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_mod/test_sys_simulation/__init__.py +0 -0
  207. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/unittest/test_mod/test_sys_simulation/test_simulation_event_source.py +0 -0
  208. {rqalpha-5.3.7 → rqalpha-5.3.9}/tests/utils.py +0 -0
  209. {rqalpha-5.3.7 → rqalpha-5.3.9}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rqalpha
3
- Version: 5.3.7
3
+ Version: 5.3.9
4
4
  Summary: Ricequant Algorithm Trading System
5
5
  Home-page: https://github.com/ricequant/rqalpha
6
6
  Author: ricequant
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-03-07T13:57:10+0800",
11
+ "date": "2024-04-12T18:06:46+0800",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "598bbf4021485f71cb75b6871997232d926b3a15",
15
- "version": "5.3.7"
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
- user_system_log.warn(
174
- _(u"Order Creation Failed: [{order_book_id}] No market data").format(
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._custom_data.get(underlying_symbol)
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, user_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
- instrument_type = self.data_proxy.instrument(order.order_book_id).type
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
- if not v.can_cancel_order(order, account):
127
- return False
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
- if not v.can_submit_order(order, account):
187
- return False
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 can_submit_order(self, order, account=None):
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 can_cancel_order(self, order, account=None):
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
- user_system_log.warn(_(
51
- u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}"
52
- ).format(order_book_id=order_book_id))
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
- user_system_log.warn(
66
- _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
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
- user_system_log.warning(_(
76
+ reason = _(
79
77
  "Order Creation Failed: "
80
- "close today amount {amount} is larger than today closable quantity {quantity}"
81
- ).format(amount=amount, quantity=position.today_closable))
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
- user_system_log.warn(_(
90
- u"Order Creation Failed: close amount {amount} is larger than position quantity {quantity}").format(
91
- amount=amount, quantity=quantity
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
- user_system_log.warn(
104
- _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=ins.order_book_id))
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
- user_system_log.warn(_(
113
- u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}"
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 not is_cash_enough(env, order, account.cash):
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
- user_system_log.warn(
142
- _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=ins.order_book_id)
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
- user_system_log.warn(_(
159
- u"Order Creation Failed: 0 order quantity, order_book_id={order_book_id}"
160
- ).format(order_book_id=ins.order_book_id))
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
- user_system_log.warn(
346
- _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
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
- user_system_log.warn(_(
384
- "Adjust position of {id_or_ins} Failed: "
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 can_cancel_order(self, order, account=None):
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 True
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 True
24
+ return None
32
25
  else:
33
- user_system_log.warn("Order Creation Failed: margin stock pool not contains {}.".format(
34
- order.order_book_id)
35
- )
36
- return False
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