参数优化

参数优化模块主要由3部分构成:

参数设置

  • 设置参数优化区间:如boll_window设置起始值为18,终止值为24,步进为2,这样就得到了[18, 20, 22, 24] 这4个待优化的参数了。

  • 设置优化目标字段:如夏普比率、盈亏比、总收益率等。

  • 随机生成参数对组合:使用迭代工具产生参数对组合,然后把参数对组合打包到一个个字典组成的列表中

  1. class OptimizationSetting:
  2. """
  3. Setting for runnning optimization.
  4. """
  5.  
  6. def __init__(self):
  7. """"""
  8. self.params = {}
  9. self.target_name = ""
  10.  
  11. def add_parameter(
  12. self, name: str, start: float, end: float = None, step: float = None
  13. ):
  14. """"""
  15. if not end and not step:
  16. self.params[name] = [start]
  17. return
  18.  
  19. if start >= end:
  20. print("参数优化起始点必须小于终止点")
  21. return
  22.  
  23. if step <= 0:
  24. print("参数优化步进必须大于0")
  25. return
  26.  
  27. value = start
  28. value_list = []
  29.  
  30. while value <= end:
  31. value_list.append(value)
  32. value += step
  33.  
  34. self.params[name] = value_list
  35.  
  36. def set_target(self, target_name: str):
  37. """"""
  38. self.target_name = target_name
  39.  
  40. def generate_setting(self):
  41. """"""
  42. keys = self.params.keys()
  43. values = self.params.values()
  44. products = list(product(*values))
  45.  
  46. settings = []
  47. for p in products:
  48. setting = dict(zip(keys, p))
  49. settings.append(setting)
  50.  
  51. return settings

参数对组合回测

多进程优化时,每个进程都会运行optimize函数,输出参数对组合以及目标优化字段的结果。其步骤如下:

  • 调用回测引擎

  • 输入回测相关设置

  • 输入参数对组合到策略中

  • 运行回测

  • 返回回测结果,包括:参数对组合、目标优化字段数值、策略统计指标

  1. def optimize(
  2. target_name: str,
  3. strategy_class: CtaTemplate,
  4. setting: dict,
  5. vt_symbol: str,
  6. interval: Interval,
  7. start: datetime,
  8. rate: float,
  9. slippage: float,
  10. size: float,
  11. pricetick: float,
  12. capital: int,
  13. end: datetime,
  14. mode: BacktestingMode,
  15. ):
  16. """
  17. Function for running in multiprocessing.pool
  18. """
  19. engine = BacktestingEngine()
  20. engine.set_parameters(
  21. vt_symbol=vt_symbol,
  22. interval=interval,
  23. start=start,
  24. rate=rate,
  25. slippage=slippage,
  26. size=size,
  27. pricetick=pricetick,
  28. capital=capital,
  29. end=end,
  30. mode=mode
  31. )
  32.  
  33. engine.add_strategy(strategy_class, setting)
  34. engine.load_data()
  35. engine.run_backtesting()
  36. engine.calculate_result()
  37. statistics = engine.calculate_statistics()
  38.  
  39. target_value = statistics[target_name]
  40. return (str(setting), target_value, statistics)

多进程优化

  • 根据CPU的核数来创建进程:若CPU为4核,则创建4个进程

  • 在每个进程都调用apply_async( )的方法运行参数对组合回测,其回测结果添加到results中 (apply_async是异步非阻塞的,即不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。)

  • pool.close()与pool.join()用于进程跑完任务后,去关闭进程。

  • 对results的内容通过目标优化字段标准进行排序,输出结果。

  1. pool = multiprocessing.Pool(multiprocessing.cpu_count())
  2.  
  3. results = []
  4. for setting in settings:
  5. result = (pool.apply_async(optimize, (
  6. target_name,
  7. self.strategy_class,
  8. setting,
  9. self.vt_symbol,
  10. self.interval,
  11. self.start,
  12. self.rate,
  13. self.slippage,
  14. self.size,
  15. self.pricetick,
  16. self.capital,
  17. self.end,
  18. self.mode
  19. )))
  20. results.append(result)
  21.  
  22. pool.close()
  23. pool.join()
  24.  
  25. # Sort results and output
  26. result_values = [result.get() for result in results]
  27. result_values.sort(reverse=True, key=lambda result: result[1])
  28.  
  29. for value in result_values:
  30. msg = f"参数:{value[0]}, 目标:{value[1]}"
  31. self.output(msg)
  32.  
  33. return result_values