996 字
5 分钟
vectorbt学习_60DC之一基础策略
基于vectorbt的基础唐奇安通道
09dc_01basic:基础方法
09dc_01basicV2:和基础方法等价,不过是基于vectorbt的指标机制的集成的dch指标。
01,基础配置信息
#conda envs:vectorbt_envimport warningsimport vectorbt as vbtimport numpy as npimport pandas as pdfrom datetime import datetime, timedeltaimport pytzfrom dateutil.parser import parseimport ipywidgets as widgetsfrom copy import deepcopyfrom tqdm import tqdmimport imageiofrom IPython import displayimport plotly.graph_objects as goimport itertoolsimport dateparserimport gcimport mathfrom tools import dbtools
warnings.filterwarnings("ignore")
pd.set_option('display.max_rows',500)pd.set_option('display.max_columns',500)pd.set_option('display.width',1000)02,行情获取和可视化
a,时间交易参数配置
# Enter your parameters hereseed = 42symbol = '600089.XSHG' #601318metric = 'total_return'
start_date = datetime(2021, 1, 1, tzinfo=pytz.utc) # time period for analysis, must be timezone-awareend_date = datetime(2023,1,1, tzinfo=pytz.utc)time_buffer = timedelta(days=100) # buffer before to pre-calculate SMA/EMA, best to set to max windowfreq = '1D'
vbt.settings.portfolio['init_cash'] = 100000. # 100$vbt.settings.portfolio['fees'] = 0.0025 # 0.25%vbt.settings.portfolio['slippage'] = 0.0025 # 0.25%b,获取行情和行情mask
# Download data with time buffercols = ['Open', 'High', 'Low', 'Close', 'Volume']# ohlcv_wbuf = vbt.YFData.download(symbol, start=start_date-time_buffer, end=end_date).get(cols)
ohlcv_wbuf=dbtools.MySQLData.download(symbol).get() # 自带工具类查询assert(~ohlcv_wbuf.empty)ohlcv_wbuf = ohlcv_wbuf.astype(np.float64)
print("origin ohlcv_wbuf size:",ohlcv_wbuf.shape)print(ohlcv_wbuf.columns)
# Create a copy of data without time bufferwobuf_mask = (ohlcv_wbuf.index >= start_date) & (ohlcv_wbuf.index <= end_date) # mask without buffer
ohlcv = ohlcv_wbuf.loc[wobuf_mask, :]
print("wobuf_mask ohlcv size:",ohlcv.shape)
# Plot the OHLC dataohlcv.vbt.ohlcv.plot().show_svg() # 绘制蜡烛图# remove show_svg() to display interactive chart!origin ohlcv_wbuf size: (1409, 5)Index(['Open', 'High', 'Low', 'Close', 'Volume'], dtype='object')wobuf_mask ohlcv size: (485, 5)
03,指标计算和可视化
# fig.show_svg()upper_window = 20 # 上边界滚动计算周期lower_window = 10 # 下边界滚动计算周期upper_window_comp_skip = 5 # 突破比较时需要和前n日的比较lower_window_comp_skip = 3 # 突破比较时需要和前n日的比较# Pre-calculate running windows on data with time bufferupper_band = vbt.talib('MAX').run(ohlcv_wbuf['High'], timeperiod=upper_window)# print(upper_band.real.head(30))lower_band = vbt.talib('MIN').run(ohlcv_wbuf['Low'], timeperiod=lower_window)
print(upper_band.real.shape)print(lower_band.real.shape)
# Remove time bufferupper_band = upper_band[wobuf_mask]lower_band = lower_band[wobuf_mask]
# there should be no nans after removing time bufferassert(~upper_band.real.isnull().any())assert(~lower_band.real.isnull().any())
print(upper_band.real.shape)print(lower_band.real.shape)
fig = ohlcv['Close'].vbt.plot(trace_kwargs=dict(name='Price'))fig = upper_band.real.vbt.plot(trace_kwargs=dict(name='Upper Band'), fig=fig)fig = lower_band.real.vbt.plot(trace_kwargs=dict(name='Lower Band'), fig=fig)fig.show_svg()(1409,)(1409,)(485,)(485,)
04,信号计算和可视化
# def crossed_above(series1, series2):# """Returns a boolean Series indicating where series1 crosses above series2."""# return (series1 > series2) & (series1.shift(1) <= series2.shift(1))
# def crossed_below(series1, series2):# """Returns a boolean Series indicating where series1 crosses below series2."""# return (series1 < series2) & (series1.shift(1) >= series2.shift(1))
# dc_entries = crossed_above(ohlcv['Close'],upper_band.real.shift(5).fillna(method='ffill'))# 后移5/3天,当天视角看就是close比对3天前的upper/lower# dc_exits = crossed_below(ohlcv['Close'],lower_band.real.shift(3).fillna(method='ffill'))
# 信号计算upper_band_nd_ago = upper_band.real.shift(upper_window_comp_skip) #n日前max价格lower_band_nd_ago = lower_band.real.shift(lower_window_comp_skip) ## Long when MACD is above zero AND signal# 优化:ohlcv_wbuf["Close"]->ohlcv_wbuf["High"]# 原理:最高价不断走高的是好行情,最高价包含情绪因素,比收盘价更具代表性dc_entries = ohlcv["Close"][upper_band_nd_ago.index].vbt.crossed_above(upper_band_nd_ago)dc_exits= ohlcv["Close"][lower_band_nd_ago.index].vbt.crossed_below(lower_band_nd_ago)
# 行情-指标-信号可视化fig = ohlcv['Close'].vbt.plot(trace_kwargs=dict(name='Price'))fig = upper_band.real.vbt.plot(trace_kwargs=dict(name='Fast MA'), fig=fig)fig = lower_band.real.vbt.plot(trace_kwargs=dict(name='Slow MA'), fig=fig)fig = dc_entries.vbt.signals.plot_as_entry_markers(ohlcv['Close'], fig=fig)fig = dc_exits.vbt.signals.plot_as_exit_markers(ohlcv['Close'], fig=fig)fig.show_svg()
# (单独)信号可视化fig = dc_entries.vbt.signals.plot(trace_kwargs=dict(name='Entries'))dc_exits.vbt.signals.plot(trace_kwargs=dict(name='Exits'), fig=fig).show_svg()
# 信号的统计信息dc_entries.vbt.signals.stats(settings=dict(other=dc_exits))

Start 2021-01-04 00:00:00+00:00End 2022-12-30 00:00:00+00:00Period 485Total 19Rate [%] 3.917526Total Overlapping 0Overlapping Rate [%] 0.0First Index 2021-01-18 00:00:00+00:00Last Index 2022-08-29 00:00:00+00:00Norm Avg Index [-1, 1] -0.19552Distance -> Other: Min 3.0Distance -> Other: Max 67.0Distance -> Other: Mean 25.315789Distance -> Other: Std 17.34952Total Partitions 19Partition Rate [%] 100.0Partition Length: Min 1.0Partition Length: Max 1.0Partition Length: Mean 1.0Partition Length: Std 0.0Partition Distance: Min 2.0Partition Distance: Max 61.0Partition Distance: Mean 21.722222Partition Distance: Std 18.549792dtype: object05,交易统计
a,基准比对
dmac_pf = vbt.Portfolio.from_signals(ohlcv['Close'], dc_entries, dc_exits)# Print statsprint(dmac_pf.stats())
# Now build portfolio for a "Hold" strategy# Here we buy once at the beginning and sell at the endhold_entries = pd.Series.vbt.signals.empty_like(dc_entries)hold_entries.iloc[0] = Truehold_exits = pd.Series.vbt.signals.empty_like(hold_entries)hold_exits.iloc[-1] = Truehold_pf = vbt.Portfolio.from_signals(ohlcv['Close'], hold_entries, hold_exits)
# Equityfig = dmac_pf.value().vbt.plot(trace_kwargs=dict(name='Value (DMAC)'))hold_pf.value().vbt.plot(trace_kwargs=dict(name='Value (Hold)'), fig=fig).show_svg()Start 2021-01-04 00:00:00+00:00End 2022-12-30 00:00:00+00:00Period 485Start Value 100000.0End Value 135478.738311Total Return [%] 35.478738Benchmark Return [%] 104.325952Max Gross Exposure [%] 100.0Total Fees Paid 6084.898884Max Drawdown [%] 52.33349Max Drawdown Duration 318.0Total Trades 9Total Closed Trades 9Total Open Trades 0Open Trade PnL 0.0Win Rate [%] 33.333333Best Trade [%] 97.749209Worst Trade [%] -19.171936Avg Winning Trade [%] 42.098525Avg Losing Trade [%] -9.811332Avg Winning Trade Duration 47.0Avg Losing Trade Duration 11.0Profit Factor 1.374907Expectancy 3942.082035dtype: object
b,交易详情和可视化
# Plot tradesprint(dmac_pf.trades.records.head(5))dmac_pf.trades.plot().show_svg() id col size entry_idx entry_price entry_fees exit_idx exit_price exit_fees pnl return direction status parent_id0 0 0 183.350720 10 544.042715 249.376559 38 550.239953 252.217228 634.674170 0.006363 0 1 01 1 0 175.831773 73 570.907710 250.959287 91 565.963545 248.785934 -1369.086519 -0.013639 0 1 12 2 0 164.485565 113 601.986212 247.545106 180 1194.915225 491.365766 96789.353009 0.977492 0 1 23 3 0 141.336528 197 1383.690600 488.915064 208 1124.681250 397.396358 -37493.793739 -0.191719 0 1 34 4 0 129.545854 230 1220.924700 395.414331 235 1108.431975 358.981916 -15327.362345 -0.096907 0 1 4
部分信息可能已经过时