0%

vectorbt学习_48DMA之八滑窗网格参数优选

本文在上一篇文章(DMA之六滑窗网格参数优选)基础上。
增加退出模块,虽然双均线本身可以生成退出信号,但是其信号大多滞后的,无法实现止损,跟踪止损,止盈等功能。
本文增加止损,跟踪止损,止盈等的回测。
本篇文章部分图示有误,以下一篇为准:31DMA之九滑窗网格参数优选

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 = '002594.XSHE'
metric = 'total_return'

start_date = datetime(2020, 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'] = 10000. # 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("ohlcv_wbuf.shape:",ohlcv_wbuf.shape)
print("ohlcv_wbuf.columns:",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("ohlcv.shape:",ohlcv.shape)

# Plot the OHLC data
ohlcv.vbt.ohlcv.plot().show_svg() # 绘制蜡烛图
# remove show_svg() to display interactive chart!
ohlcv_wbuf.shape: (978, 5)
ohlcv_wbuf.columns: Index(['Open', 'High', 'Low', 'Close', 'Volume'], dtype='object')
ohlcv.shape: (728, 5)

svg

20,网格参数-指标计算和可视化

仅可视化第一列

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
fast_windows = np.arange(10, 50,5)
slow_multis = np.arange(1.5, 5.5, 0.5)
print("fast_windows:",fast_windows)
print("slow_multis:",slow_multis)

price=ohlcv_wbuf['Close']
dualma = vbt.DualMA.run(price, fast_window=fast_windows,slow_multi=slow_multis,param_product=True)
dualma = dualma[wobuf_mask]
# there should be no nans after removing time buffer
assert(~dualma.fast_ma.isnull().any().any())
assert(~dualma.slow_ma.isnull().any().any())


print()
print('dualma.fast_ma.head(3)')
print(dualma.fast_ma.head(3))
print('dualma.slow_ma.head(3)')
print(dualma.slow_ma.head(3))

print()
fig = ohlcv['Close'].vbt.plot(trace_kwargs=dict(name='Price'))
fig = dualma.fast_ma.iloc[:,0].vbt.plot(trace_kwargs=dict(name="Fast MA col %s"%str(dualma.fast_ma.iloc[:,0].name)), fig=fig)
fig = dualma.slow_ma.iloc[:,0].vbt.plot(trace_kwargs=dict(name="Slow MA col %s"%str(dualma.slow_ma.iloc[:,0].name)), fig=fig)
fig.show_svg()

fast_windows: [10 15 20 25 30 35 40 45]
slow_multis: [1.5 2.  2.5 3.  3.5 4.  4.5 5. ]

dualma.fast_ma.head(3)
dualma_fast_window             10                                                                 15                                                                                    20                                                                      25                                                                        30                                                                                      35                                                                                    40                                                                        45                                                                             
dualma_slow_multi             1.5     2.0     2.5     3.0     3.5     4.0     4.5     5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0      1.5      2.0      2.5      3.0      3.5      4.0      4.5      5.0      1.5      2.0      2.5      3.0      3.5      4.0      4.5      5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0      1.5      2.0      2.5      3.0      3.5      4.0      4.5      5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0
date                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
2020-01-02 00:00:00+00:00  46.665  46.665  46.665  46.665  46.665  46.665  46.665  46.665  45.824667  45.824667  45.824667  45.824667  45.824667  45.824667  45.824667  45.824667  45.3025  45.3025  45.3025  45.3025  45.3025  45.3025  45.3025  45.3025  44.9476  44.9476  44.9476  44.9476  44.9476  44.9476  44.9476  44.9476  44.816667  44.816667  44.816667  44.816667  44.816667  44.816667  44.816667  44.816667  44.594571  44.594571  44.594571  44.594571  44.594571  44.594571  44.594571  44.594571  44.5425  44.5425  44.5425  44.5425  44.5425  44.5425  44.5425  44.5425  44.440222  44.440222  44.440222  44.440222  44.440222  44.440222  44.440222  44.440222
2020-01-03 00:00:00+00:00  46.972  46.972  46.972  46.972  46.972  46.972  46.972  46.972  46.128667  46.128667  46.128667  46.128667  46.128667  46.128667  46.128667  46.128667  45.5025  45.5025  45.5025  45.5025  45.5025  45.5025  45.5025  45.5025  45.1420  45.1420  45.1420  45.1420  45.1420  45.1420  45.1420  45.1420  44.964000  44.964000  44.964000  44.964000  44.964000  44.964000  44.964000  44.964000  44.723714  44.723714  44.723714  44.723714  44.723714  44.723714  44.723714  44.723714  44.6265  44.6265  44.6265  44.6265  44.6265  44.6265  44.6265  44.6265  44.555556  44.555556  44.555556  44.555556  44.555556  44.555556  44.555556  44.555556
2020-01-06 00:00:00+00:00  47.138  47.138  47.138  47.138  47.138  47.138  47.138  47.138  46.456000  46.456000  46.456000  46.456000  46.456000  46.456000  46.456000  46.456000  45.7310  45.7310  45.7310  45.7310  45.7310  45.7310  45.7310  45.7310  45.3376  45.3376  45.3376  45.3376  45.3376  45.3376  45.3376  45.3376  45.112667  45.112667  45.112667  45.112667  45.112667  45.112667  45.112667  45.112667  44.871143  44.871143  44.871143  44.871143  44.871143  44.871143  44.871143  44.871143  44.7115  44.7115  44.7115  44.7115  44.7115  44.7115  44.7115  44.7115  44.660222  44.660222  44.660222  44.660222  44.660222  44.660222  44.660222  44.660222
dualma.slow_ma.head(3)
dualma_fast_window                10                                                                              15                                                                                      20                                                                                25                                                                                 30                                                                                    35                                                                                      40                                                                                   45                                                                             
dualma_slow_multi                1.5      2.0      2.5        3.0        3.5      4.0        4.5      5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0        1.5      2.0      2.5        3.0        3.5        4.0        4.5      5.0        1.5      2.0        2.5        3.0        3.5      4.0        4.5       5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5      5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0        1.5        2.0      2.5        3.0        3.5        4.0        4.5       5.0        1.5        2.0        2.5        3.0        3.5        4.0        4.5        5.0
date                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
2020-01-02 00:00:00+00:00  45.824667  45.3025  44.9476  44.816667  44.594571  44.5425  44.440222  44.6384  45.180455  44.816667  44.545676  44.440222  44.717692  45.135167  45.513134  46.025200  44.816667  44.5425  44.6384  45.135167  45.697429  46.307750  46.683111  47.0983  44.545676  44.6384  45.235806  46.025200  46.560460  47.0983  47.997679  48.61136  44.440222  45.135167  46.025200  46.683111  47.425238  48.410917  48.769630  48.8484  44.717692  45.697429  46.560460  47.425238  48.496066  48.803714  48.852357  49.430914  45.135167  46.307750  47.0983  48.410917  48.803714  48.892313  49.622778  50.14240  45.513134  46.683111  47.997679  48.769630  48.852357  49.622778  50.162574  50.375822
2020-01-03 00:00:00+00:00  46.128667  45.5025  45.1420  44.964000  44.723714  44.6265  44.555556  44.6660  45.373636  44.964000  44.652162  44.555556  44.741538  45.119167  45.485821  45.984267  44.964000  44.6265  44.6660  45.119167  45.666714  46.291125  46.643333  47.0707  44.652162  44.6660  45.229677  45.984267  46.549080  47.0707  47.936429  48.56848  44.555556  45.119167  45.984267  46.643333  47.349905  48.362083  48.758074  48.8320  44.741538  45.666714  46.549080  47.349905  48.460984  48.784357  48.838471  49.366457  45.119167  46.291125  47.0707  48.362083  48.784357  48.878875  49.584500  50.12260  45.485821  46.643333  47.936429  48.758074  48.838471  49.584500  50.141139  50.379778
2020-01-06 00:00:00+00:00  46.456000  45.7310  45.3376  45.112667  44.871143  44.7115  44.660222  44.6908  45.562273  45.112667  44.787297  44.660222  44.773846  45.116667  45.474478  45.950800  45.112667  44.7115  44.6908  45.116667  45.641143  46.267875  46.621889  47.0449  44.787297  44.6908  45.232742  45.950800  46.534598  47.0449  47.864554  48.52880  44.660222  45.116667  45.950800  46.621889  47.278952  48.320667  48.743185  48.8232  44.773846  45.641143  46.534598  47.278952  48.406803  48.770500  48.833885  49.298743  45.116667  46.267875  47.0449  48.320667  48.770500  48.860063  49.552222  50.09115  45.474478  46.621889  47.864554  48.743185  48.833885  49.552222  50.122772  50.388044

svg

21,网格参数-信号计算和可视化

仅可视化第一列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 信号计算
dmac_size=dualma.fast_ma_above(dualma.slow_ma)
print('dmac_size.shape:',dmac_size.shape)
print()
print('dmac_size.iloc[:3,:3]:')
print(dmac_size.iloc[:3,:3])


# 行情-指标-信号可视化
fig = ohlcv['Close'].vbt.plot(trace_kwargs=dict(name='Price'))
fig = dualma.fast_ma.iloc[:,0].vbt.plot(trace_kwargs=dict(name='Fast MA'), fig=fig)
fig = dualma.slow_ma.iloc[:,0].vbt.plot(trace_kwargs=dict(name='Slow MA'), fig=fig)
fig = dmac_size.iloc[:,0].vbt.signals.plot_as_markers(ohlcv['Close'], fig=fig)
fig.show_svg()

# (单独)信号可视化
fig = dmac_size.iloc[:,0].vbt.signals.plot(trace_kwargs=dict(name='Entries'))
fig.show_svg()

# 信号的统计信息
dmac_size.vbt.signals.stats()
dmac_size.shape: (728, 64)

dmac_size.iloc[:3,:3]:
dualma_fast_window           10            
dualma_slow_multi           1.5   2.0   2.5
date                                       
2020-01-02 00:00:00+00:00  True  True  True
2020-01-03 00:00:00+00:00  True  True  True
2020-01-06 00:00:00+00:00  True  True  True

svg

svg

Start                       2020-01-02 00:00:00+00:00
End                         2022-12-30 00:00:00+00:00
Period                                            728
Total                                       474.03125
Rate [%]                                    65.114183
First Index                 2020-01-15 16:52:30+00:00
Last Index                  2022-11-07 20:15:00+00:00
Norm Avg Index [-1, 1]                      -0.159967
Distance: Min                                     1.0
Distance: Max                               82.734375
Distance: Mean                               1.464916
Distance: Std                                5.175417
Total Partitions                             6.671875
Partition Rate [%]                           1.510978
Partition Length: Min                       41.671875
Partition Length: Max                      211.171875
Partition Length: Mean                     110.468174
Partition Length: Std                       78.523847
Partition Distance: Min                      26.78125
Partition Distance: Max                     82.734375
Partition Distance: Mean                    51.365493
Partition Distance: Std                     28.015768
Name: agg_func_mean, dtype: object

22,行情,信号的滑窗处理

注意点:
01,训练集和验证集比例3:1,或者2:1,对应:window_len和set_lens为4:1(或3:1),过大了历史包袱沉重,无法及时响应最新行情,过小了则容易参数跳变,形成类似过拟合效果

a,参数设置和效果预览

代码中

1
2
3
4
5
6
7
8
9
10
11
#todo 这里是自然日计算的,但后面训练,验证集个数计算都完全正确,哪里应该和预想的不一致
合理的。实测bar_days= 60时

print(in_indexes[0][0])
print(in_indexes[1][0])
print(in_indexes[0][53:55])

2019-01-02 00:00:00+00:00
2019-03-25 00:00:00+00:00
DatetimeIndex(['2019-03-25 00:00:00+00:00', '2019-03-26 00:00:00+00:00'], dtype='datetime64[ns, UTC]', name='split_0', freq=None)
可见第二行第一个位于第一行第53个,不足设置的60,就是由于切分优先保证了数据的足量,但是数据间隔方面则可能有所重叠。
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
# 滚动周期参数设置和大致效果可视化
start_end_days=int((end_date-start_date).days) #todo 这里是自然日计算的,但后面训练,验证集个数计算都完全正确,哪里应该和预想的不一致
bar_days= 80 # 训练,验证集时间长度,以此为单位
test_bar_num=2 # 训练集时间长度
verify_bar_num=1 # 验证集时间长度
verify_overlap=0 # 验证集重叠时间长度
pre_test_days=0 # 由于测试集一部分时间用于计算指标,导致实际训练时间不足,这个是一定程度补充的days周期
# n取值需要满足:确保验证集合收尾相接
# => (n-1)*(verify_bar_num-verify_overlap)+(verify_bar_num+test_bar_num)=start_end_days/bar_days
# => n=(start_end_days/bar_days-test_bar_num-verify_overlap)/(verify_bar_num-verify_overlap)
calc_n=(start_end_days/bar_days-test_bar_num-verify_overlap)/(verify_bar_num-verify_overlap)


split_kwargs = dict(
n=int(calc_n),
window_len=int(bar_days*(test_bar_num+verify_bar_num)+pre_test_days),
set_lens=(int(bar_days*verify_bar_num),),
left_to_right=False
) # 10 windows, each 2 years long, reserve 180 days for test
# 合理设置n,最好确保验证集,连续且无重复
pf_kwargs = dict(
direction='longonly', # long and short
freq='d'
)
print('split_kwargs:',split_kwargs)

def roll_in_and_out_samples(price, **kwargs):
return price.vbt.rolling_split(**kwargs)

# 验证:单列数据验证,橘黄色验证集连续且无重复
roll_in_and_out_samples(price, **split_kwargs, plot=True, trace_names=['in-sample', 'out-sample']).show_svg()
split_kwargs: {'n': 11, 'window_len': 240, 'set_lens': (80,), 'left_to_right': False}

svg

b,根据滑窗参数切分行情数据和信号

in_price.shape: (160, 11)
out_price.shape: (80, 11)

in_price.index: RangeIndex(start=0, stop=160, step=1)
in_price.columns: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype='int64', name='split_idx')

in_price[0:3]:
split_idx     0      1      2      3      4      5       6       7       8       9       10
0          49.17  58.15  51.20  43.39  48.15  97.90  167.98  239.52  202.00  251.77  253.14
1          48.06  56.16  49.50  43.15  49.73  96.55  164.08  225.00  214.11  252.50  266.49
2          50.65  55.36  50.29  43.79  52.25  94.50  168.03  208.99  227.02  246.86  266.08

###############################
in_dmac_size.shape: (160, 704)
out_dmac_size.shape: (80, 704)

in_dmac_size.iloc[:5,:5]:
split_idx              0                        
dualma_fast_window    10                        
dualma_slow_multi    1.5   2.0   2.5   3.0   3.5
0                   True  True  True  True  True
1                   True  True  True  True  True
2                   True  True  True  True  True
3                   True  True  True  True  True
4                   True  True  True  True  True

23,滑窗的收益数据计算

a,持有参数收益

在此区间,基础标的物表现

1
2
3
4
5
6
7
8
9
10
def simulate_holding(price, **kwargs):
pf = vbt.Portfolio.from_holding(price, **kwargs)
return pf.sharpe_ratio()

in_hold_sharpe = simulate_holding(in_price, **pf_kwargs)
print(in_hold_sharpe.head(5))

out_hold_sharpe = simulate_holding(out_price, **pf_kwargs)
print(out_hold_sharpe.head(5))

split_idx
0    0.235446
1   -1.630616
2    0.598889
3    2.647397
4    4.501923
Name: sharpe_ratio, dtype: float64
split_idx
0   -0.929956
1    2.065991
2    4.100300
3    4.801291
4    0.688785
Name: sharpe_ratio, dtype: float64

b,网格参数收益(训练集和验证集)

in_sharpe.shape: (11264,)
split_idx  dualma_fast_window  dualma_slow_multi  sl_stop  sl_trail  tp_stop
0          10                  1.5                0.05     False     0.1       -0.875730
                                                                     0.2       -0.875730
                                                           True      0.1        0.213753
                                                                     0.2        0.213753
                                                  0.10     False     0.1       -0.279062
                                                                                  ...   
10         45                  5.0                0.15     True      0.2       -1.593755
                                                  0.20     False     0.1       -2.154236
                                                                     0.2       -2.154236
                                                           True      0.1       -1.910520
                                                                     0.2       -1.910520
Name: sharpe_ratio, Length: 11264, dtype: float64

split_idx              0                                                                                                                                                                                                                                                                                                                                                                                                                                                               1                                                                                                                                                                                                                                                                                                                                                                                                                                                               2                                                                         \
dualma_fast_window     10                                                      15                                                      20                                                      25                                                      30                                                      35                                                      40                                                      45                                                      10                                                      15                                                      20                                                      25                                                      30                                                      35                                                      40                                                      45                                                      10                                                      15                 
dualma_slow_multi     1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5   
0                    True  False  False  False  False  False  False  False  False  False  False  False   True   True   True   True  False  False   True   True   True   True   True   True  False   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   
1                   False  False  False  False  False  False  False   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   
2                   False   True   True   True   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   

split_idx                                                                                                                                                                                                                                                                                                                                                                                                 3                                                                                                                                                                                                                                                                                                                                                                                                                  ...     7                                                                                                                                                                                                \
dualma_fast_window                                        20                                                      25                                                      30                                                      35                                                      40                                                      45                                                      10                                                      15                                                      20                                                      25                                                      30                                                      35                                                      40                                                      45         ...     10            15                                                      20                                                      25                                                      30          
dualma_slow_multi     3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0  ...    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0   
0                    True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   True  False  False  False  False  False   True   True   True  False  False  False   True   True   True   True   True  False   True  ...  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   
1                   False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  ...  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   
2                   False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  ...  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   

split_idx                                                                                                                                                                                                                                8                                                                                                                                                                                                                                                                                                                                                                                                                                                               9                                                                                                                                                                                                                                                                                                                       \
dualma_fast_window                                               35                                                      40                                                      45                                                      10                                                      15                                                      20                                                      25                                                      30                                                      35                                                      40                                                      45                                                      10                                                      15                                                      20                                                      25                                                      30                                                      35                               
dualma_slow_multi     2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5   
0                   False  False  False  False  False  False  False  False  False  False  False  False  False   True  False  False  False  False  False   True   True   True  False  False  False  False   True   True   True   True  False   True   True   True   True  False  False  False   True   True   True   True   True  False  False  False   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   
1                   False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   True   True   True  False  False  False  False  False  False  False  False  False   True   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   
2                   False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   

split_idx                                                                                                                                                   10                                                                                                                                                                                                                                                                                                                                                                                                                                                           
dualma_fast_window                          40                                                      45                                                      10                                                      15                                                      20                                                      25                                                      30                                                      35                                                      40                                                      45                                                   
dualma_slow_multi     4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0    1.5    2.0    2.5    3.0    3.5    4.0    4.5    5.0  
0                    True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True   True  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False   True   True  False  False  False  False   True   True   True   True  False  False  False   True   True   True   True   True  False  False   True   True   True   True   True   True  False  False   True   True   True   True   True   True  False   True   True   True   True   True   True   True  
1                   False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  
2                   False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  False  

[3 rows x 704 columns]
out_sharpe.shape: (11264,)
split_idx  dualma_fast_window  dualma_slow_multi  sl_stop  sl_trail  tp_stop
0          10                  1.5                0.05     False     0.1       -1.069452
                                                                     0.2       -1.069452
                                                           True      0.1       -0.297334
                                                                     0.2       -0.297334
                                                  0.10     False     0.1       -2.012693
                                                                                  ...   
10         45                  5.0                0.15     True      0.2       -2.766034
                                                  0.20     False     0.1       -0.197531
                                                                     0.2       -0.197531
                                                           True      0.1       -0.197531
                                                                     0.2       -0.197531
Name: sharpe_ratio, Length: 11264, dtype: float64
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
36
37
38
39
40
41
42
43
44
45
46
47
import pandas as pd
import matplotlib.pyplot as plt

# 根据索引层筛选数据
groups = in_return.groupby(level=['sl_trail','sl_stop'])

# 计算每个分组的统计数据
# statistics = groups.agg(['mean', 'var', 'max', 'min', 'median'])
statistics = groups.agg([
('mean', 'mean'),
('var', 'var'),
('max', 'max'),
('min', 'min'),
('median', 'median'),
('25%', lambda x: np.percentile(x, 25)),
('75%', lambda x: np.percentile(x, 75))
])
print(statistics)


def compare_true_false_statistics(statistics):
"""
比较 sl_trail 索引层为 True 和 False 时各统计指标的大小。

:param statistics: 包含 True 和 False 分组的统计数据。
:return: 一个新的 DataFrame,展示 True 是否大于 False。
"""
# 确保索引是多重索引,并且第一个索引是 sl_trail
if not isinstance(statistics.index, pd.MultiIndex) or statistics.index.names[0] != 'sl_trail':
raise ValueError("数据的第一个索引必须是 'sl_trail' 并且为多重索引。")

# 提取 True 和 False 的统计数据
true_stats = statistics.xs(True, level='sl_trail')
false_stats = statistics.xs(False, level='sl_trail')

# 比较 True 和 False 的每个统计指标
comparison = true_stats > false_stats

# 将比较结果转换为整数类型(True为1,False为0)
comparison = comparison.astype(int)

return comparison

# 示例使用
# 假设 statistics 是上述提供的 DataFrame
comparison_results = compare_true_false_statistics(statistics)
print(comparison_results)
                      mean       var       max       min    median       25%       75%
sl_trail sl_stop                                                                      
False    0.05     0.156963  0.158100  2.451051 -0.274652 -0.009410 -0.111586  0.300105
         0.10     0.169930  0.169304  2.451051 -0.370515  0.026649 -0.134527  0.414560
         0.15     0.162313  0.178970  2.451051 -0.355247  0.022469 -0.169337  0.438223
         0.20     0.212244  0.170921  2.451051 -0.370934  0.081500 -0.086851  0.455634
True     0.05     0.024409  0.026795  1.337420 -0.350482 -0.014005 -0.087060  0.130420
         0.10     0.157421  0.081934  1.347645 -0.332450  0.133399 -0.097223  0.351686
         0.15     0.111382  0.084515  1.294188 -0.410083  0.065638 -0.147819  0.338981
         0.20     0.178996  0.128846  2.451051 -0.357140  0.113125 -0.067093  0.316135
         mean  var  max  min  median  25%  75%
sl_stop                                       
0.05        0    0    0    0       0    1    0
0.10        0    0    0    1       1    1    0
0.15        0    0    0    0       1    1    0
0.20        0    0    0    1       1    1    0

c,训练集上的最佳参数用于验证集

大致思路:
01,获取各split_idx的最佳收益(sharp_radio)的参数组合idxmax,也就是fast_window,slow_window,split_idx,三维索引元组
02,按照split_idx进行聚类,取得各split_idx对应的最佳参数。实际含义就是各滑动窗口的最佳参数

v1:简单最大值优选法
选取,测试集合的最优参数作为验证集参数,如果sharp_ratio就最大,回撤就最小类似这样的简单优选策略。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def get_best_index(performance, higher_better=True):
if higher_better:
return performance[performance.groupby('split_idx').idxmax()].index
return performance[performance.groupby('split_idx').idxmin()].index
in_best_index_basic = get_best_index(in_sharpe)

print('in_best_index')
print(in_best_index_basic)

# 绘图:参数走势图
df_plot_tmp = in_best_index_basic.to_frame(index=False)
# 将split_idx设置为行索引,并按照split_idx从小到大排序
df_plot_tmp.set_index('split_idx', inplace=True)
df_plot_tmp.sort_index(inplace=True)
df_plot_tmp['dualma_slow_window'] = df_plot_tmp['dualma_fast_window']*df_plot_tmp['dualma_slow_multi']
df_plot_tmp[['dualma_fast_window','dualma_slow_window']].vbt.plot().show_svg()
in_best_index[:5]
MultiIndex([( 0, 35, 2.0,  0.1,  True, 0.1),
            ( 1, 15, 4.0, 0.05,  True, 0.1),
            ( 2, 10, 3.0, 0.05, False, 0.1),
            ( 3, 25, 3.5, 0.05, False, 0.1),
            ( 4, 40, 5.0, 0.05, False, 0.1),
            ( 5, 35, 5.0,  0.2,  True, 0.1),
            ( 6, 10, 4.0,  0.1,  True, 0.1),
            ( 7, 45, 3.0, 0.15, False, 0.1),
            ( 8, 40, 1.5,  0.1, False, 0.1),
            ( 9, 20, 1.5,  0.1, False, 0.1),
            (10, 30, 1.5, 0.05,  True, 0.1)],
           names=['split_idx', 'dualma_fast_window', 'dualma_slow_multi', 'sl_stop', 'sl_trail', 'tp_stop'])

svg

将滚动获取的最佳参数用于验证集,统计收益信息

24,sharp ratio的汇总可视化

basic为例的基础分析视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cv_results_df = pd.DataFrame({
'in_sample_hold': in_hold_sharpe.values,
'in_sample_median': in_sharpe.groupby('split_idx').median().values,
'in_sample_best': in_test_best_sharpe_basic.values,
'out_sample_hold': out_hold_sharpe.values,
'out_sample_median': out_sharpe.groupby('split_idx').median().values,
'out_sample_test': out_test_sharpe_basic.values
})

color_schema = vbt.settings['plotting']['color_schema']

cv_results_df.vbt.plot(
trace_kwargs=[
dict(line_color=color_schema['blue']),
dict(line_color=color_schema['blue'], line_dash='dash'),
dict(line_color=color_schema['blue'], line_dash='dot'),
dict(line_color=color_schema['orange']),
dict(line_color=color_schema['orange'], line_dash='dash'),
dict(line_color=color_schema['orange'], line_dash='dot')
]
).show_svg()

svg

关注点:

蓝色部分
正常排序是(从上到下):点线,实现,线段,

橘色部分

实线对实线
说明测试集和验证集的周期收益情况,二者同时出现0轴同侧较好(同时上涨,同时下跌,保持行情的稳定性or延续性)

线段对线段
二者一方面随着各自颜色的实线趋势变化(受各自实线影响较大),其他应该无必然联系

点线对点线
蓝色点高于橘色点线,蓝色是训练集内最佳,橘色则是训练集得到最优参数用于验证集结果收益,大概率低于验证集。

测试,验证集时间长度差异,引入偏差
由于测试集一般是验证集的2-3倍(或更多),对于单边行情(假如上涨),则(测试集的)实线收益。蓝色线大概率位于橘色线上方。
如果下跌,则相反。蓝色由于时间长,大概率位于橘色下方。

注意:
01,202406,对于当前case,y周取值为sharp ratio夏普比,而非收益率。所以数据点高低并不反映收益率。
所以,以上结论需要稍斟酌,并不完全准确。

25,滚动回测收益可视化

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 验证集:原始价格变动
in_price_org=in_price.iloc[-1, :]/in_price.iloc[0, :]
print('in_price_org shape:',in_price_org.shape)
print('in_price_org.head(5)')
print(in_price_org.head(5))


cv_results_df = pd.DataFrame({
'out_price_org': in_price_org.cumprod(),
'out_test_return_mean': (in_test_best_return_basic.values+1).cumprod(),
})

color_dmac_pfschema = vbt.settings['plotting']['color_schema']


cv_results_df.vbt.plot(
trace_kwargs=[
dict(line_color=color_schema['blue']),
dict(line_color=color_schema['green'])
]
).show_svg()



# 验证集:原始价格变动
out_price_org=out_price.iloc[-1, :]/out_price.iloc[0, :]
print('out_price_org shape:',out_price_org.shape)
print('out_price_org.head(5)')
print(out_price_org.head(5))

print()
print('out_test_return_basic shape:',out_test_return_basic.shape)
print('out_test_return_basic.head(5) + 1')
print(out_test_return_basic.head(5)+1)

cv_results_df = pd.DataFrame({
'out_price_org': out_price_org.cumprod(),
'out_test_return_mean': (out_test_return_basic.values+1).cumprod(),
})

color_dmac_pfschema = vbt.settings['plotting']['color_schema']


cv_results_df.vbt.plot(
trace_kwargs=[
dict(line_color=color_schema['blue']),
dict(line_color=color_schema['green'])
]
).show_svg()
in_price_org shape: (11,)
in_price_org.head(5)
split_idx
0    1.007525
1    0.774549
2    1.086914
3    1.933856
4    3.468328
dtype: float64

svg

out_price_org shape: (11,)
out_price_org.head(5)
split_idx
0    0.940574
1    1.315436
2    1.625985
3    2.111239
4    1.059162
dtype: float64

out_test_return_basic shape: (11,)
out_test_return_basic.head(5) + 1
split_idx  dualma_fast_window  dualma_slow_multi  sl_stop  sl_trail  tp_stop
0          35                  2.0                0.10     True      0.1        0.875962
1          15                  4.0                0.05     True      0.1        1.195700
2          10                  3.0                0.05     False     0.1        1.064199
3          25                  3.5                0.05     False     0.1        1.571024
4          40                  5.0                0.05     False     0.1        1.053886
Name: total_return, dtype: float64

svg

上图可见,以上参数优选方法表现基本接近(也符合之前的sharp ratio接近的特征),不论何种参数优选策略,均优于单纯的持有(不过,结论未必通用)。

26,计算正确性验证(略)

a,准备校验数据,数据展示
b,行情->指标 计算正确
c,指标->信号 计算正确
entry record: 48.9220 price: 51.5800

27,回测结果汇总

原始双均线

参数

1
2
fast_windows = np.arange(10, 50,5)
slow_multis = np.arange(1.5, 5.5, 0.5)

最佳参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
in_best_index[:5]
MultiIndex([( 0, 35, 2.0),
( 1, 10, 4.5),
( 2, 10, 2.0),
( 3, 25, 3.5),
( 4, 40, 5.0),
( 5, 35, 5.0),
( 6, 10, 1.5),
( 7, 45, 3.0),
( 8, 40, 1.5),
( 9, 20, 1.5),
(10, 25, 1.5)],
names=['split_idx', 'dualma_fast_window', 'dualma_slow_multi'])

最佳参数样本内网sharp

最佳参数测试集回测表现

最佳参数验证集回测表现

简单说明:对于训练集合,其整体时间为2T,2倍于预测时间。 所以
01,训练集和验证集数据图上,即使同一种颜色也无太大比较意义
02,训练集绿色线高于蓝色线,说明参数优选效果(拟合效果,训练效果)较好。这也是合理,毕竟用训练的最优最结果又用来回测自身,效果当然也应当好嘛。
03,验证集绿色高于蓝色越多越好,说明相对简单持有具有超额收益。当然实际上有难度,尤其是行情好时。由于策略需要控制风险(追求高sharpe),所以时间维度难以持续满仓,所以牛市可能不如稳定持有,但是遇到大跌时,规避风险的优势就很明显了。

跟踪止损

参数

1
2
sl_stops = [0.05,0.1,0.15,0.20]
sl_trail=True

最佳参数

1
2
3
4
5
6
7
8
9
10
11
12
MultiIndex([( 0, 35, 2.0,  0.1),
( 1, 15, 4.0, 0.05),
( 2, 10, 2.0, 0.05),
( 3, 10, 1.5, 0.1),
( 4, 40, 5.0, 0.2),
( 5, 35, 5.0, 0.2),
( 6, 10, 4.0, 0.1),
( 7, 45, 2.5, 0.2),
( 8, 40, 1.5, 0.2),
( 9, 20, 1.5, 0.1),
(10, 30, 1.5, 0.05)],
names=['split_idx', 'dualma_fast_window', 'dualma_slow_multi', 'sl_stop'])

最佳参数样本内网sharp

最佳参数测试集回测表现

最佳参数验证集回测表现

跟踪止损+np.inf

参数

1
2
sl_stops = [np.inf,0.05,0.1,0.15,0.20]
sl_trail=True

最佳参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
merged_df[in_test_best_index_basic]
in_sharpe in_return out_sharpe out_return
split_idx dualma_fast_window dualma_slow_multi sl_stop
0 35 2.0 0.10 1.979770 0.319978 -2.876613 -0.124038
1 15 4.0 0.05 0.324361 0.016997 2.231171 0.195700
2 10 2.0 0.05 1.844657 0.303627 2.693463 0.161817
3 25 3.5 inf 3.374967 1.233830 3.996941 0.571024
4 40 5.0 inf 4.501923 2.451051 0.688785 0.053886
5 35 5.0 0.20 2.959891 1.144421 -2.467499 -0.193663
6 10 4.0 0.10 3.029320 0.727907 -1.060044 -0.073690
7 45 3.0 inf 2.296182 0.749108 inf 0.000000
8 40 1.5 inf 2.489317 0.692895 3.678357 0.449287
9 20 1.5 inf 2.926436 0.575073 2.364898 0.128734
10 30 1.5 0.05 2.402594 0.302466 -4.323912 -0.074724

最佳参数样本内网sharp

最佳参数测试集回测表现

最佳参数验证集回测表现

止损止盈

1
2
3
sl_stops = [0.05,0.1,0.15,0.20]
sl_trails = [False, True]
tp_stops = [0.1, 0.2]

最佳参数

1
2
3
4
5
6
7
8
9
10
11
12
13
MultiIndex([( 0, 45, 2.0, 0.05, False, 0.1),
( 1, 15, 4.0, 0.05, False, 0.1),
( 2, 10, 2.0, 0.05, True, 0.2),
( 3, 10, 2.0, 0.05, True, 0.2),
( 4, 15, 1.5, 0.05, False, 0.2),
( 5, 40, 3.5, 0.2, False, 0.2),
( 6, 20, 4.0, 0.05, False, 0.2),
( 7, 25, 2.0, 0.05, False, 0.2),
( 8, 40, 1.5, 0.1, False, 0.2),
( 9, 30, 5.0, 0.1, False, 0.2),
(10, 30, 3.0, 0.05, False, 0.2)],
names=['split_idx', 'dualma_fast_window', 'dualma_slow_multi', 'sl_stop', 'sl_trail', 'tp_stop'])

最佳参数样本内网sharp

最佳参数训练集回测表现

最佳参数验证集回测表现

止损止盈+np.inf

参数

1
2
3
sl_stops = [np.inf,0.05,0.1,0.15,0.20]
sl_trails = [False, True]
tp_stops = [np.inf,0.1, 0.2]

最佳参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
merged_df[in_test_best_index_basic]
in_sharpe in_return out_sharpe out_return
split_idx dualma_fast_window dualma_slow_multi sl_stop sl_trail tp_stop
0 45 2.0 inf False 0.1 3.158667 0.237753 -0.929956 -0.064111
1 15 4.0 inf False 0.1 0.664945 0.034948 2.563318 0.145963
2 10 3.0 0.05 False inf 1.978273 0.408342 1.451395 0.064199
3 25 3.5 inf False inf 3.374967 1.233830 3.996941 0.571024
4 15 1.5 inf False 0.2 5.245280 1.127771 2.858175 0.239233
5 35 5.0 0.20 True inf 2.959891 1.144421 -2.467499 -0.193663
6 20 4.0 inf False 0.2 4.039079 0.462475 1.890751 0.207220
7 45 3.0 inf False inf 2.296182 0.749108 inf 0.000000
8 40 1.5 inf False 0.2 2.665200 0.492175 2.449875 0.239941
9 30 5.0 inf False 0.2 3.738112 0.507262 -0.434888 -0.063484
10 30 3.0 inf False 0.2 2.943695 0.258812 -3.877240 -0.075374

最佳参数样本内网sharp

最佳参数测试集回测表现

最佳参数验证集回测表现

小汇总

策略 参数 训练区标的 训练区最优 验证区标的 验证区表现
原始双均线 fast_windows = np.arange(10, 50,5)
slow_multis = np.arange(1.5, 5.5, 0.5)
25, 220 8 5.5
跟踪止损 sl_stops = [0.05,0.1,0.15,0.20]
sl_trail=True
25 220 8 3.5
跟踪止损+inf sl_stops = [np.inf,0.05,0.1,0.15,0.20]
sl_trail=True
25 300 8 2
止损止盈 sl_stops = [0.05,0.1,0.15,0.20]
sl_trails = [False, True]
tp_stops = [0.1, 0.2]
25 40 8 1
止损止盈+inf sl_stops = [np.inf,0.05,0.1,0.15,0.20]
sl_trails = [False, True]
tp_stops = [np.inf,0.1, 0.2]
25 140 8 2

结论:
01,可见策略越复杂,则训练集上的最优效果也越好(拟合效果更佳)
比如:跟踪止损+inf 优于 跟踪止损,止损止盈+inf 优于 止损止盈
反例:止损止盈 小于 跟踪止损,这个主要是止盈的限制,盈利达到xx后卖出限制了受益最大值,所以可解释。
02,止盈可以考虑不加,效果整体不如不止盈的。
03,跟踪止损表现一般
以上结果仅对此案例有效,无法通用泛化。还需更多数据支持。
比较反常的:”止损止盈+inf”的140小于“跟踪止损+inf”的220,原因是我们参数选择时并非基于最高收益,而是基于最高sharpe,所以“止损止盈+inf”选中标的和“跟踪止损+inf”肯定存在差异。