教程

止损止盈信号

测试止损、移动止损和止盈配置

会员内容预览(英文)

Our goal is to use large-scale backtesting to compare the performance of trading with and without stop loss (SL), trailing stop (TS), and take profit (TP) signals. To ensure this analysis is comprehensive, we will conduct a large number of experiments across three dimensions: instruments, time, and parameters.

First, we will select 10 cryptocurrencies by market capitalization (excluding stablecoins such as USDT) and gather 3 years of their daily pricing data. Specifically, we will backtest the period from 2018 to 2021, as this range includes periods of sharp price declines (such as corrections after the all-time high in December 2017 and during the coronavirus crisis in March 2020) as well as surges (the all-time high in December 2020). This provides a balanced perspective. For each instrument, we will split this period into 400 smaller, overlapping time windows, each lasting 6 months. We will run our tests on each of these windows to account for different market conditions. For each instrument and time window, we will generate an entry signal at the very first bar and determine an exit signal according to the stop configuration. We will test 100 stop values, increasing by 1% increments, and compare the performance of each one to trading randomly and holding during that specific time window. In total, we will conduct 2,000,000 tests.

Make sure you have at least 16 GB of free RAM available, or memory swapping enabled.

Parameters

The first step is to define the parameters of the analysis pipeline. As discussed above, we will backtest 3 years of pricing data, use 400 time windows, 10 cryptocurrencies, and 100 stop values. We will also set fees and slippage to 0.25% each, and the initial capital to $100. The absolute amount does not matter, but it must be consistent across all assets to allow for direct comparison. Feel free to change any parameter of interest.

from vectorbtpro import *
import ipywidgets

seed = 42
symbols = [
    "BTC-USD", "ETH-USD", "XRP-USD", "BCH-USD", "LTC-USD",
    "BNB-USD", "EOS-USD", "XLM-USD", "XMR-USD", "ADA-USD"
]
start_date = vbt.utc_timestamp("2018-01-01")
end_date = vbt.utc_timestamp("2021-01-01")
time_delta = end_date - start_date
window_len = vbt.timedelta("180d")
window_cnt = 400
exit_types = ["SL", "TS", "TP", "Random", "Holding"]
step = 0.01  
stops = np.arange(step, 1 + step, step)

vbt.settings.wrapping["freq"] = "d"
vbt.settings.plotting["layout"]["template"] = "vbt_dark"
vbt.settings.portfolio["init_cash"] = 100.  
vbt.settings.portfolio["fees"] = 0.0025  
vbt.settings.portfolio["slippage"] = 0.0025  

pd.Series({
    "Start date": start_date,
    "End date": end_date,
    "Time period (days)": time_delta.days,
    "Assets": len(symbols),
    "Window length": window_len,
    "Windows": window_cnt,
    "Exit types": len(exit_types),
    "Stop values": len(stops),
    "Tests per asset": window_cnt * len(stops) * len(exit_types),
    "Tests per window": len(symbols) * len(stops) * len(exit_types),
    "Tests per exit type": len(symbols) * window_cnt * len(stops),
    "Tests per stop type and value": len(symbols) * window_cnt,
    "Tests total": len(symbols) * window_cnt * len(stops) * len(exit_types)
})
Start date                       2018-01-01 00:00:00+00:00
End date                         2021-01-01 00:00:00+00:00
Time period (days)                                    1096
Assets                                                  10
Window length                            180 days 00:00:00
Windows                                                400
Exit types                                               5
Stop values                                            100
Tests per asset                                     200000
Tests per window                                      5000
Tests per exit type                                 400000
Tests per stop type and value                         4000
Tests total                                        2000000
dtype: object

Our configuration produces sample sizes with enough statistical power to analyze four variables: assets (200k tests per asset), time (5k tests per time window), exit types (400k tests per exit type), and stop values (4k tests per stop type and value). Similar to Tableau's approach to dimensions and measures, we can group our performance metrics by each of these variables. However, we will mainly focus on 5 exit types: SL exits, TS exits, TP exits, random exits, and holding exits (executed at the last bar).

cols = ["Open", "Low", "High", "Close", "Volume"]
yfdata = vbt.YFData.pull(symbols, start=start_date, end=end_date)
Symbol 10/10
yfdata.data.keys()
dict_keys(['BTC-USD', 'ETH-USD', 'XRP-USD', 'BCH-USD', 'LTC-USD',
           'BNB-USD', 'EOS-USD', 'XLM-USD', 'XMR-USD', 'ADA-USD'])
yfdata.data["BTC-USD"].shape
(1096, 7)

The data instance yfdata contains a dictionary of OHLCV data, keyed by cryptocurrency name. Each DataFrame contains 1096 rows (days) and 5 columns (O, H, L, C, and V). You can plot each DataFrame as follows:

yfdata.plot(symbol="BTC-USD").show()  

Since assets are one of the dimensions we want to analyze, VBT expects us to combine them as columns into a single DataFrame and label them clearly. To do this, we swap assets and features to create a dictionary of DataFrames, now with assets as columns and keyed by feature name, such as "Open".

ohlcv = yfdata.concat()

ohlcv.keys()
dict_keys(['Open', 'High', 'Low', 'Close',
           'Volume', 'Dividends', 'Stock Splits'])
ohlcv['Open'].shape
(1096, 10)

Time windows

止损止盈类订单是投资者工具箱中的重要组成部分,有助于限制持仓亏损并锁定利润。但在特定市场状态下,订单类型和参数值怎样组合才是最优的?

✅ 学习如何在短短几分钟内运行 200 万次测试,为主流加密货币市场回答这个问题。与开源文章不同,我们还将把止损止盈的触发价格纳入分析,以提高准确性!

版权所有 © 2021–2026 Oleg Polakow。保留所有权利。

本站内容与文档供使用和评估 VectorBT PRO 以及教育用途。任何其他用途,包括开发或支持竞争产品或服务,均须事先取得书面同意。