增加自有数据源

策略中直接读取自有数据

RQAlpha 不限制本地运行的策略调使用哪些库,因此您可以直接在策略中读取文件、访问数据库等,但需要关注如下两个注意事项:

  • 请在 init, before_trading, handle_bar, handle_tick, after_trading 等函数中读取自有数据,而不要在函数外执行数据获取的代码,否则可能会产生异常。
  • RQAlpha 是读取策略代码并执行的,因此实际当前路径是运行 rqalpha 命令的路径,策略使用相对路径容易产生异常。如果您需要根据策略路径来定位相对路径可以通过 context.config.base.strategy_file 来获取策略路径,从而获取相对策略文件的其他路径,具体使用方式请看下面的示例代码。read_csv_as_df
  1. from rqalpha.api import *
  2.  
  3.  
  4. def read_csv_as_df(csv_path):
  5. # 通过 pandas 读取 csv 文件,并生成 DataFrame
  6. import pandas as pd
  7. data = pd.read_csv(csv_path)
  8. return data
  9.  
  10.  
  11. def init(context):
  12. import os
  13. # 获取当前运行策略的文件路径
  14. strategy_file_path = context.config.base.strategy_file
  15. # 根据当前策略的文件路径寻找到相对路径为 "../IF1706_20161108.csv" 的 csv 文件
  16. csv_path = os.path.join(os.path.dirname(strategy_file_path), "../IF1706_20161108.csv")
  17. # 读取 csv 文件并生成 df
  18. IF1706_df = read_csv_as_df(csv_path)
  19. # 传入 context 中
  20. context.IF1706_df = IF1706_df
  21.  
  22.  
  23. def before_trading(context):
  24. # 通过context 获取在 init 阶段读取的 csv 文件数据
  25. logger.info(context.IF1706_df)
  26.  
  27.  
  28. def handle_bar(context, bar):
  29. pass
  30.  
  31.  
  32. __config__ = {
  33. "base": {
  34. "start_date": "2015-01-09",
  35. "end_date": "2015-01-10",
  36. "frequency": "1d",
  37. "matching_type": "current_bar",
  38. "benchmark": None,
  39. "accounts": {
  40. "future": 1000000
  41. }
  42. },
  43. "extra": {
  44. "log_level": "verbose",
  45. },
  46. }

在策略中 import 自定义模块

如果您定义了自定义模块,希望在策略中引用,只需要在初始化的时候将模块对应的路径添加到 sys.path 即可,但需要关注如下两个注意事项:

  • 如果没有特殊原因,请在 init 阶段添加 sys.path 路径。
  • 如果您的自定义模块是基于策略策略的相对路径,则需要在 init 函数中通过 context.config.base.strategy_file 获取到策略路径,然后再添加到 sys.path 中。
  • RQAlpha 是读取策略代码并执行的,因此实际当前路径是执行 rqalpha 命令的路径,避免使用相对路径。get_csv_module
  1. import os
  2.  
  3.  
  4. def read_csv_as_df(csv_path):
  5. import pandas as pd
  6. data = pd.read_csv(csv_path)
  7. return data
  8.  
  9.  
  10. def get_csv():
  11. csv_path = os.path.join(os.path.dirname(__file__), "../IF1706_20161108.csv")
  12. return read_csv_as_df(csv_path)

import_get_csv_module

  1. from rqalpha.api import *
  2.  
  3.  
  4. def init(context):
  5. import os
  6. import sys
  7. strategy_file_path = context.config.base.strategy_file
  8. sys.path.append(os.path.realpath(os.path.dirname(strategy_file_path)))
  9.  
  10. from get_csv_module import get_csv
  11.  
  12. IF1706_df = get_csv()
  13. context.IF1706_df = IF1706_df
  14.  
  15.  
  16. def before_trading(context):
  17. logger.info(context.IF1706_df)
  18.  
  19.  
  20. __config__ = {
  21. "base": {
  22. "start_date": "2015-01-09",
  23. "end_date": "2015-01-10",
  24. "frequency": "1d",
  25. "matching_type": "current_bar",
  26. "benchmark": None,
  27. "accounts": {
  28. "future": 1000000
  29. }
  30. },
  31. "extra": {
  32. "log_level": "verbose",
  33. },
  34. }

扩展 API 实现自有数据的读取

我们通过创建一个 Mod 来实现扩展 API,启动策略时,只需要开启该 Mod, 对应的扩展 API 便可以生效,在策略中直接使用。

rqalpha_mod_extend_api_demo

  1. import os
  2. import pandas as pd
  3. from rqalpha.interface import AbstractMod
  4.  
  5.  
  6. __config__ = {
  7. "csv_path": None
  8. }
  9.  
  10.  
  11. def load_mod():
  12. return ExtendAPIDemoMod()
  13.  
  14.  
  15. class ExtendAPIDemoMod(AbstractMod):
  16. def __init__(self):
  17. # 注入API 一定要在初始化阶段,否则无法成功注入
  18. self._csv_path = None
  19. self._inject_api()
  20.  
  21. def start_up(self, env, mod_config):
  22. self._csv_path = os.path.abspath(os.path.join(os.path.dirname(__file__), mod_config.csv_path))
  23.  
  24. def tear_down(self, code, exception=None):
  25. pass
  26.  
  27. def _inject_api(self):
  28. from rqalpha import export_as_api
  29. from rqalpha.execution_context import ExecutionContext
  30. from rqalpha.const import EXECUTION_PHASE
  31.  
  32. @export_as_api
  33. @ExecutionContext.enforce_phase(EXECUTION_PHASE.ON_INIT,
  34. EXECUTION_PHASE.BEFORE_TRADING,
  35. EXECUTION_PHASE.ON_BAR,
  36. EXECUTION_PHASE.AFTER_TRADING,
  37. EXECUTION_PHASE.SCHEDULED)
  38. def get_csv_as_df():
  39. data = pd.read_csv(self._csv_path)
  40. return data

如上代码,我们定义了 rqalpha_mod_extend_api_demo Mod,该 Mod 接受一个参数: csv_path, 其会转换为基于 Mod 的相对路径来获取对应的 csv 地址。

在该Mod中通过 _inject_api 方法,定义了 get_csv_ad_df 函数,并通过 from rqalpha import export_as_api 装饰器完成了 API 的注入。

如果想限制扩展API所运行使用的范围,可以通过 ExecutionContext.enforce_phase 来控制.

接下来我们看一下如何在策略中使用该扩展API:

test_extend_api

  1. from rqalpha.api import *
  2.  
  3.  
  4. def init(context):
  5. IF1706_df = get_csv_as_df()
  6. context.IF1706_df = IF1706_df
  7.  
  8.  
  9. def before_trading(context):
  10. logger.info(context.IF1706_df)
  11.  
  12.  
  13. __config__ = {
  14. "base": {
  15. "start_date": "2015-01-09",
  16. "end_date": "2015-01-10",
  17. "frequency": "1d",
  18. "matching_type": "current_bar",
  19. "benchmark": None,
  20. "accounts": {
  21. "future": 1000000
  22. }
  23. },
  24. "extra": {
  25. "log_level": "verbose",
  26. },
  27. "mod": {
  28. "extend_api_demo": {
  29. "enabled": True,
  30. "lib": "rqalpha.examples.extend_api.rqalpha_mod_extend_api_demo",
  31. "csv_path": "../IF1706_20161108.csv"
  32. }
  33. }
  34. }

如上述代码,首先配置信息中添加 extend_api_demo 对应的配置

  • enabled: True 表示开启该 Mod
  • lib: 指定该 Mod 对应的加载位置(rqlalpha 会自动去寻找 rqalpha_mod_xxx 对应的库,如果该库已经通过 pip install 安装,则无需显式指定 lib)
  • csvpath: 指定 csv 所在位置至此,我们就可以直接在策略中使用 _get_csv_as_df 函数了。