Profiles
yaml
version: 0.1.1
# 白名单,设置可以直接在策略代码中指定哪些模块的配置项目
whitelist: [base, extra, validator, mod]
base:
# 可以指定回测的唯一ID,用户区分多次回测的结果
run_id: 9999
# 数据源所存储的文件路径
data_bundle_path: data/bundle/
# 启动的策略文件路径
strategy_file: strategies/macd.py
# 回测起始日期
start_date: 2005-06-01
# 回测结束日期(如果是实盘,则忽略该配置)
end_date: 2050-01-01
# 股票起始资金,默认为0
stock_starting_cash: 1000000
# 期货起始资金,默认为0
future_starting_cash: 1000000
# 设置策略类型,目前支持 `stock` (股票策略)、`future` (期货策略)及 `stock_future` (混合策略)
strategy_type: stock
# 运行类型,`b` 为回测,`p` 为模拟交易, `r` 为实盘交易。
run_type: b
# 目前支持 `1d` (日线回测) 和 `1m` (分钟线回测),如果要进行分钟线,请注意是否拥有对应的数据源,目前开源版本是不提供对应的数据源的。
frequency: 1d
# 启用的回测引擎,目前支持 `current_bar` (当前Bar收盘价撮合) 和 `next_bar` (下一个Bar开盘价撮合)
matching_type: next_bar
# Benchmark,如果不设置,默认没有基准参照。
benchmark: ~
# 设置滑点
slippage: 0
# 设置手续费乘数,默认为1
commission_multiplier: 1
# 设置保证金乘数,默认为1
margin_multiplier: 1
# 在模拟交易和实盘交易中,RQAlpha支持策略的pause && resume,该选项表示开启 resume 功能
resume_mode: false
# 在模拟交易和实盘交易中,RQAlpha支持策略的pause && resume,该选项表示开启 persist 功能呢,
# 其会在每个bar结束对进行策略的持仓、账户信息,用户的代码上线文等内容进行持久化
persist: false
persist_mode: real_time
# 选择是否开启自动处理, 默认不开启
handle_split: false
account_list: [2]
securities: 0
extra:
# 选择日期的输出等级,有 `verbose` | `info` | `warning` | `error` 等选项,您可以通过设置 `verbose` 来查看最详细的日志,
# 或者设置 `error` 只查看错误级别的日志输出
log_level: info
user_system_log_disabled: false
# 在回测结束后,选择是否查看图形化的收益曲线
context_vars: ~
# force_run_init_when_pt_resume: 在PT的resume模式时,是否强制执行用户init。主要用于用户改代码。
force_run_init_when_pt_resume: false
# enable_profiler: 是否启动性能分析
enable_profiler: false
is_hold: false
locale: zh_Hans_CN
validator:
# cash_return_by_stock_delisted: 开启该项,当持仓股票退市时,按照退市价格返还现金
cash_return_by_stock_delisted: false
# close_amount: 在执行order_value操作时,进行实际下单数量的校验和scale,默认开启
close_amount: true
# bar_limit: 在处于涨跌停时,无法买进/卖出,默认开启
bar_limit: true
mod:
# 回测 / 模拟交易 支持 Mod
simulation:
lib: 'mod.simulation'
enabled: true
priority: 100
# 技术分析API
funcat_api:
lib: 'mod.funcat'
enabled: false
priority: 200
# 开启该选项,可以在命令行查看回测进度
progress:
lib: 'mod.progress'
enabled: false
priority: 400
# 接收实时行情运行
simple_stock_realtime_trade:
lib: 'mod.realtime'
persist_path: "./persist/strategy/"
fps: 3
enabled: false
priority: 500
# 渐进式输出运行结果
progressive_output_csv:
lib: 'mod.progressive_output_csv'
enabled: false
output_path: "./"
priority: 600
risk_manager:
lib: 'mod.risk_manager'
enabled: true
priority: 700
# available_cash: 查可用资金是否充足,默认开启
available_cash: true
# available_position: 检查可平仓位是否充足,默认开启
available_position: true
analyser:
priority: 100
enabled: true
lib: 'mod.analyser'
record: true
output_file: data/result/output_file
plot: data/result/plot
plot_save_file: data/result/plot_save_file
report_save_path: data/result/
json
No demo here.
Load configuration
import os
import codecs
import json
import pprint
import yaml
from utils.i18n import gettext
def load_config(config_path, loader=yaml.Loader):
"""
在项目启动时去加载配置
:param config_path: 配置路径
:param loader: 配置加载器
:return:
"""
if config_path is None:
return dict()
if not os.path.exists(config_path): # 判断路径是否真实存在
raise RuntimeError(gettext(u"config.yml not found in {config_path}").format(config_path))
if ".json" in config_path: # 如果是 .json 格式的配置
# codecs 模块是专门用来做编码转换的
with codecs.open(config_path, encoding="utf-8") as f:
json_config = f.read()
config = json.loads(json_config)
else:
with codecs.open(config_path, encoding="utf-8") as stream:
config = yaml.load(stream, loader)
return config
if __name__ == '__main__':
config = load_config(config_path='config.yml')
print(pprint.pformat(config))
Convert an object dictionary
The conversion dictionary object, you can use Call
class RqAttrDict(object):
"""
将字典类型转换为对象 这样就可以用 . 来操作 字典的键值
"""
def __init__(self, d=None):
# 一个对象的 __dict__ 魔法方法包含了其全部属性值
self.__dict__ = d if d is not None else dict()
# 迭代字典中的嵌套字典 仍然赋值为嵌套字典对象的格式
# 因为在 py2 里面 dict.items() 返回的是数组 six.iteritems() 返回的是生成器
# 但是在 py3 里面 dict.items() 也是返回生成器
for k, v in list(six.iteritems(self.__dict__)):
if isinstance(v, dict):
self.__dict__[k] = RqAttrDict(v)
def __repr__(self):
# __str__ 会覆盖 __repr__
return pprint.pformat(self.__dict__)
def __iter__(self):
# 返回迭代器本身或者是其他可迭代的对象的实例 实现了委托迭代
# 然后去调用该对象的 __next__ 方法
return self.__dict__.__iter__()
def update(self, other):
# 递归更新字典
RqAttrDict._update_dict_recursive(self, other)
def items(self):
# 返回生成器对象
return six.iteritems(self.__dict__)
iteritems = items
@staticmethod
def _update_dict_recursive(target, other):
# 使用 other 去更新 target
if isinstance(other, RqAttrDict):
other = other.__dict__
if isinstance(target, RqAttrDict):
target = target.__dict__
for k, v in six.iteritems(other):
if isinstance(v, collections.Mapping): # 如果他的值仍然是个字典 为甚不用 dict 二是用 collections.Mapping
r = RqAttrDict._update_dict_recursive(target.get(k, {}), v)
target[k] = r
else:
target[k] = other[k]
return target
def convert_to_dict(self):
# 将对象转换为 字典
result_dict = dict()
for k, v in list(six.iteritems(self.__dict__)):
if isinstance(v, RqAttrDict):
v = v.convert_to_dict()
result_dict[k] = v
return result_dict
This completes the configuration work before the start.
The relevant code: