基于backtrader的唐奇安结合ADX策略实现(自动多参数调优和回测)

##导入相关包 优化jupyter画图设置
from datetime import datetime,timedelta
import backtrader as bt
import tushare as ts
import pandas as pd
import talib as ta
import numpy as np
import matplotlib.pyplot as plt
import mplfinance as mpf
import pyfolio as pf
import optunity
import optunity.metrics
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.rcParams['figure.figsize']=[10, 8]
plt.rcParams['figure.dpi']=200
plt.rcParams['figure.facecolor']='w'
plt.rcParams['figure.edgecolor']='k'
# K线数据获取
#数字货币回测
# 从Binance币安在线api下载k线,进行回测
import requests
import json
import pandas as pd
import datetime as dt
def get_binance_bars(symbol, interval, startTime, endTime):url = "https://api.binance.com/api/v3/klines"startTime = str(int(startTime.timestamp() * 1000))endTime = str(int(endTime.timestamp() * 1000))limit = '50'req_params = {"symbol" : symbol, 'interval' : interval, 'startTime' : startTime, 'endTime' : endTime, 'limit' : limit}df = pd.DataFrame(json.loads(requests.get(url, params = req_params).text))if (len(df.index) == 0):return Nonedf = df.iloc[:, 0:6]df.columns = ['datetime', 'open', 'high', 'low', 'close', 'volume']df.open = df.open.astype("float")df.high = df.high.astype("float")df.low = df.low.astype("float")df.close = df.close.astype("float")df.volume = df.volume.astype("float")df.index = [dt.datetime.fromtimestamp(x / 1000.0) for x in df.datetime]return df
df_list = []
# 数据起点时间
last_datetime = dt.datetime(2022,1,1)
while True:new_df = get_binance_bars('ETHUSDT', '4h', last_datetime, dt.datetime(2022,7,10)) # 获取k线数据if new_df is None:breakdf_list.append(new_df)last_datetime = max(new_df.index) + dt.timedelta(0, 5)dataframe=pd.concat(df_list)
dataframe['openinterest']=0
dataframe=dataframe[['open','high','low','close','volume','openinterest']]
print(dataframe.shape)
print(dataframe.tail())
dataframe.head()
(1099, 6)open     high      low    close       volume  \
2022-07-09 08:00:00  1214.03  1221.79  1204.67  1217.01  147773.1735
2022-07-09 12:00:00  1217.01  1227.40  1210.69  1225.02   79680.3095
2022-07-09 16:00:00  1225.01  1228.25  1205.27  1210.28   80972.9123
2022-07-09 20:00:00  1210.28  1222.61  1206.52  1215.24   83406.7132
2022-07-10 00:00:00  1215.23  1235.40  1209.33  1218.61   89320.9760   openinterest
2022-07-09 08:00:00             0
2022-07-09 12:00:00             0
2022-07-09 16:00:00             0
2022-07-09 20:00:00             0
2022-07-10 00:00:00             0
open high low close volume openinterest
2022-01-01 00:00:00 3784.64 3788.45 3623.00 3626.27 54604.9027 0
2022-01-01 04:00:00 3626.21 3712.50 3622.29 3676.23 39496.5993 0
2022-01-01 08:00:00 3676.22 3748.45 3676.22 3723.96 26592.7693 0
2022-01-01 12:00:00 3723.96 3765.27 3701.00 3715.31 27251.1401 0
2022-01-01 16:00:00 3715.32 3733.84 3673.46 3693.37 23727.9949 0
#编写海龟策略
class D_ADX_TradingStrategy(bt.Strategy):params = dict(N1= 40, # 唐奇安通道上轨的tN2=30, # 唐奇安通道下轨的tN3=30,# ADX的强度值N4=20, # ADX的时间周期参数printlog=False, )def log(self, txt, dt=None,doprint=False):if self.params.printlog or doprint:dt = dt or self.datas[0].datetime.date(0)print(f'{dt.isoformat()},{txt}')def __init__(self): self.order = None                   self.buy_count = 0 # 记录买入次数self.last_price = 0 # 记录买入价格self.close = self.datas[0].closeself.high = self.datas[0].highself.low = self.datas[0].low# 计算唐奇安通道上轨:过去20日的最高价self.DonchianH = bt.ind.Highest(self.high(-1), period=int(self.p.N1), subplot=True)# 计算唐奇安通道下轨:过去10日的最低价self.DonchianL = bt.ind.Lowest(self.low(-1), period=int(self.p.N2), subplot=True)# 计算唐奇安通道中轨self.DonchianM= (self.DonchianH+self.DonchianL)/2# 生成唐奇安通道上轨突破:close>DonchianH,取值为1.0;反之为 -1.0self.CrossoverH = bt.ind.CrossOver(self.close(0), self.DonchianH, subplot=False)# 生成唐奇安通道下轨突破:self.CrossoverL = bt.ind.CrossOver(self.close(0), self.DonchianL, subplot=False)# 生成唐奇安通道中轨突破:self.CrossoverM = bt.ind.CrossOver(self.close(0), self.DonchianM, subplot=False)# 计算 ADX,直接调用 talib self.ADX = bt.talib.ADX(self.high, self.low, self.close,timeperiod=int(self.p.N4),subplot=True)
#         self.log(self.ADX[-1],doprint=True)def next(self):
#         self.log(self.ADX[0],doprint=True)# 如果还有订单在执行中,就不做新的仓位调整if self.order:return  # 如果当前持有多单if self.position.size > 0 :# 平仓设置if self.CrossoverM<0 or self.ADX[0]<self.ADX[-1]:self.order = self.sell(size=abs(self.position.size))self.buy_count = 0 # 如果当前持有空单elif self.position.size < 0 :# 平仓设置if self.CrossoverM>0 or self.ADX[0]<self.ADX[-1]:self.order = self.buy(size=abs(self.position.size))self.buy_count = 0 else: # 如果没有持仓,等待入场时机#入场: 价格突破上轨线且空仓时,做多if self.CrossoverH > 0 and self.buy_count == 0 and self.ADX[0]>self.ADX[-1] and self.ADX[-1]>int(self.p.N3):self.buy_unit = int(self.broker.getvalue()/self.close[0]/4)
#                 self.buy_unit=500self.order = self.buy(size=self.buy_unit)self.last_price = self.position.price # 记录买入价格self.buy_count = 1  # 记录本次交易价格#入场: 价格跌破下轨线且空仓时,做空elif self.CrossoverL < 0 and self.buy_count == 0 and self.ADX[0]>self.ADX[-1] and self.ADX[-1]>int(self.p.N3):self.buy_unit = int(self.broker.getvalue()/self.close[0]/4)self.buy_unit=500self.order = self.sell(size=self.buy_unit)self.last_price = self.position.price # 记录买入价格self.buy_count = 1  # 记录本次交易价格# 打印订单日志def notify_order(self, order):order_status = ['Created','Submitted','Accepted','Partial','Completed','Canceled','Expired','Margin','Rejected']# 未被处理的订单if order.status in [order.Submitted, order.Accepted]:self.log('ref:%.0f, name: %s, Order: %s'% (order.ref,order.data._name,order_status[order.status]))return# 已经处理的订单if order.status in [order.Partial, order.Completed]:if order.isbuy():self.log('BUY EXECUTED, status: %s, ref:%.0f, name: %s, Size: %.2f, Price: %.2f, Cost: %.2f, Comm %.2f' %(order_status[order.status], # 订单状态order.ref, # 订单编号order.data._name, # 股票名称order.executed.size, # 成交量order.executed.price, # 成交价order.executed.value, # 成交额order.executed.comm)) # 佣金else: # Sellself.log('SELL EXECUTED, status: %s, ref:%.0f, name: %s, Size: %.2f, Price: %.2f, Cost: %.2f, Comm %.2f' %(order_status[order.status],order.ref,order.data._name,order.executed.size,order.executed.price,order.executed.value,order.executed.comm))elif order.status in [order.Canceled, order.Margin, order.Rejected, order.Expired]:# 订单未完成self.log('ref:%.0f, name: %s, status: %s'% (order.ref, order.data._name, order_status[order.status]))self.order = Nonedef notify_trade(self, trade):# 交易刚打开时if trade.justopened:self.log('Trade Opened, name: %s, Size: %.2f,Price: %.2f' % (trade.getdataname(), trade.size, trade.price))# 交易结束elif trade.isclosed:self.log('Trade Closed, name: %s, GROSS %.2f, NET %.2f, Comm %.2f' %(trade.getdataname(), trade.pnl, trade.pnlcomm, trade.commission))# 更新交易状态else:self.log('Trade Updated, name: %s, Size: %.2f,Price: %.2f' % (trade.getdataname(), trade.size, trade.price))def stop(self):self.log(f'(组合线:{self.p.N1},{self.p.N2},{self.p.N3},{self.p.N4}); 期末总资金: {self.broker.getvalue():.2f}', doprint=False)
#编写回测主函数
def main(N1,N2,N3,N4,para_opt=True,startcash=100000,com=0.02):if para_opt==True:cerebro = bt.Cerebro()cerebro.addstrategy(D_ADX_TradingStrategy,N1=N1,N2=N2,N3=N3,N4=N4)data = bt.feeds.PandasData(dataname=dataframe)    cerebro.adddata(data)#broker设置资金、手续费cerebro.broker.setcash(startcash)cerebro.broker.setcommission(commission=com)cerebro.run(maxcpus=2)value = cerebro.broker.getvalue()return valueelse:cerebro = bt.Cerebro()cerebro.addstrategy(D_ADX_TradingStrategy,N1=N1,N2=N2,N3=N3,N4=N4)data = bt.feeds.PandasData(dataname=dataframe)    cerebro.adddata(data)#broker设置资金、手续费cerebro.broker.setcash(startcash)cerebro.broker.setcommission(commission=com)#设置指标观察cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')print('期初总资金: %.2f' % cerebro.broker.getvalue())results=cerebro.run(maxcpus=2)cerebro.plot(iplot=False)result = results[0]pyfolio = result.analyzers.pyfolio # 注意:后面不要调用 .get_analysis() 方法# 或者是 result[0].analyzers.getbyname('pyfolio')returns, positions, transactions, gross_lev = pyfolio.get_pf_items()pf.create_full_tear_sheet(returns)
'''backtrader内置的策略参数优化方法是权利搜索方法,也就是遍历每个参数组合值。在参数很多,每个参数取值变化范围大的情况下,优化效率是很低的。
可以采用智能优化算法,比如粒子群优化等进行大规模参数优化。下面,我们用python开源算法库optunity来对backtrader策略参数进行优化。 '''
# 执行优化,第一个参数是评估函数
'''
执行10次回测,设置两个参数sma1、sma2的取值范围
num_evals: 执行次数
Available solvers: particle swarm, tpe, sobol, nelder-mead, random search, cma-es, grid search
sma1、sma2 确定参数的取值范围
'''
opt = optunity.maximize(f=main,num_evals=100,solver_name='particle swarm',N1=[40,100], #上轨参数调优取值范围N2=[40,100], #下轨参数调优取值范围N3=[20,50], #ADX强度参数调优取值范围N4=[8,20] ##ADX时间周期参数调优取值范围)optimal_pars, details, _ = opt  # optimal_pars 最优参数组合
print(optimal_pars)
{'N1': 76.64719168590987, 'N2': 83.65052762407552, 'N3': 25.247355935345496, 'N4': 15.344248021285086}
#最优参数回测并画图
main(N1=optimal_pars['N1'],N2=optimal_pars['N2'],N3=optimal_pars['N3'],N4=optimal_pars['N4'],para_opt=False)
期初总资金: 100000.00

Start date 2022-01-01
End date 2022-07-10
Total months 9
Backtest
Annual return 276.335%
Cumulative returns 173.054%
Annual volatility 3386.631%
Sharpe ratio -0.12
Calmar ratio 2.35
Stability NaN
Max drawdown -117.486%
Omega ratio 0.90
Sortino ratio -0.15
Skew -3.82
Kurtosis 92.83
Tail ratio 0.60
Daily value at risk -428.304%
Worst drawdown periods Net drawdown in % Peak date Valley date Recovery date Duration
0 117.49 2022-01-22 2022-05-04 2022-06-13 101
1 25.22 2022-01-20 2022-01-21 2022-01-22 2
2 23.40 2022-06-15 2022-06-19 NaT NaN
3 3.43 2022-06-13 2022-06-14 2022-06-15 3
4 NaN NaT NaT NaT NaN

基于backtrader的唐奇安结合ADX策略实现(自动多参数调优和回测)相关推荐

  1. 基于backtrader的唐奇安通道策略实现

    基于backtrader的唐奇安通道策略实现 代码实现 ##导入相关包 优化jupyter画图设置 from datetime import datetime,timedelta import bac ...

  2. 用Python的Pandas和Matplotlib绘制股票唐奇安通道,布林带通道和鳄鱼组线

    根据指定股票通道指标的算法,能用过去一定时间段的交易数据绘制出上下两条通道线,即价格通道里的上下轨道.一般来说,当股价向上突破上轨时,即预测后市将涨,反之当股价向下突破下轨时,即预测后市将跌. 这里将 ...

  3. 用Python的Pandas绘制股票唐奇安通道!

    1  计算并绘制唐奇安通道 唐奇安通道是由上阻力线.下支撑线和中心线这三条线组成. 上阻力线 = 过去N天的最高价 下支撑线 = 过去N天的最低价 中心线 =(上线 + 下线)除以 2 在实际的分析场 ...

  4. 【转】用Python的Pandas和Matplotlib绘制股票唐奇安通道,布林带通道和鳄鱼组线

    我最近出了一本书,<基于股票大数据分析的Python入门实战 视频教学版>,京东链接:https://item.jd.com/69241653952.html,在其中给出了MACD,KDJ ...

  5. python:海龟交易法则 画唐奇安通道

    回忆一下海龟交易法则的策略: 入场条件:当收盘价突破20日价格高点时,买入一单元股票: 加仓条件:当价格大于上一次买入价格的0.5个ATR(平均波幅),买入一单元股票,加仓次数不超过3次: 止损条件: ...

  6. python量化交易策略——唐奇安通道和海龟策略(1)

    本文采用唐奇安通道和海龟策略相结合的方式 # coding=utf-8 from __future__ import print_function, absolute_import, unicode_ ...

  7. 【金融量化】通道突破策略之布林带策略(Bollinger Band )、肯特纳通道策略(Keltner Channel)、唐奇安通道策略(Donchian)原理简介

    通道突破策略 1 布林带策略(Bollinger Band ) 布林带是一种多功能工具,结合移动平均线和标准差来检测市场波动的变化.布林带指标包含三个组成部分: 中轨 = N时间段的简单移动平均线(S ...

  8. Donchian Channel(唐奇安通道)及其发明人Richard Donchian的前世今生

    Richard Donchian是谁 Richard Donchian(1905.9-1993),"趋势交易之父",是职业期货交易员,于20世纪中期开发了Donchian Chan ...

  9. python :pandas 画唐奇安通道

    本篇数据来源:公开的基金净值,累计净值 表头:date,jz,ljjz pd_roll_dc.py # -*- coding: utf-8 -*- import os, sys if len(sys. ...

最新文章

  1. 2017年计算机四级试题,2017年全国计算机四级考试模拟试题与答案
  2. 干货!谷歌推荐的技术能力提升指南
  3. 黑马lavarel教程---8、session
  4. 设计模式--代理(Proxy)模式
  5. 图解10大机器学习算法
  6. 愚弄dnn_不要被泛型和向后兼容性所愚弄。 使用泛型类型
  7. php输入数据提交排序,排序php数据var
  8. spring cloud单点登录
  9. mysql常用命令案例
  10. 思科BFD协议帮助侦测网络失败
  11. Missing iOS Distribution signing identity for …
  12. 用户体验报告(Echo)
  13. 小米盒子刷arm linux,最新小米盒子3s刷原生安卓系统图文教程!值得收藏
  14. 个人php源码,php个人发卡平台源码 v1.4 免费版
  15. 巧用万能驱动包安装驱动
  16. hadoop 8088端口网页无法打开
  17. Authenticator App 两步验证会不会造成亚马逊账号关联?
  18. 虚拟机域渗透环境搭建
  19. eclipse 重命名文件、移动文件、删除等操作时出现.svntmp文件
  20. python代码画樱花主要特色,手机python代码画樱花

热门文章

  1. 黑马程序员_ios基础总结1_IOS概述
  2. 全国黄金价格数据(1978-2020年)
  3. .NET Core 性能监控
  4. 学习python不知不觉一个月了
  5. 初始C语言 C生万物
  6. ppst开发技术视频——ubuntu crontab 的使用方法
  7. USB host关于收到STALL处理
  8. 弄清java中的字节与字符
  9. 交流/备用电池供电切换电路
  10. 微信小程序地图导航源码、地图导航小程序源码