Untitled

unknown
plain_text
a month ago
4.9 kB
4
Indexable
Never
```import os
import vectorbtpro as vbt
from numba import njit
import numpy as np

import talib

# Define the symbols and date range
symbols = {'BTC-USD': 'Bitcoin', 'TSLA': 'Tesla'}
start_date = '2024-08-01'
end_date = '2024-08-20'

# Define the range of parameters for Supertrend
periods = list(range(5, 51))  # Periods from 5 to 50 with an increment of 1
multipliers = [round(x * 0.01, 2) for x in range(50, 301, 1)]  # Multiplier from 0.5 to 3.0 with an increment of 0.01

# Define the Supertrend logic using Numba and VectorBT's IndicatorFactory
@njit
def get_final_bands_nb(close, upper, lower):
trend = np.full(close.shape, np.nan)
dir_ = np.full(close.shape, 1)
long = np.full(close.shape, np.nan)
short = np.full(close.shape, np.nan)

for i in range(1, close.shape[0]):
if close[i] > upper[i - 1]:
dir_[i] = 1
elif close[i] < lower[i - 1]:
dir_[i] = -1
else:
dir_[i] = dir_[i - 1]
if dir_[i] > 0 and lower[i] < lower[i - 1]:
lower[i] = lower[i - 1]
if dir_[i] < 0 and upper[i] > upper[i - 1]:
upper[i] = upper[i - 1]

if dir_[i] > 0:
trend[i] = long[i] = lower[i]
else:
trend[i] = short[i] = upper[i]

return trend, dir_, long, short

def get_basic_bands(med_price, atr, multiplier):
matr = multiplier * atr
upper = med_price + matr
lower = med_price - matr
return upper, lower

def faster_supertrend_talib(high, low, close, period=7, multiplier=3):
avg_price = talib.MEDPRICE(high, low)
atr = talib.ATR(high, low, close, period)
upper, lower = get_basic_bands(avg_price, atr, multiplier)
return get_final_bands_nb(close, upper, lower)

# Create the SuperTrend indicator using IndicatorFactory
SuperTrend = vbt.IF(
class_name='SuperTrend',
short_name='st',
input_names=['high', 'low', 'close'],
param_names=['period', 'multiplier'],
output_names=['supert', 'superd', 'superl', 'supers']
).with_apply_func(
faster_supertrend_talib,
takes_1d=True,
period=7,
multiplier=3
)

# Loop through each symbol
for symbol, name in symbols.items():
# Format the filename with start and end month/year
filename = f'{name}_{start_date}_to_{end_date}_daily.csv'

# Check if the file already exists
# if os.path.exists(filename):
# else:
#     yahoo_data = vbt.YFData.pull(symbol, tz="EDT", start=start_date, end=end_date)
#     # Save the data to a CSV file
#     yahoo_data.to_csv(filename)

# Load the data from the CSV file using vectorbtpro
data = vbt.Data.from_csv(filename)

# Run the SuperTrend indicator with all combinations of periods and multipliers
supertrend = SuperTrend.run(
data['High'], data['Low'], data['Close'],
period=periods, multiplier=multipliers,
param_product=True
)

# Generate signals based on Supertrend crossover
entries = supertrend.superd == 1
exits = supertrend.superd == -1

# Run backtests with advanced portfolio management features
portfolio = vbt.Portfolio.from_signals(
data['Close'],
entries,
exits,
init_cash=100_000,
slippage=0.001,  # Example slippage
freq='1D',
parallel=True  # Enable parallel processing for faster backtesting
)

# Retrieve and display comprehensive performance metrics
metrics = {
'Total Return (%)': portfolio.total_return() * 100,
'Win Rate (%)': portfolio.win_rate() * 100,
'Sharpe Ratio': portfolio.sharpe_ratio(),
'Max Drawdown (%)': portfolio.max_drawdown() * 100,
'Net Profit (\$)': portfolio.net_profit(),
'Net Profit (%)': portfolio.net_profit(return_pct=True) * 100,
}

metrics_df = vbt.DataFrame(metrics, index=[symbol])
print(f"\nMetrics for {name}:")
print(metrics_df)

# Save the results to a CSV file
metrics_df.to_csv(f'{name}_supertrend_backtest_results_pro.csv')

# Plot the results
portfolio.plot().show()

# Compare against Buy and Hold strategy