Premio Nobel William Sharp
Introducción
La evaluación del desempeño de la estrategia es una parte muy importante del comercio cuantitativo. La inversión requiere no sólo comprender la tasa de rendimiento de la estrategia, sino también el riesgo de la estrategia. Backtrader proporciona una variedad de analizadores que pueden generar una variedad de indicadores de desempeño para analizar el efecto del backtesting de la estrategia.
Instrucciones
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='AnnualReturn')
cerebro.addanalyzer(bt.analyzers.SharpeRatio, riskfreerate=0.003, annualize=True, _name='SharpeRatio')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='DrawDown')
strats = cerebro.run()
# 第一个策略
strat = strats[0]
print("--------------- AnnualReturn -----------------")
print(strat.analyzers.AnnualReturn.get_analysis())
print("--------------- SharpeRatio -----------------")
print(strat.analyzers.SharpeRatio.get_analysis())
print("--------------- DrawDown -----------------")
print(strat.analyzers.DrawDown.get_analysis())
AnnualReturn representa el analizador de rendimiento anualizado , SharpeRatio representa el analizador de índice de Sharpe y DrawDown representa el analizador de backtest. Los resultados de cada analizador generalmente se devuelven en forma de un diccionario OrderedDict, como se muestra a continuación. Puede obtener los valores requeridos a través de claves, como strat.analyzers.SharpeRatio.get_analysis()['sharperatio'].
--------------- AnnualReturn -----------------
OrderedDict([(2010, 0.0055023006637382466), (2011, 0.0015355496623354892), (2012, 0.004218277850025043), (2013, 0.09220659214070048), (2014, 0.05213380413050861), (2015, 0.012115724348371826), (2016, -0.017901621371985033), (2017, 0.06763449420829182), (2018, 0.01391412496311406), (2019, 0.05472002239157425), (2020, 1.8864865026259587), (2021, 0.36892175167157526), (2022, -0.2711252801992251)])
--------------- SharpeRatio -----------------
OrderedDict([('sharperatio', 0.3360518820606975)])
--------------- DrawDown -----------------
AutoOrderedDict([('len', 145), ('drawdown', 35.66222565509548), ('moneydown', 21054.40185546875), ('max', AutoOrderedDict([('len', 648), ('drawdown', 40.770090001923634), ('moneydown', 24070.00244140625)]))])
Se puede ver que los resultados generados por el analizador son solo valores numéricos y no hay ningún dibujo. Por SharpeRatio
ejemplo, la relación de Sharpe se calcula con un valor de 0,3360518820606975. De hecho, Analyzers
el objeto de líneas no está incluido, lo que también significa que el objeto analizador es muy amigable con la memoria y no ocupa mucha memoria.
-
Explicación adicional: un analizador analiza el desempeño de una estrategia en lugar del desempeño de todo el sistema. Para la clase de analizador agregada a través de la función addanalyzer, en
cerebro.run
tiempo de ejecución, cada instancia del analizador se vinculará a cada estrategia. Si el backtest contiene 3 estrategias, se crearán 3 instancias del mismo analizador y cada instancia se vinculará a diferentes estrategias. -
Algunos
Analyzer
objetos analizadores utilizan otros analizadores para completar tareas, comoSharpeRatio
utilizarTimeReturn
la salida del analizador para cálculos adicionales, pero estas dependencias no son visibles para el usuario.
Analizadores que vienen con backtrader
-
AnnualReturn: tasa de rendimiento anualizada
-
Calmar: Relación Calmar
-
DrawDown: retroceso
-
TimeDrawDown: inconveniente en la granularidad de tiempo especificada
-
Apalancamiento bruto: apalancamiento total
-
PositionsValue: valor de posición
-
PyFolio: Genera datos compatibles con pyfolio
-
LogReturnsRolling: retornos continuos de registros
-
PeriodStats: Información estadística básica para un período determinado
-
Rentabilidad: calcule la rentabilidad total, media, compuesta y anualizada utilizando el método logarítmico
-
SharpeRatio: relación de nitidez
-
SharpeRatio_A: ratio de Sharpe anualizado
-
SQN: Número de calidad del sistema
-
TimeReturn: tasa de rendimiento en diferentes periodos
-
TradeAnalyzer: estadísticas comerciales como ganancias, pérdidas, etc.
-
Transacciones: el tema, el precio, la cantidad y otra información de cada transacción.
-
VWR: rentabilidad ponderada por variabilidad, rentabilidad ponderada por volatilidad
Los analizadores Analyzer más utilizados incluyen: AnnualReturn, DrawDown, PyFolio, SharpeRatio, TimeReturn.
Crear un nuevo analizador Analizador
Si el analizador que viene con backtrader no puede satisfacer sus necesidades, puede crear su propio analizador. Tomemos SharpeRatio
como ejemplo, el código de referencia es el siguiente. El índice de Sharpe es uno de los indicadores de evaluación del desempeño más utilizados y refleja el exceso de tasa de retorno aportado por la fluctuación de las unidades. Cuanto mayor, mejor. El índice de Sharpe es el exceso de rendimiento de la estrategia en relación con el rendimiento libre de riesgo dividido por la desviación estándar del rendimiento.
import backtrader as bt
from backtrader.utils.py3 import map
from backtrader.mathsupport import average, standarddev
class SharpeRatio(bt.Analyzer):
params = (
('timeframe', bt.TimeFrame.Years),
('riskfreerate', 0.01),
)
def __init__(self):
super(SharpeRatio, self).__init__()
self.anret = bt.analyzers.AnnualReturn()
# analyzer与策略一样,都是从第0根bar开始运行
def start(self):
pass
def prenext(self):
pass
def nextstart(self):
pass
def next(self):
pass
# 一般对策略整体的评价指标是在策略结束后开始计算的
def stop(self):
retfree = [self.p.riskfreerate] * len(self.anret.rets)
retavg = average(list(map(operator.sub, self.anret.rets, retfree)))
retdev = standarddev(self.anret.rets)
self.ratio = retavg / retdev
# Analyzer类特有方法,返回包含分析结果的类dict对象
def get_analysis(self):
return dict(sharperatio=self.ratio)
# 支持与策略一样的信息打印函数
def notify_order(self, order):
pass
def notify_trade(self, trade):
pass
def notify_cashvalue(self, cash, value):
pass
def notify_fund(self, cash, value, fundvalue, shares):
pass
Como se puede ver en el código anterior, aunque Analyzer
el objeto no tiene un objeto Líneas y no necesita iterar en líneas, siguen el mismo modo de operación que la estrategia. Por supuesto, también existe este método get_analysis
único para devolver resultados de análisis. .
Usando PyFolio en backtrader
cerebro.addanalyzer(bt.analyzers.PyFolio)
strats = cerebro.run()
# retrieve the 1st strategy
strat0 = strats[0]
pyfolio = strats.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
import pyfolio as pf
pf.create_full_tear_sheet(returns)
pyfolio
También se puede ejecutar fuera de Jupyter Notebook, pero se admite mejor cuando se ejecuta dentro de Jupyter.
Comparar con el punto de referencia de referencia
import backtrader as bt
cerebro = bt.Cerebro()
spypd = bt.feeds.PandasData(dataname=spydata, name="spy")
cerebro.adddata(spypd)
cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years, _name='TimeReturn')
cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years, data=spypd, _name='BenchTimeReturn')
strats = cerebro.run()
time_return = strat.analyzers.getbyname('TimeReturn').get_analysis()
bench_time_return = strat.analyzers.getbyname('BenchTimeReturn').get_analysis()
print("--------------- TimeReturn -----------------")
print(time_return)
print("--------------- BenchTimeReturn -----------------")
print(bench_time_return)
Registro de salida:
--------------- TimeReturn -----------------
OrderedDict([(datetime.date(2009, 12, 31), 0.0), (datetime.date(2010, 12, 31), 0.0055023006637382466), (datetime.date(2011, 12, 31), 0.0015355496623354892), (datetime.date(2012, 12, 31), 0.004218277850025043), (datetime.date(2013, 12, 31), 0.09220659214070048), (datetime.date(2014, 12, 31), 0.05213380413050861), (datetime.date(2015, 12, 31), 0.012115724348371826), (datetime.date(2016, 12, 31), -0.017901621371985033), (datetime.date(2017, 12, 31), 0.06763449420829182), (datetime.date(2018, 12, 31), 0.01391412496311406), (datetime.date(2019, 12, 31), 0.05472002239157425), (datetime.date(2020, 12, 31), 1.8864865026259587), (datetime.date(2021, 12, 31), 0.36892175167157526), (datetime.date(2022, 12, 31), -0.2711252801992251)])
--------------- SpyTimeReturn -----------------
OrderedDict([(datetime.date(2009, 12, 31), -0.011793865755532318), (datetime.date(2010, 12, 31), 0.12840988195524994), (datetime.date(2011, 12, 31), -0.001988071570576566), (datetime.date(2012, 12, 31), 0.134741065036728), (datetime.date(2013, 12, 31), 0.2968892471880906), (datetime.date(2014, 12, 31), 0.11289182180470925), (datetime.date(2015, 12, 31), -0.008124930541476227), (datetime.date(2016, 12, 31), 0.09643402233275422), (datetime.date(2017, 12, 31), 0.19384416771302204), (datetime.date(2018, 12, 31), -0.06347893319524989), (datetime.date(2019, 12, 31), 0.28785206349908), (datetime.date(2020, 12, 31), 0.16162313396749006), (datetime.date(2021, 12, 31), 0.2703540848726258), (datetime.date(2022, 12, 31), -0.13563244077211734)])
Tenga en cuenta que no todos los analizadores admiten la comparación de puntos de referencia.
Conclusión y comunicación
Siga la cuenta pública de WeChat: Zhuge Shuo Talk para obtener más contenido. Al mismo tiempo, también puede recibir invitaciones para unirse a grupos de intercambio de inversiones y grupos de seminarios de inversión cuantitativa, donde podrá comunicarse y discutir con muchos entusiastas de las inversiones, profesionales cuantitativos y expertos en tecnología, y mejorar rápidamente su nivel de inversión.
Escribir artículos no es fácil, si crees que este artículo te resulta útil, dale me gusta.