LOADING
996 字
5 分钟
vectorbt学习_60DC之一基础策略

基于vectorbt的基础唐奇安通道

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

01,基础配置信息#

#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,时间交易参数配置#

# 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#

# 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,指标计算和可视化#

# 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,信号计算和可视化#

# 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,基准比对#

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,交易详情和可视化#

# 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

vectorbt学习_60DC之一基础策略
/posts/quant/ad942d90/
作者
思想的巨人
发布于
2024-12-10
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时