0%

vectorbt学习_60DC之一基础策略

基于vectorbt的基础唐奇安通道

09dc_01basic:基础方法
09dc_01basicV2:和基础方法等价,不过是基于vectorbt的指标机制的集成的dch指标。

01,基础配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#conda envs:vectorbt_env
import warnings
import vectorbt as vbt
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
import pytz
from dateutil.parser import parse
import ipywidgets as widgets
from copy import deepcopy
from tqdm import tqdm
import imageio
from IPython import display
import plotly.graph_objects as go
import itertools
import dateparser
import gc
import math
from 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,时间交易参数配置

1
2
3
4
5
6
7
8
9
10
11
12
13
# Enter your parameters here
seed = 42
symbol = '600089.XSHG' #601318
metric = 'total_return'

start_date = datetime(2021, 1, 1, tzinfo=pytz.utc) # time period for analysis, must be timezone-aware
end_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 window
freq = '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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Download data with time buffer
cols = ['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 buffer
wobuf_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 data
ohlcv.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)

svg

03,指标计算和可视化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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 buffer
upper_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 buffer
upper_band = upper_band[wobuf_mask]
lower_band = lower_band[wobuf_mask]

# there should be no nans after removing time buffer
assert(~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,)

svg

04,信号计算和可视化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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))

svg

svg

Start                       2021-01-04 00:00:00+00:00
End                         2022-12-30 00:00:00+00:00
Period                                            485
Total                                              19
Rate [%]                                     3.917526
Total Overlapping                                   0
Overlapping Rate [%]                              0.0
First Index                 2021-01-18 00:00:00+00:00
Last Index                  2022-08-29 00:00:00+00:00
Norm Avg Index [-1, 1]                       -0.19552
Distance -> Other: Min                            3.0
Distance -> Other: Max                           67.0
Distance -> Other: Mean                     25.315789
Distance -> Other: Std                       17.34952
Total Partitions                                   19
Partition Rate [%]                              100.0
Partition Length: Min                             1.0
Partition Length: Max                             1.0
Partition Length: Mean                            1.0
Partition Length: Std                             0.0
Partition Distance: Min                           2.0
Partition Distance: Max                          61.0
Partition Distance: Mean                    21.722222
Partition Distance: Std                     18.549792
dtype: object

05,交易统计

a,基准比对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dmac_pf = vbt.Portfolio.from_signals(ohlcv['Close'], dc_entries, dc_exits)
# Print stats
print(dmac_pf.stats())

# Now build portfolio for a "Hold" strategy
# Here we buy once at the beginning and sell at the end
hold_entries = pd.Series.vbt.signals.empty_like(dc_entries)
hold_entries.iloc[0] = True
hold_exits = pd.Series.vbt.signals.empty_like(hold_entries)
hold_exits.iloc[-1] = True
hold_pf = vbt.Portfolio.from_signals(ohlcv['Close'], hold_entries, hold_exits)

# Equity
fig = 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:00
End                           2022-12-30 00:00:00+00:00
Period                                              485
Start Value                                    100000.0
End Value                                 135478.738311
Total Return [%]                              35.478738
Benchmark Return [%]                         104.325952
Max Gross Exposure [%]                            100.0
Total Fees Paid                             6084.898884
Max Drawdown [%]                               52.33349
Max Drawdown Duration                             318.0
Total Trades                                          9
Total Closed Trades                                   9
Total Open Trades                                     0
Open Trade PnL                                      0.0
Win Rate [%]                                  33.333333
Best Trade [%]                                97.749209
Worst Trade [%]                              -19.171936
Avg Winning Trade [%]                         42.098525
Avg Losing Trade [%]                          -9.811332
Avg Winning Trade Duration                         47.0
Avg Losing Trade Duration                          11.0
Profit Factor                                  1.374907
Expectancy                                  3942.082035
dtype: object

svg

b,交易详情和可视化

1
2
3
# Plot trades
print(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_id
0   0    0  183.350720         10   544.042715  249.376559        38   550.239953  252.217228    634.674170  0.006363          0       1          0
1   1    0  175.831773         73   570.907710  250.959287        91   565.963545  248.785934  -1369.086519 -0.013639          0       1          1
2   2    0  164.485565        113   601.986212  247.545106       180  1194.915225  491.365766  96789.353009  0.977492          0       1          2
3   3    0  141.336528        197  1383.690600  488.915064       208  1124.681250  397.396358 -37493.793739 -0.191719          0       1          3
4   4    0  129.545854        230  1220.924700  395.414331       235  1108.431975  358.981916 -15327.362345 -0.096907          0       1          4

svg